Ethereal-dev: Re: [Ethereal-dev] Unhandled exception...
Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.
From: "Gautham Thavva" <gautham.thavva@xxxxxxxxx>
Date: Sat, 12 Oct 2002 10:15:58 -0400
Hi Ashok, I have used diff version for windows and have enclosed the diffs as html. Please tell me if you need any other information. Thanks, Gautham On Fri, 11 Oct 2002 16:15:34 Ashok Narayanan wrote: > >You probably need to send out more information: > >1) A diff of your changes > >2) If you got a core dump, the backtrace of that core dump > >-Ashok > >> >> Please can someone who knows about the GUI help me. I had to include a text field for entering an IP address which would call a routine >> for bringing HDLC traffic from a remote terminal. >> >> These were the changes I made. >> >> I modified the capture file structure in file.h to add >> the IP address field. (gchar *ipaddr) >> I initialized the capture file variable in main.c >> (cfile.ipaddr = NULL) >> I added the GUI text entry construct in the capture_dlg.c >> When an IP address is entered, I trigger the remote >> capture by calling a routine. >> >> What happened was that initially, ethereal just quit. >> Then I commented out the portion of calling of the routine and recompiled. I then encountered Unhandled exception:0xC0000005:Access Violation. It was at the instruction do_capture(save_file) in capture_dlg.c >> >> I then commented out all the extra additions and having brought >> to the original state, no longer faced the unhandled exception. >> That however doesn't solve my problem. I don't understand why the >> GUI additions caused the error. >> >> Did I miss updating somewhere else? >> Please can someone help in resolving this issue. >> >> with regards, >> Gautham Thavva >> >> >> ____________________________________________________________ >> Watch a championship game with Elway or McGwire. >> Enter Now at http://champions.lycos.com >> _______________________________________________ >> Ethereal-dev mailing list >> Ethereal-dev@xxxxxxxxxxxx >> http://www.ethereal.com/mailman/listinfo/ethereal-dev > > > >--- Asok the Intern ---------------------------------------- >Ashok Narayanan >IOS Network Protocols, Cisco Systems >250 Apollo Drive, Chelmsford, MA 01824 >Ph: 978-497-8387. Fax: 978-497-8513 (Attn: Ashok Narayanan) > > ____________________________________________________________ Watch a championship game with Elway or McGwire. Enter Now at http://champions.lycos.comTitle: Differences Analysis
Base file: C:\ws\ethereal-0.9.5\gtk\capture_dlg.cCompared file: C:\ethereal-0.9.5\gtk\capture_dlg.cDifference Analysis Generated by HtmlDiff on 10/11/2002 5:51 PM 1: /* capture_dlg.c 2: * Routines for packet capture windows 3: * 4: * $Id: capture_dlg.c,v 1.69 2002/06/24 20:56:15 guy Exp $ 5: * 6: * Ethereal - Network traffic analyzer 7: * By Gerald Combs <gerald@xxxxxxxxxxxx> 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: #ifdef HAVE_LIBPCAP 30: 31: #include <stdlib.h> 32: #include <stdio.h> 33: #include <string.h> 34: #include <gtk/gtk.h> 35: 36: #ifdef HAVE_UNISTD_H 37: #include <unistd.h> 38: #endif 39: 40: #include <time.h> 41: 42: #include <pcap.h> 43: 44: #ifdef NEED_SNPRINTF_H 45: # include "snprintf.h" 46: #endif 47: 48: #include "capture.h" 49: #include "capture_remote.h" 49: #include "globals.h" 50: #include <epan/resolv.h> 51: #include "main.h" 52: #include "ui_util.h" 53: #include "capture_dlg.h" 54: #include "filter_prefs.h" 55: #include "simple_dialog.h" 56: #include "dlg_utils.h" 57: #include "pcap-util.h" 58: #include "prefs.h" 59: #include "ringbuffer.h" 60: 61: #ifdef _WIN32 62: #include "capture-wpcap.h" 63: #endif 64: 65: /* Capture callback data keys */ 66: #define E_CAP_IFACE_KEY "cap_iface" 67: #define E_CAP_SNAP_CB_KEY "cap_snap_cb" 68: #define E_CAP_SNAP_SB_KEY "cap_snap_sb" 69: #define E_CAP_PROMISC_KEY "cap_promisc" 70: #define E_CAP_FILT_KEY "cap_filter_te" 72: #define E_CAP_IPADDR_TE_KEY "cap_ipaddr_te" 73: #define E_CAP_V5_IF_TE_KEY "cap_v5_if_te" 71: #define E_CAP_FILE_TE_KEY "cap_file_te" 72: #define E_CAP_RING_ON_TB_KEY "cap_ringbuffer_on_tb" 73: #define E_CAP_RING_NBF_LB_KEY "cap_ringbuffer_nbf_lb" 74: #define E_CAP_RING_NBF_SB_KEY "cap_ringbuffer_nbf_sb" 75: #define E_CAP_SYNC_KEY "cap_sync" 76: #define E_CAP_AUTO_SCROLL_KEY "cap_auto_scroll" 77: #define E_CAP_COUNT_CB_KEY "cap_count_cb" 78: #define E_CAP_COUNT_SB_KEY "cap_count_sb" 79: #define E_CAP_FILESIZE_CB_KEY "cap_filesize_cb" 80: #define E_CAP_FILESIZE_SB_KEY "cap_filesize_sb" 81: #define E_CAP_FILESIZE_LB_KEY "cap_filesize_lb" 82: #define E_CAP_DURATION_CB_KEY "cap_duration_cb" 83: #define E_CAP_DURATION_SB_KEY "cap_duration_sb" 84: #define E_CAP_M_RESOLVE_KEY "cap_m_resolve" 85: #define E_CAP_N_RESOLVE_KEY "cap_n_resolve" 86: #define E_CAP_T_RESOLVE_KEY "cap_t_resolve" 87: 88: #define E_FS_CALLER_PTR_KEY "fs_caller_ptr" 89: #define E_FILE_SEL_DIALOG_PTR_KEY "file_sel_dialog_ptr" 90: 91: static void 92: capture_prep_file_cb(GtkWidget *w, gpointer te); 93: 94: static void 95: cap_prep_fs_ok_cb(GtkWidget *w, gpointer data); 96: 97: static void 98: cap_prep_fs_cancel_cb(GtkWidget *w, gpointer data); 99: 100: static void 101: cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data); 102: 103: static void 104: capture_prep_adjust_sensitivity(GtkWidget *tb, gpointer parent_w); 105: 106: static void 107: capture_prep_ok_cb(GtkWidget *ok_bt, gpointer parent_w); 108: 109: static void 110: capture_prep_close_cb(GtkWidget *close_bt, gpointer parent_w); 111: 112: static void 113: capture_prep_destroy_cb(GtkWidget *win, gpointer user_data); 114: 115: void 116: capture_stop_cb(GtkWidget *w _U_, gpointer d _U_) 117: { 118: capture_stop(); 119: } 120: 121: /* 122: * Keep a static pointer to the current "Capture Options" window, if 123: * any, so that if somebody tries to do "Capture:Start" while there's 124: * already a "Capture Options" window up, we just pop up the existing 125: * one, rather than creating a new one. 126: */ 127: static GtkWidget *cap_open_w; 128: 129: void 130: capture_prep_cb(GtkWidget *w _U_, gpointer d _U_) 131: { 132: GtkWidget *main_vb, 133: *capture_fr, *capture_vb, 134: *if_hb, *if_cb, *if_lb, 135: *snap_hb, *snap_cb, *snap_sb, *snap_lb, 136: *promisc_cb, 137: *filter_hb, *filter_bt, *filter_te, 141: *remote_snoop_fr, *remote_snoop_vb, 142: *ipaddr_hb, *ipaddr_lb, *ipaddr_te, 143: *v5_if_hb, *v5_if_lb, *v5_if_te, 138: *file_fr, *file_vb, 139: *file_hb, *file_bt, *file_te, 140: *ringbuffer_hb, *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb, 141: *display_fr, *display_vb, 142: *sync_cb, *auto_scroll_cb, 143: *limit_fr, *limit_vb, 144: *count_hb, *count_cb, *count_sb, *count_lb, 145: *filesize_hb, *filesize_cb, *filesize_sb, *filesize_lb, 146: *duration_hb, *duration_cb, *duration_sb, *duration_lb, 147: *resolv_fr, *resolv_vb, 148: *m_resolv_cb, *n_resolv_cb, *t_resolv_cb, 149: *bbox, *ok_bt, *cancel_bt; 150: GtkAccelGroup *accel_group; 151: GtkAdjustment *snap_adj, *ringbuffer_nbf_adj, 152: *count_adj, *filesize_adj, *duration_adj; 153: GList *if_list; 154: int err; 155: char err_str[PCAP_ERRBUF_SIZE]; 156: 157: if (cap_open_w != NULL) { 158: /* There's already a "Capture Options" dialog box; reactivate it. */ 159: reactivate_window(cap_open_w); 160: return; 161: } 162: 163: #ifdef _WIN32 164: /* Is WPcap loaded? */ 165: if (!has_wpcap) { 166: simple_dialog(ESD_TYPE_CRIT, NULL, 167: "Unable to load WinPcap (wpcap.dll); Ethereal will not be able\n" 168: "to capture packets.\n\n" 169: "In order to capture packets, WinPcap must be installed; see\n" 170: "\n" 171: " http://winpcap.polito.it/\n" 172: "\n" 173: "or the mirror at\n" 174: "\n" 175: " http://winpcap.mirror.ethereal.com/\n" 176: "\n" 177: "or the mirror at\n" 178: "\n" 179: " http://www.mirrors.wiretapped.net/security/packet-capture/winpcap/\n" 180: "\n" 181: "for a downloadable version of WinPcap and for instructions\n" 182: "on how to install WinPcap."); 183: return; 184: } 185: #endif 186: 187: if_list = get_interface_list(&err, err_str); 188: if (if_list == NULL && err == CANT_GET_INTERFACE_LIST) { 189: simple_dialog(ESD_TYPE_WARN, NULL, "Can't get list of interfaces: %s", 190: err_str); 191: } 192: 193: cap_open_w = dlg_window_new("Ethereal: Capture Options"); 194: gtk_signal_connect(GTK_OBJECT(cap_open_w), "destroy", 195: GTK_SIGNAL_FUNC(capture_prep_destroy_cb), NULL); 196: 197: /* Accelerator group for the accelerators (or, as they're called in 198: Windows and, I think, in Motif, "mnemonics"; Alt+<key> is a mnemonic, 199: Ctrl+<key> is an accelerator). */ 200: accel_group = gtk_accel_group_new(); 201: gtk_window_add_accel_group(GTK_WINDOW(cap_open_w), accel_group); 202: 203: main_vb = gtk_vbox_new(FALSE, 0); 204: gtk_container_border_width(GTK_CONTAINER(main_vb), 5); 205: gtk_container_add(GTK_CONTAINER(cap_open_w), main_vb); 206: gtk_widget_show(main_vb); 207: 208: /* Capture-related options frame */ 209: capture_fr = gtk_frame_new("Capture"); 210: gtk_container_add(GTK_CONTAINER(main_vb), capture_fr); 211: gtk_widget_show(capture_fr); 212: 213: capture_vb = gtk_vbox_new(FALSE, 0); 214: gtk_container_add(GTK_CONTAINER(capture_fr), capture_vb); 215: gtk_widget_show(capture_vb); 216: 217: /* Interface row */ 218: if_hb = gtk_hbox_new(FALSE, 3); 219: gtk_container_add(GTK_CONTAINER(capture_vb), if_hb); 220: gtk_widget_show(if_hb); 221: 222: if_lb = gtk_label_new("Interface:"); 223: gtk_box_pack_start(GTK_BOX(if_hb), if_lb, FALSE, FALSE, 6); 224: gtk_widget_show(if_lb); 225: 226: if_cb = gtk_combo_new(); 227: if (if_list != NULL) 228: gtk_combo_set_popdown_strings(GTK_COMBO(if_cb), if_list); 229: if (cfile.iface == NULL && prefs.capture_device != NULL) { 230: /* No interface was specified on the command line or in a previous 231: capture, but there is one specified in the preferences file; 232: make the one from the preferences file the default */ 233: cfile.iface = g_strdup(prefs.capture_device); 234: } 235: if (cfile.iface != NULL) 236: gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), cfile.iface); 237: else if (if_list != NULL) 238: gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry), if_list->data); 239: gtk_box_pack_start(GTK_BOX(if_hb), if_cb, TRUE, TRUE, 6); 240: gtk_widget_show(if_cb); 241: 242: free_interface_list(if_list); 243: 244: /* Capture length row */ 245: snap_hb = gtk_hbox_new(FALSE, 3); 246: gtk_container_add(GTK_CONTAINER(capture_vb), snap_hb); 247: gtk_widget_show(snap_hb); 248: 249: snap_cb = dlg_check_button_new_with_label_with_mnemonic( 250: "_Limit each packet to", accel_group); 251: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(snap_cb), 252: capture_opts.has_snaplen); 253: gtk_signal_connect(GTK_OBJECT(snap_cb), "toggled", 254: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 255: gtk_box_pack_start(GTK_BOX(snap_hb), snap_cb, FALSE, FALSE, 0); 256: gtk_widget_show(snap_cb); 257: 258: snap_adj = (GtkAdjustment *) gtk_adjustment_new((float) capture_opts.snaplen, 259: MIN_PACKET_SIZE, WTAP_MAX_PACKET_SIZE, 1.0, 10.0, 0.0); 260: snap_sb = gtk_spin_button_new (snap_adj, 0, 0); 261: gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (snap_sb), TRUE); 262: gtk_widget_set_usize (snap_sb, 80, 0); 263: gtk_box_pack_start (GTK_BOX(snap_hb), snap_sb, FALSE, FALSE, 0); 264: gtk_widget_show(snap_sb); 265: 266: snap_lb = gtk_label_new("bytes"); 267: gtk_misc_set_alignment(GTK_MISC(snap_lb), 0, 0.5); 268: gtk_box_pack_start(GTK_BOX(snap_hb), snap_lb, FALSE, FALSE, 0); 269: gtk_widget_show(snap_lb); 270: 271: /* Promiscuous mode row */ 272: promisc_cb = dlg_check_button_new_with_label_with_mnemonic( 273: "Capture packets in _promiscuous mode", accel_group); 274: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(promisc_cb), 275: capture_opts.promisc_mode); 276: gtk_container_add(GTK_CONTAINER(capture_vb), promisc_cb); 277: gtk_widget_show(promisc_cb); 278: 279: /* Filter row */ 280: filter_hb = gtk_hbox_new(FALSE, 3); 281: gtk_container_add(GTK_CONTAINER(capture_vb), filter_hb); 282: gtk_widget_show(filter_hb); 283: 284: filter_bt = gtk_button_new_with_label("Filter:"); 285: gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked", 286: GTK_SIGNAL_FUNC(capture_filter_construct_cb), NULL); 287: gtk_box_pack_start(GTK_BOX(filter_hb), filter_bt, FALSE, FALSE, 3); 288: gtk_widget_show(filter_bt); 289: 290: filter_te = gtk_entry_new(); 291: if (cfile.cfilter) gtk_entry_set_text(GTK_ENTRY(filter_te), cfile.cfilter); 292: gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te); 293: gtk_box_pack_start(GTK_BOX(filter_hb), filter_te, TRUE, TRUE, 3); 294: gtk_widget_show(filter_te); 295: 302: /* Remote Snoop frame */ 303: 304: remote_snoop_fr = gtk_frame_new("Remote Snoop"); 305: gtk_container_add(GTK_CONTAINER(main_vb), remote_snoop_fr); 306: gtk_widget_show(remote_snoop_fr); 307: 308: remote_snoop_vb = gtk_vbox_new(FALSE, 0); 309: gtk_container_add(GTK_CONTAINER(remote_snoop_fr), remote_snoop_vb); 310: gtk_widget_show(remote_snoop_vb); 311: 312: /* IP address row */ 313: 314: ipaddr_hb = gtk_hbox_new(FALSE, 3); 315: gtk_container_add(GTK_CONTAINER(remote_snoop_vb), ipaddr_hb); 316: gtk_widget_show(ipaddr_hb); 317: 318: ipaddr_lb = gtk_label_new("IP address:"); 319: gtk_box_pack_start(GTK_BOX(ipaddr_hb), ipaddr_lb, FALSE, FALSE, 6); 320: gtk_widget_show(ipaddr_lb); 321: 322: ipaddr_te = gtk_entry_new(); 323: gtk_box_pack_start(GTK_BOX(ipaddr_hb), ipaddr_te, TRUE, TRUE, 3); 324: gtk_widget_show(ipaddr_te); 325: 326: /* V5 Interface row*/ 327: 328: v5_if_hb = gtk_hbox_new(FALSE, 3); 329: gtk_container_add(GTK_CONTAINER(remote_snoop_vb), v5_if_hb); 330: gtk_widget_show(v5_if_hb); 331: 332: v5_if_lb = gtk_label_new("V5 Interface:"); 333: gtk_box_pack_start(GTK_BOX(v5_if_hb), v5_if_lb, FALSE, FALSE, 6); 334: gtk_widget_show(v5_if_lb); 335: 336: v5_if_te = gtk_entry_new(); 337: gtk_box_pack_start(GTK_BOX(v5_if_hb), v5_if_te, TRUE, TRUE, 3); 338: gtk_widget_show(v5_if_te); 339: 340: 296: /* Capture file-related options frame */ 297: file_fr = gtk_frame_new("Capture file(s)"); 298: gtk_container_add(GTK_CONTAINER(main_vb), file_fr); 299: gtk_widget_show(file_fr); 300: 301: file_vb = gtk_vbox_new(FALSE, 3); 302: gtk_container_add(GTK_CONTAINER(file_fr), file_vb); 303: gtk_widget_show(file_vb); 304: 305: /* File row */ 306: file_hb = gtk_hbox_new(FALSE, 3); 307: gtk_container_add(GTK_CONTAINER(file_vb), file_hb); 308: gtk_widget_show(file_hb); 309: 310: file_bt = gtk_button_new_with_label("File:"); 311: gtk_box_pack_start(GTK_BOX(file_hb), file_bt, FALSE, FALSE, 3); 312: gtk_widget_show(file_bt); 313: 314: file_te = gtk_entry_new(); 315: gtk_box_pack_start(GTK_BOX(file_hb), file_te, TRUE, TRUE, 3); 316: gtk_widget_show(file_te); 317: 318: gtk_signal_connect(GTK_OBJECT(file_bt), "clicked", 319: GTK_SIGNAL_FUNC(capture_prep_file_cb), GTK_OBJECT(file_te)); 320: 321: /* Ring buffer row */ 322: ringbuffer_hb = gtk_hbox_new(FALSE, 3); 323: gtk_container_add(GTK_CONTAINER(file_vb), ringbuffer_hb); 324: gtk_widget_show(ringbuffer_hb); 325: 326: ringbuffer_on_tb = dlg_check_button_new_with_label_with_mnemonic( 327: "Use _ring buffer", accel_group); 328: /* Ring buffer mode is allowed only if we're not doing an "Update list of 329: packets in real time" capture, so force it off if we're doing such 330: a capture. */ 331: if (capture_opts.sync_mode) 332: capture_opts.ringbuffer_on = FALSE; 333: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), 334: capture_opts.ringbuffer_on); 335: gtk_signal_connect(GTK_OBJECT(ringbuffer_on_tb), "toggled", 336: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 337: gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_on_tb, FALSE, FALSE, 0); 338: gtk_widget_show(ringbuffer_on_tb); 339: 340: ringbuffer_nbf_lb = gtk_label_new("Number of files"); 341: gtk_misc_set_alignment(GTK_MISC(ringbuffer_nbf_lb), 1, 0.5); 342: gtk_box_pack_start(GTK_BOX(ringbuffer_hb), ringbuffer_nbf_lb, FALSE, FALSE, 6); 343: gtk_widget_show(ringbuffer_nbf_lb); 344: 345: ringbuffer_nbf_adj = (GtkAdjustment *) gtk_adjustment_new((float) capture_opts.ringbuffer_num_files, 346: RINGBUFFER_MIN_NUM_FILES, RINGBUFFER_MAX_NUM_FILES, 1.0, 10.0, 0.0); 347: ringbuffer_nbf_sb = gtk_spin_button_new (ringbuffer_nbf_adj, 0, 0); 348: gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (ringbuffer_nbf_sb), TRUE); 349: gtk_widget_set_usize (ringbuffer_nbf_sb, 40, 0); 350: gtk_box_pack_start (GTK_BOX(ringbuffer_hb), ringbuffer_nbf_sb, TRUE, TRUE, 0); 351: gtk_widget_show(ringbuffer_nbf_sb); 352: 353: /* Display-related options frame */ 354: display_fr = gtk_frame_new("Display options"); 355: gtk_container_add(GTK_CONTAINER(main_vb), display_fr); 356: gtk_widget_show(display_fr); 357: 358: display_vb = gtk_vbox_new(FALSE, 0); 359: gtk_container_add(GTK_CONTAINER(display_fr), display_vb); 360: gtk_widget_show(display_vb); 361: 362: /* "Update display in real time" row */ 363: sync_cb = dlg_check_button_new_with_label_with_mnemonic( 364: "_Update list of packets in real time", accel_group); 365: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(sync_cb), 366: capture_opts.sync_mode); 367: gtk_signal_connect(GTK_OBJECT(sync_cb), "toggled", 368: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 369: gtk_container_add(GTK_CONTAINER(display_vb), sync_cb); 370: gtk_widget_show(sync_cb); 371: 372: /* "Auto-scroll live update" row */ 373: auto_scroll_cb = dlg_check_button_new_with_label_with_mnemonic( 374: "_Automatic scrolling in live capture", accel_group); 375: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(auto_scroll_cb), auto_scroll_live); 376: gtk_container_add(GTK_CONTAINER(display_vb), auto_scroll_cb); 377: gtk_widget_show(auto_scroll_cb); 378: 379: /* Capture limits frame */ 380: limit_fr = gtk_frame_new("Capture limits"); 381: gtk_container_add(GTK_CONTAINER(main_vb), limit_fr); 382: gtk_widget_show(limit_fr); 383: 384: limit_vb = gtk_vbox_new(FALSE, 0); 385: gtk_container_add(GTK_CONTAINER(limit_fr), limit_vb); 386: gtk_widget_show(limit_vb); 387: 388: /* Count row */ 389: count_hb = gtk_hbox_new(FALSE, 3); 390: gtk_container_add(GTK_CONTAINER(limit_vb), count_hb); 391: gtk_widget_show(count_hb); 392: 393: count_cb = gtk_check_button_new_with_label("Stop capture after"); 394: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(count_cb), 395: capture_opts.has_autostop_count); 396: gtk_signal_connect(GTK_OBJECT(count_cb), "toggled", 397: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 398: gtk_box_pack_start(GTK_BOX(count_hb), count_cb, FALSE, FALSE, 0); 399: gtk_widget_show(count_cb); 400: 401: count_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_count, 402: 1, INT_MAX, 1.0, 10.0, 0.0); 403: count_sb = gtk_spin_button_new (count_adj, 0, 0); 404: gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (count_sb), TRUE); 405: gtk_widget_set_usize (count_sb, 80, 0); 406: gtk_box_pack_start (GTK_BOX(count_hb), count_sb, FALSE, FALSE, 0); 407: gtk_widget_show(count_sb); 408: 409: count_lb = gtk_label_new("packet(s) captured"); 410: gtk_misc_set_alignment(GTK_MISC(count_lb), 0, 0.5); 411: gtk_box_pack_start(GTK_BOX(count_hb), count_lb, FALSE, FALSE, 0); 412: gtk_widget_show(count_lb); 413: 414: /* Filesize row */ 415: filesize_hb = gtk_hbox_new(FALSE, 3); 416: gtk_container_add(GTK_CONTAINER(limit_vb), filesize_hb); 417: gtk_widget_show(filesize_hb); 418: 419: filesize_cb = gtk_check_button_new_with_label(""); 420: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb), 421: capture_opts.has_autostop_filesize); 422: gtk_signal_connect(GTK_OBJECT(filesize_cb), "toggled", 423: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 424: gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_cb, FALSE, FALSE, 0); 425: gtk_widget_show(filesize_cb); 426: 427: filesize_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_filesize, 428: 1, INT_MAX, 1.0, 10.0, 0.0); 429: filesize_sb = gtk_spin_button_new (filesize_adj, 0, 0); 430: gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (filesize_sb), TRUE); 431: gtk_widget_set_usize (filesize_sb, 80, 0); 432: gtk_box_pack_start (GTK_BOX(filesize_hb), filesize_sb, FALSE, FALSE, 0); 433: gtk_widget_show(filesize_sb); 434: 435: filesize_lb = gtk_label_new(""); 436: gtk_misc_set_alignment(GTK_MISC(filesize_lb), 0, 0.5); 437: gtk_box_pack_start(GTK_BOX(filesize_hb), filesize_lb, FALSE, FALSE, 0); 438: gtk_widget_show(filesize_lb); 439: 440: /* Duration row */ 441: duration_hb = gtk_hbox_new(FALSE, 3); 442: gtk_container_add(GTK_CONTAINER(limit_vb), duration_hb); 443: gtk_widget_show(duration_hb); 444: 445: duration_cb = gtk_check_button_new_with_label("Stop capture after"); 446: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(duration_cb), 447: capture_opts.has_autostop_duration); 448: gtk_signal_connect(GTK_OBJECT(duration_cb), "toggled", 449: GTK_SIGNAL_FUNC(capture_prep_adjust_sensitivity), GTK_OBJECT(cap_open_w)); 450: gtk_box_pack_start(GTK_BOX(duration_hb), duration_cb, FALSE, FALSE, 0); 451: gtk_widget_show(duration_cb); 452: 453: duration_adj = (GtkAdjustment *) gtk_adjustment_new(capture_opts.autostop_duration, 454: 1, INT_MAX, 1.0, 10.0, 0.0); 455: duration_sb = gtk_spin_button_new (duration_adj, 0, 0); 456: gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (duration_sb), TRUE); 457: gtk_widget_set_usize (duration_sb, 80, 0); 458: gtk_box_pack_start (GTK_BOX(duration_hb), duration_sb, FALSE, FALSE, 0); 459: gtk_widget_show(duration_sb); 460: 461: duration_lb = gtk_label_new("second(s)"); 462: gtk_misc_set_alignment(GTK_MISC(duration_lb), 0, 0.5); 463: gtk_box_pack_start(GTK_BOX(duration_hb), duration_lb, FALSE, FALSE, 0); 464: gtk_widget_show(duration_lb); 465: 466: /* Resolution options frame */ 467: resolv_fr = gtk_frame_new("Name resolution"); 468: gtk_container_add(GTK_CONTAINER(main_vb), resolv_fr); 469: gtk_widget_show(resolv_fr); 470: 471: resolv_vb = gtk_vbox_new(FALSE, 0); 472: gtk_container_add(GTK_CONTAINER(resolv_fr), resolv_vb); 473: gtk_widget_show(resolv_vb); 474: 475: m_resolv_cb = dlg_check_button_new_with_label_with_mnemonic( 476: "Enable _MAC name resolution", accel_group); 477: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(m_resolv_cb), 478: g_resolv_flags & RESOLV_MAC); 479: gtk_container_add(GTK_CONTAINER(resolv_vb), m_resolv_cb); 480: gtk_widget_show(m_resolv_cb); 481: 482: n_resolv_cb = dlg_check_button_new_with_label_with_mnemonic( 483: "Enable _network name resolution", accel_group); 484: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(n_resolv_cb), 485: g_resolv_flags & RESOLV_NETWORK); 486: gtk_container_add(GTK_CONTAINER(resolv_vb), n_resolv_cb); 487: gtk_widget_show(n_resolv_cb); 488: 489: t_resolv_cb = dlg_check_button_new_with_label_with_mnemonic( 490: "Enable _transport name resolution", accel_group); 491: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(t_resolv_cb), 492: g_resolv_flags & RESOLV_TRANSPORT); 493: gtk_container_add(GTK_CONTAINER(resolv_vb), t_resolv_cb); 494: gtk_widget_show(t_resolv_cb); 495: 496: /* Button row: OK and cancel buttons */ 497: bbox = gtk_hbutton_box_new(); 498: gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END); 499: gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5); 500: gtk_container_add(GTK_CONTAINER(main_vb), bbox); 501: gtk_widget_show(bbox); 502: 503: ok_bt = gtk_button_new_with_label ("OK"); 504: gtk_signal_connect(GTK_OBJECT(ok_bt), "clicked", 505: GTK_SIGNAL_FUNC(capture_prep_ok_cb), GTK_OBJECT(cap_open_w)); 506: GTK_WIDGET_SET_FLAGS(ok_bt, GTK_CAN_DEFAULT); 507: gtk_box_pack_start (GTK_BOX (bbox), ok_bt, TRUE, TRUE, 0); 508: gtk_widget_grab_default(ok_bt); 509: gtk_widget_show(ok_bt); 510: 511: cancel_bt = gtk_button_new_with_label ("Cancel"); 512: gtk_signal_connect(GTK_OBJECT(cancel_bt), "clicked", 513: GTK_SIGNAL_FUNC(capture_prep_close_cb), GTK_OBJECT(cap_open_w)); 514: GTK_WIDGET_SET_FLAGS(cancel_bt, GTK_CAN_DEFAULT); 515: gtk_box_pack_start (GTK_BOX (bbox), cancel_bt, TRUE, TRUE, 0); 516: gtk_widget_show(cancel_bt); 517: 518: /* Attach pointers to needed widgets to the capture prefs window/object */ 519: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_IFACE_KEY, if_cb); 520: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_CB_KEY, snap_cb); 521: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SNAP_SB_KEY, snap_sb); 522: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_PROMISC_KEY, promisc_cb); 523: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILT_KEY, filter_te); 569: 570: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_IPADDR_TE_KEY, ipaddr_te); 571: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_V5_IF_TE_KEY, v5_if_te); 572: 524: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILE_TE_KEY, file_te); 525: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_ON_TB_KEY, ringbuffer_on_tb); 526: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_NBF_LB_KEY, ringbuffer_nbf_lb); 527: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_RING_NBF_SB_KEY, ringbuffer_nbf_sb); 528: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_SYNC_KEY, sync_cb); 529: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_AUTO_SCROLL_KEY, auto_scroll_cb); 530: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_CB_KEY, count_cb); 531: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_COUNT_SB_KEY, count_sb); 532: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILESIZE_CB_KEY, filesize_cb); 533: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILESIZE_SB_KEY, filesize_sb); 534: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_FILESIZE_LB_KEY, filesize_lb); 535: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_DURATION_CB_KEY, duration_cb); 536: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_DURATION_SB_KEY, duration_sb); 537: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_M_RESOLVE_KEY, m_resolv_cb); 538: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_N_RESOLVE_KEY, n_resolv_cb); 539: gtk_object_set_data(GTK_OBJECT(cap_open_w), E_CAP_T_RESOLVE_KEY, t_resolv_cb); 540: 541: /* Set the sensitivity of various widgets as per the settings of other 542: widgets. */ 543: capture_prep_adjust_sensitivity(NULL, cap_open_w); 544: 545: /* Catch the "activate" signal on the frame number and file name text 546: entries, so that if the user types Return there, we act as if the 547: "OK" button had been selected, as happens if Return is typed if some 548: widget that *doesn't* handle the Return key has the input focus. */ 549: dlg_set_activate(filter_te, ok_bt); 550: dlg_set_activate(file_te, ok_bt); 551: 601: dlg_set_activate(ipaddr_te, ok_bt); 602: dlg_set_activate(v5_if_te, ok_bt); 603: 604: 552: /* Catch the "key_press_event" signal in the window, so that we can catch 553: the ESC key being pressed and act as if the "Cancel" button had 554: been selected. */ 555: dlg_set_cancel(cap_open_w, cancel_bt); 556: 557: /* XXX - why does not 558: 559: gtk_widget_grab_focus(if_cb); 560: 561: give the initial focus to the "Interface" combo box? 562: 563: Or should I phrase that as "why does GTK+ continually frustrate 564: attempts to make GUIs driveable from the keyboard?" We have to 565: go catch the activate signal on every single GtkEntry widget 566: (rather than having widgets whose activate signal is *not* 567: caught not catch the Return keystroke, so that it passes on, 568: ultimately, to the window, which can activate the default 569: widget, i.e. the "OK" button); we have to catch the "key_press_event" 570: signal and have the handler check for ESC, so that we can have ESC 571: activate the "Cancel" button; in order to support Alt+<key> mnemonics 572: for buttons and the like, we may have to construct an accelerator 573: group by hand and set up the accelerators by hand (if that even 574: works - I've not tried it yet); we have to do a "gtk_widget_grab_focus()" 575: to keep some container widget from getting the initial focus, so that 576: you don't have to tab into the first widget in order to start typing 577: in it; and it now appears that you simply *can't* make a combo box 578: get the initial focus, at least not in the obvious fashion. Sigh.... */ 579: 580: gtk_widget_show(cap_open_w); 581: } 582: 583: static void 584: capture_prep_file_cb(GtkWidget *w, gpointer file_te) 585: { 586: GtkWidget *caller = gtk_widget_get_toplevel(w); 587: GtkWidget *fs; 588: 589: /* Has a file selection dialog box already been opened for that top-level 590: widget? */ 591: fs = gtk_object_get_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY); 592: 593: if (fs != NULL) { 594: /* Yes. Just re-activate that dialog box. */ 595: reactivate_window(fs); 596: return; 597: } 598: 599: fs = gtk_file_selection_new ("Ethereal: Capture File"); 600: 601: gtk_object_set_data(GTK_OBJECT(fs), E_CAP_FILE_TE_KEY, file_te); 602: 603: /* Set the E_FS_CALLER_PTR_KEY for the new dialog to point to our caller. */ 604: gtk_object_set_data(GTK_OBJECT(fs), E_FS_CALLER_PTR_KEY, caller); 605: 606: /* Set the E_FILE_SEL_DIALOG_PTR_KEY for the caller to point to us */ 607: gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, fs); 608: 609: /* Call a handler when the file selection box is destroyed, so we can inform 610: our caller, if any, that it's been destroyed. */ 611: gtk_signal_connect(GTK_OBJECT(fs), "destroy", 612: GTK_SIGNAL_FUNC(cap_prep_fs_destroy_cb), NULL); 613: 614: gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->ok_button), 615: "clicked", (GtkSignalFunc) cap_prep_fs_ok_cb, fs); 616: 617: /* Connect the cancel_button to destroy the widget */ 618: gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION(fs)->cancel_button), 619: "clicked", (GtkSignalFunc) cap_prep_fs_cancel_cb, fs); 620: 621: /* Catch the "key_press_event" signal in the window, so that we can catch 622: the ESC key being pressed and act as if the "Cancel" button had 623: been selected. */ 624: dlg_set_cancel(fs, GTK_FILE_SELECTION(fs)->cancel_button); 625: 626: gtk_widget_show(fs); 627: } 628: 629: static void 630: cap_prep_fs_ok_cb(GtkWidget *w _U_, gpointer data) 631: { 632: gtk_entry_set_text(GTK_ENTRY(gtk_object_get_data(GTK_OBJECT(data), 633: E_CAP_FILE_TE_KEY)), 634: gtk_file_selection_get_filename (GTK_FILE_SELECTION(data))); 635: gtk_widget_destroy(GTK_WIDGET(data)); 636: } 637: 638: static void 639: cap_prep_fs_cancel_cb(GtkWidget *w _U_, gpointer data) 640: { 641: gtk_widget_destroy(GTK_WIDGET(data)); 642: } 643: 644: static void 645: cap_prep_fs_destroy_cb(GtkWidget *win, gpointer data _U_) 646: { 647: GtkWidget *caller; 648: 649: /* Get the widget that requested that we be popped up. 650: (It should arrange to destroy us if it's destroyed, so 651: that we don't get a pointer to a non-existent window here.) */ 652: caller = gtk_object_get_data(GTK_OBJECT(win), E_FS_CALLER_PTR_KEY); 653: 654: /* Tell it we no longer exist. */ 655: gtk_object_set_data(GTK_OBJECT(caller), E_FILE_SEL_DIALOG_PTR_KEY, NULL); 656: 657: /* Now nuke this window. */ 658: gtk_grab_remove(GTK_WIDGET(win)); 659: gtk_widget_destroy(GTK_WIDGET(win)); 660: } 661: 662: static void 663: capture_prep_ok_cb(GtkWidget *ok_bt _U_, gpointer parent_w) { 664: GtkWidget *if_cb, *snap_cb, *snap_sb, *promisc_cb, *filter_te, 665: *file_te, *ringbuffer_on_tb, *ringbuffer_nbf_sb, 719: *ipaddr_te, *v5_if_te, *file_te, *ringbuffer_on_tb, 720: *ringbuffer_nbf_sb, 666: *sync_cb, *auto_scroll_cb, 667: *count_cb, *count_sb, 668: *filesize_cb, *filesize_sb, 669: *duration_cb, *duration_sb, 670: *m_resolv_cb, *n_resolv_cb, *t_resolv_cb; 671: gchar *if_text; 672: gchar *if_name; 673: gchar *filter_text; 729: gchar *ipaddr_text; 730: gchar *v5_if_text; 674: gchar *save_file; 675: 676: if_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IFACE_KEY); 677: snap_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_CB_KEY); 678: snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_SB_KEY); 679: promisc_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_PROMISC_KEY); 680: filter_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILT_KEY); 739: 740: ipaddr_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_IPADDR_TE_KEY); 741: v5_if_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_V5_IF_TE_KEY); 742: 681: file_te = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILE_TE_KEY); 682: ringbuffer_on_tb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_ON_TB_KEY); 683: ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_NBF_SB_KEY); 684: sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY); 685: auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY); 686: count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_CB_KEY); 687: count_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_SB_KEY); 688: filesize_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_CB_KEY); 689: filesize_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_SB_KEY); 690: duration_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_CB_KEY); 691: duration_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_SB_KEY); 692: m_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_M_RESOLVE_KEY); 693: n_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_N_RESOLVE_KEY); 694: t_resolv_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_T_RESOLVE_KEY); 695: 696: if_text = 697: g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(if_cb)->entry))); 698: /* Windows combo entries have a description followed by the interface name */ 699: if_name = strrchr(if_text, ' '); 700: if (if_name == NULL) { 701: if_name = if_text; 702: } else { 703: if_name++; 704: } 705: if (if_name == NULL) { 706: simple_dialog(ESD_TYPE_CRIT, NULL, 707: "You didn't specify an interface on which to capture packets."); 708: g_free(if_text); 709: return; 710: } 711: if (cfile.iface) 712: g_free(cfile.iface); 713: cfile.iface = g_strdup(if_name); 714: g_free(if_text); 715: 716: capture_opts.has_snaplen = 717: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb)); 718: if (capture_opts.has_snaplen) { 719: capture_opts.snaplen = 720: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(snap_sb)); 721: if (capture_opts.snaplen < 1) 722: capture_opts.snaplen = WTAP_MAX_PACKET_SIZE; 723: else if (capture_opts.snaplen < MIN_PACKET_SIZE) 724: capture_opts.snaplen = MIN_PACKET_SIZE; 725: } 726: 727: capture_opts.promisc_mode = 728: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(promisc_cb)); 729: 730: /* XXX - don't try to get clever and set "cfile.filter" to NULL if the 731: filter string is empty, as an indication that we don't have a filter 732: and thus don't have to set a filter when capturing - the version of 733: libpcap in Red Hat Linux 6.1, and versions based on later patches 734: in that series, don't bind the AF_PACKET socket to an interface 735: until a filter is set, which means they aren't bound at all if 736: no filter is set, which means no packets arrive as input on that 737: socket, which means Ethereal never sees any packets. */ 738: filter_text = gtk_entry_get_text(GTK_ENTRY(filter_te)); 739: if (cfile.cfilter) 740: g_free(cfile.cfilter); 741: g_assert(filter_text != NULL); 742: cfile.cfilter = g_strdup(filter_text); 743: 806: /* IP Address and V5 Interface */ 807: 808: ipaddr_text = gtk_entry_get_text(GTK_ENTRY(ipaddr_te)); 809: if (cfile.ipaddr) 810: g_free(cfile.ipaddr); 811: g_assert(ipaddr_text != NULL); 812: cfile.ipaddr = g_strdup(ipaddr_text); 813: cfile.has_ipaddr = TRUE; 814: 815: v5_if_text = gtk_entry_get_text(GTK_ENTRY(v5_if_te)); 816: if (cfile.v5iface) 817: g_free(cfile.v5iface); 818: g_assert(v5_if_text != NULL); 819: cfile.v5iface = g_strdup(v5_if_text); 820: cfile.has_v5iface = TRUE; 821: 744: save_file = gtk_entry_get_text(GTK_ENTRY(file_te)); 745: if (save_file && save_file[0]) { 746: /* User specified a file to which the capture should be written. */ 747: save_file = g_strdup(save_file); 748: } else { 749: /* User didn't specify a file; save to a temporary file. */ 750: save_file = NULL; 751: } 752: 753: capture_opts.has_autostop_count = 754: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb)); 755: if (capture_opts.has_autostop_count) 756: capture_opts.autostop_count = 757: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(count_sb)); 758: 759: capture_opts.has_autostop_filesize = 760: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb)); 761: if (capture_opts.has_autostop_filesize) 762: capture_opts.autostop_filesize = 763: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filesize_sb)); 764: 765: capture_opts.has_autostop_duration = 766: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb)); 767: if (capture_opts.has_autostop_duration) 768: capture_opts.autostop_duration = 769: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(duration_sb)); 770: 771: capture_opts.sync_mode = 772: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb)); 773: 774: auto_scroll_live = 775: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(auto_scroll_cb)); 776: 777: g_resolv_flags = RESOLV_NONE; 778: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(m_resolv_cb))) 779: g_resolv_flags |= RESOLV_MAC; 780: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(n_resolv_cb))) 781: g_resolv_flags |= RESOLV_NETWORK; 782: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(t_resolv_cb))) 783: g_resolv_flags |= RESOLV_TRANSPORT; 784: 785: capture_opts.ringbuffer_on = 786: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb)) && 787: !(capture_opts.sync_mode); 788: if (capture_opts.ringbuffer_on) { 789: if (save_file == NULL) { 790: simple_dialog(ESD_TYPE_CRIT, NULL, 791: "You must specify a save file if you want to use the ring buffer."); 792: return; 793: } else if (!capture_opts.has_autostop_filesize) { 794: simple_dialog(ESD_TYPE_CRIT, NULL, 795: "You must specify a file size at which to rotate the capture files\n" 796: "if you want to use the ring buffer."); 797: return; 798: } 799: } 800: 801: capture_opts.ringbuffer_num_files = 802: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(ringbuffer_nbf_sb)); 803: if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES) 804: capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES; 805: else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES) 806: capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES; 807: 808: gtk_widget_destroy(GTK_WIDGET(parent_w)); 809: 887: /* 888: if(cfile.has_ipaddr) 889: do_snooping(); 890: */ 810: do_capture(save_file); 811: } 812: 813: static void 814: capture_prep_close_cb(GtkWidget *close_bt _U_, gpointer parent_w) 815: { 816: gtk_grab_remove(GTK_WIDGET(parent_w)); 817: gtk_widget_destroy(GTK_WIDGET(parent_w)); 818: } 819: 820: static void 821: capture_prep_destroy_cb(GtkWidget *win, gpointer user_data _U_) 822: { 823: GtkWidget *capture_prep_filter_w; 824: GtkWidget *fs; 825: 826: /* Is there a filter edit/selection dialog associated with this 827: Capture Options dialog? */ 828: capture_prep_filter_w = gtk_object_get_data(GTK_OBJECT(win), E_FILT_DIALOG_PTR_KEY); 829: 830: if (capture_prep_filter_w != NULL) { 831: /* Yes. Destroy it. */ 832: gtk_widget_destroy(capture_prep_filter_w); 833: } 834: 835: /* Is there a file selection dialog associated with this 836: Print File dialog? */ 837: fs = gtk_object_get_data(GTK_OBJECT(win), E_FILE_SEL_DIALOG_PTR_KEY); 838: 839: if (fs != NULL) { 840: /* Yes. Destroy it. */ 841: gtk_widget_destroy(fs); 842: } 843: 844: /* Note that we no longer have a "Capture Options" dialog box. */ 845: cap_open_w = NULL; 846: } 847: 848: /* 849: * Adjust the sensitivity of various widgets as per the current setting 850: * of other widgets. 851: */ 852: static void 853: capture_prep_adjust_sensitivity(GtkWidget *tb _U_, gpointer parent_w) 854: { 855: GtkWidget *snap_cb, *snap_sb, 856: *ringbuffer_on_tb, *ringbuffer_nbf_lb, *ringbuffer_nbf_sb, 857: *sync_cb, *auto_scroll_cb, 858: *count_cb, *count_sb, 859: *filesize_cb, *filesize_sb, *filesize_lb, 860: *duration_cb, *duration_sb; 861: 862: snap_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_CB_KEY); 863: snap_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SNAP_SB_KEY); 864: ringbuffer_on_tb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_ON_TB_KEY); 865: ringbuffer_nbf_lb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_NBF_LB_KEY); 866: ringbuffer_nbf_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_RING_NBF_SB_KEY); 867: sync_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_SYNC_KEY); 868: auto_scroll_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_AUTO_SCROLL_KEY); 869: count_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_CB_KEY); 870: count_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_COUNT_SB_KEY); 871: filesize_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_CB_KEY); 872: filesize_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_SB_KEY); 873: filesize_lb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_FILESIZE_LB_KEY); 874: duration_cb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_CB_KEY); 875: duration_sb = (GtkWidget *) gtk_object_get_data(GTK_OBJECT(parent_w), E_CAP_DURATION_SB_KEY); 876: 877: /* The snapshot length spinbox is sensitive iff the "Limit each packet 878: to" checkbox is on. */ 879: gtk_widget_set_sensitive(GTK_WIDGET(snap_sb), 880: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(snap_cb))); 881: 882: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(sync_cb))) { 883: /* "Update list of packets in real time" captures enabled; we don't 884: support ring buffer mode for those captures, so turn ring buffer 885: mode off if it's on, and make its toggle button, and the spin 886: button for the number of ring buffer files (and the spin button's 887: label), insensitive. */ 888: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) { 889: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb), FALSE); 890: } 891: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), FALSE); 892: 893: /* Auto-scroll mode is meaningful only in "Update list of packets 894: in real time" captures, so make its toggle button sensitive. */ 895: gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), TRUE); 896: } else { 897: /* "Update list of packets in real time" captures disabled; that 898: means ring buffer mode is OK, so make its toggle button 899: sensitive. */ 900: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_on_tb), TRUE); 901: 902: /* Auto-scroll mode is meaningful only in "Update list of packets 903: in real time" captures, so make its toggle button insensitive. */ 904: gtk_widget_set_sensitive(GTK_WIDGET(auto_scroll_cb), FALSE); 905: } 906: 907: if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(ringbuffer_on_tb))) { 908: /* Ring buffer mode enabled. Make the spin button for the number 909: of ring buffer files, and its label, sensitive. */ 910: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), TRUE); 911: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), TRUE); 912: 913: /* Also, indicate that the file size is a size at which to switch 914: ring buffer files, not a size at which to stop the capture, 915: turn its button on. */ 916: gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child), 917: "Rotate capture file every"); 918: gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s)"); 919: gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(filesize_cb), TRUE); 920: } else { 921: /* Ring buffer mode disabled. Make the spin button for the number 922: of ring buffer files, and its label insensitive. */ 923: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_lb), FALSE); 924: gtk_widget_set_sensitive(GTK_WIDGET(ringbuffer_nbf_sb), FALSE); 925: 926: /* Also, indicate that the file size is a size at which to stop the 927: capture, not a size at which to switch ring buffer files. */ 928: gtk_label_set_text(GTK_LABEL(GTK_BIN(filesize_cb)->child), 929: "Stop capture after"); 930: gtk_label_set_text(GTK_LABEL(filesize_lb), "kilobyte(s) captured"); 931: } 932: 933: /* The maximum packet count spinbox is sensitive iff the "Stop capture 934: after N packets captured" checkbox is on. */ 935: gtk_widget_set_sensitive(GTK_WIDGET(count_sb), 936: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(count_cb))); 937: 938: /* The maximum file size spinbox is sensitive iff the "Stop capture 939: after N kilobytes captured" checkbox is on. */ 940: gtk_widget_set_sensitive(GTK_WIDGET(filesize_sb), 941: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filesize_cb))); 942: 943: /* The capture duration spinbox is sensitive iff the "Stop capture 944: after N seconds" checkbox is on. */ 945: gtk_widget_set_sensitive(GTK_WIDGET(duration_sb), 946: gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(duration_cb))); 947: } 948: 949: #endif /* HAVE_LIBPCAP */ 950: |
Base file: C:\ws\ethereal-0.9.5\file.hCompared file: C:\ethereal-0.9.5\file.hDifference Analysis Generated by HtmlDiff on 10/11/2002 5:53 PM 1: /* file.h
2: * Definitions for file structures and routines
3: *
4: * $Id: file.h,v 1.94 2002/05/27 22:00:35 guy Exp $
5: *
6: * Ethereal - Network traffic analyzer
7: * By Gerald Combs <gerald@xxxxxxxxxxxx>
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: #ifndef __FILE_H__
26: #define __FILE_H__
27:
28: #ifdef HAVE_SYS_TYPES_H
29: #include <sys/types.h>
30: #endif
31:
32: #include "wiretap/wtap.h"
33: #include <epan/dfilter/dfilter.h>
34: #include "print.h"
35: #include <errno.h>
36: #include <epan/epan.h>
37:
38: /* Current state of file. */
39: typedef enum {
40: FILE_CLOSED, /* No file open */
41: FILE_READ_IN_PROGRESS, /* Reading a file we've opened */
42: FILE_READ_ABORTED, /* Read aborted by user */
43: FILE_READ_DONE /* Read completed */
44: } file_state;
45:
46: typedef struct _capture_file {
47: file_state state; /* Current state of capture file */
48: int filed; /* File descriptor of capture file */
49: gchar *filename; /* Name of capture file */
50: gboolean is_tempfile; /* Is capture file a temporary file? */
51: gboolean user_saved;/* If capture file is temporary, has it been saved by user yet? */
52: long f_len; /* Length of capture file */
53: guint16 cd_t; /* File type of capture file */
54: int lnk_t; /* Link-layer type with which to save capture */
55: guint32 vers; /* Version. For tcpdump minor is appended to major */
56: int count; /* Total number of frames */
57: int marked_count; /* Number of marked frames */
58: gboolean drops_known; /* TRUE if we know how many packets were dropped */
59: guint32 drops; /* Dropped packets */
60: guint32 esec; /* Elapsed seconds */
61: guint32 eusec; /* Elapsed microseconds */
62: gboolean has_snap; /* TRUE if maximum capture packet length is known */
63: int snap; /* Maximum captured packet length */
64: long progbar_quantum; /* Number of bytes read per progress bar update */
65: long progbar_nextstep; /* Next point at which to update progress bar */
66: gchar *iface; /* Interface */
67: gchar *save_file; /* File that user saved capture to */
68: int save_file_fd; /* File descriptor for saved file */
69: wtap *wth; /* Wiretap session */
70: dfilter_t *rfcode; /* Compiled read filter program */
71: gchar *dfilter; /* Display filter string */
72: dfilter_t *dfcode; /* Compiled display filter program */
73: gchar *ipaddr; /* IP address */
74: gboolean has_ipaddr; /* TRUE if IP address has been entered */
75: gchar *v5iface; /* V5 Interface */
76: gboolean has_v5iface; /* TRUE if V5 interface has been entered */
73: #ifdef HAVE_LIBPCAP
74: gchar *cfilter; /* Capture filter string */
75: #endif
76: gchar *sfilter; /* Search filter string */
77: gboolean sbackward; /* TRUE if search is backward, FALSE if forward */
78: union wtap_pseudo_header pseudo_header; /* Packet pseudo_header */
79: guint8 pd[WTAP_MAX_PACKET_SIZE]; /* Packet data */
80: GMemChunk *plist_chunk; /* Memory chunk for frame_data structures */
81: frame_data *plist; /* Packet list */
82: frame_data *plist_end; /* Last packet in list */
83: frame_data *first_displayed; /* First frame displayed */
84: frame_data *last_displayed; /* Last frame displayed */
85: column_info cinfo; /* Column formatting information */
86: frame_data *current_frame; /* Frame data for current frame */
87: epan_dissect_t *edt; /* Protocol dissection fo rcurrently selected packet */
88: FILE *print_fh; /* File we're printing to */
89: } capture_file;
90:
91: /* Return values from "read_cap_file()", "continue_tail_cap_file()",
92: and "finish_tail_cap_file()". */
93: typedef enum {
94: READ_SUCCESS, /* read succeeded */
95: READ_ERROR, /* read got an error */
96: READ_ABORTED /* read aborted by user */
97: } read_status_t;
98:
99: int open_cap_file(char *, gboolean, capture_file *);
100: void close_cap_file(capture_file *);
101: read_status_t read_cap_file(capture_file *, int *);
102: int start_tail_cap_file(char *, gboolean, capture_file *);
103: read_status_t continue_tail_cap_file(capture_file *, int, int *);
104: read_status_t finish_tail_cap_file(capture_file *, int *);
105: /* size_t read_frame_header(capture_file *); */
106: gboolean save_cap_file(char *, capture_file *, gboolean, gboolean, guint);
107:
108: int filter_packets(capture_file *cf, gchar *dfilter);
109: void colorize_packets(capture_file *);
110: void redissect_packets(capture_file *cf);
111: int print_packets(capture_file *cf, print_args_t *print_args);
112: void change_time_formats(capture_file *);
113: gboolean find_packet(capture_file *cf, dfilter_t *sfcode);
114:
115: typedef enum {
116: FOUND_FRAME, /* found the frame */
117: NO_SUCH_FRAME, /* no frame with that number */
118: FRAME_NOT_DISPLAYED /* frame with that number isn't displayed */
119: } goto_result_t;
120: goto_result_t goto_frame(capture_file *cf, guint fnumber);
121:
122: void select_packet(capture_file *, int);
123: void unselect_packet(capture_file *);
124:
125: void unselect_field(void);
126:
127: /*
128: * Mark a particular frame in a particular capture.
129: */
130: void mark_frame(capture_file *, frame_data *);
131:
132: /*
133: * Unmark a particular frame in a particular capture.
134: */
135: void unmark_frame(capture_file *, frame_data *);
136:
137: /* Moves or copies a file. Returns 0 on failure, 1 on success */
138: int file_mv(char *from, char *to);
139:
140: /* Copies a file. Returns 0 on failure, 1 on success */
141: int file_cp(char *from, char *to);
142:
143: char *file_open_error_message(int, gboolean);
144: char *file_read_error_message(int);
145: char *file_write_error_message(int);
146:
147: #endif /* file.h */
148:
|
Base file: C:\ws\ethereal-0.9.5\gtk\main.cCompared file: C:\ethereal-0.9.5\gtk\main.cDifference Analysis Generated by HtmlDiff on 10/11/2002 5:52 PM 1: /* main.c
2: *
3: * $Id: main.c,v 1.252 2002/05/30 00:44:50 guy Exp $
4: *
5: * Ethereal - Network traffic analyzer
6: * By Gerald Combs <gerald@xxxxxxxxxxxx>
7: * Copyright 1998 Gerald Combs
8: *
9: * Richard Sharpe, 13-Feb-1999, added support for initializing structures
10: * needed by dissect routines
11: * Jeff Foster, 2001/03/12, added support tabbed hex display windowss
12: *
13: *
14: * This program is free software; you can redistribute it and/or
15: * modify it under the terms of the GNU General Public License
16: * as published by the Free Software Foundation; either version 2
17: * of the License, or (at your option) any later version.
18: *
19: * This program is distributed in the hope that it will be useful,
20: * but WITHOUT ANY WARRANTY; without even the implied warranty of
21: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22: * GNU General Public License for more details.
23: *
24: * You should have received a copy of the GNU General Public License
25: * along with this program; if not, write to the Free Software
26: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27: *
28: *
29: * To do:
30: * - Graphs
31: * - Playback window
32: * - Multiple window support
33: * - Add cut/copy/paste
34: * - Create header parsing routines
35: * - Make byte view selections more fancy?
36: */
37:
38: #ifdef HAVE_CONFIG_H
39: # include "config.h"
40: #endif
41:
42: #include <gtk/gtk.h>
43:
44: #include <stdlib.h>
45: #include <stdio.h>
46: #include <string.h>
47: #include <ctype.h>
48:
49: #ifdef HAVE_UNISTD_H
50: #include <unistd.h>
51: #endif
52:
53: #include <errno.h>
54:
55: #ifdef HAVE_SYS_TYPES_H
56: #include <sys/types.h>
57: #endif
58:
59: #ifdef HAVE_SYS_STAT_H
60: #include <sys/stat.h>
61: #endif
62:
63: #ifdef HAVE_IO_H
64: #include <io.h> /* open/close on win32 */
65: #endif
66:
67: #ifdef HAVE_DIRECT_H
68: #include <direct.h>
69: #endif
70:
71: #ifdef HAVE_NETINET_IN_H
72: #include <netinet/in.h>
73: #endif
74:
75: #include <signal.h>
76:
77: #ifdef HAVE_LIBPCAP
78: #include <pcap.h>
79: #endif
80:
81: #ifdef HAVE_LIBZ
82: #include <zlib.h> /* to get the libz version number */
83: #endif
84:
85: #ifdef NEED_SNPRINTF_H
86: # include "snprintf.h"
87: #endif
88:
89: #ifdef HAVE_UCD_SNMP_VERSION_H
90: #include <ucd-snmp/version.h>
91: #endif /* HAVE_UCD_SNMP_VERSION_H */
92:
93: #ifdef NEED_STRERROR_H
94: #include "strerror.h"
95: #endif
96:
97: #ifdef NEED_GETOPT_H
98: #include "getopt.h"
99: #endif
100:
101: #ifdef WIN32 /* Needed for console I/O */
102: #include <fcntl.h>
103: #include <conio.h>
104: #endif
105:
106: #include <epan/epan.h>
107: #include <epan/filesystem.h>
108: #include <epan/epan_dissect.h>
109:
110: #include "main.h"
111: #include <epan/timestamp.h>
112: #include <epan/packet.h>
113: #include "capture.h"
114: #include "summary.h"
115: #include "file.h"
116: #include "filters.h"
117: #include "prefs.h"
118: #include "menu.h"
119: #include "../menu.h"
120: #include "color.h"
121: #include "color_utils.h"
122: #include "filter_prefs.h"
123: #include "file_dlg.h"
124: #include "column.h"
125: #include "print.h"
126: #include <epan/resolv.h>
127: #ifdef HAVE_LIBPCAP
128: #include "pcap-util.h"
129: #endif
130: #include "statusbar.h"
131: #include "simple_dialog.h"
132: #include "proto_draw.h"
133: #include <epan/dfilter/dfilter.h>
134: #include "keys.h"
135: #include "packet_win.h"
136: #include "gtkglobals.h"
137: #include <epan/plugins.h>
138: #include "colors.h"
139: #include <epan/strutil.h>
140: #include "register.h"
141: #include "ringbuffer.h"
142: #include "ui_util.h"
143: #include "image/clist_ascend.xpm"
144: #include "image/clist_descend.xpm"
145:
146: #ifdef WIN32
147: #include "capture-wpcap.h"
148: #endif
149:
150: typedef struct column_arrows {
151: GtkWidget *table;
152: GtkWidget *ascend_pm;
153: GtkWidget *descend_pm;
154: } column_arrows;
155:
156: capture_file cfile;
157: GtkWidget *top_level, *packet_list, *tree_view, *byte_nb_ptr,
158: *tv_scrollw, *pkt_scrollw;
159: static GtkWidget *info_bar;
160: GdkFont *m_r_font, *m_b_font;
161: guint m_font_height, m_font_width;
162: static guint main_ctx, file_ctx, help_ctx;
163: static GString *comp_info_str;
164: gchar *ethereal_path = NULL;
165: gchar *last_open_dir = NULL;
166: gint root_x = G_MAXINT, root_y = G_MAXINT, top_width, top_height;
167:
168: ts_type timestamp_type = RELATIVE;
169:
170: GtkStyle *item_style;
171:
172: /* Specifies the field currently selected in the GUI protocol tree */
173: field_info *finfo_selected = NULL;
174:
175: #ifdef WIN32
176: static gboolean has_no_console; /* TRUE if app has no console */
177: static gboolean console_was_created; /* TRUE if console was created */
178: static void create_console(void);
179: static void destroy_console(void);
180: static void console_log_handler(const char *log_domain,
181: GLogLevelFlags log_level, const char *message, gpointer user_data);
182: #endif
183:
184: static void create_main_window(gint, gint, gint, e_prefs*);
185:
186: #define E_DFILTER_CM_KEY "display_filter_combo"
187: #define E_DFILTER_FL_KEY "display_filter_list"
188:
189: /* About Ethereal window */
190: void
191: about_ethereal( GtkWidget *w _U_, gpointer data _U_ ) {
192: simple_dialog(ESD_TYPE_INFO, NULL,
193: "Ethereal - Network Protocol Analyzer\n"
194: "Version " VERSION " (C) 1998-2000 Gerald Combs <gerald@xxxxxxxxxxxx>\n"
195: "Compiled %s\n\n"
196:
197: "Check the man page for complete documentation and\n"
198: "for the list of contributors.\n"
199:
200: "\nSee http://www.ethereal.com/ for more information.",
201: comp_info_str->str);
202: }
203:
204: void
205: set_fonts(GdkFont *regular, GdkFont *bold)
206: {
207: /* Yes, assert. The code that loads the font should check
208: * for NULL and provide its own error message. */
209: g_assert(m_r_font && m_b_font);
210: m_r_font = regular;
211: m_b_font = bold;
212:
213: m_font_height = m_r_font->ascent + m_r_font->descent;
214: m_font_width = gdk_string_width(m_r_font, "0");
215: }
216:
217:
218: /* Match selected byte pattern */
219: static void
220: match_selected_cb_do(gpointer data, int action, gchar *text)
221: {
222: GtkWidget *filter_te;
223: char *cur_filter, *new_filter;
224:
225: if (!text)
226: return;
227: g_assert(data);
228: filter_te = gtk_object_get_data(GTK_OBJECT(data), E_DFILTER_TE_KEY);
229: g_assert(filter_te);
230:
231: cur_filter = gtk_editable_get_chars(GTK_EDITABLE(filter_te), 0, -1);
232:
233: switch (action&MATCH_SELECTED_MASK) {
234:
235: case MATCH_SELECTED_REPLACE:
236: new_filter = g_strdup(text);
237: break;
238:
239: case MATCH_SELECTED_AND:
240: if ((!cur_filter) || (0 == strlen(cur_filter)))
241: new_filter = g_strdup(text);
242: else
243: new_filter = g_strconcat("(", cur_filter, ") && (", text, ")", NULL);
244: break;
245:
246: case MATCH_SELECTED_OR:
247: if ((!cur_filter) || (0 == strlen(cur_filter)))
248: new_filter = g_strdup(text);
249: else
250: new_filter = g_strconcat("(", cur_filter, ") || (", text, ")", NULL);
251: break;
252:
253: case MATCH_SELECTED_NOT:
254: new_filter = g_strconcat("!(", text, ")", NULL);
255: break;
256:
257: case MATCH_SELECTED_AND_NOT:
258: if ((!cur_filter) || (0 == strlen(cur_filter)))
259: new_filter = g_strconcat("!(", text, ")", NULL);
260: else
261: new_filter = g_strconcat("(", cur_filter, ") && !(", text, ")", NULL);
262: break;
263:
264: case MATCH_SELECTED_OR_NOT:
265: if ((!cur_filter) || (0 == strlen(cur_filter)))
266: new_filter = g_strconcat("!(", text, ")", NULL);
267: else
268: new_filter = g_strconcat("(", cur_filter, ") || !(", text, ")", NULL);
269: break;
270:
271: default:
272: g_assert_not_reached();
273: new_filter = NULL;
274: break;
275: }
276:
277: /* Free up the copy we got of the old filter text. */
278: g_free(cur_filter);
279:
280: /* create a new one and set the display filter entry accordingly */
281: gtk_entry_set_text(GTK_ENTRY(filter_te), new_filter);
282:
283: /* Run the display filter so it goes in effect. */
284: if (action&MATCH_SELECTED_APPLY_NOW)
285: filter_packets(&cfile, new_filter);
286:
287: /* Free up the new filter text. */
288: g_free(new_filter);
289:
290: /* Free up the generated text we were handed. */
291: g_free(text);
292: }
293:
294: void
295: match_selected_cb_replace(GtkWidget *w, gpointer data)
296: {
297: if (finfo_selected)
298: match_selected_cb_do((data ? data : w),
299: MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
300: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
301: }
302:
303: void
304: match_selected_cb_and(GtkWidget *w, gpointer data)
305: {
306: if (finfo_selected)
307: match_selected_cb_do((data ? data : w),
308: MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
309: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
310: }
311:
312: void
313: match_selected_cb_or(GtkWidget *w, gpointer data)
314: {
315: if (finfo_selected)
316: match_selected_cb_do((data ? data : w),
317: MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
318: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
319: }
320:
321: void
322: match_selected_cb_not(GtkWidget *w, gpointer data)
323: {
324: if (finfo_selected)
325: match_selected_cb_do((data ? data : w),
326: MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
327: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
328: }
329:
330: void
331: match_selected_cb_and_not(GtkWidget *w, gpointer data)
332: {
333: if (finfo_selected)
334: match_selected_cb_do((data ? data : w),
335: MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
336: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
337: }
338:
339: void
340: match_selected_cb_or_not(GtkWidget *w, gpointer data)
341: {
342: if (finfo_selected)
343: match_selected_cb_do((data ? data : w),
344: MATCH_SELECTED_OR_NOT,
345: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
346: }
347:
348: void
349: prepare_selected_cb_replace(GtkWidget *w, gpointer data)
350: {
351: if (finfo_selected)
352: match_selected_cb_do((data ? data : w),
353: MATCH_SELECTED_REPLACE,
354: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
355: }
356:
357: void
358: prepare_selected_cb_and(GtkWidget *w, gpointer data)
359: {
360: if (finfo_selected)
361: match_selected_cb_do((data ? data : w),
362: MATCH_SELECTED_AND,
363: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
364: }
365:
366: void
367: prepare_selected_cb_or(GtkWidget *w, gpointer data)
368: {
369: if (finfo_selected)
370: match_selected_cb_do((data ? data : w),
371: MATCH_SELECTED_OR,
372: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
373: }
374:
375: void
376: prepare_selected_cb_not(GtkWidget *w, gpointer data)
377: {
378: if (finfo_selected)
379: match_selected_cb_do((data ? data : w),
380: MATCH_SELECTED_NOT,
381: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
382: }
383:
384: void
385: prepare_selected_cb_and_not(GtkWidget *w, gpointer data)
386: {
387: if (finfo_selected)
388: match_selected_cb_do((data ? data : w),
389: MATCH_SELECTED_AND_NOT,
390: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
391: }
392:
393: void
394: prepare_selected_cb_or_not(GtkWidget *w, gpointer data)
395: {
396: if (finfo_selected)
397: match_selected_cb_do((data ? data : w),
398: MATCH_SELECTED_OR_NOT,
399: proto_alloc_dfilter_string(finfo_selected, cfile.pd));
400: }
401:
402: static gchar *
403: get_text_from_packet_list(gpointer data)
404: {
405: gint row = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_ROW_KEY);
406: gint column = (gint)gtk_object_get_data(GTK_OBJECT(data), E_MPACKET_LIST_COL_KEY);
407: frame_data *fdata = (frame_data *)gtk_clist_get_row_data(GTK_CLIST(packet_list), row);
408: epan_dissect_t *edt;
409: gchar *buf=NULL;
410: int len;
411: int err;
412:
413: if (fdata != NULL) {
414: /* XXX - do something with "err" */
415: wtap_seek_read(cfile.wth, fdata->file_off, &cfile.pseudo_header,
416: cfile.pd, fdata->cap_len, &err);
417:
418: edt = epan_dissect_new(FALSE, FALSE);
419: epan_dissect_run(edt, &cfile.pseudo_header, cfile.pd, fdata,
420: &cfile.cinfo);
421: epan_dissect_fill_in_columns(edt);
422:
423: if (strlen(cfile.cinfo.col_expr[column]) != 0 &&
424: strlen(cfile.cinfo.col_expr_val[column]) != 0) {
425: len = strlen(cfile.cinfo.col_expr[column]) +
426: strlen(cfile.cinfo.col_expr_val[column]) + 5;
427: buf = g_malloc0(len);
428: snprintf(buf, len, "%s == %s", cfile.cinfo.col_expr[column],
429: cfile.cinfo.col_expr_val[column]);
430: }
431:
432: epan_dissect_free(edt);
433: }
434:
435: return buf;
436: }
437:
438: void
439: match_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
440: {
441: match_selected_cb_do(data,
442: MATCH_SELECTED_REPLACE|MATCH_SELECTED_APPLY_NOW,
443: get_text_from_packet_list(data));
444: }
445:
446: void
447: match_selected_cb_and2(GtkWidget *w _U_, gpointer data)
448: {
449: match_selected_cb_do(data,
450: MATCH_SELECTED_AND|MATCH_SELECTED_APPLY_NOW,
451: get_text_from_packet_list(data));
452: }
453:
454: void
455: match_selected_cb_or2(GtkWidget *w _U_, gpointer data)
456: {
457: match_selected_cb_do(data,
458: MATCH_SELECTED_OR|MATCH_SELECTED_APPLY_NOW,
459: get_text_from_packet_list(data));
460: }
461:
462: void
463: match_selected_cb_not2(GtkWidget *w _U_, gpointer data)
464: {
465: match_selected_cb_do(data,
466: MATCH_SELECTED_NOT|MATCH_SELECTED_APPLY_NOW,
467: get_text_from_packet_list(data));
468: }
469:
470: void
471: match_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
472: {
473: match_selected_cb_do(data,
474: MATCH_SELECTED_AND_NOT|MATCH_SELECTED_APPLY_NOW,
475: get_text_from_packet_list(data));
476: }
477:
478: void
479: match_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
480: {
481: match_selected_cb_do(data,
482: MATCH_SELECTED_OR_NOT|MATCH_SELECTED_APPLY_NOW,
483: get_text_from_packet_list(data));
484: }
485:
486: void
487: prepare_selected_cb_replace2(GtkWidget *w _U_, gpointer data)
488: {
489: match_selected_cb_do(data,
490: MATCH_SELECTED_REPLACE,
491: get_text_from_packet_list(data));
492: }
493:
494: void
495: prepare_selected_cb_and2(GtkWidget *w _U_, gpointer data)
496: {
497: match_selected_cb_do(data,
498: MATCH_SELECTED_AND,
499: get_text_from_packet_list(data));
500: }
501:
502: void
503: prepare_selected_cb_or2(GtkWidget *w _U_, gpointer data)
504: {
505: match_selected_cb_do(data,
506: MATCH_SELECTED_OR,
507: get_text_from_packet_list(data));
508: }
509:
510: void
511: prepare_selected_cb_not2(GtkWidget *w _U_, gpointer data)
512: {
513: match_selected_cb_do(data,
514: MATCH_SELECTED_NOT,
515: get_text_from_packet_list(data));
516: }
517:
518: void
519: prepare_selected_cb_and_not2(GtkWidget *w _U_, gpointer data)
520: {
521: match_selected_cb_do(data,
522: MATCH_SELECTED_AND_NOT,
523: get_text_from_packet_list(data));
524: }
525:
526: void
527: prepare_selected_cb_or_not2(GtkWidget *w _U_, gpointer data)
528: {
529: match_selected_cb_do(data,
530: MATCH_SELECTED_OR_NOT,
531: get_text_from_packet_list(data));
532: }
533:
534: /* Run the current display filter on the current packet set, and
535: redisplay. */
536: static void
537: filter_activate_cb(GtkWidget *w, gpointer data)
538: {
539: GtkCombo *filter_cm = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_CM_KEY);
540: GList *filter_list = gtk_object_get_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY);
541: GList *li;
542: gboolean add_filter = TRUE;
543: gboolean free_filter = TRUE;
544: char *s;
545:
546: g_assert(data);
547: s = g_strdup(gtk_entry_get_text(GTK_ENTRY(data)));
548:
549: /* GtkCombos don't let us get at their list contents easily, so we maintain
550: our own filter list, and feed it to gtk_combo_set_popdown_strings when
551: a new filter is added. */
552: if (filter_packets(&cfile, s)) {
553: li = g_list_first(filter_list);
554: while (li) {
555: if (li->data && strcmp(s, li->data) == 0)
556: add_filter = FALSE;
557: li = li->next;
558: }
559:
560: if (add_filter) {
561: free_filter = FALSE;
562: filter_list = g_list_append(filter_list, s);
563: gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
564: gtk_combo_set_popdown_strings(filter_cm, filter_list);
565: gtk_entry_set_text(GTK_ENTRY(filter_cm->entry), g_list_last(filter_list)->data);
566: }
567: }
568: if (free_filter)
569: g_free(s);
570: }
571:
572: /* redisplay with no display filter */
573: static void
574: filter_reset_cb(GtkWidget *w, gpointer data _U_)
575: {
576: GtkWidget *filter_te = NULL;
577:
578: if ((filter_te = gtk_object_get_data(GTK_OBJECT(w), E_DFILTER_TE_KEY))) {
579: gtk_entry_set_text(GTK_ENTRY(filter_te), "");
580: }
581: filter_packets(&cfile, NULL);
582: }
583:
584: /* GTKClist compare routine, overrides default to allow numeric comparison */
585: static gint
586: packet_list_compare(GtkCList *clist, gconstpointer ptr1, gconstpointer ptr2)
587: {
588: /* Get row text strings */
589: char *text1 = GTK_CELL_TEXT (((GtkCListRow *)ptr1)->cell[clist->sort_column])->text;
590: char *text2 = GTK_CELL_TEXT (((GtkCListRow *)ptr2)->cell[clist->sort_column])->text;
591:
592: /* Attempt to convert to numbers */
593: double num1 = atof(text1);
594: double num2 = atof(text2);
595:
596: gint col_fmt = cfile.cinfo.col_fmt[clist->sort_column];
597:
598: if ((col_fmt == COL_NUMBER) || (col_fmt == COL_REL_TIME) || (col_fmt == COL_DELTA_TIME) ||
599: ((col_fmt == COL_CLS_TIME) && (timestamp_type == RELATIVE)) ||
600: ((col_fmt == COL_CLS_TIME) && (timestamp_type == DELTA)) ||
601: (col_fmt == COL_UNRES_SRC_PORT) || (col_fmt == COL_UNRES_DST_PORT) ||
602: ((num1 != 0) && (num2 != 0) && ((col_fmt == COL_DEF_SRC_PORT) || (col_fmt == COL_RES_SRC_PORT) ||
603: (col_fmt == COL_DEF_DST_PORT) || (col_fmt == COL_RES_DST_PORT))) ||
604: (col_fmt == COL_PACKET_LENGTH)) {
605:
606: /* Compare numeric column */
607:
608: if (num1 < num2)
609: return -1;
610: else if (num1 > num2)
611: return 1;
612: else
613: return 0;
614: }
615:
616: else {
617:
618: /* Compare text column */
619: if (!text2)
620: return (text1 != NULL);
621:
622: if (!text1)
623: return -1;
624:
625: return strcmp(text1, text2);
626: }
627: }
628:
629: /* What to do when a column is clicked */
630: static void
631: packet_list_click_column_cb(GtkCList *clist, gint column, gpointer data)
632: {
633: column_arrows *col_arrows = (column_arrows *) data;
634: int i;
635:
636: gtk_clist_freeze(clist);
637:
638: for (i = 0; i < cfile.cinfo.num_cols; i++) {
639: gtk_widget_hide(col_arrows[i].ascend_pm);
640: gtk_widget_hide(col_arrows[i].descend_pm);
641: }
642:
643: if (column == clist->sort_column) {
644: if (clist->sort_type == GTK_SORT_ASCENDING) {
645: clist->sort_type = GTK_SORT_DESCENDING;
646: gtk_widget_show(col_arrows[column].descend_pm);
647: } else {
648: clist->sort_type = GTK_SORT_ASCENDING;
649: gtk_widget_show(col_arrows[column].ascend_pm);
650: }
651: }
652: else {
653: clist->sort_type = GTK_SORT_ASCENDING;
654: gtk_widget_show(col_arrows[column].ascend_pm);
655: gtk_clist_set_sort_column(clist, column);
656: }
657: gtk_clist_thaw(clist);
658:
659: gtk_clist_sort(clist);
660: }
661:
662: /* mark packets */
663: static void
664: set_frame_mark(gboolean set, frame_data *frame, gint row) {
665: GdkColor fg, bg;
666:
667: if (row == -1)
668: return;
669: if (set) {
670: mark_frame(&cfile, frame);
671: color_t_to_gdkcolor(&fg, &prefs.gui_marked_fg);
672: color_t_to_gdkcolor(&bg, &prefs.gui_marked_bg);
673: } else {
674: unmark_frame(&cfile, frame);
675: fg = BLACK;
676: bg = WHITE;
677: }
678: file_set_save_marked_sensitive();
679: gtk_clist_set_background(GTK_CLIST(packet_list), row, &bg);
680: gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &fg);
681: }
682:
683: static void
684: packet_list_button_pressed_cb(GtkWidget *w, GdkEvent *event, gpointer data _U_) {
685:
686: GdkEventButton *event_button = (GdkEventButton *)event;
687: gint row, column;
688:
689: if (w == NULL || event == NULL)
690: return;
691:
692: if (event->type == GDK_BUTTON_PRESS && event_button->button == 2 &&
693: gtk_clist_get_selection_info(GTK_CLIST(w), event_button->x, event_button->y,
694: &row, &column)) {
695: frame_data *fdata = (frame_data *) gtk_clist_get_row_data(GTK_CLIST(w), row);
696: set_frame_mark(!fdata->flags.marked, fdata, row);
697: }
698: }
699:
700: void mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) {
701: if (cfile.current_frame) {
702: /* XXX hum, should better have a "cfile->current_row" here ... */
703: set_frame_mark(!cfile.current_frame->flags.marked,
704: cfile.current_frame,
705: gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
706: cfile.current_frame));
707: }
708: }
709:
710: static void mark_all_frames(gboolean set) {
711: frame_data *fdata;
712: for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
713: set_frame_mark(set,
714: fdata,
715: gtk_clist_find_row_from_data(GTK_CLIST(packet_list), fdata));
716: }
717: }
718:
719: void update_marked_frames(void) {
720: frame_data *fdata;
721: if (cfile.plist == NULL) return;
722: for (fdata = cfile.plist; fdata != NULL; fdata = fdata->next) {
723: if (fdata->flags.marked)
724: set_frame_mark(TRUE,
725: fdata,
726: gtk_clist_find_row_from_data(GTK_CLIST(packet_list),
727: fdata));
728: }
729: }
730:
731: void mark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
732: mark_all_frames(TRUE);
733: }
734:
735: void unmark_all_frames_cb(GtkWidget *w _U_, gpointer data _U_) {
736: mark_all_frames(FALSE);
737: }
738:
739: /* What to do when a list item is selected/unselected */
740: static void
741: packet_list_select_cb(GtkWidget *w _U_, gint row, gint col _U_, gpointer evt _U_) {
742:
743: /* Remove the hex display tabbed pages */
744: while( (gtk_notebook_get_nth_page( GTK_NOTEBOOK(byte_nb_ptr), 0)))
745: gtk_notebook_remove_page( GTK_NOTEBOOK(byte_nb_ptr), 0);
746:
747: select_packet(&cfile, row);
748: }
749:
750:
751: static void
752: packet_list_unselect_cb(GtkWidget *w _U_, gint row _U_, gint col _U_, gpointer evt _U_) {
753:
754: unselect_packet(&cfile);
755: }
756:
757:
758: static void
759: tree_view_select_row_cb(GtkCTree *ctree, GList *node, gint column _U_, gpointer user_data _U_)
760: {
761: field_info *finfo;
762: gchar *help_str = NULL;
763: gboolean has_blurb = FALSE;
764: guint length = 0, byte_len;
765: GtkWidget *byte_view;
766: const guint8 *byte_data;
767:
768: g_assert(node);
769: finfo = gtk_ctree_node_get_row_data( ctree, GTK_CTREE_NODE(node) );
770: if (!finfo) return;
771:
772: set_notebook_page(byte_nb_ptr, finfo->ds_tvb);
773:
774: byte_view = get_notebook_bv_ptr(byte_nb_ptr);
775: byte_data = get_byte_view_data_and_length(byte_view, &byte_len);
776: g_assert(byte_data != NULL);
777:
778: finfo_selected = finfo;
779: set_menus_for_selected_tree_row(TRUE);
780:
781: if (finfo->hfinfo) {
782: if (finfo->hfinfo->blurb != NULL &&
783: finfo->hfinfo->blurb[0] != '\0') {
784: has_blurb = TRUE;
785: length = strlen(finfo->hfinfo->blurb);
786: } else {
787: length = strlen(finfo->hfinfo->name);
788: }
789: statusbar_pop_field_msg(); /* get rid of current help msg */
790: if (length) {
791: length += strlen(finfo->hfinfo->abbrev) + 10;
792: help_str = g_malloc(sizeof(gchar) * length);
793: sprintf(help_str, "%s (%s)",
794: (has_blurb) ? finfo->hfinfo->blurb : finfo->hfinfo->name,
795: finfo->hfinfo->abbrev);
796: statusbar_push_field_msg(help_str);
797: g_free(help_str);
798: } else {
799: /*
800: * Don't show anything if the field name is zero-length;
801: * the pseudo-field for "proto_tree_add_text()" is such
802: * a field, and we don't want "Text (text)" showing up
803: * on the status line if you've selected such a field.
804: *
805: * XXX - there are zero-length fields for which we *do*
806: * want to show the field name.
807: *
808: * XXX - perhaps the name and abbrev field should be null
809: * pointers rather than null strings for that pseudo-field,
810: * but we'd have to add checks for null pointers in some
811: * places if we did that.
812: *
813: * Or perhaps protocol tree items added with
814: * "proto_tree_add_text()" should have -1 as the field index,
815: * with no pseudo-field being used, but that might also
816: * require special checks for -1 to be added.
817: */
818: statusbar_push_field_msg("");
819: }
820: }
821:
822: packet_hex_print(GTK_TEXT(byte_view), byte_data, cfile.current_frame,
823: finfo, byte_len);
824: }
825:
826: static void
827: tree_view_unselect_row_cb(GtkCTree *ctree _U_, GList *node _U_, gint column _U_, gpointer user_data _U_)
828: {
829: GtkWidget *byte_view;
830: const guint8 *data;
831: guint len;
832:
833: /*
834: * Which byte view is displaying the current protocol tree
835: * row's data?
836: */
837: byte_view = get_notebook_bv_ptr(byte_nb_ptr);
838: if (byte_view == NULL)
839: return; /* none */
840:
841: data = "" &len);
842: if (data == NULL)
843: return; /* none */
844:
845: unselect_field();
846: packet_hex_print(GTK_TEXT(byte_view), data, cfile.current_frame,
847: NULL, len);
848: }
849:
850: void collapse_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
851: if (cfile.edt->tree)
852: collapse_all_tree(cfile.edt->tree, tree_view);
853: }
854:
855: void expand_all_cb(GtkWidget *widget _U_, gpointer data _U_) {
856: if (cfile.edt->tree)
857: expand_all_tree(cfile.edt->tree, tree_view);
858: }
859:
860: void resolve_name_cb(GtkWidget *widget _U_, gpointer data _U_) {
861: if (cfile.edt->tree) {
862: guint32 tmp = g_resolv_flags;
863: g_resolv_flags = RESOLV_ALL;
864: proto_tree_draw(cfile.edt->tree, tree_view);
865: g_resolv_flags = tmp;
866: }
867: }
868:
869: /* Set the selection mode of the packet list window. */
870: void
871: set_plist_sel_browse(gboolean val)
872: {
873: gboolean old_val;
874:
875: old_val =
876: (GTK_CLIST(packet_list)->selection_mode == GTK_SELECTION_SINGLE);
877:
878: if (val == old_val) {
879: /*
880: * The mode isn't changing, so don't do anything.
881: * In particular, don't gratuitiously unselect the
882: * current packet.
883: *
884: * XXX - why do we have to unselect the current packet
885: * ourselves? The documentation for the GtkCList at
886: *
887: * http://developer.gnome.org/doc/API/gtk/gtkclist.html
888: *
889: * says "Note that setting the widget's selection mode to
890: * one of GTK_SELECTION_BROWSE or GTK_SELECTION_SINGLE will
891: * cause all the items in the GtkCList to become deselected."
892: */
893: return;
894: }
895:
896: if (finfo_selected)
897: unselect_packet(&cfile);
898:
899: /* Yeah, GTK uses "browse" in the case where we do not, but oh well. I think
900: * "browse" in Ethereal makes more sense than "SINGLE" in GTK+ */
901: if (val) {
902: gtk_clist_set_selection_mode(GTK_CLIST(packet_list), GTK_SELECTION_SINGLE);
903: }
904: else {
905: gtk_clist_set_selection_mode(GTK_CLIST(packet_list), GTK_SELECTION_BROWSE);
906: }
907: }
908:
909: /* Set the font of the packet list window. */
910: void
911: set_plist_font(GdkFont *font)
912: {
913: GtkStyle *style;
914: int i;
915:
916: style = gtk_style_new();
917: gdk_font_unref(style->font);
918: style->font = font;
919: gdk_font_ref(font);
920:
921: gtk_widget_set_style(packet_list, style);
922:
923: /* Compute static column sizes to use during a "-S" capture, so that
924: the columns don't resize during a live capture. */
925: for (i = 0; i < cfile.cinfo.num_cols; i++) {
926: cfile.cinfo.col_width[i] = gdk_string_width(font,
927: get_column_longest_string(get_column_format(i)));
928: }
929: }
930:
931: /*
932: * Push a message referring to file access onto the statusbar.
933: */
934: void
935: statusbar_push_file_msg(gchar *msg)
936: {
937: gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, msg);
938: }
939:
940: /*
941: * Pop a message referring to file access off the statusbar.
942: */
943: void
944: statusbar_pop_file_msg(void)
945: {
946: gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
947: }
948:
949: /*
950: * XXX - do we need multiple statusbar contexts?
951: */
952:
953: /*
954: * Push a message referring to the currently-selected field onto the statusbar.
955: */
956: void
957: statusbar_push_field_msg(gchar *msg)
958: {
959: gtk_statusbar_push(GTK_STATUSBAR(info_bar), help_ctx, msg);
960: }
961:
962: /*
963: * Pop a message referring to the currently-selected field off the statusbar.
964: */
965: void
966: statusbar_pop_field_msg(void)
967: {
968: gtk_statusbar_pop(GTK_STATUSBAR(info_bar), help_ctx);
969: }
970:
971: static gboolean
972: do_quit(void)
973: {
974: /* XXX - should we check whether the capture file is an
975: unsaved temporary file for a live capture and, if so,
976: pop up a "do you want to exit without saving the capture
977: file?" dialog, and then just return, leaving said dialog
978: box to forcibly quit if the user clicks "OK"?
979:
980: If so, note that this should be done in a subroutine that
981: returns TRUE if we do so, and FALSE otherwise, and if it
982: returns TRUE we should return TRUE without nuking anything.
983:
984: Note that, if we do that, we might also want to check if
985: an "Update list of packets in real time" capture is in
986: progress and, if so, ask whether they want to terminate
987: the capture and discard it, and return TRUE, before nuking
988: any child capture, if they say they don't want to do so. */
989:
990: #ifdef HAVE_LIBPCAP
991: /* Nuke any child capture in progress. */
992: kill_capture_child();
993: #endif
994:
995: /* Are we in the middle of reading a capture? */
996: if (cfile.state == FILE_READ_IN_PROGRESS) {
997: /* Yes, so we can't just close the file and quit, as
998: that may yank the rug out from under the read in
999: progress; instead, just set the state to
1000: "FILE_READ_ABORTED" and return - the code doing the read
1001: will check for that and, if it sees that, will clean
1002: up and quit. */
1003: cfile.state = FILE_READ_ABORTED;
1004:
1005: /* Say that the window should *not* be deleted;
1006: that'll be done by the code that cleans up. */
1007: return TRUE;
1008: } else {
1009: /* Close any capture file we have open; on some OSes, you
1010: can't unlink a temporary capture file if you have it
1011: open.
1012: "close_cap_file()" will unlink it after closing it if
1013: it's a temporary file.
1014:
1015: We do this here, rather than after the main loop returns,
1016: as, after the main loop returns, the main window may have
1017: been destroyed (if this is called due to a "destroy"
1018: even on the main window rather than due to the user
1019: selecting a menu item), and there may be a crash
1020: or other problem when "close_cap_file()" tries to
1021: clean up stuff in the main window.
1022:
1023: XXX - is there a better place to put this?
1024: Or should we have a routine that *just* closes the
1025: capture file, and doesn't do anything with the UI,
1026: which we'd call here, and another routine that
1027: calls that routine and also cleans up the UI, which
1028: we'd call elsewhere? */
1029: close_cap_file(&cfile);
1030:
1031: /* Exit by leaving the main loop, so that any quit functions
1032: we registered get called. */
1033: gtk_main_quit();
1034:
1035: /* Say that the window should be deleted. */
1036: return FALSE;
1037: }
1038: }
1039:
1040: static gboolean
1041: main_window_delete_event_cb(GtkWidget *widget _U_, GdkEvent *event _U_, gpointer data _U_)
1042: {
1043: gint desk_x, desk_y;
1044:
1045: /* Try to grab our geometry */
1046: gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
1047: if (gdk_window_get_deskrelative_origin(top_level->window,
1048: &desk_x, &desk_y)) {
1049: if (desk_x <= root_x && desk_y <= root_y) {
1050: root_x = desk_x;
1051: root_y = desk_y;
1052: }
1053: }
1054:
1055: /* XXX - Is this the "approved" method? */
1056: gdk_window_get_size(top_level->window, &top_width, &top_height);
1057:
1058: /* "do_quit()" indicates whether the main window should be deleted. */
1059: return do_quit();
1060: }
1061:
1062: void
1063: file_quit_cmd_cb (GtkWidget *widget _U_, gpointer data _U_)
1064: {
1065: do_quit();
1066: }
1067:
1068: static void
1069: print_usage(gboolean print_ver) {
1070:
1071: if (print_ver) {
1072: fprintf(stderr, "This is GNU " PACKAGE " " VERSION ", compiled %s\n",
1073: comp_info_str->str);
1074: }
1075: #ifdef HAVE_LIBPCAP
1076: fprintf(stderr, "\n%s [ -vh ] [ -klpQS ] [ -a <capture autostop condition> ] ...\n",
1077: PACKAGE);
1078: fprintf(stderr, "\t[ -b <number of ringbuffer files> ] [ -B <byte view height> ]\n");
1079: fprintf(stderr, "\t[ -c <count> ] [ -f <capture filter> ] [ -i <interface> ]\n");
1080: fprintf(stderr, "\t[ -m <medium font> ] [ -n ] [ -N <resolving> ]\n");
1081: fprintf(stderr, "\t[ -o <preference setting> ] ... [ -P <packet list height> ]\n");
1082: fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -s <snaplen> ] \n");
1083: fprintf(stderr, "\t[ -t <time stamp format> ] [ -T <tree view height> ]\n");
1084: fprintf(stderr, "\t[ -w <savefile> ] [ <infile> ]\n");
1085: #else
1086: fprintf(stderr, "\n%s [ -vh ] [ -B <byte view height> ] [ -m <medium font> ]\n",
1087: PACKAGE);
1088: fprintf(stderr, "\t[ -n ] [ -N <resolving> ]\n");
1089: fprintf(stderr, "\t[ -o <preference setting> ... [ -P <packet list height> ]\n");
1090: fprintf(stderr, "\t[ -r <infile> ] [ -R <read filter> ] [ -t <time stamp format> ]\n");
1091: fprintf(stderr, "\t[ -T <tree view height> ] [ <infile> ]\n");
1092: #endif
1093: }
1094:
1095: static void
1096: show_version(void)
1097: {
1098: #ifdef WIN32
1099: create_console();
1100: #endif
1101:
1102: printf("%s %s, %s\n", PACKAGE, VERSION, comp_info_str->str);
1103: }
1104:
1105: static int
1106: get_positive_int(const char *string, const char *name)
1107: {
1108: long number;
1109: char *p;
1110:
1111: number = strtol(string, &p, 10);
1112: if (p == string || *p != '\0') {
1113: fprintf(stderr, "ethereal: The specified %s \"%s\" is not a decimal number\n",
1114: name, string);
1115: exit(1);
1116: }
1117: if (number < 0) {
1118: fprintf(stderr, "ethereal: The specified %s \"%s\" is a negative number\n",
1119: name, string);
1120: exit(1);
1121: }
1122: if (number == 0) {
1123: fprintf(stderr, "ethereal: The specified %s \"%s\" is zero\n",
1124: name, string);
1125: exit(1);
1126: }
1127: if (number > INT_MAX) {
1128: fprintf(stderr, "ethereal: The specified %s \"%s\" is too large (greater than %d)\n",
1129: name, string, INT_MAX);
1130: exit(1);
1131: }
1132: return number;
1133: }
1134:
1135: #ifdef HAVE_LIBPCAP
1136: /*
1137: * Given a string of the form "<autostop criterion>:<value>", as might appear
1138: * as an argument to a "-a" option, parse it and set the criterion in
1139: * question. Return an indication of whether it succeeded or failed
1140: * in some fashion.
1141: */
1142: static gboolean
1143: set_autostop_criterion(const char *autostoparg)
1144: {
1145: u_char *p, *colonp;
1146:
1147: colonp = strchr(autostoparg, ':');
1148: if (colonp == NULL)
1149: return FALSE;
1150:
1151: p = colonp;
1152: *p++ = '\0';
1153:
1154: /*
1155: * Skip over any white space (there probably won't be any, but
1156: * as we allow it in the preferences file, we might as well
1157: * allow it here).
1158: */
1159: while (isspace(*p))
1160: p++;
1161: if (*p == '\0') {
1162: /*
1163: * Put the colon back, so if our caller uses, in an
1164: * error message, the string they passed us, the message
1165: * looks correct.
1166: */
1167: *colonp = ':';
1168: return FALSE;
1169: }
1170: if (strcmp(autostoparg,"duration") == 0) {
1171: capture_opts.has_autostop_duration = TRUE;
1172: capture_opts.autostop_duration = get_positive_int(p,"autostop duration");
1173: } else if (strcmp(autostoparg,"filesize") == 0) {
1174: capture_opts.has_autostop_filesize = TRUE;
1175: capture_opts.autostop_filesize = get_positive_int(p,"autostop filesize");
1176: } else {
1177: return FALSE;
1178: }
1179: *colonp = ':'; /* put the colon back */
1180: return TRUE;
1181: }
1182: #endif
1183:
1184: /* And now our feature presentation... [ fade to music ] */
1185: int
1186: main(int argc, char *argv[])
1187: {
1188: #ifdef HAVE_LIBPCAP
1189: char *command_name;
1190: #endif
1191: char *s;
1192: int i;
1193: int opt;
1194: extern char *optarg;
1195: gboolean arg_error = FALSE;
1196: #ifdef HAVE_LIBPCAP
1197: #ifdef HAVE_PCAP_VERSION
1198: extern char pcap_version[];
1199: #endif /* HAVE_PCAP_VERSION */
1200: #endif /* HAVE_LIBPCAP */
1201:
1202: #ifdef WIN32
1203: WSADATA wsaData;
1204: #endif
1205:
1206: char *gpf_path, *cf_path, *df_path;
1207: const char *pf_path;
1208: int gpf_open_errno, pf_open_errno, cf_open_errno, df_open_errno;
1209: int err;
1210: #ifdef HAVE_LIBPCAP
1211: gboolean start_capture = FALSE;
1212: gchar *save_file = NULL;
1213: GList *if_list;
1214: gchar err_str[PCAP_ERRBUF_SIZE];
1215: gboolean stats_known;
1216: struct pcap_stat stats;
1217: #else
1218: gboolean capture_option_specified = FALSE;
1219: #endif
1220: gint pl_size = 280, tv_size = 95, bv_size = 75;
1221: gchar *rc_file, *cf_name = NULL, *rfilter = NULL;
1222: dfilter_t *rfcode = NULL;
1223: gboolean rfilter_parse_failed = FALSE;
1224: e_prefs *prefs;
1225: char badopt;
1226: char *bold_font_name;
1227: gint desk_x, desk_y;
1228: gboolean prefs_write_needed = FALSE;
1229:
1230: #define OPTSTRING_INIT "a:b:B:c:f:hi:klm:nN:o:pP:Qr:R:Ss:t:T:w:v"
1231:
1232: #ifdef HAVE_LIBPCAP
1233: #ifdef WIN32
1234: #define OPTSTRING_CHILD "W:Z:"
1235: #else
1236: #define OPTSTRING_CHILD "W:"
1237: #endif /* WIN32 */
1238: #else
1239: #define OPTSTRING_CHILD ""
1240: #endif /* HAVE_LIBPCAP */
1241:
1242: char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_CHILD) - 1] =
1243: OPTSTRING_INIT;
1244:
1245: ethereal_path = argv[0];
1246:
1247: #ifdef WIN32
1248: /* Arrange that if we have no console window, and a GLib message logging
1249: routine is called to log a message, we pop up a console window.
1250:
1251: We do that by inserting our own handler for all messages logged
1252: to the default domain; that handler pops up a console if necessary,
1253: and then calls the default handler. */
1254: g_log_set_handler(NULL,
1255: G_LOG_LEVEL_ERROR|
1256: G_LOG_LEVEL_CRITICAL|
1257: G_LOG_LEVEL_WARNING|
1258: G_LOG_LEVEL_MESSAGE|
1259: G_LOG_LEVEL_INFO|
1260: G_LOG_LEVEL_DEBUG|
1261: G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION,
1262: console_log_handler, NULL);
1263: #endif
1264:
1265: #ifdef HAVE_LIBPCAP
1266: command_name = get_basename(ethereal_path);
1267: /* Set "capture_child" to indicate whether this is going to be a child
1268: process for a "-S" capture. */
1269: capture_child = (strcmp(command_name, CHILD_NAME) == 0);
1270: if (capture_child)
1271: strcat(optstring, OPTSTRING_CHILD);
1272: #endif
1273:
1274: /* Register all dissectors; we must do this before checking for the
1275: "-G" flag, as the "-G" flag dumps information registered by the
1276: dissectors, and we must do it before we read the preferences, in
1277: case any dissectors register preferences. */
1278: epan_init(PLUGIN_DIR,register_all_protocols,register_all_protocol_handoffs);
1279:
1280: /* Now register the preferences for any non-dissector modules.
1281: We must do that before we read the preferences as well. */
1282: prefs_register_modules();
1283:
1284: /* If invoked with the "-G" flag, we dump out information based on
1285: the argument to the "-G" flag; if no argument is specified,
1286: for backwards compatibility we dump out a glossary of display
1287: filter symbols.
1288:
1289: We must do this before calling "gtk_init()", because "gtk_init()"
1290: tries to open an X display, and we don't want to have to do any X
1291: stuff just to do a build.
1292:
1293: Given that we call "gtk_init()" before doing the regular argument
1294: list processing, so that it can handle X and GTK+ arguments and
1295: remove them from the list at which we look, this means we must do
1296: this before doing the regular argument list processing, as well.
1297:
1298: This means that:
1299:
1300: you must give the "-G" flag as the first flag on the command line;
1301:
1302: you must give it as "-G", nothing more, nothing less;
1303:
1304: the first argument after the "-G" flag, if present, will be used
1305: to specify the information to dump;
1306:
1307: arguments after that will not be used. */
1308: if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
1309: if (argc == 2)
1310: proto_registrar_dump_fields();
1311: else {
1312: if (strcmp(argv[2], "fields") == 0)
1313: proto_registrar_dump_fields();
1314: else if (strcmp(argv[2], "protocols") == 0)
1315: proto_registrar_dump_protocols();
1316: else {
1317: fprintf(stderr, "tethereal: Invalid \"%s\" option for -G flag\n",
1318: argv[2]);
1319: exit(1);
1320: }
1321: }
1322: exit(0);
1323: }
1324:
1325: /* Set the current locale according to the program environment.
1326: * We haven't localized anything, but some GTK widgets are localized
1327: * (the file selection dialogue, for example).
1328: * This also sets the C-language locale to the native environment. */
1329: gtk_set_locale();
1330:
1331: /* Let GTK get its args */
1332: gtk_init (&argc, &argv);
1333:
1334: /* Read the preference files. */
1335: prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
1336:
1337: #ifdef HAVE_LIBPCAP
1338: capture_opts.has_snaplen = FALSE;
1339: capture_opts.snaplen = MIN_PACKET_SIZE;
1340: capture_opts.has_autostop_count = FALSE;
1341: capture_opts.autostop_count = 1;
1342: capture_opts.has_autostop_duration = FALSE;
1343: capture_opts.autostop_duration = 1;
1344: capture_opts.has_autostop_filesize = FALSE;
1345: capture_opts.autostop_filesize = 1;
1346: capture_opts.ringbuffer_on = FALSE;
1347: capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
1348:
1349: /* If this is a capture child process, it should pay no attention
1350: to the "prefs.capture_prom_mode" setting in the preferences file;
1351: it should do what the parent process tells it to do, and if
1352: the parent process wants it not to run in promiscuous mode, it'll
1353: tell it so with a "-p" flag.
1354:
1355: Otherwise, set promiscuous mode from the preferences setting. */
1356: if (capture_child)
1357: capture_opts.promisc_mode = TRUE;
1358: else
1359: capture_opts.promisc_mode = prefs->capture_prom_mode;
1360:
1361: /* Set "Update list of packets in real time" mode from the preferences
1362: setting. */
1363: capture_opts.sync_mode = prefs->capture_real_time;
1364:
1365: /* And do the same for "Automatic scrolling in live capture" mode. */
1366: auto_scroll_live = prefs->capture_auto_scroll;
1367: #endif
1368:
1369: /* Set the name resolution code's flags from the preferences. */
1370: g_resolv_flags = prefs->name_resolve;
1371:
1372: /* Read the capture filter file. */
1373: read_filter_list(CFILTER_LIST, &cf_path, &cf_open_errno);
1374:
1375: /* Read the display filter file. */
1376: read_filter_list(DFILTER_LIST, &df_path, &df_open_errno);
1377:
1378: /* Initialize the capture file struct */
1379: cfile.plist = NULL;
1380: cfile.plist_end = NULL;
1381: cfile.wth = NULL;
1382: cfile.filename = NULL;
1383: cfile.user_saved = FALSE;
1384: cfile.is_tempfile = FALSE;
1385: cfile.rfcode = NULL;
1386: cfile.dfilter = NULL;
1387: cfile.dfcode = NULL;
1388: #ifdef HAVE_LIBPCAP
1389: cfile.cfilter = g_strdup(EMPTY_FILTER);
1390: #endif
1391: cfile.iface = NULL;
1392: cfile.save_file = NULL;
1393: cfile.save_file_fd = -1;
1394:
1395: cfile.ipaddr = NULL;
1396: cfile.has_ipaddr = FALSE;
1397: cfile.v5iface = NULL;
1398: cfile.has_v5iface = FALSE;
1399:
1394: cfile.has_snap = FALSE;
1395: cfile.snap = WTAP_MAX_PACKET_SIZE;
1396: cfile.count = 0;
1397: col_init(&cfile.cinfo, prefs->num_cols);
1398:
1399: /* Assemble the compile-time options */
1400: comp_info_str = g_string_new("");
1401:
1402: g_string_append(comp_info_str, "with ");
1403: g_string_sprintfa(comp_info_str,
1404: #ifdef GTK_MAJOR_VERSION
1405: "GTK+ %d.%d.%d", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
1406: GTK_MICRO_VERSION);
1407: #else
1408: "GTK+ (version unknown)");
1409: #endif
1410:
1411: g_string_append(comp_info_str, ", with ");
1412: g_string_sprintfa(comp_info_str,
1413: #ifdef GLIB_MAJOR_VERSION
1414: "GLib %d.%d.%d", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION,
1415: GLIB_MICRO_VERSION);
1416: #else
1417: "GLib (version unknown)");
1418: #endif
1419:
1420: #ifdef HAVE_LIBPCAP
1421: g_string_append(comp_info_str, ", with libpcap ");
1422: #ifdef HAVE_PCAP_VERSION
1423: g_string_append(comp_info_str, pcap_version);
1424: #else /* HAVE_PCAP_VERSION */
1425: g_string_append(comp_info_str, "(version unknown)");
1426: #endif /* HAVE_PCAP_VERSION */
1427: #else /* HAVE_LIBPCAP */
1428: g_string_append(comp_info_str, ", without libpcap");
1429: #endif /* HAVE_LIBPCAP */
1430:
1431: #ifdef HAVE_LIBZ
1432: g_string_append(comp_info_str, ", with libz ");
1433: #ifdef ZLIB_VERSION
1434: g_string_append(comp_info_str, ZLIB_VERSION);
1435: #else /* ZLIB_VERSION */
1436: g_string_append(comp_info_str, "(version unknown)");
1437: #endif /* ZLIB_VERSION */
1438: #else /* HAVE_LIBZ */
1439: g_string_append(comp_info_str, ", without libz");
1440: #endif /* HAVE_LIBZ */
1441:
1442: /* Oh, this is pretty */
1443: #ifdef HAVE_UCD_SNMP
1444: g_string_append(comp_info_str, ", with UCD SNMP ");
1445: #ifdef HAVE_UCD_SNMP_VERSION_H
1446: g_string_append(comp_info_str, VersionInfo);
1447: #else /* HAVE_UCD_SNMP_VERSION_H */
1448: g_string_append(comp_info_str, "(version unknown)");
1449: #endif /* HAVE_UCD_SNMP_VERSION_H */
1450: #else /* no SNMP library */
1451: g_string_append(comp_info_str, ", without UCD SNMP");
1452: #endif
1453:
1454: /* Now get our args */
1455: while ((opt = getopt(argc, argv, optstring)) != -1) {
1456: switch (opt) {
1457: case 'a': /* autostop criteria */
1458: #ifdef HAVE_LIBPCAP
1459: if (set_autostop_criterion(optarg) == FALSE) {
1460: fprintf(stderr, "ethereal: Invalid or unknown -a flag \"%s\"\n", optarg);
1461: exit(1);
1462: }
1463: #else
1464: capture_option_specified = TRUE;
1465: arg_error = TRUE;
1466: #endif
1467: break;
1468: case 'b': /* Ringbuffer option */
1469: #ifdef HAVE_LIBPCAP
1470: capture_opts.ringbuffer_on = TRUE;
1471: capture_opts.ringbuffer_num_files =
1472: get_positive_int(optarg, "number of ring buffer files");
1473: #else
1474: capture_option_specified = TRUE;
1475: arg_error = TRUE;
1476: #endif
1477: break;
1478: case 'B': /* Byte view pane height */
1479: bv_size = get_positive_int(optarg, "byte view pane height");
1480: break;
1481: case 'c': /* Capture xxx packets */
1482: #ifdef HAVE_LIBPCAP
1483: capture_opts.has_autostop_count = TRUE;
1484: capture_opts.autostop_count = get_positive_int(optarg, "packet count");
1485: #else
1486: capture_option_specified = TRUE;
1487: arg_error = TRUE;
1488: #endif
1489: break;
1490: case 'f':
1491: #ifdef HAVE_LIBPCAP
1492: if (cfile.cfilter)
1493: g_free(cfile.cfilter);
1494: cfile.cfilter = g_strdup(optarg);
1495: #else
1496: capture_option_specified = TRUE;
1497: arg_error = TRUE;
1498: #endif
1499: break;
1500: case 'h': /* Print help and exit */
1501: print_usage(TRUE);
1502: exit(0);
1503: break;
1504: case 'i': /* Use interface xxx */
1505: #ifdef HAVE_LIBPCAP
1506: cfile.iface = g_strdup(optarg);
1507: #else
1508: capture_option_specified = TRUE;
1509: arg_error = TRUE;
1510: #endif
1511: break;
1512: case 'k': /* Start capture immediately */
1513: #ifdef HAVE_LIBPCAP
1514: start_capture = TRUE;
1515: #else
1516: capture_option_specified = TRUE;
1517: arg_error = TRUE;
1518: #endif
1519: break;
1520: case 'l': /* Automatic scrolling in live capture mode */
1521: #ifdef HAVE_LIBPCAP
1522: auto_scroll_live = TRUE;
1523: #else
1524: capture_option_specified = TRUE;
1525: arg_error = TRUE;
1526: #endif
1527: break;
1528: case 'm': /* Fixed-width font for the display */
1529: if (prefs->gui_font_name != NULL)
1530: g_free(prefs->gui_font_name);
1531: prefs->gui_font_name = g_strdup(optarg);
1532: break;
1533: case 'n': /* No name resolution */
1534: g_resolv_flags = RESOLV_NONE;
1535: break;
1536: case 'N': /* Select what types of addresses/port #s to resolve */
1537: if (g_resolv_flags == RESOLV_ALL)
1538: g_resolv_flags = RESOLV_NONE;
1539: badopt = string_to_name_resolve(optarg, &g_resolv_flags);
1540: if (badopt != '\0') {
1541: fprintf(stderr, "ethereal: -N specifies unknown resolving option '%c'; valid options are 'm', 'n', and 't'\n",
1542: badopt);
1543: exit(1);
1544: }
1545: break;
1546: case 'o': /* Override preference from command line */
1547: switch (prefs_set_pref(optarg)) {
1548:
1549: case PREFS_SET_SYNTAX_ERR:
1550: fprintf(stderr, "ethereal: Invalid -o flag \"%s\"\n", optarg);
1551: exit(1);
1552: break;
1553:
1554: case PREFS_SET_NO_SUCH_PREF:
1555: case PREFS_SET_OBSOLETE:
1556: fprintf(stderr, "ethereal: -o flag \"%s\" specifies unknown preference\n",
1557: optarg);
1558: exit(1);
1559: break;
1560: }
1561: break;
1562: case 'p': /* Don't capture in promiscuous mode */
1563: #ifdef HAVE_LIBPCAP
1564: capture_opts.promisc_mode = FALSE;
1565: #else
1566: capture_option_specified = TRUE;
1567: arg_error = TRUE;
1568: #endif
1569: break;
1570: case 'P': /* Packet list pane height */
1571: pl_size = get_positive_int(optarg, "packet list pane height");
1572: break;
1573: case 'Q': /* Quit after capture (just capture to file) */
1574: #ifdef HAVE_LIBPCAP
1575: quit_after_cap = 1;
1576: start_capture = TRUE; /*** -Q implies -k !! ***/
1577: #else
1578: capture_option_specified = TRUE;
1579: arg_error = TRUE;
1580: #endif
1581: break;
1582: case 'r': /* Read capture file xxx */
1583: /* We may set "last_open_dir" to "cf_name", and if we change
1584: "last_open_dir" later, we free the old value, so we have to
1585: set "cf_name" to something that's been allocated. */
1586: cf_name = g_strdup(optarg);
1587: break;
1588: case 'R': /* Read file filter */
1589: rfilter = optarg;
1590: break;
1591: case 's': /* Set the snapshot (capture) length */
1592: #ifdef HAVE_LIBPCAP
1593: capture_opts.has_snaplen = TRUE;
1594: capture_opts.snaplen = get_positive_int(optarg, "snapshot length");
1595: #else
1596: capture_option_specified = TRUE;
1597: arg_error = TRUE;
1598: #endif
1599: break;
1600: case 'S': /* "Sync" mode: used for following file ala tail -f */
1601: #ifdef HAVE_LIBPCAP
1602: capture_opts.sync_mode = TRUE;
1603: #else
1604: capture_option_specified = TRUE;
1605: arg_error = TRUE;
1606: #endif
1607: break;
1608: case 't': /* Time stamp type */
1609: if (strcmp(optarg, "r") == 0)
1610: timestamp_type = RELATIVE;
1611: else if (strcmp(optarg, "a") == 0)
1612: timestamp_type = ABSOLUTE;
1613: else if (strcmp(optarg, "ad") == 0)
1614: timestamp_type = ABSOLUTE_WITH_DATE;
1615: else if (strcmp(optarg, "d") == 0)
1616: timestamp_type = DELTA;
1617: else {
1618: fprintf(stderr, "ethereal: Invalid time stamp type \"%s\"\n",
1619: optarg);
1620: fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
1621: fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
1622: exit(1);
1623: }
1624: break;
1625: case 'T': /* Tree view pane height */
1626: tv_size = get_positive_int(optarg, "tree view pane height");
1627: break;
1628: case 'v': /* Show version and exit */
1629: show_version();
1630: #ifdef WIN32
1631: if (console_was_created)
1632: destroy_console();
1633: #endif
1634: exit(0);
1635: break;
1636: case 'w': /* Write to capture file xxx */
1637: #ifdef HAVE_LIBPCAP
1638: save_file = g_strdup(optarg);
1639: #else
1640: capture_option_specified = TRUE;
1641: arg_error = TRUE;
1642: #endif
1643: break;
1644: #ifdef HAVE_LIBPCAP
1645: /* This is a hidden option supporting Sync mode, so we don't set
1646: * the error flags for the user in the non-libpcap case.
1647: */
1648: case 'W': /* Write to capture file FD xxx */
1649: cfile.save_file_fd = atoi(optarg);
1650: break;
1651: #endif
1652:
1653: #ifdef _WIN32
1654: #ifdef HAVE_LIBPCAP
1655: /* Hidden option supporting Sync mode */
1656: case 'Z': /* Write to pipe FD XXX */
1657: /* associate stdout with pipe */
1658: i = atoi(optarg);
1659: if (dup2(i, 1) < 0) {
1660: fprintf(stderr, "Unable to dup pipe handle\n");
1661: exit(1);
1662: }
1663: break;
1664: #endif /* HAVE_LIBPCAP */
1665: #endif /* _WIN32 */
1666:
1667: default:
1668: case '?': /* Bad flag - print usage message */
1669: arg_error = TRUE;
1670: break;
1671: }
1672: }
1673: argc -= optind;
1674: argv += optind;
1675: if (argc >= 1) {
1676: if (cf_name != NULL) {
1677: /*
1678: * Input file name specified with "-r" *and* specified as a regular
1679: * command-line argument.
1680: */
1681: arg_error = TRUE;
1682: } else {
1683: /*
1684: * Input file name not specified with "-r", and a command-line argument
1685: * was specified; treat it as the input file name.
1686: *
1687: * Yes, this is different from tethereal, where non-flag command-line
1688: * arguments are a filter, but this works better on GUI desktops
1689: * where a command can be specified to be run to open a particular
1690: * file - yes, you could have "-r" as the last part of the command,
1691: * but that's a bit ugly.
1692: */
1693: cf_name = g_strdup(argv[0]);
1694: }
1695: argc--;
1696: argv++;
1697: }
1698:
1699: if (argc != 0) {
1700: /*
1701: * Extra command line arguments were specified; complain.
1702: */
1703: fprintf(stderr, "Invalid argument: %s\n", argv[0]);
1704: arg_error = TRUE;
1705: }
1706: if (arg_error) {
1707: print_usage(FALSE);
1708: exit(1);
1709: }
1710:
1711: #ifdef HAVE_LIBPCAP
1712: if (capture_opts.ringbuffer_on) {
1713: /* Ring buffer works only under certain conditions:
1714: a) ring buffer does not work with temporary files;
1715: b) sync_mode and capture_opts.ringbuffer_on are mutually exclusive -
1716: sync_mode takes precedence;
1717: c) it makes no sense to enable the ring buffer if the maximum
1718: file size is set to "infinite". */
1719: if (cfile.save_file == NULL) {
1720: fprintf(stderr, "ethereal: Ring buffer requested, but capture isn't being saved to a permanent file.\n");
1721: capture_opts.ringbuffer_on = FALSE;
1722: }
1723: if (capture_opts.sync_mode) {
1724: fprintf(stderr, "ethereal: Ring buffer requested, but an \"Update list of packets in real time\" capture is being done.\n");
1725: capture_opts.ringbuffer_on = FALSE;
1726: }
1727: if (!capture_opts.has_autostop_filesize) {
1728: fprintf(stderr, "ethereal: Ring buffer requested, but no maximum capture file size was specified.\n");
1729: capture_opts.ringbuffer_on = FALSE;
1730: }
1731: }
1732: #endif
1733:
1734: #ifdef WIN32
1735: /* Load wpcap if possible */
1736: load_wpcap();
1737:
1738: /* Start windows sockets */
1739: WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
1740: #endif
1741:
1742: /* Notify all registered modules that have had any of their preferences
1743: changed either from one of the preferences file or from the command
1744: line that its preferences have changed. */
1745: prefs_apply_all();
1746:
1747: #ifndef HAVE_LIBPCAP
1748: if (capture_option_specified)
1749: fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
1750: #endif
1751: #ifdef HAVE_LIBPCAP
1752: if (start_capture) {
1753: /* We're supposed to do a live capture; did the user specify an interface
1754: to use? */
1755: if (cfile.iface == NULL) {
1756: /* No - is a default specified in the preferences file? */
1757: if (prefs->capture_device != NULL) {
1758: /* Yes - use it. */
1759: cfile.iface = g_strdup(prefs->capture_device);
1760: } else {
1761: /* No - pick the first one from the list of interfaces. */
1762: if_list = get_interface_list(&err, err_str);
1763: if (if_list == NULL) {
1764: switch (err) {
1765:
1766: case CANT_GET_INTERFACE_LIST:
1767: fprintf(stderr, "ethereal: Can't get list of interfaces: %s\n",
1768: err_str);
1769: break;
1770:
1771: case NO_INTERFACES_FOUND:
1772: fprintf(stderr, "ethereal: There are no interfaces on which a capture can be done\n");
1773: break;
1774: }
1775: exit(2);
1776: }
1777: cfile.iface = g_strdup(if_list->data); /* first interface */
1778: free_interface_list(if_list);
1779: }
1780: }
1781: }
1782: if (capture_child) {
1783: if (cfile.save_file_fd == -1) {
1784: /* XXX - send this to the standard output as something our parent
1785: should put in an error message box? */
1786: fprintf(stderr, "%s: \"-W\" flag not specified\n", CHILD_NAME);
1787: exit(1);
1788: }
1789: }
1790: #endif
1791:
1792: /* Build the column format array */
1793: for (i = 0; i < cfile.cinfo.num_cols; i++) {
1794: cfile.cinfo.col_fmt[i] = get_column_format(i);
1795: cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
1796: cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
1797: NUM_COL_FMTS);
1798: get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
1799: cfile.cinfo.col_data[i] = NULL;
1800: if (cfile.cinfo.col_fmt[i] == COL_INFO)
1801: cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
1802: else
1803: cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
1804: cfile.cinfo.col_expr[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
1805: cfile.cinfo.col_expr_val[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
1806: }
1807:
1808: #ifdef HAVE_LIBPCAP
1809: if (capture_opts.has_snaplen) {
1810: if (capture_opts.snaplen < 1)
1811: capture_opts.snaplen = WTAP_MAX_PACKET_SIZE;
1812: else if (capture_opts.snaplen < MIN_PACKET_SIZE)
1813: capture_opts.snaplen = MIN_PACKET_SIZE;
1814: }
1815:
1816: /* Check the value range of the ringbuffer_num_files parameter */
1817: if (capture_opts.ringbuffer_num_files < RINGBUFFER_MIN_NUM_FILES)
1818: capture_opts.ringbuffer_num_files = RINGBUFFER_MIN_NUM_FILES;
1819: else if (capture_opts.ringbuffer_num_files > RINGBUFFER_MAX_NUM_FILES)
1820: capture_opts.ringbuffer_num_files = RINGBUFFER_MAX_NUM_FILES;
1821: #endif
1822:
1823: rc_file = get_persconffile_path(RC_FILE, FALSE);
1824: gtk_rc_parse(rc_file);
1825:
1826: /* Try to load the regular and boldface fixed-width fonts */
1827: bold_font_name = boldify(prefs->gui_font_name);
1828: m_r_font = gdk_font_load(prefs->gui_font_name);
1829: m_b_font = gdk_font_load(bold_font_name);
1830: if (m_r_font == NULL || m_b_font == NULL) {
1831: /* XXX - pop this up as a dialog box? no */
1832: if (m_r_font == NULL) {
1833: #ifdef HAVE_LIBPCAP
1834: if (!capture_child)
1835: #endif
1836: fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
1837: prefs->gui_font_name);
1838: } else {
1839: gdk_font_unref(m_r_font);
1840: }
1841: if (m_b_font == NULL) {
1842: #ifdef HAVE_LIBPCAP
1843: if (!capture_child)
1844: #endif
1845: fprintf(stderr, "ethereal: Warning: font %s not found - defaulting to 6x13 and 6x13bold\n",
1846: bold_font_name);
1847: } else {
1848: gdk_font_unref(m_b_font);
1849: }
1850: g_free(bold_font_name);
1851: if ((m_r_font = gdk_font_load("6x13")) == NULL) {
1852: fprintf(stderr, "ethereal: Error: font 6x13 not found\n");
1853: exit(1);
1854: }
1855: if ((m_b_font = gdk_font_load("6x13bold")) == NULL) {
1856: fprintf(stderr, "ethereal: Error: font 6x13bold not found\n");
1857: exit(1);
1858: }
1859: g_free(prefs->gui_font_name);
1860: prefs->gui_font_name = g_strdup("6x13");
1861: }
1862:
1863: /* Call this for the side-effects that set_fonts() produces */
1864: set_fonts(m_r_font, m_b_font);
1865:
1866:
1867: #ifdef HAVE_LIBPCAP
1868: /* Is this a "child" ethereal, which is only supposed to pop up a
1869: capture box to let us stop the capture, and run a capture
1870: to a file that our parent will read? */
1871: if (!capture_child) {
1872: #endif
1873: /* No. Pop up the main window, and read in a capture file if
1874: we were told to. */
1875:
1876: create_main_window(pl_size, tv_size, bv_size, prefs);
1877: set_menus_for_capture_file(FALSE);
1878:
1879: colfilter_init();
1880:
1881: /* If we were given the name of a capture file, read it in now;
1882: we defer it until now, so that, if we can't open it, and pop
1883: up an alert box, the alert box is more likely to come up on
1884: top of the main window - but before the preference-file-error
1885: alert box, so, if we get one of those, it's more likely to come
1886: up on top of us. */
1887: if (cf_name) {
1888: if (rfilter != NULL) {
1889: if (!dfilter_compile(rfilter, &rfcode)) {
1890: simple_dialog(ESD_TYPE_CRIT, NULL, dfilter_error_msg);
1891: rfilter_parse_failed = TRUE;
1892: }
1893: }
1894: if (!rfilter_parse_failed) {
1895: if ((err = open_cap_file(cf_name, FALSE, &cfile)) == 0) {
1896: /* "open_cap_file()" succeeded, so it closed the previous
1897: capture file, and thus destroyed any previous read filter
1898: attached to "cf". */
1899: cfile.rfcode = rfcode;
1900: switch (read_cap_file(&cfile, &err)) {
1901:
1902: case READ_SUCCESS:
1903: case READ_ERROR:
1904: /* Just because we got an error, that doesn't mean we were unable
1905: to read any of the file; we handle what we could get from the
1906: file. */
1907: break;
1908:
1909: case READ_ABORTED:
1910: /* Exit now. */
1911: gtk_exit(0);
1912: break;
1913: }
1914: /* Save the name of the containing directory specified in the
1915: path name, if any; we can write over cf_name, which is a
1916: good thing, given that "get_dirname()" does write over its
1917: argument. */
1918: s = get_dirname(cf_name);
1919: set_last_open_dir(s);
1920: } else {
1921: if (rfcode != NULL)
1922: dfilter_free(rfcode);
1923: cfile.rfcode = NULL;
1924: }
1925: }
1926: }
1927: #ifdef HAVE_LIBPCAP
1928: }
1929: #endif
1930:
1931: /* If the global preferences file exists but we failed to open it,
1932: pop up an alert box; we defer that until now, so that the alert
1933: box is more likely to come up on top of the main window. */
1934: if (gpf_path != NULL) {
1935: simple_dialog(ESD_TYPE_WARN, NULL,
1936: "Could not open global preferences file\n\"%s\": %s.", gpf_path,
1937: strerror(gpf_open_errno));
1938: }
1939:
1940: /* If the user's preferences file exists but we failed to open it,
1941: pop up an alert box; we defer that until now, so that the alert
1942: box is more likely to come up on top of the main window. */
1943: if (pf_path != NULL) {
1944: simple_dialog(ESD_TYPE_WARN, NULL,
1945: "Could not open your preferences file\n\"%s\": %s.", pf_path,
1946: strerror(pf_open_errno));
1947: }
1948:
1949: /* If the user's capture filter file exists but we failed to open it,
1950: pop up an alert box; we defer that until now, so that the alert
1951: box is more likely to come up on top of the main window. */
1952: if (cf_path != NULL) {
1953: simple_dialog(ESD_TYPE_WARN, NULL,
1954: "Could not open your capture filter file\n\"%s\": %s.", cf_path,
1955: strerror(cf_open_errno));
1956: g_free(cf_path);
1957: }
1958:
1959: /* If the user's display filter file exists but we failed to open it,
1960: pop up an alert box; we defer that until now, so that the alert
1961: box is more likely to come up on top of the main window. */
1962: if (df_path != NULL) {
1963: simple_dialog(ESD_TYPE_WARN, NULL,
1964: "Could not open your display filter file\n\"%s\": %s.", df_path,
1965: strerror(df_open_errno));
1966: g_free(df_path);
1967: }
1968:
1969: #ifdef HAVE_LIBPCAP
1970: if (capture_child) {
1971: /* This is the child process for a sync mode or fork mode capture,
1972: so just do the low-level work of a capture - don't create
1973: a temporary file and fork off *another* child process (so don't
1974: call "do_capture()"). */
1975:
1976: /* XXX - hand these stats to the parent process */
1977: capture(&stats_known, &stats);
1978:
1979: /* The capture is done; there's nothing more for us to do. */
1980: gtk_exit(0);
1981: } else {
1982: if (start_capture) {
1983: /* "-k" was specified; start a capture. */
1984: do_capture(save_file);
1985: }
1986: else {
1987: set_menus_for_capture_in_progress(FALSE);
1988: }
1989: }
1990: #else
1991: set_menus_for_capture_in_progress(FALSE);
1992: #endif
1993:
1994: gtk_main();
1995:
1996: /* Try to save our geometry. GTK+ provides two routines to get a
1997: window's position relative to the X root window. If I understand the
1998: documentation correctly, gdk_window_get_deskrelative_origin applies
1999: mainly to Enlightenment and gdk_window_get_root_origin applies for
2000: all other WMs.
2001:
2002: The code below tries both routines, and picks the one that returns
2003: the upper-left-most coordinates.
2004:
2005: More info at:
2006:
2007: http://mail.gnome.org/archives/gtk-devel-list/2001-March/msg00289.html
2008: http://www.gtk.org/faq/#AEN600 */
2009:
2010: /* Re-read our saved preferences. */
2011: /* XXX - Move all of this into a separate function? */
2012: prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
2013:
2014: if (pf_path == NULL) {
2015: if (prefs->gui_geometry_save_position) {
2016: if (top_level->window != NULL) {
2017: gdk_window_get_root_origin(top_level->window, &root_x, &root_y);
2018: if (gdk_window_get_deskrelative_origin(top_level->window,
2019: &desk_x, &desk_y)) {
2020: if (desk_x <= root_x && desk_y <= root_y) {
2021: root_x = desk_x;
2022: root_y = desk_y;
2023: }
2024: }
2025: }
2026: if (prefs->gui_geometry_main_x != root_x) {
2027: prefs->gui_geometry_main_x = root_x;
2028: prefs_write_needed = TRUE;
2029: }
2030: if (prefs->gui_geometry_main_y != root_y) {
2031: prefs->gui_geometry_main_y = root_y;
2032: prefs_write_needed = TRUE;
2033: }
2034: }
2035:
2036: if (prefs->gui_geometry_save_size) {
2037: if (top_level->window != NULL) {
2038: /* XXX - Is this the "approved" method? */
2039: gdk_window_get_size(top_level->window, &top_width, &top_height);
2040: }
2041: if (prefs->gui_geometry_main_width != top_width) {
2042: prefs->gui_geometry_main_width = top_width;
2043: prefs_write_needed = TRUE;
2044: }
2045: if (prefs->gui_geometry_main_height != top_height) {
2046: prefs->gui_geometry_main_height = top_height;
2047: prefs_write_needed = TRUE;
2048: }
2049: }
2050:
2051: if (prefs_write_needed) {
2052: write_prefs(&pf_path);
2053: }
2054: }
2055:
2056: epan_cleanup();
2057: g_free(rc_file);
2058:
2059: #ifdef WIN32
2060: /* Shutdown windows sockets */
2061: WSACleanup();
2062:
2063: /* For some unknown reason, the "atexit()" call in "create_console()"
2064: doesn't arrange that "destroy_console()" be called when we exit,
2065: so we call it here if a console was created. */
2066: if (console_was_created)
2067: destroy_console();
2068: #endif
2069:
2070: gtk_exit(0);
2071:
2072: /* This isn't reached, but we need it to keep GCC from complaining
2073: that "main()" returns without returning a value - it knows that
2074: "exit()" never returns, but it doesn't know that "gtk_exit()"
2075: doesn't, as GTK+ doesn't declare it with the attribute
2076: "noreturn". */
2077: return 0; /* not reached */
2078: }
2079:
2080: #ifdef WIN32
2081:
2082: /* We build this as a GUI subsystem application on Win32, so
2083: "WinMain()", not "main()", gets called.
2084:
2085: Hack shamelessly stolen from the Win32 port of the GIMP. */
2086: #ifdef __GNUC__
2087: #define _stdcall __attribute__((stdcall))
2088: #endif
2089:
2090: int _stdcall
2091: WinMain (struct HINSTANCE__ *hInstance,
2092: struct HINSTANCE__ *hPrevInstance,
2093: char *lpszCmdLine,
2094: int nCmdShow)
2095: {
2096: has_no_console = TRUE;
2097: return main (__argc, __argv);
2098: }
2099:
2100: /*
2101: * If this application has no console window to which its standard output
2102: * would go, create one.
2103: */
2104: static void
2105: create_console(void)
2106: {
2107: if (has_no_console) {
2108: /* We have no console to which to print the version string, so
2109: create one and make it the standard input, output, and error. */
2110: if (!AllocConsole())
2111: return; /* couldn't create console */
2112: freopen("CONIN$", "r", stdin);
2113: freopen("CONOUT$", "w", stdout);
2114: freopen("CONOUT$", "w", stderr);
2115:
2116: /* Well, we have a console now. */
2117: has_no_console = FALSE;
2118: console_was_created = TRUE;
2119:
2120: /* Now register "destroy_console()" as a routine to be called just
2121: before the application exits, so that we can destroy the console
2122: after the user has typed a key (so that the console doesn't just
2123: disappear out from under them, giving the user no chance to see
2124: the message(s) we put in there). */
2125: atexit(destroy_console);
2126: }
2127: }
2128:
2129: static void
2130: destroy_console(void)
2131: {
2132: printf("\n\nPress any key to exit\n");
2133: _getch();
2134: FreeConsole();
2135: }
2136:
2137: /* This routine should not be necessary, at least as I read the GLib
2138: source code, as it looks as if GLib is, on Win32, *supposed* to
2139: create a console window into which to display its output.
2140:
2141: That doesn't happen, however. I suspect there's something completely
2142: broken about that code in GLib-for-Win32, and that it may be related
2143: to the breakage that forces us to just call "printf()" on the message
2144: rather than passing the message on to "g_log_default_handler()"
2145: (which is the routine that does the aforementioned non-functional
2146: console window creation). */
2147: static void
2148: console_log_handler(const char *log_domain, GLogLevelFlags log_level,
2149: const char *message, gpointer user_data)
2150: {
2151: create_console();
2152: if (console_was_created) {
2153: /* For some unknown reason, the above doesn't appear to actually cause
2154: anything to be sent to the standard output, so we'll just splat the
2155: message out directly, just to make sure it gets out. */
2156: printf("%s\n", message);
2157: } else
2158: g_log_default_handler(log_domain, log_level, message, user_data);
2159: }
2160: #endif
2161:
2162: /* Given a font name, construct the name of the next heavier version of
2163: that font. */
2164:
2165: #define XLFD_WEIGHT 3 /* index of the "weight" field */
2166:
2167: /* Map from a given weight to the appropriate weight for the "bold"
2168: version of a font.
2169: XXX - the XLFD says these strings shouldn't be used for font matching;
2170: can we get the weight, as a number, from GDK, and ask GDK to find us
2171: a font just like the given font, but with the appropriate higher
2172: weight? */
2173: static const struct {
2174: char *light;
2175: char *heavier;
2176: } weight_map[] = {
2177: { "ultralight", "light" },
2178: { "extralight", "semilight" },
2179: { "light", "medium" },
2180: { "semilight", "semibold" },
2181: { "medium", "bold" },
2182: { "normal", "bold" },
2183: { "semibold", "extrabold" },
2184: { "bold", "ultrabold" }
2185: };
2186: #define N_WEIGHTS (sizeof weight_map / sizeof weight_map[0])
2187:
2188: char *
2189: boldify(const char *font_name)
2190: {
2191: char *bold_font_name;
2192: gchar **xlfd_tokens;
2193: unsigned int i;
2194:
2195: /* Is this an XLFD font? If it begins with "-", yes, otherwise no. */
2196: if (font_name[0] == '-') {
2197: xlfd_tokens = g_strsplit(font_name, "-", XLFD_WEIGHT+1);
2198:
2199: /*
2200: * Make sure we *have* a weight (this might not be a valid
2201: * XLFD font name).
2202: */
2203: for (i = 0; i < XLFD_WEIGHT+1; i++) {
2204: if (xlfd_tokens[i] == NULL) {
2205: /*
2206: * We don't, so treat this as a non-XLFD
2207: * font name.
2208: */
2209: goto not_xlfd;
2210: }
2211: }
2212: for (i = 0; i < N_WEIGHTS; i++) {
2213: if (strcmp(xlfd_tokens[XLFD_WEIGHT],
2214: weight_map[i].light) == 0) {
2215: g_free(xlfd_tokens[XLFD_WEIGHT]);
2216: xlfd_tokens[XLFD_WEIGHT] =
2217: g_strdup(weight_map[i].heavier);
2218: break;
2219: }
2220: }
2221: bold_font_name = g_strjoinv("-", xlfd_tokens);
2222: g_strfreev(xlfd_tokens);
2223: return bold_font_name;
2224: }
2225:
2226: not_xlfd:
2227: /*
2228: * This isn't an XLFD font name; just append "bold" to the name
2229: * of the font.
2230: */
2231: bold_font_name = g_strconcat(font_name, "bold", NULL);
2232: return bold_font_name;
2233: }
2234:
2235:
2236: static void
2237: create_main_window (gint pl_size, gint tv_size, gint bv_size, e_prefs *prefs)
2238: {
2239: GtkWidget *main_vbox, *menubar, *u_pane, *l_pane,
2240: *stat_hbox, *column_lb,
2241: *filter_bt, *filter_cm, *filter_te,
2242: *filter_apply,
2243: *filter_reset;
2244: GList *filter_list = NULL;
2245: GtkAccelGroup *accel;
2246: GtkStyle *win_style;
2247: GdkBitmap *ascend_bm, *descend_bm;
2248: GdkPixmap *ascend_pm, *descend_pm;
2249: column_arrows *col_arrows;
2250: int i;
2251: /* Display filter construct dialog has an Apply button, and "OK" not
2252: only sets our text widget, it activates it (i.e., it causes us to
2253: filter the capture). */
2254: static construct_args_t args = {
2255: "Ethereal: Display Filter",
2256: TRUE,
2257: TRUE
2258: };
2259:
2260: /* Main window */
2261: top_level = gtk_window_new(GTK_WINDOW_TOPLEVEL);
2262: gtk_widget_set_name(top_level, "main window");
2263: gtk_signal_connect(GTK_OBJECT(top_level), "delete_event",
2264: GTK_SIGNAL_FUNC(main_window_delete_event_cb), NULL);
2265: gtk_signal_connect (GTK_OBJECT (top_level), "realize",
2266: GTK_SIGNAL_FUNC (window_icon_realize_cb), NULL);
2267: gtk_window_set_title(GTK_WINDOW(top_level), "The Ethereal Network Analyzer");
2268: if (prefs->gui_geometry_save_position) {
2269: gtk_widget_set_uposition(GTK_WIDGET(top_level),
2270: prefs->gui_geometry_main_x, prefs->gui_geometry_main_y);
2271: }
2272: if (prefs->gui_geometry_save_size) {
2273: gtk_widget_set_usize(GTK_WIDGET(top_level),
2274: prefs->gui_geometry_main_width, prefs->gui_geometry_main_height);
2275: } else {
2276: gtk_widget_set_usize(GTK_WIDGET(top_level), DEF_WIDTH, -1);
2277: }
2278: gtk_window_set_policy(GTK_WINDOW(top_level), TRUE, TRUE, FALSE);
2279:
2280: /* Container for menu bar, paned windows and progress/info box */
2281: main_vbox = gtk_vbox_new(FALSE, 1);
2282: gtk_container_border_width(GTK_CONTAINER(main_vbox), 1);
2283: gtk_container_add(GTK_CONTAINER(top_level), main_vbox);
2284: gtk_widget_show(main_vbox);
2285:
2286: /* Menu bar */
2287: get_main_menu(&menubar, &accel);
2288: gtk_window_add_accel_group(GTK_WINDOW(top_level), accel);
2289: gtk_box_pack_start(GTK_BOX(main_vbox), menubar, FALSE, TRUE, 0);
2290: gtk_widget_show(menubar);
2291:
2292: /* Panes for the packet list, tree, and byte view */
2293: u_pane = gtk_vpaned_new();
2294: gtk_paned_gutter_size(GTK_PANED(u_pane), (GTK_PANED(u_pane))->handle_size);
2295: l_pane = gtk_vpaned_new();
2296: gtk_paned_gutter_size(GTK_PANED(l_pane), (GTK_PANED(l_pane))->handle_size);
2297: gtk_container_add(GTK_CONTAINER(main_vbox), u_pane);
2298: gtk_widget_show(l_pane);
2299: gtk_paned_add2(GTK_PANED(u_pane), l_pane);
2300: gtk_widget_show(u_pane);
2301:
2302: /* Packet list */
2303: pkt_scrollw = scrolled_window_new(NULL, NULL);
2304: gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(pkt_scrollw),
2305: GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
2306: gtk_widget_show(pkt_scrollw);
2307: gtk_paned_add1(GTK_PANED(u_pane), pkt_scrollw);
2308:
2309: packet_list = gtk_clist_new(cfile.cinfo.num_cols);
2310: /* Column titles are filled in below */
2311: gtk_container_add(GTK_CONTAINER(pkt_scrollw), packet_list);
2312:
2313: col_arrows = (column_arrows *) g_malloc(sizeof(column_arrows) * cfile.cinfo.num_cols);
2314:
2315: set_plist_sel_browse(prefs->gui_plist_sel_browse);
2316: set_plist_font(m_r_font);
2317: gtk_widget_set_name(packet_list, "packet list");
2318: gtk_signal_connect (GTK_OBJECT (packet_list), "click_column",
2319: GTK_SIGNAL_FUNC(packet_list_click_column_cb), col_arrows);
2320: gtk_signal_connect(GTK_OBJECT(packet_list), "select_row",
2321: GTK_SIGNAL_FUNC(packet_list_select_cb), NULL);
2322: gtk_signal_connect(GTK_OBJECT(packet_list), "unselect_row",
2323: GTK_SIGNAL_FUNC(packet_list_unselect_cb), NULL);
2324: for (i = 0; i < cfile.cinfo.num_cols; i++) {
2325: if (get_column_resize_type(cfile.cinfo.col_fmt[i]) != RESIZE_MANUAL)
2326: gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
2327:
2328: /* Right-justify the packet number column. */
2329: if (cfile.cinfo.col_fmt[i] == COL_NUMBER)
2330: gtk_clist_set_column_justification(GTK_CLIST(packet_list), i,
2331: GTK_JUSTIFY_RIGHT);
2332: }
2333: gtk_widget_set_usize(packet_list, -1, pl_size);
2334: gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
2335: GTK_SIGNAL_FUNC(popup_menu_handler),
2336: gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_PACKET_LIST_KEY));
2337: gtk_signal_connect(GTK_OBJECT(packet_list), "button_press_event",
2338: GTK_SIGNAL_FUNC(packet_list_button_pressed_cb), NULL);
2339: gtk_clist_set_compare_func(GTK_CLIST(packet_list), packet_list_compare);
2340: gtk_widget_show(packet_list);
2341:
2342: /* Tree view */
2343: item_style = gtk_style_new();
2344: gdk_font_unref(item_style->font);
2345: item_style->font = m_r_font;
2346: create_tree_view(tv_size, prefs, l_pane, &tv_scrollw, &tree_view);
2347: gtk_signal_connect(GTK_OBJECT(tree_view), "tree-select-row",
2348: GTK_SIGNAL_FUNC(tree_view_select_row_cb), NULL);
2349: gtk_signal_connect(GTK_OBJECT(tree_view), "tree-unselect-row",
2350: GTK_SIGNAL_FUNC(tree_view_unselect_row_cb), NULL);
2351: gtk_signal_connect(GTK_OBJECT(tree_view), "button_press_event",
2352: GTK_SIGNAL_FUNC(popup_menu_handler),
2353: gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_TREE_VIEW_KEY));
2354: gtk_widget_show(tree_view);
2355:
2356: /* Byte view. */
2357: byte_nb_ptr = create_byte_view(bv_size, l_pane);
2358:
2359: gtk_signal_connect(GTK_OBJECT(byte_nb_ptr), "button_press_event",
2360: GTK_SIGNAL_FUNC(popup_menu_handler),
2361: gtk_object_get_data(GTK_OBJECT(popup_menu_object), PM_HEXDUMP_KEY));
2362:
2363: /* Filter/info box */
2364: stat_hbox = gtk_hbox_new(FALSE, 1);
2365: gtk_container_border_width(GTK_CONTAINER(stat_hbox), 0);
2366: gtk_box_pack_start(GTK_BOX(main_vbox), stat_hbox, FALSE, TRUE, 0);
2367: gtk_widget_show(stat_hbox);
2368:
2369: filter_bt = gtk_button_new_with_label("Filter:");
2370: gtk_signal_connect(GTK_OBJECT(filter_bt), "clicked",
2371: GTK_SIGNAL_FUNC(display_filter_construct_cb), &args);
2372: gtk_box_pack_start(GTK_BOX(stat_hbox), filter_bt, FALSE, TRUE, 0);
2373: gtk_widget_show(filter_bt);
2374:
2375: filter_cm = gtk_combo_new();
2376: filter_list = g_list_append (filter_list, "");
2377: gtk_combo_set_popdown_strings(GTK_COMBO(filter_cm), filter_list);
2378: gtk_combo_disable_activate(GTK_COMBO(filter_cm));
2379: gtk_combo_set_case_sensitive(GTK_COMBO(filter_cm), TRUE);
2380: gtk_object_set_data(GTK_OBJECT(filter_cm), E_DFILTER_FL_KEY, filter_list);
2381: filter_te = GTK_COMBO(filter_cm)->entry;
2382: gtk_object_set_data(GTK_OBJECT(filter_bt), E_FILT_TE_PTR_KEY, filter_te);
2383: gtk_object_set_data(GTK_OBJECT(filter_te), E_DFILTER_CM_KEY, filter_cm);
2384: gtk_box_pack_start(GTK_BOX(stat_hbox), filter_cm, TRUE, TRUE, 3);
2385: gtk_signal_connect(GTK_OBJECT(filter_te), "activate",
2386: GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
2387: gtk_widget_show(filter_cm);
2388:
2389: filter_reset = gtk_button_new_with_label("Reset");
2390: gtk_object_set_data(GTK_OBJECT(filter_reset), E_DFILTER_TE_KEY, filter_te);
2391: gtk_signal_connect(GTK_OBJECT(filter_reset), "clicked",
2392: GTK_SIGNAL_FUNC(filter_reset_cb), NULL);
2393: gtk_box_pack_start(GTK_BOX(stat_hbox), filter_reset, FALSE, TRUE, 1);
2394: gtk_widget_show(filter_reset);
2395:
2396: filter_apply = gtk_button_new_with_label("Apply");
2397: gtk_object_set_data(GTK_OBJECT(filter_apply), E_DFILTER_CM_KEY, filter_cm);
2398: gtk_signal_connect(GTK_OBJECT(filter_apply), "clicked",
2399: GTK_SIGNAL_FUNC(filter_activate_cb), filter_te);
2400: gtk_box_pack_start(GTK_BOX(stat_hbox), filter_apply, FALSE, TRUE, 1);
2401: gtk_widget_show(filter_apply);
2402:
2403: /* Sets the text entry widget pointer as the E_DILTER_TE_KEY data
2404: * of any widget that ends up calling a callback which needs
2405: * that text entry pointer */
2406: set_menu_object_data("/File/Open...", E_DFILTER_TE_KEY, filter_te);
2407: set_menu_object_data("/File/Reload", E_DFILTER_TE_KEY, filter_te);
2408: set_menu_object_data("/Edit/Filters...", E_FILT_TE_PTR_KEY, filter_te);
2409: set_menu_object_data("/Tools/Follow TCP Stream", E_DFILTER_TE_KEY, filter_te);
2410: set_menu_object_data("/Display/Match/Selected", E_DFILTER_TE_KEY, filter_te);
2411: set_menu_object_data("/Display/Match/Not Selected", E_DFILTER_TE_KEY, filter_te);
2412: set_menu_object_data("/Display/Match/And Selected", E_DFILTER_TE_KEY, filter_te);
2413: set_menu_object_data("/Display/Match/Or Selected", E_DFILTER_TE_KEY, filter_te);
2414: set_menu_object_data("/Display/Match/And Not Selected", E_DFILTER_TE_KEY, filter_te);
2415: set_menu_object_data("/Display/Match/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
2416: set_menu_object_data("/Display/Prepare/Selected", E_DFILTER_TE_KEY, filter_te);
2417: set_menu_object_data("/Display/Prepare/Not Selected", E_DFILTER_TE_KEY, filter_te);
2418: set_menu_object_data("/Display/Prepare/And Selected", E_DFILTER_TE_KEY, filter_te);
2419: set_menu_object_data("/Display/Prepare/Or Selected", E_DFILTER_TE_KEY, filter_te);
2420: set_menu_object_data("/Display/Prepare/And Not Selected", E_DFILTER_TE_KEY, filter_te);
2421: set_menu_object_data("/Display/Prepare/Or Not Selected", E_DFILTER_TE_KEY, filter_te);
2422: gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_DFILTER_TE_KEY, filter_te);
2423: gtk_object_set_data(GTK_OBJECT(popup_menu_object), E_MPACKET_LIST_KEY, packet_list);
2424:
2425: info_bar = gtk_statusbar_new();
2426: main_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "main");
2427: file_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "file");
2428: help_ctx = gtk_statusbar_get_context_id(GTK_STATUSBAR(info_bar), "help");
2429: gtk_statusbar_push(GTK_STATUSBAR(info_bar), main_ctx, DEF_READY_MESSAGE);
2430: gtk_box_pack_start(GTK_BOX(stat_hbox), info_bar, TRUE, TRUE, 0);
2431: gtk_widget_show(info_bar);
2432:
2433: gtk_widget_show(top_level);
2434:
2435: /* Fill in column titles. This must be done after the top level window
2436: is displayed. */
2437: win_style = gtk_widget_get_style(top_level);
2438: ascend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &ascend_bm,
2439: &win_style->bg[GTK_STATE_NORMAL], (gchar **)clist_ascend_xpm);
2440: descend_pm = gdk_pixmap_create_from_xpm_d(top_level->window, &descend_bm,
2441: &win_style->bg[GTK_STATE_NORMAL], (gchar **)clist_descend_xpm);
2442: for (i = 0; i < cfile.cinfo.num_cols; i++) {
2443: col_arrows[i].table = gtk_table_new(2, 2, FALSE);
2444: gtk_table_set_col_spacings(GTK_TABLE(col_arrows[i].table), 5);
2445: column_lb = gtk_label_new(cfile.cinfo.col_title[i]);
2446: gtk_table_attach(GTK_TABLE(col_arrows[i].table), column_lb, 0, 1, 0, 2,
2447: GTK_SHRINK, GTK_SHRINK, 0, 0);
2448: gtk_widget_show(column_lb);
2449: col_arrows[i].ascend_pm = gtk_pixmap_new(ascend_pm, ascend_bm);
2450: gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].ascend_pm,
2451: 1, 2, 1, 2, GTK_SHRINK, GTK_SHRINK, 0, 0);
2452: if (i == 0) {
2453: gtk_widget_show(col_arrows[i].ascend_pm);
2454: }
2455: col_arrows[i].descend_pm = gtk_pixmap_new(descend_pm, descend_bm);
2456: gtk_table_attach(GTK_TABLE(col_arrows[i].table), col_arrows[i].descend_pm,
2457: 1, 2, 0, 1, GTK_SHRINK, GTK_SHRINK, 0, 0);
2458: gtk_clist_set_column_widget(GTK_CLIST(packet_list), i, col_arrows[i].table);
2459: gtk_widget_show(col_arrows[i].table);
2460: }
2461: gtk_clist_column_titles_show(GTK_CLIST(packet_list));
2462: }
2463:
2464:
2465: void
2466: set_last_open_dir(char *dirname)
2467: {
2468: int len;
2469:
2470: if (last_open_dir) {
2471: g_free(last_open_dir);
2472: }
2473:
2474: if (dirname) {
2475: len = strlen(dirname);
2476: if (dirname[len-1] != G_DIR_SEPARATOR) {
2477: last_open_dir = g_strconcat(dirname, G_DIR_SEPARATOR_S,
2478: NULL);
2479: }
2480: }
2481: else {
2482: last_open_dir = NULL;
2483: }
2484: }
2485:
|
- Follow-Ups:
- Re: [Ethereal-dev] Unhandled exception...
- From: Ashok Narayanan
- Re: [Ethereal-dev] Unhandled exception...
- Prev by Date: RE: [Ethereal-dev] Wireless packet captured
- Next by Date: Re: [Ethereal-dev] Unhandled exception...
- Previous by thread: Re: [Ethereal-dev] Unhandled exception...
- Next by thread: Re: [Ethereal-dev] Unhandled exception...
- Index(es):





