util.c revision 56893
1184610Salfred/*
2184610Salfred * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3184610Salfred *	The Regents of the University of California.  All rights reserved.
4184610Salfred *
5184610Salfred * Redistribution and use in source and binary forms, with or without
6184610Salfred * modification, are permitted provided that: (1) source code distributions
7184610Salfred * retain the above copyright notice and this paragraph in its entirety, (2)
8184610Salfred * distributions including binary code include the above copyright notice and
9184610Salfred * this paragraph in its entirety in the documentation or other materials
10184610Salfred * provided with the distribution, and (3) all advertising materials mentioning
11184610Salfred * features or use of this software display the following acknowledgement:
12184610Salfred * ``This product includes software developed by the University of California,
13184610Salfred * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14184610Salfred * the University nor the names of its contributors may be used to endorse
15184610Salfred * or promote products derived from this software without specific prior
16184610Salfred * written permission.
17184610Salfred * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18184610Salfred * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19184610Salfred * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20184610Salfred */
21184610Salfred
22184610Salfred#ifndef lint
23184610Salfredstatic const char rcsid[] =
24184610Salfred    "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.62 1999/12/15 06:58:03 fenner Exp $ (LBL)";
25184610Salfred#endif
26184610Salfred
27246122Shselasky#ifdef HAVE_CONFIG_H
28246122Shselasky#include "config.h"
29246122Shselasky#endif
30194677Sthompsa
31194677Sthompsa#include <sys/types.h>
32194677Sthompsa#include <sys/time.h>
33194677Sthompsa#include <sys/file.h>
34194677Sthompsa#include <sys/stat.h>
35194677Sthompsa
36194677Sthompsa#include <ctype.h>
37194677Sthompsa#include <errno.h>
38194677Sthompsa#ifdef HAVE_FCNTL_H
39194677Sthompsa#include <fcntl.h>
40194677Sthompsa#endif
41194677Sthompsa#ifdef HAVE_MALLOC_H
42194677Sthompsa#include <malloc.h>
43194677Sthompsa#endif
44194677Sthompsa#include <pcap.h>
45194677Sthompsa#include <stdio.h>
46194677Sthompsa#if __STDC__
47194677Sthompsa#include <stdarg.h>
48184610Salfred#else
49194677Sthompsa#include <varargs.h>
50194677Sthompsa#endif
51246122Shselasky#include <stdlib.h>
52184610Salfred#include <string.h>
53188048Sthompsa#ifdef TIME_WITH_SYS_TIME
54188048Sthompsa#include <time.h>
55188076Sthompsa#endif
56188076Sthompsa#include <unistd.h>
57188076Sthompsa
58188076Sthompsa#include "interface.h"
59188076Sthompsa
60188048Sthompsa/*
61188048Sthompsa * Print out a filename (or other ascii string).
62188048Sthompsa * If ep is NULL, assume no truncation check is needed.
63188076Sthompsa * Return true if truncated.
64188048Sthompsa */
65188048Sthompsaint
66188048Sthompsafn_print(register const u_char *s, register const u_char *ep)
67188076Sthompsa{
68188076Sthompsa	register int ret;
69188076Sthompsa	register u_char c;
70188048Sthompsa
71188076Sthompsa	ret = 1;			/* assume truncated */
72188076Sthompsa	while (ep == NULL || s < ep) {
73188076Sthompsa		c = *s++;
74188076Sthompsa		if (c == '\0') {
75188048Sthompsa			ret = 0;
76188048Sthompsa			break;
77188076Sthompsa		}
78188076Sthompsa		if (!isascii(c)) {
79188076Sthompsa			c = toascii(c);
80188076Sthompsa			putchar('M');
81188076Sthompsa			putchar('-');
82188076Sthompsa		}
83188048Sthompsa		if (!isprint(c)) {
84188076Sthompsa			c ^= 0x40;	/* DEL to ?, others to alpha */
85184610Salfred			putchar('^');
86194228Sthompsa		}
87184610Salfred		putchar(c);
88184610Salfred	}
89184610Salfred	return(ret);
90184610Salfred}
91194228Sthompsa
92184610Salfred/*
93188048Sthompsa * Print out a counted filename (or other ascii string).
94184610Salfred * If ep is NULL, assume no truncation check is needed.
95 * Return true if truncated.
96 */
97int
98fn_printn(register const u_char *s, register u_int n,
99	  register const u_char *ep)
100{
101	register int ret;
102	register u_char c;
103
104	ret = 1;			/* assume truncated */
105	while (ep == NULL || s < ep) {
106		if (n-- <= 0) {
107			ret = 0;
108			break;
109		}
110		c = *s++;
111		if (!isascii(c)) {
112			c = toascii(c);
113			putchar('M');
114			putchar('-');
115		}
116		if (!isprint(c)) {
117			c ^= 0x40;	/* DEL to ?, others to alpha */
118			putchar('^');
119		}
120		putchar(c);
121	}
122	return(ret);
123}
124
125/*
126 * Print the timestamp
127 */
128void
129ts_print(register const struct timeval *tvp)
130{
131	register int s;
132
133	if (tflag > 0) {
134		/* Default */
135		s = (tvp->tv_sec + thiszone) % 86400;
136		(void)printf("%02d:%02d:%02d.%06u ",
137		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
138	} else if (tflag < 0) {
139		if (tflag < -1) {
140			static unsigned b_sec;
141			static unsigned b_usec;
142			if (b_sec == 0) {
143				printf("000000 ");
144			} else {
145				int d_usec = tvp->tv_usec - b_usec;
146				int d_sec = tvp->tv_sec - b_sec;
147
148				while (d_usec < 0) {
149					d_usec += 1000000;
150					d_sec--;
151				}
152				if (d_sec)
153					printf("%d. ", d_sec);
154				printf("%06d ", d_usec);
155			}
156			b_sec = tvp->tv_sec;
157			b_usec = tvp->tv_usec;
158		} else {
159			/* Unix timeval style */
160			(void)printf("%u.%06u ",
161				     (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
162		}
163	}
164}
165
166/*
167 * Print a relative number of seconds (e.g. hold time, prune timer)
168 * in the form 5m1s.  This does no truncation, so 32230861 seconds
169 * is represented as 1y1w1d1h1m1s.
170 */
171void
172relts_print(int secs)
173{
174    static char *lengths[]={"y","w","d","h","m","s"};
175    static int seconds[]={31536000,604800,86400,3600,60,1};
176    char **l = lengths;
177    int *s = seconds;
178
179    if (secs == 0) {
180	(void)printf("0s");
181	return;
182    }
183    while (secs) {
184	if (secs >= *s) {
185	    (void)printf("%d%s", secs / *s, *l);
186	    secs -= (secs / *s) * *s;
187	}
188	s++; l++;
189    }
190}
191
192/*
193 * Convert a token value to a string; use "fmt" if not found.
194 */
195const char *
196tok2str(register const struct tok *lp, register const char *fmt,
197	register int v)
198{
199	static char buf[128];
200
201	while (lp->s != NULL) {
202		if (lp->v == v)
203			return (lp->s);
204		++lp;
205	}
206	if (fmt == NULL)
207		fmt = "#%d";
208	(void)sprintf(buf, fmt, v);
209	return (buf);
210}
211
212
213/* VARARGS */
214__dead void
215#if __STDC__
216error(const char *fmt, ...)
217#else
218error(fmt, va_alist)
219	const char *fmt;
220	va_dcl
221#endif
222{
223	va_list ap;
224
225	(void)fprintf(stderr, "%s: ", program_name);
226#if __STDC__
227	va_start(ap, fmt);
228#else
229	va_start(ap);
230#endif
231	(void)vfprintf(stderr, fmt, ap);
232	va_end(ap);
233	if (*fmt) {
234		fmt += strlen(fmt);
235		if (fmt[-1] != '\n')
236			(void)fputc('\n', stderr);
237	}
238	exit(1);
239	/* NOTREACHED */
240}
241
242/* VARARGS */
243void
244#if __STDC__
245warning(const char *fmt, ...)
246#else
247warning(fmt, va_alist)
248	const char *fmt;
249	va_dcl
250#endif
251{
252	va_list ap;
253
254	(void)fprintf(stderr, "%s: WARNING: ", program_name);
255#if __STDC__
256	va_start(ap, fmt);
257#else
258	va_start(ap);
259#endif
260	(void)vfprintf(stderr, fmt, ap);
261	va_end(ap);
262	if (*fmt) {
263		fmt += strlen(fmt);
264		if (fmt[-1] != '\n')
265			(void)fputc('\n', stderr);
266	}
267}
268
269/*
270 * Copy arg vector into a new buffer, concatenating arguments with spaces.
271 */
272char *
273copy_argv(register char **argv)
274{
275	register char **p;
276	register u_int len = 0;
277	char *buf;
278	char *src, *dst;
279
280	p = argv;
281	if (*p == 0)
282		return 0;
283
284	while (*p)
285		len += strlen(*p++) + 1;
286
287	buf = (char *)malloc(len);
288	if (buf == NULL)
289		error("copy_argv: malloc");
290
291	p = argv;
292	dst = buf;
293	while ((src = *p++) != NULL) {
294		while ((*dst++ = *src++) != '\0')
295			;
296		dst[-1] = ' ';
297	}
298	dst[-1] = '\0';
299
300	return buf;
301}
302
303char *
304read_infile(char *fname)
305{
306	register int fd, cc;
307	register char *cp;
308	struct stat buf;
309
310	fd = open(fname, O_RDONLY);
311	if (fd < 0)
312		error("can't open %s: %s", fname, pcap_strerror(errno));
313
314	if (fstat(fd, &buf) < 0)
315		error("can't stat %s: %s", fname, pcap_strerror(errno));
316
317	cp = malloc((u_int)buf.st_size + 1);
318	cc = read(fd, cp, (int)buf.st_size);
319	if (cc < 0)
320		error("read %s: %s", fname, pcap_strerror(errno));
321	if (cc != buf.st_size)
322		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
323	cp[(int)buf.st_size] = '\0';
324
325	return (cp);
326}
327