1 /* $OpenBSD: util.c,v 1.18 2004/07/28 09:37:26 markus 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.18 2004/07/28 09:37:26 markus 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 if (*fmt) { 221 fmt += strlen(fmt); 222 if (fmt[-1] != '\n') 223 (void)fputc('\n', stderr); 224 } 225 exit(1); 226 /* NOTREACHED */ 227 } 228 229 /* VARARGS */ 230 void 231 warning(const char *fmt, ...) 232 { 233 va_list ap; 234 235 (void)fprintf(stderr, "%s: WARNING: ", program_name); 236 va_start(ap, fmt); 237 (void)vfprintf(stderr, fmt, ap); 238 va_end(ap); 239 if (*fmt) { 240 fmt += strlen(fmt); 241 if (fmt[-1] != '\n') 242 (void)fputc('\n', stderr); 243 } 244 } 245 246 247 /* 248 * Copy arg vector into a new buffer, concatenating arguments with spaces. 249 */ 250 char * 251 copy_argv(char * const *argv) 252 { 253 size_t len = 0, n; 254 char *buf; 255 256 if (argv == NULL) 257 return (NULL); 258 259 for (n = 0; argv[n]; n++) 260 len += strlen(argv[n])+1; 261 if (len == 0) 262 return (NULL); 263 264 buf = malloc(len); 265 if (buf == NULL) 266 return (NULL); 267 268 strlcpy(buf, argv[0], len); 269 for (n = 1; argv[n]; n++) { 270 strlcat(buf, " ", len); 271 strlcat(buf, argv[n], len); 272 } 273 return (buf); 274 } 275 276 char * 277 read_infile(char *fname) 278 { 279 struct stat buf; 280 int fd; 281 ssize_t cc; 282 size_t bs; 283 char *cp; 284 285 fd = open(fname, O_RDONLY); 286 if (fd < 0) 287 error("can't open %s: %s", fname, pcap_strerror(errno)); 288 289 if (fstat(fd, &buf) < 0) 290 error("can't stat %s: %s", fname, pcap_strerror(errno)); 291 292 if (buf.st_size >= SSIZE_MAX) 293 error("file too long"); 294 295 bs = buf.st_size; 296 cp = malloc(bs + 1); 297 if (cp == NULL) 298 err(1, NULL); 299 cc = read(fd, cp, bs); 300 if (cc == -1) 301 error("read %s: %s", fname, pcap_strerror(errno)); 302 if (cc != bs) 303 error("short read %s (%ld != %lu)", fname, (long)cc, 304 (unsigned long)bs); 305 cp[bs] = '\0'; 306 307 return (cp); 308 } 309 310 void 311 safeputs(const char *s) 312 { 313 while (*s) { 314 safeputchar(*s); 315 s++; 316 } 317 } 318 319 void 320 safeputchar(int c) 321 { 322 unsigned char ch; 323 324 ch = (unsigned char)(c & 0xff); 325 if (c < 0x80 && isprint(c)) 326 printf("%c", c & 0xff); 327 else 328 printf("\\%03o", c & 0xff); 329 } 330