1 /* $OpenBSD: util.c,v 1.25 2009/10/27 23:59:57 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 5 * The Regents of the University of California. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that: (1) source code distributions 9 * retain the above copyright notice and this paragraph in its entirety, (2) 10 * distributions including binary code include the above copyright notice and 11 * this paragraph in its entirety in the documentation or other materials 12 * provided with the distribution, and (3) all advertising materials mentioning 13 * features or use of this software display the following acknowledgement: 14 * ``This product includes software developed by the University of California, 15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 16 * the University nor the names of its contributors may be used to endorse 17 * or promote products derived from this software without specific prior 18 * written permission. 19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 22 */ 23 24 #include <sys/types.h> 25 #include <sys/time.h> 26 #include <sys/file.h> 27 #include <sys/limits.h> 28 #include <sys/stat.h> 29 30 #include <ctype.h> 31 #include <err.h> 32 #include <errno.h> 33 #ifdef HAVE_FCNTL_H 34 #include <fcntl.h> 35 #endif 36 #include <pcap.h> 37 #include <stdio.h> 38 #include <stdarg.h> 39 #include <stdlib.h> 40 #include <string.h> 41 #ifdef TIME_WITH_SYS_TIME 42 #include <time.h> 43 #endif 44 #include <unistd.h> 45 46 #include "interface.h" 47 #include "privsep.h" 48 /* 49 * Print out a filename (or other ascii string). 50 * If ep is NULL, assume no truncation check is needed. 51 * Return true if truncated. 52 */ 53 int 54 fn_print(register const u_char *s, register const u_char *ep) 55 { 56 register int ret; 57 register u_char c; 58 59 ret = 1; /* assume truncated */ 60 while (ep == NULL || s < ep) { 61 c = *s++; 62 if (c == '\0') { 63 ret = 0; 64 break; 65 } 66 if (!isascii(c)) { 67 c = toascii(c); 68 putchar('M'); 69 putchar('-'); 70 } 71 if (!isprint(c)) { 72 c ^= 0x40; /* DEL to ?, others to alpha */ 73 putchar('^'); 74 } 75 putchar(c); 76 } 77 return(ret); 78 } 79 80 /* 81 * Print out a counted filename (or other ascii string). 82 * If ep is NULL, assume no truncation check is needed. 83 * Return true if truncated. 84 */ 85 int 86 fn_printn(register const u_char *s, register u_int n, 87 register const u_char *ep) 88 { 89 register int ret; 90 register u_char c; 91 92 ret = 1; /* assume truncated */ 93 while (ep == NULL || s < ep) { 94 if (n-- <= 0) { 95 ret = 0; 96 break; 97 } 98 c = *s++; 99 if (!isascii(c)) { 100 c = toascii(c); 101 putchar('M'); 102 putchar('-'); 103 } 104 if (!isprint(c)) { 105 c ^= 0x40; /* DEL to ?, others to alpha */ 106 putchar('^'); 107 } 108 putchar(c); 109 } 110 return(ret); 111 } 112 113 /* 114 * Print the timestamp 115 */ 116 void 117 ts_print(register const struct bpf_timeval *tvp) 118 { 119 register int s; 120 #define TSBUFLEN 32 121 static char buf[TSBUFLEN]; 122 static struct bpf_timeval last; 123 struct timeval diff; 124 time_t t; 125 126 if (Iflag && device) 127 (void)printf("%s ", device); 128 switch(tflag){ 129 case 0: 130 break; 131 case -1: 132 /* Unix timeval style */ 133 (void)printf("%u.%06u ", 134 (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec); 135 break; 136 case -2: 137 t=tvp->tv_sec; 138 strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t)); 139 printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec); 140 break; 141 case -3: 142 case -4: 143 /* time since first/last frame */ 144 timersub(tvp, &last, &diff); 145 (void)printf("%u.%06u ", 146 (u_int32_t)diff.tv_sec, (u_int32_t)diff.tv_usec); 147 if (tflag == -3 || (last.tv_sec == 0 && last.tv_usec == 0)) 148 last = *tvp; 149 break; 150 default: 151 /* Default */ 152 s = (tvp->tv_sec + thiszone) % 86400; 153 (void)printf("%02d:%02d:%02d.%06u ", 154 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec); 155 break; 156 } 157 } 158 159 /* 160 * Print a relative number of seconds (e.g. hold time, prune timer) 161 * in the form 5m1s. This does no truncation, so 32230861 seconds 162 * is represented as 1y1w1d1h1m1s. 163 */ 164 void 165 relts_print(int secs) 166 { 167 static char *lengths[] = {"y", "w", "d", "h", "m", "s"}; 168 static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; 169 char **l = lengths; 170 int *s = seconds; 171 172 if (secs <= 0) { 173 (void)printf("0s"); 174 return; 175 } 176 while (secs > 0) { 177 if (secs >= *s) { 178 (void)printf("%d%s", secs / *s, *l); 179 secs -= (secs / *s) * *s; 180 } 181 s++; 182 l++; 183 } 184 } 185 186 /* 187 * Convert a token value to a string; use "fmt" if not found. 188 */ 189 const char * 190 tok2str(register const struct tok *lp, register const char *fmt, 191 register int v) 192 { 193 static char buf[128]; 194 195 while (lp->s != NULL) { 196 if (lp->v == v) 197 return (lp->s); 198 ++lp; 199 } 200 if (fmt == NULL) 201 fmt = "#%d"; 202 (void)snprintf(buf, sizeof(buf), fmt, v); 203 return (buf); 204 } 205 206 207 /* VARARGS */ 208 __dead void 209 error(const char *fmt, ...) 210 { 211 va_list ap; 212 213 (void)fprintf(stderr, "%s: ", program_name); 214 va_start(ap, fmt); 215 (void)vfprintf(stderr, fmt, ap); 216 va_end(ap); 217 (void)fputc('\n', stderr); 218 exit(1); 219 /* NOTREACHED */ 220 } 221 222 /* VARARGS */ 223 void 224 warning(const char *fmt, ...) 225 { 226 va_list ap; 227 228 (void)fprintf(stderr, "%s: WARNING: ", program_name); 229 va_start(ap, fmt); 230 (void)vfprintf(stderr, fmt, ap); 231 va_end(ap); 232 (void)fputc('\n', stderr); 233 } 234 235 236 /* 237 * Copy arg vector into a new buffer, concatenating arguments with spaces. 238 */ 239 char * 240 copy_argv(char * const *argv) 241 { 242 size_t len = 0, n; 243 char *buf; 244 245 if (argv == NULL) 246 return (NULL); 247 248 for (n = 0; argv[n]; n++) 249 len += strlen(argv[n])+1; 250 if (len == 0) 251 return (NULL); 252 253 buf = malloc(len); 254 if (buf == NULL) 255 return (NULL); 256 257 strlcpy(buf, argv[0], len); 258 for (n = 1; argv[n]; n++) { 259 strlcat(buf, " ", len); 260 strlcat(buf, argv[n], len); 261 } 262 return (buf); 263 } 264 265 char * 266 read_infile(char *fname) 267 { 268 struct stat buf; 269 int fd; 270 ssize_t cc; 271 size_t bs; 272 char *cp; 273 274 fd = open(fname, O_RDONLY); 275 if (fd < 0) 276 error("can't open %s: %s", fname, pcap_strerror(errno)); 277 278 if (fstat(fd, &buf) < 0) 279 error("can't stat %s: %s", fname, pcap_strerror(errno)); 280 281 if (buf.st_size >= SSIZE_MAX) 282 error("file too long"); 283 284 bs = buf.st_size; 285 cp = malloc(bs + 1); 286 if (cp == NULL) 287 err(1, NULL); 288 cc = read(fd, cp, bs); 289 if (cc == -1) 290 error("read %s: %s", fname, pcap_strerror(errno)); 291 if (cc != bs) 292 error("short read %s (%ld != %lu)", fname, (long)cc, 293 (unsigned long)bs); 294 cp[bs] = '\0'; 295 close(fd); 296 297 return (cp); 298 } 299 300 void 301 safeputs(const char *s) 302 { 303 while (*s) { 304 safeputchar(*s); 305 s++; 306 } 307 } 308 309 void 310 safeputchar(int c) 311 { 312 unsigned char ch; 313 314 ch = (unsigned char)(c & 0xff); 315 if (c < 0x80 && isprint(c)) 316 printf("%c", c & 0xff); 317 else 318 printf("\\%03o", c & 0xff); 319 } 320 321 /* 322 * Print a value a la the %b format of the kernel's printf 323 * (from sbin/ifconfig/ifconfig.c) 324 */ 325 void 326 printb(char *s, unsigned short v, char *bits) 327 { 328 int i, any = 0; 329 char c; 330 331 if (bits && *bits == 8) 332 printf("%s=%o", s, v); 333 else 334 printf("%s=%x", s, v); 335 336 if (bits) { 337 bits++; 338 putchar('<'); 339 while ((i = *bits++)) { 340 if (v & (1 << (i-1))) { 341 if (any) 342 putchar(','); 343 any = 1; 344 for (; (c = *bits) > 32; bits++) 345 putchar(c); 346 } else 347 for (; *bits > 32; bits++) 348 ; 349 } 350 putchar('>'); 351 } 352 } 353