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/strutil.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 own's 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 Wireshark with the right arguments to make
449 * it just pop up the live capture dialog box and capture with
450 * the specified capture parameters, writing to the specified file.
453 dup(sync_pipe[PIPE_WRITE]);
454 eth_close(sync_pipe[PIPE_READ]);
455 execv(exename, argv);
456 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
457 exename, strerror(errno));
458 sync_pipe_errmsg_to_parent(errmsg, "");
460 /* Exit with "_exit()", so that we don't close the connection
461 to the X server (and cause stuff buffered up by our parent but
462 not yet sent to be sent, as that stuff should only be sent by
467 sync_pipe_read_fd = sync_pipe[PIPE_READ];
472 /* Parent process - read messages from the child process over the
474 g_free( (gpointer) argv); /* free up arg array */
476 /* Close the write side of the pipe, so that only the child has it
477 open, and thus it completely closes, and thus returns to us
478 an EOF indication, if the child closes it (either deliberately
479 or by exiting abnormally). */
481 CloseHandle(sync_pipe_write);
483 eth_close(sync_pipe[PIPE_WRITE]);
486 if (capture_opts->fork_child == -1) {
487 /* We couldn't even create the child process. */
488 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
489 "Couldn't create child process: %s", strerror(errno));
490 eth_close(sync_pipe_read_fd);
492 eth_close(capture_opts->signal_pipe_write_fd);
497 /* we might wait for a moment till child is ready, so update screen now */
498 main_window_update();
500 /* We were able to set up to read the capture file;
501 arrange that our callback be called whenever it's possible
502 to read from the sync pipe, so that it's called when
503 the child process wants to tell us something. */
505 /* we have a running capture, now wait for the real capture filename */
506 pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
507 &capture_opts->fork_child, sync_pipe_input_cb);
514 /* read a number of bytes from a pipe */
515 /* (blocks until enough bytes read or an error occurs) */
517 pipe_read_bytes(int pipe, char *bytes, int required) {
523 newly = read(pipe, &bytes[offset], required);
526 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
527 "read from pipe %d: EOF (capture closed?)", pipe);
532 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
533 "read from pipe %d: error(%u): %s", pipe, errno, strerror(errno));
544 /* convert header values (indicator and 4-byte length) */
546 pipe_convert_header(const guchar *header, int header_len, char *indicator, int *block_len) {
548 g_assert(header_len == 4);
550 /* convert header values */
551 *indicator = header[0];
552 *block_len = header[1]<<16 | header[2]<<8 | header[3];
555 /* read a message from the sending pipe in the standard format
556 (1-byte message indicator, 3-byte message length (excluding length
557 and indicator field), and the rest is the message) */
559 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
565 /* read header (indicator and 3-byte length) */
566 newly = pipe_read_bytes(pipe, header, 4);
568 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
569 "read %d failed to read header: %u", pipe, newly);
573 /* convert header values */
574 pipe_convert_header(header, 4, indicator, &required);
576 /* only indicator with no value? */
578 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
579 "read %d indicator: %c empty value", pipe, *indicator);
583 /* does the data fit into the given buffer? */
585 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
586 "read %d length error, required %d > len %d, indicator: %u",
587 pipe, required, len, *indicator);
589 /* we have a problem here, try to read some more bytes from the pipe to debug where the problem really is */
590 memcpy(msg, header, sizeof(header));
591 newly = read(pipe, &msg[sizeof(header)], len-sizeof(header));
592 g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
597 /* read the actual block data */
598 newly = pipe_read_bytes(pipe, msg, required);
599 if(newly != required) {
600 g_warning("Unknown message from dumpcap, try to show it as a string: %s", msg);
604 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
605 "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
611 /* There's stuff to read from the sync pipe, meaning the child has sent
612 us a message, or the sync pipe has closed, meaning the child has
613 closed it (perhaps because it exited). */
615 sync_pipe_input_cb(gint source, gpointer user_data)
617 capture_options *capture_opts = (capture_options *)user_data;
618 char buffer[SP_MAX_MSG_LEN+1];
624 char * secondary_msg;
627 nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
630 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
631 "sync_pipe_input_cb: child has closed sync_pipe");
633 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
634 "sync_pipe_input_cb: error reading from sync pipe");
636 /* The child has closed the sync pipe, meaning it's not going to be
637 capturing any more packets. Pick up its exit status, and
638 complain if it did anything other than exit with status 0.
640 We don't have to worry about killing the child, if the sync pipe
641 returned an error. Usually this error is caused as the child killed itself
642 while going down. Even in the rare cases that this isn't the case,
643 the child will get an error when writing to the broken pipe the next time,
644 cleaning itself up then. */
645 sync_pipe_wait_for_child(capture_opts);
648 eth_close(capture_opts->signal_pipe_write_fd);
650 capture_input_closed(capture_opts);
654 /* we got a valid message block from the child, process it */
657 if(!capture_input_new_file(capture_opts, buffer)) {
658 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
660 /* We weren't able to open the new capture file; user has been
661 alerted. Close the sync pipe. */
664 /* the child has send us a filename which we couldn't open.
665 this probably means, the child is creating files faster than we can handle it.
666 this should only be the case for very fast file switches
667 we can't do much more than telling the child to stop
668 (this is the "emergency brake" if user e.g. wants to switch files every second) */
669 sync_pipe_stop(capture_opts);
672 case SP_PACKET_COUNT:
673 nread = atoi(buffer);
674 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
675 capture_input_new_packets(capture_opts, nread);
678 /* convert primary message */
679 pipe_convert_header(buffer, 4, &indicator, &primary_len);
680 primary_msg = buffer+4;
681 /* convert secondary message */
682 pipe_convert_header(primary_msg + primary_len, 4, &indicator, &secondary_len);
683 secondary_msg = primary_msg + primary_len + 4;
685 capture_input_error_message(capture_opts, primary_msg, secondary_msg);
686 /* the capture child will close the sync_pipe, nothing to do for now */
687 /* (an error message doesn't mean we have to stop capturing) */
690 capture_input_cfilter_error_message(capture_opts, buffer);
691 /* the capture child will close the sync_pipe, nothing to do for now */
694 capture_input_drops(capture_opts, atoi(buffer));
697 g_assert_not_reached();
705 /* the child process is going down, wait until it's completely terminated */
707 sync_pipe_wait_for_child(capture_options *capture_opts)
712 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
713 g_assert(capture_opts->fork_child != -1);
716 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
717 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
718 "Child capture process stopped unexpectedly (errno:%u)", errno);
721 if (wait(&wstatus) != -1) {
722 if (WIFEXITED(wstatus)) {
723 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
724 /* the child will inform us about errors through the sync_pipe, which will popup */
725 /* an error message, so don't popup another one */
727 /* If there are situations where the child won't send us such an error message, */
728 /* this should be fixed in the child and not here! */
729 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
730 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
731 "Child capture process exited: exit status %d",
732 WEXITSTATUS(wstatus));
734 } else if (WIFSTOPPED(wstatus)) {
735 /* It stopped, rather than exiting. "Should not happen." */
736 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
737 "Child capture process stopped: %s",
738 sync_pipe_signame(WSTOPSIG(wstatus)));
739 } else if (WIFSIGNALED(wstatus)) {
740 /* It died with a signal. */
741 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
742 "Child capture process died: %s%s",
743 sync_pipe_signame(WTERMSIG(wstatus)),
744 WCOREDUMP(wstatus) ? " - core dumped" : "");
746 /* What? It had to either have exited, or stopped, or died with
747 a signal; what happened here? */
748 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
749 "Child capture process died: wait status %#o", wstatus);
754 /* No more child process. */
755 capture_opts->fork_child = -1;
757 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
762 /* convert signal to corresponding name */
764 sync_pipe_signame(int sig)
767 static char sigmsg_buf[6+1+3+1];
776 sigmsg = "Interrupted";
784 sigmsg = "Illegal instruction";
788 sigmsg = "Trace trap";
796 sigmsg = "Arithmetic exception";
804 sigmsg = "Bus error";
808 sigmsg = "Segmentation violation";
811 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
812 Linux is POSIX compliant. These are not POSIX-defined signals ---
813 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
815 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
816 were omitted from POSIX.1 because their behavior is
817 implementation dependent and could not be adequately catego-
818 rized. Conforming implementations may deliver these sig-
819 nals, but must document the circumstances under which they
820 are delivered and note any restrictions concerning their
823 So we only check for SIGSYS on those systems that happen to
824 implement them (a system can be POSIX-compliant and implement
825 them, it's just that POSIX doesn't *require* a POSIX-compliant
826 system to implement them).
831 sigmsg = "Bad system call";
836 sigmsg = "Broken pipe";
840 sigmsg = "Alarm clock";
844 sigmsg = "Terminated";
848 /* Returning a static buffer is ok in the context we use it here */
849 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
859 /* tell the child through the signal pipe that we want to quit the capture */
861 signal_pipe_capquit_to_child(capture_options *capture_opts)
863 const char quit_msg[] = "QUIT";
867 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
869 /* it doesn't matter *what* we send here, the first byte will stop the capture */
870 /* simply sending a "QUIT" string */
871 /*pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, quit_msg);*/
872 ret = write(capture_opts->signal_pipe_write_fd, quit_msg, sizeof quit_msg);
874 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
875 "signal_pipe_capquit_to_child: %d header: error %s", capture_opts->signal_pipe_write_fd, strerror(errno));
881 /* user wants to stop the capture run */
883 sync_pipe_stop(capture_options *capture_opts)
885 if (capture_opts->fork_child != -1) {
887 /* send the SIGUSR1 signal to close the capture child gracefully. */
888 kill(capture_opts->fork_child, SIGUSR1);
890 /* Win32 doesn't have the kill() system call, use the special signal pipe
891 instead to close the capture child gracefully. */
892 signal_pipe_capquit_to_child(capture_opts);
898 /* Wireshark has to exit, force the capture child to close */
900 sync_pipe_kill(capture_options *capture_opts)
902 if (capture_opts->fork_child != -1) {
904 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
906 /* Remark: This is not the preferred method of closing a process!
907 * the clean way would be getting the process id of the child process,
908 * then getting window handle hWnd of that process (using EnumChildWindows),
909 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
911 * Unfortunately, I don't know how to get the process id from the
912 * handle. OpenProcess will get an handle (not a window handle)
913 * from the process ID; it will not get a window handle from the
914 * process ID. (How could it? A process can have more than one
915 * window. For that matter, a process might have *no* windows,
916 * as a process running dumpcap, the normal child process program,
919 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
920 * running in the same console; that's not necessarily the case for
921 * us, as we might not be running in a console.
922 * And this also will require to have the process id.
924 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
929 #endif /* HAVE_LIBPCAP */