util.c revision 98524
117680Spst/* 239297Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997 317680Spst * The Regents of the University of California. All rights reserved. 417680Spst * 517680Spst * Redistribution and use in source and binary forms, with or without 617680Spst * modification, are permitted provided that: (1) source code distributions 717680Spst * retain the above copyright notice and this paragraph in its entirety, (2) 817680Spst * distributions including binary code include the above copyright notice and 917680Spst * this paragraph in its entirety in the documentation or other materials 1017680Spst * provided with the distribution, and (3) all advertising materials mentioning 1117680Spst * features or use of this software display the following acknowledgement: 1217680Spst * ``This product includes software developed by the University of California, 1317680Spst * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1417680Spst * the University nor the names of its contributors may be used to endorse 1517680Spst * or promote products derived from this software without specific prior 1617680Spst * written permission. 1717680Spst * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1817680Spst * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1917680Spst * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2017680Spst */ 2117680Spst 2217680Spst#ifndef lint 2326180Sfennerstatic const char rcsid[] = 2498524Sfenner "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.72 2001/10/08 16:12:13 fenner Exp $ (LBL)"; 2517680Spst#endif 2617680Spst 2756893Sfenner#ifdef HAVE_CONFIG_H 2856893Sfenner#include "config.h" 2956893Sfenner#endif 3056893Sfenner 3117680Spst#include <sys/types.h> 3217680Spst#include <sys/time.h> 3317680Spst#include <sys/file.h> 3417680Spst#include <sys/stat.h> 3517680Spst 3617680Spst#include <ctype.h> 3717680Spst#include <errno.h> 3817680Spst#ifdef HAVE_FCNTL_H 3917680Spst#include <fcntl.h> 4017680Spst#endif 4117680Spst#include <pcap.h> 4217680Spst#include <stdio.h> 4317680Spst#include <stdarg.h> 4417680Spst#include <stdlib.h> 4517680Spst#include <string.h> 4617680Spst#ifdef TIME_WITH_SYS_TIME 4717680Spst#include <time.h> 4817680Spst#endif 4917680Spst#include <unistd.h> 5017680Spst 5117680Spst#include "interface.h" 5217680Spst 5317680Spst/* 5417680Spst * Print out a filename (or other ascii string). 5517680Spst * If ep is NULL, assume no truncation check is needed. 5617680Spst * Return true if truncated. 5717680Spst */ 5817680Spstint 5917680Spstfn_print(register const u_char *s, register const u_char *ep) 6017680Spst{ 6117680Spst register int ret; 6217680Spst register u_char c; 6317680Spst 6417680Spst ret = 1; /* assume truncated */ 6517680Spst while (ep == NULL || s < ep) { 6617680Spst c = *s++; 6717680Spst if (c == '\0') { 6817680Spst ret = 0; 6917680Spst break; 7017680Spst } 7117680Spst if (!isascii(c)) { 7217680Spst c = toascii(c); 7317680Spst putchar('M'); 7417680Spst putchar('-'); 7517680Spst } 7617680Spst if (!isprint(c)) { 7717680Spst c ^= 0x40; /* DEL to ?, others to alpha */ 7817680Spst putchar('^'); 7917680Spst } 8017680Spst putchar(c); 8117680Spst } 8217680Spst return(ret); 8317680Spst} 8417680Spst 8517680Spst/* 8617680Spst * Print out a counted filename (or other ascii string). 8717680Spst * If ep is NULL, assume no truncation check is needed. 8817680Spst * Return true if truncated. 8917680Spst */ 9017680Spstint 9117680Spstfn_printn(register const u_char *s, register u_int n, 9217680Spst register const u_char *ep) 9317680Spst{ 9417680Spst register int ret; 9517680Spst register u_char c; 9617680Spst 9717680Spst ret = 1; /* assume truncated */ 9817680Spst while (ep == NULL || s < ep) { 9917680Spst if (n-- <= 0) { 10017680Spst ret = 0; 10117680Spst break; 10217680Spst } 10317680Spst c = *s++; 10417680Spst if (!isascii(c)) { 10517680Spst c = toascii(c); 10617680Spst putchar('M'); 10717680Spst putchar('-'); 10817680Spst } 10917680Spst if (!isprint(c)) { 11017680Spst c ^= 0x40; /* DEL to ?, others to alpha */ 11117680Spst putchar('^'); 11217680Spst } 11317680Spst putchar(c); 11417680Spst } 11517680Spst return(ret); 11617680Spst} 11717680Spst 11817680Spst/* 11917680Spst * Print the timestamp 12017680Spst */ 12117680Spstvoid 12217680Spstts_print(register const struct timeval *tvp) 12317680Spst{ 12417680Spst register int s; 12575115Sfenner struct tm *tm; 12675115Sfenner time_t Time; 12775115Sfenner static unsigned b_sec; 12875115Sfenner static unsigned b_usec; 12917680Spst 13075115Sfenner switch(tflag) { 13175115Sfenner case 1: /* Default */ 13217680Spst s = (tvp->tv_sec + thiszone) % 86400; 13317680Spst (void)printf("%02d:%02d:%02d.%06u ", 13475115Sfenner s / 3600, (s % 3600) / 60, s % 60, 13575115Sfenner (unsigned)tvp->tv_usec); 13675115Sfenner break; 13775115Sfenner case -1: /* Unix timeval style */ 13875115Sfenner (void)printf("%u.%06u ", 13975115Sfenner (unsigned)tvp->tv_sec, 14075115Sfenner (unsigned)tvp->tv_usec); 14175115Sfenner break; 14275115Sfenner case -2: 14375115Sfenner if (b_sec == 0) { 14475115Sfenner printf("000000 "); 14575115Sfenner } else { 14675115Sfenner int d_usec = tvp->tv_usec - b_usec; 14775115Sfenner int d_sec = tvp->tv_sec - b_sec; 14875115Sfenner 14975115Sfenner while (d_usec < 0) { 15075115Sfenner d_usec += 1000000; 15175115Sfenner d_sec--; 15256893Sfenner } 15375115Sfenner if (d_sec) 15475115Sfenner printf("%d. ", d_sec); 15575115Sfenner printf("%06d ", d_usec); 15656893Sfenner } 15775115Sfenner b_sec = tvp->tv_sec; 15875115Sfenner b_usec = tvp->tv_usec; 15975115Sfenner break; 16075115Sfenner case -3: /* Default + Date*/ 16175115Sfenner s = (tvp->tv_sec + thiszone) % 86400; 16275115Sfenner Time = (tvp->tv_sec + thiszone) - s; 16375115Sfenner tm = gmtime (&Time); 16475115Sfenner (void)printf("%02d/%02d/%04d %02d:%02d:%02d.%06u ", 16575115Sfenner tm->tm_mon+1, tm->tm_mday, 16675115Sfenner tm->tm_year+1900, 16775115Sfenner s / 3600, (s % 3600) / 60, 16875115Sfenner s % 60, (unsigned)tvp->tv_usec); 16975115Sfenner break; 17017680Spst } 17117680Spst} 17217680Spst 17317680Spst/* 17456893Sfenner * Print a relative number of seconds (e.g. hold time, prune timer) 17556893Sfenner * in the form 5m1s. This does no truncation, so 32230861 seconds 17656893Sfenner * is represented as 1y1w1d1h1m1s. 17756893Sfenner */ 17856893Sfennervoid 17956893Sfennerrelts_print(int secs) 18056893Sfenner{ 18198524Sfenner static const char *lengths[] = {"y", "w", "d", "h", "m", "s"}; 18298524Sfenner static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1}; 18398524Sfenner const char **l = lengths; 18498524Sfenner const int *s = seconds; 18556893Sfenner 18698524Sfenner if (secs == 0) { 18775115Sfenner (void)printf("0s"); 18875115Sfenner return; 18956893Sfenner } 19098524Sfenner if (secs < 0) { 19198524Sfenner (void)printf("-"); 19298524Sfenner secs = -secs; 19398524Sfenner } 19475115Sfenner while (secs > 0) { 19575115Sfenner if (secs >= *s) { 19675115Sfenner (void)printf("%d%s", secs / *s, *l); 19775115Sfenner secs -= (secs / *s) * *s; 19875115Sfenner } 19975115Sfenner s++; 20075115Sfenner l++; 20175115Sfenner } 20256893Sfenner} 20356893Sfenner 20456893Sfenner/* 20517680Spst * Convert a token value to a string; use "fmt" if not found. 20617680Spst */ 20717680Spstconst char * 20817680Spsttok2str(register const struct tok *lp, register const char *fmt, 20917680Spst register int v) 21017680Spst{ 21117680Spst static char buf[128]; 21217680Spst 21317680Spst while (lp->s != NULL) { 21417680Spst if (lp->v == v) 21517680Spst return (lp->s); 21617680Spst ++lp; 21717680Spst } 21817680Spst if (fmt == NULL) 21917680Spst fmt = "#%d"; 22075115Sfenner (void)snprintf(buf, sizeof(buf), fmt, v); 22117680Spst return (buf); 22217680Spst} 22317680Spst 22498524Sfenner/* 22598524Sfenner * Convert a value to a string using an array; the macro 22698524Sfenner * tok2strary() in <interface.h> is the public interface to 22798524Sfenner * this function and ensures that the second argument is 22898524Sfenner * correct for bounds-checking. 22998524Sfenner */ 23098524Sfennerconst char * 23198524Sfennertok2strary_internal(register const char **lp, int n, register const char *fmt, 23298524Sfenner register int v) 23398524Sfenner{ 23498524Sfenner static char buf[128]; 23517680Spst 23698524Sfenner if (v >= 0 && v < n && lp[v] != NULL) 23798524Sfenner return lp[v]; 23898524Sfenner if (fmt == NULL) 23998524Sfenner fmt = "#%d"; 24098524Sfenner (void)snprintf(buf, sizeof(buf), fmt, v); 24198524Sfenner return (buf); 24298524Sfenner} 24398524Sfenner 24417680Spst/* VARARGS */ 24575115Sfennervoid 24617680Spsterror(const char *fmt, ...) 24717680Spst{ 24817680Spst va_list ap; 24917680Spst 25017680Spst (void)fprintf(stderr, "%s: ", program_name); 25117680Spst va_start(ap, fmt); 25217680Spst (void)vfprintf(stderr, fmt, ap); 25317680Spst va_end(ap); 25417680Spst if (*fmt) { 25517680Spst fmt += strlen(fmt); 25617680Spst if (fmt[-1] != '\n') 25717680Spst (void)fputc('\n', stderr); 25817680Spst } 25917680Spst exit(1); 26017680Spst /* NOTREACHED */ 26117680Spst} 26217680Spst 26317680Spst/* VARARGS */ 26417680Spstvoid 26517680Spstwarning(const char *fmt, ...) 26617680Spst{ 26717680Spst va_list ap; 26817680Spst 26917680Spst (void)fprintf(stderr, "%s: WARNING: ", program_name); 27017680Spst va_start(ap, fmt); 27117680Spst (void)vfprintf(stderr, fmt, ap); 27217680Spst va_end(ap); 27317680Spst if (*fmt) { 27417680Spst fmt += strlen(fmt); 27517680Spst if (fmt[-1] != '\n') 27617680Spst (void)fputc('\n', stderr); 27717680Spst } 27817680Spst} 27917680Spst 28017680Spst/* 28117680Spst * Copy arg vector into a new buffer, concatenating arguments with spaces. 28217680Spst */ 28317680Spstchar * 28417680Spstcopy_argv(register char **argv) 28517680Spst{ 28617680Spst register char **p; 28717680Spst register u_int len = 0; 28817680Spst char *buf; 28917680Spst char *src, *dst; 29017680Spst 29117680Spst p = argv; 29217680Spst if (*p == 0) 29317680Spst return 0; 29417680Spst 29517680Spst while (*p) 29617680Spst len += strlen(*p++) + 1; 29717680Spst 29817680Spst buf = (char *)malloc(len); 29917680Spst if (buf == NULL) 30017680Spst error("copy_argv: malloc"); 30117680Spst 30217680Spst p = argv; 30317680Spst dst = buf; 30417680Spst while ((src = *p++) != NULL) { 30517680Spst while ((*dst++ = *src++) != '\0') 30617680Spst ; 30717680Spst dst[-1] = ' '; 30817680Spst } 30917680Spst dst[-1] = '\0'; 31017680Spst 31117680Spst return buf; 31217680Spst} 31317680Spst 31417680Spstchar * 31517680Spstread_infile(char *fname) 31617680Spst{ 31717680Spst register int fd, cc; 31817680Spst register char *cp; 31917680Spst struct stat buf; 32017680Spst 32117680Spst fd = open(fname, O_RDONLY); 32217680Spst if (fd < 0) 32317680Spst error("can't open %s: %s", fname, pcap_strerror(errno)); 32417680Spst 32517680Spst if (fstat(fd, &buf) < 0) 32617680Spst error("can't stat %s: %s", fname, pcap_strerror(errno)); 32717680Spst 32817680Spst cp = malloc((u_int)buf.st_size + 1); 32998524Sfenner if (cp == NULL) 33098524Sfenner error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1, 33198524Sfenner fname, pcap_strerror(errno)); 33298524Sfenner cc = read(fd, cp, (u_int)buf.st_size); 33317680Spst if (cc < 0) 33417680Spst error("read %s: %s", fname, pcap_strerror(errno)); 33517680Spst if (cc != buf.st_size) 33617680Spst error("short read %s (%d != %d)", fname, cc, (int)buf.st_size); 33717680Spst cp[(int)buf.st_size] = '\0'; 33817680Spst 33917680Spst return (cp); 34017680Spst} 34175115Sfenner 34275115Sfennervoid 34375115Sfennersafeputs(const char *s) 34475115Sfenner{ 34575115Sfenner while (*s) { 34675115Sfenner safeputchar(*s); 34775115Sfenner s++; 34875115Sfenner } 34975115Sfenner} 35075115Sfenner 35175115Sfennervoid 35275115Sfennersafeputchar(int c) 35375115Sfenner{ 35475115Sfenner unsigned char ch; 35575115Sfenner 35675115Sfenner ch = (unsigned char)(c & 0xff); 35775115Sfenner if (c < 0x80 && isprint(c)) 35875115Sfenner printf("%c", c & 0xff); 35975115Sfenner else 36075115Sfenner printf("\\%03o", c & 0xff); 36175115Sfenner} 362