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