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