print.c and ps.c are in libwirshark now.
[metze/wireshark/wip.git] / capture_sync.c
index a1d0aa29bd82181e308b498a542e7adbac3fa08b..f8a6f83f28b578d31cf4c0a1ddb6bcae282c5e78 100644 (file)
@@ -115,21 +115,38 @@ static const char *sync_pipe_signame(int);
 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
 static int sync_pipe_wait_for_child(int fork_child, gchar **msgp);
 static void pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len);
-static int pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
+static ssize_t pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
                            char **err_msg);
 
+static void (*fetch_dumpcap_pid)(int) = NULL;
 
 
+void
+capture_session_init(capture_session *cap_session, void *cf)
+{
+    cap_session->cf                              = cf;
+    cap_session->fork_child                      = -1;               /* invalid process handle */
+#ifdef _WIN32
+    cap_session->signal_pipe_write_fd            = -1;
+#endif
+    cap_session->state                           = CAPTURE_STOPPED;
+#ifndef _WIN32
+    cap_session->owner                           = getuid();
+    cap_session->group                           = getgid();
+#endif
+    cap_session->session_started                 = FALSE;
+}
+
 /* Append an arg (realloc) to an argc/argv array */
 /* (add a string pointer to a NULL-terminated array of string pointers) */
-static const char **
-sync_pipe_add_arg(const char **args, int *argc, const char *arg)
+static char **
+sync_pipe_add_arg(char **args, int *argc, const char *arg)
 {
     /* Grow the array; "*argc" currently contains the number of string
        pointers, *not* counting the NULL pointer at the end, so we have
        to add 2 in order to get the new size of the array, including the
        new pointer and the terminating NULL pointer. */
-    args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
+    args = (char **)g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
 
     /* Stuff the pointer into the penultimate element of the array, which
        is the one at the index specified by "*argc". */
@@ -288,9 +305,9 @@ win32strexception(DWORD exception)
 #endif
 
 /* Initialize an argument list and add dumpcap to it. */
-static const char **
+static char **
 init_pipe_args(int *argc) {
-    const char **argv;
+    char **argv;
     const char *progfile_dir;
     char *exename;
 
@@ -302,7 +319,7 @@ init_pipe_args(int *argc) {
     /* Allocate the string pointer array with enough space for the
        terminating NULL pointer. */
     *argc = 0;
-    argv = g_malloc(sizeof (char *));
+    argv = (char **)g_malloc(sizeof (char *));
     *argv = NULL;
 
     /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
@@ -320,9 +337,9 @@ init_pipe_args(int *argc) {
 #define ARGV_NUMBER_LEN 24
 /* a new capture run: start a new dumpcap task and hand over parameters through command line */
 gboolean
-sync_pipe_start(capture_options *capture_opts) {
+sync_pipe_start(capture_options *capture_opts, capture_session *cap_session, void (*update_cb)(void))
+{
     char ssnap[ARGV_NUMBER_LEN];
-    char sdlt[ARGV_NUMBER_LEN];
     char scount[ARGV_NUMBER_LEN];
     char sfilesize[ARGV_NUMBER_LEN];
     char sfile_duration[ARGV_NUMBER_LEN];
@@ -359,7 +376,7 @@ sync_pipe_start(capture_options *capture_opts) {
 #endif
     int sync_pipe_read_fd;
     int argc;
-    const char **argv;
+    char **argv;
     int i;
     guint j;
     interface_options interface_opts;
@@ -369,7 +386,7 @@ sync_pipe_start(capture_options *capture_opts) {
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
     capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
 
-    capture_opts->fork_child = -1;
+    cap_session->fork_child = -1;
 
     argv = init_pipe_args(&argc);
     if (!argv) {
@@ -430,6 +447,10 @@ sync_pipe_start(capture_options *capture_opts) {
         argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
     }
 
+    if (capture_opts->group_read_access) {
+        argv = sync_pipe_add_arg(argv, &argc, "-g");
+    }
+
     for (j = 0; j < capture_opts->ifaces->len; j++) {
         interface_opts = g_array_index(capture_opts->ifaces, interface_options, j);
 
@@ -448,8 +469,7 @@ sync_pipe_start(capture_options *capture_opts) {
 
         if (interface_opts.linktype != -1) {
             argv = sync_pipe_add_arg(argv, &argc, "-y");
-            g_snprintf(sdlt, ARGV_NUMBER_LEN, "%s", linktype_val_to_name(interface_opts.linktype));
-            argv = sync_pipe_add_arg(argv, &argc, sdlt);
+            argv = sync_pipe_add_arg(argv, &argc, linktype_val_to_name(interface_opts.linktype));
         }
 
         if (!interface_opts.promisc_mode) {
@@ -457,7 +477,7 @@ sync_pipe_start(capture_options *capture_opts) {
         }
 
 #if defined(_WIN32) || defined(HAVE_PCAP_CREATE)
-        if (interface_opts.buffer_size != 1) {
+        if (interface_opts.buffer_size != DEFAULT_CAPTURE_BUFFER_SIZE) {
             argv = sync_pipe_add_arg(argv, &argc, "-B");
             g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d", interface_opts.buffer_size);
             argv = sync_pipe_add_arg(argv, &argc, buffer_size);
@@ -592,7 +612,7 @@ sync_pipe_start(capture_options *capture_opts) {
         g_free( (gpointer) argv);
         return FALSE;
     }
-    capture_opts->fork_child = (int) pi.hProcess;
+    cap_session->fork_child = (int) pi.hProcess;
     g_string_free(args, TRUE);
 
     /* associate the operating system filehandle to a C run-time file handle */
@@ -600,7 +620,7 @@ sync_pipe_start(capture_options *capture_opts) {
     sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
 
     /* associate the operating system filehandle to a C run-time file handle */
-    capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe, _O_BINARY);
+    cap_session->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe, _O_BINARY);
 
 #else /* _WIN32 */
     if (pipe(sync_pipe) < 0) {
@@ -613,14 +633,14 @@ sync_pipe_start(capture_options *capture_opts) {
         return FALSE;
     }
 
-    if ((capture_opts->fork_child = fork()) == 0) {
+    if ((cap_session->fork_child = fork()) == 0) {
         /*
          * Child process - run dumpcap with the right arguments to make
          * it just capture with the specified capture parameters
          */
         dup2(sync_pipe[PIPE_WRITE], 2);
         ws_close(sync_pipe[PIPE_READ]);
-        execv(argv[0], (gpointer)argv);
+        execv(argv[0], argv);
         g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
                    argv[0], g_strerror(errno));
         sync_pipe_errmsg_to_parent(2, errmsg, "");
@@ -635,6 +655,9 @@ sync_pipe_start(capture_options *capture_opts) {
         _exit(1);
     }
 
+    if (fetch_dumpcap_pid && cap_session->fork_child > 0)
+        fetch_dumpcap_pid(cap_session->fork_child);
+
     sync_pipe_read_fd = sync_pipe[PIPE_READ];
 #endif
 
@@ -656,20 +679,21 @@ sync_pipe_start(capture_options *capture_opts) {
     ws_close(sync_pipe[PIPE_WRITE]);
 #endif
 
-    if (capture_opts->fork_child == -1) {
+    if (cap_session->fork_child == -1) {
         /* We couldn't even create the child process. */
         report_failure("Couldn't create child process: %s", g_strerror(errno));
         ws_close(sync_pipe_read_fd);
 #ifdef _WIN32
-        ws_close(capture_opts->signal_pipe_write_fd);
+        ws_close(cap_session->signal_pipe_write_fd);
 #endif
         return FALSE;
     }
 
-    capture_opts->fork_child_status = 0;
+    cap_session->fork_child_status = 0;
+    cap_session->capture_opts = capture_opts;
 
     /* we might wait for a moment till child is ready, so update screen now */
-    main_window_update();
+    if (update_cb) update_cb();
 
     /* We were able to set up to read the capture file;
        arrange that our callback be called whenever it's possible
@@ -677,8 +701,8 @@ sync_pipe_start(capture_options *capture_opts) {
        the child process wants to tell us something. */
 
     /* we have a running capture, now wait for the real capture filename */
-    pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
-                           &capture_opts->fork_child, sync_pipe_input_cb);
+    pipe_input_set_handler(sync_pipe_read_fd, (gpointer) cap_session,
+                           &cap_session->fork_child, sync_pipe_input_cb);
 
     return TRUE;
 }
@@ -699,8 +723,8 @@ sync_pipe_start(capture_options *capture_opts) {
 /* XXX - assumes PIPE_BUF_SIZE > SP_MAX_MSG_LEN */
 #define PIPE_BUF_SIZE 5120
 static int
-sync_pipe_open_command(const char** argv, int *data_read_fd,
-                       int *message_read_fd, int *fork_child, gchar **msg)
+sync_pipe_open_command(char** argv, int *data_read_fd,
+                       int *message_read_fd, int *fork_child, gchar **msg, void(*update_cb)(void))
 {
     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
 #ifdef _WIN32
@@ -846,7 +870,7 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
         dup2(sync_pipe[PIPE_WRITE], 2);
         ws_close(sync_pipe[PIPE_READ]);
         ws_close(sync_pipe[PIPE_WRITE]);
-        execv(argv[0], (gpointer)argv);
+        execv(argv[0], argv);
         g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
                    argv[0], g_strerror(errno));
         sync_pipe_errmsg_to_parent(2, errmsg, "");
@@ -861,6 +885,9 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
         _exit(1);
     }
 
+    if (fetch_dumpcap_pid && *fork_child > 0)
+        fetch_dumpcap_pid(*fork_child);
+
     *data_read_fd = data_pipe[PIPE_READ];
     *message_read_fd = sync_pipe[PIPE_READ];
 #endif
@@ -894,7 +921,7 @@ sync_pipe_open_command(const char** argv, int *data_read_fd,
     }
 
     /* we might wait for a moment till child is ready, so update screen now */
-    main_window_update();
+    if (update_cb) update_cb();
     return 0;
 }
 
@@ -938,14 +965,14 @@ sync_pipe_close_command(int *data_read_fd, int *message_read_fd,
 /* XXX - assumes PIPE_BUF_SIZE > SP_MAX_MSG_LEN */
 #define PIPE_BUF_SIZE 5120
 static int
-sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
-                      gchar **secondary_msg)
+sync_pipe_run_command_actual(char** argv, gchar **data, gchar **primary_msg,
+                      gchar **secondary_msg,  void(*update_cb)(void))
 {
     gchar *msg;
     int data_pipe_read_fd, sync_pipe_read_fd, fork_child, ret;
     char *wait_msg;
     gchar buffer[PIPE_BUF_SIZE+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_msg_len;
     char *primary_msg_text;
@@ -953,10 +980,10 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
     char *secondary_msg_text;
     char *combined_msg;
     GString *data_buf = NULL;
-    int count;
+    ssize_t count;
 
     ret = sync_pipe_open_command(argv, &data_pipe_read_fd, &sync_pipe_read_fd,
-                                 &fork_child, &msg);
+                                 &fork_child, &msg, update_cb);
     if (ret == -1) {
         *primary_msg = msg;
         *secondary_msg = NULL;
@@ -1017,10 +1044,10 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
          */
 
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_msg_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_msg_len);
         primary_msg_text = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg_text + primary_msg_len, 4, &indicator,
+        pipe_convert_header((guchar*)primary_msg_text + primary_msg_len, 4, &indicator,
                             &secondary_msg_len);
         secondary_msg_text = primary_msg_text + primary_msg_len + 4;
         /* the capture child will close the sync_pipe, nothing to do */
@@ -1110,13 +1137,50 @@ sync_pipe_run_command(const char** argv, gchar **data, gchar **primary_msg,
     return ret;
 }
 
+/* centralised logging and timing for sync_pipe_run_command_actual(), 
+* redirects to sync_pipe_run_command_actual()
+*/
+static int
+sync_pipe_run_command(char** argv, gchar **data, gchar **primary_msg,
+                      gchar **secondary_msg, void (*update_cb)(void))
+{
+    int ret, i;
+    GTimeVal start_time;
+    GTimeVal end_time;
+    float elapsed;
+    int logging_enabled;
+    
+    /* check if logging is actually enabled, otherwise don't expend the CPU generating logging */
+    logging_enabled=( (G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO) & G_LOG_LEVEL_MASK & prefs.console_log_level);
+    if(logging_enabled){
+        g_get_current_time(&start_time);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "sync_pipe_run_command() starts");
+        for(i=0; argv[i] != 0; i++) {
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "  argv[%d]: %s", i, argv[i]);
+        }
+    }
+    /* do the actual sync pipe run command */
+    ret=sync_pipe_run_command_actual(argv, data, primary_msg, secondary_msg, update_cb);
+
+    if(logging_enabled){
+        g_get_current_time(&end_time);
+        elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
+                           ((end_time.tv_usec - start_time.tv_usec) / 1e6));
+
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "sync_pipe_run_command() ends, taking %.3fs, result=%d", elapsed, ret);
+
+    }
+    return ret;
+}
+
+
 int
-sync_interface_set_80211_chan(gchar *iface, char *freq, gchar *type,
+sync_interface_set_80211_chan(const gchar *iface, const char *freq, const gchar *type,
                               gchar **data, gchar **primary_msg,
-                              gchar **secondary_msg)
+                              gchar **secondary_msg, void (*update_cb)(void))
 {
     int argc, ret;
-    const char **argv;
+    char **argv;
     gchar *opt;
 
     argv = init_pipe_args(&argc);
@@ -1152,7 +1216,7 @@ sync_interface_set_80211_chan(gchar *iface, char *freq, gchar *type,
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
 
-    ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
+    ret = sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
     g_free(opt);
     return ret;
 }
@@ -1171,17 +1235,17 @@ sync_interface_set_80211_chan(gchar *iface, char *freq, gchar *type,
  */
 int
 sync_interface_list_open(gchar **data, gchar **primary_msg,
-                         gchar **secondary_msg)
+                         gchar **secondary_msg, void (*update_cb)(void))
 {
     int argc;
-    const char **argv;
+    char **argv;
 
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
 
     argv = init_pipe_args(&argc);
 
     if (!argv) {
-        *primary_msg = g_strdup("We don't know where to find dumpcap.");
+        *primary_msg = g_strdup("We don't know where to find dumpcap..");
         *secondary_msg = NULL;
         *data = NULL;
         return -1;
@@ -1195,7 +1259,7 @@ sync_interface_list_open(gchar **data, gchar **primary_msg,
     argv = sync_pipe_add_arg(argv, &argc, "-Z");
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
-    return sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
+    return sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
 }
 
 /*
@@ -1213,12 +1277,12 @@ sync_interface_list_open(gchar **data, gchar **primary_msg,
 int
 sync_if_capabilities_open(const gchar *ifname, gboolean monitor_mode,
                           gchar **data, gchar **primary_msg,
-                          gchar **secondary_msg)
+                          gchar **secondary_msg, void (*update_cb)(void))
 {
     int argc;
-    const char **argv;
+    char **argv;
 
-    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_if_capabilities_open");
 
     argv = init_pipe_args(&argc);
 
@@ -1241,7 +1305,7 @@ sync_if_capabilities_open(const gchar *ifname, gboolean monitor_mode,
     argv = sync_pipe_add_arg(argv, &argc, "-Z");
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
-    return sync_pipe_run_command(argv, data, primary_msg, secondary_msg);
+    return sync_pipe_run_command(argv, data, primary_msg, secondary_msg, update_cb);
 }
 
 /*
@@ -1251,14 +1315,14 @@ sync_if_capabilities_open(const gchar *ifname, gboolean monitor_mode,
  * that must be g_free()d, and -1 will be returned.
  */
 int
-sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
+sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg, void (*update_cb)(void))
 {
     int argc;
-    const char **argv;
+    char **argv;
     int message_read_fd, ret;
     char *wait_msg;
     gchar buffer[PIPE_BUF_SIZE+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_msg_len;
     char *primary_msg_text;
@@ -1283,7 +1347,7 @@ sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
     argv = sync_pipe_add_arg(argv, &argc, SIGNAL_PIPE_CTRL_ID_NONE);
 #endif
     ret = sync_pipe_open_command(argv, data_read_fd, &message_read_fd,
-                                 fork_child, msg);
+                                 fork_child, msg, update_cb);
     if (ret == -1)
         return -1;
 
@@ -1339,10 +1403,10 @@ sync_interface_stats_open(int *data_read_fd, int *fork_child, gchar **msg)
          */
 
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_msg_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_msg_len);
         primary_msg_text = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg_text + primary_msg_len, 4, &indicator,
+        pipe_convert_header((guchar*)primary_msg_text + primary_msg_len, 4, &indicator,
                             &secondary_msg_len);
         /*secondary_msg_text = primary_msg_text + primary_msg_len + 4;*/
         /* the capture child will close the sync_pipe, nothing to do */
@@ -1412,11 +1476,11 @@ sync_interface_stats_close(int *read_fd, int *fork_child, gchar **msg)
 
 /* read a number of bytes from a pipe */
 /* (blocks until enough bytes read or an error occurs) */
-static int
+static ssize_t
 pipe_read_bytes(int pipe_fd, char *bytes, int required, char **msg)
 {
-    int newly;
-    int offset = 0;
+    ssize_t newly;
+    ssize_t offset = 0;
     int error;
 
     while(required) {
@@ -1439,7 +1503,7 @@ pipe_read_bytes(int pipe_fd, char *bytes, int required, char **msg)
             return newly;
         }
 
-        required -= newly;
+        required -= (int)newly;
         offset += newly;
     }
 
@@ -1480,7 +1544,7 @@ static gboolean pipe_data_available(int pipe_fd) {
 /* Read a line from a pipe, similar to fgets */
 int
 sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
-    int newly;
+    ssize_t newly;
     int offset = -1;
 
     while(offset < max - 1) {
@@ -1491,11 +1555,11 @@ sync_pipe_gets_nonblock(int pipe_fd, char *bytes, int max) {
         if (newly == 0) {
             /* EOF - not necessarily an error */
             break;
-        } else if (newly < 0) {
+        } else if (newly == -1) {
             /* error */
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
                   "read from pipe %d: error(%u): %s", pipe_fd, errno, g_strerror(errno));
-            return newly;
+            return -1;
         } else if (bytes[offset] == '\n') {
             break;
         }
@@ -1516,19 +1580,19 @@ pipe_convert_header(const guchar *header, int header_len, char *indicator, int *
 
     /* convert header values */
     *indicator = header[0];
-    *block_len = header[1]<<16 | header[2]<<8 | header[3];
+    *block_len = (header[1]&0xFF)<<16 | (header[2]&0xFF)<<8 | (header[3]&0xFF);
 }
 
 /* read a message from the sending pipe in the standard format
    (1-byte message indicator, 3-byte message length (excluding length
    and indicator field), and the rest is the message) */
-static int
+static ssize_t
 pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
                 char **err_msg)
 {
     int required;
-    int newly;
-    guchar header[4];
+    ssize_t newly;
+    gchar header[4];
 
     /* read header (indicator and 3-byte length) */
     newly = pipe_read_bytes(pipe_fd, header, 4, err_msg);
@@ -1544,19 +1608,19 @@ pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
             return 0;
         }
         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
-              "read %d failed to read header: %u", pipe_fd, newly);
+              "read %d failed to read header: %lu", pipe_fd, (long)newly);
         if (newly != -1) {
             /*
              * Short read, but not an immediate EOF.
              */
-            *err_msg = g_strdup_printf("Premature EOF reading from sync pipe: got only %d bytes",
-                                       newly);
+            *err_msg = g_strdup_printf("Premature EOF reading from sync pipe: got only %ld bytes",
+                                       (long)newly);
         }
         return -1;
     }
 
     /* convert header values */
-    pipe_convert_header(header, 4, indicator, &required);
+    pipe_convert_header((guchar*)header, 4, indicator, &required);
 
     /* only indicator with no value? */
     if(required == 0) {
@@ -1610,16 +1674,17 @@ pipe_read_block(int pipe_fd, char *indicator, int len, char *msg,
 static gboolean
 sync_pipe_input_cb(gint source, gpointer user_data)
 {
-    capture_options *capture_opts = (capture_options *)user_data;
+    capture_session *cap_session = (capture_session *)user_data;
     int  ret;
     char buffer[SP_MAX_MSG_LEN+1];
-    int  nread;
+    ssize_t nread;
     char indicator;
     int  primary_len;
     char *primary_msg;
     int  secondary_len;
     char *secondary_msg;
     char *wait_msg, *combined_msg;
+    int npackets;
 
     nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer,
                             &primary_msg);
@@ -1636,7 +1701,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
 
            If we got an EOF, nread is 0 and primary_msg isn't set.  This
            is an indication that the capture is finished. */
-        ret = sync_pipe_wait_for_child(capture_opts->fork_child, &wait_msg);
+        ret = sync_pipe_wait_for_child(cap_session->fork_child, &wait_msg);
         if(nread == 0) {
             /* We got an EOF from the sync pipe.  That means that the capture
                child exited, and not in the middle of a message; we treat
@@ -1657,13 +1722,13 @@ sync_pipe_input_cb(gint source, gpointer user_data)
         }
 
         /* No more child process. */
-        capture_opts->fork_child = -1;
-        capture_opts->fork_child_status = ret;
+        cap_session->fork_child = -1;
+        cap_session->fork_child_status = ret;
 
 #ifdef _WIN32
-        ws_close(capture_opts->signal_pipe_write_fd);
+        ws_close(cap_session->signal_pipe_write_fd);
 #endif
-        capture_input_closed(capture_opts, primary_msg);
+        capture_input_closed(cap_session, primary_msg);
         g_free(primary_msg);
         return FALSE;
     }
@@ -1671,7 +1736,7 @@ sync_pipe_input_cb(gint source, gpointer user_data)
     /* we got a valid message block from the child, process it */
     switch(indicator) {
     case SP_FILE:
-        if(!capture_input_new_file(capture_opts, buffer)) {
+        if(!capture_input_new_file(cap_session, buffer)) {
             g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
 
             /* We weren't able to open the new capture file; user has been
@@ -1691,41 +1756,41 @@ sync_pipe_input_cb(gint source, gpointer user_data)
 
                This can also happen if the user specified "-", meaning
                "standard output", as the capture file. */
-            sync_pipe_stop(capture_opts);
-            capture_input_closed(capture_opts, NULL);
+            sync_pipe_stop(cap_session);
+            capture_input_closed(cap_session, NULL);
             return FALSE;
         }
         break;
     case SP_PACKET_COUNT:
-        nread = atoi(buffer);
-        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
-        capture_input_new_packets(capture_opts, nread);
+        npackets = atoi(buffer);
+        g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", npackets);
+        capture_input_new_packets(cap_session, npackets);
         break;
     case SP_ERROR_MSG:
         /* convert primary message */
-        pipe_convert_header(buffer, 4, &indicator, &primary_len);
+        pipe_convert_header((guchar*)buffer, 4, &indicator, &primary_len);
         primary_msg = buffer+4;
         /* convert secondary message */
-        pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len);
+        pipe_convert_header((guchar*)primary_msg + primary_len, 4, &indicator, &secondary_len);
         secondary_msg = primary_msg + primary_len + 4;
         /* message output */
-        capture_input_error_message(capture_opts, primary_msg, secondary_msg);
+        capture_input_error_message(cap_session, primary_msg, secondary_msg);
         /* the capture child will close the sync_pipe, nothing to do for now */
         /* (an error message doesn't mean we have to stop capturing) */
         break;
     case SP_BAD_FILTER: {
         char *ch;
-        int index;
+        int indx;
 
         ch = strtok(buffer, ":");
-        index = (int)strtol(ch, NULL, 10);
+        indx = (int)strtol(ch, NULL, 10);
         ch = strtok(NULL, ":");
-        capture_input_cfilter_error_message(capture_opts, index, ch);
+        capture_input_cfilter_error_message(cap_session, indx, ch);
          /* the capture child will close the sync_pipe, nothing to do for now */
          break;
         }
     case SP_DROPS:
-        capture_input_drops(capture_opts, (guint32)strtoul(buffer, NULL, 10));
+        capture_input_drops(cap_session, (guint32)strtoul(buffer, NULL, 10));
         break;
     default:
         g_assert_not_reached();
@@ -1806,15 +1871,18 @@ sync_pipe_wait_for_child(int fork_child, gchar **msgp)
                                     fork_child_status);
             ret = -1;
         }
-    } else {
+    } else if (errno != ECHILD) {
         *msgp = g_strdup_printf("Error from waitpid(): %s", g_strerror(errno));
         ret = -1;
+    } else {
+        /* errno == ECHILD ; echld might have already reaped the child */
+        ret = fetch_dumpcap_pid ? 0 : -1;
     }
 #endif
 
     g_get_current_time(&end_time);
-    elapsed = (end_time.tv_sec - start_time.tv_sec) +
-    ((end_time.tv_usec - start_time.tv_usec) / (float) 1e6);
+    elapsed = (float) ((end_time.tv_sec - start_time.tv_sec) +
+                       ((end_time.tv_usec - start_time.tv_usec) / 1e6));
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed after %.3fs", elapsed);
     return ret;
 }
@@ -1920,21 +1988,20 @@ sync_pipe_signame(int sig)
 #ifdef _WIN32
 /* tell the child through the signal pipe that we want to quit the capture */
 static void
-signal_pipe_capquit_to_child(capture_options *capture_opts)
+signal_pipe_capquit_to_child(capture_session *cap_session)
 {
     const char quit_msg[] = "QUIT";
     int ret;
 
-
     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
 
     /* it doesn't matter *what* we send here, the first byte will stop the capture */
     /* simply sending a "QUIT" string */
-    /*pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
-    ret = write(capture_opts->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
+    /*pipe_write_block(cap_session->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
+    ret = write(cap_session->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
     if(ret == -1) {
         g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
-              "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, g_strerror(errno));
+              "signal_pipe_capquit_to_child: %d header: error %s", cap_session->signal_pipe_write_fd, g_strerror(errno));
     }
 }
 #endif
@@ -1942,7 +2009,7 @@ signal_pipe_capquit_to_child(capture_options *capture_opts)
 
 /* user wants to stop the capture run */
 void
-sync_pipe_stop(capture_options *capture_opts)
+sync_pipe_stop(capture_session *cap_session)
 {
 #ifdef _WIN32
     int count;
@@ -1950,10 +2017,10 @@ sync_pipe_stop(capture_options *capture_opts)
     gboolean terminate = TRUE;
 #endif
 
-    if (capture_opts->fork_child != -1) {
+    if (cap_session->fork_child != -1) {
 #ifndef _WIN32
         /* send the SIGINT signal to close the capture child gracefully. */
-        int sts = kill(capture_opts->fork_child, SIGINT);
+        int sts = kill(cap_session->fork_child, SIGINT);
         if (sts != 0) {
             g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
                   "Sending SIGINT to child failed: %s\n", g_strerror(errno));
@@ -1964,11 +2031,11 @@ sync_pipe_stop(capture_options *capture_opts)
         /* First, use the special signal pipe to try to close the capture child
          * gracefully.
          */
-        signal_pipe_capquit_to_child(capture_opts);
+        signal_pipe_capquit_to_child(cap_session);
 
         /* Next, wait for the process to exit on its own */
         for (count = 0; count < STOP_SLEEP_TIME / STOP_CHECK_TIME; count++) {
-            if (GetExitCodeProcess((HANDLE) capture_opts->fork_child, &childstatus) &&
+            if (GetExitCodeProcess((HANDLE) cap_session->fork_child, &childstatus) &&
                 childstatus != STILL_ACTIVE) {
                 terminate = FALSE;
                 break;
@@ -1980,7 +2047,7 @@ sync_pipe_stop(capture_options *capture_opts)
         if (terminate) {
             g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
                   "sync_pipe_stop: forcing child to exit");
-            sync_pipe_kill(capture_opts->fork_child);
+            sync_pipe_kill(cap_session->fork_child);
         }
 #endif
     }
@@ -2022,4 +2089,8 @@ sync_pipe_kill(int fork_child)
     }
 }
 
+void capture_sync_set_fetch_dumpcap_pid_cb(void(*cb)(int pid)) {
+    fetch_dumpcap_pid = cb;
+}
+
 #endif /* HAVE_LIBPCAP */