xref: /openbsd-src/usr.sbin/tcpdump/util.c (revision 8445c53715e7030056b779e8ab40efb7820981f2)
1 /*	$OpenBSD: util.c,v 1.12 2001/09/03 13:25:53 jakob Exp $	*/
2 
3 /*
4  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that: (1) source code distributions
9  * retain the above copyright notice and this paragraph in its entirety, (2)
10  * distributions including binary code include the above copyright notice and
11  * this paragraph in its entirety in the documentation or other materials
12  * provided with the distribution, and (3) all advertising materials mentioning
13  * features or use of this software display the following acknowledgement:
14  * ``This product includes software developed by the University of California,
15  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16  * the University nor the names of its contributors may be used to endorse
17  * or promote products derived from this software without specific prior
18  * written permission.
19  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22  */
23 
24 #ifndef lint
25 static const char rcsid[] =
26     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/util.c,v 1.12 2001/09/03 13:25:53 jakob Exp $ (LBL)";
27 #endif
28 
29 #include <sys/types.h>
30 #include <sys/time.h>
31 #include <sys/file.h>
32 #include <sys/stat.h>
33 
34 #include <ctype.h>
35 #include <errno.h>
36 #ifdef HAVE_FCNTL_H
37 #include <fcntl.h>
38 #endif
39 #include <pcap.h>
40 #include <stdio.h>
41 #ifdef __STDC__
42 #include <stdarg.h>
43 #else
44 #include <varargs.h>
45 #endif
46 #include <stdlib.h>
47 #include <string.h>
48 #ifdef TIME_WITH_SYS_TIME
49 #include <time.h>
50 #endif
51 #include <unistd.h>
52 
53 #include "interface.h"
54 
55 /*
56  * Print out a filename (or other ascii string).
57  * If ep is NULL, assume no truncation check is needed.
58  * Return true if truncated.
59  */
60 int
61 fn_print(register const u_char *s, register const u_char *ep)
62 {
63 	register int ret;
64 	register u_char c;
65 
66 	ret = 1;			/* assume truncated */
67 	while (ep == NULL || s < ep) {
68 		c = *s++;
69 		if (c == '\0') {
70 			ret = 0;
71 			break;
72 		}
73 		if (!isascii(c)) {
74 			c = toascii(c);
75 			putchar('M');
76 			putchar('-');
77 		}
78 		if (!isprint(c)) {
79 			c ^= 0x40;	/* DEL to ?, others to alpha */
80 			putchar('^');
81 		}
82 		putchar(c);
83 	}
84 	return(ret);
85 }
86 
87 /*
88  * Print out a counted filename (or other ascii string).
89  * If ep is NULL, assume no truncation check is needed.
90  * Return true if truncated.
91  */
92 int
93 fn_printn(register const u_char *s, register u_int n,
94 	  register const u_char *ep)
95 {
96 	register int ret;
97 	register u_char c;
98 
99 	ret = 1;			/* assume truncated */
100 	while (ep == NULL || s < ep) {
101 		if (n-- <= 0) {
102 			ret = 0;
103 			break;
104 		}
105 		c = *s++;
106 		if (!isascii(c)) {
107 			c = toascii(c);
108 			putchar('M');
109 			putchar('-');
110 		}
111 		if (!isprint(c)) {
112 			c ^= 0x40;	/* DEL to ?, others to alpha */
113 			putchar('^');
114 		}
115 		putchar(c);
116 	}
117 	return(ret);
118 }
119 
120 /*
121  * Print the timestamp
122  */
123 void
124 ts_print(register const struct timeval *tvp)
125 {
126 	register int s;
127 #define TSBUFLEN 32
128 	static char buf[TSBUFLEN];
129 	time_t t;
130 
131 	switch(tflag){
132 	case 0:
133 		break;
134 	case -1:
135 		/* Unix timeval style */
136 		(void)printf("%u.%06u ",
137 		(u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
138 		break;
139 	case -2:
140 		t=tvp->tv_sec;
141 		strftime(buf, TSBUFLEN, "%b %d %T", localtime(&t));
142 		printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec);
143 		break;
144 	default:
145 		/* Default */
146 		s = (tvp->tv_sec + thiszone) % 86400;
147 		(void)printf("%02d:%02d:%02d.%06u ",
148 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
149 		break;
150 	}
151 }
152 
153 /*
154  * Print a relative number of seconds (e.g. hold time, prune timer)
155  * in the form 5m1s.  This does no truncation, so 32230861 seconds
156  * is represented as 1y1w1d1h1m1s.
157  */
158 void
159 relts_print(int secs)
160 {
161 	static char *lengths[] = {"y", "w", "d", "h", "m", "s"};
162 	static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
163 	char **l = lengths;
164 	int *s = seconds;
165 
166 	if (secs <= 0) {
167 		(void)printf("0s");
168 		return;
169 	}
170 	while (secs > 0) {
171 		if (secs >= *s) {
172 			(void)printf("%d%s", secs / *s, *l);
173 			secs -= (secs / *s) * *s;
174 		}
175 		s++;
176 		l++;
177 	}
178 }
179 
180 /*
181  * Convert a token value to a string; use "fmt" if not found.
182  */
183 const char *
184 tok2str(register const struct tok *lp, register const char *fmt,
185 	register int v)
186 {
187 	static char buf[128];
188 
189 	while (lp->s != NULL) {
190 		if (lp->v == v)
191 			return (lp->s);
192 		++lp;
193 	}
194 	if (fmt == NULL)
195 		fmt = "#%d";
196 	(void)snprintf(buf, sizeof(buf), fmt, v);
197 	return (buf);
198 }
199 
200 
201 /* VARARGS */
202 __dead void
203 #ifdef __STDC__
204 error(const char *fmt, ...)
205 #else
206 error(fmt, va_alist)
207 	const char *fmt;
208 	va_dcl
209 #endif
210 {
211 	va_list ap;
212 
213 	(void)fprintf(stderr, "%s: ", program_name);
214 #ifdef __STDC__
215 	va_start(ap, fmt);
216 #else
217 	va_start(ap);
218 #endif
219 	(void)vfprintf(stderr, fmt, ap);
220 	va_end(ap);
221 	if (*fmt) {
222 		fmt += strlen(fmt);
223 		if (fmt[-1] != '\n')
224 			(void)fputc('\n', stderr);
225 	}
226 	exit(1);
227 	/* NOTREACHED */
228 }
229 
230 /* VARARGS */
231 void
232 #ifdef __STDC__
233 warning(const char *fmt, ...)
234 #else
235 warning(fmt, va_alist)
236 	const char *fmt;
237 	va_dcl
238 #endif
239 {
240 	va_list ap;
241 
242 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
243 #ifdef __STDC__
244 	va_start(ap, fmt);
245 #else
246 	va_start(ap);
247 #endif
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  */
260 char *
261 copy_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 
291 char *
292 read_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 
316 void
317 safeputs(const char *s)
318 {
319 	while (*s) {
320 		safeputchar(*s);
321 		s++;
322 	}
323 }
324 
325 void
326 safeputchar(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