util.c revision 75115
1/*
2 * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
3 *	The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that: (1) source code distributions
7 * retain the above copyright notice and this paragraph in its entirety, (2)
8 * distributions including binary code include the above copyright notice and
9 * this paragraph in its entirety in the documentation or other materials
10 * provided with the distribution, and (3) all advertising materials mentioning
11 * features or use of this software display the following acknowledgement:
12 * ``This product includes software developed by the University of California,
13 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14 * the University nor the names of its contributors may be used to endorse
15 * or promote products derived from this software without specific prior
16 * written permission.
17 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20 */
21
22#ifndef lint
23static const char rcsid[] =
24    "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.69 2000/07/11 00:49:03 assar Exp $ (LBL)";
25#endif
26
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#endif
30
31#include <sys/types.h>
32#include <sys/time.h>
33#include <sys/file.h>
34#include <sys/stat.h>
35
36#include <ctype.h>
37#include <errno.h>
38#ifdef HAVE_FCNTL_H
39#include <fcntl.h>
40#endif
41#include <pcap.h>
42#include <stdio.h>
43#include <stdarg.h>
44#include <stdlib.h>
45#include <string.h>
46#ifdef TIME_WITH_SYS_TIME
47#include <time.h>
48#endif
49#include <unistd.h>
50
51#include "interface.h"
52
53/*
54 * Print out a filename (or other ascii string).
55 * If ep is NULL, assume no truncation check is needed.
56 * Return true if truncated.
57 */
58int
59fn_print(register const u_char *s, register const u_char *ep)
60{
61	register int ret;
62	register u_char c;
63
64	ret = 1;			/* assume truncated */
65	while (ep == NULL || s < ep) {
66		c = *s++;
67		if (c == '\0') {
68			ret = 0;
69			break;
70		}
71		if (!isascii(c)) {
72			c = toascii(c);
73			putchar('M');
74			putchar('-');
75		}
76		if (!isprint(c)) {
77			c ^= 0x40;	/* DEL to ?, others to alpha */
78			putchar('^');
79		}
80		putchar(c);
81	}
82	return(ret);
83}
84
85/*
86 * Print out a counted filename (or other ascii string).
87 * If ep is NULL, assume no truncation check is needed.
88 * Return true if truncated.
89 */
90int
91fn_printn(register const u_char *s, register u_int n,
92	  register const u_char *ep)
93{
94	register int ret;
95	register u_char c;
96
97	ret = 1;			/* assume truncated */
98	while (ep == NULL || s < ep) {
99		if (n-- <= 0) {
100			ret = 0;
101			break;
102		}
103		c = *s++;
104		if (!isascii(c)) {
105			c = toascii(c);
106			putchar('M');
107			putchar('-');
108		}
109		if (!isprint(c)) {
110			c ^= 0x40;	/* DEL to ?, others to alpha */
111			putchar('^');
112		}
113		putchar(c);
114	}
115	return(ret);
116}
117
118/*
119 * Print the timestamp
120 */
121void
122ts_print(register const struct timeval *tvp)
123{
124	register int s;
125	struct tm *tm;
126	time_t Time;
127	static unsigned b_sec;
128	static unsigned b_usec;
129
130	switch(tflag) {
131	case 1: /* Default */
132		s = (tvp->tv_sec + thiszone) % 86400;
133		(void)printf("%02d:%02d:%02d.%06u ",
134			     s / 3600, (s % 3600) / 60, s % 60,
135			     (unsigned)tvp->tv_usec);
136		break;
137	case -1: /* Unix timeval style */
138		(void)printf("%u.%06u ",
139			     (unsigned)tvp->tv_sec,
140			     (unsigned)tvp->tv_usec);
141		break;
142	case -2:
143		if (b_sec == 0) {
144			printf("000000 ");
145		} else {
146			int d_usec = tvp->tv_usec - b_usec;
147			int d_sec = tvp->tv_sec - b_sec;
148
149			while (d_usec < 0) {
150				d_usec += 1000000;
151				d_sec--;
152			}
153			if (d_sec)
154				printf("%d. ", d_sec);
155			printf("%06d ", d_usec);
156		}
157		b_sec = tvp->tv_sec;
158		b_usec = tvp->tv_usec;
159		break;
160	case -3: /* Default + Date*/
161		s = (tvp->tv_sec + thiszone) % 86400;
162		Time = (tvp->tv_sec + thiszone) - s;
163		tm  = gmtime (&Time);
164		(void)printf("%02d/%02d/%04d %02d:%02d:%02d.%06u ",
165			     tm->tm_mon+1, tm->tm_mday,
166			     tm->tm_year+1900,
167			     s / 3600, (s % 3600) / 60,
168			     s % 60, (unsigned)tvp->tv_usec);
169		break;
170	}
171}
172
173/*
174 * Print a relative number of seconds (e.g. hold time, prune timer)
175 * in the form 5m1s.  This does no truncation, so 32230861 seconds
176 * is represented as 1y1w1d1h1m1s.
177 */
178void
179relts_print(int secs)
180{
181	static char *lengths[] = {"y", "w", "d", "h", "m", "s"};
182	static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
183	char **l = lengths;
184	int *s = seconds;
185
186	if (secs <= 0) {
187		(void)printf("0s");
188		return;
189	}
190	while (secs > 0) {
191		if (secs >= *s) {
192			(void)printf("%d%s", secs / *s, *l);
193			secs -= (secs / *s) * *s;
194		}
195		s++;
196		l++;
197	}
198}
199
200/*
201 * Convert a token value to a string; use "fmt" if not found.
202 */
203const char *
204tok2str(register const struct tok *lp, register const char *fmt,
205	register int v)
206{
207	static char buf[128];
208
209	while (lp->s != NULL) {
210		if (lp->v == v)
211			return (lp->s);
212		++lp;
213	}
214	if (fmt == NULL)
215		fmt = "#%d";
216	(void)snprintf(buf, sizeof(buf), fmt, v);
217	return (buf);
218}
219
220
221/* VARARGS */
222void
223error(const char *fmt, ...)
224{
225	va_list ap;
226
227	(void)fprintf(stderr, "%s: ", program_name);
228	va_start(ap, fmt);
229	(void)vfprintf(stderr, fmt, ap);
230	va_end(ap);
231	if (*fmt) {
232		fmt += strlen(fmt);
233		if (fmt[-1] != '\n')
234			(void)fputc('\n', stderr);
235	}
236	exit(1);
237	/* NOTREACHED */
238}
239
240/* VARARGS */
241void
242warning(const char *fmt, ...)
243{
244	va_list ap;
245
246	(void)fprintf(stderr, "%s: WARNING: ", program_name);
247	va_start(ap, fmt);
248	(void)vfprintf(stderr, fmt, ap);
249	va_end(ap);
250	if (*fmt) {
251		fmt += strlen(fmt);
252		if (fmt[-1] != '\n')
253			(void)fputc('\n', stderr);
254	}
255}
256
257/*
258 * Copy arg vector into a new buffer, concatenating arguments with spaces.
259 */
260char *
261copy_argv(register char **argv)
262{
263	register char **p;
264	register u_int len = 0;
265	char *buf;
266	char *src, *dst;
267
268	p = argv;
269	if (*p == 0)
270		return 0;
271
272	while (*p)
273		len += strlen(*p++) + 1;
274
275	buf = (char *)malloc(len);
276	if (buf == NULL)
277		error("copy_argv: malloc");
278
279	p = argv;
280	dst = buf;
281	while ((src = *p++) != NULL) {
282		while ((*dst++ = *src++) != '\0')
283			;
284		dst[-1] = ' ';
285	}
286	dst[-1] = '\0';
287
288	return buf;
289}
290
291char *
292read_infile(char *fname)
293{
294	register int fd, cc;
295	register char *cp;
296	struct stat buf;
297
298	fd = open(fname, O_RDONLY);
299	if (fd < 0)
300		error("can't open %s: %s", fname, pcap_strerror(errno));
301
302	if (fstat(fd, &buf) < 0)
303		error("can't stat %s: %s", fname, pcap_strerror(errno));
304
305	cp = malloc((u_int)buf.st_size + 1);
306	cc = read(fd, cp, (int)buf.st_size);
307	if (cc < 0)
308		error("read %s: %s", fname, pcap_strerror(errno));
309	if (cc != buf.st_size)
310		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
311	cp[(int)buf.st_size] = '\0';
312
313	return (cp);
314}
315
316void
317safeputs(const char *s)
318{
319	while (*s) {
320		safeputchar(*s);
321		s++;
322	}
323}
324
325void
326safeputchar(int c)
327{
328	unsigned char ch;
329
330	ch = (unsigned char)(c & 0xff);
331	if (c < 0x80 && isprint(c))
332		printf("%c", c & 0xff);
333	else
334		printf("\\%03o", c & 0xff);
335}
336