1/* 2 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25/*RCSID("OpenBSD: misc.c,v 1.22 2003/09/18 08:49:45 markus Exp ");*/ 26 27/* For xmalloc, xfree etc: 28 * Author: Tatu Ylonen <ylo@cs.hut.fi> 29 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 30 * All rights reserved 31 * Versions of malloc and friends that check their results, and never return 32 * failure (they call fatal if they encounter an error). 33 * 34 * As far as I am concerned, the code I have written for this software 35 * can be used freely for any purpose. Any derived versions of this 36 * software must be clearly marked as such, and if the derived work is 37 * incompatible with the protocol description in the RFC file, it must be 38 * called by a name other than "ssh" or "Secure Shell". 39 */ 40 41/*RCSID("OpenBSD: xmalloc.c,v 1.16 2001/07/23 18:21:46 stevesk Exp ");*/ 42 43#include "includes.h" 44#include "scpmisc.h" 45 46void * 47xmalloc(size_t size) 48{ 49 void *ptr; 50 51 if (size == 0) { 52 fprintf(stderr, "xmalloc: zero size\n"); 53 exit(EXIT_FAILURE); 54 } 55 ptr = malloc(size); 56 if (ptr == NULL) { 57 fprintf(stderr, "xmalloc: out of memory (allocating %lu bytes)\n", (u_long) size); 58 exit(EXIT_FAILURE); 59 } 60 return ptr; 61} 62 63void * 64xrealloc(void *ptr, size_t new_size) 65{ 66 void *new_ptr; 67 68 if (new_size == 0) { 69 fprintf(stderr, "xrealloc: zero size\n"); 70 exit(EXIT_FAILURE); 71 } 72 if (ptr == NULL) 73 new_ptr = malloc(new_size); 74 else 75 new_ptr = realloc(ptr, new_size); 76 if (new_ptr == NULL) { 77 fprintf(stderr, "xrealloc: out of memory (new_size %lu bytes)\n", (u_long) new_size); 78 exit(EXIT_FAILURE); 79 } 80 return new_ptr; 81} 82 83void 84xfree(void *ptr) 85{ 86 if (ptr == NULL) { 87 fprintf(stderr, "xfree: NULL pointer given as argument\n"); 88 exit(EXIT_FAILURE); 89 } 90 free(ptr); 91} 92 93char * 94xstrdup(const char *str) 95{ 96 size_t len; 97 char *cp; 98 99 len = strlen(str) + 1; 100 cp = xmalloc(len); 101 strncpy(cp, str, len); 102 return cp; 103} 104 105char * 106cleanhostname(char *host) 107{ 108 if (*host == '[' && host[strlen(host) - 1] == ']') { 109 host[strlen(host) - 1] = '\0'; 110 return (host + 1); 111 } else 112 return host; 113} 114 115char * 116colon(char *cp) 117{ 118 int flag = 0; 119 120 if (*cp == ':') /* Leading colon is part of file name. */ 121 return (0); 122 if (*cp == '[') 123 flag = 1; 124 125 for (; *cp; ++cp) { 126 if (*cp == '@' && *(cp+1) == '[') 127 flag = 1; 128 if (*cp == ']' && *(cp+1) == ':' && flag) 129 return (cp+1); 130 if (*cp == ':' && !flag) 131 return (cp); 132 if (*cp == '/') 133 return (0); 134 } 135 return (0); 136} 137 138/* function to assist building execv() arguments */ 139void 140addargs(arglist *args, char *fmt, ...) 141{ 142 va_list ap; 143 char *cp; 144 u_int nalloc; 145 int r; 146 147 va_start(ap, fmt); 148 r = vasprintf(&cp, fmt, ap); 149 va_end(ap); 150 if (r == -1) 151 fatal("addargs: argument too long"); 152 153 nalloc = args->nalloc; 154 if (args->list == NULL) { 155 nalloc = 32; 156 args->num = 0; 157 } else if (args->num+2 >= nalloc) 158 nalloc *= 2; 159 160 args->list = xrealloc(args->list, nalloc * sizeof(char *)); 161 args->nalloc = nalloc; 162 args->list[args->num++] = cp; 163 args->list[args->num] = NULL; 164} 165 166void 167replacearg(arglist *args, u_int which, char *fmt, ...) 168{ 169 va_list ap; 170 char *cp; 171 int r; 172 173 va_start(ap, fmt); 174 r = vasprintf(&cp, fmt, ap); 175 va_end(ap); 176 if (r == -1) 177 fatal("replacearg: argument too long"); 178 179 if (which >= args->num) 180 fatal("replacearg: tried to replace invalid arg %d >= %d", 181 which, args->num); 182 xfree(args->list[which]); 183 args->list[which] = cp; 184} 185 186void 187freeargs(arglist *args) 188{ 189 u_int i; 190 191 if (args->list != NULL) { 192 for (i = 0; i < args->num; i++) 193 xfree(args->list[i]); 194 xfree(args->list); 195 args->nalloc = args->num = 0; 196 args->list = NULL; 197 } 198} 199 200/* 201 * NB. duplicate __progname in case it is an alias for argv[0] 202 * Otherwise it may get clobbered by setproctitle() 203 */ 204char *ssh_get_progname(char *argv0) 205{ 206 char *p; 207 208 if (argv0 == NULL) 209 return ("unknown"); /* XXX */ 210 p = strrchr(argv0, '/'); 211 if (p == NULL) 212 p = argv0; 213 else 214 p++; 215 216 return (xstrdup(p)); 217} 218 219void fatal(char* fmt,...) 220{ 221 va_list args; 222 va_start(args, fmt); 223 vfprintf(stderr, fmt, args); 224 va_end(args); 225 exit(255); 226} 227 228void 229sanitise_stdfd(void) 230{ 231 int nullfd, dupfd; 232 233 if ((nullfd = dupfd = open(_PATH_DEVNULL, O_RDWR)) == -1) { 234 fprintf(stderr, "Couldn't open /dev/null: %s", strerror(errno)); 235 exit(1); 236 } 237 while (++dupfd <= 2) { 238 /* Only clobber closed fds */ 239 if (fcntl(dupfd, F_GETFL, 0) >= 0) 240 continue; 241 if (dup2(nullfd, dupfd) == -1) { 242 fprintf(stderr, "dup2: %s", strerror(errno)); 243 exit(1); 244 } 245 } 246 if (nullfd > 2) 247 close(nullfd); 248} 249