Re-enable capture tests now that a a dumpcap problem has been corrected.
[obnox/wireshark/wip.git] / capture_sync.c
index 2aa50625fd1779df4f8d6d4a66c002ac1dc46d09..b7bbb23a4c76a75f312272234a08511799c42e24 100644 (file)
@@ -1,10 +1,10 @@
 /* capture_sync.c
- * Synchronisation between Ethereal capture parent and child instances
+ * Synchronisation between Wireshark capture parent and child instances
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
  * Copyright 1998 Gerald Combs
  *
  * This program is free software; you can redistribute it and/or
 #include <unistd.h>
 #endif
 
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
 #include <signal.h>
 
 #ifdef _WIN32
-#include <fcntl.h>
-#include "epan/strutil.h"
+#include "epan/unicode-utils.h"
 #endif
 
 #ifdef HAVE_SYS_WAIT_H
@@ -208,10 +211,34 @@ protect_arg (const gchar *argv)
 }
 #endif
 
+/* Initialize an argument list and add dumpcap to it. */
+static const char **
+init_pipe_args(int *argc) {
+    const char **argv;
+    const char *progfile_dir;
+    char *exename;
+
+    progfile_dir = get_progfile_dir();
+    if (progfile_dir == NULL) {
+      return NULL;
+    }
+
+    /* Allocate the string pointer array with enough space for the
+       terminating NULL pointer. */
+    *argc = 0;
+    argv = g_malloc(sizeof (char *));
+    *argv = NULL;
 
+    /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
+    exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap", progfile_dir);
 
-#define ARGV_NUMBER_LEN 24
+    /* Make that the first argument in the argument list (argv[0]). */
+    argv = sync_pipe_add_arg(argv, argc, exename);
 
+    return argv;
+}
+
+#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) {
@@ -241,7 +268,6 @@ sync_pipe_start(capture_options *capture_opts) {
     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
 #endif
     int sync_pipe_read_fd;
-    char *exename;
     int argc;
     const char **argv;
 
@@ -251,18 +277,12 @@ sync_pipe_start(capture_options *capture_opts) {
 
     capture_opts->fork_child = -1;
 
-    /* Allocate the string pointer array with enough space for the
-       terminating NULL pointer. */
-    argc = 0;
-    argv = g_malloc(sizeof (char *));
-    *argv = NULL;
-
-    /* take ethereal's absolute program path and replace "ethereal" with "dumpcap" */
-    exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap",
-                              get_progfile_dir());
-
-    /* Make that the first argument in the argument list (argv[0]). */
-    argv = sync_pipe_add_arg(argv, &argc, exename);
+    argv = init_pipe_args(&argc);
+    if (!argv) {
+        /* We don't know where to find dumpcap. */
+        simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "We don't know where to find dumpcap.");
+        return FALSE;
+    }
 
     argv = sync_pipe_add_arg(argv, &argc, "-i");
     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
@@ -364,6 +384,7 @@ sync_pipe_start(capture_options *capture_opts) {
       /* Couldn't create the pipe between parent and child. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
                         strerror(errno));
+      g_free( (gpointer) argv[0]);
       g_free( (gpointer) argv);
       return FALSE;
     }
@@ -375,6 +396,7 @@ sync_pipe_start(capture_options *capture_opts) {
                         strerror(errno));
       CloseHandle(sync_pipe_read);
       CloseHandle(sync_pipe_write);
+      g_free( (gpointer) argv[0]);
       g_free( (gpointer) argv);
       return FALSE;
     }
@@ -410,6 +432,10 @@ sync_pipe_start(capture_options *capture_opts) {
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
                     "Couldn't run %s in child process: error %u",
                     args->str, GetLastError());
+      CloseHandle(sync_pipe_read);
+      CloseHandle(sync_pipe_write);
+      g_free( (gpointer) argv[0]);
+      g_free( (gpointer) argv);
       return FALSE;
     }
     capture_opts->fork_child = (int) pi.hProcess;
@@ -422,29 +448,29 @@ sync_pipe_start(capture_options *capture_opts) {
     /* associate the operating system filehandle to a C run-time file handle */
     capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
 
-    /* child own's the read side now, close our handle */
+    /* child owns the read side now, close our handle */
     CloseHandle(signal_pipe_read);
 #else /* _WIN32 */
     if (pipe(sync_pipe) < 0) {
       /* Couldn't create the pipe between parent and child. */
       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
                        strerror(errno));
+      g_free( (gpointer) argv[0]);
       g_free(argv);
       return FALSE;
     }
 
     if ((capture_opts->fork_child = fork()) == 0) {
       /*
-       * Child process - run Ethereal with the right arguments to make
-       * it just pop up the live capture dialog box and capture with
-       * the specified capture parameters, writing to the specified file.
+       * Child process - run dumpcap with the right arguments to make
+       * it just capture with the specified capture parameters
        */
       eth_close(1);
       dup(sync_pipe[PIPE_WRITE]);
       eth_close(sync_pipe[PIPE_READ]);
-      execv(exename, argv);
+      execv(argv[0], (gpointer)argv);
       g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
-               exename, strerror(errno));
+               argv[0], strerror(errno));
       sync_pipe_errmsg_to_parent(errmsg, "");
 
       /* Exit with "_exit()", so that we don't close the connection
@@ -457,7 +483,7 @@ sync_pipe_start(capture_options *capture_opts) {
     sync_pipe_read_fd = sync_pipe[PIPE_READ];
 #endif
 
-    g_free(exename);
+    g_free( (gpointer) argv[0]);  /* exename */
 
     /* Parent process - read messages from the child process over the
        sync pipe. */
