Add (what I think are) missing add_new_data_source() calls;
[obnox/wireshark/wip.git] / dumpcap.c
index 6479f09523a473ed1ae241e41dd2a84333d21088..f0ddbac65816ed27864828e77f98375b699dc71d 100644 (file)
--- a/dumpcap.c
+++ b/dumpcap.c
@@ -235,7 +235,7 @@ typedef struct _pcap_options {
 #endif
     gboolean       cap_pipe_modified;     /* TRUE if data in the pipe uses modified pcap headers */
     gboolean       cap_pipe_byte_swapped; /* TRUE if data in the pipe is byte swapped */
-#if defined(USE_THREADS) && defined(_WIN32)
+#if defined(_WIN32)
     char *         cap_pipe_buf;          /* Pointer to the data buffer we read into */
 #endif
     int            cap_pipe_bytes_to_read;/* Used by cap_pipe_dispatch */
@@ -247,7 +247,7 @@ typedef struct _pcap_options {
         STATE_READ_DATA
     } cap_pipe_state;
     enum { PIPOK, PIPEOF, PIPERR, PIPNEXIST } cap_pipe_err;
-#if defined(USE_THREADS) && defined(_WIN32)
+#if defined(_WIN32)
     GMutex *cap_pipe_read_mtx;
     GAsyncQueue *cap_pipe_pending_q, *cap_pipe_done_q;
 #endif
@@ -318,7 +318,7 @@ static gboolean need_timeout_workaround;
  * WaitForSingleObject. If it's less than 1000 WaitForSingleObject
  * will return immediately.
  */
-#if defined(USE_THREADS) && defined(_WIN32)
+#if defined(_WIN32)
 #define PIPE_READ_TIMEOUT   100000
 #else
 #define PIPE_READ_TIMEOUT   250000
@@ -386,11 +386,11 @@ print_usage(gboolean print_ver)
 #ifdef HAVE_BPF_IMAGE
     fprintf(output, "  -d                       print generated BPF code for capture filter\n");
 #endif
-    fprintf(output, "  -S                       print statistics for each interface once every second\n");
+    fprintf(output, "  -S                       print statistics for each interface once per second\n");
     fprintf(output, "  -M                       for -D, -L, and -S, produce machine-readable output\n");
     fprintf(output, "\n");
 #ifdef HAVE_PCAP_REMOTE
-    fprintf(output, "\nRPCAP options:\n");
+    fprintf(output, "RPCAP options:\n");
     fprintf(output, "  -r                       don't ignore own RPCAP traffic in capture\n");
     fprintf(output, "  -u                       use UDP for RPCAP data transfer\n");
     fprintf(output, "  -A <user>:<password>     use RPCAP password authentication\n");
@@ -413,11 +413,9 @@ print_usage(gboolean print_ver)
     fprintf(output, "                           filesize:NUM - switch to next file after NUM KB\n");
     fprintf(output, "                              files:NUM - ringbuffer: replace after NUM files\n");
     fprintf(output, "  -n                       use pcapng format instead of pcap\n");
-    /*fprintf(output, "\n");*/
+    fprintf(output, "\n");
     fprintf(output, "Miscellaneous:\n");
-#ifdef USE_THREADS
     fprintf(output, "  -t                       use a separate thread per interface\n");
-#endif
     fprintf(output, "  -q                       don't report packet capture counts\n");
     fprintf(output, "  -v                       print version information and exit\n");
     fprintf(output, "  -h                       display this help and exit\n");
@@ -1547,7 +1545,7 @@ cap_pipe_adjust_header(gboolean byte_swapped, struct pcap_hdr *hdr, struct pcapr
     }
 }
 
