xref: /openbsd-src/usr.sbin/tcpdump/util.c (revision 47911bd667ac77dc523b8a13ef40b012dbffa741)
1 /*	$OpenBSD: util.c,v 1.15 2002/02/19 19:39:40 millert 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.15 2002/02/19 19:39:40 millert 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 #include <stdarg.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #ifdef TIME_WITH_SYS_TIME
45 #include <time.h>
46 #endif
47 #include <unistd.h>
48 
49 #include "interface.h"
50 
51 /*
52  * Print out a filename (or other ascii string).
53  * If ep is NULL, assume no truncation check is needed.
54  * Return true if truncated.
55  */
56 int
57 fn_print(register const u_char *s, register const u_char *ep)
58 {
59 	register int ret;
60 	register u_char c;
61 
62 	ret = 1;			/* assume truncated */
63 	while (ep == NULL || s < ep) {
64 		c = *s++;
65 		if (c == '\0') {
66 			ret = 0;
67 			break;
68 		}
69 		if (!isascii(c)) {
70 			c = toascii(c);
71 			putchar('M');
72 			putchar('-');
73 		}
74 		if (!isprint(c)) {
75 			c ^= 0x40;	/* DEL to ?, others to alpha */
76 			putchar('^');
77 		}
78 		putchar(c);
79 	}
80 	return(ret);
81 }
82 
83 /*
84  * Print out a counted filename (or other ascii string).
85  * If ep is NULL, assume no truncation check is needed.
86  * Return true if truncated.
87  */
88 int
89 fn_printn(register const u_char *s, register u_int n,
90 	  register const u_char *ep)
91 {
92 	register int ret;
93 	register u_char c;
94 
95 	ret = 1;			/* assume truncated */
96 	while (ep == NULL || s < ep) {
97 		if (n-- <= 0) {
98 			ret = 0;
99 			break;
100 		}
101 		c = *s++;
102 		if (!isascii(c)) {
103 			c = toascii(c);
104 			putchar('M');
105 			putchar('-');
106 		}
107 		if (!isprint(c)) {
108 			c ^= 0x40;	/* DEL to ?, others to alpha */
109 			putchar('^');
110 		}
111 		putchar(c);
112 	}
113 	return(ret);
114 }
115 
116 /*
117  * Print the timestamp
118  */
119 void
120 ts_print(register const struct bpf_timeval *tvp)
121 {
122 	register int s;
123 #define TSBUFLEN 32
124 	static char buf[TSBUFLEN];
125 	time_t t;
126 
127 	switch(tflag){
128 	case 0:
129 		break;
130 	case -1:
131 		/* Unix timeval style */
132 		(void)printf("%u.%06u ",
133 		    (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
134 		break;
135 	case -2:
136 		t=tvp->tv_sec;
137 		strftime(buf, TSBUFLEN, "%b %d %T", localtime(&t));
138 		printf("%s.%06u ", buf, (u_int32_t)tvp->tv_usec);
139 		break;
140 	default:
141 		/* Default */
142 		s = (tvp->tv_sec + thiszone) % 86400;
143 		(void)printf("%02d:%02d:%02d.%06u ",
144 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
145 		break;
146 	}
147 }
148 
149 /*
150  * Print a relative number of seconds (e.g. hold time, prune timer)
151  * in the form 5m1s.  This does no truncation, so 32230861 seconds
152  * is represented as 1y1w1d1h1m1s.
153  */
154 void
155 relts_print(int secs)
156 {
157 	static char *lengths[] = {"y", "w", "d", "h", "m", "s"};
158 	static int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
159 	char **l = lengths;
160 	int *s = seconds;
161 
162 	if (secs <= 0) {
163 		(void)printf("0s");
164 		return;
165 	}
166 	while (secs > 0) {
167 		if (secs >= *s) {
168 			(void)printf("%d%s", secs / *s, *l);
169 			secs -= (secs / *s) * *s;
170 		}
171 		s++;
172 		l++;
173 	}
174 }
175 
176 /*
177  * Convert a token value to a string; use "fmt" if not found.
178  */
179 const char *
180 tok2str(register const struct tok *lp, register const char *fmt,
181 	register int v)
182 {
183 	static char buf[128];
184 
185 	while (lp->s != NULL) {
186 		if (lp->v == v)
187 			return (lp->s);
188 		++lp;
189 	}
190 	if (fmt == NULL)
191 		fmt = "#%d";
192 	(void)snprintf(buf, sizeof(buf), fmt, v);
193 	return (buf);
194 }
195 
196 
197 /* VARARGS */
198 __dead void
199 error(const char *fmt, ...)
200 {
201 	va_list ap;
202 
203 	(void)fprintf(stderr, "%s: ", program_name);
204 	va_start(ap, fmt);
205 	(void)vfprintf(stderr, fmt, ap);
206 	va_end(ap);
207 	if (*fmt) {
208 		fmt += strlen(fmt);
209 		if (fmt[-1] != '\n')
210 			(void)fputc('\n', stderr);
211 	}
212 	exit(1);
213 	/* NOTREACHED */
214 }
215 
216 /* VARARGS */
217 void
218 warning(const char *fmt, ...)
219 {
220 	va_list ap;
221 
222 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
223 	va_start(ap, fmt);
224 	(void)vfprintf(stderr, fmt, ap);
225 	va_end(ap);
226 	if (*fmt) {
227 		fmt += strlen(fmt);
228 		if (fmt[-1] != '\n')
229 			(void)fputc('\n', stderr);
230 	}
231 }
232 
233 /*
234  * Copy arg vector into a new buffer, concatenating arguments with spaces.
235  */
236 char *
237 copy_argv(register char **argv)
238 {
239 	register char **p;
240 	register u_int len = 0;
241 	char *buf;
242 	char *src, *dst;
243 
244 	p = argv;
245 	if (*p == 0)
246 		return 0;
247 
248 	while (*p)
249 		len += strlen(*p++) + 1;
250 
251 	buf = (char *)malloc(len);
252 	if (buf == NULL)
253 		error("copy_argv: malloc");
254 
255 	p = argv;
256 	dst = buf;
257 	while ((src = *p++) != NULL) {
258 		while ((*dst++ = *src++) != '\0')
259 			;
260 		dst[-1] = ' ';
261 	}
262 	dst[-1] = '\0';
263 
264 	return buf;
265 }
266 
267 char *
268 read_infile(char *fname)
269 {
270 	register int fd, cc;
271 	register char *cp;
272 	struct stat buf;
273 
274 	fd = open(fname, O_RDONLY);
275 	if (fd < 0)
276 		error("can't open %s: %s", fname, pcap_strerror(errno));
277 
278 	if (fstat(fd, &buf) < 0)
279 		error("can't stat %s: %s", fname, pcap_strerror(errno));
280 
281 	cp = malloc((u_int)buf.st_size + 1);
282 	cc = read(fd, cp, (int)buf.st_size);
283 	if (cc < 0)
284 		error("read %s: %s", fname, pcap_strerror(errno));
285 	if (cc != buf.st_size)
286 		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
287 	cp[(int)buf.st_size] = '\0';
288 
289 	return (cp);
290 }
291 
292 void
293 safeputs(const char *s)
294 {
295 	while (*s) {
296 		safeputchar(*s);
297 		s++;
298 	}
299 }
300 
301 void
302 safeputchar(int c)
303 {
304 	unsigned char ch;
305 
306 	ch = (unsigned char)(c & 0xff);
307 	if (c < 0x80 && isprint(c))
308 		printf("%c", c & 0xff);
309 	else
310 		printf("\\%03o", c & 0xff);
311 }
312