diff options
author | Bill Meier <wmeier@newsguy.com> | 2008-02-23 19:59:38 +0000 |
---|---|---|
committer | Bill Meier <wmeier@newsguy.com> | 2008-02-23 19:59:38 +0000 |
commit | 8d4f01eea70c59acb0ef18acbc4f5254d4149e9f (patch) | |
tree | e87d1ef9d38dc5f7c31485b5f2c073d9f04188cc /dumpcap.c | |
parent | e6837f14d463998df7b8cb71d4408e60b8a73fb0 (diff) | |
download | wireshark-8d4f01eea70c59acb0ef18acbc4f5254d4149e9f.tar.gz wireshark-8d4f01eea70c59acb0ef18acbc4f5254d4149e9f.tar.bz2 wireshark-8d4f01eea70c59acb0ef18acbc4f5254d4149e9f.zip |
Ensure tshark/wireshark always get good err msgs from dumpcap:
1. Clean up dumpcap 'as a child' err msg handling so that:
- all err msgs are properly formatted when being sent
back to the parent.
- any log Critical, Warning, etc messages
are sent back to parent and are properly formatted.
2. Change handling of -w <...> slightly in capture_opts.c
so that wireshark provides a good error message if
there is a 'write permissions' issue on the file.
(Previously the error popup said only
"Child exited with status 2").
This fixes bug #2288.
Add some conditionalized DEBUG_CHILD_DUMPCAP code for
dumpcap debug logging to a file.
svn path=/trunk/; revision=24446
Diffstat (limited to 'dumpcap.c')
-rw-r--r-- | dumpcap.c | 146 |
1 files changed, 108 insertions, 38 deletions
@@ -107,6 +107,13 @@ #include "wiretap/libpcap.h" /*#define DEBUG_DUMPCAP*/ +/*#define DEBUG_CHILD_DUMPCAP*/ + +#ifdef DEBUG_CHILD_DUMPCAP +FILE *debug_log; /* for logging debug messages to */ + /* a file if DEBUG_CHILD_DUMPCAP */ + /* is defined */ +#endif static gboolean capture_child = FALSE; /* FALSE: standalone call, TRUE: this is an Wireshark capture child */ #ifdef _WIN32 @@ -353,9 +360,12 @@ cmdarg_err(const char *fmt, ...) va_list ap; if(capture_child) { - /* Print a bare error */ + gchar *msg; + /* Generate a 'special format' message back to parent */ va_start(ap, fmt); - vfprintf(stderr, fmt, ap); + msg = g_strdup_vprintf(fmt, ap); + sync_pipe_errmsg_to_parent(2, msg, ""); + g_free(msg); va_end(ap); } else { va_start(ap, fmt); @@ -375,7 +385,12 @@ cmdarg_err_cont(const char *fmt, ...) va_list ap; if(capture_child) { - /* XXX - convert to g_log */ + gchar *msg; + va_start(ap, fmt); + msg = g_strdup_vprintf(fmt, ap); + sync_pipe_errmsg_to_parent(2, msg, ""); + g_free(msg); + va_end(ap); } else { va_start(ap, fmt); vfprintf(stderr, fmt, ap); @@ -483,14 +498,14 @@ relinquish_privs_except_capture(void) if (started_with_special_privs()) { print_caps("Pre drop, pre set"); if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) == -1) { - perror("prctl()"); + cmdarg_err("prctl() fail return: %s", strerror(errno)); } cap_set_flag(caps, CAP_PERMITTED, cl_len, cap_list, CAP_SET); cap_set_flag(caps, CAP_INHERITABLE, cl_len, cap_list, CAP_SET); if (cap_set_proc(caps)) { - perror("capset()"); + cmdarg_err("cap_set_proc() fail return: %s", strerror(errno)); } print_caps("Pre drop, post set"); } @@ -500,7 +515,7 @@ relinquish_privs_except_capture(void) print_caps("Post drop, pre set"); cap_set_flag(caps, CAP_EFFECTIVE, cl_len, cap_list, CAP_SET); if (cap_set_proc(caps)) { - perror("capset()"); + cmdarg_err("cap_set_proc() fail return: %s", strerror(errno)); } print_caps("Post drop, post set"); cap_free(caps); @@ -2198,6 +2213,7 @@ main(int argc, char *argv[]) gboolean machine_readable = FALSE; gboolean print_statistics = FALSE; int status, run_once_args = 0; + gint i; #ifdef HAVE_PCAP_REMOTE #define OPTSTRING_INIT "a:A:b:c:Df:hi:Lm:MprSs:uvw:y:Z:" @@ -2214,6 +2230,61 @@ main(int argc, char *argv[]) char optstring[sizeof(OPTSTRING_INIT) + sizeof(OPTSTRING_WIN32) - 1] = OPTSTRING_INIT OPTSTRING_WIN32; +#ifdef DEBUG_CHILD_DUMPCAP + if ((debug_log = fopen("dumpcap_debug_log.tmp","w")) == NULL) { + fprintf (stderr, "Unable to open debug log file !\n"); + exit (1); + } +#endif + + /* Determine if dumpcap is running as a child process by going thru */ + /* the command line args to see if a -Z option (which is the */ + /* hidden option which indicates that dumpcap has been invoked */ + /* from a parent process using a pipe). */ + /* "Child" status needs to be determined immediately upon startup so */ + /* that any messages generated by dumpcap (eg: during initialization)*/ + /* will be formatted properly if being sent back to a parent via */ + /* a pipe. */ + + for (i=1; i<argc; i++) { + if (g_ascii_strcasecmp("-Z", argv[i]) == 0) { + capture_child = TRUE; +#ifdef _WIN32 + /* set output pipe to binary mode, to avoid ugly text conversions */ + _setmode(2, O_BINARY); +#endif + } + } + + /* The default_log_handler will use stdout, which makes trouble in */ + /* capture child mode, as it uses stdout for it's sync_pipe. */ + /* So: the filtering is done in the console_log_handler and not here.*/ + /* We set the log handlers right up front to make sure that any log */ + /* messages when running as child will be sent back to the parent */ + /* with the correct format. */ + + log_flags = + G_LOG_LEVEL_ERROR| + G_LOG_LEVEL_CRITICAL| + G_LOG_LEVEL_WARNING| + G_LOG_LEVEL_MESSAGE| + G_LOG_LEVEL_INFO| + G_LOG_LEVEL_DEBUG| + G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION; + + g_log_set_handler(NULL, + log_flags, + console_log_handler, NULL /* user_data */); + g_log_set_handler(LOG_DOMAIN_MAIN, + log_flags, + console_log_handler, NULL /* user_data */); + g_log_set_handler(LOG_DOMAIN_CAPTURE, + log_flags, + console_log_handler, NULL /* user_data */); + g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD, + log_flags, + console_log_handler, NULL /* user_data */); + #ifdef _WIN32 /* Load wpcap if possible. Do this before collecting the run-time version information */ load_wpcap(); @@ -2245,31 +2316,6 @@ main(int argc, char *argv[]) relinquish_privs_except_capture(); #endif - /* the default_log_handler will use stdout, which makes trouble in */ - /* capture child mode, as it uses stdout for it's sync_pipe */ - /* so do the filtering in the console_log_handler and not here */ - log_flags = - G_LOG_LEVEL_ERROR| - G_LOG_LEVEL_CRITICAL| - G_LOG_LEVEL_WARNING| - G_LOG_LEVEL_MESSAGE| - G_LOG_LEVEL_INFO| - G_LOG_LEVEL_DEBUG| - G_LOG_FLAG_FATAL|G_LOG_FLAG_RECURSION; - - g_log_set_handler(NULL, - log_flags, - console_log_handler, NULL /* user_data */); - g_log_set_handler(LOG_DOMAIN_MAIN, - log_flags, - console_log_handler, NULL /* user_data */); - g_log_set_handler(LOG_DOMAIN_CAPTURE, - log_flags, - console_log_handler, NULL /* user_data */); - g_log_set_handler(LOG_DOMAIN_CAPTURE_CHILD, - log_flags, - console_log_handler, NULL /* user_data */); - /* Set the initial values in the capture_opts. This might be overwritten by the command line parameters. */ capture_opts_init(capture_opts, NULL); @@ -2475,13 +2521,13 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level, const char *message, gpointer user_data _U_) { time_t curr; - struct tm *today; + struct tm *today; const char *level; - + gchar *msg; /* ignore log message, if log_level isn't interesting */ if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) { -#ifndef DEBUG_DUMPCAP +#if !defined(DEBUG_DUMPCAP) && !defined(DEBUG_CHILD_DUMPCAP) return; #endif } @@ -2515,19 +2561,43 @@ console_log_handler(const char *log_domain, GLogLevelFlags log_level, g_assert_not_reached(); } - /* don't use printf (stdout), in child mode we're using stdout for the sync_pipe */ + /* Generate the output message */ if(log_level & G_LOG_LEVEL_MESSAGE) { /* normal user messages without additional infos */ - fprintf(stderr, "%s\n", message); - fflush(stderr); + msg = g_strdup_printf("%s\n", message); } else { /* info/debug messages with additional infos */ - fprintf(stderr, "%02u:%02u:%02u %8s %s %s\n", + msg = g_strdup_printf("%02u:%02u:%02u %8s %s %s\n", today->tm_hour, today->tm_min, today->tm_sec, log_domain != NULL ? log_domain : "", level, message); + } + + /* DEBUG & INFO msgs (if we're debugging today) */ +#if defined(DEBUG_DUMPCAP) || defined(DEBUG_CHILD_DUMPCAP) + if( !(log_level & G_LOG_LEVEL_MASK & ~(G_LOG_LEVEL_DEBUG|G_LOG_LEVEL_INFO))) { +#ifdef DEBUG_DUMPCAP + fprintf(stderr, "%s", msg); + fflush(stderr); +#endif +#ifdef DEBUG_CHILD_DUMPCAP + fprintf(debug_log, "%s", msg); + fflush(debug_log); +#endif + g_free(msg); + return; + } +#endif + + /* ERROR, CRITICAL, WARNING, MESSAGE messages goto stderr or */ + /* to parent especially formatted if dumpcap running as child. */ + if (capture_child) { + sync_pipe_errmsg_to_parent(2, msg, ""); + } else { + fprintf(stderr, "%s", msg); fflush(stderr); } + g_free(msg); } |