@@ -499,7 +525,375 @@ sync_pipe_start(capture_options *capture_opts) {
     return TRUE;
 }
 
+/*
+ * Open dumpcap with the supplied arguments.  On success, msg points to
+ * a buffer containing the dumpcap output and returns 0.  read_fd and
+ * fork_child point to the pipe's file descriptor and child PID/handle,
+ * respectively.  On failure, msg points to the error message returned by
+ * dumpcap, and returns dumpcap's exit value.  In either case, msg must be
+ * freed with g_free().
+ */
+/* XXX - This duplicates a lot of code in sync_pipe_start() */
+#define PIPE_BUF_SIZE 5120
+static int
+sync_pipe_open_command(const char** argv, int *read_fd, int *fork_child, gchar **msg) {
+#ifdef _WIN32
+    HANDLE sync_pipe_read;                  /* pipe used to send messages from child to parent */
+    HANDLE sync_pipe_write;                 /* pipe used to send messages from parent to child */
+    GString *args = g_string_sized_new(200);
+    gchar *quoted_arg;
+    SECURITY_ATTRIBUTES sa;
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    int i;
+#else
+    int sync_pipe[2];                       /* pipe used to send messages from child to parent */
+    enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
+#endif
+
+    *fork_child = -1;
+    *read_fd = -1;
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_run_command");
+
+    if (!msg) {
+        /* We can't return anything */
+#ifdef _WIN32
+        g_string_free(args, TRUE);
+#endif
+        return -1;
+    }
+
+#ifdef _WIN32
+    /* init SECURITY_ATTRIBUTES */
+    sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+    sa.bInheritHandle = TRUE;
+    sa.lpSecurityDescriptor = NULL;
+
+    /* Create a pipe for the child process */
+    /* (inrease this value if you have trouble while fast capture file switches) */
+    if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
+        /* Couldn't create the pipe between parent and child. */
+        *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+        g_free( (gpointer) argv[0]);
+        g_free( (gpointer) argv);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* init STARTUPINFO */
+    memset(&si, 0, sizeof(si));
+    si.cb           = sizeof(si);
+#ifdef DEBUG_CHILD
+    si.dwFlags = STARTF_USESHOWWINDOW;
+    si.wShowWindow  = SW_SHOW;
+#else
+    si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
+    si.wShowWindow  = SW_HIDE;  /* this hides the console window */
+    si.hStdInput = NULL;
+    si.hStdOutput = sync_pipe_write;
+    si.hStdError = sync_pipe_write;
+    /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
+#endif
+
+    /* convert args array into a single string */
+    /* XXX - could change sync_pipe_add_arg() instead */
+    /* there is a drawback here: the length is internally limited to 1024 bytes */
+    for(i=0; argv[i] != 0; i++) {
+        if(i != 0) g_string_append_c(args, ' ');    /* don't prepend a space before the path!!! */
+        quoted_arg = protect_arg(argv[i]);
+        g_string_append(args, quoted_arg);
+        g_free(quoted_arg);
+    }
+
+    /* call dumpcap */
+    if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
+                      CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
+        *msg = g_strdup_printf("Couldn't run %s in child process: error %u",
+                        args->str, GetLastError());
+        CloseHandle(sync_pipe_read);
+        CloseHandle(sync_pipe_write);
+        g_free( (gpointer) argv[0]);
+        g_free( (gpointer) argv);
+        return CANT_RUN_DUMPCAP;
+    }
+    *fork_child = (int) pi.hProcess;
+    g_string_free(args, TRUE);
+
+    /* associate the operating system filehandle to a C run-time file handle */
+    /* (good file handle infos at: http://www.flounder.com/handles.htm) */
+    *read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
+
+#else /* _WIN32 */
+    if (pipe(sync_pipe) < 0) {
+        /* Couldn't create the pipe between parent and child. */
+        *msg = g_strdup_printf("Couldn't create sync pipe: %s", strerror(errno));
+        g_free( (gpointer) argv[0]);
+        g_free(argv);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    if ((*fork_child = fork()) == 0) {
+        /*
+         * Child process - run dumpcap with the right arguments to make
+         * it just capture with the specified capture parameters
+         */
+        eth_close(1);
+        dup(sync_pipe[PIPE_WRITE]);
+        eth_close(sync_pipe[PIPE_READ]);
+        execv(argv[0], (gpointer)argv);
+        *msg = g_strdup_printf("Couldn't run %s in child process: %s",
+                argv[0], strerror(errno));
+        return CANT_RUN_DUMPCAP;
+    }
+
+    *read_fd = sync_pipe[PIPE_READ];
+#endif
+
+    g_free( (gpointer) argv[0]);  /* exename */
+
+    /* Parent process - read messages from the child process over the
+       sync pipe. */
+    g_free( (gpointer) argv);  /* free up arg array */
 
+    /* Close the write side of the pipe, so that only the child has it
+       open, and thus it completely closes, and thus returns to us
+       an EOF indication, if the child closes it (either deliberately
+       or by exiting abnormally). */
+#ifdef _WIN32
+    CloseHandle(sync_pipe_write);
+#else
+    eth_close(sync_pipe[PIPE_WRITE]);
+#endif
+
+    if (*fork_child == -1) {
+        /* We couldn't even create the child process. */
+        *msg = g_strdup_printf("Couldn't create child process: %s", strerror(errno));
+        eth_close(*read_fd);
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* we might wait for a moment till child is ready, so update screen now */
+    main_window_update();
+    return 0;
+}
+
+static int
+#ifdef _WIN32
+sync_pipe_close_command(int *read_fd, int *fork_child, gchar **msg) {
+#else
+sync_pipe_close_command(int *read_fd, gchar **msg) {
+#endif
+    int fork_child_status;
+
+    eth_close(*read_fd);
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open: wait till child closed");
+
+#ifdef _WIN32
+    /* XXX - Should we signal the child somehow? */
+    sync_pipe_kill(*fork_child);
+    if (_cwait(&fork_child_status, *fork_child, _WAIT_CHILD) == -1) {
+        *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+            "(errno:%u)", errno);
+        return CANT_RUN_DUMPCAP;
+    }
+#else
+    if (wait(&fork_child_status) != -1) {
+        if (WIFEXITED(fork_child_status)) {
+            /* The child exited. */
+            fork_child_status = WEXITSTATUS(fork_child_status);
+        } else {
+            if (WIFSTOPPED(fork_child_status)) {
+                /* It stopped, rather than exiting.  "Should not happen." */
+                *msg = g_strdup_printf("Child capture process stopped: %s",
+                    sync_pipe_signame(WSTOPSIG(fork_child_status)));
+            } else if (WIFSIGNALED(fork_child_status)) {
+                /* It died with a signal. */
+                *msg = g_strdup_printf("Child capture process died: %s%s",
+                   sync_pipe_signame(WTERMSIG(fork_child_status)),
+                   WCOREDUMP(fork_child_status) ? " - core dumped" : "");
+            } else {
+                /* What?  It had to either have exited, or stopped, or died with
+                   a signal; what happened here? */
+                *msg = g_strdup_printf("Child capture process died: wait status %#o",
+                    fork_child_status);
+            }
+            return CANT_RUN_DUMPCAP;
+        }
+    } else {
+      *msg = g_strdup_printf("Child capture process stopped unexpectedly "
+        "(errno:%u)", errno);
+      return CANT_RUN_DUMPCAP;
+    }
+#endif
+    return 0;
+}
+
+/*
+ * Run dumpcap with the supplied arguments.  On success, msg points to
+ * a buffer containing the dumpcap output and returns 0.  On failure, msg
+ * points to the error message returned by dumpcap, and returns dumpcap's
+ * exit value.  In either case, msg must be freed with g_free().
+ */
+/* XXX - This duplicates a lot of code in sync_pipe_start() */
+#define PIPE_BUF_SIZE 5120
+static int
+sync_pipe_run_command(const char** argv, gchar **msg) {
+    int sync_pipe_read_fd, fork_child, ret;
+    gchar buf[PIPE_BUF_SIZE+1];
+    GString *msg_buf = NULL;
+    int count;
+
+    ret = sync_pipe_open_command(argv, &sync_pipe_read_fd, &fork_child, msg);
+
+    if (ret)
+       return ret;
+
+    /* We were able to set up to read dumpcap's output.  Do so and
+       return its exit value. */
+    msg_buf = g_string_new("");
+    while ((count = eth_read(sync_pipe_read_fd, buf, PIPE_BUF_SIZE)) > 0) {
+        buf[count] = '\0';
+        g_string_append(msg_buf, buf);
+    }
+
+#ifdef _WIN32
+    ret = sync_pipe_close_command(&sync_pipe_read_fd, &fork_child, msg);
+#else
+    ret = sync_pipe_close_command(&sync_pipe_read_fd, msg);
+#endif
+
+    if (ret) {
+       g_string_free(msg_buf, TRUE);
+       return ret;
+    }
+
+    *msg = msg_buf->str;
+    g_string_free(msg_buf, FALSE);
+    return 0;
+}
+
+/*
+ * Get an interface list using dumpcap.  On success, msg points to
+ * a buffer containing the dumpcap output and returns 0.  On failure, msg
+ * points to the error message returned by dumpcap, and returns dumpcap's
+ * exit value.  In either case, msg must be freed with g_free().
+ */
+int
+sync_interface_list_open(gchar **msg) {
+    int argc;
+    const char **argv;
+
+    if (!msg) {
+        /* We can't return anything */
+        return -1;
+    }
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_interface_list_open");
+
+    argv = init_pipe_args(&argc);
+
+    if (!argv) {
+        *msg = g_strdup_printf("We don't know where to find dumpcap.");
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* Ask for the interface list */
+    argv = sync_pipe_add_arg(argv, &argc, "-D");
+    argv = sync_pipe_add_arg(argv, &argc, "-M");
+
+    /* dumpcap should be running in capture child mode (hidden feature) */
+#ifndef DEBUG_CHILD
+    argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#endif
+
+    return sync_pipe_run_command(argv, msg);
+}
+
+/*
+ * Get an linktype list using dumpcap.  On success, msg points to
+ * a buffer containing the dumpcap output and returns 0.  On failure, msg
+ * points to the error message returned by dumpcap, and returns dumpcap's
+ * exit value.  In either case, msg must be freed with g_free().
+ */
+int
+sync_linktype_list_open(gchar *ifname, gchar **msg) {
+    int argc;
+    const char **argv;
+
+    if (!msg) {
+        /* We can't return anything */
+        return -1;
+    }
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
+
+    argv = init_pipe_args(&argc);
+
+    if (!argv) {
+        *msg = g_strdup_printf("We don't know where to find dumpcap.");
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* Ask for the linktype list */
+    argv = sync_pipe_add_arg(argv, &argc, "-i");
+    argv = sync_pipe_add_arg(argv, &argc, ifname);
+    argv = sync_pipe_add_arg(argv, &argc, "-L");
+    argv = sync_pipe_add_arg(argv, &argc, "-M");
+
+    /* dumpcap should be running in capture child mode (hidden feature) */
+#ifndef DEBUG_CHILD
+    argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#endif
+
+    return sync_pipe_run_command(argv, msg);
+}
+
+/*
+ * Start getting interface statistics using dumpcap.  On success, read_fd
+ * contains the file descriptor for the pipe's stdout, msg is unchanged,
+ * and zero is returned.  On failure, msg will point to an error message
+ * that must be g_free()d and a nonzero error value will be returned.
+ */
+int
+sync_interface_stats_open(int *read_fd, int *fork_child, gchar **msg) {
+    int argc;
+    const char **argv;
+
+    if (!msg) {
+        /* We can't return anything */
+        return -1;
+    }
+
+    g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_linktype_list_open");
+
+    argv = init_pipe_args(&argc);
+
+    if (!argv) {
+        *msg = g_strdup_printf("We don't know where to find dumpcap.");
+        return CANT_RUN_DUMPCAP;
+    }
+
+    /* Ask for the linktype list */
+    argv = sync_pipe_add_arg(argv, &argc, "-S");
+    argv = sync_pipe_add_arg(argv, &argc, "-M");
+
+    /* dumpcap should be running in capture child mode (hidden feature) */
+#ifndef DEBUG_CHILD
+    argv = sync_pipe_add_arg(argv, &argc, "-Z");
+#endif
+
+    return sync_pipe_open_command(argv, read_fd, fork_child, msg);
+}
+
+/* Close down the stats process */
+int
+sync_interface_stats_close(int *read_fd, int *fork_child, gchar **msg) {
+#ifdef _WIN32
+    return sync_pipe_close_command(read_fd, fork_child, msg);
+#else
+    return sync_pipe_close_command(read_fd, msg);
+#endif
+}
 
 /* read a number of bytes from a pipe */
 /* (blocks until enough bytes read or an error occurs) */
@@ -508,7 +902,6 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
     int newly;
     int offset = 0;
 
-
     while(required) {
         newly = read(pipe, &bytes[offset], required);
         if (newly == 0) {
@@ -531,9 +924,70 @@ pipe_read_bytes(int pipe, char *bytes, int required) {
     return offset;
 }
 
+static gboolean pipe_data_available(int pipe) {
+#ifdef _WIN32 /* PeekNamedPipe */
+    HANDLE hPipe = (HANDLE) _get_osfhandle(pipe);
+    DWORD bytes_avail;
+
+    if (hPipe == INVALID_HANDLE_VALUE)
+        return FALSE;
+
+    if (! PeekNamedPipe(hPipe, NULL, 0, NULL, &bytes_avail, NULL))
+        return FALSE;
+
+    if (bytes_avail > 0)
+        return TRUE;
+    return FALSE;
+#else /* select */
+    fd_set rfds;
+    struct timeval timeout;
+
+    FD_ZERO(&rfds);
+    FD_SET(pipe, &rfds);
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+
+    if (select(pipe+1, &rfds, NULL, NULL, &timeout) > 0)
+        return TRUE;
+
+    return FALSE;
+#endif
+}
+
+/* Read a line from a pipe, similar to fgets */
+int
+sync_pipe_gets_nonblock(int pipe, char *bytes, int max) {
+    int newly;
+    int offset = -1;
+
+    while(offset < max - 1) {
+        offset++;
+        if (! pipe_data_available(pipe))
+            break;
+        newly = read(pipe, &bytes[offset], 1);
+        if (newly == 0) {
+            /* EOF - not necessarily an error */
+            break;
+        } else if (newly < 0) {
+            /* error */
+            g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
+                  "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
+            return newly;
+        } else if (bytes[offset] == '\n') {
+            break;
+        }
+    }
+
+    if (offset >= 0)
+        bytes[offset] = '\0';
+
+    return offset;
+}
+
+
 /* convert header values (indicator and 4-byte length) */
 static void
-pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {    
+pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
 
     g_assert(header_len == 4);
 
@@ -627,10 +1081,10 @@ sync_pipe_input_cb(gint source, gpointer user_data)
        capturing any more packets.  Pick up its exit status, and
        complain if it did anything other than exit with status 0.
 
-       We don't have to worry about killing the child, if the sync pipe 
-       returned an error. Usually this error is caused as the child killed itself 
-       while going down. Even in the rare cases that this isn't the case, 
-       the child will get an error when writing to the broken pipe the next time, 
+       We don't have to worry about killing the child, if the sync pipe
+       returned an error. Usually this error is caused as the child killed itself
+       while going down. Even in the rare cases that this isn't the case,
+       the child will get an error when writing to the broken pipe the next time,
        cleaning itself up then. */
     sync_pipe_wait_for_child(capture_opts);
 
@@ -885,13 +1339,13 @@ sync_pipe_stop(capture_options *capture_opts)
 }
 
 
-/* Ethereal has to exit, force the capture child to close */
+/* Wireshark has to exit, force the capture child to close */
 void
-sync_pipe_kill(capture_options *capture_opts)
+sync_pipe_kill(int fork_child)
 {
-  if (capture_opts->fork_child != -1) {
+  if (fork_child != -1) {
 #ifndef _WIN32
-      kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
+      kill(fork_child, SIGTERM);       /* SIGTERM so it can clean up if necessary */
 #else
       /* Remark: This is not the preferred method of closing a process!
        * the clean way would be getting the process id of the child process,
@@ -911,7 +1365,7 @@ sync_pipe_kill(capture_options *capture_opts)
        * us, as we might not be running in a console.
        * And this also will require to have the process id.
        */
-      TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
+      TerminateProcess((HANDLE) (fork_child), 0);
 #endif
   }
 }