2 * Synchronisation between Wireshark capture parent and child instances
6 * Wireshark - Network traffic analyzer
7 * By Gerald Combs <gerald@wireshark.org>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
44 #include "epan/unicode-utils.h"
47 #ifdef HAVE_SYS_WAIT_H
48 # include <sys/wait.h>
51 #include "capture-pcap-util.h"
55 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
56 * macros) on UNIX systems that don't have them.
59 # define WIFEXITED(status) (((status) & 0177) == 0)
62 # define WIFSTOPPED(status) (((status) & 0177) == 0177)
65 # define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
68 # define WEXITSTATUS(status) ((status) >> 8)
71 # define WTERMSIG(status) ((status) & 0177)
74 # define WCOREDUMP(status) ((status) & 0200)
77 # define WSTOPSIG(status) ((status) >> 8)
81 #include <epan/packet.h>
82 #include <epan/prefs.h>
86 #include <epan/filesystem.h>
89 #include "capture_sync.h"
90 #include "simple_dialog.h"
92 #include "sync_pipe.h"
95 #include "capture-wpcap.h"
98 #include "file_util.h"
102 #include <process.h> /* For spawning child process */
108 static const char *sync_pipe_signame(int);
112 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
113 static void sync_pipe_wait_for_child(capture_options *capture_opts);
117 /* Append an arg (realloc) to an argc/argv array */
118 /* (add a string pointer to a NULL-terminated array of string pointers) */
120 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
122 /* Grow the array; "*argc" currently contains the number of string
123 pointers, *not* counting the NULL pointer at the end, so we have
124 to add 2 in order to get the new size of the array, including the
125 new pointer and the terminating NULL pointer. */
126 args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
128 /* Stuff the pointer into the penultimate element of the array, which
129 is the one at the index specified by "*argc". */
132 /* Now bump the count. */
135 /* We overwrite the NULL pointer; put it back right after the
145 /* Quote the argument element if necessary, so that it will get
146 * reconstructed correctly in the C runtime startup code. Note that
147 * the unquoting algorithm in the C runtime is really weird, and
148 * rather different than what Unix shells do. See stdargv.c in the C
149 * runtime sources (in the Platform SDK, in src/crt).
151 * Stolen from GLib's protect_argv(), an internal routine that quotes
152 * string in an argument list so that they arguments will be handled
153 * correctly in the command-line string passed to CreateProcess()
154 * if that string is constructed by gluing those strings together.
157 protect_arg (const gchar *argv)
160 const gchar *p = argv;
163 gboolean need_dblquotes = FALSE;
166 if (*p == ' ' || *p == '\t')
167 need_dblquotes = TRUE;
170 else if (*p == '\\') {
173 while (*pp && *pp == '\\')
182 q = new_arg = g_malloc (len + need_dblquotes*2 + 1);
191 else if (*p == '\\') {
194 while (*pp && *pp == '\\')
213 #define ARGV_NUMBER_LEN 24
215 /* a new capture run: start a new dumpcap task and hand over parameters through command line */
217 sync_pipe_start(capture_options *capture_opts) {
218 char ssnap[ARGV_NUMBER_LEN];
219 char scount[ARGV_NUMBER_LEN];
220 char sfilesize[ARGV_NUMBER_LEN];
221 char sfile_duration[ARGV_NUMBER_LEN];
222 char sring_num_files[ARGV_NUMBER_LEN];
223 char sautostop_files[ARGV_NUMBER_LEN];
224 char sautostop_filesize[ARGV_NUMBER_LEN];
225 char sautostop_duration[ARGV_NUMBER_LEN];
227 char buffer_size[ARGV_NUMBER_LEN];
228 HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
229 HANDLE sync_pipe_write; /* pipe used to send messages from child to parent */
230 HANDLE signal_pipe_read; /* pipe used to send messages from parent to child (currently only stop) */
231 HANDLE signal_pipe_write; /* pipe used to send messages from parent to child (currently only stop) */
232 GString *args = g_string_sized_new(200);
234 SECURITY_ATTRIBUTES sa;
236 PROCESS_INFORMATION pi;
240 int sync_pipe[2]; /* pipe used to send messages from child to parent */
241 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
243 int sync_pipe_read_fd;
244 const char *progfile_dir;
250 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
251 capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
253 capture_opts->fork_child = -1;
255 progfile_dir = get_progfile_dir();
256 if (progfile_dir == NULL) {
257 /* We don't know where to find dumpcap. */
258 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "We don't know where to find dumpcap.");
262 /* Allocate the string pointer array with enough space for the
263 terminating NULL pointer. */
265 argv = g_malloc(sizeof (char *));
268 /* take Wireshark's absolute program path and replace "Wireshark" with "dumpcap" */
269 exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap", progfile_dir);
271 /* Make that the first argument in the argument list (argv[0]). */
272 argv = sync_pipe_add_arg(argv, &argc, exename);
274 argv = sync_pipe_add_arg(argv, &argc, "-i");
275 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
277 if (capture_opts->has_snaplen) {
278 argv = sync_pipe_add_arg(argv, &argc, "-s");
279 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
280 argv = sync_pipe_add_arg(argv, &argc, ssnap);
283 if (capture_opts->linktype != -1) {
284 argv = sync_pipe_add_arg(argv, &argc, "-y");
285 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
286 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",linktype_val_to_name(capture_opts->linktype));
288 /* we can't get the type name, just treat it as a number */
289 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
291 argv = sync_pipe_add_arg(argv, &argc, ssnap);
294 if(capture_opts->multi_files_on) {
295 if (capture_opts->has_autostop_filesize) {
296 argv = sync_pipe_add_arg(argv, &argc, "-b");
297 g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
298 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
301 if (capture_opts->has_file_duration) {
302 argv = sync_pipe_add_arg(argv, &argc, "-b");
303 g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
304 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
307 if (capture_opts->has_ring_num_files) {
308 argv = sync_pipe_add_arg(argv, &argc, "-b");
309 g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
310 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
313 if (capture_opts->has_autostop_files) {
314 argv = sync_pipe_add_arg(argv, &argc, "-a");
315 g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
316 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
319 if (capture_opts->has_autostop_filesize) {
320 argv = sync_pipe_add_arg(argv, &argc, "-a");
321 g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
322 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
326 if (capture_opts->has_autostop_packets) {
327 argv = sync_pipe_add_arg(argv, &argc, "-c");
328 g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
329 argv = sync_pipe_add_arg(argv, &argc, scount);
332 if (capture_opts->has_autostop_duration) {
333 argv = sync_pipe_add_arg(argv, &argc, "-a");
334 g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
335 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
338 if (!capture_opts->promisc_mode)
339 argv = sync_pipe_add_arg(argv, &argc, "-p");
341 /* dumpcap should be running in capture child mode (hidden feature) */
343 argv = sync_pipe_add_arg(argv, &argc, "-Z");
347 argv = sync_pipe_add_arg(argv, &argc, "-B");
348 g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
349 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
352 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
353 argv = sync_pipe_add_arg(argv, &argc, "-f");
354 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
357 if(capture_opts->save_file) {
358 argv = sync_pipe_add_arg(argv, &argc, "-w");
359 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
363 /* init SECURITY_ATTRIBUTES */
364 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
365 sa.bInheritHandle = TRUE;
366 sa.lpSecurityDescriptor = NULL;
368 /* Create a pipe for the child process */
369 /* (inrease this value if you have trouble while fast capture file switches) */
370 if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
371 /* Couldn't create the pipe between parent and child. */
372 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
374 g_free( (gpointer) argv);
378 /* Create a pipe for the parent process */
379 if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
380 /* Couldn't create the signal pipe between parent and child. */
381 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
383 CloseHandle(sync_pipe_read);
384 CloseHandle(sync_pipe_write);
385 g_free( (gpointer) argv);
389 /* init STARTUPINFO */
390 memset(&si, 0, sizeof(si));
393 si.dwFlags = STARTF_USESHOWWINDOW;
394 si.wShowWindow = SW_SHOW;
396 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
397 si.wShowWindow = SW_HIDE; /* this hides the console window */
398 si.hStdInput = signal_pipe_read;
399 si.hStdOutput = sync_pipe_write;
400 si.hStdError = sync_pipe_write;
401 /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
404 /* convert args array into a single string */
405 /* XXX - could change sync_pipe_add_arg() instead */
406 /* there is a drawback here: the length is internally limited to 1024 bytes */
407 for(i=0; argv[i] != 0; i++) {
408 if(i != 0) g_string_append_c(args, ' '); /* don't prepend a space before the path!!! */
409 quoted_arg = protect_arg(argv[i]);
410 g_string_append(args, quoted_arg);
415 if(!CreateProcess(NULL, utf_8to16(args->str), NULL, NULL, TRUE,
416 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
417 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
418 "Couldn't run %s in child process: error %u",
419 args->str, GetLastError());
420 CloseHandle(sync_pipe_read);
421 CloseHandle(sync_pipe_write);
422 g_free( (gpointer) argv);
425 capture_opts->fork_child = (int) pi.hProcess;
426 g_string_free(args, TRUE);
428 /* associate the operating system filehandle to a C run-time file handle */
429 /* (good file handle infos at: http://www.flounder.com/handles.htm) */
430 sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
432 /* associate the operating system filehandle to a C run-time file handle */
433 capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
435 /* child owns the read side now, close our handle */
436 CloseHandle(signal_pipe_read);
438 if (pipe(sync_pipe) < 0) {
439 /* Couldn't create the pipe between parent and child. */
440 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
446 if ((capture_opts->fork_child = fork()) == 0) {
448 * Child process - run dumpcap with the right arguments to make
449 * it just capture with the specified capture parameters
452 dup(sync_pipe[PIPE_WRITE]);
453 eth_close(sync_pipe[PIPE_READ]);
454 execv(exename, argv);
455 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
456 exename, strerror(errno));
457 sync_pipe_errmsg_to_parent(errmsg, "");
459 /* Exit with "_exit()", so that we don't close the connection
460 to the X server (and cause stuff buffered up by our parent but
461 not yet sent to be sent, as that stuff should only be sent by
466 sync_pipe_read_fd = sync_pipe[PIPE_READ];
471 /* Parent process - read messages from the child process over the
473 g_free( (gpointer) argv); /* free up arg array */
475 /* Close the write side of the pipe, so that only the child has it
476 open, and thus it completely closes, and thus returns to us
477 an EOF indication, if the child closes it (either deliberately
478 or by exiting abnormally). */
480 CloseHandle(sync_pipe_write);
482 eth_close(sync_pipe[PIPE_WRITE]);
485 if (capture_opts->fork_child == -1) {
486 /* We couldn't even create the child process. */
487 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
488 "Couldn't create child process: %s", strerror(errno));
489 eth_close(sync_pipe_read_fd);
491 eth_close(capture_opts->signal_pipe_write_fd);
496 /* we might wait for a moment till child is ready, so update screen now */
497 main_window_update();
499 /* We were able to set up to read the capture file;
500 arrange that our callback be called whenever it's possible
501 to read from the sync pipe, so that it's called when
502 the child process wants to tell us something. */
504 /* we have a running capture, now wait for the real capture filename */
505 pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
506 &capture_opts->fork_child, sync_pipe_input_cb);
513 /* read a number of bytes from a pipe */
514 /* (blocks until enough bytes read or an error occurs) */
516 pipe_read_bytes(int pipe, char *bytes, int required) {
522 newly = read(pipe, &bytes[offset], required);
525 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
526 "read from pipe %d: EOF (capture closed?)", pipe);
531 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
532 "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
543 /* convert header values (indicator and 4-byte length) */
545 pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
547 g_assert(header_len == 4);
549 /* convert header values */
550 *indicator = header[0];
551 *block_len = header[1]<<16 | header[2]<<8 | header[3];
554 /* read a message from the sending pipe in the standard format
555 (1-byte message indicator, 3-byte message length (excluding length
556 and indicator field), and the rest is the message) */
558 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
564 /* read header (indicator and 3-byte length) */
565 newly = pipe_read_bytes(pipe, header, 4);
567 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
568 "read %d failed to read header: %u", pipe, newly);
572 /* convert header values */
573 pipe_convert_header(header, 4, indicator, &required);
575 /* only indicator with no value? */
577 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
578 "read %d indicator: %c empty value", pipe, *indicator);
582 /* does the data fit into the given buffer? */
584 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
585 "read %d length error, required %d > len %d, indicator: %u",
586 pipe, required, len, *indicator);
588 /* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
589 memcpy(msg, header, sizeof(header));
590 newly = read(pipe, &msg[sizeof(header)], len-sizeof(header));
591 g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
596 /* read the actual block data */
597 newly = pipe_read_bytes(pipe, msg, required);
598 if(newly != required) {
599 g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
603 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
604 "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
610 /* There's stuff to read from the sync pipe, meaning the child has sent
611 us a message, or the sync pipe has closed, meaning the child has
612 closed it (perhaps because it exited). */
614 sync_pipe_input_cb(gint source, gpointer user_data)
616 capture_options *capture_opts = (capture_options *)user_data;
617 char buffer[SP_MAX_MSG_LEN+1];
623 char * secondary_msg;
626 nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
629 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
630 "sync_pipe_input_cb: child has closed sync_pipe");
632 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
633 "sync_pipe_input_cb: error reading from sync pipe");
635 /* The child has closed the sync pipe, meaning it's not going to be
636 capturing any more packets. Pick up its exit status, and
637 complain if it did anything other than exit with status 0.
639 We don't have to worry about killing the child, if the sync pipe
640 returned an error. Usually this error is caused as the child killed itself
641 while going down. Even in the rare cases that this isn't the case,
642 the child will get an error when writing to the broken pipe the next time,
643 cleaning itself up then. */
644 sync_pipe_wait_for_child(capture_opts);
647 eth_close(capture_opts->signal_pipe_write_fd);
649 capture_input_closed(capture_opts);
653 /* we got a valid message block from the child, process it */
656 if(!capture_input_new_file(capture_opts, buffer)) {
657 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
659 /* We weren't able to open the new capture file; user has been
660 alerted. Close the sync pipe. */
663 /* the child has send us a filename which we couldn't open.
664 this probably means, the child is creating files faster than we can handle it.
665 this should only be the case for very fast file switches
666 we can't do much more than telling the child to stop
667 (this is the "emergency brake" if user e.g. wants to switch files every second) */
668 sync_pipe_stop(capture_opts);
671 case SP_PACKET_COUNT:
672 nread = atoi(buffer);
673 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
674 capture_input_new_packets(capture_opts, nread);
677 /* convert primary message */
678 pipe_convert_header(buffer, 4, &indicator, &primary_len);
679 primary_msg = buffer+4;
680 /* convert secondary message */
681 pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len);
682 secondary_msg = primary_msg + primary_len + 4;
684 capture_input_error_message(capture_opts, primary_msg, secondary_msg);
685 /* the capture child will close the sync_pipe, nothing to do for now */
686 /* (an error message doesn't mean we have to stop capturing) */
689 capture_input_cfilter_error_message(capture_opts, buffer);
690 /* the capture child will close the sync_pipe, nothing to do for now */
693 capture_input_drops(capture_opts, atoi(buffer));
696 g_assert_not_reached();
704 /* the child process is going down, wait until it's completely terminated */
706 sync_pipe_wait_for_child(capture_options *capture_opts)
711 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
712 g_assert(capture_opts->fork_child != -1);
715 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
716 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
717 "Child capture process stopped unexpectedly (errno:%u)", errno);
720 if (wait(&wstatus) != -1) {
721 if (WIFEXITED(wstatus)) {
722 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
723 /* the child will inform us about errors through the sync_pipe, which will popup */
724 /* an error message, so don't popup another one */
726 /* If there are situations where the child won't send us such an error message, */
727 /* this should be fixed in the child and not here! */
728 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
729 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
730 "Child capture process exited: exit status %d",
731 WEXITSTATUS(wstatus));
733 } else if (WIFSTOPPED(wstatus)) {
734 /* It stopped, rather than exiting. "Should not happen." */
735 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
736 "Child capture process stopped: %s",
737 sync_pipe_signame(WSTOPSIG(wstatus)));
738 } else if (WIFSIGNALED(wstatus)) {
739 /* It died with a signal. */
740 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
741 "Child capture process died: %s%s",
742 sync_pipe_signame(WTERMSIG(wstatus)),
743 WCOREDUMP(wstatus) ? " - core dumped" : "");
745 /* What? It had to either have exited, or stopped, or died with
746 a signal; what happened here? */
747 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
748 "Child capture process died: wait status %#o", wstatus);
753 /* No more child process. */
754 capture_opts->fork_child = -1;
756 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
761 /* convert signal to corresponding name */
763 sync_pipe_signame(int sig)
766 static char sigmsg_buf[6+1+3+1];
775 sigmsg = "Interrupted";
783 sigmsg = "Illegal instruction";
787 sigmsg = "Trace trap";
795 sigmsg = "Arithmetic exception";
803 sigmsg = "Bus error";
807 sigmsg = "Segmentation violation";
810 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
811 Linux is POSIX compliant. These are not POSIX-defined signals ---
812 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
814 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
815 were omitted from POSIX.1 because their behavior is
816 implementation dependent and could not be adequately catego-
817 rized. Conforming implementations may deliver these sig-
818 nals, but must document the circumstances under which they
819 are delivered and note any restrictions concerning their
822 So we only check for SIGSYS on those systems that happen to
823 implement them (a system can be POSIX-compliant and implement
824 them, it's just that POSIX doesn't *require* a POSIX-compliant
825 system to implement them).
830 sigmsg = "Bad system call";
835 sigmsg = "Broken pipe";
839 sigmsg = "Alarm clock";
843 sigmsg = "Terminated";
847 /* Returning a static buffer is ok in the context we use it here */
848 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
858 /* tell the child through the signal pipe that we want to quit the capture */
860 signal_pipe_capquit_to_child(capture_options *capture_opts)
862 const char quit_msg[] = "QUIT";
866 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
868 /* it doesn't matter *what* we send here, the first byte will stop the capture */
869 /* simply sending a "QUIT" string */
870 /*pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
871 ret = write(capture_opts->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
873 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
874 "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, strerror(errno));
880 /* user wants to stop the capture run */
882 sync_pipe_stop(capture_options *capture_opts)
884 if (capture_opts->fork_child != -1) {
886 /* send the SIGUSR1 signal to close the capture child gracefully. */
887 kill(capture_opts->fork_child, SIGUSR1);
889 /* Win32 doesn't have the kill() system call, use the special signal pipe
890 instead to close the capture child gracefully. */
891 signal_pipe_capquit_to_child(capture_opts);
897 /* Wireshark has to exit, force the capture child to close */
899 sync_pipe_kill(capture_options *capture_opts)
901 if (capture_opts->fork_child != -1) {
903 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
905 /* Remark: This is not the preferred method of closing a process!
906 * the clean way would be getting the process id of the child process,
907 * then getting window handle hWnd of that process (using EnumChildWindows),
908 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
910 * Unfortunately, I don't know how to get the process id from the
911 * handle. OpenProcess will get an handle (not a window handle)
912 * from the process ID; it will not get a window handle from the
913 * process ID. (How could it? A process can have more than one
914 * window. For that matter, a process might have *no* windows,
915 * as a process running dumpcap, the normal child process program,
918 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
919 * running in the same console; that's not necessarily the case for
920 * us, as we might not be running in a console.
921 * And this also will require to have the process id.
923 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
928 #endif /* HAVE_LIBPCAP */