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>
83 #include "capture_sync.h"
84 #include "simple_dialog.h"
87 #include "capture-wpcap.h"
97 #include <process.h> /* For spawning child process */
100 /* Win32 needs the O_BINARY flag for open() */
107 static char *sync_pipe_signame(int);
111 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
112 static void sync_pipe_wait_for_child(capture_options *capture_opts);
114 /* Size of buffer to hold decimal representation of
115 signed/unsigned 64-bit int */
116 #define SP_DECISIZE 20
119 * Indications sent out on the sync pipe.
121 #define SP_FILE 'F' /* the name of the recently opened file */
122 #define SP_ERROR_MSG 'E' /* error message */
123 #define SP_PACKET_COUNT 'P' /* count of packets captured since last message */
124 #define SP_DROPS 'D' /* count of packets dropped in capture */
125 #define SP_QUIT 'Q' /* capture quit message (from parent to child) */
128 /* write a message to the recipient pipe in the standard format
129 (3 digit message length (excluding length and indicator field),
130 1 byte message indicator and the rest is the message) */
132 pipe_write_block(int pipe, char indicator, int len, const char *msg)
134 char lenbuf[3+1+1]; /* 3 digit len + indicator + zero terminator */
137 /*g_warning("write %d enter", pipe);*/
139 g_assert(len < 1000);
140 g_assert(indicator < '0' || indicator > '9');
142 /* write header (3 digit len + indicator) */
143 g_snprintf(lenbuf, 5, "%03u%c", len, indicator);
145 ret = write(pipe, lenbuf, strlen(lenbuf));
150 /* write value (if we have one) */
152 /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
153 ret = write(pipe, msg, len);
158 /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
161 /*g_warning("write %d leave", pipe);*/
165 /* read a message from the sending pipe in the standard format
166 (3 digit message length (excluding length and indicator field),
167 1 byte message indicator and the rest is the message) */
169 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
176 /* read header (3 digit len and indicator) */
180 newly = read(pipe, &header[offset], required);
183 /*g_warning("read %d header empty (capture closed)", pipe);*/
188 /*g_warning("read %d header error: %s", pipe, strerror(errno));*/
196 /* convert header values */
197 *indicator = header[3];
198 required = atoi(header);
200 /* only indicator with no value? */
202 /*g_warning("read %d indicator: %c empty value", pipe, *indicator);*/
206 g_assert(required <= len);
212 newly = read(pipe, &msg[offset], required);
215 /*g_warning("read %d value error, indicator: %u", pipe, *indicator);*/
223 /*g_warning("read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg);*/
228 sync_pipe_packet_count_to_parent(int packet_count)
230 char tmp[SP_DECISIZE+1+1];
232 g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
234 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);
236 pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
240 sync_pipe_filename_to_parent(const char *filename)
242 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_filename_to_parent: %s", filename);
244 pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
248 sync_pipe_errmsg_to_parent(const char *errmsg)
250 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
252 pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
256 sync_pipe_drops_to_parent(int drops)
258 char tmp[SP_DECISIZE+1+1];
261 g_snprintf(tmp, sizeof(tmp), "%d", drops);
263 g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_drops_to_parent: %s", tmp);
265 pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
272 signal_pipe_capquit_to_child(capture_options *capture_opts)
275 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
277 pipe_write_block(capture_opts->signal_pipe_fd, SP_QUIT, 0, NULL);
282 /* Add a string pointer to a NULL-terminated array of string pointers. */
284 sync_pipe_add_arg(char **args, int *argc, char *arg)
286 /* Grow the array; "*argc" currently contains the number of string
287 pointers, *not* counting the NULL pointer at the end, so we have
288 to add 2 in order to get the new size of the array, including the
289 new pointer and the terminating NULL pointer. */
290 args = g_realloc(args, (*argc + 2) * sizeof (char *));
292 /* Stuff the pointer into the penultimate element of the array, which
293 is the one at the index specified by "*argc". */
296 /* Now bump the count. */
299 /* We overwrite the NULL pointer; put it back right after the
307 /* Given a string, return a pointer to a quote-encapsulated version of
308 the string, so we can pass it as an argument with "spawnvp" even
309 if it contains blanks. */
311 sync_pipe_quote_encapsulate(const char *string)
313 char *encapsulated_string;
315 encapsulated_string = g_new(char, strlen(string) + 3);
316 sprintf(encapsulated_string, "\"%s\"", string);
317 return encapsulated_string;
323 #define ARGV_NUMBER_LEN 24
326 sync_pipe_start(capture_options *capture_opts) {
327 char ssnap[ARGV_NUMBER_LEN];
328 char scount[ARGV_NUMBER_LEN];
329 char sfilesize[ARGV_NUMBER_LEN];
330 char sfile_duration[ARGV_NUMBER_LEN];
331 char sring_num_files[ARGV_NUMBER_LEN];
332 char sautostop_files[ARGV_NUMBER_LEN];
333 char sautostop_filesize[ARGV_NUMBER_LEN];
334 char sautostop_duration[ARGV_NUMBER_LEN];
336 char buffer_size[ARGV_NUMBER_LEN];
337 char sync_pipe_fd[ARGV_NUMBER_LEN];
338 char signal_pipe_fd[ARGV_NUMBER_LEN];
341 char *savefilestring;
342 int signal_pipe[2]; /* pipe used to send messages from parent to child (currently only stop) */
348 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
349 int sync_pipe[2]; /* pipe used to send messages from child to parent */
352 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
353 #ifdef LOG_CAPTURE_VERBOSE
354 capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
357 capture_opts->fork_child = -1;
359 /* Allocate the string pointer array with enough space for the
360 terminating NULL pointer. */
362 argv = g_malloc(sizeof (char *));
365 /* Now add those arguments used on all platforms. */
366 argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
368 argv = sync_pipe_add_arg(argv, &argc, "-i");
369 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
371 if (capture_opts->has_snaplen) {
372 argv = sync_pipe_add_arg(argv, &argc, "-s");
373 sprintf(ssnap,"%d",capture_opts->snaplen);
374 argv = sync_pipe_add_arg(argv, &argc, ssnap);
377 if (capture_opts->linktype != -1) {
378 argv = sync_pipe_add_arg(argv, &argc, "-y");
379 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
380 sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts->linktype));
382 /* XXX - just treat it as a number */
383 sprintf(ssnap,"%d",capture_opts->linktype);
385 argv = sync_pipe_add_arg(argv, &argc, ssnap);
388 if(capture_opts->multi_files_on) {
389 if (capture_opts->has_autostop_filesize) {
390 argv = sync_pipe_add_arg(argv, &argc, "-b");
391 sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
392 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
395 if (capture_opts->has_file_duration) {
396 argv = sync_pipe_add_arg(argv, &argc, "-b");
397 sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
398 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
401 if (capture_opts->has_ring_num_files) {
402 argv = sync_pipe_add_arg(argv, &argc, "-b");
403 sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
404 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
407 if (capture_opts->has_autostop_files) {
408 argv = sync_pipe_add_arg(argv, &argc, "-a");
409 sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
410 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
413 if (capture_opts->has_autostop_filesize) {
414 argv = sync_pipe_add_arg(argv, &argc, "-a");
415 sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
416 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
420 if (capture_opts->has_autostop_packets) {
421 argv = sync_pipe_add_arg(argv, &argc, "-c");
422 sprintf(scount,"%d",capture_opts->autostop_packets);
423 argv = sync_pipe_add_arg(argv, &argc, scount);
426 if (capture_opts->has_autostop_duration) {
427 argv = sync_pipe_add_arg(argv, &argc, "-a");
428 sprintf(sautostop_duration,"duration:%d",capture_opts->autostop_duration);
429 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
432 if (!capture_opts->show_info) {
433 argv = sync_pipe_add_arg(argv, &argc, "-H");
436 if (!capture_opts->promisc_mode)
437 argv = sync_pipe_add_arg(argv, &argc, "-p");
440 /* Create a pipe for the child process */
441 /* (inrease this value if you have trouble while fast capture file switches) */
442 if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
443 /* Couldn't create the pipe between parent and child. */
444 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
450 /* Create a pipe for the parent process */
451 if(_pipe(signal_pipe, 512, O_BINARY) < 0) {
452 /* Couldn't create the signal pipe between parent and child. */
453 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
455 close(sync_pipe[PIPE_READ]);
456 close(sync_pipe[PIPE_WRITE]);
461 capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
463 argv = sync_pipe_add_arg(argv, &argc, "-B");
464 sprintf(buffer_size,"%d",capture_opts->buffer_size);
465 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
467 /* Convert font name to a quote-encapsulated string and pass to child */
468 argv = sync_pipe_add_arg(argv, &argc, "-m");
469 fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
470 argv = sync_pipe_add_arg(argv, &argc, fontstring);
472 /* Convert sync pipe write handle to a string and pass to child */
473 argv = sync_pipe_add_arg(argv, &argc, "-Z");
474 sprintf(sync_pipe_fd,"sync:%d",sync_pipe[PIPE_WRITE]);
475 argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
477 /* Convert signal pipe read handle to a string and pass to child */
478 argv = sync_pipe_add_arg(argv, &argc, "-Z");
479 sprintf(signal_pipe_fd,"signal:%d",signal_pipe[PIPE_READ]);
480 argv = sync_pipe_add_arg(argv, &argc, signal_pipe_fd);
482 /* Convert filter string to a quote delimited string and pass to child */
484 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
485 argv = sync_pipe_add_arg(argv, &argc, "-f");
486 filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
487 argv = sync_pipe_add_arg(argv, &argc, filterstring);
490 /* Convert save file name to a quote delimited string and pass to child */
491 savefilestring = NULL;
492 if(capture_opts->save_file) {
493 argv = sync_pipe_add_arg(argv, &argc, "-w");
494 savefilestring = sync_pipe_quote_encapsulate(capture_opts->save_file);
495 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
499 capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
502 g_free(filterstring);
505 g_free(savefilestring);
508 /* child own's the read side now, close our handle */
509 close(signal_pipe[PIPE_READ]);
511 if (pipe(sync_pipe) < 0) {
512 /* Couldn't create the pipe between parent and child. */
513 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
519 argv = sync_pipe_add_arg(argv, &argc, "-m");
520 argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
522 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
523 argv = sync_pipe_add_arg(argv, &argc, "-f");
524 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
527 if(capture_opts->save_file) {
528 argv = sync_pipe_add_arg(argv, &argc, "-w");
529 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
532 if ((capture_opts->fork_child = fork()) == 0) {
534 * Child process - run Ethereal with the right arguments to make
535 * it just pop up the live capture dialog box and capture with
536 * the specified capture parameters, writing to the specified file.
538 * args: -i interface specification
540 * -W file descriptor to write
541 * -c count to capture
544 * -f "filter expression"
547 dup(sync_pipe[PIPE_WRITE]);
548 close(sync_pipe[PIPE_READ]);
549 execvp(ethereal_path, argv);
550 snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
551 ethereal_path, strerror(errno));
552 sync_pipe_errmsg_to_parent(errmsg);
554 /* Exit with "_exit()", so that we don't close the connection
555 to the X server (and cause stuff buffered up by our parent but
556 not yet sent to be sent, as that stuff should only be sent by
562 /* Parent process - read messages from the child process over the
564 g_free(argv); /* free up arg array */
566 /* Close the write side of the pipe, so that only the child has it
567 open, and thus it completely closes, and thus returns to us
568 an EOF indication, if the child closes it (either deliberately
569 or by exiting abnormally). */
570 close(sync_pipe[PIPE_WRITE]);
572 if (capture_opts->fork_child == -1) {
573 /* We couldn't even create the child process. */
574 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
575 "Couldn't create child process: %s", strerror(errno));
576 close(sync_pipe[PIPE_READ]);
578 close(signal_pipe[PIPE_WRITE]);
583 /* we might wait for a moment till child is ready, so update screen now */
584 main_window_update();
586 /* We were able to set up to read the capture file;
587 arrange that our callback be called whenever it's possible
588 to read from the sync pipe, so that it's called when
589 the child process wants to tell us something. */
591 /* we have a running capture, now wait for the real capture filename */
592 pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts,
593 &capture_opts->fork_child, sync_pipe_input_cb);
598 /* There's stuff to read from the sync pipe, meaning the child has sent
599 us a message, or the sync pipe has closed, meaning the child has
600 closed it (perhaps because it exited). */
602 sync_pipe_input_cb(gint source, gpointer user_data)
604 capture_options *capture_opts = (capture_options *)user_data;
606 char buffer[BUFSIZE+1];
611 nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
613 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
615 /* The child has closed the sync pipe, meaning it's not going to be
616 capturing any more packets. Pick up its exit status, and
617 complain if it did anything other than exit with status 0. */
618 sync_pipe_wait_for_child(capture_opts);
621 close(capture_opts->signal_pipe_fd);
623 capture_input_closed(capture_opts);
629 if(!capture_input_new_file(capture_opts, buffer)) {
630 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
632 /* We weren't able to open the new capture file; user has been
633 alerted. Close the sync pipe. */
634 /* XXX - is it safe to close the pipe inside this callback? */
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 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\"", buffer);
652 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
653 /* the capture child will close the sync_pipe, nothing to do for now */
656 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", atoi(buffer), plurality(atoi(buffer), "", "s"));
657 cf_set_drops_known(capture_opts->cf, TRUE);
658 cf_set_drops(capture_opts->cf, atoi(buffer));
661 g_assert_not_reached();
669 /* the child process is going down, wait until it's completely terminated */
671 sync_pipe_wait_for_child(capture_options *capture_opts)
676 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
677 g_assert(capture_opts->fork_child != -1);
680 /* XXX - analyze the wait status and display more information
682 XXX - set "fork_child" to -1 if we find it exited? */
683 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
684 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
685 "Child capture process stopped unexpectedly");
688 if (wait(&wstatus) != -1) {
689 if (WIFEXITED(wstatus)) {
690 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
691 /* the child will inform us about errors through the sync_pipe, which will popup */
692 /* an error message, so don't popup another one */
694 /* XXX - if there are situations where the child won't send us such an error message, */
695 /* this should be fixed in the child and not here! */
696 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
697 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
698 "Child capture process exited: exit status %d",
699 WEXITSTATUS(wstatus));
701 } else if (WIFSTOPPED(wstatus)) {
702 /* It stopped, rather than exiting. "Should not happen." */
703 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
704 "Child capture process stopped: %s",
705 sync_pipe_signame(WSTOPSIG(wstatus)));
706 } else if (WIFSIGNALED(wstatus)) {
707 /* It died with a signal. */
708 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
709 "Child capture process died: %s%s",
710 sync_pipe_signame(WTERMSIG(wstatus)),
711 WCOREDUMP(wstatus) ? " - core dumped" : "");
713 /* What? It had to either have exited, or stopped, or died with
714 a signal; what happened here? */
715 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
716 "Child capture process died: wait status %#o", wstatus);
720 /* No more child process. */
721 capture_opts->fork_child = -1;
724 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
729 /* convert signal to corresponding name */
731 sync_pipe_signame(int sig)
734 static char sigmsg_buf[6+1+3+1];
743 sigmsg = "Interrupted";
751 sigmsg = "Illegal instruction";
755 sigmsg = "Trace trap";
763 sigmsg = "Arithmetic exception";
771 sigmsg = "Bus error";
775 sigmsg = "Segmentation violation";
778 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
779 Linux is POSIX compliant. These are not POSIX-defined signals ---
780 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
782 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
783 were omitted from POSIX.1 because their behavior is
784 implementation dependent and could not be adequately catego-
785 rized. Conforming implementations may deliver these sig-
786 nals, but must document the circumstances under which they
787 are delivered and note any restrictions concerning their
790 So we only check for SIGSYS on those systems that happen to
791 implement them (a system can be POSIX-compliant and implement
792 them, it's just that POSIX doesn't *require* a POSIX-compliant
793 system to implement them).
798 sigmsg = "Bad system call";
803 sigmsg = "Broken pipe";
807 sigmsg = "Alarm clock";
811 sigmsg = "Terminated";
815 sprintf(sigmsg_buf, "Signal %d", sig);
824 /* user wants to stop the capture run */
826 sync_pipe_stop(capture_options *capture_opts)
828 /* XXX - in which cases this will be 0? */
829 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
831 /* send the SIGUSR1 signal to close the capture child gracefully. */
832 kill(capture_opts->fork_child, SIGUSR1);
834 /* Win32 doesn't have the kill() system call, use the special signal pipe
835 instead to close the capture child gracefully. */
836 signal_pipe_capquit_to_child(capture_opts);
842 /* Ethereal has to exit, force the capture child to close */
844 sync_pipe_kill(capture_options *capture_opts)
846 /* XXX - in which cases this will be 0? */
847 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
849 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
851 /* XXX: this is not the preferred method of closing a process!
852 * the clean way would be getting the process id of the child process,
853 * then getting window handle hWnd of that process (using EnumChildWindows),
854 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
856 * Unfortunately, I don't know how to get the process id from the
857 * handle. OpenProcess will get an handle (not a window handle)
858 * from the process ID; it will not get a window handle from the
859 * process ID. (How could it? A process can have more than one
862 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
863 * running in the same console; that's not necessarily the case for
864 * us, as we might not be running in a console.
865 * And this also will require to have the process id.
867 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
872 #endif /* HAVE_LIBPCAP */