A "character encoding" variable is now set per packet. The existence
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.23 1999/11/22 06:24:42 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 <gtk/gtk.h>
33
34 #include <stdarg.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <stdio.h>
38 #include <errno.h>
39
40 #ifdef HAVE_FCNTL_H
41 #include <fcntl.h>
42 #endif
43
44 #ifdef HAVE_UNISTD_H
45 #include <unistd.h>
46 #endif
47
48 #ifdef HAVE_SYS_TYPES_H
49 #include <sys/types.h>
50 #endif
51
52 #ifdef HAVE_SYS_STAT_H
53 #include <sys/stat.h>
54 #endif
55
56 #ifdef NEED_SNPRINTF_H
57 # ifdef HAVE_STDARG_H
58 #  include <stdarg.h>
59 # else
60 #  include <varargs.h>
61 # endif
62 # include "snprintf.h"
63 #endif
64
65 #include "util.h"
66
67 #include "image/icon-excl.xpm"
68 #include "image/icon-ethereal.xpm"
69
70 static void simple_dialog_cancel_cb(GtkWidget *, gpointer);
71
72 const gchar *bm_key = "button mask";
73
74 /* Simple dialog function - Displays a dialog box with the supplied message
75  * text.
76  * 
77  * Args:
78  * type       : One of ESD_TYPE_*.
79  * btn_mask   : The address of a gint.  The value passed in determines if
80  *              the 'Cancel' button is displayed.  The button pressed by the 
81  *              user is passed back.
82  * msg_format : Sprintf-style format of the text displayed in the dialog.
83  * ...        : Argument list for msg_format
84  *
85  */
86  
87 #define ESD_MAX_MSG_LEN 2048
88 void
89 simple_dialog(gint type, gint *btn_mask, gchar *msg_format, ...) {
90   GtkWidget   *win, *main_vb, *top_hb, *type_pm, *msg_label,
91               *bbox, *ok_btn, *cancel_btn;
92   GdkPixmap   *pixmap;
93   GdkBitmap   *mask;
94   GtkStyle    *style;
95   GdkColormap *cmap;
96   va_list      ap;
97   gchar        message[ESD_MAX_MSG_LEN];
98   gchar      **icon;
99
100   /* Main window */
101   win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
102   gtk_container_border_width(GTK_CONTAINER(win), 7);
103
104   switch (type) {
105   case ESD_TYPE_WARN :
106     gtk_window_set_title(GTK_WINDOW(win), "Ethereal: Warning");
107     icon = icon_excl_xpm;
108     break;
109   case ESD_TYPE_CRIT :
110     gtk_window_set_title(GTK_WINDOW(win), "Ethereal: Critical");
111     icon = icon_excl_xpm;
112     break;
113   case ESD_TYPE_INFO :
114   default :
115     icon = icon_ethereal_xpm;
116     gtk_window_set_title(GTK_WINDOW(win), "Ethereal: Information");
117     break;
118   }
119
120   gtk_object_set_data(GTK_OBJECT(win), bm_key, btn_mask);
121
122   /* Container for our rows */
123   main_vb = gtk_vbox_new(FALSE, 5);
124   gtk_container_border_width(GTK_CONTAINER(main_vb), 5);
125   gtk_container_add(GTK_CONTAINER(win), main_vb);
126   gtk_widget_show(main_vb);
127
128   /* Top row: Icon and message text */
129   top_hb = gtk_hbox_new(FALSE, 10);
130   gtk_container_add(GTK_CONTAINER(main_vb), top_hb);
131   gtk_widget_show(top_hb);
132   
133   style = gtk_widget_get_style(win);
134   cmap  = gdk_colormap_get_system();
135   pixmap = gdk_pixmap_colormap_create_from_xpm_d(NULL, cmap,  &mask,
136     &style->bg[GTK_STATE_NORMAL], icon);
137   type_pm = gtk_pixmap_new(pixmap, mask);
138   gtk_misc_set_alignment (GTK_MISC (type_pm), 0.5, 0.0);
139   gtk_container_add(GTK_CONTAINER(top_hb), type_pm);
140   gtk_widget_show(type_pm);
141
142   /* Load our vararg list into the message string */
143   va_start(ap, msg_format);
144   vsnprintf(message, ESD_MAX_MSG_LEN, msg_format, ap);
145
146   msg_label = gtk_label_new(message);
147   gtk_label_set_justify(GTK_LABEL(msg_label), GTK_JUSTIFY_FILL);
148   gtk_container_add(GTK_CONTAINER(top_hb), msg_label);
149   gtk_widget_show(msg_label);
150   
151   /* Button row */
152   bbox = gtk_hbutton_box_new();
153   gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
154   gtk_container_add(GTK_CONTAINER(main_vb), bbox);
155   gtk_widget_show(bbox);
156
157   ok_btn = gtk_button_new_with_label ("OK");
158   gtk_signal_connect_object(GTK_OBJECT(ok_btn), "clicked",
159     GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT (win)); 
160   gtk_container_add(GTK_CONTAINER(bbox), ok_btn);
161   GTK_WIDGET_SET_FLAGS(ok_btn, GTK_CAN_DEFAULT);
162   gtk_widget_grab_default(ok_btn);
163   gtk_widget_show(ok_btn);
164
165   if (btn_mask && *btn_mask == ESD_BTN_CANCEL) {
166     cancel_btn = gtk_button_new_with_label("Cancel");
167     gtk_signal_connect(GTK_OBJECT(cancel_btn), "clicked",
168       GTK_SIGNAL_FUNC(simple_dialog_cancel_cb), (gpointer) win);
169     gtk_container_add(GTK_CONTAINER(bbox), cancel_btn);
170     GTK_WIDGET_SET_FLAGS(cancel_btn, GTK_CAN_DEFAULT);
171     gtk_widget_show(cancel_btn);
172   }
173
174   if (btn_mask)
175     *btn_mask = ESD_BTN_OK;
176
177   gtk_widget_show(win);
178 }
179
180 static void
181 simple_dialog_cancel_cb(GtkWidget *w, gpointer win) {
182   gint *btn_mask = (gint *) gtk_object_get_data(win, bm_key);
183   
184   if (btn_mask)
185     *btn_mask = ESD_BTN_CANCEL;
186   gtk_widget_destroy(GTK_WIDGET(win));
187 }
188
189 static char *
190 setup_tmpdir(char *dir)
191 {
192         int len = strlen(dir);
193         char *newdir;
194
195         /* Append slash if necessary */
196         if (dir[len - 1] == '/') {
197                 newdir = dir;
198         }
199         else {
200                 newdir = g_malloc(len + 2);
201                 strcpy(newdir, dir);
202                 strcat(newdir, "/");
203         }
204         return newdir;
205 }
206
207 static int
208 try_tempfile(char *namebuf, int namebuflen, const char *dir, const char *pfx)
209 {
210         static const char suffix[] = "XXXXXXXXXX";
211         int namelen = strlen(dir) + strlen(pfx) + sizeof suffix;
212         mode_t old_umask;
213         int tmp_fd;
214
215         if (namebuflen < namelen) {
216                 /* Stick in a truncated name, so that if this error is
217                    reported with the file name, you at least get
218                    something. */
219                 snprintf(namebuf, namebuflen, "%s%s%s", dir, pfx, suffix);
220                 errno = ENAMETOOLONG;
221                 return -1;
222         }
223         strcpy(namebuf, dir);
224         strcat(namebuf, pfx);
225         strcat(namebuf, suffix);
226
227         /* The Single UNIX Specification doesn't say that "mkstemp()"
228            creates the temporary file with mode rw-------, so we
229            won't assume that all UNIXes will do so; instead, we set
230            the umask to 0077 to take away all group and other
231            permissions, attempt to create the file, and then put
232            the umask back. */
233         old_umask = umask(0077);
234         tmp_fd = mkstemp(namebuf);
235         umask(old_umask);
236         return tmp_fd;
237 }
238
239 static char *tmpdir = NULL;
240 #ifdef WIN32
241 static char *temp = NULL;
242 #endif
243 static char *E_tmpdir;
244
245 #ifndef P_tmpdir
246 #define P_tmpdir "/var/tmp"
247 #endif
248
249 int
250 create_tempfile(char *namebuf, int namebuflen, const char *pfx)
251 {
252         char *dir;
253         int fd;
254         static gboolean initialized;
255
256         if (!initialized) {
257                 if ((dir = getenv("TMPDIR")) != NULL)
258                         tmpdir = setup_tmpdir(dir);
259 #ifdef WIN32
260                 if ((dir = getenv("TEMP")) != NULL)
261                         temp = setup_tmpdir(dir);
262 #endif
263
264                 E_tmpdir = setup_tmpdir(P_tmpdir);
265                 initialized = TRUE;
266         }
267
268         if (tmpdir != NULL) {
269                 fd = try_tempfile(namebuf, namebuflen, tmpdir, pfx);
270                 if (fd != -1)
271                         return fd;
272         }
273
274 #ifdef WIN32
275         if (temp != NULL) {
276                 fd = try_tempfile(namebuf, namebuflen, temp, pfx);
277                 if (fd != -1)
278                         return fd;
279         }
280 #endif
281
282         fd = try_tempfile(namebuf, namebuflen, E_tmpdir, pfx);
283         if (fd != -1)
284                 return fd;
285
286         return try_tempfile(namebuf, namebuflen, "/tmp", pfx);
287 }
288
289 /* ASCII/EBCDIC conversion tables from
290  * http://www.room42.com/store/computer_center/code_tables.shtml
291  */
292 static guint8 ASCII_translate_EBCDIC [ 256 ] = {
293     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
294     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
295     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
296     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
297     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
298     0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
299     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
300     0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
301     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
302     0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
303     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
304     0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
305     0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
306     0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
307     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
308     0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 0x4B,
309     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
310     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
311     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
312     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
313     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
314     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
315     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
316     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
317     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
318     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
319     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
320     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
321     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
322     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
323     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
324     0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
325 };
326
327 void
328 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
329 {
330         guint   i;
331         guint8  *bufptr;
332
333         bufptr = buf;
334
335         for (i = 0; i < bytes; i++, bufptr++) {
336                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
337         }
338 }
339
340 guint8
341 ASCII_to_EBCDIC1(guint8 c)
342 {
343         return ASCII_translate_EBCDIC[c];
344 }
345
346 static guint8 EBCDIC_translate_ASCII [ 256 ] = {
347     0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
348     0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
349     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
350     0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
351     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
352     0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
353     0x2E, 0x2E, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
354     0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x2E, 0x3F,
355     0x20, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
356     0x2E, 0x2E, 0x2E, 0x3C, 0x28, 0x2B, 0x7C,
357     0x26, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
358     0x2E, 0x21, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
359     0x2D, 0x2F, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
360     0x2E, 0x7C, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
361     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
362     0x2E, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
363     0x2E, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
364     0x69, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
365     0x2E, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71,
366     0x72, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
367     0x2E, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
368     0x7A, 0x2E, 0x2E, 0x2E, 0x5B, 0x2E, 0x2E,
369     0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
370     0x2E, 0x2E, 0x2E, 0x2E, 0x5D, 0x2E, 0x2E,
371     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
372     0x49, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
373     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51,                                             
374     0x52, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
375     0x5C, 0x2E, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
376     0x5A, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E,
377     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,                 
378     0x39, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E, 0x2E
379 };
380
381 void
382 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
383 {
384         guint   i;
385         guint8  *bufptr;
386
387         bufptr = buf;
388
389         for (i = 0; i < bytes; i++, bufptr++) {
390                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
391         }
392 }
393
394 guint8
395 EBCDIC_to_ASCII1(guint8 c)
396 {
397         return EBCDIC_translate_ASCII[c];
398 }
399