Fixed bug in dissect_ndr_pointer(). Top level Unique and Full pointers are
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.54 2001/11/09 07:44:48 guy 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 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
207     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
208     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
209     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
210     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
211     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
212     0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
213     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
214     0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
215     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
216     0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
217     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
218     0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
219     0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
220     0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
221     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
222     0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
223     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
224     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
225     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
226     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
227     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
228     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
229     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
230     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
231     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
232     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
233     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
234     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
235     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
236     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
237     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
238     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
239 };
240
241 void
242 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
243 {
244         guint   i;
245         guint8  *bufptr;
246
247         bufptr = buf;
248
249         for (i = 0; i < bytes; i++, bufptr++) {
250                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
251         }
252 }
253
254 guint8
255 ASCII_to_EBCDIC1(guint8 c)
256 {
257         return ASCII_translate_EBCDIC[c];
258 }
259
260 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
261     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
262     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
263     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
264     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
265     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
266     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
267     0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
268     0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
269     0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
270     0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
271     0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
272     0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
273     0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
274     0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
275     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
276     0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
277     0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
278     0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
279     0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
280     0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
281     0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
282     0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
283     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
284     0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
285     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
286     0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
287     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,                                             
288     0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
289     0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
290     0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
291     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,                 
292     0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
293 };
294
295 void
296 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
297 {
298         guint   i;
299         guint8  *bufptr;
300
301         bufptr = buf;
302
303         for (i = 0; i < bytes; i++, bufptr++) {
304                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
305         }
306 }
307
308 guint8
309 EBCDIC_to_ASCII1(guint8 c)
310 {
311         return EBCDIC_translate_ASCII[c];
312 }
313
314 /* Compute the difference between two seconds/microseconds time stamps. */
315 void
316 compute_timestamp_diff(gint *diffsec, gint *diffusec,
317         guint32 sec1, guint32 usec1, guint32 sec2, guint32 usec2)
318 {
319   if (sec1 == sec2) {
320     /* The seconds part of the first time is the same as the seconds
321        part of the second time, so if the microseconds part of the first
322        time is less than the microseconds part of the second time, the
323        first time is before the second time.  The microseconds part of
324        the delta should just be the difference between the microseconds
325        part of the first time and the microseconds part of the second
326        time; don't adjust the seconds part of the delta, as it's OK if
327        the microseconds part is negative. */
328
329     *diffsec = sec1 - sec2;
330     *diffusec = usec1 - usec2;
331   } else if (sec1 <= sec2) {
332     /* The seconds part of the first time is less than the seconds part
333        of the second time, so the first time is before the second time.
334
335        Both the "seconds" and "microseconds" value of the delta
336        should have the same sign, so if the difference between the
337        microseconds values would be *positive*, subtract 1,000,000
338        from it, and add one to the seconds value. */
339     *diffsec = sec1 - sec2;
340     if (usec2 >= usec1) {
341       *diffusec = usec1 - usec2;
342     } else {
343       *diffusec = (usec1 - 1000000) - usec2;
344       (*diffsec)++;
345     }
346   } else {
347     /* Oh, good, we're not caught in a chronosynclastic infindibulum. */
348     *diffsec = sec1 - sec2;
349     if (usec2 <= usec1) {
350       *diffusec = usec1 - usec2;
351     } else {
352       *diffusec = (usec1 + 1000000) - usec2;
353       (*diffsec)--;
354     }
355   }
356 }