util.c revision 111726
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.72.2.2 2002/07/16 04:03:54 guy 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 const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
182	static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
183	const char **l = lengths;
184	const int *s = seconds;
185
186	if (secs == 0) {
187		(void)printf("0s");
188		return;
189	}
190	if (secs < 0) {
191		(void)printf("-");
192		secs = -secs;
193	}
194	while (secs > 0) {
195		if (secs >= *s) {
196			(void)printf("%d%s", secs / *s, *l);
197			secs -= (secs / *s) * *s;
198		}
199		s++;
200		l++;
201	}
202}
203
204/*
205 * Convert a token value to a string; use "fmt" if not found.
206 */
207const char *
208tok2str(register const struct tok *lp, register const char *fmt,
209	register int v)
210{
211	static char buf[128];
212
213	while (lp->s != NULL) {
214		if (lp->v == v)
215			return (lp->s);
216		++lp;
217	}
218	if (fmt == NULL)
219		fmt = "#%d";
220	(void)snprintf(buf, sizeof(buf), fmt, v);
221	return (buf);
222}
223
224/*
225 * Convert a value to a string using an array; the macro
226 * tok2strary() in <interface.h> is the public interface to
227 * this function and ensures that the second argument is
228 * correct for bounds-checking.
229 */
230const char *
231tok2strary_internal(register const char **lp, int n, register const char *fmt,
232	register int v)
233{
234	static char buf[128];
235
236	if (v >= 0 && v < n && lp[v] != NULL)
237		return lp[v];
238	if (fmt == NULL)
239		fmt = "#%d";
240	(void)snprintf(buf, sizeof(buf), fmt, v);
241	return (buf);
242}
243
244/* VARARGS */
245void
246error(const char *fmt, ...)
247{
248	va_list ap;
249
250	(void)fprintf(stderr, "%s: ", program_name);
251	va_start(ap, fmt);
252	(void)vfprintf(stderr, fmt, ap);
253	va_end(ap);
254	if (*fmt) {
255		fmt += strlen(fmt);
256		if (fmt[-1] != '\n')
257			(void)fputc('\n', stderr);
258	}
259	exit(1);
260	/* NOTREACHED */
261}
262
263/* VARARGS */
264void
265warning(const char *fmt, ...)
266{
267	va_list ap;
268
269	(void)fprintf(stderr, "%s: WARNING: ", program_name);
270	va_start(ap, fmt);
271	(void)vfprintf(stderr, fmt, ap);
272	va_end(ap);
273	if (*fmt) {
274		fmt += strlen(fmt);
275		if (fmt[-1] != '\n')
276			(void)fputc('\n', stderr);
277	}
278}
279
280/*
281 * Copy arg vector into a new buffer, concatenating arguments with spaces.
282 */
283char *
284copy_argv(register char **argv)
285{
286	register char **p;
287	register u_int len = 0;
288	char *buf;
289	char *src, *dst;
290
291	p = argv;
292	if (*p == 0)
293		return 0;
294
295	while (*p)
296		len += strlen(*p++) + 1;
297
298	buf = (char *)malloc(len);
299	if (buf == NULL)
300		error("copy_argv: malloc");
301
302	p = argv;
303	dst = buf;
304	while ((src = *p++) != NULL) {
305		while ((*dst++ = *src++) != '\0')
306			;
307		dst[-1] = ' ';
308	}
309	dst[-1] = '\0';
310
311	return buf;
312}
313
314char *
315read_infile(char *fname)
316{
317	register int fd, cc;
318	register char *cp;
319	struct stat buf;
320
321	fd = open(fname, O_RDONLY);
322	if (fd < 0)
323		error("can't open %s: %s", fname, pcap_strerror(errno));
324
325	if (fstat(fd, &buf) < 0)
326		error("can't stat %s: %s", fname, pcap_strerror(errno));
327
328	cp = malloc((u_int)buf.st_size + 1);
329	if (cp == NULL)
330		error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
331			fname, pcap_strerror(errno));
332	cc = read(fd, cp, (u_int)buf.st_size);
333	if (cc < 0)
334		error("read %s: %s", fname, pcap_strerror(errno));
335	if (cc != buf.st_size)
336		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
337	cp[(int)buf.st_size] = '\0';
338
339	return (cp);
340}
341
342void
343safeputs(const char *s)
344{
345	while (*s) {
346		safeputchar(*s);
347		s++;
348	}
349}
350
351void
352safeputchar(int c)
353{
354	unsigned char ch;
355
356	ch = (unsigned char)(c & 0xff);
357	if (ch < 0x80 && isprint(ch))
358		printf("%c", ch);
359	else
360		printf("\\%03o", ch);
361}
362