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 const 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(const char **args, int *argc, const 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( (gpointer) 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
308 #define ARGV_NUMBER_LEN 24
311 sync_pipe_start(capture_options *capture_opts) {
312 char ssnap[ARGV_NUMBER_LEN];
313 char scount[ARGV_NUMBER_LEN];
314 char sfilesize[ARGV_NUMBER_LEN];
315 char sfile_duration[ARGV_NUMBER_LEN];
316 char sring_num_files[ARGV_NUMBER_LEN];
317 char sautostop_files[ARGV_NUMBER_LEN];
318 char sautostop_filesize[ARGV_NUMBER_LEN];
319 char sautostop_duration[ARGV_NUMBER_LEN];
321 char buffer_size[ARGV_NUMBER_LEN];
322 char sync_pipe_fd[ARGV_NUMBER_LEN];
323 char signal_pipe_fd[ARGV_NUMBER_LEN];
326 char *savefilestring;
327 int signal_pipe[2]; /* pipe used to send messages from parent to child (currently only stop) */
333 enum PIPES { PIPE_READ, PIPE_WRITE }; /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
334 int sync_pipe[2]; /* pipe used to send messages from child to parent */
337 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
338 #ifdef LOG_CAPTURE_VERBOSE
339 capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
342 capture_opts->fork_child = -1;
344 /* Allocate the string pointer array with enough space for the
345 terminating NULL pointer. */
347 argv = g_malloc(sizeof (char *));
350 /* Now add those arguments used on all platforms. */
351 argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
353 argv = sync_pipe_add_arg(argv, &argc, "-i");
354 argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
356 if (capture_opts->has_snaplen) {
357 argv = sync_pipe_add_arg(argv, &argc, "-s");
358 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
359 argv = sync_pipe_add_arg(argv, &argc, ssnap);
362 if (capture_opts->linktype != -1) {
363 argv = sync_pipe_add_arg(argv, &argc, "-y");
364 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
365 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",pcap_datalink_val_to_name(capture_opts->linktype));
367 /* XXX - just treat it as a number */
368 g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
370 argv = sync_pipe_add_arg(argv, &argc, ssnap);
373 if(capture_opts->multi_files_on) {
374 if (capture_opts->has_autostop_filesize) {
375 argv = sync_pipe_add_arg(argv, &argc, "-b");
376 g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
377 argv = sync_pipe_add_arg(argv, &argc, sfilesize);
380 if (capture_opts->has_file_duration) {
381 argv = sync_pipe_add_arg(argv, &argc, "-b");
382 g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
383 argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
386 if (capture_opts->has_ring_num_files) {
387 argv = sync_pipe_add_arg(argv, &argc, "-b");
388 g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
389 argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
392 if (capture_opts->has_autostop_files) {
393 argv = sync_pipe_add_arg(argv, &argc, "-a");
394 g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
395 argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
398 if (capture_opts->has_autostop_filesize) {
399 argv = sync_pipe_add_arg(argv, &argc, "-a");
400 g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
401 argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
405 if (capture_opts->has_autostop_packets) {
406 argv = sync_pipe_add_arg(argv, &argc, "-c");
407 g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
408 argv = sync_pipe_add_arg(argv, &argc, scount);
411 if (capture_opts->has_autostop_duration) {
412 argv = sync_pipe_add_arg(argv, &argc, "-a");
413 g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
414 argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
417 if (!capture_opts->show_info) {
418 argv = sync_pipe_add_arg(argv, &argc, "-H");
421 if (!capture_opts->promisc_mode)
422 argv = sync_pipe_add_arg(argv, &argc, "-p");
425 /* Create a pipe for the child process */
426 /* (inrease this value if you have trouble while fast capture file switches) */
427 if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
428 /* Couldn't create the pipe between parent and child. */
429 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
431 g_free( (gpointer) argv);
435 /* Create a pipe for the parent process */
436 if(_pipe(signal_pipe, 512, O_BINARY) < 0) {
437 /* Couldn't create the signal pipe between parent and child. */
438 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
440 close(sync_pipe[PIPE_READ]);
441 close(sync_pipe[PIPE_WRITE]);
442 g_free( (gpointer) argv);
446 capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
448 argv = sync_pipe_add_arg(argv, &argc, "-B");
449 g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
450 argv = sync_pipe_add_arg(argv, &argc, buffer_size);
452 /* Convert font name to a quote-encapsulated string and pass to child */
453 argv = sync_pipe_add_arg(argv, &argc, "-m");
454 fontstring = g_strdup_printf("\"%s\"", prefs.PREFS_GUI_FONT_NAME);
455 argv = sync_pipe_add_arg(argv, &argc, fontstring);
457 /* Convert sync pipe write handle to a string and pass to child */
458 argv = sync_pipe_add_arg(argv, &argc, "-Z");
459 g_snprintf(sync_pipe_fd, ARGV_NUMBER_LEN, "sync:%d",sync_pipe[PIPE_WRITE]);
460 argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
462 /* Convert signal pipe read handle to a string and pass to child */
463 argv = sync_pipe_add_arg(argv, &argc, "-Z");
464 g_snprintf(signal_pipe_fd, ARGV_NUMBER_LEN, "signal:%d",signal_pipe[PIPE_READ]);
465 argv = sync_pipe_add_arg(argv, &argc, signal_pipe_fd);
467 /* Convert filter string to a quote delimited string and pass to child */
469 if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
470 argv = sync_pipe_add_arg(argv, &argc, "-f");
471 filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
472 argv = sync_pipe_add_arg(argv, &argc, filterstring);
475 /* Convert save file name to a quote delimited string and pass to child */
476 savefilestring = NULL;
477 if(capture_opts->save_file) {
478 argv = sync_pipe_add_arg(argv, &argc, "-w");
479 savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
480 argv = sync_pipe_add_arg(argv, &argc, savefilestring);
484 capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
487 g_free(filterstring);
490 g_free(savefilestring);
493 /* child own's the read side now, close our handle */
494 close(signal_pipe[PIPE_READ]);
496 if (pipe(sync_pipe) < 0) {
497 /* Couldn't create the pipe between parent and child. */
498 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
504 argv = sync_pipe_add_arg(argv, &argc, "-m");
505 argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
507 if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
508 argv = sync_pipe_add_arg(argv, &argc, "-f");
509 argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
512 if(capture_opts->save_file) {
513 argv = sync_pipe_add_arg(argv, &argc, "-w");
514 argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
517 if ((capture_opts->fork_child = fork()) == 0) {
519 * Child process - run Ethereal with the right arguments to make
520 * it just pop up the live capture dialog box and capture with
521 * the specified capture parameters, writing to the specified file.
523 * args: -i interface specification
525 * -W file descriptor to write
526 * -c count to capture
529 * -f "filter expression"
532 dup(sync_pipe[PIPE_WRITE]);
533 close(sync_pipe[PIPE_READ]);
534 execvp(ethereal_path, argv);
535 g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
536 ethereal_path, strerror(errno));
537 sync_pipe_errmsg_to_parent(errmsg);
539 /* Exit with "_exit()", so that we don't close the connection
540 to the X server (and cause stuff buffered up by our parent but
541 not yet sent to be sent, as that stuff should only be sent by
547 /* Parent process - read messages from the child process over the
549 g_free( (gpointer) argv); /* free up arg array */
551 /* Close the write side of the pipe, so that only the child has it
552 open, and thus it completely closes, and thus returns to us
553 an EOF indication, if the child closes it (either deliberately
554 or by exiting abnormally). */
555 close(sync_pipe[PIPE_WRITE]);
557 if (capture_opts->fork_child == -1) {
558 /* We couldn't even create the child process. */
559 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
560 "Couldn't create child process: %s", strerror(errno));
561 close(sync_pipe[PIPE_READ]);
563 close(signal_pipe[PIPE_WRITE]);
568 /* we might wait for a moment till child is ready, so update screen now */
569 main_window_update();
571 /* We were able to set up to read the capture file;
572 arrange that our callback be called whenever it's possible
573 to read from the sync pipe, so that it's called when
574 the child process wants to tell us something. */
576 /* we have a running capture, now wait for the real capture filename */
577 pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts,
578 &capture_opts->fork_child, sync_pipe_input_cb);
583 /* There's stuff to read from the sync pipe, meaning the child has sent
584 us a message, or the sync pipe has closed, meaning the child has
585 closed it (perhaps because it exited). */
587 sync_pipe_input_cb(gint source, gpointer user_data)
589 capture_options *capture_opts = (capture_options *)user_data;
591 char buffer[BUFSIZE+1];
596 nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
598 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
600 /* The child has closed the sync pipe, meaning it's not going to be
601 capturing any more packets. Pick up its exit status, and
602 complain if it did anything other than exit with status 0. */
603 sync_pipe_wait_for_child(capture_opts);
606 close(capture_opts->signal_pipe_fd);
608 capture_input_closed(capture_opts);
614 if(!capture_input_new_file(capture_opts, buffer)) {
615 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
617 /* We weren't able to open the new capture file; user has been
618 alerted. Close the sync pipe. */
619 /* XXX - is it safe to close the pipe inside this callback? */
622 /* the child has send us a filename which we couldn't open.
623 this probably means, the child is creating files faster than we can handle it.
624 this should only be the case for very fast file switches
625 we can't do much more than telling the child to stop
626 (this is the emergency brake if user e.g. wants to switch files every second) */
627 sync_pipe_stop(capture_opts);
630 case SP_PACKET_COUNT:
631 nread = atoi(buffer);
632 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
633 capture_input_new_packets(capture_opts, nread);
636 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\"", buffer);
637 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
638 /* the capture child will close the sync_pipe, nothing to do for now */
641 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", atoi(buffer), plurality(atoi(buffer), "", "s"));
642 cf_set_drops_known(capture_opts->cf, TRUE);
643 cf_set_drops(capture_opts->cf, atoi(buffer));
646 g_assert_not_reached();
654 /* the child process is going down, wait until it's completely terminated */
656 sync_pipe_wait_for_child(capture_options *capture_opts)
661 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
662 g_assert(capture_opts->fork_child != -1);
665 /* XXX - analyze the wait status and display more information
667 XXX - set "fork_child" to -1 if we find it exited? */
668 if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
669 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
670 "Child capture process stopped unexpectedly");
673 if (wait(&wstatus) != -1) {
674 if (WIFEXITED(wstatus)) {
675 /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
676 /* the child will inform us about errors through the sync_pipe, which will popup */
677 /* an error message, so don't popup another one */
679 /* XXX - if there are situations where the child won't send us such an error message, */
680 /* this should be fixed in the child and not here! */
681 if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
682 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
683 "Child capture process exited: exit status %d",
684 WEXITSTATUS(wstatus));
686 } else if (WIFSTOPPED(wstatus)) {
687 /* It stopped, rather than exiting. "Should not happen." */
688 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
689 "Child capture process stopped: %s",
690 sync_pipe_signame(WSTOPSIG(wstatus)));
691 } else if (WIFSIGNALED(wstatus)) {
692 /* It died with a signal. */
693 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
694 "Child capture process died: %s%s",
695 sync_pipe_signame(WTERMSIG(wstatus)),
696 WCOREDUMP(wstatus) ? " - core dumped" : "");
698 /* What? It had to either have exited, or stopped, or died with
699 a signal; what happened here? */
700 simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
701 "Child capture process died: wait status %#o", wstatus);
705 /* No more child process. */
706 capture_opts->fork_child = -1;
709 g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
714 /* convert signal to corresponding name */
716 sync_pipe_signame(int sig)
719 static char sigmsg_buf[6+1+3+1];
728 sigmsg = "Interrupted";
736 sigmsg = "Illegal instruction";
740 sigmsg = "Trace trap";
748 sigmsg = "Arithmetic exception";
756 sigmsg = "Bus error";
760 sigmsg = "Segmentation violation";
763 /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
764 Linux is POSIX compliant. These are not POSIX-defined signals ---
765 ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
767 ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
768 were omitted from POSIX.1 because their behavior is
769 implementation dependent and could not be adequately catego-
770 rized. Conforming implementations may deliver these sig-
771 nals, but must document the circumstances under which they
772 are delivered and note any restrictions concerning their
775 So we only check for SIGSYS on those systems that happen to
776 implement them (a system can be POSIX-compliant and implement
777 them, it's just that POSIX doesn't *require* a POSIX-compliant
778 system to implement them).
783 sigmsg = "Bad system call";
788 sigmsg = "Broken pipe";
792 sigmsg = "Alarm clock";
796 sigmsg = "Terminated";
800 /* XXX - returning a static buffer is ok in the context we use it here */
801 g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
810 /* user wants to stop the capture run */
812 sync_pipe_stop(capture_options *capture_opts)
814 /* XXX - in which cases this will be 0? */
815 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
817 /* send the SIGUSR1 signal to close the capture child gracefully. */
818 kill(capture_opts->fork_child, SIGUSR1);
820 /* Win32 doesn't have the kill() system call, use the special signal pipe
821 instead to close the capture child gracefully. */
822 signal_pipe_capquit_to_child(capture_opts);
828 /* Ethereal has to exit, force the capture child to close */
830 sync_pipe_kill(capture_options *capture_opts)
832 /* XXX - in which cases this will be 0? */
833 if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
835 kill(capture_opts->fork_child, SIGTERM); /* SIGTERM so it can clean up if necessary */
837 /* XXX: this is not the preferred method of closing a process!
838 * the clean way would be getting the process id of the child process,
839 * then getting window handle hWnd of that process (using EnumChildWindows),
840 * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0)
842 * Unfortunately, I don't know how to get the process id from the
843 * handle. OpenProcess will get an handle (not a window handle)
844 * from the process ID; it will not get a window handle from the
845 * process ID. (How could it? A process can have more than one
848 * Hint: GenerateConsoleCtrlEvent() will only work if both processes are
849 * running in the same console; that's not necessarily the case for
850 * us, as we might not be running in a console.
851 * And this also will require to have the process id.
853 TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
858 #endif /* HAVE_LIBPCAP */