2 * Synchronisation between Ethereal capture parent and child instances
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
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 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
50 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
51 * macros) on UNIX systems that don't have them.
54 # define WIFEXITED(status) (((status) & 0177) == 0)
57 # define WIFSTOPPED(status) (((status) & 0177) == 0177)
60 # define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
63 # define WEXITSTATUS(status) ((status) >> 8)
66 # define WTERMSIG(status) ((status) & 0177)
69 # define WCOREDUMP(status) ((status) & 0200)
72 # define WSTOPSIG(status) ((status) >> 8)
76 #include <epan/packet.h>
77 #include <epan/prefs.h>
81 #include <epan/filesystem.h>
84 #include "capture_sync.h"
85 #include "simple_dialog.h"
88 #include "capture-wpcap.h"
91 #include "file_util.h"
95 #include <process.h> /* For spawning child process */
100 static const char *sync_pipe_signame(int);
104 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
105 static void sync_pipe_wait_for_child(capture_options *capture_opts);
108 * Maximum length of sync pipe message data. Must be < 2^24, as the
109 * message length is 3 bytes.
110 * XXX - this must be large enough to handle a Really Big Filter
111 * Expression, as the error message for an incorrect filter expression
112 * is a bit larger than the filter expression.
114 #define SP_MAX_MSG_LEN 4096
117 /* write a message to the recipient pipe in the standard format
118 (3 digit message length (excluding length and indicator field),
119 1 byte message indicator and the rest is the message) */
121 pipe_write_block(int pipe, char indicator, int len, const char *msg)
123 guchar header[3+1]; /* indicator + 3-byte len */
126 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "write %d enter", pipe);
128 g_assert(indicator < '0' || indicator > '9');
129 g_assert(len <= SP_MAX_MSG_LEN);
131 /* write header (indicator + 3-byte len) */
132 header[0] = indicator;
133 header[1] = (len >> 16) & 0xFF;
134 header[2] = (len >> 8) & 0xFF;
135 header[3] = (len >> 0) & 0xFF;
137 ret = write(pipe, header, sizeof header);
139 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
140 "write %d header: error %s", pipe, strerror(errno));
144 /* write value (if we have one) */
146 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
147 "write %d indicator: %c value len: %u msg: %s", pipe, indicator,
149 ret = write(pipe, msg, len);
151 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
152 "write %d value: error %s", pipe, strerror(errno));
156 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
157 "write %d indicator: %c no value", pipe, indicator);
160 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "write %d leave", pipe);
166 sync_pipe_errmsg_to_parent(const char *errmsg)
168 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
170 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
177 signal_pipe_capquit_to_child(capture_options *capture_opts)
180 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
182 pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, 0, NULL);
188 /* read a message from the sending pipe in the standard format
189 (1-byte message indicator, 3-byte message length (excluding length
190 and indicator field), and the rest is the message) */
192 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
199 /* read header (indicator and 3-byte length) */
203 newly = read(pipe, &header[offset], required);
206 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
207 "read %d header empty (capture closed)", pipe);
212 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
213 "read %d header error: %s", pipe, strerror(errno));
221 /* convert header values */
222 *indicator = header[0];
223 required = header[1]<<16 | header[2]<<8 | header[3];
225 /* only indicator with no value? */
227 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
228 "read %d indicator: %c empty value", pipe, *indicator);
233 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
234 "read %d length error, required %d > len %d, indicator: %u",
235 pipe, required, len, *indicator);
243 newly = read(pipe, &msg[offset], required);
246 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
247 "read %d value error: %s, indicator: %u", pipe,
248 strerror(errno), *indicator);
256 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
257 "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
264 /* Add a string pointer to a NULL-terminated array of string pointers. */
266 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
268 /* Grow the array; "*argc" currently contains the number of string
269 pointers, *not* counting the NULL pointer at the end, so we have
270 to add 2 in order to get the new size of the array, including the
271 new pointer and the terminating NULL pointer. */
272 args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
274 /* Stuff the pointer into the penultimate element of the array, which
275 is the one at the index specified by "*argc". */
278 /* Now bump the count. */
281 /* We overwrite the NULL pointer; put it back right after the
290 #define ARGV_NUMBER_LEN 24
293 sync_pipe_start(capture_options *capture_opts) {
294 char ssnap[ARGV_NUMBER_LEN];
295 char scount[ARGV_NUMBER_LEN];
296 char sfilesize[ARGV_NUMBER_LEN];
297 char sfile_duration[ARGV_NUMBER_LEN];
298 char sring_num_files[ARGV_NUMBER_LEN];
299 char sautostop_files[ARGV_NUMBER_LEN];
300 char sautostop_filesize[ARGV_NUMBER_LEN];
301 char sautostop_duration[ARGV_NUMBER_LEN];
303 char buffer_size[ARGV_NUMBER_LEN];
305 char *savefilestring;
306 HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
307 HANDLE sync_pipe_write; /* pipe used to send messages from child to parent */
308 HANDLE signal_pipe_read; /* pipe used to send messages from parent to child (currently only stop) */
309 HANDLE signal_pipe_write; /* pipe used to send messages from parent to child (currently only stop) */
310 GString *args = g_string_sized_new(200);
311 SECURITY_ATTRIBUTES sa;
313 PROCESS_INFORMATION pi;
317 int sync_pipe[2]; /* pipe used to send messages from child to parent */
318 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
320 int sync_pipe_read_fd;
326 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
327 capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
329 capture_opts->fork_child = -1;
331 /* Allocate the string pointer array with enough space for the
332 terminating NULL pointer. */
334 argv = g_malloc(sizeof (char *));
337 /* take ethereal's absolute program path and replace ethereal with dumpcap */
338 exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap",
341 /* Make that the first argument in the argument list (argv[0]). */
342 argv = sync_pipe_add_arg(argv, &argc, exename);
344 argv = sync_pipe_add_arg(argv, &argc, "-i");
345 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
347 if (capture_opts->has_snaplen) {
348 argv = sync_pipe_add_arg(argv, &argc, "-s");
349 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
350 argv = sync_pipe_add_arg(argv, &argc, ssnap);
353 if (capture_opts->linktype != -1) {
354 argv = sync_pipe_add_arg(argv, &argc, "-y");
355 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
356 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",pcap_datalink_val_to_name(capture_opts->linktype));
358 /* XXX - just treat it as a number */
359 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
361 argv = sync_pipe_add_arg(argv, &argc, ssnap);
364 if(capture_opts->multi_files_on) {
365 if (capture_opts->has_autostop_filesize) {
366 argv = sync_pipe_add_arg(argv, &argc, "-b");
367 g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
368 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
371 if (capture_opts->has_file_duration) {
372 argv = sync_pipe_add_arg(argv, &argc, "-b");
373 g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
374 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
377 if (capture_opts->has_ring_num_files) {
378 argv = sync_pipe_add_arg(argv, &argc, "-b");
379 g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
380 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
383 if (capture_opts->has_autostop_files) {
384 argv = sync_pipe_add_arg(argv, &argc, "-a");
385 g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
386 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
389 if (capture_opts->has_autostop_filesize) {
390 argv = sync_pipe_add_arg(argv, &argc, "-a");
391 g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
392 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
396 if (capture_opts->has_autostop_packets) {
397 argv = sync_pipe_add_arg(argv, &argc, "-c");
398 g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
399 argv = sync_pipe_add_arg(argv, &argc, scount);
402 if (capture_opts->has_autostop_duration) {
403 argv = sync_pipe_add_arg(argv, &argc, "-a");
404 g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
405 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
408 if (!capture_opts->promisc_mode)
409 argv = sync_pipe_add_arg(argv, &argc, "-p");
411 /* dumpcap should be running in capture child mode (hidden feature) */
413 argv = sync_pipe_add_arg(argv, &argc, "-Z");
417 argv = sync_pipe_add_arg(argv, &argc, "-B");
418 g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
419 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
421 /* Convert filter string to a quote delimited string and pass to child */
423 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
424 argv = sync_pipe_add_arg(argv, &argc, "-f");
425 filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
426 argv = sync_pipe_add_arg(argv, &argc, filterstring);
429 /* Convert save file name to a quote delimited string and pass to child */
430 savefilestring = NULL;
431 if(capture_opts->save_file) {
432 argv = sync_pipe_add_arg(argv, &argc, "-w");
433 savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
434 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
437 /* init SECURITY_ATTRIBUTES */
438 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
439 sa.bInheritHandle = TRUE;
440 sa.lpSecurityDescriptor = NULL;
442 /* Create a pipe for the child process */
443 /* (inrease this value if you have trouble while fast capture file switches) */
444 if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
445 /* Couldn't create the pipe between parent and child. */
446 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
448 g_free( (gpointer) argv);
452 /* Create a pipe for the parent process */
453 if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
454 /* Couldn't create the signal pipe between parent and child. */
455 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
457 CloseHandle(sync_pipe_read);
458 CloseHandle(sync_pipe_write);
459 g_free( (gpointer) argv);
463 /* init STARTUPINFO */
464 memset(&si, 0, sizeof(si));
467 si.dwFlags = STARTF_USESHOWWINDOW;
468 si.wShowWindow = SW_SHOW;
470 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
471 si.wShowWindow = SW_HIDE; /* this hides the console window */
472 si.hStdInput = signal_pipe_read;
473 si.hStdOutput = sync_pipe_write;
474 si.hStdError = sync_pipe_write;
477 g_string_append(args, exename);
479 /* convert args array into a single string */
480 /* XXX - could change sync_pipe_add_arg() instead */
481 /* there is a drawback here: the length is internally limited to 1024 bytes */
482 for(i=0; argv[i] != 0; i++) {
483 g_string_append_c(args, ' ');
484 g_string_append(args, argv[i]);
488 if(!CreateProcess(NULL, args->str, NULL, NULL, TRUE,
489 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
490 g_error("couldn't open dumpcap.exe!");
492 capture_opts->fork_child = (int) pi.hProcess;
493 g_string_free(args, TRUE);
495 /* associate the operating system filehandle to a C run-time file handle */
496 /* (good file handle infos at: http://www.flounder.com/handles.htm) */
497 sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
499 /* associate the operating system filehandle to a C run-time file handle */
500 capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
503 g_free(filterstring);
506 g_free(savefilestring);
509 /* child own's the read side now, close our handle */
510 CloseHandle(signal_pipe_read);
512 if (pipe(sync_pipe) < 0) {
513 /* Couldn't create the pipe between parent and child. */
514 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
520 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
521 argv = sync_pipe_add_arg(argv, &argc, "-f");
522 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
525 if(capture_opts->save_file) {
526 argv = sync_pipe_add_arg(argv, &argc, "-w");
527 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
530 if ((capture_opts->fork_child = fork()) == 0) {
532 * Child process - run Ethereal with the right arguments to make
533 * it just pop up the live capture dialog box and capture with
534 * the specified capture parameters, writing to the specified file.
536 * args: -i interface specification
538 * -c count to capture
541 * -f "filter expression"
544 dup(sync_pipe[PIPE_WRITE]);
545 eth_close(sync_pipe[PIPE_READ]);
546 execvp(exename, argv);
547 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
548 exename, strerror(errno));
549 sync_pipe_errmsg_to_parent(errmsg);
551 /* Exit with "_exit()", so that we don't close the connection
552 to the X server (and cause stuff buffered up by our parent but
553 not yet sent to be sent, as that stuff should only be sent by
558 sync_pipe_read_fd = sync_pipe[PIPE_READ];
563 /* Parent process - read messages from the child process over the
565 g_free( (gpointer) argv); /* free up arg array */
567 /* Close the write side of the pipe, so that only the child has it
568 open, and thus it completely closes, and thus returns to us
569 an EOF indication, if the child closes it (either deliberately
570 or by exiting abnormally). */
572 CloseHandle(sync_pipe_write);
574 eth_close(sync_pipe[PIPE_WRITE]);
577 if (capture_opts->fork_child == -1) {
578 /* We couldn't even create the child process. */
579 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
580 "Couldn't create child process: %s", strerror(errno));
581 eth_close(sync_pipe_read_fd);
583 eth_close(capture_opts->signal_pipe_write_fd);
588 /* we might wait for a moment till child is ready, so update screen now */
589 main_window_update();
591 /* We were able to set up to read the capture file;
592 arrange that our callback be called whenever it's possible
593 to read from the sync pipe, so that it's called when
594 the child process wants to tell us something. */
596 /* we have a running capture, now wait for the real capture filename */
597 pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
598 &capture_opts->fork_child, sync_pipe_input_cb);
603 /* There's stuff to read from the sync pipe, meaning the child has sent
604 us a message, or the sync pipe has closed, meaning the child has
605 closed it (perhaps because it exited). */
607 sync_pipe_input_cb(gint source, gpointer user_data)
609 capture_options *capture_opts = (capture_options *)user_data;
610 char buffer[SP_MAX_MSG_LEN+1];
615 nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
618 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
619 "sync_pipe_input_cb: child has closed sync_pipe");
621 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
622 "sync_pipe_input_cb: error reading from sync pipe");
624 /* The child has closed the sync pipe, meaning it's not going to be
625 capturing any more packets. Pick up its exit status, and
626 complain if it did anything other than exit with status 0.
628 XXX - what if we got an error from the sync pipe? Do we have
629 to kill the child? */
630 sync_pipe_wait_for_child(capture_opts);
633 eth_close(capture_opts->signal_pipe_write_fd);
635 capture_input_closed(capture_opts);
641 if(!capture_input_new_file(capture_opts, buffer)) {
642 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
644 /* We weren't able to open the new capture file; user has been
645 alerted. Close the sync pipe. */
648 /* the child has send us a filename which we couldn't open.
649 this probably means, the child is creating files faster than we can handle it.
650 this should only be the case for very fast file switches
651 we can't do much more than telling the child to stop
652 (this is the "emergency brake" if user e.g. wants to switch files every second) */
653 sync_pipe_stop(capture_opts);
656 case SP_PACKET_COUNT:
657 nread = atoi(buffer);
658 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
659 capture_input_new_packets(capture_opts, nread);
662 capture_input_error_message(capture_opts, buffer);
663 /* the capture child will close the sync_pipe, nothing to do for now */
666 capture_input_drops(capture_opts, atoi(buffer));
669 g_assert_not_reached();
677 /* the child process is going down, wait until it's completely terminated */
679 sync_pipe_wait_for_child(capture_options *capture_opts)
684 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
685 g_assert(capture_opts->fork_child != -1);
688 /* XXX - analyze the wait status and display more information
690 XXX - set "fork_child" to -1 if we find it exited? */
691 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
692 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
693 "Child capture process stopped unexpectedly");
696 if (wait(&wstatus) != -1) {
697 if (WIFEXITED(wstatus)) {
698 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
699 /* the child will inform us about errors through the sync_pipe, which will popup */
700 /* an error message, so don't popup another one */
702 /* XXX - if there are situations where the child won't send us such an error message, */
703 /* this should be fixed in the child and not here! */
704 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
705 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
706 "Child capture process exited: exit status %d",
707 WEXITSTATUS(wstatus));
709 } else if (WIFSTOPPED(wstatus)) {
710 /* It stopped, rather than exiting. "Should not happen." */
711 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
712 "Child capture process stopped: %s",
713 sync_pipe_signame(WSTOPSIG(wstatus)));
714 } else if (WIFSIGNALED(wstatus)) {
715 /* It died with a signal. */
716 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
717 "Child capture process died: %s%s",
718 sync_pipe_signame(WTERMSIG(wstatus)),
719 WCOREDUMP(wstatus) ? " - core dumped" : "");
721 /* What? It had to either have exited, or stopped, or died with
722 a signal; what happened here? */
723 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
724 "Child capture process died: wait status %#o", wstatus);
728 /* No more child process. */
729 capture_opts->fork_child = -1;
732 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
737 /* convert signal to corresponding name */
739 sync_pipe_signame(int sig)
742 static char sigmsg_buf[6+1+3+1];
751 sigmsg = "Interrupted";
759 sigmsg = "Illegal instruction";
763 sigmsg = "Trace trap";
771 sigmsg = "Arithmetic exception";
779 sigmsg = "Bus error";
783 sigmsg = "Segmentation violation";
786 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
787 Linux is POSIX compliant. These are not POSIX-defined signals ---
788 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
790 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
791 were omitted from POSIX.1 because their behavior is
792 implementation dependent and could not be adequately catego-
793 rized. Conforming implementations may deliver these sig-
794 nals, but must document the circumstances under which they
795 are delivered and note any restrictions concerning their
798 So we only check for SIGSYS on those systems that happen to
799 implement them (a system can be POSIX-compliant and implement
800 them, it's just that POSIX doesn't *require* a POSIX-compliant
801 system to implement them).
806 sigmsg = "Bad system call";
811 sigmsg = "Broken pipe";
815 sigmsg = "Alarm clock";
819 sigmsg = "Terminated";
823 /* XXX - returning a static buffer is ok in the context we use it here */
824 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
833 /* user wants to stop the capture run */
835 sync_pipe_stop(capture_options *capture_opts)
837 /* XXX - in which cases this will be 0? */
838 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
840 /* send the SIGUSR1 signal to close the capture child gracefully. */
841 kill(capture_opts->fork_child, SIGUSR1);
843 /* Win32 doesn't have the kill() system call, use the special signal pipe
844 instead to close the capture child gracefully. */
845 signal_pipe_capquit_to_child(capture_opts);
851 /* Ethereal has to exit, force the capture child to close */
853 sync_pipe_kill(capture_options *capture_opts)
855 /* XXX - in which cases this will be 0? */
856 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
858 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
860 /* XXX: this is not the preferred method of closing a process!
861 * the clean way would be getting the process id of the child process,
862 * then getting window handle hWnd of that process (using EnumChildWindows),
863 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
865 * Unfortunately, I don't know how to get the process id from the
866 * handle. OpenProcess will get an handle (not a window handle)
867 * from the process ID; it will not get a window handle from the
868 * process ID. (How could it? A process can have more than one
871 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
872 * running in the same console; that's not necessarily the case for
873 * us, as we might not be running in a console.
874 * And this also will require to have the process id.
876 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
881 #endif /* HAVE_LIBPCAP */