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