Add support for Banyan Vines addresses to the code that handles the
[obnox/wireshark/wip.git] / file.c
1 /* file.c
2  * File I/O routines
3  *
4  * $Id: file.c,v 1.112 1999/10/22 08:30:02 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 #ifdef HAVE_SYS_WAIT_H
73 # include <sys/wait.h>
74 #endif
75
76 #include "gtk/main.h"
77 #include "column.h"
78 #include "gtk/menu.h"
79 #include "packet.h"
80 #include "print.h"
81 #include "file.h"
82 #include "util.h"
83 #include "gtk/proto_draw.h"
84 #include "dfilter.h"
85 #include "timestamp.h"
86 #include "conversation.h"
87
88 #ifndef __RESOLV_H__
89 #include "resolv.h"
90 #endif
91
92 #include "packet-atalk.h"
93
94 #include "packet-ipv6.h"
95
96 #include "packet-ncp.h"
97
98 extern GtkWidget *packet_list, *prog_bar, *info_bar, *byte_view, *tree_view;
99 extern guint      file_ctx;
100 extern int        sync_pipe[];
101
102 guint cap_input_id;
103 gboolean auto_scroll_live = FALSE;
104
105 static guint32 firstsec, firstusec;
106 static guint32 prevsec, prevusec;
107
108 static void wtap_dispatch_cb(u_char *, const struct wtap_pkthdr *, int,
109     const u_char *);
110
111 static void freeze_clist(capture_file *cf);
112 static void thaw_clist(capture_file *cf);
113
114 /* Update the progress bar this many times when reading a file. */
115 #define N_PROGBAR_UPDATES       100
116
117 int
118 open_cap_file(char *fname, capture_file *cf) {
119   wtap       *wth;
120   int         err;
121   FILE_T      fh;
122   int         fd;
123   struct stat cf_stat;
124
125   wth = wtap_open_offline(fname, &err);
126   if (wth == NULL)
127     goto fail;
128
129   /* Find the size of the file. */
130   fh = wtap_file(wth);
131   fd = wtap_fd(wth);
132   if (fstat(fd, &cf_stat) < 0) {
133     err = errno;
134     wtap_close(wth);
135     goto fail;
136   }
137
138   /* The open succeeded.  Close whatever capture file we had open,
139      and fill in the information for this file. */
140   close_cap_file(cf, info_bar, file_ctx);
141
142   /* Initialize the table of conversations. */
143   conversation_init();
144
145   /* Initialize protocol-specific variables */
146   afs_init_protocol();
147   ncp_init_protocol();
148   smb_init_protocol();
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   cf->filename = g_strdup(fname);
157
158   cf->cd_t      = wtap_file_type(cf->wth);
159   cf->cd_t_desc = wtap_file_type_string(cf->wth);
160   cf->count     = 0;
161   cf->drops     = 0;
162   cf->esec      = 0;
163   cf->eusec     = 0;
164   cf->snap      = wtap_snapshot_length(cf->wth);
165   cf->update_progbar = FALSE;
166   cf->progbar_quantum = 0;
167   cf->progbar_nextstep = 0;
168   firstsec = 0, firstusec = 0;
169   prevsec = 0, prevusec = 0;
170  
171   return (0);
172
173 fail:
174   simple_dialog(ESD_TYPE_WARN, NULL,
175                         file_open_error_message(err, FALSE), fname);
176   return (err);
177 }
178
179 /* Reset everything to a pristine state */
180 void
181 close_cap_file(capture_file *cf, void *w, guint context) {
182   frame_data *fd, *fd_next;
183
184   if (cf->fh) {
185     file_close(cf->fh);
186     cf->fh = NULL;
187   }
188   if (cf->wth) {
189     wtap_close(cf->wth);
190     cf->wth = NULL;
191   }
192   for (fd = cf->plist; fd != NULL; fd = fd_next) {
193     fd_next = fd->next;
194     g_free(fd);
195   }
196   if (cf->rfcode != NULL) {
197     dfilter_destroy(cf->rfcode);
198     cf->rfcode = NULL;
199   }
200   cf->plist = NULL;
201   cf->plist_end = NULL;
202   unselect_packet(cf);  /* nothing to select */
203
204   gtk_clist_freeze(GTK_CLIST(packet_list));
205   gtk_clist_clear(GTK_CLIST(packet_list));
206   gtk_clist_thaw(GTK_CLIST(packet_list));
207   gtk_statusbar_pop(GTK_STATUSBAR(w), context);
208
209   /* Disable all menu items that make sense only if you have a capture. */
210   set_menu_sensitivity("/File/Save", FALSE);
211   set_menu_sensitivity("/File/Save As...", FALSE);
212   set_menu_sensitivity("/File/Close", FALSE);
213   set_menu_sensitivity("/File/Reload", FALSE);
214   set_menu_sensitivity("/File/Print...", FALSE);
215   set_menu_sensitivity("/Display/Options...", FALSE);
216   set_menu_sensitivity("/Tools/Summary", FALSE);
217 }
218
219 int
220 read_cap_file(capture_file *cf) {
221   gchar  *name_ptr, *load_msg, *load_fmt = " Loading: %s...";
222   gchar  *done_fmt = " File: %s  Drops: %d";
223   int     success;
224   int     err;
225   size_t  msg_len;
226   char   *errmsg;
227   char    errmsg_errno[1024+1];
228   gchar   err_str[2048+1];
229
230   if ((name_ptr = (gchar *) strrchr(cf->filename, '/')) == NULL)
231     name_ptr = cf->filename;
232   else
233     name_ptr++;
234
235   load_msg = g_malloc(strlen(name_ptr) + strlen(load_fmt) + 2);
236   sprintf(load_msg, load_fmt, name_ptr);
237   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
238
239   cf->update_progbar = TRUE;
240   /* Update the progress bar when it gets to this value. */
241   cf->progbar_nextstep = 0;
242   /* When we reach the value that triggers a progress bar update,
243      bump that value by this amount. */
244   cf->progbar_quantum = cf->f_len/N_PROGBAR_UPDATES;
245
246   freeze_clist(cf);
247   proto_tree_is_visible = FALSE;
248   success = wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
249   wtap_close(cf->wth);
250   cf->wth = NULL;
251   cf->filed = open(cf->filename, O_RDONLY);
252   cf->fh = filed_open(cf->filed, "r");
253   cf->unfiltered_count = cf->count;
254   thaw_clist(cf);
255
256   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
257   gtk_progress_set_value(GTK_PROGRESS(prog_bar), 0);
258
259   gtk_statusbar_pop(GTK_STATUSBAR(info_bar), file_ctx);
260
261   msg_len = strlen(name_ptr) + strlen(done_fmt) + 64;
262   load_msg = g_realloc(load_msg, msg_len);
263
264   if (cf->user_saved || !cf->save_file)
265     snprintf(load_msg, msg_len, done_fmt, name_ptr, cf->drops);
266   else
267     snprintf(load_msg, msg_len, done_fmt, "<none>", cf->drops);
268
269   gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, load_msg);
270   g_free(load_msg);
271
272   /* Enable menu items that make sense if you have a capture. */
273   set_menu_sensitivity("/File/Close", TRUE);
274   set_menu_sensitivity("/File/Reload", TRUE);
275   set_menu_sensitivity("/File/Print...", TRUE);
276   set_menu_sensitivity("/Display/Options...", TRUE);
277   set_menu_sensitivity("/Tools/Summary", TRUE);
278
279   if (!success) {
280     /* Put up a message box noting that the read failed somewhere along
281        the line.  Don't throw out the stuff we managed to read, though,
282        if any. */
283     switch (err) {
284
285     case WTAP_ERR_CANT_READ:
286       errmsg = "An attempt to read from the file failed for"
287                " some unknown reason.";
288       break;
289
290     case WTAP_ERR_SHORT_READ:
291       errmsg = "The capture file appears to have been cut short"
292                " in the middle of a packet.";
293       break;
294
295     case WTAP_ERR_BAD_RECORD:
296       errmsg = "The capture file appears to be damaged or corrupt.";
297       break;
298
299     default:
300       sprintf(errmsg_errno, "An error occurred while reading the"
301                               " capture file: %s.", wtap_strerror(err));
302       errmsg = errmsg_errno;
303       break;
304     }
305     snprintf(err_str, sizeof err_str, errmsg);
306     simple_dialog(ESD_TYPE_WARN, NULL, err_str);
307     return (err);
308   } else
309     return (0);
310 }
311
312 #ifdef HAVE_LIBPCAP
313 void 
314 cap_file_input_cb (gpointer data, gint source, GdkInputCondition condition) {
315   
316   capture_file *cf = (capture_file *)data;
317   char buffer[256+1], *p = buffer, *q = buffer;
318   int  nread;
319   int  to_read = 0;
320   gboolean exit_loop = FALSE;
321   int  err;
322   int  wstatus;
323   int  wsignal;
324   char *msg;
325   char *sigmsg;
326   char sigmsg_buf[6+1+3+1];
327   char *coredumped;
328
329   /* avoid reentrancy problems and stack overflow */
330   gtk_input_remove(cap_input_id);
331
332   if ((nread = read(sync_pipe[0], buffer, 256)) <= 0) {
333
334     /* The child has closed the sync pipe, meaning it's not going to be
335        capturing any more packets.  Pick up its exit status, and
336        complain if it died of a signal. */
337     if (wait(&wstatus) != -1) {
338       /* XXX - are there any platforms on which we can run that *don't*
339          support POSIX.1's <sys/wait.h> and macros therein? */
340       wsignal = wstatus & 0177;
341       coredumped = "";
342       if (wstatus == 0177) {
343         /* It stopped, rather than exiting.  "Should not happen." */
344         msg = "stopped";
345         wsignal = (wstatus >> 8) & 0xFF;
346       } else {
347         msg = "terminated";
348         if (wstatus & 0200)
349           coredumped = " - core dumped";
350       }
351       if (wsignal != 0) {
352         switch (wsignal) {
353
354         case SIGHUP:
355           sigmsg = "Hangup";
356           break;
357
358         case SIGINT:
359           sigmsg = "Interrupted";
360           break;
361
362         case SIGQUIT:
363           sigmsg = "Quit";
364           break;
365
366         case SIGILL:
367           sigmsg = "Illegal instruction";
368           break;
369
370         case SIGTRAP:
371           sigmsg = "Trace trap";
372           break;
373
374         case SIGABRT:
375           sigmsg = "Abort";
376           break;
377
378         case SIGFPE:
379           sigmsg = "Arithmetic exception";
380           break;
381
382         case SIGKILL:
383           sigmsg = "Killed";
384           break;
385
386         case SIGBUS:
387           sigmsg = "Bus error";
388           break;
389
390         case SIGSEGV:
391           sigmsg = "Segmentation violation";
392           break;
393
394         /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO 
395                 Linux is POSIX compliant.  These are not POSIX-defined signals ---
396                   ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
397
398                ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
399                 were omitted from POSIX.1 because their behavior is
400                 implementation dependent and could not be adequately catego-
401                 rized.  Conforming implementations may deliver these sig-
402                 nals, but must document the circumstances under which they
403                 are delivered and note any restrictions concerning their
404                 delivery.''
405         */
406
407         #ifdef SIGSYS
408         case SIGSYS:
409           sigmsg = "Bad system call";
410           break;
411         #endif
412
413         case SIGPIPE:
414           sigmsg = "Broken pipe";
415           break;
416
417         case SIGALRM:
418           sigmsg = "Alarm clock";
419           break;
420
421         case SIGTERM:
422           sigmsg = "Terminated";
423           break;
424
425         default:
426           sprintf(sigmsg_buf, "Signal %d", wsignal);
427           sigmsg = sigmsg_buf;
428           break;
429         }
430         simple_dialog(ESD_TYPE_WARN, NULL,
431                 "Child capture process %s: %s%s", msg, sigmsg, coredumped);
432       }
433     }
434       
435     /* Read what remains of the capture file, and stop capture (restore
436        menu items) */
437     gtk_clist_freeze(GTK_CLIST(packet_list));
438
439     /* XXX - do something if this fails? */
440     wtap_loop(cf->wth, 0, wtap_dispatch_cb, (u_char *) cf, &err);
441
442     thaw_clist(cf);
443     if (auto_scroll_live)
444       gtk_clist_moveto(GTK_CLIST(packet_list), 
445                        cf->plist_end->row, -1, 1.0, 1.0);
446
447     wtap_close(cf->wth);
448     cf->wth = NULL;
449     set_menu_sensitivity("/File/Open...", TRUE);
450     set_menu_sensitivity("/File/Close", TRUE);
451     set_menu_sensitivity("/File/Save As...", TRUE);
452     set_menu_sensitivity("/File/Print...", TRUE);
453     set_menu_sensitivity("/File/Reload", TRUE);
454     set_menu_sensitivity("/Capture/Start...", TRUE);
455     set_menu_sensitivity("/Tools/Summary", TRUE);
456     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, " File: <none>");
457     return;
458   }
459
460   buffer[nread] = '\0';
461
462   while(!exit_loop) {
463     /* look for (possibly multiple) '*' */
464     switch (*q) {
465     case '*' :
466       to_read += atoi(p);
467       p = q + 1; 
468       q++;
469       break;
470     case '\0' :
471       /* XXX should handle the case of a pipe full (i.e. no star found) */
472       exit_loop = TRUE;
473       break;
474     default :
475       q++;
476       break;
477     } 
478   }
479
480   gtk_clist_freeze(GTK_CLIST(packet_list));
481   /* XXX - do something if this fails? */
482   wtap_loop(cf->wth, to_read, wtap_dispatch_cb, (u_char *) cf, &err);
483   gtk_clist_thaw(GTK_CLIST(packet_list));
484   if (auto_scroll_live)
485     gtk_clist_moveto(GTK_CLIST(packet_list), cf->plist_end->row, -1, 1.0, 1.0);
486
487   /* restore pipe handler */
488   cap_input_id = gtk_input_add_full (sync_pipe[0],
489                                      GDK_INPUT_READ,
490                                      cap_file_input_cb,
491                                      NULL,
492                                      (gpointer) cf,
493                                      NULL);
494 }
495
496 int
497 tail_cap_file(char *fname, capture_file *cf) {
498   int     err;
499   int     i;
500
501   err = open_cap_file(fname, cf);
502   if ((err == 0) && (cf->cd_t != WTAP_FILE_UNKNOWN)) {
503
504     set_menu_sensitivity("/File/Open...", FALSE);
505     set_menu_sensitivity("/Display/Options...", TRUE);
506     set_menu_sensitivity("/Capture/Start...", FALSE);
507
508     for (i = 0; i < cf->cinfo.num_cols; i++) {
509       if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_LIVE)
510         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
511       else {
512         gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
513         gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
514                                 cf->cinfo.col_width[i]);
515         gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
516       }
517     }
518
519     cf->fh = file_open(fname, "r");
520
521     cap_input_id = gtk_input_add_full (sync_pipe[0],
522                                        GDK_INPUT_READ,
523                                        cap_file_input_cb,
524                                        NULL,
525                                        (gpointer) cf,
526                                        NULL);
527     gtk_statusbar_push(GTK_STATUSBAR(info_bar), file_ctx, 
528                        " <live capture in progress>");
529   }
530   else {
531     close(sync_pipe[0]);
532   }
533   return err;
534 }
535 #endif /* HAVE_LIBPCAP */
536
537 /* To do: Add check_col checks to the col_add* routines */
538
539 static void
540 col_set_abs_time(frame_data *fd, int col)
541 {
542   struct tm *tmp;
543   time_t then;
544
545   then = fd->abs_secs;
546   tmp = localtime(&then);
547   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%02d:%02d:%02d.%04ld",
548     tmp->tm_hour,
549     tmp->tm_min,
550     tmp->tm_sec,
551     (long)fd->abs_usecs/100);
552 }
553
554 static void
555 col_set_rel_time(frame_data *fd, int col)
556 {
557   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->rel_secs,
558     fd->rel_usecs);
559 }
560
561 static void
562 col_set_delta_time(frame_data *fd, int col)
563 {
564   snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%d.%06d", fd->del_secs,
565     fd->del_usecs);
566 }
567
568 /* Add "command-line-specified" time. */
569 static void
570 col_set_cls_time(frame_data *fd, int col)
571 {
572   switch (timestamp_type) {
573     case ABSOLUTE:
574       col_set_abs_time(fd, col);
575       break;
576
577     case RELATIVE:
578       col_set_rel_time(fd, col);
579       break;
580
581     case DELTA:
582       col_set_delta_time(fd, col);
583       break;
584   }
585 }
586
587 static void
588 col_set_addr(frame_data *fd, int col, address *addr, gboolean is_res)
589 {
590   u_int ipv4_addr;
591   struct e_in6_addr ipv6_addr;
592   struct atalk_ddp_addr ddp_addr;
593
594   switch (addr->type) {
595
596   case AT_ETHER:
597     if (is_res)
598       strncpy(fd->cinfo->col_data[col], get_ether_name(addr->data), COL_MAX_LEN);
599     else
600       strncpy(fd->cinfo->col_data[col], ether_to_str(addr->data), COL_MAX_LEN);
601     break;
602
603   case AT_IPv4:
604     memcpy(&ipv4_addr, addr->data, sizeof ipv4_addr);
605     if (is_res)
606       strncpy(fd->cinfo->col_data[col], get_hostname(ipv4_addr), COL_MAX_LEN);
607     else
608       strncpy(fd->cinfo->col_data[col], ip_to_str(addr->data), COL_MAX_LEN);
609     break;
610
611   case AT_IPv6:
612     memcpy(&ipv6_addr.s6_addr, addr->data, sizeof ipv6_addr.s6_addr);
613     if (is_res)
614       strncpy(fd->cinfo->col_data[col], get_hostname6(&ipv6_addr), COL_MAX_LEN);
615     else
616       strncpy(fd->cinfo->col_data[col], ip6_to_str(&ipv6_addr), COL_MAX_LEN);
617     break;
618
619   case AT_IPX:
620     strncpy(fd->cinfo->col_data[col],
621       ipx_addr_to_str(pntohl(&addr->data[0]), &addr->data[4]), COL_MAX_LEN);
622     break;
623
624   case AT_SNA:
625     switch (addr->len) {
626
627     case 1:
628       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X", addr->data[0]);
629       break;
630
631     case 2:
632       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%04X",
633         pntohs(&addr->data[0]));
634       break;
635     }
636     break;
637
638   case AT_ATALK:
639     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
640     strncpy(fd->cinfo->col_data[col], atalk_addr_to_str(&ddp_addr),
641       COL_MAX_LEN);
642     break;
643
644   case AT_VINES:
645     strncpy(fd->cinfo->col_data[col], vines_addr_to_str(&addr->data[0]),
646       COL_MAX_LEN);
647     break;
648
649   default:
650     break;
651   }
652   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
653 }
654
655 static void
656 col_set_port(frame_data *fd, int col, port_type ptype, guint32 port,
657                 gboolean is_res)
658 {
659   switch (ptype) {
660
661   case PT_TCP:
662     if (is_res)
663       strncpy(fd->cinfo->col_data[col], get_tcp_port(port), COL_MAX_LEN);
664     else
665       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
666     break;
667
668   case PT_UDP:
669     if (is_res)
670       strncpy(fd->cinfo->col_data[col], get_udp_port(port), COL_MAX_LEN);
671     else
672       snprintf(fd->cinfo->col_data[col], COL_MAX_LEN, "%u", port);
673     break;
674
675   default:
676     break;
677   }
678   fd->cinfo->col_data[col][COL_MAX_LEN - 1] = '\0';
679 }
680
681 static void
682 fill_in_columns(frame_data *fd)
683 {
684   int i;
685
686   for (i = 0; i < fd->cinfo->num_cols; i++) {
687     switch (fd->cinfo->col_fmt[i]) {
688
689     case COL_NUMBER:
690       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%u", fd->num);
691       break;
692
693     case COL_CLS_TIME:
694       col_set_cls_time(fd, i);
695       break;
696
697     case COL_ABS_TIME:
698       col_set_abs_time(fd, i);
699       break;
700
701     case COL_REL_TIME:
702       col_set_rel_time(fd, i);
703       break;
704
705     case COL_DELTA_TIME:
706       col_set_delta_time(fd, i);
707       break;
708
709     case COL_DEF_SRC:
710     case COL_RES_SRC:   /* COL_DEF_SRC is currently just like COL_RES_SRC */
711       col_set_addr(fd, i, &pi.src, TRUE);
712       break;
713
714     case COL_UNRES_SRC:
715       col_set_addr(fd, i, &pi.src, FALSE);
716       break;
717
718     case COL_DEF_DL_SRC:
719     case COL_RES_DL_SRC:
720       col_set_addr(fd, i, &pi.dl_src, TRUE);
721       break;
722
723     case COL_UNRES_DL_SRC:
724       col_set_addr(fd, i, &pi.dl_src, FALSE);
725       break;
726
727     case COL_DEF_NET_SRC:
728     case COL_RES_NET_SRC:
729       col_set_addr(fd, i, &pi.net_src, TRUE);
730       break;
731
732     case COL_UNRES_NET_SRC:
733       col_set_addr(fd, i, &pi.net_src, FALSE);
734       break;
735
736     case COL_DEF_DST:
737     case COL_RES_DST:   /* COL_DEF_DST is currently just like COL_RES_DST */
738       col_set_addr(fd, i, &pi.dst, TRUE);
739       break;
740
741     case COL_UNRES_DST:
742       col_set_addr(fd, i, &pi.dst, FALSE);
743       break;
744
745     case COL_DEF_DL_DST:
746     case COL_RES_DL_DST:
747       col_set_addr(fd, i, &pi.dl_dst, TRUE);
748       break;
749
750     case COL_UNRES_DL_DST:
751       col_set_addr(fd, i, &pi.dl_dst, FALSE);
752       break;
753
754     case COL_DEF_NET_DST:
755     case COL_RES_NET_DST:
756       col_set_addr(fd, i, &pi.net_dst, TRUE);
757       break;
758
759     case COL_UNRES_NET_DST:
760       col_set_addr(fd, i, &pi.net_dst, FALSE);
761       break;
762
763     case COL_DEF_SRC_PORT:
764     case COL_RES_SRC_PORT:      /* COL_DEF_SRC_PORT is currently just like COL_RES_SRC_PORT */
765       col_set_port(fd, i, pi.ptype, pi.srcport, TRUE);
766       break;
767
768     case COL_UNRES_SRC_PORT:
769       col_set_port(fd, i, pi.ptype, pi.srcport, FALSE);
770       break;
771
772     case COL_DEF_DST_PORT:
773     case COL_RES_DST_PORT:      /* COL_DEF_DST_PORT is currently just like COL_RES_DST_PORT */
774       col_set_port(fd, i, pi.ptype, pi.destport, TRUE);
775       break;
776
777     case COL_UNRES_DST_PORT:
778       col_set_port(fd, i, pi.ptype, pi.destport, FALSE);
779       break;
780
781     case COL_PROTOCOL:  /* currently done by dissectors */
782     case COL_INFO:      /* currently done by dissectors */
783       break;
784
785     case COL_PACKET_LENGTH:
786       snprintf(fd->cinfo->col_data[i], COL_MAX_LEN, "%d", fd->pkt_len);
787       break;
788
789     case NUM_COL_FMTS:  /* keep compiler happy - shouldn't get here */
790       break;
791     }
792   }
793 }
794
795 static void
796 add_packet_to_packet_list(frame_data *fdata, capture_file *cf, const u_char *buf)
797 {
798   gint          i, row;
799   gint          crow;
800   gint          color;
801   proto_tree   *protocol_tree;
802
803   fdata->num = cf->count;
804
805   /* If we don't have the time stamp of the first packet in the
806      capture, it's because this is the first packet.  Save the time
807      stamp of this packet as the time stamp of the first packet. */
808   if (!firstsec && !firstusec) {
809     firstsec  = fdata->abs_secs;
810     firstusec = fdata->abs_usecs;
811   }
812
813   /* Get the time elapsed between the first packet and this packet. */
814   cf->esec = fdata->abs_secs - firstsec;
815   if (firstusec <= fdata->abs_usecs) {
816     cf->eusec = fdata->abs_usecs - firstusec;
817   } else {
818     cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
819     cf->esec--;
820   }
821
822   fdata->cinfo = &cf->cinfo;
823   for (i = 0; i < fdata->cinfo->num_cols; i++) {
824     fdata->cinfo->col_data[i][0] = '\0';
825   }
826
827   /* Apply the filters */
828   if (cf->dfcode != NULL ||
829       CFILTERS_CONTAINS_FILTER(cf)) {
830         protocol_tree = proto_tree_create_root();
831         dissect_packet(buf, fdata, protocol_tree);
832         if (cf->dfcode != NULL)
833                 fdata->passed_dfilter = dfilter_apply(cf->dfcode, protocol_tree, cf->pd);
834         else
835                 fdata->passed_dfilter = TRUE;
836         /* Apply color filters. */
837         color = -1;
838         for(crow = 0; cf->colors->num_of_filters && 
839               crow < cf->colors->num_of_filters; crow++) {
840
841             if(color_filter(cf,crow)->c_colorfilter == NULL) {
842                 continue;
843             }
844             if(dfilter_apply(color_filter(cf,crow)->c_colorfilter, protocol_tree,
845                  cf->pd)){
846                 color = crow;
847                 break;
848             }
849         }
850
851         proto_tree_free(protocol_tree);
852   }
853   else {
854         dissect_packet(buf, fdata, NULL);
855         fdata->passed_dfilter = TRUE;
856         color = -1;
857   }
858   if (fdata->passed_dfilter) {
859     /* If we don't have the time stamp of the previous displayed packet,
860        it's because this is the first displayed packet.  Save the time
861        stamp of this packet as the time stamp of the previous displayed
862        packet. */
863     if (!prevsec && !prevusec) {
864       prevsec  = fdata->abs_secs;
865       prevusec = fdata->abs_usecs;
866     }
867
868     /* Get the time elapsed between the first packet and this packet. */
869     fdata->rel_secs = cf->esec;
870     fdata->rel_usecs = cf->eusec;
871   
872     /* Get the time elapsed between the previous displayed packet and
873        this packet. */
874     fdata->del_secs = fdata->abs_secs - prevsec;
875     if (prevusec <= fdata->abs_usecs) {
876       fdata->del_usecs = fdata->abs_usecs - prevusec;
877     } else {
878       fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
879       fdata->del_secs--;
880     }
881     prevsec = fdata->abs_secs;
882     prevusec = fdata->abs_usecs;
883
884     fill_in_columns(fdata);
885
886     row = gtk_clist_append(GTK_CLIST(packet_list), fdata->cinfo->col_data);
887     fdata->row = row;
888
889     if (cf->colors->color_filters && (color != -1)){
890         gtk_clist_set_background(GTK_CLIST(packet_list), row,
891                    &(color_filter(cf,color)->bg_color));
892         gtk_clist_set_foreground(GTK_CLIST(packet_list), row,
893                    &(color_filter(cf,color)->fg_color));
894     } else {
895         gtk_clist_set_background(GTK_CLIST(packet_list), row, &WHITE);
896         gtk_clist_set_foreground(GTK_CLIST(packet_list), row, &BLACK);
897     }
898
899     /* If this was the selected packet, remember the row it's in, so
900        we can re-select it.  ("selected_packet" is 0-origin, as it's
901        a GList index; "num", however, is 1-origin.) */
902     if (cf->selected_packet == fdata->num - 1)
903       cf->selected_row = row;
904   } else
905     fdata->row = -1;    /* not in the display */
906   fdata->cinfo = NULL;
907 }
908
909 static void
910 wtap_dispatch_cb(u_char *user, const struct wtap_pkthdr *phdr, int offset,
911   const u_char *buf) {
912   frame_data   *fdata;
913   capture_file *cf = (capture_file *) user;
914   int           passed;
915   proto_tree   *protocol_tree;
916   frame_data   *plist_end;
917   int file_pos;
918   float prog_val;
919
920   /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
921      when we update it, we have to run the GTK+ main loop to get it
922      to repaint what's pending, and doing so may involve an "ioctl()"
923      to see if there's any pending input from an X server, and doing
924      that for every packet can be costly, especially on a big file.
925      
926      Do so only if we were told to do so; when reading a capture file
927      being updated by a live capture, we don't do so (as we're not
928      "done" until the capture stops, so we don't know how close to
929      "done" we are. */
930
931   if (cf->update_progbar && offset >= cf->progbar_nextstep) {
932       file_pos = lseek(cf->filed, 0, SEEK_CUR);
933       prog_val = (gfloat) file_pos / (gfloat) cf->f_len;
934       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), prog_val);
935       cf->progbar_nextstep += cf->progbar_quantum;
936       while (gtk_events_pending())
937       gtk_main_iteration();
938   }
939
940   /* Allocate the next list entry, and add it to the list. */
941   fdata = (frame_data *) g_malloc(sizeof(frame_data));
942
943   fdata->next = NULL;
944   fdata->pkt_len  = phdr->len;
945   fdata->cap_len  = phdr->caplen;
946   fdata->file_off = offset;
947   fdata->lnk_t = phdr->pkt_encap;
948   fdata->abs_secs  = phdr->ts.tv_sec;
949   fdata->abs_usecs = phdr->ts.tv_usec;
950   fdata->pseudo_header = phdr->pseudo_header;
951   fdata->cinfo = NULL;
952
953   passed = TRUE;
954   if (cf->rfcode) {
955     protocol_tree = proto_tree_create_root();
956     dissect_packet(buf, fdata, protocol_tree);
957     passed = dfilter_apply(cf->rfcode, protocol_tree, cf->pd);
958     proto_tree_free(protocol_tree);
959   }   
960   if (passed) {
961     plist_end = cf->plist_end;
962     if (plist_end != NULL)
963       plist_end->next = fdata;
964     else
965       cf->plist = fdata;
966     cf->plist_end = fdata;
967
968     cf->count++;
969     add_packet_to_packet_list(fdata, cf, buf);
970   } else
971     g_free(fdata);
972 }
973
974 void
975 filter_packets(capture_file *cf, gchar *dftext)
976 {
977   dfilter *dfcode;
978
979   if (dftext == NULL) {
980     /* The new filter is an empty filter (i.e., display all packets). */
981     dfcode = NULL;
982   } else {
983     /*
984      * We have a filter; try to compile it.
985      */
986     if (dfilter_compile(dftext, &dfcode) != 0) {
987       /* The attempt failed; report an error. */
988       simple_dialog(ESD_TYPE_WARN, NULL, dfilter_error_msg);
989       return;
990     }
991
992     /* Was it empty? */
993     if (dfcode == NULL) {
994       /* Yes - free the filter text, and set it to null. */
995       g_free(dftext);
996       dftext = NULL;
997     }
998   }
999
1000   /* We have a valid filter.  Replace the current filter. */
1001   if (cf->dfilter != NULL)
1002     g_free(cf->dfilter);
1003   cf->dfilter = dftext;
1004   if (cf->dfcode != NULL)
1005     dfilter_destroy(cf->dfcode);
1006   cf->dfcode = dfcode;
1007
1008   /* Now go through the list of packets we've read from the capture file,
1009      applying the current display filter, and, if the packet passes the
1010      display filter, add it to the summary display, appropriately
1011      colored.  (That's how we colorize the display - it's like filtering
1012      the display, only we don't install a new filter.) */
1013   colorize_packets(cf);
1014 }
1015
1016 void
1017 colorize_packets(capture_file *cf)
1018 {
1019   frame_data *fd;
1020   guint32 progbar_quantum;
1021   guint32 progbar_nextstep;
1022
1023   gtk_progress_set_activity_mode(GTK_PROGRESS(prog_bar), FALSE);
1024
1025   /* Freeze the packet list while we redo it, so we don't get any
1026      screen updates while it happens. */
1027   gtk_clist_freeze(GTK_CLIST(packet_list));
1028
1029   /* Clear it out. */
1030   gtk_clist_clear(GTK_CLIST(packet_list));
1031
1032   /* If a packet was selected, we don't know yet what row, if any, it'll
1033      get. */
1034   cf->selected_row = -1;
1035
1036   /* Iterate through the list of packets, calling a routine
1037      to run the filter on the packet, see if it matches, and
1038      put it in the display list if so.  */
1039   firstsec = 0;
1040   firstusec = 0;
1041   prevsec = 0;
1042   prevusec = 0;
1043   cf->unfiltered_count = cf->count;
1044   cf->count = 0;
1045
1046   proto_tree_is_visible = FALSE;
1047
1048   /* Update the progress bar when it gets to this value. */
1049   progbar_nextstep = 0;
1050   /* When we reach the value that triggers a progress bar update,
1051      bump that value by this amount. */
1052   progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1053   gtk_progress_bar_set_orientation(GTK_PROGRESS_BAR(prog_bar), GTK_PROGRESS_LEFT_TO_RIGHT);
1054
1055   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1056     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1057        when we update it, we have to run the GTK+ main loop to get it
1058        to repaint what's pending, and doing so may involve an "ioctl()"
1059        to see if there's any pending input from an X server, and doing
1060        that for every packet can be costly, especially on a big file. */
1061     if (cf->count >= progbar_nextstep) {
1062       /* let's not divide by zero. I should never be started
1063        * with unfiltered_count == 0, so let's assert that
1064        */
1065       g_assert(cf->unfiltered_count > 0);
1066
1067         gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1068                 (gfloat) cf->count / cf->unfiltered_count);
1069
1070       progbar_nextstep += progbar_quantum;
1071       while (gtk_events_pending())
1072         gtk_main_iteration();
1073     }
1074
1075     cf->count++;
1076
1077     wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1078
1079     add_packet_to_packet_list(fd, cf, cf->pd);
1080   }
1081  
1082   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1083
1084   if (cf->selected_row != -1) {
1085     /* We had a selected packet and it passed the filter. */
1086     gtk_clist_select_row(GTK_CLIST(packet_list), cf->selected_row, -1);
1087   } else {
1088     /* If we had one, it didn't pass the filter. */
1089     unselect_packet(cf);
1090   }
1091
1092   /* Unfreeze the packet list. */
1093   gtk_clist_thaw(GTK_CLIST(packet_list));
1094 }
1095
1096 int
1097 print_packets(capture_file *cf, print_args_t *print_args)
1098 {
1099   int         i;
1100   frame_data *fd;
1101   guint32     progbar_quantum;
1102   guint32     progbar_nextstep;
1103   guint32     count;
1104   proto_tree *protocol_tree;
1105   gint       *col_widths = NULL;
1106   gint        data_width;
1107   gboolean    print_separator;
1108
1109   cf->print_fh = open_print_dest(print_args->to_file, print_args->dest);
1110   if (cf->print_fh == NULL)
1111     return FALSE;       /* attempt to open destination failed */
1112
1113   /* XXX - printing multiple frames in PostScript looks as if it's
1114      tricky - you have to deal with page boundaries, I think -
1115      and I'll have to spend some time learning enough about
1116      PostScript to figure it out, so, for now, we only print
1117      multiple frames as text. */
1118 #if 0
1119   print_preamble(cf->print_fh);
1120 #endif
1121
1122   if (print_args->print_summary) {
1123     /* We're printing packet summaries.
1124
1125        Find the widths for each of the columns - maximum of the
1126        width of the title and the width of the data - and print
1127        the column titles. */
1128     col_widths = (gint *) g_malloc(sizeof(gint) * cf->cinfo.num_cols);
1129     for (i = 0; i < cf->cinfo.num_cols; i++) {
1130       /* Don't pad the last column. */
1131       if (i == cf->cinfo.num_cols - 1)
1132         col_widths[i] = 0;
1133       else {
1134         col_widths[i] = strlen(cf->cinfo.col_title[i]);
1135         data_width = get_column_char_width(get_column_format(i));
1136         if (data_width > col_widths[i])
1137           col_widths[i] = data_width;
1138       }
1139
1140       /* Right-justify the packet number column. */
1141       if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1142         fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_title[i]);
1143       else
1144         fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_title[i]);
1145       if (i == cf->cinfo.num_cols - 1)
1146         fputc('\n', cf->print_fh);
1147       else
1148         fputc(' ', cf->print_fh);
1149     }
1150   }
1151
1152   print_separator = FALSE;
1153   proto_tree_is_visible = TRUE;
1154
1155   /* Update the progress bar when it gets to this value. */
1156   progbar_nextstep = 0;
1157   /* When we reach the value that triggers a progress bar update,
1158      bump that value by this amount. */
1159   progbar_quantum = cf->unfiltered_count/N_PROGBAR_UPDATES;
1160   /* Count of packets we've looked at. */
1161   count = 0;
1162
1163   /* Iterate through the list of packets, printing the packets that
1164      were selected by the current display filter.  */
1165   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1166     /* Update the progress bar, but do it only N_PROGBAR_UPDATES times;
1167        when we update it, we have to run the GTK+ main loop to get it
1168        to repaint what's pending, and doing so may involve an "ioctl()"
1169        to see if there's any pending input from an X server, and doing
1170        that for every packet can be costly, especially on a big file. */
1171     if (count >= progbar_nextstep) {
1172       /* let's not divide by zero. I should never be started
1173        * with unfiltered_count == 0, so let's assert that
1174        */
1175       g_assert(cf->unfiltered_count > 0);
1176
1177       gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar),
1178         (gfloat) count / cf->unfiltered_count);
1179       progbar_nextstep += progbar_quantum;
1180       while (gtk_events_pending())
1181         gtk_main_iteration();
1182     }
1183     count++;
1184
1185     if (fd->passed_dfilter) {
1186       wtap_seek_read (cf->cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1187       if (print_args->print_summary) {
1188         /* Fill in the column information, but don't bother creating
1189            the logical protocol tree. */
1190         fd->cinfo = &cf->cinfo;
1191         for (i = 0; i < fd->cinfo->num_cols; i++) {
1192           fd->cinfo->col_data[i][0] = '\0';
1193         }
1194         dissect_packet(cf->pd, fd, NULL);
1195         fill_in_columns(fd);
1196         for (i = 0; i < cf->cinfo.num_cols; i++) {
1197           /* Right-justify the packet number column. */
1198           if (cf->cinfo.col_fmt[i] == COL_NUMBER)
1199             fprintf(cf->print_fh, "%*s", col_widths[i], cf->cinfo.col_data[i]);
1200           else
1201             fprintf(cf->print_fh, "%-*s", col_widths[i], cf->cinfo.col_data[i]);
1202           if (i == cf->cinfo.num_cols - 1)
1203             fputc('\n', cf->print_fh);
1204           else
1205             fputc(' ', cf->print_fh);
1206         }
1207       } else {
1208         if (print_separator)
1209           fputc('\n', cf->print_fh);
1210
1211         /* Create the logical protocol tree. */
1212         protocol_tree = proto_tree_create_root();
1213         dissect_packet(cf->pd, fd, protocol_tree);
1214
1215         /* Print the information in that tree. */
1216         proto_tree_print(FALSE, print_args, (GNode *)protocol_tree,
1217                         cf->pd, fd, cf->print_fh);
1218
1219         proto_tree_free(protocol_tree);
1220
1221         if (print_args->print_hex) {
1222           /* Print the full packet data as hex. */
1223           print_hex_data(cf->print_fh, cf->pd, fd->cap_len);
1224         }
1225
1226         /* Print a blank line if we print anything after this. */
1227         print_separator = TRUE;
1228       }
1229     }
1230   }
1231
1232   if (col_widths != NULL)
1233     g_free(col_widths);
1234
1235 #if 0
1236   print_finale(cf->print_fh);
1237 #endif
1238
1239   close_print_dest(print_args->to_file, cf->print_fh);
1240  
1241   gtk_progress_bar_update(GTK_PROGRESS_BAR(prog_bar), 0);
1242
1243   cf->print_fh = NULL;
1244   return TRUE;
1245 }
1246
1247 /* Scan through the packet list and change all columns that use the
1248    "command-line-specified" time stamp format to use the current
1249    value of that format. */
1250 void
1251 change_time_formats(capture_file *cf)
1252 {
1253   frame_data *fd;
1254   int i;
1255   GtkStyle  *pl_style;
1256
1257   /* Freeze the packet list while we redo it, so we don't get any
1258      screen updates while it happens. */
1259   freeze_clist(cf);
1260
1261   /* Iterate through the list of packets, checking whether the packet
1262      is in a row of the summary list and, if so, whether there are
1263      any columns that show the time in the "command-line-specified"
1264      format and, if so, update that row. */
1265   for (fd = cf->plist; fd != NULL; fd = fd->next) {
1266     if (fd->row != -1) {
1267       /* This packet is in the summary list, on row "fd->row". */
1268
1269       /* XXX - there really should be a way of checking "cf->cinfo" for this;
1270          the answer isn't going to change from packet to packet, so we should
1271          simply skip all the "change_time_formats()" work if we're not
1272          changing anything. */
1273       fd->cinfo = &cf->cinfo;
1274       if (check_col(fd, COL_CLS_TIME)) {
1275         /* There are columns that show the time in the "command-line-specified"
1276            format; update them. */
1277         for (i = 0; i < cf->cinfo.num_cols; i++) {
1278           if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1279             /* This is one of the columns that shows the time in
1280                "command-line-specified" format; update it. */
1281             cf->cinfo.col_data[i][0] = '\0';
1282             col_set_cls_time(fd, i);
1283             gtk_clist_set_text(GTK_CLIST(packet_list), fd->row, i,
1284                           cf->cinfo.col_data[i]);
1285           }
1286         }
1287       }
1288     }
1289   }
1290
1291   /* Set the column widths of those columns that show the time in
1292      "command-line-specified" format. */
1293   pl_style = gtk_widget_get_style(packet_list);
1294   for (i = 0; i < cf->cinfo.num_cols; i++) {
1295     if (cf->cinfo.fmt_matx[i][COL_CLS_TIME]) {
1296       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1297         get_column_width(COL_CLS_TIME, pl_style->font));
1298     }
1299   }
1300
1301   /* Unfreeze the packet list. */
1302   thaw_clist(cf);
1303 }
1304
1305 static void
1306 clear_tree_and_hex_views(void)
1307 {
1308   GList *selection;
1309   GtkWidget *tmp_item;
1310
1311   /* Clear the hex dump. */
1312   gtk_text_freeze(GTK_TEXT(byte_view));
1313   gtk_text_set_point(GTK_TEXT(byte_view), 0);
1314   gtk_text_forward_delete(GTK_TEXT(byte_view),
1315     gtk_text_get_length(GTK_TEXT(byte_view)));
1316   gtk_text_thaw(GTK_TEXT(byte_view));
1317
1318   /* Deselect any selected tree item. gtktree.c should
1319    * do this when we clear_items, but it doesn't. I copied
1320    * this while() loop from gtktree.c, gtk_real_tree_select_child()
1321    */
1322   if (GTK_TREE(tree_view)->root_tree) {
1323           selection = GTK_TREE(tree_view)->root_tree->selection;
1324           while (selection) {
1325                   tmp_item = selection->data;
1326                   gtk_tree_item_deselect(GTK_TREE_ITEM(tmp_item));
1327                   gtk_widget_unref(tmp_item);
1328                   selection = selection->next;
1329           }
1330           g_list_free(GTK_TREE(tree_view)->root_tree->selection);
1331           GTK_TREE(tree_view)->root_tree->selection = NULL;
1332   }
1333
1334   /* Clear the protocol tree view. The length arg of -1
1335    * means to clear all items up to the end. */
1336   gtk_tree_clear_items(GTK_TREE(tree_view), 0, -1);
1337 }
1338
1339
1340 /* Select the packet on a given row. */
1341 void
1342 select_packet(capture_file *cf, int row)
1343 {
1344   frame_data *fd;
1345   int i;
1346
1347   /* Clear out whatever's currently in the hex dump. */
1348   gtk_text_freeze(GTK_TEXT(byte_view));
1349   gtk_text_set_point(GTK_TEXT(byte_view), 0);
1350   gtk_text_forward_delete(GTK_TEXT(byte_view),
1351     gtk_text_get_length(GTK_TEXT(byte_view)));
1352
1353   /* Search through the list of frames to see which one is in
1354      this row. */
1355   for (fd = cf->plist, i = 0; fd != NULL; fd = fd->next, i++) {
1356     if (fd->row == row)
1357       break;
1358   }
1359
1360   g_assert(fd != NULL);
1361
1362   cf->fd = fd;
1363
1364   /* Remember the ordinal number of that frame. */
1365   cf->selected_packet = i;
1366
1367   /* Get the data in that frame. */
1368   wtap_seek_read (cf-> cd_t, cf->fh, fd->file_off, cf->pd, fd->cap_len);
1369
1370   /* Create the logical protocol tree. */
1371   if (cf->protocol_tree)
1372       proto_tree_free(cf->protocol_tree);
1373   cf->protocol_tree = proto_tree_create_root();
1374   proto_tree_is_visible = TRUE;
1375   dissect_packet(cf->pd, cf->fd, cf->protocol_tree);
1376
1377   /* Display the GUI protocol tree and hex dump. */
1378   clear_tree_and_hex_views();
1379   proto_tree_draw(cf->protocol_tree, tree_view);
1380   packet_hex_print(GTK_TEXT(byte_view), cf->pd, cf->fd->cap_len, -1, -1);
1381   gtk_text_thaw(GTK_TEXT(byte_view));
1382
1383   /* A packet is selected, so "File/Print Packet" has something to print. */
1384   set_menu_sensitivity("/File/Print Packet", TRUE);
1385   set_menu_sensitivity("/Display/Collapse All", TRUE);
1386   set_menu_sensitivity("/Display/Expand All", TRUE);
1387 }
1388
1389 /* Unselect the selected packet, if any. */
1390 void
1391 unselect_packet(capture_file *cf)
1392 {
1393   cf->selected_packet = -1;     /* nothing there to be selected */
1394   cf->selected_row = -1;
1395
1396   /* Destroy the protocol tree for that packet. */
1397   if (cf->protocol_tree != NULL) {
1398     proto_tree_free(cf->protocol_tree);
1399     cf->protocol_tree = NULL;
1400   }
1401
1402   /* Clear out the display of that packet. */
1403   clear_tree_and_hex_views();
1404
1405   /* No packet is selected, so "File/Print Packet" has nothing to print. */
1406   set_menu_sensitivity("/File/Print Packet", FALSE);
1407   set_menu_sensitivity("/Display/Collapse All", FALSE);
1408   set_menu_sensitivity("/Display/Expand All", FALSE);
1409 }
1410
1411 static void
1412 freeze_clist(capture_file *cf)
1413 {
1414   int i;
1415
1416   /* Make the column sizes static, so they don't adjust while
1417      we're reading the capture file (freezing the clist doesn't
1418      seem to suffice). */
1419   for (i = 0; i < cf->cinfo.num_cols; i++)
1420     gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, FALSE);
1421   gtk_clist_freeze(GTK_CLIST(packet_list));
1422 }
1423
1424 static void
1425 thaw_clist(capture_file *cf)
1426 {
1427   int i;
1428
1429   for (i = 0; i < cf->cinfo.num_cols; i++) {
1430     if (get_column_resize_type(cf->cinfo.col_fmt[i]) == RESIZE_MANUAL) {
1431       /* Set this column's width to the appropriate value. */
1432       gtk_clist_set_column_width(GTK_CLIST(packet_list), i,
1433                                 cf->cinfo.col_width[i]);
1434     } else {
1435       /* Make this column's size dynamic, so that it adjusts to the
1436          appropriate size. */
1437       gtk_clist_set_column_auto_resize(GTK_CLIST(packet_list), i, TRUE);
1438     }
1439   }
1440   gtk_clist_thaw(GTK_CLIST(packet_list));
1441
1442   /* Hopefully, the columns have now gotten their appropriate sizes;
1443      make them resizeable - a column that auto-resizes cannot be
1444      resized by the user, and *vice versa*. */
1445   for (i = 0; i < cf->cinfo.num_cols; i++)
1446     gtk_clist_set_column_resizeable(GTK_CLIST(packet_list), i, TRUE);
1447 }
1448
1449 /* Tries to mv a file. If unsuccessful, tries to cp the file.
1450  * Returns 0 on failure to do either, 1 on success of either
1451  */
1452 int
1453 file_mv(char *from, char *to)
1454 {
1455
1456 #define COPY_BUFFER_SIZE        8192
1457
1458         int retval;
1459
1460 #ifndef WIN32
1461         /* try a hard link */
1462         retval = link(from, to);
1463
1464         /* or try a copy */
1465         if (retval < 0) {
1466 #endif
1467                 retval = file_cp(from, to);
1468                 if (!retval) {
1469                         return 0;
1470                 }
1471 #ifndef WIN32
1472         }
1473 #endif
1474
1475         unlink(from);
1476         return 1;
1477 }
1478
1479 /* Copies a file.
1480  * Returns 0 on failure to do either, 1 on success of either
1481  */
1482 int
1483 file_cp(char *from, char *to)
1484 {
1485
1486 #define COPY_BUFFER_SIZE        8192
1487
1488         int from_fd, to_fd, nread, nwritten;
1489         char *buffer;
1490
1491         buffer = g_malloc(COPY_BUFFER_SIZE);
1492
1493         from_fd = open(from, O_RDONLY);
1494         if (from_fd < 0) {
1495                 simple_dialog(ESD_TYPE_WARN, NULL,
1496                         file_open_error_message(errno, TRUE), from);
1497                 return 0;
1498         }
1499
1500         to_fd = creat(to, 0644);
1501         if (to_fd < 0) {
1502                 simple_dialog(ESD_TYPE_WARN, NULL,
1503                         file_open_error_message(errno, TRUE), to);
1504                 close(from_fd);
1505                 return 0;
1506         }
1507
1508         while( (nread = read(from_fd, buffer, COPY_BUFFER_SIZE)) > 0) {
1509                 nwritten = write(to_fd, buffer, nread);
1510                 if (nwritten < nread) {
1511                         if (nwritten < 0) {
1512                                 simple_dialog(ESD_TYPE_WARN, NULL,
1513                                         file_write_error_message(errno), to);
1514                         } else {
1515                                 simple_dialog(ESD_TYPE_WARN, NULL,
1516 "The file \"%s\" could not be saved: tried writing %d, wrote %d.\n",
1517                                         to, nread, nwritten);
1518                         }
1519                         close(from_fd);
1520                         close(to_fd);
1521                         return 0;
1522                 }
1523         }
1524         if (nread < 0) {
1525                 simple_dialog(ESD_TYPE_WARN, NULL,
1526                         file_read_error_message(errno), from);
1527                 close(from_fd);
1528                 close(to_fd);
1529                 return 0;
1530         }
1531         close(from_fd);
1532         close(to_fd);
1533
1534         return 1;
1535 }
1536
1537 char *
1538 file_open_error_message(int err, int for_writing)
1539 {
1540   char *errmsg;
1541   static char errmsg_errno[1024+1];
1542
1543   switch (err) {
1544
1545   case WTAP_ERR_NOT_REGULAR_FILE:
1546     errmsg = "The file \"%s\" is invalid.";
1547     break;
1548
1549   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1550   case WTAP_ERR_UNSUPPORTED:
1551     errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
1552     break;
1553
1554   case WTAP_ERR_BAD_RECORD:
1555     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1556     break;
1557
1558   case WTAP_ERR_CANT_OPEN:
1559     if (for_writing)
1560       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1561     else
1562       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1563     break;
1564
1565   case WTAP_ERR_SHORT_READ:
1566     errmsg = "The file \"%s\" appears to have been cut short"
1567              " in the middle of a packet.";
1568     break;
1569
1570   case ENOENT:
1571     if (for_writing)
1572       errmsg = "The path to the file \"%s\" does not exist.";
1573     else
1574       errmsg = "The file \"%s\" does not exist.";
1575     break;
1576
1577   case EACCES:
1578     if (for_writing)
1579       errmsg = "You do not have permission to create or write to the file \"%s\".";
1580     else
1581       errmsg = "You do not have permission to read the file \"%s\".";
1582     break;
1583
1584   default:
1585     sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
1586                                 wtap_strerror(err));
1587     errmsg = errmsg_errno;
1588     break;
1589   }
1590   return errmsg;
1591 }
1592
1593 char *
1594 file_read_error_message(int err)
1595 {
1596   static char errmsg_errno[1024+1];
1597
1598   sprintf(errmsg_errno, "An error occurred while reading from the file \"%%s\": %s.",
1599                                 wtap_strerror(err));
1600   return errmsg_errno;
1601 }
1602
1603 char *
1604 file_write_error_message(int err)
1605 {
1606   char *errmsg;
1607   static char errmsg_errno[1024+1];
1608
1609   switch (err) {
1610
1611   case ENOSPC:
1612     errmsg = "The file \"%s\" could not be saved because there is no space left on the file system.";
1613     break;
1614
1615 #ifdef EDQUOT
1616   case EDQUOT:
1617     errmsg = "The file \"%s\" could not be saved because you are too close to, or over, your disk quota.";
1618     break;
1619 #endif
1620
1621   default:
1622     sprintf(errmsg_errno, "An error occurred while writing to the file \"%%s\": %s.",
1623                                 wtap_strerror(err));
1624     errmsg = errmsg_errno;
1625     break;
1626   }
1627   return errmsg;
1628 }