"uint" is defined on all platforms; use "guint" instead.
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.55 2002/04/08 20:23:55 gram Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  * 
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  * 
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <glib.h>
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdio.h>
34 #include <errno.h>
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #ifdef HAVE_SYS_TYPES_H
41 #include <sys/types.h>
42 #endif
43
44 #ifdef HAVE_SYS_STAT_H
45 #include <sys/stat.h>
46 #endif
47
48 #ifdef NEED_SNPRINTF_H
49 # include "snprintf.h"
50 #endif
51
52 #ifdef NEED_MKSTEMP
53 #include "mkstemp.h"
54 #endif
55
56 #ifdef HAVE_IO_H
57 #include <io.h>
58 typedef int mode_t;     /* for win32 */
59 #endif
60
61 #include "util.h"
62
63 /*
64  * Collect command-line arguments as a string consisting of the arguments,
65  * separated by spaces.
66  */
67 char *
68 get_args_as_string(int argc, char **argv, int optind)
69 {
70         int len;
71         int i;
72         char *argstring;
73
74         /*
75          * Find out how long the string will be.
76          */
77         len = 0;
78         for (i = optind; i < argc; i++) {
79                 len += strlen(argv[i]);
80                 len++;  /* space, or '\0' if this is the last argument */
81         }
82
83         /*
84          * Allocate the buffer for the string.
85          */
86         argstring = g_malloc(len);
87
88         /*
89          * Now construct the string.
90          */
91         strcpy(argstring, "");
92         i = optind;
93         for (;;) {
94                 strcat(argstring, argv[i]);
95                 i++;
96                 if (i == argc)
97                         break;
98                 strcat(argstring, " ");
99         }
100         return argstring;
101 }
102
103 static char *
104 setup_tmpdir(char *dir)
105 {
106         int len = strlen(dir);
107         char *newdir;
108
109         /* Append slash if necessary */
110         if (dir[len - 1] == '/') {
111                 newdir = dir;
112         }
113         else {
114                 newdir = g_malloc(len + 2);
115                 strcpy(newdir, dir);
116                 strcat(newdir, "/");
117         }
118         return newdir;
119 }
120
121 static int
122 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
123 {
124         static const char suffix[] = "XXXXXXXXXX";
125         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
126         mode_t old_umask;
127         int tmp_fd;
128
129         if (namebuflen < namelen) {
130                 /* Stick in a truncated name, so that if this error is
131                    reported with the file name, you at least get
132                    something. */
133                 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
134                 errno = ENAMETOOLONG;
135                 return -1;
136         }
137         strcpy(namebuf, dir);
138         strcat(namebuf, pfx);
139         strcat(namebuf, suffix);
140
141         /* The Single UNIX Specification doesn't say that "mkstemp()"
142            creates the temporary file with mode rw-------, so we
143            won't assume that all UNIXes will do so; instead, we set
144            the umask to 0077 to take away all group and other
145            permissions, attempt to create the file, and then put
146            the umask back. */
147         old_umask = umask(0077);
148         tmp_fd = mkstemp(namebuf);
149         umask(old_umask);
150         return tmp_fd;
151 }
152
153 static char *tmpdir = NULL;
154 #ifdef WIN32
155 static char *temp = NULL;
156 #endif
157 static char *E_tmpdir;
158
159 #ifndef P_tmpdir
160 #define P_tmpdir "/var/tmp"
161 #endif
162
163 int
164 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
165 {
166         char *dir;
167         int fd;
168         static gboolean initialized;
169
170         if (!initialized) {
171                 if ((dir = getenv("TMPDIR")) != NULL)
172                         tmpdir = setup_tmpdir(dir);
173 #ifdef WIN32
174                 if ((dir = getenv("TEMP")) != NULL)
175                         temp = setup_tmpdir(dir);
176 #endif
177
178                 E_tmpdir = setup_tmpdir(P_tmpdir);
179                 initialized = TRUE;
180         }
181
182         if (tmpdir != NULL) {
183                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
184                 if (fd != -1)
185                         return fd;
186         }
187
188 #ifdef WIN32
189         if (temp != NULL) {
190                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
191                 if (fd != -1)
192                         return fd;
193         }
194 #endif
195
196         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
197         if (fd != -1)
198                 return fd;
199
200         return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
201 }
202
203 /* ASCII/EBCDIC conversion tables from
204  * http://www.room42.com/store/computer_center/code_tables.shtml
205  */
206 #if 0
207 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
208     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
209     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
210     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
211     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
212     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
213     0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
214     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
215     0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
216     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
217     0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
218     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
219     0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
220     0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
221     0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
222     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
223     0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
224     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
225     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
226     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
227     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
228     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
229     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
230     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
231     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
232     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
233     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
234     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
235     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
236     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
237     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
238     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
239     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
240 };
241
242 void
243 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
244 {
245         guint   i;
246         guint8  *bufptr;
247
248         bufptr = buf;
249
250         for (i = 0; i < bytes; i++, bufptr++) {
251                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
252         }
253 }
254
255 guint8
256 ASCII_to_EBCDIC1(guint8 c)
257 {
258         return ASCII_translate_EBCDIC[c];
259 }
260 #endif
261
262 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
263     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
264     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
265     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
266     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
267     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
268     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
269     0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
270     0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
271     0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
272     0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
273     0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
274     0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
275     0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
276     0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
277     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
278     0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
279     0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
280     0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
281     0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
282     0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
283     0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
284     0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
285     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
286     0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
287     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
288     0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
289     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,                                             
290     0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
291     0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
292     0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
293     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,                 
294     0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
295 };
296
297 void
298 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
299 {
300         guint   i;
301         guint8  *bufptr;
302
303         bufptr = buf;
304
305         for (i = 0; i < bytes; i++, bufptr++) {
306                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
307         }
308 }
309
310 guint8
311 EBCDIC_to_ASCII1(guint8 c)
312 {
313         return EBCDIC_translate_ASCII[c];
314 }
315
316 /* Compute the difference between two seconds/microseconds time stamps. */
317 void
318 compute_timestamp_diff(gint *diffsec, gint *diffusec,
319         guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
320 {
321   if (sec1 == sec2) {
322     /* The seconds part of the first time is the same as the seconds
323        part of the second time, so if the microseconds part of the first
324        time is less than the microseconds part of the second time, the
325        first time is before the second time.  The microseconds part of
326        the delta should just be the difference between the microseconds
327        part of the first time and the microseconds part of the second
328        time; don't adjust the seconds part of the delta, as it's OK if
329        the microseconds part is negative. */
330
331     *diffsec = sec1 - sec2;
332     *diffusec = usec1 - usec2;
333   } else if (sec1 <= sec2) {
334     /* The seconds part of the first time is less than the seconds part
335        of the second time, so the first time is before the second time.
336
337        Both the "seconds" and "microseconds" value of the delta
338        should have the same sign, so if the difference between the
339        microseconds values would be *positive*, subtract 1,000,000
340        from it, and add one to the seconds value. */
341     *diffsec = sec1 - sec2;
342     if (usec2 >= usec1) {
343       *diffusec = usec1 - usec2;
344     } else {
345       *diffusec = (usec1 - 1000000) - usec2;
346       (*diffsec)++;
347     }
348   } else {
349     /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
350     *diffsec = sec1 - sec2;
351     if (usec2 <= usec1) {
352       *diffusec = usec1 - usec2;
353     } else {
354       *diffusec = (usec1 + 1000000) - usec2;
355       (*diffsec)--;
356     }
357   }
358 }