Move the GTK+ implementations of various UI utilities out of "util.c"
[obnox/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
3  *
4  * $Id: file.c,v 1.135 1999/12/09 07:19:03 guy Exp $
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@zing.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * 
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  * 
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  * 
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
24  */
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <gtk/gtk.h>
31
32 #include <stdio.h>
33
34 #ifdef HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37
38 #include <time.h>
39
40 #ifdef HAVE_IO_H
41 #include <io.h>
42 #endif
43
44 #include <stdlib.h>
45 #include <string.h>
46 #include <sys/stat.h>
47 #include <errno.h>
48 #include <fcntl.h>
49 #include <signal.h>
50
51 #ifdef NEED_SNPRINTF_H
52 # ifdef HAVE_STDARG_H
53 #  include <stdarg.h>
54 # else
55 #  include <varargs.h>
56 # endif
57 # include "snprintf.h"
58 #endif
59
60 #ifdef NEED_STRERROR_H
61 #include "strerror.h"
62 #endif
63
64 #ifdef HAVE_SYS_TYPES_H
65 # include <sys/types.h>
66 #endif
67
68 #ifdef HAVE_NETINET_IN_H
69 # include <netinet/in.h>
70 #endif
71
72 #include "gtk/main.h"
73 #include "column.h"
74 #include "gtk/menu.h"
75 #include "packet.h"
76 #include "print.h"
77 #include "file.h"
78 #include "util.h"
79 #include "ui_util.h"
80 #include "gtk/proto_draw.h"
81 #include "dfilter.h"
82 #include "timestamp.h"
83 #include "conversation.h"
84 #include "globals.h"
85
86 #ifndef __RESOLV_H__
87 #include "resolv.h"
88 #endif
89
90 #include "packet-atalk.h"
91
92 #include "packet-ipv6.h"
93
94 #include "packet-sna.h"
95
96 #include "packet-vines.h"
97
98 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
99 extern guint      file_ctx;
100
101 gboolean auto_scroll_live = FALSE;
102
103 static guint32 firstsec, firstusec;
104 static guint32 prevsec, prevusec;
105
106 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
107     const u_char *);
108
109 static void freeze_clist(capture_file *cf);
110 static void thaw_clist(capture_file *cf);
111
112 static char *file_rename_error_message(int err);
113 static char *file_close_error_message(int err);
114
115 /* Update the progress bar this many times when reading a file. */
116 #define N_PROGBAR_UPDATES       100
117
118 int
119 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
120 {
121   wtap       *wth;
122   int         err;
123   FILE_T      fh;
124   int         fd;
125   struct stat cf_stat;
126
127   wth = wtap_open_offline(fname, &err);
128   if (wth == NULL)
129     goto fail;
130
131   /* Find the size of the file. */
132   fh = wtap_file(wth);
133   fd = wtap_fd(wth);
134   if (fstat(fd, &cf_stat) < 0) {
135     err = errno;
136     wtap_close(wth);
137     goto fail;
138   }
139
140   /* The open succeeded.  Close whatever capture file we had open,
141      and fill in the information for this file. */
142   close_cap_file(cf, info_bar);
143
144   /* Initialize the table of conversations. */
145   conversation_init();
146
147   /* Initialize protocol-specific variables */
148   init_all_protocols();
149
150   cf->wth = wth;
151   cf->fh = fh;
152   cf->filed = fd;
153   cf->f_len = cf_stat.st_size;
154
155   /* Set the file name because we need it to set the follow stream filter.
156      XXX - is that still true?  We need it for other reasons, though,
157      in any case. */
158   cf->filename = g_strdup(fname);
159
160   /* Indicate whether it's a permanent or temporary file. */
161   cf->is_tempfile = is_tempfile;
162
163   /* If it's a temporary capture buffer file, mark it as not saved. */
164   cf->user_saved = !is_tempfile;
165
166   cf->cd_t      = wtap_file_type(cf->wth);
167   cf->count     = 0;
168   cf->drops     = 0;
169   cf->esec      = 0;
170   cf->eusec     = 0;
171   cf->snap      = wtap_snapshot_length(cf->wth);
172   cf->update_progbar = FALSE;
173   cf->progbar_quantum = 0;
174   cf->progbar_nextstep = 0;
175   firstsec = 0, firstusec = 0;
176   prevsec = 0, prevusec = 0;
177  
178   return (0);
179
180 fail:
181   simple_dialog(ESD_TYPE_WARN, NULL,
182                         file_open_error_message(err, FALSE), fname);
183   return (err);
184 }
185
186 /* Reset everything to a pristine state */
187 void
188 close_cap_file(capture_file *cf, void *w)
189 {
190   frame_data *fd, *fd_next;
191
192   if (cf->fh) {
193     file_close(cf->fh);
194     cf->fh = NULL;
195   }
196   if (cf->wth) {
197     wtap_close(cf->wth);
198     cf->wth = NULL;
199   }
200   /* We have no file open... */
201   if (cf->filename != NULL) {
202     /* If it's a temporary file, remove it. */
203     if (cf->is_tempfile)
204       unlink(cf->filename);
205     g_free(cf->filename);
206     cf->filename = NULL;
207   }
208   /* ...which means we have nothing to save. */
209   cf->user_saved = FALSE;
210
211   for (fd = cf->plist; fd != NULL; fd = fd_next) {
212     fd_next = fd->next;
213     g_free(fd);
214   }
215   if (cf->rfcode != NULL) {
216     dfilter_destroy(cf->rfcode);
217     cf->rfcode = NULL;
218   }
219   cf->plist = NULL;
220   cf->plist_end = NULL;
221   unselect_packet(cf);  /* nothing to select */
222
223   /* Clear the packet list. */
224   gtk_clist_freeze(GTK_CLIST(packet_list));
225   gtk_clist_clear(GTK_CLIST(packet_list));
226   gtk_clist_thaw(GTK_CLIST(packet_list));
227
228   /* Clear any file-related status bar messages.
229      XXX - should be "clear *ALL* file-related status bar messages;
230      will there ever be more than one on the stack? */
231   gtk_statusbar_pop(GTK_STATUSBAR(w), file_ctx);
232
233   /* Restore the standard title bar message. */
234   set_main_window_name("The Ethereal Network Analyzer");
235
236   /* Disable all menu items that make sense only if you have a capture. */
237   set_menu_sensitivity("/File/Save", FALSE);
238   set_menu_sensitivity("/File/Save As...", FALSE);
239   set_menu_sensitivity("/File/Close", FALSE);
240   set_menu_sensitivity("/File/Reload", FALSE);
241   set_menu_sensitivity("/File/Print...", FALSE);
242   set_menu_sensitivity("/Display/Options...", FALSE);
243   set_menu_sensitivity("/Display/Match Selected", FALSE);
244   set_menu_sensitivity("/Display/Colorize Display...", FALSE);
245   set_menu_sensitivity("/Display/Find Frame...", FALSE);
246   set_menu_sensitivity("/Display/Go To Frame...", FALSE);
247   set_menu_sensitivity("/Display/Collapse All", FALSE);
248   set_menu_sensitivity("/Display/Expand All", FALSE);
249   set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
250   set_menu_sensitivity("/Tools/Graph", FALSE);
251   set_menu_sensitivity("/Tools/Summary", FALSE);
252 }
253
254 /* Set the file name in the status line, in the name for the main window,
255    and in the name for the main window's icon. */
256 static void
257 set_display_filename(capture_file *cf)
258 {
259   gchar  *name_ptr;
260   size_t  msg_len;
261   gchar  *done_fmt = " File: %s  Drops: %u";
262   gchar  *done_msg;
263   gchar  *win_name_fmt = "%s - Ethereal";
264   gchar  *win_name;
265
266   if (!cf->is_tempfile) {
267     /* Get the last component of the file name, and put that in the
268        status bar. */
269     if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
270       name_ptr = cf->filename;
271     else
272       name_ptr++;
273   } else {
274     /* The file we read is a temporary file from a live capture;
275        we don't mention its name in the status bar. */
276     name_ptr = "<capture>";
277   }
278
279   msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
280   done_msg = g_malloc(msg_len);
281   snprintf(done_msg, msg_len, done_fmt, name_ptr, cf->drops);
282   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, done_msg);
283   g_free(done_msg);
284
285   msg_len = strlen(name_ptr) + strlen(win_name_fmt) + 1;
286   win_name = g_malloc(msg_len);
287   snprintf(win_name, msg_len, win_name_fmt, name_ptr);
288   set_main_window_name(win_name);
289   g_free(win_name);
290 }
291
292 int
293 read_cap_file(capture_file *cf)
294 {
295   gchar  *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
296   int     success;
297   int     err;
298   size_t  msg_len;
299   char   *errmsg;
300   char    errmsg_errno[1024+1];
301   gchar   err_str[2048+1];
302
303   if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
304     name_ptr = cf->filename;
305   else
306     name_ptr++;
307
308   msg_len = strlen(name_ptr) + strlen(load_fmt) + 2;
309   load_msg = g_malloc(msg_len);
310   snprintf(load_msg, msg_len, load_fmt, name_ptr);
311   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
312   g_free(load_msg);
313
314   cf->update_progbar = TRUE;
315   /* Update the progress bar when it gets to this value. */
316   cf->progbar_nextstep = 0;
317   /* When we reach the value that triggers a progress bar update,
318      bump that value by this amount. */
319   cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
320
321   freeze_clist(cf);
322   proto_tree_is_visible = FALSE;
323   success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
324   /* Set the file encapsulation type now; we don't know what it is until
325      we've looked at all the packets, as we don't know until then whether
326      there's more than one type (and thus whether it's
327      WTAP_ENCAP_PER_PACKET). */
328   cf->lnk_t = wtap_file_encap(cf->wth);
329   wtap_close(cf->wth);
330   cf->wth = NULL;
331   cf->filed = open(cf->filename, O_RDONLY);
332   cf->fh = filed_open(cf->filed, "r");
333   cf->unfiltered_count = cf->count;
334   cf->current_frame = cf->first_displayed;
335   /* Make the first row the selected row. */
336   gtk_clist_select_row(GTK_CLIST(packet_list), 0, -1);
337   thaw_clist(cf);
338
339   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
340   gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
341
342   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
343   set_display_filename(cf);
344
345   /* Enable menu items that make sense if you have a capture file you've
346      finished reading. */
347   set_menu_sensitivity("/File/Save", !cf->user_saved);
348   set_menu_sensitivity("/File/Save As...", TRUE);
349   set_menu_sensitivity("/File/Close", TRUE);
350   set_menu_sensitivity("/File/Reload", TRUE);
351   set_menu_sensitivity("/File/Print...", TRUE);
352
353   /* Enable menu items that make sense if you have some captured packets. */
354   set_menu_sensitivity("/Display/Options...", TRUE);
355   set_menu_sensitivity("/Display/Match Selected", TRUE);
356   set_menu_sensitivity("/Display/Colorize Display...", TRUE);
357   set_menu_sensitivity("/Display/Find Frame...", TRUE);
358   set_menu_sensitivity("/Display/Go To Frame...", TRUE);
359   set_menu_sensitivity("/Tools/Graph", TRUE);
360   set_menu_sensitivity("/Tools/Summary", TRUE);
361
362   if (!success) {
363     /* Put up a message box noting that the read failed somewhere along
364        the line.  Don't throw out the stuff we managed to read, though,
365        if any. */
366     switch (err) {
367
368     case WTAP_ERR_CANT_READ:
369       errmsg = "An attempt to read from the file failed for"
370                " some unknown reason.";
371       break;
372
373     case WTAP_ERR_SHORT_READ:
374       errmsg = "The capture file appears to have been cut short"
375                " in the middle of a packet.";
376       break;
377
378     case WTAP_ERR_BAD_RECORD:
379       errmsg = "The capture file appears to be damaged or corrupt.";
380       break;
381
382     default:
383       sprintf(errmsg_errno, "An error occurred while reading the"
384                               " capture file: %s.", wtap_strerror(err));
385       errmsg = errmsg_errno;
386       break;
387     }
388     snprintf(err_str, sizeof err_str, errmsg);
389     simple_dialog(ESD_TYPE_WARN, NULL, err_str);
390     return (err);
391   } else
392     return (0);
393 }
394
395 #ifdef HAVE_LIBPCAP
396 int
397 start_tail_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
398 {
399   int     err;
400   int     i;
401
402   err = open_cap_file(fname, is_tempfile, cf);
403   if (err == 0) {
404     /* Disable menu items that make sense only if you have a capture
405        file you've finished reading. */
406     set_menu_sensitivity("/File/Open...", FALSE);
407
408     /* Disable menu items that make sense only if you're not currently
409        running a capture. */
410     set_menu_sensitivity("/Capture/Start...", FALSE);
411
412     /* Enable menu items that make sense if you have some captured
413        packets (yes, I know, we don't have any *yet*). */
414     set_menu_sensitivity("/Display/Options...", TRUE);
415     set_menu_sensitivity("/Display/Match Selected", TRUE);
416     set_menu_sensitivity("/Display/Colorize Display...", TRUE);
417     set_menu_sensitivity("/Display/Find Frame...", TRUE);
418     set_menu_sensitivity("/Display/Go To Frame...", TRUE);
419     set_menu_sensitivity("/Tools/Graph", TRUE);
420     set_menu_sensitivity("/Tools/Summary", TRUE);
421
422     for (i = 0; i < cf->cinfo.num_cols; i++) {
423       if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
424         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
425       else {
426         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
427         gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
428                                 cf->cinfo.col_width[i]);
429         gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
430       }
431     }
432
433     /* Yes, "open_cap_file()" set this - but it set it to a file handle
434        from Wiretap, which will be closed when we close the file; we
435        want it to remain open even after that, so that we can read
436        packet data from it. */
437     cf->fh = file_open(fname, "r");
438
439     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, 
440                        " <live capture in progress>");
441   }
442   return err;
443 }
444
445 int
446 continue_tail_cap_file(capture_file *cf, int to_read)
447 {
448   int err;
449
450   gtk_clist_freeze(GTK_CLIST(packet_list));
451
452   wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
453
454   gtk_clist_thaw(GTK_CLIST(packet_list));
455   if (auto_scroll_live && cf->plist_end != NULL)
456     gtk_clist_moveto(GTK_CLIST(packet_list), 
457                        cf->plist_end->row, -1, 1.0, 1.0);
458   return err;
459 }
460
461 int
462 finish_tail_cap_file(capture_file *cf)
463 {
464   int err;
465
466   gtk_clist_freeze(GTK_CLIST(packet_list));
467
468   wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
469
470   thaw_clist(cf);
471   if (auto_scroll_live && cf->plist_end != NULL)
472     gtk_clist_moveto(GTK_CLIST(packet_list), 
473                        cf->plist_end->row, -1, 1.0, 1.0);
474
475   /* Set the file encapsulation type now; we don't know what it is until
476      we've looked at all the packets, as we don't know until then whether
477      there's more than one type (and thus whether it's
478      WTAP_ENCAP_PER_PACKET). */
479   cf->lnk_t = wtap_file_encap(cf->wth);
480
481   /* There's nothing more to read from the capture file - close it. */
482   wtap_close(cf->wth);
483   cf->wth = NULL;
484
485   /* Pop the "<live capture in progress>" message off the status bar. */
486   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
487
488   set_display_filename(cf);
489
490   /* Restore the "File/Open" menu item. */
491   set_menu_sensitivity("/File/Open...", TRUE);
492
493   /* Enable menu items that make sense if you have a capture file
494      you've finished reading. */
495   set_menu_sensitivity("/File/Save", !cf->user_saved);
496   set_menu_sensitivity("/File/Save As...", TRUE);
497   set_menu_sensitivity("/File/Close", TRUE);
498   set_menu_sensitivity("/File/Reload", TRUE);
499   set_menu_sensitivity("/File/Print...", TRUE);
500
501   /* Enable menu items that make sense if you're not currently running
502      a capture. */
503   set_menu_sensitivity("/Capture/Start...", TRUE);
504
505   return err;
506 }
507 #endif /* HAVE_LIBPCAP */
508
509 /* To do: Add check_col checks to the col_add* routines */
510
511 static void
512 col_set_abs_time(frame_data *fd, int col)
513 {
514   struct tm *tmp;
515   time_t then;
516
517   then = fd->abs_secs;
518   tmp = localtime(&then);
519   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
520     tmp->tm_hour,
521     tmp->tm_min,
522     tmp->tm_sec,
523     (long)fd->abs_usecs/100);
524 }
525
526 static void
527 col_set_rel_time(frame_data *fd, int col)
528 {
529   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
530     fd->rel_usecs);
531 }
532
533 static void
534 col_set_delta_time(frame_data *fd, int col)
535 {
536   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
537     fd->del_usecs);
538 }
539
540 /* Add "command-line-specified" time. */
541 static void
542 col_set_cls_time(frame_data *fd, int col)
543 {
544   switch (timestamp_type) {
545     case ABSOLUTE:
546       col_set_abs_time(fd, col);
547       break;
548
549     case RELATIVE:
550       col_set_rel_time(fd, col);
551       break;
552
553     case DELTA:
554       col_set_delta_time(fd, col);
555       break;
556   }
557 }
558
559 static void
560 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
561 {
562   u_int ipv4_addr;
563   struct e_in6_addr ipv6_addr;
564   struct atalk_ddp_addr ddp_addr;
565   struct sna_fid_type_4_addr sna_fid_type_4_addr;
566
567   switch (addr->type) {
568
569   case AT_ETHER:
570     if (is_res)
571       strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
572     else
573       strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
574     break;
575
576   case AT_IPv4:
577     memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
578     if (is_res)
579       strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
580     else
581       strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
582     break;
583
584   case AT_IPv6:
585     memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
586     if (is_res)
587       strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
588     else
589       strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
590     break;
591
592   case AT_IPX:
593     strncpy(fd->cinfo->col_data[col],
594       ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
595     break;
596
597   case AT_SNA:
598     switch (addr->len) {
599
600     case 1:
601       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
602       break;
603
604     case 2:
605       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
606         pntohs(&addr->data[0]));
607       break;
608
609     case SNA_FID_TYPE_4_ADDR_LEN:
610       memcpy(&sna_fid_type_4_addr, addr->data, SNA_FID_TYPE_4_ADDR_LEN);
611       strncpy(fd->cinfo->col_data[col],
612         sna_fid_type_4_addr_to_str(&sna_fid_type_4_addr), COL_MAX_LEN);
613       break;
614     }
615     break;
616
617   case AT_ATALK:
618     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
619     strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
620       COL_MAX_LEN);
621     break;
622
623   case AT_VINES:
624     strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
625       COL_MAX_LEN);
626     break;
627
628   default:
629     break;
630   }
631   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
632 }
633
634 static void
635 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
636                 gboolean is_res)
637 {
638   switch (ptype) {
639
640   case PT_TCP:
641     if (is_res)
642       strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
643     else
644       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
645     break;
646
647   case PT_UDP:
648     if (is_res)
649       strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
650     else
651       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
652     break;
653
654   default:
655     break;
656   }
657   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
658 }
659
660 static void
661 fill_in_columns(frame_data *fd)
662 {
663   int i;
664
665   for (i = 0; i < fd->cinfo->num_cols; i++) {
666     switch (fd->cinfo->col_fmt[i]) {
667
668     case COL_NUMBER:
669       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
670       break;
671
672     case COL_CLS_TIME:
673       col_set_cls_time(fd, i);
674       break;
675
676     case COL_ABS_TIME:
677       col_set_abs_time(fd, i);
678       break;
679
680     case COL_REL_TIME:
681       col_set_rel_time(fd, i);
682       break;
683
684     case COL_DELTA_TIME:
685       col_set_delta_time(fd, i);
686       break;
687
688     case COL_DEF_SRC:
689     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
690       col_set_addr(fd, i, &pi.src, TRUE);
691       break;
692
693     case COL_UNRES_SRC:
694       col_set_addr(fd, i, &pi.src, FALSE);
695       break;
696
697     case COL_DEF_DL_SRC:
698     case COL_RES_DL_SRC:
699       col_set_addr(fd, i, &pi.dl_src, TRUE);
700       break;
701
702     case COL_UNRES_DL_SRC:
703       col_set_addr(fd, i, &pi.dl_src, FALSE);
704       break;
705
706     case COL_DEF_NET_SRC:
707     case COL_RES_NET_SRC:
708       col_set_addr(fd, i, &pi.net_src, TRUE);
709       break;
710
711     case COL_UNRES_NET_SRC:
712       col_set_addr(fd, i, &pi.net_src, FALSE);
713       break;
714
715     case COL_DEF_DST:
716     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
717       col_set_addr(fd, i, &pi.dst, TRUE);
718       break;
719
720     case COL_UNRES_DST:
721       col_set_addr(fd, i, &pi.dst, FALSE);
722       break;
723
724     case COL_DEF_DL_DST:
725     case COL_RES_DL_DST:
726       col_set_addr(fd, i, &pi.dl_dst, TRUE);
727       break;
728
729     case COL_UNRES_DL_DST:
730       col_set_addr(fd, i, &pi.dl_dst, FALSE);
731       break;
732
733     case COL_DEF_NET_DST:
734     case COL_RES_NET_DST:
735       col_set_addr(fd, i, &pi.net_dst, TRUE);
736       break;
737
738     case COL_UNRES_NET_DST:
739       col_set_addr(fd, i, &pi.net_dst, FALSE);
740       break;
741
742     case COL_DEF_SRC_PORT:
743     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
744       col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
745       break;
746
747     case COL_UNRES_SRC_PORT:
748       col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
749       break;
750
751     case COL_DEF_DST_PORT:
752     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
753       col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
754       break;
755
756     case COL_UNRES_DST_PORT:
757       col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
758       break;
759
760     case COL_PROTOCOL:  /* currently done by dissectors */
761     case COL_INFO:      /* currently done by dissectors */
762       break;
763
764     case COL_PACKET_LENGTH:
765       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
766       break;
767
768     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
769       break;
770     }
771   }
772 }
773
774 static void
775 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
776 {
777   gint          i, row;
778   gint          crow;
779   gint          color;
780   proto_tree   *protocol_tree;
781
782   fdata->num = cf->count;
783
784   /* If we don't have the time stamp of the first packet in the
785      capture, it's because this is the first packet.  Save the time
786      stamp of this packet as the time stamp of the first packet. */
787   if (!firstsec && !firstusec) {
788     firstsec  = fdata->abs_secs;
789     firstusec = fdata->abs_usecs;
790   }
791
792   /* Get the time elapsed between the first packet and this packet. */
793   cf->esec = fdata->abs_secs - firstsec;
794   if (firstusec <= fdata->abs_usecs) {
795     cf->eusec = fdata->abs_usecs - firstusec;
796   } else {
797     cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
798     cf->esec--;
799   }
800
801   fdata->cinfo = &cf->cinfo;
802   for (i = 0; i < fdata->cinfo->num_cols; i++) {
803     fdata->cinfo->col_data[i][0] = '\0';
804   }
805
806   /* Apply the filters */
807   if (cf->dfcode != NULL || CFILTERS_CONTAINS_FILTER(cf->colors)) {
808         protocol_tree = proto_tree_create_root();
809         dissect_packet(buf, fdata, protocol_tree);
810         if (cf->dfcode != NULL)
811                 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
812         else
813                 fdata->passed_dfilter = TRUE;
814         /* Apply color filters. */
815         color = -1;
816         for(crow = 0; cf->colors->num_of_filters && 
817               crow < cf->colors->num_of_filters; crow++) {
818
819             if(color_filter(cf->colors,crow)->c_colorfilter == NULL) {
820                 continue;
821             }
822             if(dfilter_apply(color_filter(cf->colors,crow)->c_colorfilter, protocol_tree,
823                  cf->pd)){
824                 color = crow;
825                 break;
826             }
827         }
828
829         proto_tree_free(protocol_tree);
830   }
831   else {
832         dissect_packet(buf, fdata, NULL);
833         fdata->passed_dfilter = TRUE;
834         color = -1;
835   }
836   if (fdata->passed_dfilter) {
837     /* If we don't have the time stamp of the previous displayed packet,
838        it's because this is the first displayed packet.  Save the time
839        stamp of this packet as the time stamp of the previous displayed
840        packet. */
841     if (!prevsec && !prevusec) {
842       prevsec  = fdata->abs_secs;
843       prevusec = fdata->abs_usecs;
844     }
845
846     /* Get the time elapsed between the first packet and this packet. */
847     fdata->rel_secs = cf->esec;
848     fdata->rel_usecs = cf->eusec;
849   
850     /* Get the time elapsed between the previous displayed packet and
851        this packet. */
852     fdata->del_secs = fdata->abs_secs - prevsec;
853     if (prevusec <= fdata->abs_usecs) {
854       fdata->del_usecs = fdata->abs_usecs - prevusec;
855     } else {
856       fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
857       fdata->del_secs--;
858     }
859     prevsec = fdata->abs_secs;
860     prevusec = fdata->abs_usecs;
861
862     fill_in_columns(fdata);
863
864     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
865     fdata->row = row;
866
867     if (cf->colors->color_filters && (color != -1)){
868         gtk_clist_set_background(GTK_CLIST(packet_list), row,
869                    &(color_filter(cf->colors,color)->bg_color));
870         gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
871                    &(color_filter(cf->colors,color)->fg_color));
872     } else {
873         gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
874         gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
875     }
876
877     /* If we haven't yet seen the first frame, this is it. */
878     if (cf->first_displayed == NULL)
879       cf->first_displayed = fdata;
880
881     /* This is the last frame we've seen so far. */
882     cf->last_displayed = fdata;
883
884     /* If this was the current frame, remember the row it's in, so
885        we can arrange that it's on the screen when we're done. */
886     if (cf->current_frame == fdata)
887       cf->current_row = row;
888   } else
889     fdata->row = -1;    /* not in the display */
890   fdata->cinfo = NULL;
891 }
892
893 static void
894 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
895   const u_char *buf) {
896   frame_data   *fdata;
897   capture_file *cf = (capture_file *) user;
898   int           passed;
899   proto_tree   *protocol_tree;
900   frame_data   *plist_end;
901   int file_pos;
902   float prog_val;
903
904   /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
905      when we update it, we have to run the GTK+ main loop to get it
906      to repaint what's pending, and doing so may involve an "ioctl()"
907      to see if there's any pending input from an X server, and doing
908      that for every packet can be costly, especially on a big file.
909      
910      Do so only if we were told to do so; when reading a capture file
911      being updated by a live capture, we don't do so (as we're not
912      "done" until the capture stops, so we don't know how close to
913      "done" we are. */
914
915   if (cf->update_progbar && offset >= cf->progbar_nextstep) {
916       file_pos = lseek(cf->filed, 0, SEEK_CUR);
917       prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
918       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
919       cf->progbar_nextstep += cf->progbar_quantum;
920       while (gtk_events_pending())
921       gtk_main_iteration();
922   }
923
924   /* Allocate the next list entry, and add it to the list. */
925   fdata = (frame_data *) g_malloc(sizeof(frame_data));
926
927   fdata->next = NULL;
928   fdata->prev = NULL;
929   fdata->pkt_len  = phdr->len;
930   fdata->cap_len  = phdr->caplen;
931   fdata->file_off = offset;
932   fdata->lnk_t = phdr->pkt_encap;
933   fdata->abs_secs  = phdr->ts.tv_sec;
934   fdata->abs_usecs = phdr->ts.tv_usec;
935   fdata->encoding = CHAR_ASCII;
936   fdata->pseudo_header = phdr->pseudo_header;
937   fdata->cinfo = NULL;
938
939   passed = TRUE;
940   if (cf->rfcode) {
941     protocol_tree = proto_tree_create_root();
942     dissect_packet(buf, fdata, protocol_tree);
943     passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
944     proto_tree_free(protocol_tree);
945   }   
946   if (passed) {
947     plist_end = cf->plist_end;
948     fdata->prev = plist_end;
949     if (plist_end != NULL)
950       plist_end->next = fdata;
951     else
952       cf->plist = fdata;
953     cf->plist_end = fdata;
954
955     cf->count++;
956     add_packet_to_packet_list(fdata, cf, buf);
957   } else
958     g_free(fdata);
959 }
960
961 int
962 filter_packets(capture_file *cf, gchar *dftext)
963 {
964   dfilter *dfcode;
965
966   if (dftext == NULL) {
967     /* The new filter is an empty filter (i.e., display all packets). */
968     dfcode = NULL;
969   } else {
970     /*
971      * We have a filter; try to compile it.
972      */
973     if (dfilter_compile(dftext, &dfcode) != 0) {
974       /* The attempt failed; report an error. */
975       simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
976       return 0;
977     }
978
979     /* Was it empty? */
980     if (dfcode == NULL) {
981       /* Yes - free the filter text, and set it to null. */
982       g_free(dftext);
983       dftext = NULL;
984     }
985   }
986
987   /* We have a valid filter.  Replace the current filter. */
988   if (cf->dfilter != NULL)
989     g_free(cf->dfilter);
990   cf->dfilter = dftext;
991   if (cf->dfcode != NULL)
992     dfilter_destroy(cf->dfcode);
993   cf->dfcode = dfcode;
994
995   /* Now go through the list of packets we've read from the capture file,
996      applying the current display filter, and, if the packet passes the
997      display filter, add it to the summary display, appropriately
998      colored.  (That's how we colorize the display - it's like filtering
999      the display, only we don't install a new filter.) */
1000   colorize_packets(cf);
1001   return 1;
1002 }
1003
1004 void
1005 colorize_packets(capture_file *cf)
1006 {
1007   frame_data *fd;
1008   guint32 progbar_quantum;
1009   guint32 progbar_nextstep;
1010
1011   /* We need to re-initialize all the state information that protocols
1012      keep, because we're making a fresh pass through all the packets. */
1013
1014   /* Initialize the table of conversations. */
1015   conversation_init();
1016
1017   /* Initialize protocol-specific variables */
1018   init_all_protocols();
1019
1020   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1021
1022   /* Freeze the packet list while we redo it, so we don't get any
1023      screen updates while it happens. */
1024   gtk_clist_freeze(GTK_CLIST(packet_list));
1025
1026   /* Clear it out. */
1027   gtk_clist_clear(GTK_CLIST(packet_list));
1028
1029   /* We don't yet know which will be the first and last frames displayed. */
1030   cf->first_displayed = NULL;
1031   cf->last_displayed = NULL;
1032
1033   /* If a packet was selected, we don't know yet what row, if any, it'll
1034      get. */
1035   cf->current_row = -1;
1036
1037   /* Iterate through the list of packets, calling a routine
1038      to run the filter on the packet, see if it matches, and
1039      put it in the display list if so.  */
1040   firstsec = 0;
1041   firstusec = 0;
1042   prevsec = 0;
1043   prevusec = 0;
1044   cf->unfiltered_count = cf->count;
1045   cf->count = 0;
1046
1047   proto_tree_is_visible = FALSE;
1048
1049   /* Update the progress bar when it gets to this value. */
1050   progbar_nextstep = 0;
1051   /* When we reach the value that triggers a progress bar update,
1052      bump that value by this amount. */
1053   progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1054   gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1055
1056   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1057     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1058        when we update it, we have to run the GTK+ main loop to get it
1059        to repaint what's pending, and doing so may involve an "ioctl()"
1060        to see if there's any pending input from an X server, and doing
1061        that for every packet can be costly, especially on a big file. */
1062     if (cf->count >= progbar_nextstep) {
1063       /* let's not divide by zero. I should never be started
1064        * with unfiltered_count == 0, so let's assert that
1065        */
1066       g_assert(cf->unfiltered_count > 0);
1067
1068         gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1069                 (gfloat) cf->count / cf->unfiltered_count);
1070
1071       progbar_nextstep += progbar_quantum;
1072       while (gtk_events_pending())
1073         gtk_main_iteration();
1074     }
1075
1076     cf->count++;
1077
1078     wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1079
1080     add_packet_to_packet_list(fd, cf, cf->pd);
1081   }
1082  
1083   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1084
1085   if (cf->current_row != -1) {
1086     /* The current frame passed the filter; make sure it's visible. */
1087     if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), cf->current_row))
1088       gtk_clist_moveto(GTK_CLIST(packet_list), cf->current_row, -1, 0.0, 0.0);
1089     if (cf->current_frame_is_selected) {
1090       /* It was selected, so re-select it. */
1091       gtk_clist_select_row(GTK_CLIST(packet_list), cf->current_row, -1);
1092     }
1093     finfo_selected = NULL;
1094   } else {
1095     /* The current frame didn't pass the filter; make the first frame
1096        the current frame, and leave it unselected. */
1097     unselect_packet(cf);
1098     cf->current_frame = cf->first_displayed;
1099   }
1100
1101   /* Unfreeze the packet list. */
1102   gtk_clist_thaw(GTK_CLIST(packet_list));
1103 }
1104
1105 int
1106 print_packets(capture_file *cf, print_args_t *print_args)
1107 {
1108   int         i;
1109   frame_data *fd;
1110   guint32     progbar_quantum;
1111   guint32     progbar_nextstep;
1112   guint32     count;
1113   proto_tree *protocol_tree;
1114   gint       *col_widths = NULL;
1115   gint        data_width;
1116   gboolean    print_separator;
1117
1118   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1119   if (cf->print_fh == NULL)
1120     return FALSE;       /* attempt to open destination failed */
1121
1122   /* XXX - printing multiple frames in PostScript looks as if it's
1123      tricky - you have to deal with page boundaries, I think -
1124      and I'll have to spend some time learning enough about
1125      PostScript to figure it out, so, for now, we only print
1126      multiple frames as text. */
1127 #if 0
1128   print_preamble(cf->print_fh);
1129 #endif
1130
1131   if (print_args->print_summary) {
1132     /* We're printing packet summaries.
1133
1134        Find the widths for each of the columns - maximum of the
1135        width of the title and the width of the data - and print
1136        the column titles. */
1137     col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1138     for (i = 0; i < cf->cinfo.num_cols; i++) {
1139       /* Don't pad the last column. */
1140       if (i == cf->cinfo.num_cols - 1)
1141         col_widths[i] = 0;
1142       else {
1143         col_widths[i] = strlen(cf->cinfo.col_title[i]);
1144         data_width = get_column_char_width(get_column_format(i));
1145         if (data_width > col_widths[i])
1146           col_widths[i] = data_width;
1147       }
1148
1149       /* Right-justify the packet number column. */
1150       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1151         fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1152       else
1153         fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1154       if (i == cf->cinfo.num_cols - 1)
1155         fputc('\n', cf->print_fh);
1156       else
1157         fputc(' ', cf->print_fh);
1158     }
1159   }
1160
1161   print_separator = FALSE;
1162   proto_tree_is_visible = TRUE;
1163
1164   /* Update the progress bar when it gets to this value. */
1165   progbar_nextstep = 0;
1166   /* When we reach the value that triggers a progress bar update,
1167      bump that value by this amount. */
1168   progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1169   /* Count of packets we've looked at. */
1170   count = 0;
1171
1172   /* Iterate through the list of packets, printing the packets that
1173      were selected by the current display filter.  */
1174   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1175     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1176        when we update it, we have to run the GTK+ main loop to get it
1177        to repaint what's pending, and doing so may involve an "ioctl()"
1178        to see if there's any pending input from an X server, and doing
1179        that for every packet can be costly, especially on a big file. */
1180     if (count >= progbar_nextstep) {
1181       /* let's not divide by zero. I should never be started
1182        * with unfiltered_count == 0, so let's assert that
1183        */
1184       g_assert(cf->unfiltered_count > 0);
1185
1186       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1187         (gfloat) count / cf->unfiltered_count);
1188       progbar_nextstep += progbar_quantum;
1189       while (gtk_events_pending())
1190         gtk_main_iteration();
1191     }
1192     count++;
1193
1194     if (fd->passed_dfilter) {
1195       wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1196       if (print_args->print_summary) {
1197         /* Fill in the column information, but don't bother creating
1198            the logical protocol tree. */
1199         fd->cinfo = &cf->cinfo;
1200         for (i = 0; i < fd->cinfo->num_cols; i++) {
1201           fd->cinfo->col_data[i][0] = '\0';
1202         }
1203         dissect_packet(cf->pd, fd, NULL);
1204         fill_in_columns(fd);
1205         for (i = 0; i < cf->cinfo.num_cols; i++) {
1206           /* Right-justify the packet number column. */
1207           if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1208             fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1209           else
1210             fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1211           if (i == cf->cinfo.num_cols - 1)
1212             fputc('\n', cf->print_fh);
1213           else
1214             fputc(' ', cf->print_fh);
1215         }
1216       } else {
1217         if (print_separator)
1218           fputc('\n', cf->print_fh);
1219
1220         /* Create the logical protocol tree. */
1221         protocol_tree = proto_tree_create_root();
1222         dissect_packet(cf->pd, fd, protocol_tree);
1223
1224         /* Print the information in that tree. */
1225         proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1226                         cf->pd, fd, cf->print_fh);
1227
1228         proto_tree_free(protocol_tree);
1229
1230         if (print_args->print_hex) {
1231           /* Print the full packet data as hex. */
1232           print_hex_data(cf->print_fh, cf->pd, fd->cap_len, fd->encoding);
1233         }
1234
1235         /* Print a blank line if we print anything after this. */
1236         print_separator = TRUE;
1237       }
1238     }
1239   }
1240
1241   if (col_widths != NULL)
1242     g_free(col_widths);
1243
1244 #if 0
1245   print_finale(cf->print_fh);
1246 #endif
1247
1248   close_print_dest(print_args->to_file, cf->print_fh);
1249  
1250   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1251
1252   cf->print_fh = NULL;
1253   return TRUE;
1254 }
1255
1256 /* Scan through the packet list and change all columns that use the
1257    "command-line-specified" time stamp format to use the current
1258    value of that format. */
1259 void
1260 change_time_formats(capture_file *cf)
1261 {
1262   frame_data *fd;
1263   int i;
1264   GtkStyle  *pl_style;
1265
1266   /* Freeze the packet list while we redo it, so we don't get any
1267      screen updates while it happens. */
1268   freeze_clist(cf);
1269
1270   /* Iterate through the list of packets, checking whether the packet
1271      is in a row of the summary list and, if so, whether there are
1272      any columns that show the time in the "command-line-specified"
1273      format and, if so, update that row. */
1274   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1275     if (fd->row != -1) {
1276       /* This packet is in the summary list, on row "fd->row". */
1277
1278       /* XXX - there really should be a way of checking "cf->cinfo" for this;
1279          the answer isn't going to change from packet to packet, so we should
1280          simply skip all the "change_time_formats()" work if we're not
1281          changing anything. */
1282       fd->cinfo = &cf->cinfo;
1283       if (check_col(fd, COL_CLS_TIME)) {
1284         /* There are columns that show the time in the "command-line-specified"
1285            format; update them. */
1286         for (i = 0; i < cf->cinfo.num_cols; i++) {
1287           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1288             /* This is one of the columns that shows the time in
1289                "command-line-specified" format; update it. */
1290             cf->cinfo.col_data[i][0] = '\0';
1291             col_set_cls_time(fd, i);
1292             gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1293                           cf->cinfo.col_data[i]);
1294           }
1295         }
1296       }
1297     }
1298   }
1299
1300   /* Set the column widths of those columns that show the time in
1301      "command-line-specified" format. */
1302   pl_style = gtk_widget_get_style(packet_list);
1303   for (i = 0; i < cf->cinfo.num_cols; i++) {
1304     if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1305       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1306         get_column_width(COL_CLS_TIME, pl_style->font));
1307     }
1308   }
1309
1310   /* Unfreeze the packet list. */
1311   thaw_clist(cf);
1312 }
1313
1314 static void
1315 clear_tree_and_hex_views(void)
1316 {
1317   GList *selection;
1318   GtkWidget *tmp_item;
1319
1320   /* Clear the hex dump. */
1321   gtk_text_freeze(GTK_TEXT(byte_view));
1322   gtk_text_set_point(GTK_TEXT(byte_view), 0);
1323   gtk_text_forward_delete(GTK_TEXT(byte_view),
1324     gtk_text_get_length(GTK_TEXT(byte_view)));
1325   gtk_text_thaw(GTK_TEXT(byte_view));
1326
1327   /* Deselect any selected tree item. gtktree.c should
1328    * do this when we clear_items, but it doesn't. I copied
1329    * this while() loop from gtktree.c, gtk_real_tree_select_child()
1330    */
1331   if (GTK_TREE(tree_view)->root_tree) {
1332           selection = GTK_TREE(tree_view)->root_tree->selection;
1333           while (selection) {
1334                   tmp_item = selection->data;
1335                   gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
1336                   gtk_widget_unref(tmp_item);
1337                   selection = selection->next;
1338           }
1339           g_list_free(GTK_TREE(tree_view)->root_tree->selection);
1340           GTK_TREE(tree_view)->root_tree->selection = NULL;
1341   }
1342
1343   /* Clear the protocol tree view. The length arg of -1
1344    * means to clear all items up to the end. */
1345   gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
1346 }
1347
1348 gboolean
1349 find_packet(capture_file *cf, dfilter *sfcode)
1350 {
1351   frame_data *start_fd;
1352   frame_data *fd;
1353   frame_data *new_fd = NULL;
1354   guint32 progbar_quantum;
1355   guint32 progbar_nextstep;
1356   int count;
1357   proto_tree *protocol_tree;
1358
1359   start_fd = cf->current_frame;
1360   if (start_fd != NULL)  {
1361     gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1362
1363     /* Iterate through the list of packets, starting at the packet we've
1364        picked, calling a routine to run the filter on the packet, see if
1365        it matches, and stop if so.  */
1366     count = 0;
1367     fd = start_fd;
1368
1369     proto_tree_is_visible = FALSE;
1370
1371     /* Update the progress bar when it gets to this value. */
1372     progbar_nextstep = 0;
1373     /* When we reach the value that triggers a progress bar update,
1374        bump that value by this amount.
1375
1376        We base the progress bar on the extent to which we've gone through
1377        the displayed packets, as those are the only ones for which we
1378        have to do a significant amount of work. */
1379     progbar_quantum = cf->count/N_PROGBAR_UPDATES;
1380     gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1381
1382     fd = start_fd;
1383     for (;;) {
1384       /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1385          when we update it, we have to run the GTK+ main loop to get it
1386          to repaint what's pending, and doing so may involve an "ioctl()"
1387          to see if there's any pending input from an X server, and doing
1388          that for every packet can be costly, especially on a big file. */
1389       if (count >= progbar_nextstep) {
1390         /* let's not divide by zero. I should never be started
1391          * with count == 0, so let's assert that
1392          */
1393         g_assert(cf->count > 0);
1394
1395         gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1396                 (gfloat) count / cf->count);
1397
1398         progbar_nextstep += progbar_quantum;
1399         while (gtk_events_pending())
1400           gtk_main_iteration();
1401       }
1402
1403       /* Go past the current frame. */
1404       if (cf->sbackward) {
1405         /* Go on to the previous frame. */
1406         fd = fd->prev;
1407         if (fd == NULL)
1408           fd = cf->plist_end;   /* wrap around */
1409       } else {
1410         /* Go on to the next frame. */
1411         fd = fd->next;
1412         if (fd == NULL)
1413           fd = cf->plist;       /* wrap around */
1414       }
1415
1416       if (fd == start_fd) {
1417         /* We're back to the frame we were on originally.  The search
1418            failed. */
1419         break;
1420       }
1421
1422       /* Is this packet in the display? */
1423       if (fd->passed_dfilter) {
1424         count++;
1425
1426         /* Yes.  Does it match the search filter? */
1427         protocol_tree = proto_tree_create_root();
1428         wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1429         dissect_packet(cf->pd, fd, protocol_tree);
1430         if (dfilter_apply(sfcode, protocol_tree, cf->pd)) {
1431           new_fd = fd;
1432           break;        /* found it! */
1433         }
1434       }
1435     }
1436
1437     gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1438   }
1439
1440   if (new_fd != NULL) {
1441     /* We found a frame.  Make it visible, and select it. */
1442     if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), new_fd->row))
1443       gtk_clist_moveto(GTK_CLIST(packet_list), new_fd->row, -1, 0.0, 0.0);
1444     gtk_clist_select_row(GTK_CLIST(packet_list), new_fd->row, -1);
1445     return TRUE;        /* success */
1446   } else
1447     return FALSE;       /* failure */
1448 }
1449
1450 goto_result_t
1451 goto_frame(capture_file *cf, guint fnumber)
1452 {
1453   frame_data *fd;
1454
1455   for (fd = cf->plist; fd != NULL && fd->num < fnumber; fd = fd->next)
1456     ;
1457
1458   if (fd == NULL)
1459     return NO_SUCH_FRAME;       /* we didn't find that frame */
1460   if (!fd->passed_dfilter)
1461     return FRAME_NOT_DISPLAYED; /* the frame with that number isn't displayed */
1462
1463   /* We found that frame, and it's currently being displayed.
1464      Make it visible, and select it. */
1465   if (!gtk_clist_row_is_visible(GTK_CLIST(packet_list), fd->row))
1466     gtk_clist_moveto(GTK_CLIST(packet_list), fd->row, -1, 0.0, 0.0);
1467   gtk_clist_select_row(GTK_CLIST(packet_list), fd->row, -1);
1468   return FOUND_FRAME;
1469 }
1470
1471 /* Select the packet on a given row. */
1472 void
1473 select_packet(capture_file *cf, int row)
1474 {
1475   frame_data *fd;
1476   int i;
1477
1478   /* Clear out whatever's currently in the hex dump. */
1479   gtk_text_freeze(GTK_TEXT(byte_view));
1480   gtk_text_set_point(GTK_TEXT(byte_view), 0);
1481   gtk_text_forward_delete(GTK_TEXT(byte_view),
1482     gtk_text_get_length(GTK_TEXT(byte_view)));
1483
1484   /* Search through the list of frames to see which one is in
1485      this row. */
1486   for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1487     if (fd->row == row)
1488       break;
1489   }
1490
1491   g_assert(fd != NULL);
1492
1493   /* Record that this frame is the current frame, and that it's selected. */
1494   cf->current_frame = fd;
1495   cf->current_frame_is_selected = TRUE;
1496
1497   /* Get the data in that frame. */
1498   wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1499
1500   /* Create the logical protocol tree. */
1501   if (cf->protocol_tree)
1502       proto_tree_free(cf->protocol_tree);
1503   cf->protocol_tree = proto_tree_create_root();
1504   proto_tree_is_visible = TRUE;
1505   dissect_packet(cf->pd, cf->current_frame, cf->protocol_tree);
1506
1507   /* Display the GUI protocol tree and hex dump. */
1508   clear_tree_and_hex_views();
1509   proto_tree_draw(cf->protocol_tree, tree_view);
1510   packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->current_frame->cap_len,
1511                         -1, -1, cf->current_frame->encoding);
1512   gtk_text_thaw(GTK_TEXT(byte_view));
1513
1514   /* A packet is selected, so "File/Print Packet" has something to print. */
1515   set_menu_sensitivity("/File/Print Packet", TRUE);
1516   set_menu_sensitivity("/Display/Collapse All", TRUE);
1517   set_menu_sensitivity("/Display/Expand All", TRUE);
1518   
1519   if (pi.ipproto == 6) {
1520       set_menu_sensitivity("/Tools/Follow TCP Stream", TRUE);
1521   } else {
1522       set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
1523   }
1524 }
1525
1526 /* Unselect the selected packet, if any. */
1527 void
1528 unselect_packet(capture_file *cf)
1529 {
1530   cf->current_frame_is_selected = FALSE;
1531
1532   /* Destroy the protocol tree for that packet. */
1533   if (cf->protocol_tree != NULL) {
1534     proto_tree_free(cf->protocol_tree);
1535     cf->protocol_tree = NULL;
1536   }
1537
1538   finfo_selected = NULL;
1539
1540   /* Clear out the display of that packet. */
1541   clear_tree_and_hex_views();
1542
1543   /* No packet is selected, so "File/Print Packet" has nothing to print. */
1544   set_menu_sensitivity("/File/Print Packet", FALSE);
1545   set_menu_sensitivity("/Display/Collapse All", FALSE);
1546   set_menu_sensitivity("/Display/Expand All", FALSE);
1547   set_menu_sensitivity("/Tools/Follow TCP Stream", FALSE);
1548 }
1549
1550 static void
1551 freeze_clist(capture_file *cf)
1552 {
1553   int i;
1554
1555   /* Make the column sizes static, so they don't adjust while
1556      we're reading the capture file (freezing the clist doesn't
1557      seem to suffice). */
1558   for (i = 0; i < cf->cinfo.num_cols; i++)
1559     gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1560   gtk_clist_freeze(GTK_CLIST(packet_list));
1561 }
1562
1563 static void
1564 thaw_clist(capture_file *cf)
1565 {
1566   int i;
1567
1568   for (i = 0; i < cf->cinfo.num_cols; i++) {
1569     if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1570       /* Set this column's width to the appropriate value. */
1571       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1572                                 cf->cinfo.col_width[i]);
1573     } else {
1574       /* Make this column's size dynamic, so that it adjusts to the
1575          appropriate size. */
1576       gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1577     }
1578   }
1579   gtk_clist_thaw(GTK_CLIST(packet_list));
1580
1581   /* Hopefully, the columns have now gotten their appropriate sizes;
1582      make them resizeable - a column that auto-resizes cannot be
1583      resized by the user, and *vice versa*. */
1584   for (i = 0; i < cf->cinfo.num_cols; i++)
1585     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1586 }
1587
1588 int
1589 save_cap_file(char *fname, capture_file *cf, gboolean save_filtered,
1590                 guint save_format)
1591 {
1592   gchar        *from_filename;
1593   gchar        *name_ptr, *save_msg, *save_fmt = " Saving: %s...";
1594   size_t        msg_len;
1595   int           err;
1596   gboolean      do_copy;
1597   int           from_fd, to_fd, nread, nwritten;
1598   wtap_dumper  *pdh;
1599   frame_data   *fd;
1600   struct wtap_pkthdr hdr;
1601   guint8        pd[65536];
1602
1603   if ((name_ptr = (gchar *) strrchr(fname, '/')) == NULL)
1604     name_ptr = fname;
1605   else
1606     name_ptr++;
1607   msg_len = strlen(name_ptr) + strlen(save_fmt) + 2;
1608   save_msg = g_malloc(msg_len);
1609   snprintf(save_msg, msg_len, save_fmt, name_ptr);
1610   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, save_msg);
1611   g_free(save_msg);
1612
1613   if (!save_filtered && save_format == cf->cd_t) {
1614     /* We're not filtering packets, and we're saving it in the format
1615        it's already in, so we can just move or copy the raw data. */
1616
1617     /* In this branch, we set "err" only if we get an error, so we
1618        must first clear it. */
1619     err = 0;
1620     if (cf->is_tempfile) {
1621       /* The file being saved is a temporary file from a live
1622          capture, so it doesn't need to stay around under that name;
1623          first, try renaming the capture buffer file to the new name. */
1624       if (rename(cf->filename, fname) == 0) {
1625         /* That succeeded - there's no need to copy the source file. */
1626         from_filename = NULL;
1627         do_copy = FALSE;
1628       } else {
1629         if (errno == EXDEV) {
1630           /* They're on different file systems, so we have to copy the
1631              file. */
1632           do_copy = TRUE;
1633           from_filename = cf->filename;
1634         } else {
1635           /* The rename failed, but not because they're on different
1636              file systems - put up an error message.  (Or should we
1637              just punt and try to copy?  The only reason why I'd
1638              expect the rename to fail and the copy to succeed would
1639              be if we didn't have permission to remove the file from
1640              the temporary directory, and that might be fixable - but
1641              is it worth requiring the user to go off and fix it?) */
1642           err = errno;
1643           simple_dialog(ESD_TYPE_WARN, NULL,
1644                                 file_rename_error_message(err), fname);
1645           goto done;
1646         }
1647       }
1648     } else {
1649       /* It's a permanent file, so we should copy it, and not remove the
1650          original. */
1651       do_copy = TRUE;
1652       from_filename = cf->filename;
1653     }
1654
1655     /* Copy the file, if we haven't moved it. */
1656     if (do_copy) {
1657       /* Copy the raw bytes of the file. */
1658       from_fd = open(from_filename, O_RDONLY);
1659       if (from_fd < 0) {
1660         err = errno;
1661         simple_dialog(ESD_TYPE_WARN, NULL,
1662                         file_open_error_message(err, TRUE), from_filename);
1663         goto done;
1664       }
1665
1666       to_fd = creat(fname, 0644);
1667       if (to_fd < 0) {
1668         err = errno;
1669         simple_dialog(ESD_TYPE_WARN, NULL,
1670                         file_open_error_message(err, TRUE), fname);
1671         close(from_fd);
1672         goto done;
1673       }
1674
1675       while ((nread = read(from_fd, pd, sizeof pd)) > 0) {
1676         nwritten = write(to_fd, pd, nread);
1677         if (nwritten < nread) {
1678           if (nwritten < 0)
1679             err = errno;
1680           else
1681             err = WTAP_ERR_SHORT_WRITE;
1682           simple_dialog(ESD_TYPE_WARN, NULL,
1683                                 file_write_error_message(err), fname);
1684           close(from_fd);
1685           close(to_fd);
1686           goto done;
1687         }
1688       }
1689       if (nread < 0) {
1690         err = errno;
1691         simple_dialog(ESD_TYPE_WARN, NULL,
1692                         file_read_error_message(err), from_filename);
1693         close(from_fd);
1694         close(to_fd);
1695         goto done;
1696       }
1697       close(from_fd);
1698       if (close(to_fd) < 0) {
1699         err = errno;
1700         simple_dialog(ESD_TYPE_WARN, NULL,
1701                 file_close_error_message(err), fname);
1702         goto done;
1703       }
1704     }
1705   } else {
1706     /* Either we're filtering packets, or we're saving in a different
1707        format; we can't do that by copying or moving the capture file,
1708        we have to do it by writing the packets out in Wiretap. */
1709     pdh = wtap_dump_open(fname, save_format, cf->lnk_t, cf->snap, &err);
1710     if (pdh == NULL) {
1711       simple_dialog(ESD_TYPE_WARN, NULL,
1712                         file_open_error_message(err, TRUE), fname);
1713       goto done;
1714     }
1715
1716     /* XXX - have a way to save only the packets currently selected by
1717        the display filter.
1718
1719        If we do that, should we make that file the current file?  If so,
1720        it means we can no longer get at the other packets.  What does
1721        NetMon do? */
1722     for (fd = cf->plist; fd != NULL; fd = fd->next) {
1723       /* XXX - do a progress bar */
1724       if (!save_filtered || fd->passed_dfilter) {
1725         /* Either we're saving all frames, or we're saving filtered frames
1726            and this one passed the display filter - save it. */
1727         hdr.ts.tv_sec = fd->abs_secs;
1728         hdr.ts.tv_usec = fd->abs_usecs;
1729         hdr.caplen = fd->cap_len;
1730         hdr.len = fd->pkt_len;
1731         hdr.pkt_encap = fd->lnk_t;
1732         wtap_seek_read(cf->cd_t, cf->fh, fd->file_off, pd, fd->cap_len);
1733
1734         if (!wtap_dump(pdh, &hdr, pd, &err)) {
1735             simple_dialog(ESD_TYPE_WARN, NULL,
1736                                 file_write_error_message(err), fname);
1737             wtap_dump_close(pdh, &err);
1738             goto done;
1739         }
1740       }
1741     }
1742
1743     if (!wtap_dump_close(pdh, &err)) {
1744       simple_dialog(ESD_TYPE_WARN, NULL,
1745                 file_close_error_message(err), fname);
1746       goto done;
1747     }
1748   }
1749
1750 done:
1751
1752   /* Pop the "Saving:" message off the status bar. */
1753   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
1754   if (err == 0) {
1755     if (!save_filtered) {
1756       /* We saved the entire capture, not just some packets from it.
1757          Open and read the file we saved it to.
1758
1759          XXX - this is somewhat of a waste; we already have the
1760          packets, all this gets us is updated file type information
1761          (which we could just stuff into "cf"), and having the new
1762          file be the one we have opened and from which we're reading
1763          the data, and it means we have to spend time opening and
1764          reading the file, which could be a significant amount of
1765          time if the file is large. */
1766       cf->user_saved = TRUE;
1767
1768       if ((err = open_cap_file(fname, FALSE, cf)) == 0) {
1769         /* XXX - report errors if this fails? */
1770         err = read_cap_file(cf);
1771         set_menu_sensitivity("/File/Save", FALSE);
1772       }
1773     }
1774   }
1775   return err;
1776 }
1777
1778 char *
1779 file_open_error_message(int err, int for_writing)
1780 {
1781   char *errmsg;
1782   static char errmsg_errno[1024+1];
1783
1784   switch (err) {
1785
1786   case WTAP_ERR_NOT_REGULAR_FILE:
1787     errmsg = "The file \"%s\" is invalid.";
1788     break;
1789
1790   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1791   case WTAP_ERR_UNSUPPORTED:
1792     /* Seen only when opening a capture file for reading. */
1793     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1794     break;
1795
1796   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1797     /* Seen only when opening a capture file for writing. */
1798     errmsg = "Ethereal does not support writing capture files in that format.";
1799     break;
1800
1801   case WTAP_ERR_UNSUPPORTED_ENCAP:
1802   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1803     /* Seen only when opening a capture file for writing. */
1804     errmsg = "Ethereal cannot save this capture in that format.";
1805     break;
1806
1807   case WTAP_ERR_BAD_RECORD:
1808     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1809     break;
1810
1811   case WTAP_ERR_CANT_OPEN:
1812     if (for_writing)
1813       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1814     else
1815       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1816     break;
1817
1818   case WTAP_ERR_SHORT_READ:
1819     errmsg = "The file \"%s\" appears to have been cut short"
1820              " in the middle of a packet.";
1821     break;
1822
1823   case WTAP_ERR_SHORT_WRITE:
1824     errmsg = "A full header couldn't be written to the file \"%s\".";
1825     break;
1826
1827   case ENOENT:
1828     if (for_writing)
1829       errmsg = "The path to the file \"%s\" does not exist.";
1830     else
1831       errmsg = "The file \"%s\" does not exist.";
1832     break;
1833
1834   case EACCES:
1835     if (for_writing)
1836       errmsg = "You do not have permission to create or write to the file \"%s\".";
1837     else
1838       errmsg = "You do not have permission to read the file \"%s\".";
1839     break;
1840
1841   default:
1842     sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1843                                 wtap_strerror(err));
1844     errmsg = errmsg_errno;
1845     break;
1846   }
1847   return errmsg;
1848 }
1849
1850 static char *
1851 file_rename_error_message(int err)
1852 {
1853   char *errmsg;
1854   static char errmsg_errno[1024+1];
1855
1856   switch (err) {
1857
1858   case ENOENT:
1859     errmsg = "The path to the file \"%s\" does not exist.";
1860     break;
1861
1862   case EACCES:
1863     errmsg = "You do not have permission to move the capture file to \"%s\".";
1864     break;
1865
1866   default:
1867     sprintf(errmsg_errno, "The file \"%%s\" could not be moved: %s.",
1868                                 wtap_strerror(err));
1869     errmsg = errmsg_errno;
1870     break;
1871   }
1872   return errmsg;
1873 }
1874
1875 char *
1876 file_read_error_message(int err)
1877 {
1878   static char errmsg_errno[1024+1];
1879
1880   sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1881                                 wtap_strerror(err));
1882   return errmsg_errno;
1883 }
1884
1885 char *
1886 file_write_error_message(int err)
1887 {
1888   char *errmsg;
1889   static char errmsg_errno[1024+1];
1890
1891   switch (err) {
1892
1893   case ENOSPC:
1894     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1895     break;
1896
1897 #ifdef EDQUOT
1898   case EDQUOT:
1899     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1900     break;
1901 #endif
1902
1903   default:
1904     sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1905                                 wtap_strerror(err));
1906     errmsg = errmsg_errno;
1907     break;
1908   }
1909   return errmsg;
1910 }
1911
1912 /* Check for write errors - if the file is being written to an NFS server,
1913    a write error may not show up until the file is closed, as NFS clients
1914    might not send writes to the server until the "write()" call finishes,
1915    so that the write may fail on the server but the "write()" may succeed. */
1916 static char *
1917 file_close_error_message(int err)
1918 {
1919   char *errmsg;
1920   static char errmsg_errno[1024+1];
1921
1922   switch (err) {
1923
1924   case WTAP_ERR_CANT_CLOSE:
1925     errmsg = "The file \"%s\" couldn't be closed for some unknown reason.";
1926     break;
1927
1928   case WTAP_ERR_SHORT_WRITE:
1929     errmsg = "Not all the data could be written to the file \"%s\".";
1930     break;
1931
1932   case ENOSPC:
1933     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1934     break;
1935
1936 #ifdef EDQUOT
1937   case EDQUOT:
1938     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1939     break;
1940 #endif
1941
1942   default:
1943     sprintf(errmsg_errno, "An error occurred while closing the file \"%%s\": %s.",
1944                                 wtap_strerror(err));
1945     errmsg = errmsg_errno;
1946     break;
1947   }
1948   return errmsg;
1949 }