-#if defined(USE_THREADS) && defined(_WIN32)
+#if defined(_WIN32)
 /*
  * Thread function that reads from a pipe and pushes the data
  * to the main application thread.
@@ -1635,7 +1633,7 @@ static void *cap_pipe_read(void *arg)
 }
 #endif
 
-#if (!(defined(USE_THREADS) && defined(_WIN32))) || defined(MUST_DO_SELECT)
+#if !defined(_WIN32) || defined(MUST_DO_SELECT)
 /* Provide select() functionality for a single file descriptor
  * on UNIX/POSIX. Windows uses cap_pipe_read via a thread.
  *
@@ -1682,7 +1680,7 @@ cap_pipe_open_live(char *pipename,
     wchar_t *err_str;
 #endif
 #endif
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
     int          sel_ret;
     unsigned int bytes_read;
 #endif
@@ -1851,7 +1849,7 @@ cap_pipe_open_live(char *pipename,
 
     pcap_opts->from_cap_pipe = TRUE;
 
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
     /* read the pcap header */
     bytes_read = 0;
     while (bytes_read < sizeof magic) {
@@ -1926,7 +1924,7 @@ cap_pipe_open_live(char *pipename,
         goto error;
     }
 
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
     /* Read the rest of the header */
     bytes_read = 0;
     while (bytes_read < sizeof(struct pcap_hdr)) {
@@ -2006,7 +2004,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
     struct pcap_pkthdr phdr;
     enum { PD_REC_HDR_READ, PD_DATA_READ, PD_PIPE_EOF, PD_PIPE_ERR,
            PD_ERR } result;
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
     GTimeVal wait_time;
     gpointer q_status;
 #else
@@ -2023,7 +2021,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
     switch (pcap_opts->cap_pipe_state) {
 
     case STATE_EXPECT_REC_HDR:
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
         if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) {
 #endif
 
@@ -2032,7 +2030,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
                 sizeof(struct pcaprec_modified_hdr) : sizeof(struct pcaprec_hdr);
             pcap_opts->cap_pipe_bytes_read = 0;
 
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
             pcap_opts->cap_pipe_buf = (char *) &pcap_opts->cap_pipe_rechdr;
             g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf);
             g_mutex_unlock(pcap_opts->cap_pipe_read_mtx);
@@ -2041,7 +2039,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
         /* Fall through */
 
     case STATE_READ_REC_HDR:
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
         b = read(pcap_opts->cap_pipe_fd, ((char *)&pcap_opts->cap_pipe_rechdr)+pcap_opts->cap_pipe_bytes_read,
                  pcap_opts->cap_pipe_bytes_to_read - pcap_opts->cap_pipe_bytes_read);
         if (b <= 0) {
@@ -2073,7 +2071,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
         break;
 
     case STATE_EXPECT_DATA:
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
         if (g_mutex_trylock(pcap_opts->cap_pipe_read_mtx)) {
 #endif
 
@@ -2081,7 +2079,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
             pcap_opts->cap_pipe_bytes_to_read = pcap_opts->cap_pipe_rechdr.hdr.incl_len;
             pcap_opts->cap_pipe_bytes_read = 0;
 
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
             pcap_opts->cap_pipe_buf = (char *) data;
             g_async_queue_push(pcap_opts->cap_pipe_pending_q, pcap_opts->cap_pipe_buf);
             g_mutex_unlock(pcap_opts->cap_pipe_read_mtx);
@@ -2090,7 +2088,7 @@ cap_pipe_dispatch(loop_data *ld, pcap_options *pcap_opts, guchar *data, char *er
         /* Fall through */
 
     case STATE_READ_DATA:
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
         b = read(pcap_opts->cap_pipe_fd, data+pcap_opts->cap_pipe_bytes_read,
                  pcap_opts->cap_pipe_bytes_to_read - pcap_opts->cap_pipe_bytes_read);
         if (b <= 0) {
@@ -2292,15 +2290,20 @@ capture_loop_open_input(capture_options *capture_opts, loop_data *ld,
 #endif
         pcap_opts->cap_pipe_modified = FALSE;
         pcap_opts->cap_pipe_byte_swapped = FALSE;
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
         pcap_opts->cap_pipe_buf = NULL;
 #endif
         pcap_opts->cap_pipe_bytes_to_read = 0;
         pcap_opts->cap_pipe_bytes_read = 0;
         pcap_opts->cap_pipe_state = 0;
         pcap_opts->cap_pipe_err = PIPOK;
-#if defined(USE_THREADS) && defined(_WIN32)
+#ifdef _WIN32
+#if GLIB_CHECK_VERSION(2,31,0)
+        pcap_opts->cap_pipe_read_mtx = g_malloc(sizeof(GMutex));
+        g_mutex_init(pcap_opts->cap_pipe_read_mtx);
+#else
         pcap_opts->cap_pipe_read_mtx = g_mutex_new();
+#endif
         pcap_opts->cap_pipe_pending_q = g_async_queue_new();
         pcap_opts->cap_pipe_done_q = g_async_queue_new();
 #endif
@@ -2552,7 +2555,6 @@ capture_loop_init_output(capture_options *capture_opts, loop_data *ld, char *err
                                                                        &err);
             }
         } else {
-            interface_opts = g_array_index(capture_opts->ifaces, interface_options, 0);
             pcap_opts = g_array_index(ld->pcaps, pcap_options *, 0);
             if (pcap_opts->from_cap_pipe) {
                 pcap_opts->snaplen = pcap_opts->cap_pipe_hdr.snaplen;
@@ -2636,7 +2638,7 @@ capture_loop_dispatch(loop_data *ld,
     int       inpkts;
     gint      packet_count_before;
     guchar    pcap_data[WTAP_MAX_PACKET_SIZE];
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
     int       sel_ret;
 #endif
 
@@ -2646,7 +2648,7 @@ capture_loop_dispatch(loop_data *ld,
 #ifdef LOG_CAPTURE_VERBOSE
         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "capture_loop_dispatch: from capture pipe");
 #endif
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
         sel_ret = cap_pipe_select(pcap_opts->cap_pipe_fd);
         if (sel_ret <= 0) {
             if (sel_ret < 0 && errno != EINTR) {
@@ -2664,7 +2666,7 @@ capture_loop_dispatch(loop_data *ld,
             if (inpkts < 0) {
                 ld->go = FALSE;
             }
-#if !(defined(USE_THREADS) && defined(_WIN32))
+#ifndef _WIN32
         }
 #endif
     }
@@ -2983,7 +2985,6 @@ do_file_switch_or_stop(capture_options *capture_opts,
                                                                            &global_ld.err);
                 }
             } else {
-                interface_opts = g_array_index(capture_opts->ifaces, interface_options, 0);
                 pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, 0);
                 successful = libpcap_write_file_header(global_ld.pdh, pcap_opts->linktype, pcap_opts->snaplen,
                                                        &global_ld.bytes_written, &global_ld.err);
@@ -3043,7 +3044,7 @@ static gboolean
 capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct pcap_stat *stats)
 {
 #ifdef WIN32
-    time_t upd_time, cur_time;
+    DWORD upd_time, cur_time;   /* GetTickCount() returns a "DWORD" (which is 'unsigned long') */
 #else
     struct timeval upd_time, cur_time;
 #endif
@@ -3062,7 +3063,6 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
     interface_options interface_opts;
     guint i, error_index = 0;
 
-    interface_opts = capture_opts->default_options;
     *errmsg           = '\0';
     *secondary_errmsg = '\0';
 
@@ -3191,7 +3191,12 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
         pcap_queue_packets = 0;
         for (i = 0; i < global_ld.pcaps->len; i++) {
             pcap_opts = g_array_index(global_ld.pcaps, pcap_options *, i);
+#if GLIB_CHECK_VERSION(2,31,0)
+            /* XXX - Add an interface name here? */
+            pcap_opts->tid = g_thread_new("Capture read", pcap_read_handler, pcap_opts);
+#else
             pcap_opts->tid = g_thread_create(pcap_read_handler, pcap_opts, TRUE, NULL);
+#endif
         }
     }
     while (global_ld.go) {
@@ -3267,8 +3272,8 @@ capture_loop_start(capture_options *capture_opts, gboolean *stats_known, struct
 #define DUMPCAP_UPD_TIME 500
 
 #ifdef WIN32
-        cur_time = GetTickCount();
-        if ( (cur_time - upd_time) > DUMPCAP_UPD_TIME) {
+        cur_time = GetTickCount();  /* Note: wraps to 0 if sys runs for 49.7 days */
+        if ((cur_time - upd_time) > DUMPCAP_UPD_TIME) { /* wrap just causes an extra update */
 #else
         gettimeofday(&cur_time, NULL);
         if ((cur_time.tv_sec * 1000000 + cur_time.tv_usec) >
@@ -3703,6 +3708,7 @@ main(int argc, char *argv[])
 #if defined(__APPLE__) && defined(__LP64__)
     struct utsname       osinfo;
 #endif
+    GString             *str;
 
 #ifdef _WIN32
     arg_list_utf_16to8(argc, argv);
@@ -3750,12 +3756,7 @@ main(int argc, char *argv[])
 #define OPTSTRING_d ""
 #endif
 
-#ifdef USE_THREADS
-#define OPTSTRING_t "t"
-#else
-#define OPTSTRING_t ""
-#endif
-#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:ghi:" OPTSTRING_I "L" OPTSTRING_m "MnpPq" OPTSTRING_r "Ss:" OPTSTRING_t OPTSTRING_u "vw:y:Z:"
+#define OPTSTRING "a:" OPTSTRING_A "b:" OPTSTRING_B "c:" OPTSTRING_d "Df:ghi:" OPTSTRING_I "L" OPTSTRING_m "MnpPq" OPTSTRING_r "Ss:t" OPTSTRING_u "vw:y:Z:"
 
 #ifdef DEBUG_CHILD_DUMPCAP
     if ((debug_log = ws_fopen("dumpcap_debug_log.tmp","w")) == NULL) {
@@ -3855,11 +3856,11 @@ main(int argc, char *argv[])
     /* Initialize the pcaps list */
     global_ld.pcaps = g_array_new(FALSE, FALSE, sizeof(pcap_options *));
 
+#if !GLIB_CHECK_VERSION(2,31,0)
     /* Initialize the thread system */
-#ifdef USE_THREADS
-    if (!g_thread_supported())
-        g_thread_init(NULL);
+    g_thread_init(NULL);
 #endif
+
 #ifdef _WIN32
     /* Load wpcap if possible. Do this before collecting the run-time version information */
     load_wpcap();
@@ -4076,11 +4077,9 @@ main(int argc, char *argv[])
         case 'q':        /* Quiet */
             quiet = TRUE;
             break;
-#ifdef USE_THREADS
         case 't':
             use_threads = TRUE;
             break;
-#endif
             /*** all non capture option specific ***/
         case 'D':        /* Print a list of capture devices and exit */
             list_interfaces = TRUE;
@@ -4148,12 +4147,10 @@ main(int argc, char *argv[])
     } else {
         /* We're supposed to capture traffic; */
         /* Are we capturing on multiple interface? If so, use threads and pcapng. */
-#ifdef USE_THREADS
         if (global_capture_opts.ifaces->len > 1) {
             use_threads = TRUE;
             global_capture_opts.use_pcapng = TRUE;
         }
-#endif
         /* Was the ring buffer option specified and, if so, does it make sense? */
         if (global_capture_opts.multi_files_on) {
             /* Ring buffer works only under certain conditions:
@@ -4236,11 +4233,41 @@ main(int argc, char *argv[])
 
     /* Let the user know what interfaces were chosen. */
     /* get_interface_descriptive_name() is not available! */
-    for (j = 0; j < global_capture_opts.ifaces->len; j++) {
-        interface_options interface_opts;
+    if (capture_child) {
+        for (j = 0; j < global_capture_opts.ifaces->len; j++) {
+            interface_options interface_opts;
+
+            interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
+            g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s\n",
+                  interface_opts.name);
+        }
+    } else {
+        str = g_string_new("");
+#ifdef _WIN32
+        if (global_capture_opts.ifaces->len < 2) {
+#else
+        if (global_capture_opts.ifaces->len < 4) {
+#endif
+            for (j = 0; j < global_capture_opts.ifaces->len; j++) {
+                interface_options interface_opts;
 
-        interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
-        g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "Interface: %s", interface_opts.name);
+                interface_opts = g_array_index(global_capture_opts.ifaces, interface_options, j);
+                if (j > 0) {
+                    if (global_capture_opts.ifaces->len > 2) {
+                        g_string_append_printf(str, ",");
+                    }
+                    g_string_append_printf(str, " ");
+                    if (j == global_capture_opts.ifaces->len - 1) {
+                        g_string_append_printf(str, "and ");
+                    }
+                }
+                g_string_append_printf(str, "%s", interface_opts.name);
+            }
+        } else {
+            g_string_append_printf(str, "%u interfaces", global_capture_opts.ifaces->len);
+        }
+        fprintf(stderr, "Capturing on %s\n", str->str);
+        g_string_free(str, TRUE);
     }
 
     if (list_link_layer_types) {
@@ -4463,11 +4490,11 @@ report_cfilter_error(capture_options *capture_opts, guint i, const char *errmsg)
              * the error message below.
              */
             interface_opts = g_array_index(capture_opts->ifaces, interface_options, i);
-            fprintf(stderr,
-              "Invalid capture filter \"%s\" for interface %s!\n"
+            cmdarg_err(
+              "Invalid capture filter: \"%s\" for interface %s!\n"
               "\n"
               "That string isn't a valid capture filter (%s).\n"
-              "See the User's Guide for a description of the capture filter syntax.\n",
+              "See the User's Guide for a description of the capture filter syntax.",
               interface_opts.cfilter, interface_opts.name, errmsg);
         }
     }
@@ -4483,9 +4510,9 @@ report_capture_error(const char *error_msg, const char *secondary_error_msg)
             "Secondary Error: %s", secondary_error_msg);
         sync_pipe_errmsg_to_parent(2, error_msg, secondary_error_msg);
     } else {
-        fprintf(stderr, "%s\n", error_msg);
+        cmdarg_err("%s", error_msg);
         if (secondary_error_msg[0] != '\0')
-          fprintf(stderr, "%s\n", secondary_error_msg);
+          cmdarg_err_cont("%s", secondary_error_msg);
     }
 }
 
@@ -4570,6 +4597,6 @@ signal_pipe_check_running(void)
  * indent-tabs-mode: nil
  * End:
  *
- * vi: set shiftwidth=4 tabstop=8 expandtab
+ * vi: set shiftwidth=4 tabstop=8 expandtab:
  * :indentSize=4:tabSize=8:noTabs=true:
  */