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