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