Clear "fdata->data_src" when initializing a "frame_data" structure.
[obnox/wireshark/wip.git] / tethereal.c
1 /* tethereal.c
2  *
3  * $Id: tethereal.c,v 1.70 2001/03/24 09:24:41 guy Exp $
4  *
5  * Ethereal - Network traffic analyzer
6  * By Gerald Combs <gerald@zing.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
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
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <stdlib.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <locale.h>
35
36 #ifdef HAVE_UNISTD_H
37 #include <unistd.h>
38 #endif
39
40 #include <errno.h>
41
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
44 #endif
45
46 #ifdef HAVE_SYS_STAT_H
47 #include <sys/stat.h>
48 #endif
49
50 #ifdef HAVE_FCNTL_H
51 #include <fcntl.h>
52 #endif
53
54 #include <signal.h>
55
56 #ifdef HAVE_LIBPCAP
57 #include <pcap.h>
58 #endif
59
60 #ifdef NEED_SNPRINTF_H
61 # include "snprintf.h"
62 #endif
63
64 #if defined(HAVE_UCD_SNMP_SNMP_H)
65 #ifdef HAVE_UCD_SNMP_VERSION_H
66 #include <ucd-snmp/version.h>
67 #endif /* HAVE_UCD_SNMP_VERSION_H */
68 #elif defined(HAVE_SNMP_SNMP_H)
69 #ifdef HAVE_SNMP_VERSION_H
70 #include <snmp/version.h>
71 #endif /* HAVE_SNMP_VERSION_H */
72 #endif /* SNMP */
73
74 #ifdef NEED_STRERROR_H
75 #include "strerror.h"
76 #endif
77
78 #ifdef NEED_GETOPT_H
79 #include "getopt.h"
80 #endif
81
82 #include <glib.h>
83 #include <epan.h>
84
85 #include "globals.h"
86 #include "timestamp.h"
87 #include "packet.h"
88 #include "file.h"
89 #include "prefs.h"
90 #include "column.h"
91 #include "print.h"
92 #include "resolv.h"
93 #include "util.h"
94 #include "conversation.h"
95 #include "plugins.h"
96
97 static guint32 firstsec, firstusec;
98 static guint32 prevsec, prevusec;
99 static gchar   comp_info_str[256];
100 static gboolean verbose;
101 static gboolean print_hex;
102 static gboolean line_buffered;
103
104 #ifdef HAVE_LIBPCAP
105 typedef struct _loop_data {
106   gint           linktype;
107   pcap_t        *pch;
108   wtap_dumper   *pdh;
109 } loop_data;
110
111 static loop_data ld;
112
113 static int capture(int, int);
114 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
115   const u_char *);
116 static void capture_cleanup(int);
117 #endif
118
119 typedef struct {
120   capture_file *cf;
121   wtap_dumper *pdh;
122 } cb_args_t;
123
124 static int load_cap_file(capture_file *, int);
125 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
126     union wtap_pseudo_header *, const u_char *);
127 static void show_capture_file_io_error(const char *, int, gboolean);
128 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
129     union wtap_pseudo_header *, const u_char *);
130
131 packet_info  pi;
132 capture_file cfile;
133 FILE        *data_out_file = NULL;
134 guint        main_ctx, file_ctx;
135 ts_type timestamp_type = RELATIVE;
136 #ifdef HAVE_LIBPCAP
137 static int promisc_mode = TRUE;
138 #endif
139
140 static void 
141 print_usage(void)
142 {
143   int i;
144
145   fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
146           VERSION, comp_info_str);
147 #ifdef HAVE_LIBPCAP
148   fprintf(stderr, "t%s [ -vVhlp ] [ -c count ] [ -f <capture filter> ]\n", PACKAGE);
149   fprintf(stderr, "\t[ -F <capture file type> ] [ -i interface ] [ -n ]\n");
150   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
151   fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
152 #else
153   fprintf(stderr, "t%s [ -vVhl ] [ -F <capture file type> ] [ -n ]\n", PACKAGE);
154   fprintf(stderr, "\t[ -o <preference setting> ] ... [ -r infile ] [ -R <read filter> ]\n");
155   fprintf(stderr, "\t[ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
156 #endif
157   fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
158   for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
159     if (wtap_dump_can_open(i))
160       fprintf(stderr, "\t%s - %s\n",
161         wtap_file_type_short_string(i), wtap_file_type_string(i));
162   }
163   fprintf(stderr, "\tdefault is libpcap\n");
164 }
165
166 int
167 main(int argc, char *argv[])
168 {
169   int                  opt, i;
170   extern char         *optarg;
171   gboolean             arg_error = FALSE;
172 #ifdef HAVE_LIBPCAP
173 #ifdef WIN32
174   char pcap_version[] = "0.4a6";
175 #else
176   extern char          pcap_version[];
177 #endif
178 #endif
179
180 #ifdef WIN32
181   WSADATA               wsaData;
182 #endif
183
184   char                *gpf_path, *pf_path;
185   int                  gpf_open_errno, pf_open_errno;
186   int                  err;
187 #ifdef HAVE_LIBPCAP
188   gboolean             capture_filter_specified = FALSE;
189   int                  packet_count = 0;
190   GList               *if_list;
191   gchar                err_str[PCAP_ERRBUF_SIZE];
192 #else
193   gboolean             capture_option_specified = FALSE;
194 #endif
195   int                 out_file_type = WTAP_FILE_PCAP;
196   gchar               *cf_name = NULL, *rfilter = NULL;
197   dfilter_t           *rfcode = NULL;
198   e_prefs             *prefs;
199
200   /* Register all dissectors; we must do this before checking for the
201      "-G" flag, as the "-G" flag dumps a list of fields registered
202      by the dissectors, and we must do it before we read the preferences,
203      in case any dissectors register preferences. */
204   epan_init(PLUGIN_DIR);
205
206   /* Now register the preferences for any non-dissector modules.
207      We must do that before we read the preferences as well. */
208   prefs_register_modules();
209
210   /* If invoked with the "-G" flag, we dump out a glossary of
211      display filter symbols.
212
213      We do this here to mirror what happens in the GTK+ version, although
214      it's not necessary here. */
215   if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
216     proto_registrar_dump();
217     exit(0);
218   }
219
220   /* Set the C-language locale to the native environment. */
221   setlocale(LC_ALL, "");
222
223   prefs = read_prefs(&gpf_open_errno, &gpf_path, &pf_open_errno, &pf_path);
224   if (gpf_path != NULL) {
225     fprintf(stderr, "Can't open global preferences file \"%s\": %s.\n", pf_path,
226         strerror(gpf_open_errno));
227   }
228   if (pf_path != NULL) {
229     fprintf(stderr, "Can't open your preferences file \"%s\": %s.\n", pf_path,
230         strerror(pf_open_errno));
231   }
232     
233   /* Initialize the capture file struct */
234   cfile.plist           = NULL;
235   cfile.plist_end       = NULL;
236   cfile.wth             = NULL;
237   cfile.filename        = NULL;
238   cfile.user_saved      = FALSE;
239   cfile.is_tempfile     = FALSE;
240   cfile.rfcode          = NULL;
241   cfile.dfilter         = NULL;
242   cfile.dfcode          = NULL;
243 #ifdef HAVE_LIBPCAP
244   cfile.cfilter         = g_strdup("");
245 #endif
246   cfile.iface           = NULL;
247   cfile.save_file       = NULL;
248   cfile.save_file_fd    = -1;
249   cfile.snap            = WTAP_MAX_PACKET_SIZE;
250   cfile.count           = 0;
251   col_init(&cfile.cinfo, prefs->num_cols);
252
253   /* Assemble the compile-time options */
254   snprintf(comp_info_str, 256,
255 #ifdef GTK_MAJOR_VERSION
256     "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
257     GTK_MICRO_VERSION,
258 #else
259     "GTK+ (version unknown), %s%s, %s%s, %s%s",
260 #endif
261
262 #ifdef HAVE_LIBPCAP
263    "with libpcap ", pcap_version,
264 #else
265    "without libpcap", "",
266 #endif
267
268 #ifdef HAVE_LIBZ
269 #ifdef ZLIB_VERSION
270    "with libz ", ZLIB_VERSION,
271 #else /* ZLIB_VERSION */
272    "with libz ", "(version unknown)",
273 #endif /* ZLIB_VERSION */
274 #else /* HAVE_LIBZ */
275    "without libz", "",
276 #endif /* HAVE_LIBZ */
277
278 /* Oh, this is pretty */
279 #if defined(HAVE_UCD_SNMP_SNMP_H)
280 #ifdef HAVE_UCD_SNMP_VERSION_H
281    "with UCD SNMP ", VersionInfo
282 #else /* HAVE_UCD_SNMP_VERSION_H */
283    "with UCD SNMP ", "(version unknown)"
284 #endif /* HAVE_UCD_SNMP_VERSION_H */
285 #elif defined(HAVE_SNMP_SNMP_H)
286 #ifdef HAVE_SNMP_VERSION_H
287    "with CMU SNMP ", snmp_Version()
288 #else /* HAVE_SNMP_VERSION_H */
289    "with CMU SNMP ", "(version unknown)"
290 #endif /* HAVE_SNMP_VERSION_H */
291 #else /* no SNMP */
292    "without SNMP", ""
293 #endif
294    );
295     
296   /* Now get our args */
297   while ((opt = getopt(argc, argv, "c:Df:F:hi:lno:pr:R:s:t:vw:Vx")) != EOF) {
298     switch (opt) {
299       case 'c':        /* Capture xxx packets */
300 #ifdef HAVE_LIBPCAP
301         packet_count = atoi(optarg);
302 #else
303         capture_option_specified = TRUE;
304         arg_error = TRUE;
305 #endif
306         break;
307       case 'f':
308 #ifdef HAVE_LIBPCAP
309         capture_filter_specified = TRUE;
310         cfile.cfilter = g_strdup(optarg);
311 #else
312         capture_option_specified = TRUE;
313         arg_error = TRUE;
314 #endif
315         break;
316       case 'F':
317         out_file_type = wtap_short_string_to_file_type(optarg);
318         if (out_file_type < 0) {
319           fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
320                         optarg);
321           exit(1);
322         }
323         break;
324       case 'h':        /* Print help and exit */
325         print_usage();
326         exit(0);
327         break;
328       case 'i':        /* Use interface xxx */
329 #ifdef HAVE_LIBPCAP
330         cfile.iface = g_strdup(optarg);
331 #else
332         capture_option_specified = TRUE;
333         arg_error = TRUE;
334 #endif
335         break;
336       case 'l':        /* "Line-buffer" standard output */
337         /* This isn't line-buffering, strictly speaking, it's just
338            flushing the standard output after the information for
339            each packet is printed; however, that should be good
340            enough for all the purposes to which "-l" is put.
341
342            See the comment in "wtap_dispatch_cb_print()" for an
343            explanation of why we do that, and why we don't just
344            use "setvbuf()" to make the standard output line-buffered
345            (short version: in Windows, "line-buffered" is the same
346            as "fully-buffered", and the output buffer is only flushed
347            when it fills up). */
348         line_buffered = TRUE;
349         break;
350       case 'n':        /* No name resolution */
351         g_resolving_actif = 0;
352         break;
353       case 'o':        /* Override preference from command line */
354         switch (prefs_set_pref(optarg)) {
355
356         case PREFS_SET_SYNTAX_ERR:
357           fprintf(stderr, "tethereal: Invalid -o flag \"%s\"\n", optarg);
358           exit(1);
359           break;
360
361         case PREFS_SET_NO_SUCH_PREF:
362           fprintf(stderr, "tethereal: -o flag \"%s\" specifies unknown preference\n",
363                         optarg);
364           exit(1);
365           break;
366         }
367         break;
368       case 'p':        /* Don't capture in promiscuous mode */
369 #ifdef HAVE_LIBPCAP
370         promisc_mode = 0;
371 #else
372         capture_option_specified = TRUE;
373         arg_error = TRUE;
374 #endif
375         break;
376       case 'r':        /* Read capture file xxx */
377         cf_name = g_strdup(optarg);
378         break;
379       case 'R':        /* Read file filter */
380         rfilter = optarg;
381         break;
382       case 's':        /* Set the snapshot (capture) length */
383 #ifdef HAVE_LIBPCAP
384         cfile.snap = atoi(optarg);
385 #else
386         capture_option_specified = TRUE;
387         arg_error = TRUE;
388 #endif
389         break;
390       case 't':        /* Time stamp type */
391         if (strcmp(optarg, "r") == 0)
392           timestamp_type = RELATIVE;
393         else if (strcmp(optarg, "a") == 0)
394           timestamp_type = ABSOLUTE;
395         else if (strcmp(optarg, "ad") == 0)
396           timestamp_type = ABSOLUTE_WITH_DATE;
397         else if (strcmp(optarg, "d") == 0)
398           timestamp_type = DELTA;
399         else {
400           fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
401             optarg);
402           fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
403           fprintf(stderr, "\"ad\" for absolute with date, or \"d\" for delta.\n");
404           exit(1);
405         }
406         break;
407       case 'v':        /* Show version and exit */
408         printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
409         exit(0);
410         break;
411       case 'w':        /* Write to capture file xxx */
412         cfile.save_file = g_strdup(optarg);
413         break;
414       case 'V':        /* Verbose */
415         verbose = TRUE;
416         break;
417       case 'x':        /* Print packet data in hex (and ASCII) */
418         print_hex = TRUE;
419         break;
420     }
421   }
422   
423   /* If no capture filter or read filter has been specified, and there are
424      still command-line arguments, treat them as the tokens of a capture
425      filter (if no "-r" flag was specified) or a read filter (if a "-r"
426      flag was specified. */
427   if (optind < argc) {
428     if (cf_name != NULL) {
429       if (rfilter != NULL) {
430         fprintf(stderr,
431 "tethereal: Read filters were specified both with \"-R\" and with additional command-line arguments\n");
432         exit(2);
433       }
434       rfilter = get_args_as_string(argc, argv, optind);
435     } else {
436 #ifdef HAVE_LIBPCAP
437       if (capture_filter_specified) {
438         fprintf(stderr,
439 "tethereal: Capture filters were specified both with \"-f\" and with additional command-line arguments\n");
440         exit(2);
441       }
442       cfile.cfilter = get_args_as_string(argc, argv, optind);
443 #else
444       capture_option_specified = TRUE;
445 #endif
446     }
447   }
448
449 #ifdef WIN32
450   /* Start windows sockets */
451   WSAStartup( MAKEWORD( 1, 1 ), &wsaData );
452 #endif
453
454   /* Notify all registered modules that have had any of their preferences
455      changed either from one of the preferences file or from the command
456      line that its preferences have changed. */
457   prefs_apply_all();
458
459 #ifndef HAVE_LIBPCAP
460   if (capture_option_specified)
461     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
462 #endif
463   if (arg_error)
464     print_usage();
465
466   /* Build the column format array */  
467   for (i = 0; i < cfile.cinfo.num_cols; i++) {
468     cfile.cinfo.col_fmt[i] = get_column_format(i);
469     cfile.cinfo.col_title[i] = g_strdup(get_column_title(i));
470     cfile.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
471       NUM_COL_FMTS);
472     get_column_format_matches(cfile.cinfo.fmt_matx[i], cfile.cinfo.col_fmt[i]);
473     cfile.cinfo.col_data[i] = NULL;
474     if (cfile.cinfo.col_fmt[i] == COL_INFO)
475       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
476     else
477       cfile.cinfo.col_buf[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
478   }
479
480   if (cfile.snap < 1)
481     cfile.snap = WTAP_MAX_PACKET_SIZE;
482   else if (cfile.snap < MIN_PACKET_SIZE)
483     cfile.snap = MIN_PACKET_SIZE;
484   
485   if (rfilter != NULL) {
486     if (!dfilter_compile(rfilter, &rfcode)) {
487       fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
488       epan_cleanup();
489       exit(2);
490     }
491   }
492   cfile.rfcode = rfcode;
493   if (cf_name) {
494     err = open_cap_file(cf_name, FALSE, &cfile);
495     if (err != 0) {
496       epan_cleanup();
497       exit(2);
498     }
499     err = load_cap_file(&cfile, out_file_type);
500     if (err != 0) {
501       epan_cleanup();
502       exit(2);
503     }
504     cf_name[0] = '\0';
505   } else {
506     /* No capture file specified, so we're supposed to do a live capture;
507        do we have support for live captures? */
508 #ifdef HAVE_LIBPCAP
509     /* Yes; did the user specify an interface to use? */
510     if (cfile.iface == NULL) {
511         /* No - pick the first one from the list of interfaces. */
512         if_list = get_interface_list(&err, err_str);
513         if (if_list == NULL) {
514             switch (err) {
515
516             case CANT_GET_INTERFACE_LIST:
517                 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
518                         err_str);
519                 break;
520
521             case NO_INTERFACES_FOUND:
522                 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
523                 break;
524             }
525             exit(2);
526         }
527         cfile.iface = g_strdup(if_list->data);  /* first interface */
528         free_interface_list(if_list);
529     }
530     capture(packet_count, out_file_type);
531 #else
532     /* No - complain. */
533     fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
534     exit(2);
535 #endif
536   }
537
538   epan_cleanup();
539
540   exit(0);
541 }
542
543 #ifdef HAVE_LIBPCAP
544 /* Do the low-level work of a capture.
545    Returns TRUE if it succeeds, FALSE otherwise. */
546 static int
547 capture(int packet_count, int out_file_type)
548 {
549   gchar       err_str[PCAP_ERRBUF_SIZE];
550   bpf_u_int32 netnum, netmask;
551   struct bpf_program fcode;
552   void        (*oldhandler)(int);
553   int         err, inpkts;
554   char        errmsg[1024+1];
555 #ifndef _WIN32
556   static const char ppamsg[] = "can't find PPA for ";
557   char       *libpcap_warn;
558 #endif
559   struct pcap_stat stats;
560
561   /* Initialize the table of conversations. */
562   epan_conversation_init();
563
564   /* Initialize protocol-specific variables */
565   init_all_protocols();
566
567   ld.linktype       = WTAP_ENCAP_UNKNOWN;
568   ld.pdh            = NULL;
569
570   /* Open the network interface to capture from it. */
571   ld.pch = pcap_open_live(cfile.iface, cfile.snap, promisc_mode, 1000, err_str);
572
573   if (ld.pch == NULL) {
574     /* Well, we couldn't start the capture. */
575 #ifdef _WIN32
576     /* On Win32 OSes, the capture devices are probably available to all
577        users; don't warn about permissions problems.
578
579        Do, however, warn that Token Ring and PPP devices aren't supported. */
580     snprintf(errmsg, sizeof errmsg,
581         "The capture session could not be initiated (%s).\n"
582         "Please check that you have the proper interface specified.\n"
583         "\n"
584         "Note that the driver Tethereal uses for packet capture on Windows\n"
585         "doesn't support capturing on Token Ring interfaces, and doesn't\n"
586         "support capturing on PPP/WAN interfaces in Windows NT/2000.\n",
587         err_str);
588 #else
589       /* If we got a "can't find PPA for XXX" message, warn the user (who
590          is running Ethereal on HP-UX) that they don't have a version
591          of libpcap patched to properly handle HP-UX (the patched version
592          says "can't find /dev/dlpi PPA for XXX" rather than "can't find
593          PPA for XXX"). */
594       if (strncmp(err_str, ppamsg, sizeof ppamsg - 1) == 0)
595         libpcap_warn =
596           "\n\n"
597           "You are running Tethereal with a version of the libpcap library\n"
598           "that doesn't handle HP-UX network devices well; this means that\n"
599           "Tethereal may not be able to capture packets.\n"
600           "\n"
601           "To fix this, you will need to download the source to Tethereal\n"
602           "from www.ethereal.com if you have not already done so, read\n"
603           "the instructions in the \"README.hpux\" file in the source\n"
604           "distribution, download the source to libpcap if you have not\n"
605           "already done so, patch libpcap as per the instructions, rebuild\n"
606           "and install libpcap, and then build Tethereal (if you have already\n"
607           "built Tethereal from source, do a \"make distclean\" and re-run\n"
608           "configure before building).";
609       else
610         libpcap_warn = "";
611     snprintf(errmsg, sizeof errmsg,
612       "The capture session could not be initiated (%s).\n"
613       "Please check to make sure you have sufficient permissions, and that\n"
614       "you have the proper interface specified.%s", err_str, libpcap_warn);
615 #endif
616     goto error;
617   }
618
619   if (cfile.cfilter) {
620     /* A capture filter was specified; set it up. */
621     if (pcap_lookupnet (cfile.iface, &netnum, &netmask, err_str) < 0) {
622       /*
623        * Well, we can't get the netmask for this interface; it's used
624        * only for filters that check for broadcast IP addresses, so
625        * we just warn the user, and punt and use 0.
626        */
627       fprintf(stderr, 
628         "Warning:  Couldn't obtain netmask info (%s)\n.", err_str);
629       netmask = 0;
630     }
631     if (pcap_compile(ld.pch, &fcode, cfile.cfilter, 1, netmask) < 0) {
632       snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
633         pcap_geterr(ld.pch));
634       goto error;
635     }
636     if (pcap_setfilter(ld.pch, &fcode) < 0) {
637       snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
638         pcap_geterr(ld.pch));
639       goto error;
640     }
641   }
642
643   ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
644   if (cfile.save_file != NULL) {
645     /* Set up to write to the capture file. */
646     if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
647       strcpy(errmsg, "The network you're capturing from is of a type"
648                " that Tethereal doesn't support.");
649       goto error;
650     }
651     ld.pdh = wtap_dump_open(cfile.save_file, out_file_type,
652                 ld.linktype, pcap_snapshot(ld.pch), &err);
653
654     if (ld.pdh == NULL) {
655       snprintf(errmsg, sizeof errmsg, file_open_error_message(errno, TRUE),
656                 cfile.save_file);
657       goto error;
658     }
659   }
660
661   /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
662      and exit.
663      XXX - deal with signal semantics on various platforms.  Or just
664      use "sigaction()" and be done with it? */
665   signal(SIGTERM, capture_cleanup);
666   signal(SIGINT, capture_cleanup);
667 #if !defined(WIN32)
668   if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
669     signal(SIGHUP, oldhandler);
670 #endif
671
672   /* Let the user know what interface was chosen. */
673   fprintf(stderr, "Capturing on %s\n", cfile.iface);
674   fflush(stderr);
675
676   inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
677
678   if (cfile.save_file != NULL) {
679     /* We're saving to a file, which means we're printing packet counts
680        to the standard output.  Send a newline so that we move to the
681        line after the packet count. */
682     fprintf(stderr, "\n");
683   }
684
685   /* If we got an error while capturing, report it. */
686   if (inpkts < 0) {
687     fprintf(stderr, "tethereal: Error while capturing packets: %s\n",
688         pcap_geterr(ld.pch));
689   }
690
691   /* Get the capture statistics, and, if any packets were dropped, report
692      that. */
693   if (pcap_stats(ld.pch, &stats) >= 0) {
694     if (stats.ps_drop != 0) {
695       fprintf(stderr, "%u packets dropped\n", stats.ps_drop);
696     }
697   } else {
698     fprintf(stderr, "tethereal: Can't get packet-drop statistics: %s\n",
699         pcap_geterr(ld.pch));
700   }
701   pcap_close(ld.pch);
702
703   return TRUE;
704
705 error:
706   g_free(cfile.save_file);
707   cfile.save_file = NULL;
708   fprintf(stderr, "tethereal: %s\n", errmsg);
709   if (ld.pch != NULL)
710     pcap_close(ld.pch);
711
712   return FALSE;
713 }
714
715 static void
716 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
717   const u_char *pd)
718 {
719   struct wtap_pkthdr whdr;
720   loop_data *ld = (loop_data *) user;
721   cb_args_t args;
722
723   whdr.ts.tv_sec = phdr->ts.tv_sec;
724   whdr.ts.tv_usec = phdr->ts.tv_usec;
725   whdr.caplen = phdr->caplen;
726   whdr.len = phdr->len;
727   whdr.pkt_encap = ld->linktype;
728
729   args.cf = &cfile;
730   args.pdh = ld->pdh;
731   if (ld->pdh) {
732     wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, NULL, pd);
733     fprintf(stderr, "\r%u ", cfile.count);
734     fflush(stdout);
735   } else {
736     wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, NULL, pd);
737   }
738 }
739
740 static void
741 capture_cleanup(int signum)
742 {
743   int err;
744
745   fprintf(stderr, "\n");
746   pcap_close(ld.pch);
747   if (ld.pdh != NULL) {
748     if (!wtap_dump_close(ld.pdh, &err)) {
749       show_capture_file_io_error(cfile.save_file, err, TRUE);
750       exit(2);
751     }
752   }
753   exit(0);
754 }
755 #endif /* HAVE_LIBPCAP */
756
757 static int
758 load_cap_file(capture_file *cf, int out_file_type)
759 {
760   gint         linktype;
761   wtap_dumper *pdh;
762   int          err;
763   int          success;
764   cb_args_t    args;
765
766   linktype = wtap_file_encap(cf->wth);
767   if (cf->save_file != NULL) {
768     /* Set up to write to the capture file. */
769     pdh = wtap_dump_open(cf->save_file, out_file_type,
770                 linktype, wtap_snapshot_length(cf->wth), &err);
771
772     if (pdh == NULL) {
773       /* We couldn't set up to write to the capture file. */
774       switch (err) {
775
776       case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
777         fprintf(stderr,
778                 "tethereal: Capture files can't be written in that format.\n");
779         break;
780
781       case WTAP_ERR_UNSUPPORTED_ENCAP:
782       case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
783         fprintf(stderr,
784 "tethereal: The capture file being read cannot be written in that format.\n");
785         break;
786
787       case WTAP_ERR_CANT_OPEN:
788         fprintf(stderr,
789 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
790                  cf->save_file);
791         break;
792
793       case WTAP_ERR_SHORT_WRITE:
794         fprintf(stderr,
795 "tethereal: A full header couldn't be written to the file \"%s\".\n",
796                 cf->save_file);
797         break;
798
799       default:
800         if (err < 0) {
801           fprintf(stderr,
802                 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
803                 cf->save_file, err);
804         } else {
805           fprintf(stderr,
806                 "tethereal: The file \"%s\" could not be opened: %s\n.",
807                 cf->save_file, strerror(err));
808         }
809         break;
810       }
811       goto out;
812     }
813     args.cf = cf;
814     args.pdh = pdh;
815     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
816                         &err);
817   } else {
818     args.cf = cf;
819     args.pdh = NULL;
820     success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
821                         &err);
822   }
823   if (!success) {
824     /* Print up a message box noting that the read failed somewhere along
825        the line. */
826     switch (err) {
827
828     case WTAP_ERR_UNSUPPORTED_ENCAP:
829       fprintf(stderr,
830 "tethereal: \"%s\" is a capture file is for a network type that Tethereal doesn't support.\n",
831         cf->filename);
832       break;
833
834     case WTAP_ERR_CANT_READ:
835       fprintf(stderr,
836 "tethereal: An attempt to read from \"%s\" failed for some unknown reason.\n",
837         cf->filename);
838       break;
839
840     case WTAP_ERR_SHORT_READ:
841       fprintf(stderr,
842 "tethereal: \"%s\" appears to have been cut short in the middle of a packet.\n",
843         cf->filename);
844       break;
845
846     case WTAP_ERR_BAD_RECORD:
847       fprintf(stderr,
848 "tethereal: \"%s\" appears to be damaged or corrupt.\n",
849         cf->filename);
850       break;
851
852     default:
853       fprintf(stderr,
854 "tethereal: An error occurred while reading \"%s\": %s.\n",
855         cf->filename, wtap_strerror(err));
856       break;
857     }
858   }
859
860 out:
861   wtap_close(cf->wth);
862   cf->wth = NULL;
863
864   return err;
865 }
866
867 static void
868 fill_in_fdata(frame_data *fdata, capture_file *cf,
869         const struct wtap_pkthdr *phdr,
870         const union wtap_pseudo_header *pseudo_header, int offset)
871 {
872   int i;
873
874   fdata->next = NULL;
875   fdata->prev = NULL;
876   fdata->pfd = NULL;
877   fdata->data_src = NULL;
878   fdata->num = cf->count;
879   fdata->pkt_len = phdr->len;
880   fdata->cap_len = phdr->caplen;
881   fdata->file_off = offset;
882   fdata->cinfo = NULL;
883   fdata->lnk_t = phdr->pkt_encap;
884   fdata->abs_secs  = phdr->ts.tv_sec;
885   fdata->abs_usecs = phdr->ts.tv_usec;
886   fdata->flags.passed_dfilter = 0;
887   fdata->flags.encoding = CHAR_ASCII;
888   fdata->flags.visited = 0;
889   fdata->flags.marked = 0;
890
891   /* If we don't have the time stamp of the first packet in the
892      capture, it's because this is the first packet.  Save the time
893      stamp of this packet as the time stamp of the first packet. */
894   if (!firstsec && !firstusec) {
895     firstsec  = fdata->abs_secs;
896     firstusec = fdata->abs_usecs;
897   }
898
899   /* If we don't have the time stamp of the previous displayed packet,
900      it's because this is the first displayed packet.  Save the time
901      stamp of this packet as the time stamp of the previous displayed
902      packet. */
903   if (!prevsec && !prevusec) {
904     prevsec  = fdata->abs_secs;
905     prevusec = fdata->abs_usecs;
906   }
907
908   /* Get the time elapsed between the first packet and this packet. */
909   compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
910                 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
911
912   /* If it's greater than the current elapsed time, set the elapsed time
913      to it (we check for "greater than" so as not to be confused by
914      time moving backwards). */
915   if (cf->esec < fdata->rel_secs
916         || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
917     cf->esec = fdata->rel_secs;
918     cf->eusec = fdata->rel_usecs;
919   }
920   
921   /* Get the time elapsed between the previous displayed packet and
922      this packet. */
923   compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
924                 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
925   prevsec = fdata->abs_secs;
926   prevusec = fdata->abs_usecs;
927
928   fdata->cinfo = &cf->cinfo;
929   for (i = 0; i < fdata->cinfo->num_cols; i++) {
930     fdata->cinfo->col_buf[i][0] = '\0';
931     fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
932   }
933 }
934
935 /* Free up all data attached to a "frame_data" structure. */
936 static void
937 clear_fdata(frame_data *fdata)
938 {
939   if (fdata->pfd)
940     g_slist_free(fdata->pfd);
941   if (fdata->data_src)
942     g_slist_free(fdata->data_src);
943 }
944
945 static void
946 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
947   union wtap_pseudo_header *pseudo_header, const u_char *buf)
948 {
949   cb_args_t    *args = (cb_args_t *) user;
950   capture_file *cf = args->cf;
951   wtap_dumper  *pdh = args->pdh;
952   frame_data    fdata;
953   proto_tree   *protocol_tree;
954   int           err;
955   gboolean      passed;
956   epan_dissect_t *edt;
957
958   cf->count++;
959   if (cf->rfcode) {
960     fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
961     protocol_tree = proto_tree_create_root();
962     edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
963     passed = dfilter_apply_edt(cf->rfcode, edt);
964   } else {
965     protocol_tree = NULL;
966     passed = TRUE;
967     edt = NULL;
968   }
969   if (passed) {
970     if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
971 #ifdef HAVE_LIBPCAP
972       if (ld.pch != NULL) {
973         /* We're capturing packets, so we're printing a count of packets
974            captured; move to the line after the count. */
975         fprintf(stderr, "\n");
976       }
977 #endif
978       show_capture_file_io_error(cf->save_file, err, FALSE);
979 #ifdef HAVE_LIBPCAP
980       if (ld.pch != NULL)
981         pcap_close(ld.pch);
982 #endif
983       wtap_dump_close(pdh, &err);
984       exit(2);
985     }
986   }
987   if (protocol_tree != NULL)
988     proto_tree_free(protocol_tree);
989   if (edt != NULL)
990     epan_dissect_free(edt);
991   clear_fdata(&fdata);
992 }
993
994 static void
995 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
996 {
997   switch (err) {
998
999   case ENOSPC:
1000     fprintf(stderr,
1001 "tethereal: Not all the packets could be written to \"%s\" because there is "
1002 "no space left on the file system.\n",
1003         fname);
1004     break;
1005
1006 #ifdef EDQUOT
1007   case EDQUOT:
1008     fprintf(stderr,
1009 "tethereal: Not all the packets could be written to \"%s\" because you are "
1010 "too close to, or over your disk quota.\n",
1011         fname);
1012   break;
1013 #endif
1014
1015   case WTAP_ERR_CANT_CLOSE:
1016     fprintf(stderr,
1017 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1018         fname);
1019     break;
1020
1021   case WTAP_ERR_SHORT_WRITE:
1022     fprintf(stderr,
1023 "tethereal: Not all the packets could be written to \"%s\".\n",
1024         fname);
1025     break;
1026
1027   default:
1028     if (is_close) {
1029       fprintf(stderr,
1030 "tethereal: \"%s\" could not be closed: %s.\n",
1031         fname, wtap_strerror(err));
1032     } else {
1033       fprintf(stderr,
1034 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1035         fname, wtap_strerror(err));
1036     }
1037     break;
1038   }
1039 }
1040
1041 static void
1042 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1043   union wtap_pseudo_header *pseudo_header, const u_char *buf)
1044 {
1045   cb_args_t    *args = (cb_args_t *) user;
1046   capture_file *cf = args->cf;
1047   frame_data    fdata;
1048   proto_tree   *protocol_tree;
1049   gboolean      passed;
1050   print_args_t  print_args;
1051   epan_dissect_t *edt;
1052   int           i;
1053
1054   cf->count++;
1055
1056   /* The protocol tree will be "visible", i.e., printed, only if we're
1057      not printing a summary. */
1058   proto_tree_is_visible = verbose;
1059
1060   fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1061
1062   passed = TRUE;
1063   if (cf->rfcode || verbose)
1064     protocol_tree = proto_tree_create_root();
1065   else
1066     protocol_tree = NULL;
1067   edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1068   if (cf->rfcode)
1069     passed = dfilter_apply_edt(cf->rfcode, edt);
1070   if (passed) {
1071     /* The packet passed the read filter. */
1072     if (verbose) {
1073       /* Print the information in the protocol tree. */
1074       print_args.to_file = TRUE;
1075       print_args.format = PR_FMT_TEXT;
1076       print_args.print_summary = FALSE;
1077       print_args.print_hex = print_hex;
1078       print_args.expand_all = TRUE;
1079       proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1080                         buf, &fdata, stdout);
1081       if (!print_hex) {
1082         /* "print_hex_data()" will put out a leading blank line, as well
1083            as a trailing one; print one here, to separate the packets,
1084            only if "print_hex_data()" won't be called. */
1085         printf("\n");
1086       }
1087     } else {
1088       /* Just fill in the columns. */
1089       fill_in_columns(&fdata);
1090
1091       /* Now print them. */
1092       for (i = 0; i < cf->cinfo.num_cols; i++) {
1093         switch (cf->cinfo.col_fmt[i]) {
1094         case COL_NUMBER:
1095           /*
1096            * Don't print this if we're doing a live capture from a network
1097            * interface - if we're doing a live capture, you won't be
1098            * able to look at the capture in the future (it's not being
1099            * saved anywhere), so the frame numbers are unlikely to be
1100            * useful.
1101            *
1102            * (XXX - it might be nice to be able to save and print at
1103            * the same time, sort of like an "Update list of packets
1104            * in real time" capture in Ethereal.)
1105            */
1106           if (cf->iface != NULL)
1107             continue;
1108           printf("%3s", cf->cinfo.col_data[i]);
1109           break;
1110
1111         case COL_CLS_TIME:
1112         case COL_REL_TIME:
1113         case COL_ABS_TIME:
1114         case COL_ABS_DATE_TIME: /* XXX - wider */
1115           printf("%10s", cf->cinfo.col_data[i]);
1116           break;
1117
1118         case COL_DEF_SRC:
1119         case COL_RES_SRC:
1120         case COL_UNRES_SRC:
1121         case COL_DEF_DL_SRC:
1122         case COL_RES_DL_SRC:
1123         case COL_UNRES_DL_SRC:
1124         case COL_DEF_NET_SRC:
1125         case COL_RES_NET_SRC:
1126         case COL_UNRES_NET_SRC:
1127           printf("%12s", cf->cinfo.col_data[i]);
1128           break;
1129
1130         case COL_DEF_DST:
1131         case COL_RES_DST:
1132         case COL_UNRES_DST:
1133         case COL_DEF_DL_DST:
1134         case COL_RES_DL_DST:
1135         case COL_UNRES_DL_DST:
1136         case COL_DEF_NET_DST:
1137         case COL_RES_NET_DST:
1138         case COL_UNRES_NET_DST:
1139           printf("%-12s", cf->cinfo.col_data[i]);
1140           break;
1141
1142         default:
1143           printf("%s", cf->cinfo.col_data[i]);
1144           break;
1145         }
1146         if (i != cf->cinfo.num_cols - 1) {
1147           /*
1148            * This isn't the last column, so we need to print a
1149            * separator between this column and the next.
1150            *
1151            * If we printed a network source and are printing a
1152            * network destination of the same type next, separate
1153            * them with "->"; if we printed a network destination
1154            * and are printing a network source of the same type
1155            * next, separate them with "<-"; otherwise separate them
1156            * with a space.
1157            */
1158           switch (cf->cinfo.col_fmt[i]) {
1159
1160           case COL_DEF_SRC:
1161           case COL_RES_SRC:
1162           case COL_UNRES_SRC:
1163             switch (cf->cinfo.col_fmt[i + 1]) {
1164
1165             case COL_DEF_DST:
1166             case COL_RES_DST:
1167             case COL_UNRES_DST:
1168               printf(" -> ");
1169               break;
1170
1171             default:
1172               putchar(' ');
1173               break;
1174             }
1175             break;
1176
1177           case COL_DEF_DL_SRC:
1178           case COL_RES_DL_SRC:
1179           case COL_UNRES_DL_SRC:
1180             switch (cf->cinfo.col_fmt[i + 1]) {
1181
1182             case COL_DEF_DL_DST:
1183             case COL_RES_DL_DST:
1184             case COL_UNRES_DL_DST:
1185               printf(" -> ");
1186               break;
1187
1188             default:
1189               putchar(' ');
1190               break;
1191             }
1192             break;
1193
1194           case COL_DEF_NET_SRC:
1195           case COL_RES_NET_SRC:
1196           case COL_UNRES_NET_SRC:
1197             switch (cf->cinfo.col_fmt[i + 1]) {
1198
1199             case COL_DEF_NET_DST:
1200             case COL_RES_NET_DST:
1201             case COL_UNRES_NET_DST:
1202               printf(" -> ");
1203               break;
1204
1205             default:
1206               putchar(' ');
1207               break;
1208             }
1209             break;
1210
1211           case COL_DEF_DST:
1212           case COL_RES_DST:
1213           case COL_UNRES_DST:
1214             switch (cf->cinfo.col_fmt[i + 1]) {
1215
1216             case COL_DEF_SRC:
1217             case COL_RES_SRC:
1218             case COL_UNRES_SRC:
1219               printf(" <- ");
1220               break;
1221
1222             default:
1223               putchar(' ');
1224               break;
1225             }
1226             break;
1227
1228           case COL_DEF_DL_DST:
1229           case COL_RES_DL_DST:
1230           case COL_UNRES_DL_DST:
1231             switch (cf->cinfo.col_fmt[i + 1]) {
1232
1233             case COL_DEF_DL_SRC:
1234             case COL_RES_DL_SRC:
1235             case COL_UNRES_DL_SRC:
1236               printf(" <- ");
1237               break;
1238
1239             default:
1240               putchar(' ');
1241               break;
1242             }
1243             break;
1244
1245           case COL_DEF_NET_DST:
1246           case COL_RES_NET_DST:
1247           case COL_UNRES_NET_DST:
1248             switch (cf->cinfo.col_fmt[i + 1]) {
1249
1250             case COL_DEF_NET_SRC:
1251             case COL_RES_NET_SRC:
1252             case COL_UNRES_NET_SRC:
1253               printf(" <- ");
1254               break;
1255
1256             default:
1257               putchar(' ');
1258               break;
1259             }
1260             break;
1261
1262           default:
1263             putchar(' ');
1264             break;
1265           }
1266         }
1267       }
1268       putchar('\n');
1269     }
1270     if (print_hex) {
1271       print_hex_data(stdout, print_args.format, &fdata);
1272       putchar('\n');
1273     }
1274     fdata.cinfo = NULL;
1275   }
1276
1277   /* The ANSI C standard does not appear to *require* that a line-buffered
1278      stream be flushed to the host environment whenever a newline is
1279      written, it just says that, on such a stream, characters "are
1280      intended to be transmitted to or from the host environment as a
1281      block when a new-line character is encountered".
1282
1283      The Visual C++ 6.0 C implementation doesn't do what is intended;
1284      even if you set a stream to be line-buffered, it still doesn't
1285      flush the buffer at the end of every line.
1286
1287      So, if the "-l" flag was specified, we flush the standard output
1288      at the end of a packet.  This will do the right thing if we're
1289      printing packet summary lines, and, as we print the entire protocol
1290      tree for a single packet without waiting for anything to happen,
1291      it should be as good as line-buffered mode if we're printing
1292      protocol trees.  (The whole reason for the "-l" flag in either
1293      tcpdump or Tethereal is to allow the output of a live capture to
1294      be piped to a program or script and to have that script see the
1295      information for the packet as soon as it's printed, rather than
1296      having to wait until a standard I/O buffer fills up. */
1297   if (line_buffered)
1298     fflush(stdout);
1299   if (protocol_tree != NULL)
1300     proto_tree_free(protocol_tree);
1301
1302   epan_dissect_free(edt);
1303
1304   clear_fdata(&fdata);
1305
1306   proto_tree_is_visible = FALSE;
1307 }
1308
1309 char *
1310 file_open_error_message(int err, gboolean for_writing)
1311 {
1312   char *errmsg;
1313   static char errmsg_errno[1024+1];
1314
1315   switch (err) {
1316
1317   case WTAP_ERR_NOT_REGULAR_FILE:
1318     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1319     break;
1320
1321   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1322   case WTAP_ERR_UNSUPPORTED:
1323     /* Seen only when opening a capture file for reading. */
1324     errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1325     break;
1326
1327   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1328     /* Seen only when opening a capture file for writing. */
1329     errmsg = "Tethereal does not support writing capture files in that format.";
1330     break;
1331
1332   case WTAP_ERR_UNSUPPORTED_ENCAP:
1333   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1334     if (for_writing)
1335       errmsg = "Tethereal cannot save this capture in that format.";
1336     else
1337       errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1338     break;
1339
1340   case WTAP_ERR_BAD_RECORD:
1341     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1342     break;
1343
1344   case WTAP_ERR_CANT_OPEN:
1345     if (for_writing)
1346       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1347     else
1348       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1349     break;
1350
1351   case WTAP_ERR_SHORT_READ:
1352     errmsg = "The file \"%s\" appears to have been cut short"
1353              " in the middle of a packet.";
1354     break;
1355
1356   case WTAP_ERR_SHORT_WRITE:
1357     errmsg = "A full header couldn't be written to the file \"%s\".";
1358     break;
1359
1360   case ENOENT:
1361     if (for_writing)
1362       errmsg = "The path to the file \"%s\" does not exist.";
1363     else
1364       errmsg = "The file \"%s\" does not exist.";
1365     break;
1366
1367   case EACCES:
1368     if (for_writing)
1369       errmsg = "You do not have permission to create or write to the file \"%s\".";
1370     else
1371       errmsg = "You do not have permission to read the file \"%s\".";
1372     break;
1373
1374   case EISDIR:
1375     errmsg = "\"%s\" is a directory (folder), not a file.";
1376     break;
1377
1378   default:
1379     snprintf(errmsg_errno, sizeof(errmsg_errno),
1380              "The file \"%%s\" could not be opened: %s.",
1381              wtap_strerror(err));
1382     errmsg = errmsg_errno;
1383     break;
1384   }
1385   return errmsg;
1386 }
1387
1388 int
1389 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1390 {
1391   wtap       *wth;
1392   int         err;
1393   FILE_T      fh;
1394   int         fd;
1395   struct stat cf_stat;
1396   char        err_msg[2048+1];
1397
1398   wth = wtap_open_offline(fname, &err, FALSE);
1399   if (wth == NULL)
1400     goto fail;
1401
1402   /* Find the size of the file. */
1403   fh = wtap_file(wth);
1404   fd = wtap_fd(wth);
1405   if (fstat(fd, &cf_stat) < 0) {
1406     err = errno;
1407     wtap_close(wth);
1408     goto fail;
1409   }
1410
1411   /* The open succeeded.  Fill in the information for this file. */
1412
1413   /* Initialize the table of conversations. */
1414   epan_conversation_init();
1415
1416   /* Initialize protocol-specific variables */
1417   init_all_protocols();
1418
1419   cf->wth = wth;
1420   cf->filed = fd;
1421   cf->f_len = cf_stat.st_size;
1422
1423   /* Set the file name because we need it to set the follow stream filter.
1424      XXX - is that still true?  We need it for other reasons, though,
1425      in any case. */
1426   cf->filename = g_strdup(fname);
1427
1428   /* Indicate whether it's a permanent or temporary file. */
1429   cf->is_tempfile = is_tempfile;
1430
1431   /* If it's a temporary capture buffer file, mark it as not saved. */
1432   cf->user_saved = !is_tempfile;
1433
1434   cf->cd_t      = wtap_file_type(cf->wth);
1435   cf->count     = 0;
1436   cf->drops_known = FALSE;
1437   cf->drops     = 0;
1438   cf->esec      = 0;
1439   cf->eusec     = 0;
1440   cf->snap      = wtap_snapshot_length(cf->wth);
1441   cf->progbar_quantum = 0;
1442   cf->progbar_nextstep = 0;
1443   firstsec = 0, firstusec = 0;
1444   prevsec = 0, prevusec = 0;
1445  
1446   return (0);
1447
1448 fail:
1449   snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1450   fprintf(stderr, "tethereal: %s\n", err_msg);
1451   return (err);
1452 }