3 * $Id: tethereal.c,v 1.12 2000/01/22 07:19:26 guy Exp $
5 * Ethereal - Network traffic analyzer
6 * By Gerald Combs <gerald@zing.org>
7 * Copyright 1998 Gerald Combs
9 * Text-mode variant, by Gilbert Ramirez <gram@xiexie.org>.
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.
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.
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.
40 #include <sys/types.h>
45 #ifdef NEED_SNPRINTF_H
51 # include "snprintf.h"
54 #if defined(HAVE_UCD_SNMP_SNMP_H)
55 #ifdef HAVE_UCD_SNMP_VERSION_H
56 #include <ucd-snmp/version.h>
57 #endif /* HAVE_UCD_SNMP_VERSION_H */
58 #elif defined(HAVE_SNMP_SNMP_H)
59 #ifdef HAVE_SNMP_VERSION_H
60 #include <snmp/version.h>
61 #endif /* HAVE_SNMP_VERSION_H */
64 #ifdef NEED_STRERROR_H
69 #include "timestamp.h"
79 #include "conversation.h"
82 static guint32 firstsec, firstusec;
83 static guint32 prevsec, prevusec;
84 static gchar comp_info_str[256];
85 static gboolean verbose;
86 static gboolean print_hex;
89 typedef struct _loop_data {
97 static int capture(int, int);
98 static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *,
100 static void capture_cleanup(int);
108 static int load_cap_file(capture_file *, int);
109 static void wtap_dispatch_cb_write(u_char *, const struct wtap_pkthdr *, int,
111 static void wtap_dispatch_cb_print(u_char *, const struct wtap_pkthdr *, int,
113 static gchar *col_info(frame_data *, gint);
117 FILE *data_out_file = NULL;
118 guint main_ctx, file_ctx;
119 ts_type timestamp_type = RELATIVE;
121 /* call initialization routines at program startup time */
123 ethereal_proto_init(void) {
134 ethereal_proto_cleanup(void) {
144 fprintf(stderr, "This is GNU t%s %s, compiled with %s\n", PACKAGE,
145 VERSION, comp_info_str);
147 fprintf(stderr, "t%s [ -vVh ] [ -c count ] [ -f <filter expression> ] [ -F <capture type> ]\n", PACKAGE);
148 fprintf(stderr, "\t[ -i iface ] [ -r infile ] [ -R <filter expression> ]\n");
149 fprintf(stderr, "\t[ -s snaplen ] [ -t <time stamp format> ] [ -w savefile ] [ -x ]\n");
150 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
151 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
152 if (wtap_dump_can_open(i))
153 fprintf(stderr, "\t%s - %s\n",
154 wtap_file_type_short_string(i), wtap_file_type_string(i));
156 fprintf(stderr, "\tdefault is libpcap\n");
160 main(int argc, char *argv[])
164 gboolean arg_error = FALSE;
166 extern char pcap_version[];
171 int packet_count = 0;
173 gchar err_str[PCAP_ERRBUF_SIZE];
175 gboolean capture_option_specified = FALSE;
177 int out_file_type = WTAP_FILE_PCAP;
178 gchar *cf_name = NULL, *rfilter = NULL;
179 dfilter *rfcode = NULL;
182 /* If invoked with the "-G" flag, we dump out a glossary of
183 display filter symbols.
185 We do this here to mirror what happens in the GTK+ version, although
186 it's not necessary here. */
187 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
188 ethereal_proto_init();
189 proto_registrar_dump();
193 prefs = read_prefs(&pf_path);
194 if (pf_path != NULL) {
195 fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
199 /* Initialize the capture file struct */
205 cf.user_saved = FALSE;
206 cf.is_tempfile = FALSE;
211 cf.cfilter = g_strdup("");
215 cf.save_file_fd = -1;
216 cf.snap = WTAP_MAX_PACKET_SIZE;
218 cf.cinfo.num_cols = prefs->num_cols;
219 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
220 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
221 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
222 cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
223 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
225 /* Assemble the compile-time options */
226 snprintf(comp_info_str, 256,
227 #ifdef GTK_MAJOR_VERSION
228 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
231 "GTK+ (version unknown), %s%s, %s%s, %s%s",
235 "with libpcap ", pcap_version,
237 "without libpcap", "",
242 "with libz ", ZLIB_VERSION,
243 #else /* ZLIB_VERSION */
244 "with libz ", "(version unknown)",
245 #endif /* ZLIB_VERSION */
246 #else /* HAVE_LIBZ */
248 #endif /* HAVE_LIBZ */
250 /* Oh, this is pretty */
251 #if defined(HAVE_UCD_SNMP_SNMP_H)
252 #ifdef HAVE_UCD_SNMP_VERSION_H
253 "with UCD SNMP ", VersionInfo
254 #else /* HAVE_UCD_SNMP_VERSION_H */
255 "with UCD SNMP ", "(version unknown)"
256 #endif /* HAVE_UCD_SNMP_VERSION_H */
257 #elif defined(HAVE_SNMP_SNMP_H)
258 #ifdef HAVE_SNMP_VERSION_H
259 "with CMU SNMP ", snmp_Version()
260 #else /* HAVE_SNMP_VERSION_H */
261 "with CMU SNMP ", "(version unknown)"
262 #endif /* HAVE_SNMP_VERSION_H */
268 /* Now get our args */
269 while ((opt = getopt(argc, argv, "c:f:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
271 case 'c': /* Capture xxx packets */
273 packet_count = atoi(optarg);
275 capture_option_specified = TRUE;
281 cf.cfilter = g_strdup(optarg);
283 capture_option_specified = TRUE;
288 out_file_type = wtap_short_string_to_file_type(optarg);
289 if (out_file_type < 0) {
290 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
295 case 'h': /* Print help and exit */
299 case 'i': /* Use interface xxx */
301 cf.iface = g_strdup(optarg);
303 capture_option_specified = TRUE;
307 case 'n': /* No name resolution */
308 g_resolving_actif = 0;
310 case 'r': /* Read capture file xxx */
311 cf_name = g_strdup(optarg);
313 case 'R': /* Read file filter */
316 case 's': /* Set the snapshot (capture) length */
318 cf.snap = atoi(optarg);
320 capture_option_specified = TRUE;
324 case 't': /* Time stamp type */
325 if (strcmp(optarg, "r") == 0)
326 timestamp_type = RELATIVE;
327 else if (strcmp(optarg, "a") == 0)
328 timestamp_type = ABSOLUTE;
329 else if (strcmp(optarg, "d") == 0)
330 timestamp_type = DELTA;
332 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
334 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
335 fprintf(stderr, "or \"d\" for delta.\n");
339 case 'v': /* Show version and exit */
340 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
343 case 'w': /* Write to capture file xxx */
344 cf.save_file = g_strdup(optarg);
346 case 'V': /* Verbose */
349 case 'x': /* Print packet data in hex (and ASCII) */
356 if (capture_option_specified)
357 fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
362 /* Build the column format array */
363 for (i = 0; i < cf.cinfo.num_cols; i++) {
364 cf.cinfo.col_fmt[i] = get_column_format(i);
365 cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
366 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
368 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
369 if (cf.cinfo.col_fmt[i] == COL_INFO)
370 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
372 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
376 cf.snap = WTAP_MAX_PACKET_SIZE;
377 else if (cf.snap < MIN_PACKET_SIZE)
378 cf.snap = MIN_PACKET_SIZE;
380 ethereal_proto_init(); /* Init anything that needs initializing */
382 if (rfilter != NULL) {
383 if (dfilter_compile(rfilter, &rfcode) != 0) {
384 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
385 ethereal_proto_cleanup();
391 err = open_cap_file(cf_name, FALSE, &cf);
393 ethereal_proto_cleanup();
396 err = load_cap_file(&cf, out_file_type);
398 ethereal_proto_cleanup();
403 /* No capture file specified, so we're supposed to do a live capture;
404 do we have support for live captures? */
406 /* Yes; did the user specify an interface to use? */
407 if (cf.iface == NULL) {
408 /* No - pick the first one from the list of interfaces. */
409 if_list = get_interface_list(&err, err_str);
410 if (if_list == NULL) {
413 case CANT_GET_INTERFACE_LIST:
414 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
418 case NO_INTERFACES_FOUND:
419 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
424 cf.iface = g_strdup(if_list->data); /* first interface */
425 free_interface_list(if_list);
427 capture(packet_count, out_file_type);
430 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
435 ethereal_proto_cleanup();
441 /* Do the low-level work of a capture.
442 Returns TRUE if it succeeds, FALSE otherwise. */
444 capture(int packet_count, int out_file_type)
446 gchar err_str[PCAP_ERRBUF_SIZE];
447 bpf_u_int32 netnum, netmask;
448 void (*oldhandler)(int);
452 ld.linktype = WTAP_ENCAP_UNKNOWN;
455 /* Open the network interface to capture from it. */
456 ld.pch = pcap_open_live(cf.iface, cf.snap, 1, 1000, err_str);
458 if (ld.pch == NULL) {
459 /* Well, we couldn't start the capture.
460 If this is a child process that does the capturing in sync
461 mode or fork mode, it shouldn't do any UI stuff until we pop up the
462 capture-progress window, and, since we couldn't start the
463 capture, we haven't popped it up. */
464 snprintf(errmsg, sizeof errmsg,
465 "The capture session could not be initiated (%s).\n"
466 "Please check to make sure you have sufficient permissions, and that\n"
467 "you have the proper interface specified.", err_str);
472 /* A capture filter was specified; set it up. */
473 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
474 snprintf(errmsg, sizeof errmsg,
475 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
478 if (pcap_compile(ld.pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
479 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
480 pcap_geterr(ld.pch));
483 if (pcap_setfilter(ld.pch, &cf.fcode) < 0) {
484 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
485 pcap_geterr(ld.pch));
490 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
491 if (cf.save_file != NULL) {
492 /* Set up to write to the capture file. */
493 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
494 strcpy(errmsg, "The network you're capturing from is of a type"
495 " that Ethereal doesn't support.");
498 ld.pdh = wtap_dump_open(cf.save_file, out_file_type,
499 ld.linktype, pcap_snapshot(ld.pch), &err);
501 if (ld.pdh == NULL) {
502 /* We couldn't set up to write to the capture file. */
505 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
506 strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
509 case WTAP_ERR_UNSUPPORTED_ENCAP:
510 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
511 strcpy(errmsg, "Tethereal cannot save this capture in that format.");
514 case WTAP_ERR_CANT_OPEN:
515 strcpy(errmsg, "The file to which the capture would be written"
516 " couldn't be created for some unknown reason.");
519 case WTAP_ERR_SHORT_WRITE:
520 strcpy(errmsg, "A full header couldn't be written to the file"
521 " to which the capture would be written.");
526 sprintf(errmsg, "The file to which the capture would be"
527 " written (\"%s\") could not be opened: Error %d.",
530 sprintf(errmsg, "The file to which the capture would be"
531 " written (\"%s\") could not be opened: %s.",
532 cf.save_file, strerror(err));
540 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
542 XXX - deal with signal semantics on various platforms. Or just
543 use "sigaction()" and be done with it? */
544 signal(SIGTERM, capture_cleanup);
545 signal(SIGINT, capture_cleanup);
546 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
547 signal(SIGHUP, oldhandler);
549 /* Let the user know what interface was chosen. */
550 printf("Capturing on %s\n", cf.iface);
552 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
558 g_free(cf.save_file);
560 fprintf(stderr, "tethereal: %s\n", errmsg);
568 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
571 struct wtap_pkthdr whdr;
572 loop_data *ld = (loop_data *) user;
576 whdr.caplen = phdr->caplen;
577 whdr.len = phdr->len;
578 whdr.pkt_encap = ld->linktype;
583 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
585 printf("\r%u ", cf.count);
588 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
593 capture_cleanup(int signum)
600 wtap_dump_close(ld.pdh, &err);
601 /* XXX - complain if this fails */
604 #endif /* HAVE_LIBPCAP */
607 load_cap_file(capture_file *cf, int out_file_type)
615 linktype = wtap_file_encap(cf->wth);
616 if (cf->save_file != NULL) {
617 /* Set up to write to the capture file. */
618 pdh = wtap_dump_open(cf->save_file, out_file_type,
619 linktype, wtap_snapshot_length(cf->wth), &err);
622 /* We couldn't set up to write to the capture file. */
625 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
627 "tethereal: Capture files can't be written in that format.\n");
630 case WTAP_ERR_UNSUPPORTED_ENCAP:
631 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
633 "tethereal: The capture file being read cannot be written in that format.\n");
636 case WTAP_ERR_CANT_OPEN:
638 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
642 case WTAP_ERR_SHORT_WRITE:
644 "tethereal: A full header couldn't be written to the file \"%s\".\n",
651 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
655 "tethereal: The file \"%s\" could not be opened: %s\n.",
656 cf->save_file, strerror(err));
664 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
669 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
673 /* Print up a message box noting that the read failed somewhere along
677 case WTAP_ERR_CANT_READ:
679 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
682 case WTAP_ERR_SHORT_READ:
684 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
687 case WTAP_ERR_BAD_RECORD:
689 "tethereal: The capture file appears to be damaged or corrupt.\n");
694 "tethereal: An error occurred while reading the capture file: %s.\n",
708 fill_in_fdata(frame_data *fdata, capture_file *cf,
709 const struct wtap_pkthdr *phdr, int offset)
715 fdata->pkt_len = phdr->len;
716 fdata->cap_len = phdr->caplen;
717 fdata->file_off = offset;
718 fdata->lnk_t = phdr->pkt_encap;
719 fdata->abs_secs = phdr->ts.tv_sec;
720 fdata->abs_usecs = phdr->ts.tv_usec;
721 fdata->encoding = CHAR_ASCII;
722 fdata->pseudo_header = phdr->pseudo_header;
725 fdata->num = cf->count;
727 /* If we don't have the time stamp of the first packet in the
728 capture, it's because this is the first packet. Save the time
729 stamp of this packet as the time stamp of the first packet. */
730 if (!firstsec && !firstusec) {
731 firstsec = fdata->abs_secs;
732 firstusec = fdata->abs_usecs;
735 /* Get the time elapsed between the first packet and this packet. */
736 cf->esec = fdata->abs_secs - firstsec;
737 if (firstusec <= fdata->abs_usecs) {
738 cf->eusec = fdata->abs_usecs - firstusec;
740 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
744 /* If we don't have the time stamp of the previous displayed packet,
745 it's because this is the first displayed packet. Save the time
746 stamp of this packet as the time stamp of the previous displayed
748 if (!prevsec && !prevusec) {
749 prevsec = fdata->abs_secs;
750 prevusec = fdata->abs_usecs;
753 /* Get the time elapsed between the first packet and this packet. */
754 fdata->rel_secs = cf->esec;
755 fdata->rel_usecs = cf->eusec;
757 /* Get the time elapsed between the previous displayed packet and
759 fdata->del_secs = fdata->abs_secs - prevsec;
760 if (prevusec <= fdata->abs_usecs) {
761 fdata->del_usecs = fdata->abs_usecs - prevusec;
763 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
766 prevsec = fdata->abs_secs;
767 prevusec = fdata->abs_usecs;
769 fdata->cinfo = &cf->cinfo;
770 for (i = 0; i < fdata->cinfo->num_cols; i++) {
771 fdata->cinfo->col_data[i][0] = '\0';
776 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
779 cb_args_t *args = (cb_args_t *) user;
780 capture_file *cf = args->cf;
781 wtap_dumper *pdh = args->pdh;
783 proto_tree *protocol_tree;
789 fill_in_fdata(&fdata, cf, phdr, offset);
790 protocol_tree = proto_tree_create_root();
791 dissect_packet(buf, &fdata, protocol_tree);
792 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
794 protocol_tree = NULL;
798 /* XXX - do something if this fails */
799 wtap_dump(pdh, phdr, buf, &err);
801 if (protocol_tree != NULL)
802 proto_tree_free(protocol_tree);
806 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
809 cb_args_t *args = (cb_args_t *) user;
810 capture_file *cf = args->cf;
812 proto_tree *protocol_tree;
814 print_args_t print_args;
818 fill_in_fdata(&fdata, cf, phdr, offset);
821 if (cf->rfcode || verbose)
822 protocol_tree = proto_tree_create_root();
824 protocol_tree = NULL;
825 dissect_packet(buf, &fdata, protocol_tree);
827 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
829 /* The packet passed the read filter. */
831 /* Print the information in the protocol tree. */
832 print_args.to_file = TRUE;
833 print_args.format = PR_FMT_TEXT;
834 print_args.print_summary = FALSE;
835 print_args.print_hex = print_hex;
836 print_args.expand_all = TRUE;
837 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
838 buf, &fdata, stdout);
840 /* "print_hex_data()" will put out a leading blank line, as well
841 as a trailing one; print one here, to separate the packets,
842 only if "print_hex_data()" won't be called. */
846 /* Just fill in the columns. */
847 fill_in_columns(&fdata);
848 if (cf->iface == NULL) {
849 printf("%3s %10s %12s -> %-12s %s %s\n",
850 col_info(&fdata, COL_NUMBER),
851 col_info(&fdata, COL_CLS_TIME),
852 col_info(&fdata, COL_DEF_SRC),
853 col_info(&fdata, COL_DEF_DST),
854 col_info(&fdata, COL_PROTOCOL),
855 col_info(&fdata, COL_INFO));
857 printf("%12s -> %-12s %s %s\n",
858 col_info(&fdata, COL_DEF_SRC),
859 col_info(&fdata, COL_DEF_DST),
860 col_info(&fdata, COL_PROTOCOL),
861 col_info(&fdata, COL_INFO));
865 print_hex_data(stdout, print_args.format, buf,
866 fdata.cap_len, fdata.encoding);
871 if (protocol_tree != NULL)
872 proto_tree_free(protocol_tree);
876 file_open_error_message(int err, int for_writing)
879 static char errmsg_errno[1024+1];
883 case WTAP_ERR_NOT_REGULAR_FILE:
884 errmsg = "The file \"%s\" is invalid.";
887 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
888 case WTAP_ERR_UNSUPPORTED:
889 /* Seen only when opening a capture file for reading. */
890 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
893 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
894 /* Seen only when opening a capture file for writing. */
895 errmsg = "Ethereal does not support writing capture files in that format.";
898 case WTAP_ERR_UNSUPPORTED_ENCAP:
899 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
900 /* Seen only when opening a capture file for writing. */
901 errmsg = "Ethereal cannot save this capture in that format.";
904 case WTAP_ERR_BAD_RECORD:
905 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
908 case WTAP_ERR_CANT_OPEN:
910 errmsg = "The file \"%s\" could not be created for some unknown reason.";
912 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
915 case WTAP_ERR_SHORT_READ:
916 errmsg = "The file \"%s\" appears to have been cut short"
917 " in the middle of a packet.";
920 case WTAP_ERR_SHORT_WRITE:
921 errmsg = "A full header couldn't be written to the file \"%s\".";
926 errmsg = "The path to the file \"%s\" does not exist.";
928 errmsg = "The file \"%s\" does not exist.";
933 errmsg = "You do not have permission to create or write to the file \"%s\".";
935 errmsg = "You do not have permission to read the file \"%s\".";
939 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
941 errmsg = errmsg_errno;
948 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
955 char err_msg[2048+1];
957 wth = wtap_open_offline(fname, &err);
961 /* Find the size of the file. */
964 if (fstat(fd, &cf_stat) < 0) {
970 /* The open succeeded. Fill in the information for this file. */
972 /* Initialize the table of conversations. */
975 /* Initialize protocol-specific variables */
976 init_all_protocols();
981 cf->f_len = cf_stat.st_size;
983 /* Set the file name because we need it to set the follow stream filter.
984 XXX - is that still true? We need it for other reasons, though,
986 cf->filename = g_strdup(fname);
988 /* Indicate whether it's a permanent or temporary file. */
989 cf->is_tempfile = is_tempfile;
991 /* If it's a temporary capture buffer file, mark it as not saved. */
992 cf->user_saved = !is_tempfile;
994 cf->cd_t = wtap_file_type(cf->wth);
999 cf->snap = wtap_snapshot_length(cf->wth);
1000 cf->update_progbar = FALSE;
1001 cf->progbar_quantum = 0;
1002 cf->progbar_nextstep = 0;
1003 firstsec = 0, firstusec = 0;
1004 prevsec = 0, prevusec = 0;
1009 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1010 fprintf(stderr, "tethereal: %s\n", err_msg);
1014 /* Get the text in a given column */
1016 col_info(frame_data *fd, gint el) {
1020 for (i = 0; i < fd->cinfo->num_cols; i++) {
1021 if (fd->cinfo->fmt_matx[i][el])
1022 return fd->cinfo->col_data[i];