Don't attempt to modify the data pointed to by the result of
[obnox/wireshark/wip.git] / tethereal.c
1 /* tethereal.c
2  *
3  * $Id: tethereal.c,v 1.68 2001/02/18 03:38:42 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->num = cf->count;
878   fdata->pkt_len = phdr->len;
879   fdata->cap_len = phdr->caplen;
880   fdata->file_off = offset;
881   fdata->cinfo = NULL;
882   fdata->lnk_t = phdr->pkt_encap;
883   fdata->abs_secs  = phdr->ts.tv_sec;
884   fdata->abs_usecs = phdr->ts.tv_usec;
885   fdata->flags.passed_dfilter = 0;
886   fdata->flags.encoding = CHAR_ASCII;
887   fdata->flags.visited = 0;
888   fdata->flags.marked = 0;
889
890   /* If we don't have the time stamp of the first packet in the
891      capture, it's because this is the first packet.  Save the time
892      stamp of this packet as the time stamp of the first packet. */
893   if (!firstsec && !firstusec) {
894     firstsec  = fdata->abs_secs;
895     firstusec = fdata->abs_usecs;
896   }
897
898   /* If we don't have the time stamp of the previous displayed packet,
899      it's because this is the first displayed packet.  Save the time
900      stamp of this packet as the time stamp of the previous displayed
901      packet. */
902   if (!prevsec && !prevusec) {
903     prevsec  = fdata->abs_secs;
904     prevusec = fdata->abs_usecs;
905   }
906
907   /* Get the time elapsed between the first packet and this packet. */
908   compute_timestamp_diff(&fdata->rel_secs, &fdata->rel_usecs,
909                 fdata->abs_secs, fdata->abs_usecs, firstsec, firstusec);
910
911   /* If it's greater than the current elapsed time, set the elapsed time
912      to it (we check for "greater than" so as not to be confused by
913      time moving backwards). */
914   if (cf->esec < fdata->rel_secs
915         || (cf->esec == fdata->rel_secs && cf->eusec < fdata->rel_usecs)) {
916     cf->esec = fdata->rel_secs;
917     cf->eusec = fdata->rel_usecs;
918   }
919   
920   /* Get the time elapsed between the previous displayed packet and
921      this packet. */
922   compute_timestamp_diff(&fdata->del_secs, &fdata->del_usecs,
923                 fdata->abs_secs, fdata->abs_usecs, prevsec, prevusec);
924   prevsec = fdata->abs_secs;
925   prevusec = fdata->abs_usecs;
926
927   fdata->cinfo = &cf->cinfo;
928   for (i = 0; i < fdata->cinfo->num_cols; i++) {
929     fdata->cinfo->col_buf[i][0] = '\0';
930     fdata->cinfo->col_data[i] = fdata->cinfo->col_buf[i];
931   }
932 }
933
934 static void
935 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
936   union wtap_pseudo_header *pseudo_header, const u_char *buf)
937 {
938   cb_args_t    *args = (cb_args_t *) user;
939   capture_file *cf = args->cf;
940   wtap_dumper  *pdh = args->pdh;
941   frame_data    fdata;
942   proto_tree   *protocol_tree;
943   int           err;
944   gboolean      passed;
945   epan_dissect_t *edt;
946
947   cf->count++;
948   if (cf->rfcode) {
949     fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
950     protocol_tree = proto_tree_create_root();
951     edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
952     passed = dfilter_apply_edt(cf->rfcode, edt);
953   } else {
954     protocol_tree = NULL;
955     passed = TRUE;
956     edt = NULL;
957   }
958   if (passed) {
959     if (!wtap_dump(pdh, phdr, pseudo_header, buf, &err)) {
960 #ifdef HAVE_LIBPCAP
961       if (ld.pch != NULL) {
962         /* We're capturing packets, so we're printing a count of packets
963            captured; move to the line after the count. */
964         fprintf(stderr, "\n");
965       }
966 #endif
967       show_capture_file_io_error(cf->save_file, err, FALSE);
968 #ifdef HAVE_LIBPCAP
969       if (ld.pch != NULL)
970         pcap_close(ld.pch);
971 #endif
972       wtap_dump_close(pdh, &err);
973       exit(2);
974     }
975   }
976   if (protocol_tree != NULL)
977     proto_tree_free(protocol_tree);
978   if (edt != NULL)
979     epan_dissect_free(edt);
980 }
981
982 static void
983 show_capture_file_io_error(const char *fname, int err, gboolean is_close)
984 {
985   switch (err) {
986
987   case ENOSPC:
988     fprintf(stderr,
989 "tethereal: Not all the packets could be written to \"%s\" because there is "
990 "no space left on the file system.\n",
991         fname);
992     break;
993
994 #ifdef EDQUOT
995   case EDQUOT:
996     fprintf(stderr,
997 "tethereal: Not all the packets could be written to \"%s\" because you are "
998 "too close to, or over your disk quota.\n",
999         fname);
1000   break;
1001 #endif
1002
1003   case WTAP_ERR_CANT_CLOSE:
1004     fprintf(stderr,
1005 "tethereal: \"%s\" couldn't be closed for some unknown reason.\n",
1006         fname);
1007     break;
1008
1009   case WTAP_ERR_SHORT_WRITE:
1010     fprintf(stderr,
1011 "tethereal: Not all the packets could be written to \"%s\".\n",
1012         fname);
1013     break;
1014
1015   default:
1016     if (is_close) {
1017       fprintf(stderr,
1018 "tethereal: \"%s\" could not be closed: %s.\n",
1019         fname, wtap_strerror(err));
1020     } else {
1021       fprintf(stderr,
1022 "tethereal: An error occurred while writing to \"%s\": %s.\n",
1023         fname, wtap_strerror(err));
1024     }
1025     break;
1026   }
1027 }
1028
1029 static void
1030 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
1031   union wtap_pseudo_header *pseudo_header, const u_char *buf)
1032 {
1033   cb_args_t    *args = (cb_args_t *) user;
1034   capture_file *cf = args->cf;
1035   frame_data    fdata;
1036   proto_tree   *protocol_tree;
1037   gboolean      passed;
1038   print_args_t  print_args;
1039   epan_dissect_t *edt;
1040   int           i;
1041
1042   cf->count++;
1043
1044   /* The protocol tree will be "visible", i.e., printed, only if we're
1045      not printing a summary. */
1046   proto_tree_is_visible = verbose;
1047
1048   fill_in_fdata(&fdata, cf, phdr, pseudo_header, offset);
1049
1050   passed = TRUE;
1051   if (cf->rfcode || verbose)
1052     protocol_tree = proto_tree_create_root();
1053   else
1054     protocol_tree = NULL;
1055   edt = epan_dissect_new(pseudo_header, buf, &fdata, protocol_tree);
1056   if (cf->rfcode)
1057     passed = dfilter_apply_edt(cf->rfcode, edt);
1058   if (passed) {
1059     /* The packet passed the read filter. */
1060     if (verbose) {
1061       /* Print the information in the protocol tree. */
1062       print_args.to_file = TRUE;
1063       print_args.format = PR_FMT_TEXT;
1064       print_args.print_summary = FALSE;
1065       print_args.print_hex = print_hex;
1066       print_args.expand_all = TRUE;
1067       proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
1068                         buf, &fdata, stdout);
1069       if (!print_hex) {
1070         /* "print_hex_data()" will put out a leading blank line, as well
1071            as a trailing one; print one here, to separate the packets,
1072            only if "print_hex_data()" won't be called. */
1073         printf("\n");
1074       }
1075     } else {
1076       /* Just fill in the columns. */
1077       fill_in_columns(&fdata);
1078
1079       /* Now print them. */
1080       for (i = 0; i < cf->cinfo.num_cols; i++) {
1081         switch (cf->cinfo.col_fmt[i]) {
1082         case COL_NUMBER:
1083           /*
1084            * Don't print this if we're doing a live capture from a network
1085            * interface - if we're doing a live capture, you won't be
1086            * able to look at the capture in the future (it's not being
1087            * saved anywhere), so the frame numbers are unlikely to be
1088            * useful.
1089            *
1090            * (XXX - it might be nice to be able to save and print at
1091            * the same time, sort of like an "Update list of packets
1092            * in real time" capture in Ethereal.)
1093            */
1094           if (cf->iface != NULL)
1095             continue;
1096           printf("%3s", cf->cinfo.col_data[i]);
1097           break;
1098
1099         case COL_CLS_TIME:
1100         case COL_REL_TIME:
1101         case COL_ABS_TIME:
1102         case COL_ABS_DATE_TIME: /* XXX - wider */
1103           printf("%10s", cf->cinfo.col_data[i]);
1104           break;
1105
1106         case COL_DEF_SRC:
1107         case COL_RES_SRC:
1108         case COL_UNRES_SRC:
1109         case COL_DEF_DL_SRC:
1110         case COL_RES_DL_SRC:
1111         case COL_UNRES_DL_SRC:
1112         case COL_DEF_NET_SRC:
1113         case COL_RES_NET_SRC:
1114         case COL_UNRES_NET_SRC:
1115           printf("%12s", cf->cinfo.col_data[i]);
1116           break;
1117
1118         case COL_DEF_DST:
1119         case COL_RES_DST:
1120         case COL_UNRES_DST:
1121         case COL_DEF_DL_DST:
1122         case COL_RES_DL_DST:
1123         case COL_UNRES_DL_DST:
1124         case COL_DEF_NET_DST:
1125         case COL_RES_NET_DST:
1126         case COL_UNRES_NET_DST:
1127           printf("%-12s", cf->cinfo.col_data[i]);
1128           break;
1129
1130         default:
1131           printf("%s", cf->cinfo.col_data[i]);
1132           break;
1133         }
1134         if (i != cf->cinfo.num_cols - 1) {
1135           /*
1136            * This isn't the last column, so we need to print a
1137            * separator between this column and the next.
1138            *
1139            * If we printed a network source and are printing a
1140            * network destination of the same type next, separate
1141            * them with "->"; if we printed a network destination
1142            * and are printing a network source of the same type
1143            * next, separate them with "<-"; otherwise separate them
1144            * with a space.
1145            */
1146           switch (cf->cinfo.col_fmt[i]) {
1147
1148           case COL_DEF_SRC:
1149           case COL_RES_SRC:
1150           case COL_UNRES_SRC:
1151             switch (cf->cinfo.col_fmt[i + 1]) {
1152
1153             case COL_DEF_DST:
1154             case COL_RES_DST:
1155             case COL_UNRES_DST:
1156               printf(" -> ");
1157               break;
1158
1159             default:
1160               putchar(' ');
1161               break;
1162             }
1163             break;
1164
1165           case COL_DEF_DL_SRC:
1166           case COL_RES_DL_SRC:
1167           case COL_UNRES_DL_SRC:
1168             switch (cf->cinfo.col_fmt[i + 1]) {
1169
1170             case COL_DEF_DL_DST:
1171             case COL_RES_DL_DST:
1172             case COL_UNRES_DL_DST:
1173               printf(" -> ");
1174               break;
1175
1176             default:
1177               putchar(' ');
1178               break;
1179             }
1180             break;
1181
1182           case COL_DEF_NET_SRC:
1183           case COL_RES_NET_SRC:
1184           case COL_UNRES_NET_SRC:
1185             switch (cf->cinfo.col_fmt[i + 1]) {
1186
1187             case COL_DEF_NET_DST:
1188             case COL_RES_NET_DST:
1189             case COL_UNRES_NET_DST:
1190               printf(" -> ");
1191               break;
1192
1193             default:
1194               putchar(' ');
1195               break;
1196             }
1197             break;
1198
1199           case COL_DEF_DST:
1200           case COL_RES_DST:
1201           case COL_UNRES_DST:
1202             switch (cf->cinfo.col_fmt[i + 1]) {
1203
1204             case COL_DEF_SRC:
1205             case COL_RES_SRC:
1206             case COL_UNRES_SRC:
1207               printf(" <- ");
1208               break;
1209
1210             default:
1211               putchar(' ');
1212               break;
1213             }
1214             break;
1215
1216           case COL_DEF_DL_DST:
1217           case COL_RES_DL_DST:
1218           case COL_UNRES_DL_DST:
1219             switch (cf->cinfo.col_fmt[i + 1]) {
1220
1221             case COL_DEF_DL_SRC:
1222             case COL_RES_DL_SRC:
1223             case COL_UNRES_DL_SRC:
1224               printf(" <- ");
1225               break;
1226
1227             default:
1228               putchar(' ');
1229               break;
1230             }
1231             break;
1232
1233           case COL_DEF_NET_DST:
1234           case COL_RES_NET_DST:
1235           case COL_UNRES_NET_DST:
1236             switch (cf->cinfo.col_fmt[i + 1]) {
1237
1238             case COL_DEF_NET_SRC:
1239             case COL_RES_NET_SRC:
1240             case COL_UNRES_NET_SRC:
1241               printf(" <- ");
1242               break;
1243
1244             default:
1245               putchar(' ');
1246               break;
1247             }
1248             break;
1249
1250           default:
1251             putchar(' ');
1252             break;
1253           }
1254         }
1255       }
1256       putchar('\n');
1257     }
1258     if (print_hex) {
1259       print_hex_data(stdout, print_args.format, buf,
1260                         fdata.cap_len, fdata.flags.encoding);
1261       putchar('\n');
1262     }
1263     fdata.cinfo = NULL;
1264   }
1265
1266   /* The ANSI C standard does not appear to *require* that a line-buffered
1267      stream be flushed to the host environment whenever a newline is
1268      written, it just says that, on such a stream, characters "are
1269      intended to be transmitted to or from the host environment as a
1270      block when a new-line character is encountered".
1271
1272      The Visual C++ 6.0 C implementation doesn't do what is intended;
1273      even if you set a stream to be line-buffered, it still doesn't
1274      flush the buffer at the end of every line.
1275
1276      So, if the "-l" flag was specified, we flush the standard output
1277      at the end of a packet.  This will do the right thing if we're
1278      printing packet summary lines, and, as we print the entire protocol
1279      tree for a single packet without waiting for anything to happen,
1280      it should be as good as line-buffered mode if we're printing
1281      protocol trees.  (The whole reason for the "-l" flag in either
1282      tcpdump or Tethereal is to allow the output of a live capture to
1283      be piped to a program or script and to have that script see the
1284      information for the packet as soon as it's printed, rather than
1285      having to wait until a standard I/O buffer fills up. */
1286   if (line_buffered)
1287     fflush(stdout);
1288   if (protocol_tree != NULL)
1289     proto_tree_free(protocol_tree);
1290
1291   epan_dissect_free(edt);
1292
1293   proto_tree_is_visible = FALSE;
1294 }
1295
1296 char *
1297 file_open_error_message(int err, gboolean for_writing)
1298 {
1299   char *errmsg;
1300   static char errmsg_errno[1024+1];
1301
1302   switch (err) {
1303
1304   case WTAP_ERR_NOT_REGULAR_FILE:
1305     errmsg = "The file \"%s\" is a \"special file\" or socket or other non-regular file.";
1306     break;
1307
1308   case WTAP_ERR_FILE_UNKNOWN_FORMAT:
1309   case WTAP_ERR_UNSUPPORTED:
1310     /* Seen only when opening a capture file for reading. */
1311     errmsg = "The file \"%s\" is not a capture file in a format Tethereal understands.";
1312     break;
1313
1314   case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
1315     /* Seen only when opening a capture file for writing. */
1316     errmsg = "Tethereal does not support writing capture files in that format.";
1317     break;
1318
1319   case WTAP_ERR_UNSUPPORTED_ENCAP:
1320   case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
1321     if (for_writing)
1322       errmsg = "Tethereal cannot save this capture in that format.";
1323     else
1324       errmsg = "The file \"%s\" is a capture for a network type that Tethereal doesn't support.";
1325     break;
1326
1327   case WTAP_ERR_BAD_RECORD:
1328     errmsg = "The file \"%s\" appears to be damaged or corrupt.";
1329     break;
1330
1331   case WTAP_ERR_CANT_OPEN:
1332     if (for_writing)
1333       errmsg = "The file \"%s\" could not be created for some unknown reason.";
1334     else
1335       errmsg = "The file \"%s\" could not be opened for some unknown reason.";
1336     break;
1337
1338   case WTAP_ERR_SHORT_READ:
1339     errmsg = "The file \"%s\" appears to have been cut short"
1340              " in the middle of a packet.";
1341     break;
1342
1343   case WTAP_ERR_SHORT_WRITE:
1344     errmsg = "A full header couldn't be written to the file \"%s\".";
1345     break;
1346
1347   case ENOENT:
1348     if (for_writing)
1349       errmsg = "The path to the file \"%s\" does not exist.";
1350     else
1351       errmsg = "The file \"%s\" does not exist.";
1352     break;
1353
1354   case EACCES:
1355     if (for_writing)
1356       errmsg = "You do not have permission to create or write to the file \"%s\".";
1357     else
1358       errmsg = "You do not have permission to read the file \"%s\".";
1359     break;
1360
1361   case EISDIR:
1362     errmsg = "\"%s\" is a directory (folder), not a file.";
1363     break;
1364
1365   default:
1366     snprintf(errmsg_errno, sizeof(errmsg_errno),
1367              "The file \"%%s\" could not be opened: %s.",
1368              wtap_strerror(err));
1369     errmsg = errmsg_errno;
1370     break;
1371   }
1372   return errmsg;
1373 }
1374
1375 int
1376 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
1377 {
1378   wtap       *wth;
1379   int         err;
1380   FILE_T      fh;
1381   int         fd;
1382   struct stat cf_stat;
1383   char        err_msg[2048+1];
1384
1385   wth = wtap_open_offline(fname, &err, FALSE);
1386   if (wth == NULL)
1387     goto fail;
1388
1389   /* Find the size of the file. */
1390   fh = wtap_file(wth);
1391   fd = wtap_fd(wth);
1392   if (fstat(fd, &cf_stat) < 0) {
1393     err = errno;
1394     wtap_close(wth);
1395     goto fail;
1396   }
1397
1398   /* The open succeeded.  Fill in the information for this file. */
1399
1400   /* Initialize the table of conversations. */
1401   epan_conversation_init();
1402
1403   /* Initialize protocol-specific variables */
1404   init_all_protocols();
1405
1406   cf->wth = wth;
1407   cf->filed = fd;
1408   cf->f_len = cf_stat.st_size;
1409
1410   /* Set the file name because we need it to set the follow stream filter.
1411      XXX - is that still true?  We need it for other reasons, though,
1412      in any case. */
1413   cf->filename = g_strdup(fname);
1414
1415   /* Indicate whether it's a permanent or temporary file. */
1416   cf->is_tempfile = is_tempfile;
1417
1418   /* If it's a temporary capture buffer file, mark it as not saved. */
1419   cf->user_saved = !is_tempfile;
1420
1421   cf->cd_t      = wtap_file_type(cf->wth);
1422   cf->count     = 0;
1423   cf->drops_known = FALSE;
1424   cf->drops     = 0;
1425   cf->esec      = 0;
1426   cf->eusec     = 0;
1427   cf->snap      = wtap_snapshot_length(cf->wth);
1428   cf->progbar_quantum = 0;
1429   cf->progbar_nextstep = 0;
1430   firstsec = 0, firstusec = 0;
1431   prevsec = 0, prevusec = 0;
1432  
1433   return (0);
1434
1435 fail:
1436   snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1437   fprintf(stderr, "tethereal: %s\n", err_msg);
1438   return (err);
1439 }