From 15f905102907db3230fd7a5d46d7e336bc800235 Mon Sep 17 00:00:00 2001 From: Ulf Lamping Date: Sat, 7 Jan 2006 01:29:45 +0000 Subject: [PATCH] move output_to_pipe flag from tethereal's loop_data into capture_opts, so it can be used by dumpcap (capture_loop.c) as well svn path=/trunk/; revision=16972 --- capture_loop.c | 7 ++-- capture_loop.h | 3 +- capture_opts.c | 65 +++++++++++++++++++++++++++++++++++ capture_opts.h | 1 + tethereal.c | 93 ++++++++++++++------------------------------------ 5 files changed, 98 insertions(+), 71 deletions(-) diff --git a/capture_loop.c b/capture_loop.c index e2302a2d6a..58745e7c12 100644 --- a/capture_loop.c +++ b/capture_loop.c @@ -995,7 +995,7 @@ capture_loop_dispatch(capture_options *capture_opts, loop_data *ld, } -/* open the output file (temporary/specified name/ringbuffer) */ +/* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */ /* Returns TRUE if the file opened successfully, FALSE otherwise. */ gboolean capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, @@ -1020,7 +1020,7 @@ capture_loop_open_output(capture_options *capture_opts, int *save_file_fd, if (capture_opts->multi_files_on) { /* ringbuffer is enabled; that doesn't work with standard output */ g_snprintf(errmsg, errmsg_len, - "Ring buffer requested, but capture is being written to the standard error."); + "Ring buffer requested, but capture is being written to the standard output."); g_free(capfile_name); return FALSE; } else { @@ -1290,6 +1290,9 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct continue; } } /* cnd_autostop_size */ + if (capture_opts->output_to_pipe) { + wtap_dump_flush(ld.wtap_pdh); + } } /* inpkts */ /* Only update once a second (Win32: 500ms) so as not to overload slow displays */ diff --git a/capture_loop.h b/capture_loop.h index 46133093b6..defb31110b 100644 --- a/capture_loop.h +++ b/capture_loop.h @@ -90,8 +90,7 @@ typedef struct _loop_data { jmp_buf stopenv; /* T: starting point of loop (jump back this point on SIG...) */ char *save_file; /* T: Name of file to which we're writing */ - gboolean output_to_pipe; /* T: output to a pipe, flush outut file immediately */ - capture_packet_cb_fct packet_cb; /* callback for a single captured packet */ + capture_packet_cb_fct packet_cb; /* callback for a single captured packet */ /* pcap "input file" */ pcap_t *pcap_h; /* pcap handle */ diff --git a/capture_opts.c b/capture_opts.c index 8e27f4ef85..4b6595fad9 100644 --- a/capture_opts.c +++ b/capture_opts.c @@ -45,8 +45,11 @@ #include "capture-pcap-util.h" #include "capture_ui_utils.h" +#include +static gboolean capture_opts_output_to_pipe(const char *save_file); + void capture_opts_init(capture_options *capture_opts, void *cfile) @@ -89,6 +92,7 @@ capture_opts_init(capture_options *capture_opts, void *cfile) capture_opts->signal_pipe_fd = -1; #endif capture_opts->state = CAPTURE_STOPPED; + capture_opts->output_to_pipe = FALSE; } @@ -409,6 +413,7 @@ capture_opts_add_opt(capture_options *capture_opts, int opt, const char *optarg, break; case 'w': /* Write to capture file xxx */ capture_opts->save_file = g_strdup(optarg); + capture_opts->output_to_pipe = capture_opts_output_to_pipe(capture_opts->save_file); break; case 'y': /* Set the pcap data link type */ #ifdef HAVE_PCAP_DATALINK_NAME_TO_VAL @@ -575,4 +580,64 @@ gboolean capture_opts_trim_iface(capture_options *capture_opts, const char *capt } + +#ifndef S_IFIFO +#define S_IFIFO _S_IFIFO +#endif +#ifndef S_ISFIFO +#define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO) +#endif + +/* copied from filesystem.c */ +static int capture_opts_test_for_fifo(const char *path) +{ + struct stat statb; + + if (eth_stat(path, &statb) < 0) + return errno; + + if (S_ISFIFO(statb.st_mode)) + return ESPIPE; + else + return 0; +} + +static gboolean capture_opts_output_to_pipe(const char *save_file) +{ + int err; + + if (save_file != NULL) { + /* We're writing to a capture file. */ + if (strcmp(save_file, "-") == 0) { + /* Writing to stdout. */ + /* XXX - should we check whether it's a pipe? It's arguably + silly to do "-w - >output_file" rather than "-w output_file", + but by not checking we might be violating the Principle Of + Least Astonishment. */ + return TRUE; + } else { + /* not a capture file, test for a FIFO (aka named pipe) */ + err = capture_opts_test_for_fifo(save_file); + switch (err) { + + case ENOENT: /* it doesn't exist, so we'll be creating it, + and it won't be a FIFO */ + case 0: /* found it, but it's not a FIFO */ + break; + + case ESPIPE: /* it is a FIFO */ + return TRUE; + break; + + default: /* couldn't stat it */ + cmdarg_err("Error testing whether capture file is a pipe: %s", + strerror(errno)); + exit(2); + } + } + } + + return FALSE; +} + #endif /* HAVE_LIBPCAP */ diff --git a/capture_opts.h b/capture_opts.h index 44fbfa28f8..7bf7c177ea 100644 --- a/capture_opts.h +++ b/capture_opts.h @@ -94,6 +94,7 @@ typedef struct capture_options_tag { int signal_pipe_fd; /**< the pipe to signal the child */ #endif capture_state state; /**< current state of the capture engine */ + gboolean output_to_pipe; /**< save_file is a pipe (named or stdout) */ } capture_options; diff --git a/tethereal.c b/tethereal.c index ed447a40e6..2412d1a988 100644 --- a/tethereal.c +++ b/tethereal.c @@ -152,7 +152,7 @@ static gboolean infoprint; /* if TRUE, print capture info after clearing infodel #endif /* HAVE_LIBPCAP */ -static int capture(char *, int); +static int capture(int); static void capture_pcap_cb(u_char *, const struct pcap_pkthdr *, const u_char *); static void report_counts(void); @@ -634,7 +634,6 @@ main(int argc, char *argv[]) gboolean capture_option_specified = FALSE; #endif gboolean quiet = FALSE; - gchar *save_file = NULL; int out_file_type = WTAP_FILE_PCAP; gchar *cf_name = NULL, *rfilter = NULL; #ifdef HAVE_PCAP_OPEN_DEAD @@ -835,6 +834,7 @@ main(int argc, char *argv[]) case 'i': /* Use interface xxx */ case 'p': /* Don't capture in promiscuous mode */ case 's': /* Set the snapshot (capture) length */ + case 'w': /* Write to capture file xxx */ case 'y': /* Set the pcap data link type */ #ifdef _WIN32 case 'B': /* Buffer size */ @@ -984,9 +984,6 @@ main(int argc, char *argv[]) runtime_info_str->str); exit(0); break; - case 'w': /* Write to capture file xxx */ - save_file = g_strdup(optarg); - break; case 'V': /* Verbose */ verbose = TRUE; break; @@ -1041,56 +1038,20 @@ main(int argc, char *argv[]) /* If we're not writing to a file and "-q" wasn't specified we should print packet information */ - if (save_file == NULL && !quiet) + if (capture_opts.save_file == NULL && !quiet) print_packet_info = TRUE; - /* See if we're writing a capture file and the file is a pipe */ -#ifdef HAVE_LIBPCAP - ld.output_to_pipe = FALSE; -#endif - if (save_file != NULL) { - /* We're writing to a capture file. */ - if (strcmp(save_file, "-") == 0) { - /* Write to the standard output. - If we'll also be writing dissected packets to the standard + if (capture_opts.save_file != NULL && + strcmp(capture_opts.save_file, "-") == 0 + && print_packet_info) { + /* If we're writing to the standard output. + and we'll also be writing dissected packets to the standard output, reject the request. At best, we could redirect that to the standard error; we *can't* write both to the standard output and have either of them be useful. */ - if (print_packet_info) { - cmdarg_err("You can't write both raw packet data and dissected packets" - " to the standard output."); - exit(1); - } -#ifdef HAVE_LIBPCAP - /* XXX - should we check whether it's a pipe? It's arguably - silly to do "-w - >output_file" rather than "-w output_file", - but by not checking we might be violating the Principle Of - Least Astonishment. */ - ld.output_to_pipe = TRUE; -#endif - } -#ifdef HAVE_LIBPCAP - else { - /* not a capture file, test for a FIFO (aka named pipe) */ - err = test_for_fifo(save_file); - switch (err) { - - case ENOENT: /* it doesn't exist, so we'll be creating it, - and it won't be a FIFO */ - case 0: /* found it, but it's not a FIFO */ - break; - - case ESPIPE: /* it is a FIFO */ - ld.output_to_pipe = TRUE; - break; - - default: /* couldn't stat it */ - cmdarg_err("Error testing whether capture file is a pipe: %s", - strerror(errno)); - exit(2); - } - } -#endif + cmdarg_err("You can't write both raw packet data and dissected packets" + " to the standard output."); + exit(1); } #ifndef HAVE_LIBPCAP @@ -1139,7 +1100,7 @@ main(int argc, char *argv[]) } else { /* If they didn't specify a "-w" flag, but specified a maximum capture file size, tell them that this doesn't work, and exit. */ - if (capture_opts.has_autostop_filesize && save_file == NULL) { + if (capture_opts.has_autostop_filesize && capture_opts.save_file == NULL) { cmdarg_err("Maximum capture file size specified, but " "capture isn't being saved to a file."); exit(1); @@ -1155,17 +1116,17 @@ main(int argc, char *argv[]) (XXX - shouldn't that be "if there is no stop criterion", as you might want to switch files based on a packet count or a time). */ - if (save_file == NULL) { + if (capture_opts.save_file == NULL) { cmdarg_err("Multiple capture files requested, but " "the capture isn't being saved to a file."); exit(1); } - if (strcmp(save_file, "-") == 0) { + if (strcmp(capture_opts.save_file, "-") == 0) { cmdarg_err("Multiple capture files requested, but " "the capture is being written to the standard output."); exit(1); } - if (ld.output_to_pipe) { + if (capture_opts.output_to_pipe) { cmdarg_err("Multiple capture files requested, but " "the capture file is a pipe."); exit(1); @@ -1340,7 +1301,7 @@ main(int argc, char *argv[]) } /* Process the packets in the file */ - err = load_cap_file(&cfile, save_file, out_file_type); + err = load_cap_file(&cfile, capture_opts.save_file, out_file_type); if (err != 0) { epan_cleanup(); exit(2); @@ -1387,7 +1348,7 @@ main(int argc, char *argv[]) /* For now, assume libpcap gives microsecond precision. */ timestamp_set_precision(TS_PREC_AUTO_USEC); - capture(save_file, out_file_type); + capture(out_file_type); if (capture_opts.multi_files_on) { ringbuf_free(); @@ -1412,7 +1373,7 @@ main(int argc, char *argv[]) static condition *volatile cnd_file_duration = NULL; /* this must be visible in process_packet */ static int -capture(char *save_file, int out_file_type) +capture(int out_file_type) { int err = 0; int volatile volatile_err = 0; @@ -1461,9 +1422,7 @@ capture(char *save_file, int out_file_type) setgid(getgid()); #endif - capture_opts.save_file = save_file; - - /* open the output file (temporary/specified name/ringbuffer) */ + /* open the output file (temporary/specified name/ringbuffer/named pipe/stdout) */ if (!capture_loop_open_output(&capture_opts, &save_file_fd, errmsg, sizeof(errmsg))) { goto error; } @@ -1616,7 +1575,7 @@ capture(char *save_file, int out_file_type) its maximum size. */ if (capture_opts.multi_files_on) { /* Switch to the next ringbuffer file */ - if (ringbuf_switch_file(&ld.wtap_pdh, &save_file, &save_file_fd, &loop_err)) { + if (ringbuf_switch_file(&ld.wtap_pdh, &capture_opts.save_file, &save_file_fd, &loop_err)) { /* File switch succeeded: reset the condition */ cnd_reset(cnd_autostop_size); if (cnd_file_duration) { @@ -1632,7 +1591,7 @@ capture(char *save_file, int out_file_type) ld.go = FALSE; } } - if (ld.output_to_pipe) { + if (capture_opts.output_to_pipe) { if (ld.packet_count > packet_count_prev) { wtap_dump_flush(ld.wtap_pdh); packet_count_prev = ld.packet_count; @@ -1674,18 +1633,18 @@ capture(char *save_file, int out_file_type) if (volatile_err == 0) write_ok = TRUE; else { - show_capture_file_io_error(save_file, volatile_err, FALSE); + show_capture_file_io_error(capture_opts.save_file, volatile_err, FALSE); write_ok = FALSE; } - if (save_file != NULL) { + if (capture_opts.save_file != NULL) { /* We're saving to a file or files; close all files. */ close_ok = capture_loop_close_output(&capture_opts, &ld, &err); /* If we've displayed a message about a write error, there's no point in displaying another message about an error on close. */ if (!close_ok && write_ok) - show_capture_file_io_error(save_file, err, TRUE); + show_capture_file_io_error(capture_opts.save_file, err, TRUE); } #ifndef _WIN32 @@ -1717,8 +1676,8 @@ error: if (capture_opts.multi_files_on) { ringbuf_error_cleanup(); } - g_free(save_file); - save_file = NULL; + g_free(capture_opts.save_file); + capture_opts.save_file = NULL; cmdarg_err("%s", errmsg); #ifndef _WIN32 if (ld.from_cap_pipe) {