xref: /openbsd-src/usr.sbin/tcpdump/util.c (revision a4afd6dad3fba28f80e70208181c06c482259988)
1 /*
2  * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996
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
23 static const char rcsid[] =
24     "@(#) $Header: /home/cvs/src/usr.sbin/tcpdump/util.c,v 1.5 1996/12/12 16:22:20 bitblt Exp $ (LBL)";
25 #endif
26 
27 #include <sys/types.h>
28 #include <sys/time.h>
29 #include <sys/file.h>
30 #include <sys/stat.h>
31 
32 #include <ctype.h>
33 #include <errno.h>
34 #ifdef HAVE_FCNTL_H
35 #include <fcntl.h>
36 #endif
37 #include <pcap.h>
38 #include <stdio.h>
39 #if __STDC__
40 #include <stdarg.h>
41 #else
42 #include <varargs.h>
43 #endif
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  */
58 int
59 fn_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  */
90 int
91 fn_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  */
121 void
122 ts_print(register const struct timeval *tvp)
123 {
124 	register int s;
125 
126 	if (tflag > 0) {
127 		/* Default */
128 		s = (tvp->tv_sec + thiszone) % 86400;
129 		(void)printf("%02d:%02d:%02d.%06u ",
130 		    s / 3600, (s % 3600) / 60, s % 60, (u_int32_t)tvp->tv_usec);
131 	} else if (tflag < 0) {
132 		/* Unix timeval style */
133 		(void)printf("%u.%06u ",
134 		    (u_int32_t)tvp->tv_sec, (u_int32_t)tvp->tv_usec);
135 	}
136 }
137 
138 /*
139  * Convert a token value to a string; use "fmt" if not found.
140  */
141 const char *
142 tok2str(register const struct tok *lp, register const char *fmt,
143 	register int v)
144 {
145 	static char buf[128];
146 
147 	while (lp->s != NULL) {
148 		if (lp->v == v)
149 			return (lp->s);
150 		++lp;
151 	}
152 	if (fmt == NULL)
153 		fmt = "#%d";
154 	(void)sprintf(buf, fmt, v);
155 	return (buf);
156 }
157 
158 
159 /* VARARGS */
160 __dead void
161 #if __STDC__
162 error(const char *fmt, ...)
163 #else
164 error(fmt, va_alist)
165 	const char *fmt;
166 	va_dcl
167 #endif
168 {
169 	va_list ap;
170 
171 	(void)fprintf(stderr, "%s: ", program_name);
172 #if __STDC__
173 	va_start(ap, fmt);
174 #else
175 	va_start(ap);
176 #endif
177 	(void)vfprintf(stderr, fmt, ap);
178 	va_end(ap);
179 	if (*fmt) {
180 		fmt += strlen(fmt);
181 		if (fmt[-1] != '\n')
182 			(void)fputc('\n', stderr);
183 	}
184 	exit(1);
185 	/* NOTREACHED */
186 }
187 
188 /* VARARGS */
189 void
190 #if __STDC__
191 warning(const char *fmt, ...)
192 #else
193 warning(fmt, va_alist)
194 	const char *fmt;
195 	va_dcl
196 #endif
197 {
198 	va_list ap;
199 
200 	(void)fprintf(stderr, "%s: WARNING: ", program_name);
201 #if __STDC__
202 	va_start(ap, fmt);
203 #else
204 	va_start(ap);
205 #endif
206 	(void)vfprintf(stderr, fmt, ap);
207 	va_end(ap);
208 	if (*fmt) {
209 		fmt += strlen(fmt);
210 		if (fmt[-1] != '\n')
211 			(void)fputc('\n', stderr);
212 	}
213 }
214 
215 /*
216  * Copy arg vector into a new buffer, concatenating arguments with spaces.
217  */
218 char *
219 copy_argv(register char **argv)
220 {
221 	register char **p;
222 	register u_int len = 0;
223 	char *buf;
224 	char *src, *dst;
225 
226 	p = argv;
227 	if (*p == 0)
228 		return 0;
229 
230 	while (*p)
231 		len += strlen(*p++) + 1;
232 
233 	buf = (char *)malloc(len);
234 	if (buf == NULL)
235 		error("copy_argv: malloc");
236 
237 	p = argv;
238 	dst = buf;
239 	while ((src = *p++) != NULL) {
240 		while ((*dst++ = *src++) != '\0')
241 			;
242 		dst[-1] = ' ';
243 	}
244 	dst[-1] = '\0';
245 
246 	return buf;
247 }
248 
249 /* A replacement for strdup() that cuts down on malloc() overhead */
250 char *
251 savestr(register const char *str)
252 {
253 	register u_int size;
254 	register char *p;
255 	static char *strptr = NULL;
256 	static u_int strsize = 0;
257 
258 	size = strlen(str) + 1;
259 	if (size > strsize) {
260 		strsize = 1024;
261 		if (strsize < size)
262 			strsize = size;
263 		strptr = (char *)malloc(strsize);
264 		if (strptr == NULL)
265 			error("savestr: malloc");
266 	}
267 	(void)strcpy(strptr, str);
268 	p = strptr;
269 	strptr += size;
270 	strsize -= size;
271 	return (p);
272 }
273 
274 char *
275 read_infile(char *fname)
276 {
277 	register int fd, cc;
278 	register char *cp;
279 	struct stat buf;
280 
281 	fd = open(fname, O_RDONLY);
282 	if (fd < 0)
283 		error("can't open %s: %s", fname, pcap_strerror(errno));
284 
285 	if (fstat(fd, &buf) < 0)
286 		error("can't stat %s: %s", fname, pcap_strerror(errno));
287 
288 	cp = malloc((u_int)buf.st_size + 1);
289 	cc = read(fd, cp, (int)buf.st_size);
290 	if (cc < 0)
291 		error("read %s: %s", fname, pcap_strerror(errno));
292 	if (cc != buf.st_size)
293 		error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
294 	cp[(int)buf.st_size] = '\0';
295 
296 	return (cp);
297 }
298 
299 /*
300  * Returns the difference between gmt and local time in seconds.
301  * Use gmtime() and localtime() to keep things simple.
302  */
303 int32_t
304 gmt2local(void)
305 {
306 	register int dt, dir;
307 	register struct tm *gmt, *loc;
308 	time_t t;
309 	struct tm sgmt;
310 
311 	t = time(NULL);
312 	gmt = &sgmt;
313 	*gmt = *gmtime(&t);
314 	loc = localtime(&t);
315 	dt = (loc->tm_hour - gmt->tm_hour) * 60 * 60 +
316 	    (loc->tm_min - gmt->tm_min) * 60;
317 
318 	/*
319 	 * If the year or julian day is different, we span 00:00 GMT
320 	 * and must add or subtract a day. Check the year first to
321 	 * avoid problems when the julian day wraps.
322 	 */
323 	dir = loc->tm_year - gmt->tm_year;
324 	if (dir == 0)
325 		dir = loc->tm_yday - gmt->tm_yday;
326 	dt += dir * 24 * 60 * 60;
327 
328 	return (dt);
329 }
330