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