Add ASCII/EBCDIC conversion to TCP Follow window. Also add Close button
[obnox/wireshark/wip.git] / util.c
1 /* util.c
2  * Utility routines
3  *
4  * $Id: util.c,v 1.22 1999/10/19 04:11:15 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 void
293 ASCII_to_EBCDIC(guint8 *buf, guint bytes)
294 {
295         guint   i;
296         guint8  *bufptr;
297
298         static guint8 ASCII_translate_EBCDIC [ 256 ] = {
299             0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
300             0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
301             0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,
302             0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
303             0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D, 0x4D,
304             0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
305             0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8,
306             0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
307             0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8,
308             0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
309             0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7,
310             0xE8, 0xE9, 0xAD, 0xE0, 0xBD, 0x5F, 0x6D,
311             0x7D, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
312             0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
313             0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
314             0xA8, 0xA9, 0xC0, 0x6A, 0xD0, 0xA1, 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             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
326             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
327             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
328             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
329             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B,
330             0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B, 0x4B
331         };
332
333         bufptr = buf;
334
335         for (i = 0; i < bytes; i++, bufptr++) {
336                 *bufptr = ASCII_translate_EBCDIC[*bufptr];
337         }
338 }
339
340 void
341 EBCDIC_to_ASCII(guint8 *buf, guint bytes)
342 {
343         guint   i;
344         guint8  *bufptr;
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         bufptr = buf;
382
383         for (i = 0; i < bytes; i++, bufptr++) {
384                 *bufptr = EBCDIC_translate_ASCII[*bufptr];
385         }
386 }
387