3 * $Id: tethereal.c,v 1.14 2000/01/24 04:53:54 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 ] [ -D ] [ -f <filter expression> ]\n", PACKAGE);
148 fprintf(stderr, "\t[ -F <capture type> ] [ -i iface ] [ -n ] [ -r infile ]\n");
149 fprintf(stderr, "\t[ -R <filter expression> ] [ -s snaplen ] [ -t <time stamp format> ]\n");
150 fprintf(stderr, "\t[ -w savefile ] [ -x ]\n");
151 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
152 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
153 if (wtap_dump_can_open(i))
154 fprintf(stderr, "\t%s - %s\n",
155 wtap_file_type_short_string(i), wtap_file_type_string(i));
157 fprintf(stderr, "\tdefault is libpcap\n");
161 main(int argc, char *argv[])
165 gboolean arg_error = FALSE;
167 extern char pcap_version[];
172 int packet_count = 0;
174 gchar err_str[PCAP_ERRBUF_SIZE];
176 gboolean capture_option_specified = FALSE;
178 int out_file_type = WTAP_FILE_PCAP;
179 gchar *cf_name = NULL, *rfilter = NULL;
180 dfilter *rfcode = NULL;
183 /* If invoked with the "-G" flag, we dump out a glossary of
184 display filter symbols.
186 We do this here to mirror what happens in the GTK+ version, although
187 it's not necessary here. */
188 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
189 ethereal_proto_init();
190 proto_registrar_dump();
194 prefs = read_prefs(&pf_path);
195 if (pf_path != NULL) {
196 fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
200 /* Initialize the capture file struct */
206 cf.user_saved = FALSE;
207 cf.is_tempfile = FALSE;
212 cf.cfilter = g_strdup("");
216 cf.save_file_fd = -1;
217 cf.snap = WTAP_MAX_PACKET_SIZE;
219 cf.cinfo.num_cols = prefs->num_cols;
220 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
221 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
222 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
223 cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
224 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
226 /* Assemble the compile-time options */
227 snprintf(comp_info_str, 256,
228 #ifdef GTK_MAJOR_VERSION
229 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
232 "GTK+ (version unknown), %s%s, %s%s, %s%s",
236 "with libpcap ", pcap_version,
238 "without libpcap", "",
243 "with libz ", ZLIB_VERSION,
244 #else /* ZLIB_VERSION */
245 "with libz ", "(version unknown)",
246 #endif /* ZLIB_VERSION */
247 #else /* HAVE_LIBZ */
249 #endif /* HAVE_LIBZ */
251 /* Oh, this is pretty */
252 #if defined(HAVE_UCD_SNMP_SNMP_H)
253 #ifdef HAVE_UCD_SNMP_VERSION_H
254 "with UCD SNMP ", VersionInfo
255 #else /* HAVE_UCD_SNMP_VERSION_H */
256 "with UCD SNMP ", "(version unknown)"
257 #endif /* HAVE_UCD_SNMP_VERSION_H */
258 #elif defined(HAVE_SNMP_SNMP_H)
259 #ifdef HAVE_SNMP_VERSION_H
260 "with CMU SNMP ", snmp_Version()
261 #else /* HAVE_SNMP_VERSION_H */
262 "with CMU SNMP ", "(version unknown)"
263 #endif /* HAVE_SNMP_VERSION_H */
269 /* Now get our args */
270 while ((opt = getopt(argc, argv, "c:Df:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
272 case 'c': /* Capture xxx packets */
274 packet_count = atoi(optarg);
276 capture_option_specified = TRUE;
280 case 'D': /* Turn off DSCP printing */
281 g_ip_dscp_actif = FALSE;
285 cf.cfilter = g_strdup(optarg);
287 capture_option_specified = TRUE;
292 out_file_type = wtap_short_string_to_file_type(optarg);
293 if (out_file_type < 0) {
294 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
299 case 'h': /* Print help and exit */
303 case 'i': /* Use interface xxx */
305 cf.iface = g_strdup(optarg);
307 capture_option_specified = TRUE;
311 case 'n': /* No name resolution */
312 g_resolving_actif = 0;
314 case 'r': /* Read capture file xxx */
315 cf_name = g_strdup(optarg);
317 case 'R': /* Read file filter */
320 case 's': /* Set the snapshot (capture) length */
322 cf.snap = atoi(optarg);
324 capture_option_specified = TRUE;
328 case 't': /* Time stamp type */
329 if (strcmp(optarg, "r") == 0)
330 timestamp_type = RELATIVE;
331 else if (strcmp(optarg, "a") == 0)
332 timestamp_type = ABSOLUTE;
333 else if (strcmp(optarg, "d") == 0)
334 timestamp_type = DELTA;
336 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
338 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
339 fprintf(stderr, "or \"d\" for delta.\n");
343 case 'v': /* Show version and exit */
344 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
347 case 'w': /* Write to capture file xxx */
348 cf.save_file = g_strdup(optarg);
350 case 'V': /* Verbose */
353 case 'x': /* Print packet data in hex (and ASCII) */
360 if (capture_option_specified)
361 fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
366 /* Build the column format array */
367 for (i = 0; i < cf.cinfo.num_cols; i++) {
368 cf.cinfo.col_fmt[i] = get_column_format(i);
369 cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
370 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
372 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
373 if (cf.cinfo.col_fmt[i] == COL_INFO)
374 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
376 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
380 cf.snap = WTAP_MAX_PACKET_SIZE;
381 else if (cf.snap < MIN_PACKET_SIZE)
382 cf.snap = MIN_PACKET_SIZE;
384 ethereal_proto_init(); /* Init anything that needs initializing */
386 if (rfilter != NULL) {
387 if (dfilter_compile(rfilter, &rfcode) != 0) {
388 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
389 ethereal_proto_cleanup();
395 err = open_cap_file(cf_name, FALSE, &cf);
397 ethereal_proto_cleanup();
400 err = load_cap_file(&cf, out_file_type);
402 ethereal_proto_cleanup();
407 /* No capture file specified, so we're supposed to do a live capture;
408 do we have support for live captures? */
410 /* Yes; did the user specify an interface to use? */
411 if (cf.iface == NULL) {
412 /* No - pick the first one from the list of interfaces. */
413 if_list = get_interface_list(&err, err_str);
414 if (if_list == NULL) {
417 case CANT_GET_INTERFACE_LIST:
418 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
422 case NO_INTERFACES_FOUND:
423 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
428 cf.iface = g_strdup(if_list->data); /* first interface */
429 free_interface_list(if_list);
431 capture(packet_count, out_file_type);
434 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
439 ethereal_proto_cleanup();
445 /* Do the low-level work of a capture.
446 Returns TRUE if it succeeds, FALSE otherwise. */
448 capture(int packet_count, int out_file_type)
450 gchar err_str[PCAP_ERRBUF_SIZE];
451 bpf_u_int32 netnum, netmask;
452 void (*oldhandler)(int);
456 ld.linktype = WTAP_ENCAP_UNKNOWN;
459 /* Open the network interface to capture from it. */
460 ld.pch = pcap_open_live(cf.iface, cf.snap, 1, 1000, err_str);
462 if (ld.pch == NULL) {
463 /* Well, we couldn't start the capture.
464 If this is a child process that does the capturing in sync
465 mode or fork mode, it shouldn't do any UI stuff until we pop up the
466 capture-progress window, and, since we couldn't start the
467 capture, we haven't popped it up. */
468 snprintf(errmsg, sizeof errmsg,
469 "The capture session could not be initiated (%s).\n"
470 "Please check to make sure you have sufficient permissions, and that\n"
471 "you have the proper interface specified.", err_str);
476 /* A capture filter was specified; set it up. */
477 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
478 snprintf(errmsg, sizeof errmsg,
479 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
482 if (pcap_compile(ld.pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
483 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
484 pcap_geterr(ld.pch));
487 if (pcap_setfilter(ld.pch, &cf.fcode) < 0) {
488 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
489 pcap_geterr(ld.pch));
494 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
495 if (cf.save_file != NULL) {
496 /* Set up to write to the capture file. */
497 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
498 strcpy(errmsg, "The network you're capturing from is of a type"
499 " that Ethereal doesn't support.");
502 ld.pdh = wtap_dump_open(cf.save_file, out_file_type,
503 ld.linktype, pcap_snapshot(ld.pch), &err);
505 if (ld.pdh == NULL) {
506 /* We couldn't set up to write to the capture file. */
509 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
510 strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
513 case WTAP_ERR_UNSUPPORTED_ENCAP:
514 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
515 strcpy(errmsg, "Tethereal cannot save this capture in that format.");
518 case WTAP_ERR_CANT_OPEN:
519 strcpy(errmsg, "The file to which the capture would be written"
520 " couldn't be created for some unknown reason.");
523 case WTAP_ERR_SHORT_WRITE:
524 strcpy(errmsg, "A full header couldn't be written to the file"
525 " to which the capture would be written.");
530 sprintf(errmsg, "The file to which the capture would be"
531 " written (\"%s\") could not be opened: Error %d.",
534 sprintf(errmsg, "The file to which the capture would be"
535 " written (\"%s\") could not be opened: %s.",
536 cf.save_file, strerror(err));
544 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
546 XXX - deal with signal semantics on various platforms. Or just
547 use "sigaction()" and be done with it? */
548 signal(SIGTERM, capture_cleanup);
549 signal(SIGINT, capture_cleanup);
550 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
551 signal(SIGHUP, oldhandler);
553 /* Let the user know what interface was chosen. */
554 printf("Capturing on %s\n", cf.iface);
556 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
562 g_free(cf.save_file);
564 fprintf(stderr, "tethereal: %s\n", errmsg);
572 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
575 struct wtap_pkthdr whdr;
576 loop_data *ld = (loop_data *) user;
580 whdr.caplen = phdr->caplen;
581 whdr.len = phdr->len;
582 whdr.pkt_encap = ld->linktype;
587 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
589 printf("\r%u ", cf.count);
592 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
597 capture_cleanup(int signum)
604 wtap_dump_close(ld.pdh, &err);
605 /* XXX - complain if this fails */
608 #endif /* HAVE_LIBPCAP */
611 load_cap_file(capture_file *cf, int out_file_type)
619 linktype = wtap_file_encap(cf->wth);
620 if (cf->save_file != NULL) {
621 /* Set up to write to the capture file. */
622 pdh = wtap_dump_open(cf->save_file, out_file_type,
623 linktype, wtap_snapshot_length(cf->wth), &err);
626 /* We couldn't set up to write to the capture file. */
629 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
631 "tethereal: Capture files can't be written in that format.\n");
634 case WTAP_ERR_UNSUPPORTED_ENCAP:
635 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
637 "tethereal: The capture file being read cannot be written in that format.\n");
640 case WTAP_ERR_CANT_OPEN:
642 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
646 case WTAP_ERR_SHORT_WRITE:
648 "tethereal: A full header couldn't be written to the file \"%s\".\n",
655 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
659 "tethereal: The file \"%s\" could not be opened: %s\n.",
660 cf->save_file, strerror(err));
668 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
673 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
677 /* Print up a message box noting that the read failed somewhere along
681 case WTAP_ERR_CANT_READ:
683 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
686 case WTAP_ERR_SHORT_READ:
688 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
691 case WTAP_ERR_BAD_RECORD:
693 "tethereal: The capture file appears to be damaged or corrupt.\n");
698 "tethereal: An error occurred while reading the capture file: %s.\n",
712 fill_in_fdata(frame_data *fdata, capture_file *cf,
713 const struct wtap_pkthdr *phdr, int offset)
719 fdata->pkt_len = phdr->len;
720 fdata->cap_len = phdr->caplen;
721 fdata->file_off = offset;
722 fdata->lnk_t = phdr->pkt_encap;
723 fdata->abs_secs = phdr->ts.tv_sec;
724 fdata->abs_usecs = phdr->ts.tv_usec;
725 fdata->encoding = CHAR_ASCII;
726 fdata->pseudo_header = phdr->pseudo_header;
729 fdata->num = cf->count;
731 /* If we don't have the time stamp of the first packet in the
732 capture, it's because this is the first packet. Save the time
733 stamp of this packet as the time stamp of the first packet. */
734 if (!firstsec && !firstusec) {
735 firstsec = fdata->abs_secs;
736 firstusec = fdata->abs_usecs;
739 /* Get the time elapsed between the first packet and this packet. */
740 cf->esec = fdata->abs_secs - firstsec;
741 if (firstusec <= fdata->abs_usecs) {
742 cf->eusec = fdata->abs_usecs - firstusec;
744 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
748 /* If we don't have the time stamp of the previous displayed packet,
749 it's because this is the first displayed packet. Save the time
750 stamp of this packet as the time stamp of the previous displayed
752 if (!prevsec && !prevusec) {
753 prevsec = fdata->abs_secs;
754 prevusec = fdata->abs_usecs;
757 /* Get the time elapsed between the first packet and this packet. */
758 fdata->rel_secs = cf->esec;
759 fdata->rel_usecs = cf->eusec;
761 /* Get the time elapsed between the previous displayed packet and
763 fdata->del_secs = fdata->abs_secs - prevsec;
764 if (prevusec <= fdata->abs_usecs) {
765 fdata->del_usecs = fdata->abs_usecs - prevusec;
767 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
770 prevsec = fdata->abs_secs;
771 prevusec = fdata->abs_usecs;
773 fdata->cinfo = &cf->cinfo;
774 for (i = 0; i < fdata->cinfo->num_cols; i++) {
775 fdata->cinfo->col_data[i][0] = '\0';
780 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
783 cb_args_t *args = (cb_args_t *) user;
784 capture_file *cf = args->cf;
785 wtap_dumper *pdh = args->pdh;
787 proto_tree *protocol_tree;
793 fill_in_fdata(&fdata, cf, phdr, offset);
794 protocol_tree = proto_tree_create_root();
795 dissect_packet(buf, &fdata, protocol_tree);
796 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
798 protocol_tree = NULL;
802 /* XXX - do something if this fails */
803 wtap_dump(pdh, phdr, buf, &err);
805 if (protocol_tree != NULL)
806 proto_tree_free(protocol_tree);
810 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
813 cb_args_t *args = (cb_args_t *) user;
814 capture_file *cf = args->cf;
816 proto_tree *protocol_tree;
818 print_args_t print_args;
822 fill_in_fdata(&fdata, cf, phdr, offset);
825 if (cf->rfcode || verbose)
826 protocol_tree = proto_tree_create_root();
828 protocol_tree = NULL;
829 dissect_packet(buf, &fdata, protocol_tree);
831 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
833 /* The packet passed the read filter. */
835 /* Print the information in the protocol tree. */
836 print_args.to_file = TRUE;
837 print_args.format = PR_FMT_TEXT;
838 print_args.print_summary = FALSE;
839 print_args.print_hex = print_hex;
840 print_args.expand_all = TRUE;
841 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
842 buf, &fdata, stdout);
844 /* "print_hex_data()" will put out a leading blank line, as well
845 as a trailing one; print one here, to separate the packets,
846 only if "print_hex_data()" won't be called. */
850 /* Just fill in the columns. */
851 fill_in_columns(&fdata);
852 if (cf->iface == NULL) {
853 printf("%3s %10s %12s -> %-12s %s %s\n",
854 col_info(&fdata, COL_NUMBER),
855 col_info(&fdata, COL_CLS_TIME),
856 col_info(&fdata, COL_DEF_SRC),
857 col_info(&fdata, COL_DEF_DST),
858 col_info(&fdata, COL_PROTOCOL),
859 col_info(&fdata, COL_INFO));
861 printf("%12s -> %-12s %s %s\n",
862 col_info(&fdata, COL_DEF_SRC),
863 col_info(&fdata, COL_DEF_DST),
864 col_info(&fdata, COL_PROTOCOL),
865 col_info(&fdata, COL_INFO));
869 print_hex_data(stdout, print_args.format, buf,
870 fdata.cap_len, fdata.encoding);
875 if (protocol_tree != NULL)
876 proto_tree_free(protocol_tree);
880 file_open_error_message(int err, int for_writing)
883 static char errmsg_errno[1024+1];
887 case WTAP_ERR_NOT_REGULAR_FILE:
888 errmsg = "The file \"%s\" is invalid.";
891 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
892 case WTAP_ERR_UNSUPPORTED:
893 /* Seen only when opening a capture file for reading. */
894 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
897 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
898 /* Seen only when opening a capture file for writing. */
899 errmsg = "Ethereal does not support writing capture files in that format.";
902 case WTAP_ERR_UNSUPPORTED_ENCAP:
903 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
904 /* Seen only when opening a capture file for writing. */
905 errmsg = "Ethereal cannot save this capture in that format.";
908 case WTAP_ERR_BAD_RECORD:
909 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
912 case WTAP_ERR_CANT_OPEN:
914 errmsg = "The file \"%s\" could not be created for some unknown reason.";
916 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
919 case WTAP_ERR_SHORT_READ:
920 errmsg = "The file \"%s\" appears to have been cut short"
921 " in the middle of a packet.";
924 case WTAP_ERR_SHORT_WRITE:
925 errmsg = "A full header couldn't be written to the file \"%s\".";
930 errmsg = "The path to the file \"%s\" does not exist.";
932 errmsg = "The file \"%s\" does not exist.";
937 errmsg = "You do not have permission to create or write to the file \"%s\".";
939 errmsg = "You do not have permission to read the file \"%s\".";
943 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
945 errmsg = errmsg_errno;
952 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
959 char err_msg[2048+1];
961 wth = wtap_open_offline(fname, &err);
965 /* Find the size of the file. */
968 if (fstat(fd, &cf_stat) < 0) {
974 /* The open succeeded. Fill in the information for this file. */
976 /* Initialize the table of conversations. */
979 /* Initialize protocol-specific variables */
980 init_all_protocols();
985 cf->f_len = cf_stat.st_size;
987 /* Set the file name because we need it to set the follow stream filter.
988 XXX - is that still true? We need it for other reasons, though,
990 cf->filename = g_strdup(fname);
992 /* Indicate whether it's a permanent or temporary file. */
993 cf->is_tempfile = is_tempfile;
995 /* If it's a temporary capture buffer file, mark it as not saved. */
996 cf->user_saved = !is_tempfile;
998 cf->cd_t = wtap_file_type(cf->wth);
1003 cf->snap = wtap_snapshot_length(cf->wth);
1004 cf->update_progbar = FALSE;
1005 cf->progbar_quantum = 0;
1006 cf->progbar_nextstep = 0;
1007 firstsec = 0, firstusec = 0;
1008 prevsec = 0, prevusec = 0;
1013 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1014 fprintf(stderr, "tethereal: %s\n", err_msg);
1018 /* Get the text in a given column */
1020 col_info(frame_data *fd, gint el) {
1024 for (i = 0; i < fd->cinfo->num_cols; i++) {
1025 if (fd->cinfo->fmt_matx[i][el])
1026 return fd->cinfo->col_data[i];