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 argv = sync_pipe_add_arg(argv, &argc, "-i");
338 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
340 if (capture_opts->has_snaplen) {
341 argv = sync_pipe_add_arg(argv, &argc, "-s");
342 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
343 argv = sync_pipe_add_arg(argv, &argc, ssnap);
346 if (capture_opts->linktype != -1) {
347 argv = sync_pipe_add_arg(argv, &argc, "-y");
348 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
349 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",pcap_datalink_val_to_name(capture_opts->linktype));
351 /* XXX - just treat it as a number */
352 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
354 argv = sync_pipe_add_arg(argv, &argc, ssnap);
357 if(capture_opts->multi_files_on) {
358 if (capture_opts->has_autostop_filesize) {
359 argv = sync_pipe_add_arg(argv, &argc, "-b");
360 g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
361 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
364 if (capture_opts->has_file_duration) {
365 argv = sync_pipe_add_arg(argv, &argc, "-b");
366 g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
367 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
370 if (capture_opts->has_ring_num_files) {
371 argv = sync_pipe_add_arg(argv, &argc, "-b");
372 g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
373 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
376 if (capture_opts->has_autostop_files) {
377 argv = sync_pipe_add_arg(argv, &argc, "-a");
378 g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
379 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
382 if (capture_opts->has_autostop_filesize) {
383 argv = sync_pipe_add_arg(argv, &argc, "-a");
384 g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
385 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
389 if (capture_opts->has_autostop_packets) {
390 argv = sync_pipe_add_arg(argv, &argc, "-c");
391 g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
392 argv = sync_pipe_add_arg(argv, &argc, scount);
395 if (capture_opts->has_autostop_duration) {
396 argv = sync_pipe_add_arg(argv, &argc, "-a");
397 g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
398 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
401 if (!capture_opts->promisc_mode)
402 argv = sync_pipe_add_arg(argv, &argc, "-p");
404 /* dumpcap should be running in capture child mode (hidden feature) */
406 argv = sync_pipe_add_arg(argv, &argc, "-Z");
409 /* take ethereal's absolute program path and replace ethereal with dumpcap */
410 exename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "dumpcap",
414 argv = sync_pipe_add_arg(argv, &argc, "-B");
415 g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
416 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
418 /* Convert filter string to a quote delimited string and pass to child */
420 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
421 argv = sync_pipe_add_arg(argv, &argc, "-f");
422 filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
423 argv = sync_pipe_add_arg(argv, &argc, filterstring);
426 /* Convert save file name to a quote delimited string and pass to child */
427 savefilestring = NULL;
428 if(capture_opts->save_file) {
429 argv = sync_pipe_add_arg(argv, &argc, "-w");
430 savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
431 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
434 /* init SECURITY_ATTRIBUTES */
435 sa.nLength = sizeof(SECURITY_ATTRIBUTES);
436 sa.bInheritHandle = TRUE;
437 sa.lpSecurityDescriptor = NULL;
439 /* Create a pipe for the child process */
440 /* (inrease this value if you have trouble while fast capture file switches) */
441 if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
442 /* Couldn't create the pipe between parent and child. */
443 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
445 g_free( (gpointer) argv);
449 /* Create a pipe for the parent process */
450 if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
451 /* Couldn't create the signal pipe between parent and child. */
452 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
454 CloseHandle(sync_pipe_read);
455 CloseHandle(sync_pipe_write);
456 g_free( (gpointer) argv);
460 /* init STARTUPINFO */
461 memset(&si, 0, sizeof(si));
464 si.dwFlags = STARTF_USESHOWWINDOW;
465 si.wShowWindow = SW_SHOW;
467 si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
468 si.wShowWindow = SW_HIDE; /* this hides the console window */
469 si.hStdInput = signal_pipe_read;
470 si.hStdOutput = sync_pipe_write;
471 si.hStdError = sync_pipe_write;
474 g_string_append(args, exename);
476 /* convert args array into a single string */
477 /* XXX - could change sync_pipe_add_arg() instead */
478 /* there is a drawback here: the length is internally limited to 1024 bytes */
479 for(i=0; argv[i] != 0; i++) {
480 g_string_append_c(args, ' ');
481 g_string_append(args, argv[i]);
485 if(!CreateProcess(NULL, args->str, NULL, NULL, TRUE,
486 CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi)) {
487 g_error("couldn't open dumpcap.exe!");
489 capture_opts->fork_child = (int) pi.hProcess;
490 g_string_free(args, TRUE);
492 /* associate the operating system filehandle to a C run-time file handle */
493 /* (good file handle infos at: http://www.flounder.com/handles.htm) */
494 sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
496 /* associate the operating system filehandle to a C run-time file handle */
497 capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
500 g_free(filterstring);
503 g_free(savefilestring);
506 /* child own's the read side now, close our handle */
507 CloseHandle(signal_pipe_read);
509 if (pipe(sync_pipe) < 0) {
510 /* Couldn't create the pipe between parent and child. */
511 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
517 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
518 argv = sync_pipe_add_arg(argv, &argc, "-f");
519 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
522 if(capture_opts->save_file) {
523 argv = sync_pipe_add_arg(argv, &argc, "-w");
524 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
527 if ((capture_opts->fork_child = fork()) == 0) {
529 * Child process - run Ethereal with the right arguments to make
530 * it just pop up the live capture dialog box and capture with
531 * the specified capture parameters, writing to the specified file.
533 * args: -i interface specification
535 * -c count to capture
538 * -f "filter expression"
541 dup(sync_pipe[PIPE_WRITE]);
542 eth_close(sync_pipe[PIPE_READ]);
543 execvp(exename, argv);
544 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
545 exename, strerror(errno));
546 sync_pipe_errmsg_to_parent(errmsg);
548 /* Exit with "_exit()", so that we don't close the connection
549 to the X server (and cause stuff buffered up by our parent but
550 not yet sent to be sent, as that stuff should only be sent by
555 sync_pipe_read_fd = sync_pipe[PIPE_READ];
560 /* Parent process - read messages from the child process over the
562 g_free( (gpointer) argv); /* free up arg array */
564 /* Close the write side of the pipe, so that only the child has it
565 open, and thus it completely closes, and thus returns to us
566 an EOF indication, if the child closes it (either deliberately
567 or by exiting abnormally). */
569 CloseHandle(sync_pipe_write);
571 eth_close(sync_pipe[PIPE_WRITE]);
574 if (capture_opts->fork_child == -1) {
575 /* We couldn't even create the child process. */
576 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
577 "Couldn't create child process: %s", strerror(errno));
578 eth_close(sync_pipe_read_fd);
580 eth_close(capture_opts->signal_pipe_write_fd);
585 /* we might wait for a moment till child is ready, so update screen now */
586 main_window_update();
588 /* We were able to set up to read the capture file;
589 arrange that our callback be called whenever it's possible
590 to read from the sync pipe, so that it's called when
591 the child process wants to tell us something. */
593 /* we have a running capture, now wait for the real capture filename */
594 pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts,
595 &capture_opts->fork_child, sync_pipe_input_cb);
600 /* There's stuff to read from the sync pipe, meaning the child has sent
601 us a message, or the sync pipe has closed, meaning the child has
602 closed it (perhaps because it exited). */
604 sync_pipe_input_cb(gint source, gpointer user_data)
606 capture_options *capture_opts = (capture_options *)user_data;
607 char buffer[SP_MAX_MSG_LEN+1];
612 nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
614 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
616 /* The child has closed the sync pipe, meaning it's not going to be
617 capturing any more packets. Pick up its exit status, and
618 complain if it did anything other than exit with status 0. */
619 sync_pipe_wait_for_child(capture_opts);
622 eth_close(capture_opts->signal_pipe_write_fd);
624 capture_input_closed(capture_opts);
630 if(!capture_input_new_file(capture_opts, buffer)) {
631 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
633 /* We weren't able to open the new capture file; user has been
634 alerted. Close the sync pipe. */
637 /* the child has send us a filename which we couldn't open.
638 this probably means, the child is creating files faster than we can handle it.
639 this should only be the case for very fast file switches
640 we can't do much more than telling the child to stop
641 (this is the "emergency brake" if user e.g. wants to switch files every second) */
642 sync_pipe_stop(capture_opts);
645 case SP_PACKET_COUNT:
646 nread = atoi(buffer);
647 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
648 capture_input_new_packets(capture_opts, nread);
651 capture_input_error_message(capture_opts, buffer);
652 /* the capture child will close the sync_pipe, nothing to do for now */
655 capture_input_drops(capture_opts, atoi(buffer));
658 g_assert_not_reached();
666 /* the child process is going down, wait until it's completely terminated */
668 sync_pipe_wait_for_child(capture_options *capture_opts)
673 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
674 g_assert(capture_opts->fork_child != -1);
677 /* XXX - analyze the wait status and display more information
679 XXX - set "fork_child" to -1 if we find it exited? */
680 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
681 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
682 "Child capture process stopped unexpectedly");
685 if (wait(&wstatus) != -1) {
686 if (WIFEXITED(wstatus)) {
687 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
688 /* the child will inform us about errors through the sync_pipe, which will popup */
689 /* an error message, so don't popup another one */
691 /* XXX - if there are situations where the child won't send us such an error message, */
692 /* this should be fixed in the child and not here! */
693 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
694 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
695 "Child capture process exited: exit status %d",
696 WEXITSTATUS(wstatus));
698 } else if (WIFSTOPPED(wstatus)) {
699 /* It stopped, rather than exiting. "Should not happen." */
700 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
701 "Child capture process stopped: %s",
702 sync_pipe_signame(WSTOPSIG(wstatus)));
703 } else if (WIFSIGNALED(wstatus)) {
704 /* It died with a signal. */
705 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
706 "Child capture process died: %s%s",
707 sync_pipe_signame(WTERMSIG(wstatus)),
708 WCOREDUMP(wstatus) ? " - core dumped" : "");
710 /* What? It had to either have exited, or stopped, or died with
711 a signal; what happened here? */
712 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
713 "Child capture process died: wait status %#o", wstatus);
717 /* No more child process. */
718 capture_opts->fork_child = -1;
721 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
726 /* convert signal to corresponding name */
728 sync_pipe_signame(int sig)
731 static char sigmsg_buf[6+1+3+1];
740 sigmsg = "Interrupted";
748 sigmsg = "Illegal instruction";
752 sigmsg = "Trace trap";
760 sigmsg = "Arithmetic exception";
768 sigmsg = "Bus error";
772 sigmsg = "Segmentation violation";
775 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
776 Linux is POSIX compliant. These are not POSIX-defined signals ---
777 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
779 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
780 were omitted from POSIX.1 because their behavior is
781 implementation dependent and could not be adequately catego-
782 rized. Conforming implementations may deliver these sig-
783 nals, but must document the circumstances under which they
784 are delivered and note any restrictions concerning their
787 So we only check for SIGSYS on those systems that happen to
788 implement them (a system can be POSIX-compliant and implement
789 them, it's just that POSIX doesn't *require* a POSIX-compliant
790 system to implement them).
795 sigmsg = "Bad system call";
800 sigmsg = "Broken pipe";
804 sigmsg = "Alarm clock";
808 sigmsg = "Terminated";
812 /* XXX - returning a static buffer is ok in the context we use it here */
813 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
822 /* user wants to stop the capture run */
824 sync_pipe_stop(capture_options *capture_opts)
826 /* XXX - in which cases this will be 0? */
827 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
829 /* send the SIGUSR1 signal to close the capture child gracefully. */
830 kill(capture_opts->fork_child, SIGUSR1);
832 /* Win32 doesn't have the kill() system call, use the special signal pipe
833 instead to close the capture child gracefully. */
834 signal_pipe_capquit_to_child(capture_opts);
840 /* Ethereal has to exit, force the capture child to close */
842 sync_pipe_kill(capture_options *capture_opts)
844 /* XXX - in which cases this will be 0? */
845 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
847 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
849 /* XXX: this is not the preferred method of closing a process!
850 * the clean way would be getting the process id of the child process,
851 * then getting window handle hWnd of that process (using EnumChildWindows),
852 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
854 * Unfortunately, I don't know how to get the process id from the
855 * handle. OpenProcess will get an handle (not a window handle)
856 * from the process ID; it will not get a window handle from the
857 * process ID. (How could it? A process can have more than one
860 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
861 * running in the same console; that's not necessarily the case for
862 * us, as we might not be running in a console.
863 * And this also will require to have the process id.
865 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
870 #endif /* HAVE_LIBPCAP */