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