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.
46 #ifdef HAVE_SYS_WAIT_H
47 # include <sys/wait.h>
50 #include "capture-pcap-util.h"
54 * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
55 * macros) on UNIX systems that don't have them.
58 # define WIFEXITED(status) (((status) & 0177) == 0)
61 # define WIFSTOPPED(status) (((status) & 0177) == 0177)
64 # define WIFSIGNALED(status) (!WIFSTOPPED(status) && !WIFEXITED(status))
67 # define WEXITSTATUS(status) ((status) >> 8)
70 # define WTERMSIG(status) ((status) & 0177)
73 # define WCOREDUMP(status) ((status) & 0200)
76 # define WSTOPSIG(status) ((status) >> 8)
80 #include <epan/packet.h>
81 #include <epan/prefs.h>
85 #include <epan/filesystem.h>
88 #include "capture_sync.h"
89 #include "simple_dialog.h"
92 #include "capture-wpcap.h"
95 #include "file_util.h"
99 #include <process.h> /* For spawning child process */
104 static const char *sync_pipe_signame(int);
108 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
109 static void sync_pipe_wait_for_child(capture_options *capture_opts);
112 * Maximum length of sync pipe message data. Must be < 2^24, as the
113 * message length is 3 bytes.
114 * XXX - this must be large enough to handle a Really Big Filter
115 * Expression, as the error message for an incorrect filter expression
116 * is a bit larger than the filter expression.
118 #define SP_MAX_MSG_LEN 4096
121 /* write a message to the recipient pipe in the standard format
122 (3 digit message length (excluding length and indicator field),
123 1 byte message indicator and the rest is the message) */
125 pipe_write_block(int pipe, char indicator, int len, const char *msg)
127 guchar header[3+1]; /* indicator + 3-byte len */
130 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "write %d enter", pipe);
132 g_assert(indicator < '0' || indicator > '9');
133 g_assert(len <= SP_MAX_MSG_LEN);
135 /* write header (indicator + 3-byte len) */
136 header[0] = indicator;
137 header[1] = (len >> 16) & 0xFF;
138 header[2] = (len >> 8) & 0xFF;
139 header[3] = (len >> 0) & 0xFF;
141 ret = write(pipe, header, sizeof header);
143 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
144 "write %d header: error %s", pipe, strerror(errno));
148 /* write value (if we have one) */
150 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
151 "write %d indicator: %c value len: %u msg: %s", pipe, indicator,
153 ret = write(pipe, msg, len);
155 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_WARNING,
156 "write %d value: error %s", pipe, strerror(errno));
160 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG,
161 "write %d indicator: %c no value", pipe, indicator);
164 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "write %d leave", pipe);
170 sync_pipe_errmsg_to_parent(const char *errmsg)
172 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
174 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
181 signal_pipe_capquit_to_child(capture_options *capture_opts)
184 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
186 pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, 0, NULL);
192 /* read a message from the sending pipe in the standard format
193 (1-byte message indicator, 3-byte message length (excluding length
194 and indicator field), and the rest is the message) */
196 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
203 /* read header (indicator and 3-byte length) */
207 newly = read(pipe, &header[offset], required);
210 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
211 "read %d header empty (capture closed)", pipe);
216 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
217 "read %d header error: %s", pipe, strerror(errno));
225 /* convert header values */
226 *indicator = header[0];
227 required = header[1]<<16 | header[2]<<8 | header[3];
229 /* only indicator with no value? */
231 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
232 "read %d indicator: %c empty value", pipe, *indicator);
237 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
238 "read %d length error, required %d > len %d, indicator: %u",
239 pipe, required, len, *indicator);
247 newly = read(pipe, &msg[offset], required);
250 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
251 "read %d value error: %s, indicator: %u", pipe,
252 strerror(errno), *indicator);
260 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
261 "read %d ok indicator: %c len: %u msg: %s", pipe, *indicator,
268 /* Add a string pointer to a NULL-terminated array of string pointers. */
270 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
272 /* Grow the array; "*argc" currently contains the number of string
273 pointers, *not* counting the NULL pointer at the end, so we have
274 to add 2 in order to get the new size of the array, including the
275 new pointer and the terminating NULL pointer. */
276 args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
278 /* Stuff the pointer into the penultimate element of the array, which
279 is the one at the index specified by "*argc". */
282 /* Now bump the count. */
285 /* We overwrite the NULL pointer; put it back right after the
295 /* Quote the argument element if necessary, so that it will get
296 * reconstructed correctly in the C runtime startup code. Note that
297 * the unquoting algorithm in the C runtime is really weird, and
298 * rather different than what Unix shells do. See stdargv.c in the C
299 * runtime sources (in the Platform SDK, in src/crt).
301 * Stolen from GLib's protect_argv(), an internal routine that quotes
302 * string in an argument list so that they arguments will be handled
303 * correctly in the command-line string passed to CreateProcess()
304 * if that string is constructed by gluing those strings together.
307 protect_arg (gchar *argv)
313 gboolean need_dblquotes = FALSE;
316 if (*p == ' ' || *p == '\t')
317 need_dblquotes = TRUE;
320 else if (*p == '\\') {
323 while (*pp && *pp == '\\')
332 q = new_arg = g_malloc (len + need_dblquotes*2 + 1);
341 else if (*p == '\\') {
344 while (*pp && *pp == '\\')
363 #define ARGV_NUMBER_LEN 24
366 sync_pipe_start(capture_options *capture_opts) {
367 char ssnap[ARGV_NUMBER_LEN];
368 char scount[ARGV_NUMBER_LEN];
369 char sfilesize[ARGV_NUMBER_LEN];
370 char sfile_duration[ARGV_NUMBER_LEN];
371 char sring_num_files[ARGV_NUMBER_LEN];
372 char sautostop_files[ARGV_NUMBER_LEN];
373 char sautostop_filesize[ARGV_NUMBER_LEN];
374 char sautostop_duration[ARGV_NUMBER_LEN];
376 char buffer_size[ARGV_NUMBER_LEN];
378 char *savefilestring;
379 HANDLE sync_pipe_read; /* pipe used to send messages from child to parent */
380 HANDLE sync_pipe_write; /* pipe used to send messages from child to parent */
381 HANDLE signal_pipe_read; /* pipe used to send messages from parent to child (currently only stop) */
382 HANDLE signal_pipe_write; /* pipe used to send messages from parent to child (currently only stop) */
383 GString *args = g_string_sized_new(200);
385 SECURITY_ATTRIBUTES sa;
387 PROCESS_INFORMATION pi;
391 int sync_pipe[2]; /* pipe used to send messages from child to parent */
392 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
394 int sync_pipe_read_fd;
400 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
401 capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
403 capture_opts->fork_child = -1;
405 /* Allocate the string pointer array with enough space for the
406 terminating NULL pointer. */
408 argv = g_malloc(sizeof (char *));
411 /* take ethereal's absolute program path and replace ethereal with dumpcap */
412 exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap",
415 /* Make that the first argument in the argument list (argv[0]). */
416 argv = sync_pipe_add_arg(argv, &argc, exename);
418 argv = sync_pipe_add_arg(argv, &argc, "-i");
419 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
421 if (capture_opts->has_snaplen) {
422 argv = sync_pipe_add_arg(argv, &argc, "-s");
423 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
424 argv = sync_pipe_add_arg(argv, &argc, ssnap);
427 if (capture_opts->linktype != -1) {
428 argv = sync_pipe_add_arg(argv, &argc, "-y");
429 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
430 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",linktype_val_to_name(capture_opts->linktype));
432 /* XXX - just treat it as a number */
433 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
435 argv = sync_pipe_add_arg(argv, &argc, ssnap);
438 if(capture_opts->multi_files_on) {
439 if (capture_opts->has_autostop_filesize) {
440 argv = sync_pipe_add_arg(argv, &argc, "-b");
441 g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
442 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
445 if (capture_opts->has_file_duration) {
446 argv = sync_pipe_add_arg(argv, &argc, "-b");
447 g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
448 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
451 if (capture_opts->has_ring_num_files) {
452 argv = sync_pipe_add_arg(argv, &argc, "-b");
453 g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
454 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
457 if (capture_opts->has_autostop_files) {
458 argv = sync_pipe_add_arg(argv, &argc, "-a");
459 g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
460 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
463 if (capture_opts->has_autostop_filesize) {
464 argv = sync_pipe_add_arg(argv, &argc, "-a");
465 g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
466 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
470 if (capture_opts->has_autostop_packets) {
471 argv = sync_pipe_add_arg(argv, &argc, "-c");
472 g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
473 argv = sync_pipe_add_arg(argv, &argc, scount);
476 if (capture_opts->has_autostop_duration) {
477 argv = sync_pipe_add_arg(argv, &argc, "-a");
478 g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
479 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
482 if (!capture_opts->promisc_mode)
483 argv = sync_pipe_add_arg(argv, &argc, "-p");
485 /* dumpcap should be running in capture child mode (hidden feature) */
487 argv = sync_pipe_add_arg(argv, &argc, "-Z");
491 argv = sync_pipe_add_arg(argv, &argc, "-B");
492 g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
493 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
495 /* Convert filter string to a quote delimited string and pass to child */
497 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
498 argv = sync_pipe_add_arg(argv, &argc, "-f");
499 filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
500 argv = sync_pipe_add_arg(argv, &argc, filterstring);
503 /* Convert save file name to a quote delimited string and pass to child */
504 savefilestring = NULL;
505 if(capture_opts->save_file) {
506 argv = sync_pipe_add_arg(argv, &argc, "-w");
507 savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
508 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
511 /* init SECURITY_ATTRIBUTES */
512 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
513 sa.bInheritHandle = TRUE;
514 sa.lpSecurityDescriptor = NULL;
516 /* Create a pipe for the child process */
517 /* (inrease this value if you have trouble while fast capture file switches) */
518 if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
519 /* Couldn't create the pipe between parent and child. */
520 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
522 g_free( (gpointer) argv);
526 /* Create a pipe for the parent process */
527 if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
528 /* Couldn't create the signal pipe between parent and child. */
529 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
531 CloseHandle(sync_pipe_read);
532 CloseHandle(sync_pipe_write);
533 g_free( (gpointer) argv);
537 /* init STARTUPINFO */
538 memset(&si, 0, sizeof(si));
541 si.dwFlags = STARTF_USESHOWWINDOW;
542 si.wShowWindow = SW_SHOW;
544 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
545 si.wShowWindow = SW_HIDE; /* this hides the console window */
546 si.hStdInput = signal_pipe_read;
547 si.hStdOutput = sync_pipe_write;
548 si.hStdError = sync_pipe_write;
549 /*si.hStdError = (HANDLE) _get_osfhandle(2);*/
553 * XXX - is this necessary? argv[0] should be the full path of
556 quoted_arg = protect_arg(exename);
557 g_string_append(args, quoted_arg);
560 /* convert args array into a single string */
561 /* XXX - could change sync_pipe_add_arg() instead */
562 /* there is a drawback here: the length is internally limited to 1024 bytes */
563 for(i=0; argv[i] != 0; i++) {
564 g_string_append_c(args, ' ');
565 quoted_arg = protect_arg(argv[i]);
566 g_string_append(args, quoted_arg);
571 if(!CreateProcess(NULL, args->str, NULL, NULL, TRUE,
572 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
573 g_error("couldn't open dumpcap.exe!");
575 capture_opts->fork_child = (int) pi.hProcess;
576 g_string_free(args, TRUE);
578 /* associate the operating system filehandle to a C run-time file handle */
579 /* (good file handle infos at: http://www.flounder.com/handles.htm) */
580 sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
582 /* associate the operating system filehandle to a C run-time file handle */
583 capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
586 g_free(filterstring);
589 g_free(savefilestring);
592 /* child own's the read side now, close our handle */
593 CloseHandle(signal_pipe_read);
595 if (pipe(sync_pipe) < 0) {
596 /* Couldn't create the pipe between parent and child. */
597 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
603 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
604 argv = sync_pipe_add_arg(argv, &argc, "-f");
605 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
608 if(capture_opts->save_file) {
609 argv = sync_pipe_add_arg(argv, &argc, "-w");
610 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
613 if ((capture_opts->fork_child = fork()) == 0) {
615 * Child process - run Ethereal with the right arguments to make
616 * it just pop up the live capture dialog box and capture with
617 * the specified capture parameters, writing to the specified file.
619 * args: -i interface specification
621 * -c count to capture
624 * -f "filter expression"
627 dup(sync_pipe[PIPE_WRITE]);
628 eth_close(sync_pipe[PIPE_READ]);
629 execv(exename, argv);
630 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
631 exename, strerror(errno));
632 sync_pipe_errmsg_to_parent(errmsg);
634 /* Exit with "_exit()", so that we don't close the connection
635 to the X server (and cause stuff buffered up by our parent but
636 not yet sent to be sent, as that stuff should only be sent by
641 sync_pipe_read_fd = sync_pipe[PIPE_READ];
646 /* Parent process - read messages from the child process over the
648 g_free( (gpointer) argv); /* free up arg array */
650 /* Close the write side of the pipe, so that only the child has it
651 open, and thus it completely closes, and thus returns to us
652 an EOF indication, if the child closes it (either deliberately
653 or by exiting abnormally). */
655 CloseHandle(sync_pipe_write);
657 eth_close(sync_pipe[PIPE_WRITE]);
660 if (capture_opts->fork_child == -1) {
661 /* We couldn't even create the child process. */
662 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
663 "Couldn't create child process: %s", strerror(errno));
664 eth_close(sync_pipe_read_fd);
666 eth_close(capture_opts->signal_pipe_write_fd);
671 /* we might wait for a moment till child is ready, so update screen now */
672 main_window_update();
674 /* We were able to set up to read the capture file;
675 arrange that our callback be called whenever it's possible
676 to read from the sync pipe, so that it's called when
677 the child process wants to tell us something. */
679 /* we have a running capture, now wait for the real capture filename */
680 pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
681 &capture_opts->fork_child, sync_pipe_input_cb);
686 /* There's stuff to read from the sync pipe, meaning the child has sent
687 us a message, or the sync pipe has closed, meaning the child has
688 closed it (perhaps because it exited). */
690 sync_pipe_input_cb(gint source, gpointer user_data)
692 capture_options *capture_opts = (capture_options *)user_data;
693 char buffer[SP_MAX_MSG_LEN+1];
698 nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
701 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
702 "sync_pipe_input_cb: child has closed sync_pipe");
704 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG,
705 "sync_pipe_input_cb: error reading from sync pipe");
707 /* The child has closed the sync pipe, meaning it's not going to be
708 capturing any more packets. Pick up its exit status, and
709 complain if it did anything other than exit with status 0.
711 XXX - what if we got an error from the sync pipe? Do we have
712 to kill the child? */
713 sync_pipe_wait_for_child(capture_opts);
716 eth_close(capture_opts->signal_pipe_write_fd);
718 capture_input_closed(capture_opts);
724 if(!capture_input_new_file(capture_opts, buffer)) {
725 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
727 /* We weren't able to open the new capture file; user has been
728 alerted. Close the sync pipe. */
731 /* the child has send us a filename which we couldn't open.
732 this probably means, the child is creating files faster than we can handle it.
733 this should only be the case for very fast file switches
734 we can't do much more than telling the child to stop
735 (this is the "emergency brake" if user e.g. wants to switch files every second) */
736 sync_pipe_stop(capture_opts);
739 case SP_PACKET_COUNT:
740 nread = atoi(buffer);
741 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
742 capture_input_new_packets(capture_opts, nread);
745 capture_input_error_message(capture_opts, buffer);
746 /* the capture child will close the sync_pipe, nothing to do for now */
749 capture_input_drops(capture_opts, atoi(buffer));
752 g_assert_not_reached();
760 /* the child process is going down, wait until it's completely terminated */
762 sync_pipe_wait_for_child(capture_options *capture_opts)
767 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
768 g_assert(capture_opts->fork_child != -1);
771 /* XXX - analyze the wait status and display more information
773 XXX - set "fork_child" to -1 if we find it exited? */
774 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
775 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
776 "Child capture process stopped unexpectedly");
779 if (wait(&wstatus) != -1) {
780 if (WIFEXITED(wstatus)) {
781 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
782 /* the child will inform us about errors through the sync_pipe, which will popup */
783 /* an error message, so don't popup another one */
785 /* XXX - if there are situations where the child won't send us such an error message, */
786 /* this should be fixed in the child and not here! */
787 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
788 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
789 "Child capture process exited: exit status %d",
790 WEXITSTATUS(wstatus));
792 } else if (WIFSTOPPED(wstatus)) {
793 /* It stopped, rather than exiting. "Should not happen." */
794 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
795 "Child capture process stopped: %s",
796 sync_pipe_signame(WSTOPSIG(wstatus)));
797 } else if (WIFSIGNALED(wstatus)) {
798 /* It died with a signal. */
799 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
800 "Child capture process died: %s%s",
801 sync_pipe_signame(WTERMSIG(wstatus)),
802 WCOREDUMP(wstatus) ? " - core dumped" : "");
804 /* What? It had to either have exited, or stopped, or died with
805 a signal; what happened here? */
806 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
807 "Child capture process died: wait status %#o", wstatus);
811 /* No more child process. */
812 capture_opts->fork_child = -1;
815 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
820 /* convert signal to corresponding name */
822 sync_pipe_signame(int sig)
825 static char sigmsg_buf[6+1+3+1];
834 sigmsg = "Interrupted";
842 sigmsg = "Illegal instruction";
846 sigmsg = "Trace trap";
854 sigmsg = "Arithmetic exception";
862 sigmsg = "Bus error";
866 sigmsg = "Segmentation violation";
869 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
870 Linux is POSIX compliant. These are not POSIX-defined signals ---
871 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
873 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
874 were omitted from POSIX.1 because their behavior is
875 implementation dependent and could not be adequately catego-
876 rized. Conforming implementations may deliver these sig-
877 nals, but must document the circumstances under which they
878 are delivered and note any restrictions concerning their
881 So we only check for SIGSYS on those systems that happen to
882 implement them (a system can be POSIX-compliant and implement
883 them, it's just that POSIX doesn't *require* a POSIX-compliant
884 system to implement them).
889 sigmsg = "Bad system call";
894 sigmsg = "Broken pipe";
898 sigmsg = "Alarm clock";
902 sigmsg = "Terminated";
906 /* XXX - returning a static buffer is ok in the context we use it here */
907 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
916 /* user wants to stop the capture run */
918 sync_pipe_stop(capture_options *capture_opts)
920 /* XXX - in which cases this will be 0? */
921 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
923 /* send the SIGUSR1 signal to close the capture child gracefully. */
924 kill(capture_opts->fork_child, SIGUSR1);
926 /* Win32 doesn't have the kill() system call, use the special signal pipe
927 instead to close the capture child gracefully. */
928 signal_pipe_capquit_to_child(capture_opts);
934 /* Ethereal has to exit, force the capture child to close */
936 sync_pipe_kill(capture_options *capture_opts)
938 /* XXX - in which cases this will be 0? */
939 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
941 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
943 /* XXX: this is not the preferred method of closing a process!
944 * the clean way would be getting the process id of the child process,
945 * then getting window handle hWnd of that process (using EnumChildWindows),
946 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
948 * Unfortunately, I don't know how to get the process id from the
949 * handle. OpenProcess will get an handle (not a window handle)
950 * from the process ID; it will not get a window handle from the
951 * process ID. (How could it? A process can have more than one
954 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
955 * running in the same console; that's not necessarily the case for
956 * us, as we might not be running in a console.
957 * And this also will require to have the process id.
959 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
964 #endif /* HAVE_LIBPCAP */