/* $OpenBSD: util.c,v 1.30 2020/01/24 22:46:37 procter Exp $ */ /* * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that: (1) source code distributions * retain the above copyright notice and this paragraph in its entirety, (2) * distributions including binary code include the above copyright notice and * this paragraph in its entirety in the documentation or other materials * provided with the distribution, and (3) all advertising materials mentioning * features or use of this software display the following acknowledgement: * ``This product includes software developed by the University of California, * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of * the University nor the names of its contributors may be used to endorse * or promote products derived from this software without specific prior * written permission. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include #include #include #include #include #include #include #include #ifdef HAVE_FCNTL_H #include #endif #include #include #include #include #include #ifdef TIME_WITH_SYS_TIME #include #endif #include #include "interface.h" #include "privsep.h" /* * Print out a filename (or other ascii string). * If ep is NULL, assume no truncation check is needed. * Return true if truncated. */ int fn_print(const u_char *s, const u_char *ep) { int ret; u_char c; ret = 1; /* assume truncated */ while (ep == NULL || s < ep) { c = *s++; if (c == '\0') { ret = 0; break; } if (!isascii(c)) { c = toascii(c); putchar('M'); putchar('-'); } if (!isprint(c)) { c ^= 0x40; /* DEL to ?, others to alpha */ putchar('^'); } putchar(c); } return(ret); } /* * Print out a counted filename (or other ascii string). * If ep is NULL, assume no truncation check is needed. * Return true if truncated. */ int fn_printn(const u_char *s, u_int n, const u_char *ep) { int ret; u_char c; ret = 1; /* assume truncated */ while (ep == NULL || s < ep) { if (n-- <= 0) { ret = 0; break; } c = *s++; if (!isascii(c)) { c = toascii(c); putchar('M'); putchar('-'); } if (!isprint(c)) { c ^= 0x40; /* DEL to ?, others to alpha */ putchar('^'); } putchar(c); } return(ret); } /* * Print the timestamp */ void ts_print(const struct bpf_timeval *tvp) { int s; #define TSBUFLEN 32 static char buf[TSBUFLEN]; static struct timeval last; struct timeval diff, cur; time_t t; if (Iflag && device) printf("%s ", device); switch(tflag){ case 0: break; case -1: /* Unix timeval style */ printf("%u.%06u ", tvp->tv_sec, tvp->tv_usec); break; case -2: t = tvp->tv_sec; strftime(buf, TSBUFLEN, "%b %d %T", priv_localtime(&t)); printf("%s.%06u ", buf, tvp->tv_usec); break; case -3: /* last frame time delta */ case -4: /* first frame time delta */ cur.tv_sec = tvp->tv_sec; cur.tv_usec = tvp->tv_usec; timersub(&cur, &last, &diff); printf("%lld.%06ld ", diff.tv_sec, diff.tv_usec); if (!timerisset(&last) || tflag == -3) last = cur; break; default: s = (tvp->tv_sec + thiszone) % 86400; printf("%02d:%02d:%02d.%06u ", s / 3600, (s % 3600) / 60, s % 60, tvp->tv_usec); break; } } /* * Print a relative number of seconds (e.g. hold time, prune timer) * in the form 5m1s. This does no truncation, so 32230861 seconds * is represented as 1y1w1d1h1m1s. */ void relts_print(int secs) { static char *lengths[] = {"y", "w", "d", "h", "m", "s"}; static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; char **l = lengths; int *s = seconds; if (secs <= 0) { printf("0s"); return; } while (secs > 0) { if (secs >= *s) { printf("%d%s", secs / *s, *l); secs -= (secs / *s) * *s; } s++; l++; } } /* * Convert a token value to a string; use "fmt" if not found. */ const char * tok2str(const struct tok *lp, const char *fmt, int v) { static char buf[128]; while (lp->s != NULL) { if (lp->v == v) return (lp->s); ++lp; } if (fmt == NULL) fmt = "#%d"; (void)snprintf(buf, sizeof(buf), fmt, v); return (buf); } __dead void error(const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); (void)fputc('\n', stderr); exit(1); /* NOTREACHED */ } void warning(const char *fmt, ...) { va_list ap; (void)fprintf(stderr, "%s: WARNING: ", program_name); va_start(ap, fmt); (void)vfprintf(stderr, fmt, ap); va_end(ap); (void)fputc('\n', stderr); } /* * Copy arg vector into a new buffer, concatenating arguments with spaces. */ char * copy_argv(char * const *argv) { size_t len = 0, n; char *buf; if (argv == NULL) return (NULL); for (n = 0; argv[n]; n++) len += strlen(argv[n])+1; if (len == 0) return (NULL); buf = malloc(len); if (buf == NULL) return (NULL); strlcpy(buf, argv[0], len); for (n = 1; argv[n]; n++) { strlcat(buf, " ", len); strlcat(buf, argv[n], len); } return (buf); } char * read_infile(char *fname) { struct stat buf; int fd; ssize_t cc; size_t bs; char *cp; fd = open(fname, O_RDONLY); if (fd == -1) error("can't open %s: %s", fname, pcap_strerror(errno)); if (fstat(fd, &buf) == -1) error("can't stat %s: %s", fname, pcap_strerror(errno)); if (buf.st_size >= SSIZE_MAX) error("file too long"); bs = buf.st_size; cp = malloc(bs + 1); if (cp == NULL) err(1, NULL); cc = read(fd, cp, bs); if (cc == -1) error("read %s: %s", fname, pcap_strerror(errno)); if (cc != bs) error("short read %s (%ld != %lu)", fname, (long)cc, (unsigned long)bs); cp[bs] = '\0'; close(fd); return (cp); } void safeputs(const char *s) { while (*s) { safeputchar(*s); s++; } } void safeputchar(int c) { unsigned char ch; ch = (unsigned char)(c & 0xff); if (c < 0x80 && isprint(c)) printf("%c", c & 0xff); else printf("\\%03o", c & 0xff); } /* * Print a value a la the %b format of the kernel's printf * (from sbin/ifconfig/ifconfig.c) */ void printb(char *s, unsigned short v, char *bits) { int i, any = 0; char c; if (bits && *bits == 8) printf("%s=%o", s, v); else printf("%s=%x", s, v); if (bits) { bits++; putchar('<'); while ((i = *bits++)) { if (v & (1 << (i-1))) { if (any) putchar(','); any = 1; for (; (c = *bits) > 32; bits++) putchar(c); } else for (; *bits > 32; bits++) ; } putchar('>'); } }