1 /* $OpenBSD: util.c,v 1.24 2008/09/19 08:52:16 mpf 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 "@(#) $Id: util.c,v 1.24 2008/09/19 08:52:16 mpf 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 if (Iflag && device) 132 (void)printf("%s ", device); 133 switch(tflag){ 134 case 0: 135 break; 136 case -1: 137 /* Unix timeval style */ 138 (void)printf("%u.%06u ", 139 (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec); 140 break; 141 case -2: 142 t=tvp->tv_sec; 143 strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t)); 144 printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec); 145 break; 146 case -3: 147 case -4: 148 /* time since first/last frame */ 149 timersub(tvp, &last, &diff); 150 (void)printf("%u.%06u ", 151 (u_int32_t)diff.tv_sec, (u_int32_t)diff.tv_usec); 152 if (tflag == -3 || (last.tv_sec == 0 && last.tv_usec == 0)) 153 last = *tvp; 154 break; 155 default: 156 /* Default */ 157 s = (tvp->tv_sec + thiszone) % 86400; 158 (void)printf("%02d:%02d:%02d.%06u ", 159 s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec); 160 break; 161 } 162 } 163 164 /* 165 * Print a relative number of seconds (e.g. hold time, prune timer) 166 * in the form 5m1s. This does no truncation, so 32230861 seconds 167 * is represented as 1y1w1d1h1m1s. 168 */ 169 void 170 relts_print(int secs) 171 { 172 static char *lengths[] = {"y", "w", "d", "h", "m", "s"}; 173 static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; 174 char **l = lengths; 175 int *s = seconds; 176 177 if (secs <= 0) { 178 (void)printf("0s"); 179 return; 180 } 181 while (secs > 0) { 182 if (secs >= *s) { 183 (void)printf("%d%s", secs / *s, *l); 184 secs -= (secs / *s) * *s; 185 } 186 s++; 187 l++; 188 } 189 } 190 191 /* 192 * Convert a token value to a string; use "fmt" if not found. 193 */ 194 const char * 195 tok2str(register const struct tok *lp, register const char *fmt, 196 register int v) 197 { 198 static char buf[128]; 199 200 while (lp->s != NULL) { 201 if (lp->v == v) 202 return (lp->s); 203 ++lp; 204 } 205 if (fmt == NULL) 206 fmt = "#%d"; 207 (void)snprintf(buf, sizeof(buf), fmt, v); 208 return (buf); 209 } 210 211 212 /* VARARGS */ 213 __dead void 214 error(const char *fmt, ...) 215 { 216 va_list ap; 217 218 (void)fprintf(stderr, "%s: ", program_name); 219 va_start(ap, fmt); 220 (void)vfprintf(stderr, fmt, ap); 221 va_end(ap); 222 (void)fputc('\n', stderr); 223 exit(1); 224 /* NOTREACHED */ 225 } 226 227 /* VARARGS */ 228 void 229 warning(const char *fmt, ...) 230 { 231 va_list ap; 232 233 (void)fprintf(stderr, "%s: WARNING: ", program_name); 234 va_start(ap, fmt); 235 (void)vfprintf(stderr, fmt, ap); 236 va_end(ap); 237 (void)fputc('\n', stderr); 238 } 239 240 241 /* 242 * Copy arg vector into a new buffer, concatenating arguments with spaces. 243 */ 244 char * 245 copy_argv(char * const *argv) 246 { 247 size_t len = 0, n; 248 char *buf; 249 250 if (argv == NULL) 251 return (NULL); 252 253 for (n = 0; argv[n]; n++) 254 len += strlen(argv[n])+1; 255 if (len == 0) 256 return (NULL); 257 258 buf = malloc(len); 259 if (buf == NULL) 260 return (NULL); 261 262 strlcpy(buf, argv[0], len); 263 for (n = 1; argv[n]; n++) { 264 strlcat(buf, " ", len); 265 strlcat(buf, argv[n], len); 266 } 267 return (buf); 268 } 269 270 char * 271 read_infile(char *fname) 272 { 273 struct stat buf; 274 int fd; 275 ssize_t cc; 276 size_t bs; 277 char *cp; 278 279 fd = open(fname, O_RDONLY); 280 if (fd < 0) 281 error("can't open %s: %s", fname, pcap_strerror(errno)); 282 283 if (fstat(fd, &buf) < 0) 284 error("can't stat %s: %s", fname, pcap_strerror(errno)); 285 286 if (buf.st_size >= SSIZE_MAX) 287 error("file too long"); 288 289 bs = buf.st_size; 290 cp = malloc(bs + 1); 291 if (cp == NULL) 292 err(1, NULL); 293 cc = read(fd, cp, bs); 294 if (cc == -1) 295 error("read %s: %s", fname, pcap_strerror(errno)); 296 if (cc != bs) 297 error("short read %s (%ld != %lu)", fname, (long)cc, 298 (unsigned long)bs); 299 cp[bs] = '\0'; 300 close(fd); 301 302 return (cp); 303 } 304 305 void 306 safeputs(const char *s) 307 { 308 while (*s) { 309 safeputchar(*s); 310 s++; 311 } 312 } 313 314 void 315 safeputchar(int c) 316 { 317 unsigned char ch; 318 319 ch = (unsigned char)(c & 0xff); 320 if (c < 0x80 && isprint(c)) 321 printf("%c", c & 0xff); 322 else 323 printf("\\%03o", c & 0xff); 324 } 325 326 /* 327 * Print a value a la the %b format of the kernel's printf 328 * (from sbin/ifconfig/ifconfig.c) 329 */ 330 void 331 printb(char *s, unsigned short v, char *bits) 332 { 333 int i, any = 0; 334 char c; 335 336 if (bits && *bits == 8) 337 printf("%s=%o", s, v); 338 else 339 printf("%s=%x", s, v); 340 341 if (bits) { 342 bits++; 343 putchar('<'); 344 while ((i = *bits++)) { 345 if (v & (1 << (i-1))) { 346 if (any) 347 putchar(','); 348 any = 1; 349 for (; (c = *bits) > 32; bits++) 350 putchar(c); 351 } else 352 for (; *bits > 32; bits++) 353 ; 354 } 355 putchar('>'); 356 } 357 } 358