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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #include "includes.h" 30 RCSID("$OpenBSD: misc.c,v 1.19 2002/03/04 17:27:39 stevesk Exp $"); 31 32 #pragma ident "%Z%%M% %I% %E% SMI" 33 34 #include "misc.h" 35 #include "log.h" 36 #include "xmalloc.h" 37 38 /* remove newline at end of string */ 39 char * 40 chop(char *s) 41 { 42 char *t = s; 43 while (*t) { 44 if (*t == '\n' || *t == '\r') { 45 *t = '\0'; 46 return s; 47 } 48 t++; 49 } 50 return s; 51 52 } 53 54 /* set/unset filedescriptor to non-blocking */ 55 void 56 set_nonblock(int fd) 57 { 58 int val; 59 60 val = fcntl(fd, F_GETFL, 0); 61 if (val < 0) { 62 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 63 return; 64 } 65 if (val & O_NONBLOCK) { 66 debug2("fd %d is O_NONBLOCK", fd); 67 return; 68 } 69 debug("fd %d setting O_NONBLOCK", fd); 70 val |= O_NONBLOCK; 71 if (fcntl(fd, F_SETFL, val) == -1) 72 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", 73 fd, strerror(errno)); 74 } 75 76 void 77 unset_nonblock(int fd) 78 { 79 int val; 80 81 val = fcntl(fd, F_GETFL, 0); 82 if (val < 0) { 83 error("fcntl(%d, F_GETFL, 0): %s", fd, strerror(errno)); 84 return; 85 } 86 if (!(val & O_NONBLOCK)) { 87 debug2("fd %d is not O_NONBLOCK", fd); 88 return; 89 } 90 debug("fd %d clearing O_NONBLOCK", fd); 91 val &= ~O_NONBLOCK; 92 if (fcntl(fd, F_SETFL, val) == -1) 93 debug("fcntl(%d, F_SETFL, O_NONBLOCK): %s", 94 fd, strerror(errno)); 95 } 96 97 /* disable nagle on socket */ 98 void 99 set_nodelay(int fd) 100 { 101 int opt; 102 socklen_t optlen; 103 104 optlen = sizeof opt; 105 if (getsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, &optlen) == -1) { 106 error("getsockopt TCP_NODELAY: %.100s", strerror(errno)); 107 return; 108 } 109 if (opt == 1) { 110 debug2("fd %d is TCP_NODELAY", fd); 111 return; 112 } 113 opt = 1; 114 debug("fd %d setting TCP_NODELAY", fd); 115 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &opt, sizeof opt) == -1) 116 error("setsockopt TCP_NODELAY: %.100s", strerror(errno)); 117 } 118 119 /* Characters considered whitespace in strsep calls. */ 120 #define WHITESPACE " \t\r\n" 121 122 /* return next token in configuration line */ 123 char * 124 strdelim(char **s) 125 { 126 char *old; 127 int wspace = 0; 128 129 if (*s == NULL) 130 return NULL; 131 132 old = *s; 133 134 *s = strpbrk(*s, WHITESPACE "="); 135 if (*s == NULL) 136 return (old); 137 138 /* Allow only one '=' to be skipped */ 139 if (*s[0] == '=') 140 wspace = 1; 141 *s[0] = '\0'; 142 143 *s += strspn(*s + 1, WHITESPACE) + 1; 144 if (*s[0] == '=' && !wspace) 145 *s += strspn(*s + 1, WHITESPACE) + 1; 146 147 return (old); 148 } 149 150 struct passwd * 151 pwcopy(struct passwd *pw) 152 { 153 struct passwd *copy = xmalloc(sizeof(*copy)); 154 155 memset(copy, 0, sizeof(*copy)); 156 copy->pw_name = xstrdup(pw->pw_name); 157 copy->pw_passwd = xstrdup(pw->pw_passwd); 158 copy->pw_gecos = xstrdup(pw->pw_gecos); 159 copy->pw_uid = pw->pw_uid; 160 copy->pw_gid = pw->pw_gid; 161 #ifdef HAVE_PW_EXPIRE_IN_PASSWD 162 copy->pw_expire = pw->pw_expire; 163 #endif 164 #ifdef HAVE_PW_CHANGE_IN_PASSWD 165 copy->pw_change = pw->pw_change; 166 #endif 167 #ifdef HAVE_PW_CLASS_IN_PASSWD 168 copy->pw_class = xstrdup(pw->pw_class); 169 #endif 170 copy->pw_dir = xstrdup(pw->pw_dir); 171 copy->pw_shell = xstrdup(pw->pw_shell); 172 return copy; 173 } 174 175 void 176 pwfree(struct passwd **pw) 177 { 178 struct passwd *p; 179 180 if (pw == NULL || *pw == NULL) 181 return; 182 183 p = *pw; 184 *pw = NULL; 185 186 xfree(p->pw_name); 187 xfree(p->pw_passwd); 188 xfree(p->pw_gecos); 189 #ifdef HAVE_PW_CLASS_IN_PASSWD 190 xfree(p->pw_class); 191 #endif 192 xfree(p->pw_dir); 193 xfree(p->pw_shell); 194 xfree(p); 195 } 196 197 /* 198 * Convert ASCII string to TCP/IP port number. 199 * Port must be >0 and <=65535. 200 * Return 0 if invalid. 201 */ 202 int 203 a2port(const char *s) 204 { 205 long port; 206 char *endp; 207 208 errno = 0; 209 port = strtol(s, &endp, 0); 210 if (s == endp || *endp != '\0' || 211 (errno == ERANGE && (port == LONG_MIN || port == LONG_MAX)) || 212 port <= 0 || port > 65535) 213 return 0; 214 215 return port; 216 } 217 218 #define SECONDS 1 219 #define MINUTES (SECONDS * 60) 220 #define HOURS (MINUTES * 60) 221 #define DAYS (HOURS * 24) 222 #define WEEKS (DAYS * 7) 223 224 /* 225 * Convert a time string into seconds; format is 226 * a sequence of: 227 * time[qualifier] 228 * 229 * Valid time qualifiers are: 230 * <none> seconds 231 * s|S seconds 232 * m|M minutes 233 * h|H hours 234 * d|D days 235 * w|W weeks 236 * 237 * Examples: 238 * 90m 90 minutes 239 * 1h30m 90 minutes 240 * 2d 2 days 241 * 1w 1 week 242 * 243 * Return -1 if time string is invalid. 244 */ 245 long 246 convtime(const char *s) 247 { 248 long total, secs; 249 const char *p; 250 char *endp; 251 252 errno = 0; 253 total = 0; 254 p = s; 255 256 if (p == NULL || *p == '\0') 257 return -1; 258 259 while (*p) { 260 secs = strtol(p, &endp, 10); 261 if (p == endp || 262 (errno == ERANGE && (secs == LONG_MIN || secs == LONG_MAX)) || 263 secs < 0) 264 return -1; 265 266 switch (*endp++) { 267 case '\0': 268 endp--; 269 break; 270 case 's': 271 case 'S': 272 break; 273 case 'm': 274 case 'M': 275 secs *= MINUTES; 276 break; 277 case 'h': 278 case 'H': 279 secs *= HOURS; 280 break; 281 case 'd': 282 case 'D': 283 secs *= DAYS; 284 break; 285 case 'w': 286 case 'W': 287 secs *= WEEKS; 288 break; 289 default: 290 return -1; 291 } 292 total += secs; 293 if (total < 0) 294 return -1; 295 p = endp; 296 } 297 298 return total; 299 } 300 301 char * 302 cleanhostname(char *host) 303 { 304 if (*host == '[' && host[strlen(host) - 1] == ']') { 305 host[strlen(host) - 1] = '\0'; 306 return (host + 1); 307 } else 308 return host; 309 } 310 311 char * 312 colon(char *cp) 313 { 314 int flag = 0; 315 316 if (*cp == ':') /* Leading colon is part of file name. */ 317 return (0); 318 if (*cp == '[') 319 flag = 1; 320 321 for (; *cp; ++cp) { 322 if (*cp == '@' && *(cp+1) == '[') 323 flag = 1; 324 if (*cp == ']' && *(cp+1) == ':' && flag) 325 return (cp+1); 326 if (*cp == ':' && !flag) 327 return (cp); 328 if (*cp == '/') 329 return (0); 330 } 331 return (0); 332 } 333 334 /* function to assist building execv() arguments */ 335 /* PRINTFLIKE2 */ 336 void 337 addargs(arglist *args, char *fmt, ...) 338 { 339 va_list ap; 340 char buf[1024]; 341 342 va_start(ap, fmt); 343 vsnprintf(buf, sizeof(buf), fmt, ap); 344 va_end(ap); 345 346 if (args->list == NULL) { 347 args->nalloc = 32; 348 args->num = 0; 349 } else if (args->num+2 >= args->nalloc) 350 args->nalloc *= 2; 351 352 args->list = xrealloc(args->list, args->nalloc * sizeof(char *)); 353 args->list[args->num++] = xstrdup(buf); 354 args->list[args->num] = NULL; 355 } 356 357 void 358 freeargs(arglist *args) 359 { 360 u_int i; 361 362 if (args->list != NULL) { 363 for (i = 0; i < args->num; i++) 364 xfree(args->list[i]); 365 xfree(args->list); 366 args->nalloc = args->num = 0; 367 args->list = NULL; 368 } 369 } 370 371 mysig_t 372 mysignal(int sig, mysig_t act) 373 { 374 #ifdef HAVE_SIGACTION 375 struct sigaction sa, osa; 376 377 if (sigaction(sig, NULL, &osa) == -1) 378 return (mysig_t) -1; 379 if (osa.sa_handler != act) { 380 memset(&sa, 0, sizeof(sa)); 381 sigemptyset(&sa.sa_mask); 382 sa.sa_flags = 0; 383 #if defined(SA_INTERRUPT) 384 if (sig == SIGALRM) 385 sa.sa_flags |= SA_INTERRUPT; 386 #endif 387 sa.sa_handler = act; 388 if (sigaction(sig, &sa, NULL) == -1) 389 return (mysig_t) -1; 390 } 391 return (osa.sa_handler); 392 #else 393 return (signal(sig, act)); 394 #endif 395 } 396