Clean up white space, and tweak a comment slightly ("message" in the
[obnox/wireshark/wip.git] / capture_sync.c
1 /* capture_sync.c
2  * Synchronisation between Ethereal capture parent and child instances
3  *
4  * $Id$
5  *
6  * Ethereal - Network traffic analyzer
7  * By Gerald Combs <gerald@ethereal.com>
8  * Copyright 1998 Gerald Combs
9  *
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.
14  *
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.
19  *
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.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #ifdef HAVE_LIBPCAP
30
31 #include <pcap.h>
32
33 #include <glib.h>
34 #include <stdio.h>
35 #include <ctype.h>
36 #include <string.h>
37
38 #ifdef HAVE_UNISTD_H
39 #include <unistd.h>
40 #endif
41
42 #include <signal.h>
43
44 #ifdef HAVE_SYS_WAIT_H
45 # include <sys/wait.h>
46 #endif
47
48 #ifndef _WIN32
49 /*
50  * Define various POSIX macros (and, in the case of WCOREDUMP, non-POSIX
51  * macros) on UNIX systems that don't have them.
52  */
53 #ifndef WIFEXITED
54 # define WIFEXITED(status)      (((status) & 0177) == 0)
55 #endif
56 #ifndef WIFSTOPPED
57 # define WIFSTOPPED(status)     (((status) & 0177) == 0177)
58 #endif
59 #ifndef WIFSIGNALED
60 # define WIFSIGNALED(status)    (!WIFSTOPPED(status) && !WIFEXITED(status))
61 #endif
62 #ifndef WEXITSTATUS
63 # define WEXITSTATUS(status)    ((status) >> 8)
64 #endif
65 #ifndef WTERMSIG
66 # define WTERMSIG(status)       ((status) & 0177)
67 #endif
68 #ifndef WCOREDUMP
69 # define WCOREDUMP(status)      ((status) & 0200)
70 #endif
71 #ifndef WSTOPSIG
72 # define WSTOPSIG(status)       ((status) >> 8)
73 #endif
74 #endif /* _WIN32 */
75
76 #include <epan/packet.h>
77 #include <epan/prefs.h>
78
79 #include "globals.h"
80 #include "file.h"
81
82 #include "capture.h"
83 #include "capture_sync.h"
84 #include "simple_dialog.h"
85
86 #ifdef _WIN32
87 #include "capture-wpcap.h"
88 #endif
89 #include "ui_util.h"
90
91 #ifdef HAVE_IO_H
92 # include <io.h>
93 #endif
94
95 #ifdef _WIN32
96 #include <process.h>    /* For spawning child process */
97 #endif
98
99 /* Win32 needs the O_BINARY flag for open() */
100 #ifndef O_BINARY
101 #define O_BINARY        0
102 #endif
103
104
105 #ifndef _WIN32
106 static char *sync_pipe_signame(int);
107 #endif
108
109
110 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
111 static void sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report);
112
113 /* Size of buffer to hold decimal representation of
114    signed/unsigned 64-bit int */
115 #define SP_DECISIZE 20
116
117 /*
118  * Indications sent out on the sync pipe.
119  */
120 #define SP_CAPSTART     ';'     /* capture start message */
121 #define SP_PACKET_COUNT '*'     /* followed by count of packets captured since last message */
122 #define SP_ERROR_MSG    '!'     /* followed by length of error message that follows */
123 #define SP_DROPS        '#'     /* followed by count of packets dropped in capture */
124 #define SP_FILE         ':'     /* followed by length of the name of the last opened file that follows */
125
126
127
128 void
129 sync_pipe_capstart_to_parent(void)
130 {
131     static const char capstart_msg = SP_CAPSTART;
132
133     write(1, &capstart_msg, 1);
134 }
135
136 void
137 sync_pipe_packet_count_to_parent(int packet_count)
138 {
139     char tmp[SP_DECISIZE+1+1];
140     sprintf(tmp, "%d%c", packet_count, SP_PACKET_COUNT);
141     write(1, tmp, strlen(tmp));
142 }
143
144 void
145 sync_pipe_filename_to_parent(const char *filename)
146 {
147     int msglen = strlen(filename);
148     char lenbuf[SP_DECISIZE+1+1];
149
150     sprintf(lenbuf, "%u%c", msglen, SP_FILE);
151     write(1, lenbuf, strlen(lenbuf));
152     write(1, filename, msglen);
153 }
154
155 void
156 sync_pipe_errmsg_to_parent(const char *errmsg)
157 {
158     int msglen = strlen(errmsg);
159     char lenbuf[SP_DECISIZE+1+1];
160
161     sprintf(lenbuf, "%u%c", msglen, SP_ERROR_MSG);
162     write(1, lenbuf, strlen(lenbuf));
163     write(1, errmsg, msglen);
164 }
165
166 void
167 sync_pipe_drops_to_parent(int drops)
168 {
169         char tmp[SP_DECISIZE+1+1];
170         sprintf(tmp, "%d%c", drops, SP_DROPS);
171         write(1, tmp, strlen(tmp));
172 }
173
174
175 /* Add a string pointer to a NULL-terminated array of string pointers. */
176 static char **
177 sync_pipe_add_arg(char **args, int *argc, char *arg)
178 {
179   /* Grow the array; "*argc" currently contains the number of string
180      pointers, *not* counting the NULL pointer at the end, so we have
181      to add 2 in order to get the new size of the array, including the
182      new pointer and the terminating NULL pointer. */
183   args = g_realloc(args, (*argc + 2) * sizeof (char *));
184
185   /* Stuff the pointer into the penultimate element of the array, which
186      is the one at the index specified by "*argc". */
187   args[*argc] = arg;
188
189   /* Now bump the count. */
190   (*argc)++;
191
192   /* We overwrite the NULL pointer; put it back right after the
193      element we added. */
194   args[*argc] = NULL;
195
196   return args;
197 }
198
199 #ifdef _WIN32
200 /* Given a string, return a pointer to a quote-encapsulated version of
201    the string, so we can pass it as an argument with "spawnvp" even
202    if it contains blanks. */
203 char *
204 sync_pipe_quote_encapsulate(const char *string)
205 {
206   char *encapsulated_string;
207
208   encapsulated_string = g_new(char, strlen(string) + 3);
209   sprintf(encapsulated_string, "\"%s\"", string);
210   return encapsulated_string;
211 }
212 #endif
213
214
215
216 gboolean
217 sync_pipe_do_capture(capture_options *capture_opts, gboolean is_tempfile) {
218     guint byte_count;
219     int  i;
220     guchar  c;
221     char *msg;
222     char ssnap[24];
223     char scount[24];                        /* need a constant for len of numbers */
224     char sfilesize[24];             /* need a constant for len of numbers */
225     char sfile_duration[24];        /* need a constant for len of numbers */
226     char sring_num_files[24];       /* need a constant for len of numbers */
227     char sautostop_files[24];       /* need a constant for len of numbers */
228     char sautostop_filesize[24];        /* need a constant for len of numbers */
229     char sautostop_duration[24];        /* need a constant for len of numbers */
230 #ifndef _WIN32
231     char errmsg[1024+1];
232 #endif
233     int argc;
234     char **argv;
235 #ifdef _WIN32
236     char sync_pipe_fd[24];
237     char *fontstring;
238     char *filterstring;
239 #endif
240     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
241     int sync_pipe[2];                       /* pipes used to sync between instances */
242
243
244     /*g_warning("sync_pipe_do_capture");
245     capture_opts_info(capture_opts);*/
246
247     capture_opts->fork_child = -1;
248
249     /* Allocate the string pointer array with enough space for the
250        terminating NULL pointer. */
251     argc = 0;
252     argv = g_malloc(sizeof (char *));
253     *argv = NULL;
254
255     /* Now add those arguments used on all platforms. */
256     argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
257
258     argv = sync_pipe_add_arg(argv, &argc, "-i");
259     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
260
261     if(capture_opts->save_file) {
262       argv = sync_pipe_add_arg(argv, &argc, "-w");
263       argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
264     }
265
266     if (capture_opts->has_snaplen) {
267       argv = sync_pipe_add_arg(argv, &argc, "-s");
268       sprintf(ssnap,"%d",capture_opts->snaplen);
269       argv = sync_pipe_add_arg(argv, &argc, ssnap);
270     }
271
272     if (capture_opts->linktype != -1) {
273       argv = sync_pipe_add_arg(argv, &argc, "-y");
274 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
275       sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts->linktype));
276 #else
277       /* XXX - just treat it as a number */
278       sprintf(ssnap,"%d",capture_opts->linktype);
279 #endif
280       argv = sync_pipe_add_arg(argv, &argc, ssnap);
281     }
282
283     if(capture_opts->multi_files_on) {
284       if (capture_opts->has_autostop_filesize) {
285         argv = sync_pipe_add_arg(argv, &argc, "-b");
286         sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
287         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
288       }
289
290       if (capture_opts->has_file_duration) {
291         argv = sync_pipe_add_arg(argv, &argc, "-b");
292         sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
293         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
294       }
295
296       if (capture_opts->has_ring_num_files) {
297         argv = sync_pipe_add_arg(argv, &argc, "-b");
298         sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
299         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
300       }
301
302       if (capture_opts->has_autostop_files) {
303         argv = sync_pipe_add_arg(argv, &argc, "-a");
304         sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
305         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
306       }
307     } else {
308         if (capture_opts->has_autostop_filesize) {
309           argv = sync_pipe_add_arg(argv, &argc, "-a");
310           sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
311           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
312         }
313     }
314
315     if (capture_opts->has_autostop_packets) {
316       argv = sync_pipe_add_arg(argv, &argc, "-c");
317       sprintf(scount,"%d",capture_opts->autostop_packets);
318       argv = sync_pipe_add_arg(argv, &argc, scount);
319     }
320
321     if (capture_opts->has_autostop_duration) {
322       argv = sync_pipe_add_arg(argv, &argc, "-a");
323       sprintf(sautostop_duration,"duration:%d",capture_opts->autostop_duration);
324       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
325     }
326
327     if (!capture_opts->show_info) {
328       argv = sync_pipe_add_arg(argv, &argc, "-H");
329     }
330
331     if (!capture_opts->promisc_mode)
332       argv = sync_pipe_add_arg(argv, &argc, "-p");
333
334 #ifdef _WIN32
335     /* Create a pipe for the child process */
336     if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
337       /* Couldn't create the pipe between parent and child. */
338       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
339                         strerror(errno));
340       return FALSE;
341     }
342
343     /* Convert font name to a quote-encapsulated string and pass to child */
344     argv = sync_pipe_add_arg(argv, &argc, "-m");
345     fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
346     argv = sync_pipe_add_arg(argv, &argc, fontstring);
347
348     /* Convert pipe write handle to a string and pass to child */
349     argv = sync_pipe_add_arg(argv, &argc, "-Z");
350     itoa(sync_pipe[PIPE_WRITE], sync_pipe_fd, 10);
351     argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
352
353     /* Convert filter string to a quote delimited string and pass to child */
354     filterstring = NULL;
355     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
356       argv = sync_pipe_add_arg(argv, &argc, "-f");
357       filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
358       argv = sync_pipe_add_arg(argv, &argc, filterstring);
359     }
360
361     /* Spawn process */
362     capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
363     g_free(fontstring);
364     if (filterstring) {
365       g_free(filterstring);
366     }
367 #else
368     if (pipe(sync_pipe) < 0) {
369       /* Couldn't create the pipe between parent and child. */
370       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
371                         strerror(errno));
372       return FALSE;
373     }
374
375     argv = sync_pipe_add_arg(argv, &argc, "-m");
376     argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
377
378     if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
379       argv = sync_pipe_add_arg(argv, &argc, "-f");
380       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
381     }
382
383     if ((capture_opts->fork_child = fork()) == 0) {
384       /*
385        * Child process - run Ethereal with the right arguments to make
386        * it just pop up the live capture dialog box and capture with
387        * the specified capture parameters, writing to the specified file.
388        *
389        * args: -i interface specification
390        * -w file to write
391        * -W file descriptor to write
392        * -c count to capture
393        * -s snaplen
394        * -m / -b fonts
395        * -f "filter expression"
396        */
397       close(1);
398       dup(sync_pipe[PIPE_WRITE]);
399       close(sync_pipe[PIPE_READ]);
400       execvp(ethereal_path, argv);
401       snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
402                 ethereal_path, strerror(errno));
403       sync_pipe_errmsg_to_parent(errmsg);
404
405       /* Exit with "_exit()", so that we don't close the connection
406          to the X server (and cause stuff buffered up by our parent but
407          not yet sent to be sent, as that stuff should only be sent by
408          our parent). */
409       _exit(2);
410     }
411 #endif
412
413     /* Parent process - read messages from the child process over the
414        sync pipe. */
415     g_free(argv);       /* free up arg array */
416
417     /* Close the write side of the pipe, so that only the child has it
418        open, and thus it completely closes, and thus returns to us
419        an EOF indication, if the child closes it (either deliberately
420        or by exiting abnormally). */
421     close(sync_pipe[PIPE_WRITE]);
422
423     if (capture_opts->fork_child == -1) {
424       /* We couldn't even create the child process. */
425       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
426                         "Couldn't create child process: %s", strerror(errno));
427       close(sync_pipe[PIPE_READ]);
428       return FALSE;
429     }
430
431     /* Read a byte count from "sync_pipe[PIPE_READ]", terminated with a
432        colon; if the count is 0, the child process created the
433        capture file and we should start reading from it, otherwise
434        the capture couldn't start and the count is a count of bytes
435        of error message, and we should display the message. */
436     byte_count = 0;
437     for (;;) {
438       i = read(sync_pipe[PIPE_READ], &c, 1);
439       if (i == 0) {
440         /* EOF - the child process died.
441            Close the read side of the sync pipe, remove the capture file,
442            and report the failure. */
443         close(sync_pipe[PIPE_READ]);
444         sync_pipe_wait_for_child(capture_opts, TRUE);
445         return FALSE;
446       }
447
448       /* the first message should be the capture start or an error message */
449       if (c == SP_CAPSTART || c == SP_ERROR_MSG)
450         break;
451       if (!isdigit(c)) {
452         /* Child process handed us crap.
453            Close the read side of the sync pipe, remove the capture file,
454            and report the failure. */
455         close(sync_pipe[PIPE_READ]);
456         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
457                         "Capture child process sent us a bad message");
458         return FALSE;
459       }
460       byte_count = byte_count*10 + c - '0';
461     }
462     if (c != SP_CAPSTART) {
463       /* Failure - the child process sent us a message indicating
464          what the problem was. */
465       if (byte_count == 0) {
466         /* Zero-length message? */
467         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
468                 "Capture child process failed, but its error message was empty.");
469       } else {
470         msg = g_malloc(byte_count + 1);
471         if (msg == NULL) {
472           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
473                 "Capture child process failed, but its error message was too big.");
474         } else {
475           i = read(sync_pipe[PIPE_READ], msg, byte_count);
476           msg[byte_count] = '\0';
477           if (i < 0) {
478             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
479                   "Capture child process failed: Error %s reading its error message.",
480                   strerror(errno));
481           } else if (i == 0) {
482             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
483                   "Capture child process failed: EOF reading its error message.");
484             sync_pipe_wait_for_child(capture_opts, FALSE);
485           } else
486             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
487           g_free(msg);
488         }
489
490         /* Close the sync pipe. */
491         close(sync_pipe[PIPE_READ]);
492       }
493       return FALSE;
494     }
495
496     /* We were able to set up to read the capture file;
497        arrange that our callback be called whenever it's possible
498        to read from the sync pipe, so that it's called when
499        the child process wants to tell us something. */
500
501     /* we have a running capture, now wait for the real capture filename */
502     pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, 
503         &capture_opts->fork_child, sync_pipe_input_cb);
504
505     return TRUE;
506 }
507
508
509 /* There's stuff to read from the sync pipe, meaning the child has sent
510    us a message, or the sync pipe has closed, meaning the child has
511    closed it (perhaps because it exited). */
512 static gboolean 
513 sync_pipe_input_cb(gint source, gpointer user_data)
514 {
515   capture_options *capture_opts = (capture_options *)user_data;
516 #define BUFSIZE 4096
517   char buffer[BUFSIZE+1], *p = buffer, *q = buffer, *msg, *r;
518   int  nread, msglen, chars_to_copy;
519   int  to_read = 0;
520
521
522   if ((nread = read(source, buffer, BUFSIZE)) <= 0) {
523     /* The child has closed the sync pipe, meaning it's not going to be
524        capturing any more packets.  Pick up its exit status, and
525        complain if it did anything other than exit with status 0. */
526     sync_pipe_wait_for_child(capture_opts, FALSE);
527     capture_input_closed(capture_opts);
528     return FALSE;
529   }
530
531   buffer[nread] = '\0';
532
533   while (nread != 0) {
534     /* look for (possibly multiple) indications */
535     switch (*q) {
536     case SP_PACKET_COUNT :
537       to_read += atoi(p);
538       p = q + 1;
539       q++;
540       nread--;
541       break;
542     case SP_DROPS :
543       cf_set_drops_known(capture_opts->cf, TRUE);
544       cf_set_drops(capture_opts->cf, atoi(p));
545       p = q + 1;
546       q++;
547       nread--;
548       break;
549     case SP_ERROR_MSG :
550       msglen = atoi(p);
551       p = q + 1;
552       q++;
553       nread--;
554
555       /* Read the entire message.
556          XXX - if the child hasn't sent it all yet, this could cause us
557          to hang until they do. */
558       msg = g_malloc(msglen + 1);
559       r = msg;
560       while (msglen != 0) {
561         if (nread == 0) {
562           /* Read more. */
563           if ((nread = read(source, buffer, BUFSIZE)) <= 0)
564             break;
565           p = buffer;
566           q = buffer;
567         }
568         chars_to_copy = MIN(msglen, nread);
569         memcpy(r, q, chars_to_copy);
570         r += chars_to_copy;
571         q += chars_to_copy;
572         nread -= chars_to_copy;
573         msglen -= chars_to_copy;
574       }
575       *r = '\0';
576       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
577       g_free(msg);
578       break;
579     case SP_FILE :
580       msglen = atoi(p);
581       p = q + 1;
582       q++;
583       nread--;
584
585       /* Read the entire file name.
586          XXX - if the child hasn't sent it all yet, this could cause us
587          to hang until they do. */
588       msg = g_malloc(msglen + 1);
589       r = msg;
590       while (msglen != 0) {
591         if (nread == 0) {
592           /* Read more. */
593           if ((nread = read(source, buffer, BUFSIZE)) <= 0)
594             break;
595           p = buffer;
596           q = buffer;
597         }
598         chars_to_copy = MIN(msglen, nread);
599         memcpy(r, q, chars_to_copy);
600         r += chars_to_copy;
601         q += chars_to_copy;
602         nread -= chars_to_copy;
603         msglen -= chars_to_copy;
604       }
605       *r = '\0';
606
607       if(!capture_input_new_file(capture_opts, msg)) {
608          /* We weren't able to open the new capture file; user has been
609             alerted. Close the sync pipe. */
610 /*            close(sync_pipe[PIPE_READ]);*/
611
612             /* XXX - how to kill things here ? */
613             /* XXX - is it safe to close the pipe inside this callback? */
614             close(source);
615       }
616
617       g_free(msg);
618
619       break;
620     default :
621       q++;
622       nread--;
623       break;
624     }
625   }
626
627   capture_input_new_packets(capture_opts, to_read);
628
629   return TRUE;
630 }
631
632
633 /* the child process is going down, wait until it's completely terminated */
634 static void
635 sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
636 {
637   int  wstatus;
638
639
640   g_assert(capture_opts->fork_child != -1);
641
642 #ifdef _WIN32
643   /* XXX - analyze the wait status and display more information
644      in the dialog box?
645      XXX - set "fork_child" to -1 if we find it exited? */
646   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
647     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
648                 "Child capture process stopped unexpectedly");
649   }
650 #else
651   if (wait(&wstatus) != -1) {
652     if (WIFEXITED(wstatus)) {
653       /* The child exited; display its exit status, if it's not zero,
654          and even if it's zero if "always_report" is true. */
655       if (always_report || WEXITSTATUS(wstatus) != 0) {
656         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
657                       "Child capture process exited: exit status %d",
658                       WEXITSTATUS(wstatus));
659       }
660     } else if (WIFSTOPPED(wstatus)) {
661       /* It stopped, rather than exiting.  "Should not happen." */
662       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
663                     "Child capture process stopped: %s",
664                     sync_pipe_signame(WSTOPSIG(wstatus)));
665     } else if (WIFSIGNALED(wstatus)) {
666       /* It died with a signal. */
667       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
668                     "Child capture process died: %s%s",
669                     sync_pipe_signame(WTERMSIG(wstatus)),
670                     WCOREDUMP(wstatus) ? " - core dumped" : "");
671     } else {
672       /* What?  It had to either have exited, or stopped, or died with
673          a signal; what happened here? */
674       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
675                     "Child capture process died: wait status %#o", wstatus);
676     }
677   }
678
679   /* No more child process. */
680   capture_opts->fork_child = -1;
681 #endif
682 }
683
684
685 #ifndef _WIN32
686 static char *
687 sync_pipe_signame(int sig)
688 {
689   char *sigmsg;
690   static char sigmsg_buf[6+1+3+1];
691
692   switch (sig) {
693
694   case SIGHUP:
695     sigmsg = "Hangup";
696     break;
697
698   case SIGINT:
699     sigmsg = "Interrupted";
700     break;
701
702   case SIGQUIT:
703     sigmsg = "Quit";
704     break;
705
706   case SIGILL:
707     sigmsg = "Illegal instruction";
708     break;
709
710   case SIGTRAP:
711     sigmsg = "Trace trap";
712     break;
713
714   case SIGABRT:
715     sigmsg = "Abort";
716     break;
717
718   case SIGFPE:
719     sigmsg = "Arithmetic exception";
720     break;
721
722   case SIGKILL:
723     sigmsg = "Killed";
724     break;
725
726   case SIGBUS:
727     sigmsg = "Bus error";
728     break;
729
730   case SIGSEGV:
731     sigmsg = "Segmentation violation";
732     break;
733
734   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
735      Linux is POSIX compliant.  These are not POSIX-defined signals ---
736      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
737
738         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
739         were omitted from POSIX.1 because their behavior is
740         implementation dependent and could not be adequately catego-
741         rized.  Conforming implementations may deliver these sig-
742         nals, but must document the circumstances under which they
743         are delivered and note any restrictions concerning their
744         delivery.''
745
746      So we only check for SIGSYS on those systems that happen to
747      implement them (a system can be POSIX-compliant and implement
748      them, it's just that POSIX doesn't *require* a POSIX-compliant
749      system to implement them).
750    */
751
752 #ifdef SIGSYS
753   case SIGSYS:
754     sigmsg = "Bad system call";
755     break;
756 #endif
757
758   case SIGPIPE:
759     sigmsg = "Broken pipe";
760     break;
761
762   case SIGALRM:
763     sigmsg = "Alarm clock";
764     break;
765
766   case SIGTERM:
767     sigmsg = "Terminated";
768     break;
769
770   default:
771     sprintf(sigmsg_buf, "Signal %d", sig);
772     sigmsg = sigmsg_buf;
773     break;
774   }
775   return sigmsg;
776 }
777 #endif
778
779
780 void
781 sync_pipe_stop(capture_options *capture_opts)
782 {
783   /* XXX - in which cases this will be 0? */
784   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
785 #ifndef _WIN32
786       kill(capture_opts->fork_child, SIGUSR1);
787 #else
788       /* XXX: this is not the preferred method of closing a process!
789        * the clean way would be getting the process id of the child process,
790        * then getting window handle hWnd of that process (using EnumChildWindows),
791        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
792        *
793        * Unfortunately, I don't know how to get the process id from the
794        * handle.  OpenProcess will get an handle (not a window handle)
795        * from the process ID; it will not get a window handle from the
796        * process ID.  (How could it?  A process can have more than one
797        * window.)
798        *
799        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
800        * running in the same console; that's not necessarily the case for
801        * us, as we might not be running in a console.
802        * And this also will require to have the process id.
803        */
804       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
805 #endif
806   }
807 }
808
809
810 void
811 sync_pipe_kill(capture_options *capture_opts)
812 {
813   /* XXX - in which cases this will be 0? */
814   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
815 #ifndef _WIN32
816       kill(capture_opts->fork_child, SIGTERM);  /* SIGTERM so it can clean up if necessary */
817 #else
818       /* XXX: this is not the preferred method of closing a process!
819        * the clean way would be getting the process id of the child process,
820        * then getting window handle hWnd of that process (using EnumChildWindows),
821        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
822        *
823        * Unfortunately, I don't know how to get the process id from the
824        * handle.  OpenProcess will get an handle (not a window handle)
825        * from the process ID; it will not get a window handle from the
826        * process ID.  (How could it?  A process can have more than one
827        * window.)
828        *
829        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
830        * running in the same console; that's not necessarily the case for
831        * us, as we might not be running in a console.
832        * And this also will require to have the process id.
833        */
834       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
835 #endif
836   }
837 }
838
839 #endif /* HAVE_LIBPCAP */