add the 'y' and 'Y' options to ps, and add the 'iac' keyword. The 'y'
[dragonfly.git] / contrib / tcpdump-3.8.3 / util.c
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
23 static const char rcsid[] _U_ =
24     "@(#) $Header: /tcpdump/master/tcpdump/util.c,v 1.87.2.3 2003/12/29 22:42:23 hannes Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <tcpdump-stdinc.h>
32
33 #include <sys/stat.h>
34
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
45 #include "interface.h"
46
47 /*
48  * Print out a filename (or other ascii string).
49  * If ep is NULL, assume no truncation check is needed.
50  * Return true if truncated.
51  */
52 int
53 fn_print(register const u_char *s, register const u_char *ep)
54 {
55         register int ret;
56         register u_char c;
57
58         ret = 1;                        /* assume truncated */
59         while (ep == NULL || s < ep) {
60                 c = *s++;
61                 if (c == '\0') {
62                         ret = 0;
63                         break;
64                 }
65                 if (!isascii(c)) {
66                         c = toascii(c);
67                         putchar('M');
68                         putchar('-');
69                 }
70                 if (!isprint(c)) {
71                         c ^= 0x40;      /* DEL to ?, others to alpha */
72                         putchar('^');
73                 }
74                 putchar(c);
75         }
76         return(ret);
77 }
78
79 /*
80  * Print out a counted filename (or other ascii string).
81  * If ep is NULL, assume no truncation check is needed.
82  * Return true if truncated.
83  */
84 int
85 fn_printn(register const u_char *s, register u_int n,
86           register const u_char *ep)
87 {
88         register u_char c;
89
90         while (n > 0 && (ep == NULL || s < ep)) {
91                 n--;
92                 c = *s++;
93                 if (!isascii(c)) {
94                         c = toascii(c);
95                         putchar('M');
96                         putchar('-');
97                 }
98                 if (!isprint(c)) {
99                         c ^= 0x40;      /* DEL to ?, others to alpha */
100                         putchar('^');
101                 }
102                 putchar(c);
103         }
104         return (n == 0) ? 0 : 1;
105 }
106
107 /*
108  * Print the timestamp
109  */
110 void
111 ts_print(register const struct timeval *tvp)
112 {
113         register int s;
114         struct tm *tm;
115         time_t Time;
116         static unsigned b_sec;
117         static unsigned b_usec;
118
119         switch(tflag) {
120         case 1: /* Default */
121                 s = (tvp->tv_sec + thiszone) % 86400;
122                 (void)printf("%02d:%02d:%02d.%06u ",
123                              s / 3600, (s % 3600) / 60, s % 60,
124                              (unsigned)tvp->tv_usec);
125                 break;
126         case -1: /* Unix timeval style */
127                 (void)printf("%u.%06u ",
128                              (unsigned)tvp->tv_sec,
129                              (unsigned)tvp->tv_usec);
130                 break;
131         case -2:
132                 if (b_sec == 0) {
133                         printf("000000 ");
134                 } else {
135                         int d_usec = tvp->tv_usec - b_usec;
136                         int d_sec = tvp->tv_sec - b_sec;
137
138                         while (d_usec < 0) {
139                                 d_usec += 1000000;
140                                 d_sec--;
141                         }
142                         if (d_sec)
143                                 printf("%d. ", d_sec);
144                         printf("%06d ", d_usec);
145                 }
146                 b_sec = tvp->tv_sec;
147                 b_usec = tvp->tv_usec;
148                 break;
149         case -3: /* Default + Date*/
150                 s = (tvp->tv_sec + thiszone) % 86400;
151                 Time = (tvp->tv_sec + thiszone) - s;
152                 tm = gmtime (&Time);
153                 if (!tm)
154                         printf("Date fail  ");
155                 else
156                         printf("%04d-%02d-%02d ",
157                                    tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday);
158                 printf("%02d:%02d:%02d.%06u ",
159                            s / 3600, (s % 3600) / 60, s % 60, (unsigned)tvp->tv_usec);
160                 break;
161         }
162 }
163
164 /*
165  * Print a relative number of seconds (e.g. hold time, prune timer)
166  * in the form 5m1s.  This does no truncation, so 32230861 seconds
167  * is represented as 1y1w1d1h1m1s.
168  */
169 void
170 relts_print(int secs)
171 {
172         static const char *lengths[] = {"y", "w", "d", "h", "m", "s"};
173         static const int seconds[] = {31536000, 604800, 86400, 3600, 60, 1};
174         const char **l = lengths;
175         const int *s = seconds;
176
177         if (secs == 0) {
178                 (void)printf("0s");
179                 return;
180         }
181         if (secs < 0) {
182                 (void)printf("-");
183                 secs = -secs;
184         }
185         while (secs > 0) {
186                 if (secs >= *s) {
187                         (void)printf("%d%s", secs / *s, *l);
188                         secs -= (secs / *s) * *s;
189                 }
190                 s++;
191                 l++;
192         }
193 }
194
195 /*
196  *  this is a generic routine for printing unknown data;
197  *  we pass on the linefeed plus indentation string to
198  *  get a proper output - returns 0 on error
199  */
200
201 int
202 print_unknown_data(const u_char *cp,const char *ident,int len)
203 {
204         hex_print(ident,cp,len);
205         return(1); /* everything is ok */
206 }
207
208 /*
209  * Convert a token value to a string; use "fmt" if not found.
210  */
211 const char *
212 tok2str(register const struct tok *lp, register const char *fmt,
213         register int v)
214 {
215         static char buf[128];
216
217         while (lp->s != NULL) {
218                 if (lp->v == v)
219                         return (lp->s);
220                 ++lp;
221         }
222         if (fmt == NULL)
223                 fmt = "#%d";
224         (void)snprintf(buf, sizeof(buf), fmt, v);
225         return (buf);
226 }
227
228 /*
229  * Convert a bit token value to a string; use "fmt" if not found.
230  * this is useful for parsing bitfields, the output strings are comma seperated
231  */
232 char *
233 bittok2str(register const struct tok *lp, register const char *fmt,
234         register int v)
235 {
236         static char buf[256]; /* our stringbuffer */
237         int buflen=0;
238         register int rotbit; /* this is the bit we rotate through all bitpositions */
239         register int tokval;
240
241         while (lp->s != NULL) {
242             tokval=lp->v;   /* load our first value */
243             rotbit=1;
244             while (rotbit != 0) {
245                 /*
246                  * lets AND the rotating bit with our token value
247                  * and see if we have got a match
248                  */
249                 if (tokval == (v&rotbit)) {
250                     /* ok we have found something */
251                     buflen+=snprintf(buf+buflen, sizeof(buf)-buflen, "%s, ",lp->s);
252                     break;
253                 }
254                 rotbit=rotbit<<1; /* no match - lets shift and try again */
255             }
256             lp++;
257         }
258
259         if (buflen != 0) { /* did we find anything */
260             /* yep, set the the trailing zero 2 bytes before to eliminate the last comma & whitespace */
261             buf[buflen-2] = '\0';
262             return (buf);
263         }
264         else {
265             /* bummer - lets print the "unknown" message as advised in the fmt string if we got one */
266             if (fmt == NULL)
267                 fmt = "#%d";
268             (void)snprintf(buf, sizeof(buf), fmt, v);
269             return (buf);
270         }
271 }
272
273 /*
274  * Convert a value to a string using an array; the macro
275  * tok2strary() in <interface.h> is the public interface to
276  * this function and ensures that the second argument is
277  * correct for bounds-checking.
278  */
279 const char *
280 tok2strary_internal(register const char **lp, int n, register const char *fmt,
281         register int v)
282 {
283         static char buf[128];
284
285         if (v >= 0 && v < n && lp[v] != NULL)
286                 return lp[v];
287         if (fmt == NULL)
288                 fmt = "#%d";
289         (void)snprintf(buf, sizeof(buf), fmt, v);
290         return (buf);
291 }
292
293 /*
294  * Convert a 32-bit netmask to prefixlen if possible
295  * the function returns the prefix-len; if plen == -1
296  * then conversion was not possible;
297  */
298
299 int
300 mask2plen (u_int32_t mask)
301 {
302         u_int32_t bitmasks[33] = {
303                 0x00000000,
304                 0x80000000, 0xc0000000, 0xe0000000, 0xf0000000,
305                 0xf8000000, 0xfc000000, 0xfe000000, 0xff000000,
306                 0xff800000, 0xffc00000, 0xffe00000, 0xfff00000,
307                 0xfff80000, 0xfffc0000, 0xfffe0000, 0xffff0000,
308                 0xffff8000, 0xffffc000, 0xffffe000, 0xfffff000,
309                 0xfffff800, 0xfffffc00, 0xfffffe00, 0xffffff00,
310                 0xffffff80, 0xffffffc0, 0xffffffe0, 0xfffffff0,
311                 0xfffffff8, 0xfffffffc, 0xfffffffe, 0xffffffff
312         };
313         int prefix_len = 32;
314
315         /* let's see if we can transform the mask into a prefixlen */
316         while (prefix_len >= 0) {
317                 if (bitmasks[prefix_len] == mask)
318                         break;
319                 prefix_len--;
320         }
321         return (prefix_len);
322 }
323
324 /* VARARGS */
325 void
326 error(const char *fmt, ...)
327 {
328         va_list ap;
329
330         (void)fprintf(stderr, "%s: ", program_name);
331         va_start(ap, fmt);
332         (void)vfprintf(stderr, fmt, ap);
333         va_end(ap);
334         if (*fmt) {
335                 fmt += strlen(fmt);
336                 if (fmt[-1] != '\n')
337                         (void)fputc('\n', stderr);
338         }
339         exit(1);
340         /* NOTREACHED */
341 }
342
343 /* VARARGS */
344 void
345 warning(const char *fmt, ...)
346 {
347         va_list ap;
348
349         (void)fprintf(stderr, "%s: WARNING: ", program_name);
350         va_start(ap, fmt);
351         (void)vfprintf(stderr, fmt, ap);
352         va_end(ap);
353         if (*fmt) {
354                 fmt += strlen(fmt);
355                 if (fmt[-1] != '\n')
356                         (void)fputc('\n', stderr);
357         }
358 }
359
360 /*
361  * Copy arg vector into a new buffer, concatenating arguments with spaces.
362  */
363 char *
364 copy_argv(register char **argv)
365 {
366         register char **p;
367         register u_int len = 0;
368         char *buf;
369         char *src, *dst;
370
371         p = argv;
372         if (*p == 0)
373                 return 0;
374
375         while (*p)
376                 len += strlen(*p++) + 1;
377
378         buf = (char *)malloc(len);
379         if (buf == NULL)
380                 error("copy_argv: malloc");
381
382         p = argv;
383         dst = buf;
384         while ((src = *p++) != NULL) {
385                 while ((*dst++ = *src++) != '\0')
386                         ;
387                 dst[-1] = ' ';
388         }
389         dst[-1] = '\0';
390
391         return buf;
392 }
393
394 /*
395  * On Windows, we need to open the file in binary mode, so that
396  * we get all the bytes specified by the size we get from "fstat()".
397  * On UNIX, that's not necessary.  O_BINARY is defined on Windows;
398  * we define it as 0 if it's not defined, so it does nothing.
399  */
400 #ifndef O_BINARY
401 #define O_BINARY        0
402 #endif
403
404 char *
405 read_infile(char *fname)
406 {
407         register int i, fd, cc;
408         register char *cp;
409         struct stat buf;
410
411         fd = open(fname, O_RDONLY|O_BINARY);
412         if (fd < 0)
413                 error("can't open %s: %s", fname, pcap_strerror(errno));
414
415         if (fstat(fd, &buf) < 0)
416                 error("can't stat %s: %s", fname, pcap_strerror(errno));
417
418         cp = malloc((u_int)buf.st_size + 1);
419         if (cp == NULL)
420                 error("malloc(%d) for %s: %s", (u_int)buf.st_size + 1,
421                         fname, pcap_strerror(errno));
422         cc = read(fd, cp, (u_int)buf.st_size);
423         if (cc < 0)
424                 error("read %s: %s", fname, pcap_strerror(errno));
425         if (cc != buf.st_size)
426                 error("short read %s (%d != %d)", fname, cc, (int)buf.st_size);
427
428         close(fd);
429         /* replace "# comment" with spaces */
430         for (i = 0; i < cc; i++) {
431                 if (cp[i] == '#')
432                         while (i < cc && cp[i] != '\n')
433                                 cp[i++] = ' ';
434         }
435         cp[cc] = '\0';
436         return (cp);
437 }
438
439 void
440 safeputs(const char *s)
441 {
442         while (*s) {
443                 safeputchar(*s);
444                 s++;
445         }
446 }
447
448 void
449 safeputchar(int c)
450 {
451         unsigned char ch;
452
453         ch = (unsigned char)(c & 0xff);
454         if (ch < 0x80 && isprint(ch))
455                 printf("%c", ch);
456         else
457                 printf("\\%03o", ch);
458 }