3 * $Id: tethereal.c,v 1.15 2000/01/24 05:13:45 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 file 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");
152 fprintf(stderr, "t%s [ -vVh ] [ -D ] [ -F <capture file type> ] [ -n ] [ -r infile ]\n", PACKAGE);
153 fprintf(stderr, "\t[ -R <filter expression> ] [ -t <time stamp format> ] [ -w savefile ]\n");
154 fprintf(stderr, "\t[ -x ]\n");
156 fprintf(stderr, "Valid file type arguments to the \"-F\" flag:\n");
157 for (i = 0; i < WTAP_NUM_FILE_TYPES; i++) {
158 if (wtap_dump_can_open(i))
159 fprintf(stderr, "\t%s - %s\n",
160 wtap_file_type_short_string(i), wtap_file_type_string(i));
162 fprintf(stderr, "\tdefault is libpcap\n");
166 main(int argc, char *argv[])
170 gboolean arg_error = FALSE;
172 extern char pcap_version[];
177 int packet_count = 0;
179 gchar err_str[PCAP_ERRBUF_SIZE];
181 gboolean capture_option_specified = FALSE;
183 int out_file_type = WTAP_FILE_PCAP;
184 gchar *cf_name = NULL, *rfilter = NULL;
185 dfilter *rfcode = NULL;
188 /* If invoked with the "-G" flag, we dump out a glossary of
189 display filter symbols.
191 We do this here to mirror what happens in the GTK+ version, although
192 it's not necessary here. */
193 if (argc >= 2 && strcmp(argv[1], "-G") == 0) {
194 ethereal_proto_init();
195 proto_registrar_dump();
199 prefs = read_prefs(&pf_path);
200 if (pf_path != NULL) {
201 fprintf(stderr, "Can't open preferences file \"%s\": %s.\n", pf_path,
205 /* Initialize the capture file struct */
211 cf.user_saved = FALSE;
212 cf.is_tempfile = FALSE;
217 cf.cfilter = g_strdup("");
221 cf.save_file_fd = -1;
222 cf.snap = WTAP_MAX_PACKET_SIZE;
224 cf.cinfo.num_cols = prefs->num_cols;
225 cf.cinfo.col_fmt = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
226 cf.cinfo.fmt_matx = (gboolean **) g_malloc(sizeof(gboolean *) * cf.cinfo.num_cols);
227 cf.cinfo.col_width = (gint *) g_malloc(sizeof(gint) * cf.cinfo.num_cols);
228 cf.cinfo.col_title = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
229 cf.cinfo.col_data = (gchar **) g_malloc(sizeof(gchar *) * cf.cinfo.num_cols);
231 /* Assemble the compile-time options */
232 snprintf(comp_info_str, 256,
233 #ifdef GTK_MAJOR_VERSION
234 "GTK+ %d.%d.%d, %s%s, %s%s, %s%s", GTK_MAJOR_VERSION, GTK_MINOR_VERSION,
237 "GTK+ (version unknown), %s%s, %s%s, %s%s",
241 "with libpcap ", pcap_version,
243 "without libpcap", "",
248 "with libz ", ZLIB_VERSION,
249 #else /* ZLIB_VERSION */
250 "with libz ", "(version unknown)",
251 #endif /* ZLIB_VERSION */
252 #else /* HAVE_LIBZ */
254 #endif /* HAVE_LIBZ */
256 /* Oh, this is pretty */
257 #if defined(HAVE_UCD_SNMP_SNMP_H)
258 #ifdef HAVE_UCD_SNMP_VERSION_H
259 "with UCD SNMP ", VersionInfo
260 #else /* HAVE_UCD_SNMP_VERSION_H */
261 "with UCD SNMP ", "(version unknown)"
262 #endif /* HAVE_UCD_SNMP_VERSION_H */
263 #elif defined(HAVE_SNMP_SNMP_H)
264 #ifdef HAVE_SNMP_VERSION_H
265 "with CMU SNMP ", snmp_Version()
266 #else /* HAVE_SNMP_VERSION_H */
267 "with CMU SNMP ", "(version unknown)"
268 #endif /* HAVE_SNMP_VERSION_H */
274 /* Now get our args */
275 while ((opt = getopt(argc, argv, "c:Df:F:hi:nr:R:s:t:vw:Vx")) != EOF) {
277 case 'c': /* Capture xxx packets */
279 packet_count = atoi(optarg);
281 capture_option_specified = TRUE;
285 case 'D': /* Turn off DSCP printing */
286 g_ip_dscp_actif = FALSE;
290 cf.cfilter = g_strdup(optarg);
292 capture_option_specified = TRUE;
297 out_file_type = wtap_short_string_to_file_type(optarg);
298 if (out_file_type < 0) {
299 fprintf(stderr, "tethereal: \"%s\" is not a valid capture file type\n",
304 case 'h': /* Print help and exit */
308 case 'i': /* Use interface xxx */
310 cf.iface = g_strdup(optarg);
312 capture_option_specified = TRUE;
316 case 'n': /* No name resolution */
317 g_resolving_actif = 0;
319 case 'r': /* Read capture file xxx */
320 cf_name = g_strdup(optarg);
322 case 'R': /* Read file filter */
325 case 's': /* Set the snapshot (capture) length */
327 cf.snap = atoi(optarg);
329 capture_option_specified = TRUE;
333 case 't': /* Time stamp type */
334 if (strcmp(optarg, "r") == 0)
335 timestamp_type = RELATIVE;
336 else if (strcmp(optarg, "a") == 0)
337 timestamp_type = ABSOLUTE;
338 else if (strcmp(optarg, "d") == 0)
339 timestamp_type = DELTA;
341 fprintf(stderr, "tethereal: Invalid time stamp type \"%s\"\n",
343 fprintf(stderr, "It must be \"r\" for relative, \"a\" for absolute,\n");
344 fprintf(stderr, "or \"d\" for delta.\n");
348 case 'v': /* Show version and exit */
349 printf("t%s %s, with %s\n", PACKAGE, VERSION, comp_info_str);
352 case 'w': /* Write to capture file xxx */
353 cf.save_file = g_strdup(optarg);
355 case 'V': /* Verbose */
358 case 'x': /* Print packet data in hex (and ASCII) */
365 if (capture_option_specified)
366 fprintf(stderr, "This version of Ethereal was not built with support for capturing packets.\n");
371 /* Build the column format array */
372 for (i = 0; i < cf.cinfo.num_cols; i++) {
373 cf.cinfo.col_fmt[i] = get_column_format(i);
374 cf.cinfo.col_title[i] = g_strdup(get_column_title(i));
375 cf.cinfo.fmt_matx[i] = (gboolean *) g_malloc0(sizeof(gboolean) *
377 get_column_format_matches(cf.cinfo.fmt_matx[i], cf.cinfo.col_fmt[i]);
378 if (cf.cinfo.col_fmt[i] == COL_INFO)
379 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_INFO_LEN);
381 cf.cinfo.col_data[i] = (gchar *) g_malloc(sizeof(gchar) * COL_MAX_LEN);
385 cf.snap = WTAP_MAX_PACKET_SIZE;
386 else if (cf.snap < MIN_PACKET_SIZE)
387 cf.snap = MIN_PACKET_SIZE;
389 ethereal_proto_init(); /* Init anything that needs initializing */
391 if (rfilter != NULL) {
392 if (dfilter_compile(rfilter, &rfcode) != 0) {
393 fprintf(stderr, "tethereal: %s\n", dfilter_error_msg);
394 ethereal_proto_cleanup();
400 err = open_cap_file(cf_name, FALSE, &cf);
402 ethereal_proto_cleanup();
405 err = load_cap_file(&cf, out_file_type);
407 ethereal_proto_cleanup();
412 /* No capture file specified, so we're supposed to do a live capture;
413 do we have support for live captures? */
415 /* Yes; did the user specify an interface to use? */
416 if (cf.iface == NULL) {
417 /* No - pick the first one from the list of interfaces. */
418 if_list = get_interface_list(&err, err_str);
419 if (if_list == NULL) {
422 case CANT_GET_INTERFACE_LIST:
423 fprintf(stderr, "tethereal: Can't get list of interfaces: %s\n",
427 case NO_INTERFACES_FOUND:
428 fprintf(stderr, "tethereal: There are no interfaces on which a capture can be done\n");
433 cf.iface = g_strdup(if_list->data); /* first interface */
434 free_interface_list(if_list);
436 capture(packet_count, out_file_type);
439 fprintf(stderr, "This version of Tethereal was not built with support for capturing packets.\n");
444 ethereal_proto_cleanup();
450 /* Do the low-level work of a capture.
451 Returns TRUE if it succeeds, FALSE otherwise. */
453 capture(int packet_count, int out_file_type)
455 gchar err_str[PCAP_ERRBUF_SIZE];
456 bpf_u_int32 netnum, netmask;
457 void (*oldhandler)(int);
461 ld.linktype = WTAP_ENCAP_UNKNOWN;
464 /* Open the network interface to capture from it. */
465 ld.pch = pcap_open_live(cf.iface, cf.snap, 1, 1000, err_str);
467 if (ld.pch == NULL) {
468 /* Well, we couldn't start the capture.
469 If this is a child process that does the capturing in sync
470 mode or fork mode, it shouldn't do any UI stuff until we pop up the
471 capture-progress window, and, since we couldn't start the
472 capture, we haven't popped it up. */
473 snprintf(errmsg, sizeof errmsg,
474 "The capture session could not be initiated (%s).\n"
475 "Please check to make sure you have sufficient permissions, and that\n"
476 "you have the proper interface specified.", err_str);
481 /* A capture filter was specified; set it up. */
482 if (pcap_lookupnet (cf.iface, &netnum, &netmask, err_str) < 0) {
483 snprintf(errmsg, sizeof errmsg,
484 "Can't use filter: Couldn't obtain netmask info (%s).", err_str);
487 if (pcap_compile(ld.pch, &cf.fcode, cf.cfilter, 1, netmask) < 0) {
488 snprintf(errmsg, sizeof errmsg, "Unable to parse filter string (%s).",
489 pcap_geterr(ld.pch));
492 if (pcap_setfilter(ld.pch, &cf.fcode) < 0) {
493 snprintf(errmsg, sizeof errmsg, "Can't install filter (%s).",
494 pcap_geterr(ld.pch));
499 ld.linktype = wtap_pcap_encap_to_wtap_encap(pcap_datalink(ld.pch));
500 if (cf.save_file != NULL) {
501 /* Set up to write to the capture file. */
502 if (ld.linktype == WTAP_ENCAP_UNKNOWN) {
503 strcpy(errmsg, "The network you're capturing from is of a type"
504 " that Ethereal doesn't support.");
507 ld.pdh = wtap_dump_open(cf.save_file, out_file_type,
508 ld.linktype, pcap_snapshot(ld.pch), &err);
510 if (ld.pdh == NULL) {
511 /* We couldn't set up to write to the capture file. */
514 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
515 strcpy(errmsg, "Tethereal does not support writing capture files in that format.");
518 case WTAP_ERR_UNSUPPORTED_ENCAP:
519 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
520 strcpy(errmsg, "Tethereal cannot save this capture in that format.");
523 case WTAP_ERR_CANT_OPEN:
524 strcpy(errmsg, "The file to which the capture would be written"
525 " couldn't be created for some unknown reason.");
528 case WTAP_ERR_SHORT_WRITE:
529 strcpy(errmsg, "A full header couldn't be written to the file"
530 " to which the capture would be written.");
535 sprintf(errmsg, "The file to which the capture would be"
536 " written (\"%s\") could not be opened: Error %d.",
539 sprintf(errmsg, "The file to which the capture would be"
540 " written (\"%s\") could not be opened: %s.",
541 cf.save_file, strerror(err));
549 /* Catch SIGINT and SIGTERM and, if we get either of them, clean up
551 XXX - deal with signal semantics on various platforms. Or just
552 use "sigaction()" and be done with it? */
553 signal(SIGTERM, capture_cleanup);
554 signal(SIGINT, capture_cleanup);
555 if ((oldhandler = signal(SIGHUP, capture_cleanup)) != SIG_DFL)
556 signal(SIGHUP, oldhandler);
558 /* Let the user know what interface was chosen. */
559 printf("Capturing on %s\n", cf.iface);
561 inpkts = pcap_loop(ld.pch, packet_count, capture_pcap_cb, (u_char *) &ld);
567 g_free(cf.save_file);
569 fprintf(stderr, "tethereal: %s\n", errmsg);
577 capture_pcap_cb(u_char *user, const struct pcap_pkthdr *phdr,
580 struct wtap_pkthdr whdr;
581 loop_data *ld = (loop_data *) user;
585 whdr.caplen = phdr->caplen;
586 whdr.len = phdr->len;
587 whdr.pkt_encap = ld->linktype;
592 wtap_dispatch_cb_write((u_char *)&args, &whdr, 0, pd);
594 printf("\r%u ", cf.count);
597 wtap_dispatch_cb_print((u_char *)&args, &whdr, 0, pd);
602 capture_cleanup(int signum)
609 wtap_dump_close(ld.pdh, &err);
610 /* XXX - complain if this fails */
613 #endif /* HAVE_LIBPCAP */
616 load_cap_file(capture_file *cf, int out_file_type)
624 linktype = wtap_file_encap(cf->wth);
625 if (cf->save_file != NULL) {
626 /* Set up to write to the capture file. */
627 pdh = wtap_dump_open(cf->save_file, out_file_type,
628 linktype, wtap_snapshot_length(cf->wth), &err);
631 /* We couldn't set up to write to the capture file. */
634 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
636 "tethereal: Capture files can't be written in that format.\n");
639 case WTAP_ERR_UNSUPPORTED_ENCAP:
640 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
642 "tethereal: The capture file being read cannot be written in that format.\n");
645 case WTAP_ERR_CANT_OPEN:
647 "tethereal: The file \"%s\" couldn't be created for some unknown reason.\n",
651 case WTAP_ERR_SHORT_WRITE:
653 "tethereal: A full header couldn't be written to the file \"%s\".\n",
660 "tethereal: The file \"%s\" could not be opened: Error %d.\n",
664 "tethereal: The file \"%s\" could not be opened: %s\n.",
665 cf->save_file, strerror(err));
673 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_write, (u_char *) &args,
678 success = wtap_loop(cf->wth, 0, wtap_dispatch_cb_print, (u_char *) &args,
682 /* Print up a message box noting that the read failed somewhere along
686 case WTAP_ERR_CANT_READ:
688 "tethereal: An attempt to read from the file failed for some unknown reason.\n");
691 case WTAP_ERR_SHORT_READ:
693 "tethereal: The capture file appears to have been cut short in the middle of a packet.\n");
696 case WTAP_ERR_BAD_RECORD:
698 "tethereal: The capture file appears to be damaged or corrupt.\n");
703 "tethereal: An error occurred while reading the capture file: %s.\n",
717 fill_in_fdata(frame_data *fdata, capture_file *cf,
718 const struct wtap_pkthdr *phdr, int offset)
724 fdata->pkt_len = phdr->len;
725 fdata->cap_len = phdr->caplen;
726 fdata->file_off = offset;
727 fdata->lnk_t = phdr->pkt_encap;
728 fdata->abs_secs = phdr->ts.tv_sec;
729 fdata->abs_usecs = phdr->ts.tv_usec;
730 fdata->encoding = CHAR_ASCII;
731 fdata->pseudo_header = phdr->pseudo_header;
734 fdata->num = cf->count;
736 /* If we don't have the time stamp of the first packet in the
737 capture, it's because this is the first packet. Save the time
738 stamp of this packet as the time stamp of the first packet. */
739 if (!firstsec && !firstusec) {
740 firstsec = fdata->abs_secs;
741 firstusec = fdata->abs_usecs;
744 /* Get the time elapsed between the first packet and this packet. */
745 cf->esec = fdata->abs_secs - firstsec;
746 if (firstusec <= fdata->abs_usecs) {
747 cf->eusec = fdata->abs_usecs - firstusec;
749 cf->eusec = (fdata->abs_usecs + 1000000) - firstusec;
753 /* If we don't have the time stamp of the previous displayed packet,
754 it's because this is the first displayed packet. Save the time
755 stamp of this packet as the time stamp of the previous displayed
757 if (!prevsec && !prevusec) {
758 prevsec = fdata->abs_secs;
759 prevusec = fdata->abs_usecs;
762 /* Get the time elapsed between the first packet and this packet. */
763 fdata->rel_secs = cf->esec;
764 fdata->rel_usecs = cf->eusec;
766 /* Get the time elapsed between the previous displayed packet and
768 fdata->del_secs = fdata->abs_secs - prevsec;
769 if (prevusec <= fdata->abs_usecs) {
770 fdata->del_usecs = fdata->abs_usecs - prevusec;
772 fdata->del_usecs = (fdata->abs_usecs + 1000000) - prevusec;
775 prevsec = fdata->abs_secs;
776 prevusec = fdata->abs_usecs;
778 fdata->cinfo = &cf->cinfo;
779 for (i = 0; i < fdata->cinfo->num_cols; i++) {
780 fdata->cinfo->col_data[i][0] = '\0';
785 wtap_dispatch_cb_write(u_char *user, const struct wtap_pkthdr *phdr, int offset,
788 cb_args_t *args = (cb_args_t *) user;
789 capture_file *cf = args->cf;
790 wtap_dumper *pdh = args->pdh;
792 proto_tree *protocol_tree;
798 fill_in_fdata(&fdata, cf, phdr, offset);
799 protocol_tree = proto_tree_create_root();
800 dissect_packet(buf, &fdata, protocol_tree);
801 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
803 protocol_tree = NULL;
807 /* XXX - do something if this fails */
808 wtap_dump(pdh, phdr, buf, &err);
810 if (protocol_tree != NULL)
811 proto_tree_free(protocol_tree);
815 wtap_dispatch_cb_print(u_char *user, const struct wtap_pkthdr *phdr, int offset,
818 cb_args_t *args = (cb_args_t *) user;
819 capture_file *cf = args->cf;
821 proto_tree *protocol_tree;
823 print_args_t print_args;
827 fill_in_fdata(&fdata, cf, phdr, offset);
830 if (cf->rfcode || verbose)
831 protocol_tree = proto_tree_create_root();
833 protocol_tree = NULL;
834 dissect_packet(buf, &fdata, protocol_tree);
836 passed = dfilter_apply(cf->rfcode, protocol_tree, buf);
838 /* The packet passed the read filter. */
840 /* Print the information in the protocol tree. */
841 print_args.to_file = TRUE;
842 print_args.format = PR_FMT_TEXT;
843 print_args.print_summary = FALSE;
844 print_args.print_hex = print_hex;
845 print_args.expand_all = TRUE;
846 proto_tree_print(FALSE, &print_args, (GNode *)protocol_tree,
847 buf, &fdata, stdout);
849 /* "print_hex_data()" will put out a leading blank line, as well
850 as a trailing one; print one here, to separate the packets,
851 only if "print_hex_data()" won't be called. */
855 /* Just fill in the columns. */
856 fill_in_columns(&fdata);
857 if (cf->iface == NULL) {
858 printf("%3s %10s %12s -> %-12s %s %s\n",
859 col_info(&fdata, COL_NUMBER),
860 col_info(&fdata, COL_CLS_TIME),
861 col_info(&fdata, COL_DEF_SRC),
862 col_info(&fdata, COL_DEF_DST),
863 col_info(&fdata, COL_PROTOCOL),
864 col_info(&fdata, COL_INFO));
866 printf("%12s -> %-12s %s %s\n",
867 col_info(&fdata, COL_DEF_SRC),
868 col_info(&fdata, COL_DEF_DST),
869 col_info(&fdata, COL_PROTOCOL),
870 col_info(&fdata, COL_INFO));
874 print_hex_data(stdout, print_args.format, buf,
875 fdata.cap_len, fdata.encoding);
880 if (protocol_tree != NULL)
881 proto_tree_free(protocol_tree);
885 file_open_error_message(int err, int for_writing)
888 static char errmsg_errno[1024+1];
892 case WTAP_ERR_NOT_REGULAR_FILE:
893 errmsg = "The file \"%s\" is invalid.";
896 case WTAP_ERR_FILE_UNKNOWN_FORMAT:
897 case WTAP_ERR_UNSUPPORTED:
898 /* Seen only when opening a capture file for reading. */
899 errmsg = "The file \"%s\" is not a capture file in a format Ethereal understands.";
902 case WTAP_ERR_UNSUPPORTED_FILE_TYPE:
903 /* Seen only when opening a capture file for writing. */
904 errmsg = "Ethereal does not support writing capture files in that format.";
907 case WTAP_ERR_UNSUPPORTED_ENCAP:
908 case WTAP_ERR_ENCAP_PER_PACKET_UNSUPPORTED:
909 /* Seen only when opening a capture file for writing. */
910 errmsg = "Ethereal cannot save this capture in that format.";
913 case WTAP_ERR_BAD_RECORD:
914 errmsg = "The file \"%s\" appears to be damaged or corrupt.";
917 case WTAP_ERR_CANT_OPEN:
919 errmsg = "The file \"%s\" could not be created for some unknown reason.";
921 errmsg = "The file \"%s\" could not be opened for some unknown reason.";
924 case WTAP_ERR_SHORT_READ:
925 errmsg = "The file \"%s\" appears to have been cut short"
926 " in the middle of a packet.";
929 case WTAP_ERR_SHORT_WRITE:
930 errmsg = "A full header couldn't be written to the file \"%s\".";
935 errmsg = "The path to the file \"%s\" does not exist.";
937 errmsg = "The file \"%s\" does not exist.";
942 errmsg = "You do not have permission to create or write to the file \"%s\".";
944 errmsg = "You do not have permission to read the file \"%s\".";
948 sprintf(errmsg_errno, "The file \"%%s\" could not be opened: %s.",
950 errmsg = errmsg_errno;
957 open_cap_file(char *fname, gboolean is_tempfile, capture_file *cf)
964 char err_msg[2048+1];
966 wth = wtap_open_offline(fname, &err);
970 /* Find the size of the file. */
973 if (fstat(fd, &cf_stat) < 0) {
979 /* The open succeeded. Fill in the information for this file. */
981 /* Initialize the table of conversations. */
984 /* Initialize protocol-specific variables */
985 init_all_protocols();
990 cf->f_len = cf_stat.st_size;
992 /* Set the file name because we need it to set the follow stream filter.
993 XXX - is that still true? We need it for other reasons, though,
995 cf->filename = g_strdup(fname);
997 /* Indicate whether it's a permanent or temporary file. */
998 cf->is_tempfile = is_tempfile;
1000 /* If it's a temporary capture buffer file, mark it as not saved. */
1001 cf->user_saved = !is_tempfile;
1003 cf->cd_t = wtap_file_type(cf->wth);
1008 cf->snap = wtap_snapshot_length(cf->wth);
1009 cf->update_progbar = FALSE;
1010 cf->progbar_quantum = 0;
1011 cf->progbar_nextstep = 0;
1012 firstsec = 0, firstusec = 0;
1013 prevsec = 0, prevusec = 0;
1018 snprintf(err_msg, sizeof err_msg, file_open_error_message(err, FALSE), fname);
1019 fprintf(stderr, "tethereal: %s\n", err_msg);
1023 /* Get the text in a given column */
1025 col_info(frame_data *fd, gint el) {
1029 for (i = 0; i < fd->cinfo->num_cols; i++) {
1030 if (fd->cinfo->fmt_matx[i][el])
1031 return fd->cinfo->col_data[i];