1 /* $OpenBSD: util.c,v 1.16 2004/01/28 19:44:55 canacar 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.16 2004/01/28 19:44:55 canacar 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 time_t t; 128 129 switch(tflag){ 130 case 0: 131 break; 132 case -1: 133 /* Unix timeval style */ 134 (void)printf("%u.%06u ", 135 (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec); 136 break; 137 case -2: 138 t=tvp->tv_sec; 139 strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t)); 140 printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec); 141 break; 142 default: 143 /* Default */ 144 s = (tvp->tv_sec + thiszone) % 86400; 145 (void)printf("%02d:%02d:%02d.%06u ", 146 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec); 147 break; 148 } 149 } 150 151 /* 152 * Print a relative number of seconds (e.g. hold time, prune timer) 153 * in the form 5m1s. This does no truncation, so 32230861 seconds 154 * is represented as 1y1w1d1h1m1s. 155 */ 156 void 157 relts_print(int secs) 158 { 159 static char *lengths[] = {"y", "w", "d", "h", "m", "s"}; 160 static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; 161 char **l = lengths; 162 int *s = seconds; 163 164 if (secs <= 0) { 165 (void)printf("0s"); 166 return; 167 } 168 while (secs > 0) { 169 if (secs >= *s) { 170 (void)printf("%d%s", secs / *s, *l); 171 secs -= (secs / *s) * *s; 172 } 173 s++; 174 l++; 175 } 176 } 177 178 /* 179 * Convert a token value to a string; use "fmt" if not found. 180 */ 181 const char * 182 tok2str(register const struct tok *lp, register const char *fmt, 183 register int v) 184 { 185 static char buf[128]; 186 187 while (lp->s != NULL) { 188 if (lp->v == v) 189 return (lp->s); 190 ++lp; 191 } 192 if (fmt == NULL) 193 fmt = "#%d"; 194 (void)snprintf(buf, sizeof(buf), fmt, v); 195 return (buf); 196 } 197 198 199 /* VARARGS */ 200 __dead void 201 error(const char *fmt, ...) 202 { 203 va_list ap; 204 205 (void)fprintf(stderr, "%s: ", program_name); 206 va_start(ap, fmt); 207 (void)vfprintf(stderr, fmt, ap); 208 va_end(ap); 209 if (*fmt) { 210 fmt += strlen(fmt); 211 if (fmt[-1] != '\n') 212 (void)fputc('\n', stderr); 213 } 214 exit(1); 215 /* NOTREACHED */ 216 } 217 218 /* VARARGS */ 219 void 220 warning(const char *fmt, ...) 221 { 222 va_list ap; 223 224 (void)fprintf(stderr, "%s: WARNING: ", program_name); 225 va_start(ap, fmt); 226 (void)vfprintf(stderr, fmt, ap); 227 va_end(ap); 228 if (*fmt) { 229 fmt += strlen(fmt); 230 if (fmt[-1] != '\n') 231 (void)fputc('\n', stderr); 232 } 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 296 return (cp); 297 } 298 299 void 300 safeputs(const char *s) 301 { 302 while (*s) { 303 safeputchar(*s); 304 s++; 305 } 306 } 307 308 void 309 safeputchar(int c) 310 { 311 unsigned char ch; 312 313 ch = (unsigned char)(c & 0xff); 314 if (c < 0x80 && isprint(c)) 315 printf("%c", c & 0xff); 316 else 317 printf("\\%03o", c & 0xff); 318 } 319