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