major capture engine rework: use two task model for EVERY capture mode
[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     int  err;
223     char ssnap[24];
224     char scount[24];                        /* need a constant for len of numbers */
225     char sfilesize[24];             /* need a constant for len of numbers */
226     char sfile_duration[24];        /* need a constant for len of numbers */
227     char sring_num_files[24];       /* need a constant for len of numbers */
228     char sautostop_files[24];       /* need a constant for len of numbers */
229     char sautostop_filesize[24];        /* need a constant for len of numbers */
230     char sautostop_duration[24];        /* need a constant for len of numbers */
231     char save_file_fd_str[24];
232 #ifndef _WIN32
233     char errmsg[1024+1];
234 #endif
235     int error;
236     int argc;
237     char **argv;
238 #ifdef _WIN32
239     char sync_pipe_fd[24];
240     char *fontstring;
241     char *filterstring;
242 #endif
243     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
244     int sync_pipe[2];                       /* pipes used to sync between instances */
245
246
247     /*g_warning("sync_pipe_do_capture");
248     capture_opts_info(capture_opts);*/
249
250     capture_opts->fork_child = -1;
251
252     /* Allocate the string pointer array with enough space for the
253        terminating NULL pointer. */
254     argc = 0;
255     argv = g_malloc(sizeof (char *));
256     *argv = NULL;
257
258     /* Now add those arguments used on all platforms. */
259     argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
260
261     argv = sync_pipe_add_arg(argv, &argc, "-i");
262     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
263
264     argv = sync_pipe_add_arg(argv, &argc, "-w");
265     argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
266
267     argv = sync_pipe_add_arg(argv, &argc, "-W");
268     sprintf(save_file_fd_str,"%d",capture_opts->save_file_fd);  /* in lieu of itoa */
269     argv = sync_pipe_add_arg(argv, &argc, save_file_fd_str);
270
271     if (capture_opts->has_snaplen) {
272       argv = sync_pipe_add_arg(argv, &argc, "-s");
273       sprintf(ssnap,"%d",capture_opts->snaplen);
274       argv = sync_pipe_add_arg(argv, &argc, ssnap);
275     }
276
277     if (capture_opts->linktype != -1) {
278       argv = sync_pipe_add_arg(argv, &argc, "-y");
279 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
280       sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts->linktype));
281 #else
282       /* XXX - just treat it as a number */
283       sprintf(ssnap,"%d",capture_opts->linktype);
284 #endif
285       argv = sync_pipe_add_arg(argv, &argc, ssnap);
286     }
287
288     if(capture_opts->multi_files_on) {
289       if (capture_opts->has_autostop_filesize) {
290         argv = sync_pipe_add_arg(argv, &argc, "-b");
291         sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
292         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
293       }
294
295       if (capture_opts->has_file_duration) {
296         argv = sync_pipe_add_arg(argv, &argc, "-b");
297         sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
298         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
299       }
300
301       if (capture_opts->has_ring_num_files) {
302         argv = sync_pipe_add_arg(argv, &argc, "-b");
303         sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
304         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
305       }
306
307       if (capture_opts->has_autostop_files) {
308         argv = sync_pipe_add_arg(argv, &argc, "-a");
309         sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
310         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
311       }
312     } else {
313         if (capture_opts->has_autostop_filesize) {
314           argv = sync_pipe_add_arg(argv, &argc, "-a");
315           sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
316           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
317         }
318     }
319
320     if (capture_opts->has_autostop_packets) {
321       argv = sync_pipe_add_arg(argv, &argc, "-c");
322       sprintf(scount,"%d",capture_opts->autostop_packets);
323       argv = sync_pipe_add_arg(argv, &argc, scount);
324     }
325
326     if (capture_opts->has_autostop_duration) {
327       argv = sync_pipe_add_arg(argv, &argc, "-a");
328       sprintf(sautostop_duration,"duration:%d",capture_opts->autostop_duration);
329       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
330     }
331
332     if (!capture_opts->show_info) {
333       argv = sync_pipe_add_arg(argv, &argc, "-H");
334     }
335
336     if (!capture_opts->promisc_mode)
337       argv = sync_pipe_add_arg(argv, &argc, "-p");
338
339 #ifdef _WIN32
340     /* Create a pipe for the child process */
341     if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
342       /* Couldn't create the pipe between parent and child. */
343       error = errno;
344       unlink(capture_opts->save_file);
345       g_free(capture_opts->save_file);
346       capture_opts->save_file = NULL;
347       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
348                         strerror(error));
349       return FALSE;
350     }
351
352     /* Convert font name to a quote-encapsulated string and pass to child */
353     argv = sync_pipe_add_arg(argv, &argc, "-m");
354     fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
355     argv = sync_pipe_add_arg(argv, &argc, fontstring);
356
357     /* Convert pipe write handle to a string and pass to child */
358     argv = sync_pipe_add_arg(argv, &argc, "-Z");
359     itoa(sync_pipe[PIPE_WRITE], sync_pipe_fd, 10);
360     argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
361
362     /* Convert filter string to a quote delimited string and pass to child */
363     filterstring = NULL;
364     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
365       argv = sync_pipe_add_arg(argv, &argc, "-f");
366       filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
367       argv = sync_pipe_add_arg(argv, &argc, filterstring);
368     }
369
370     /* Spawn process */
371     capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
372     g_free(fontstring);
373     if (filterstring) {
374       g_free(filterstring);
375     }
376 #else
377     if (pipe(sync_pipe) < 0) {
378       /* Couldn't create the pipe between parent and child. */
379       error = errno;
380       unlink(capture_opts->save_file);
381       g_free(capture_opts->save_file);
382       capture_opts->save_file = NULL;
383       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
384                         strerror(error));
385       return FALSE;
386     }
387
388     argv = sync_pipe_add_arg(argv, &argc, "-m");
389     argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
390
391     if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
392       argv = sync_pipe_add_arg(argv, &argc, "-f");
393       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
394     }
395
396     if ((capture_opts->fork_child = fork()) == 0) {
397       /*
398        * Child process - run Ethereal with the right arguments to make
399        * it just pop up the live capture dialog box and capture with
400        * the specified capture parameters, writing to the specified file.
401        *
402        * args: -i interface specification
403        * -w file to write
404        * -W file descriptor to write
405        * -c count to capture
406        * -s snaplen
407        * -m / -b fonts
408        * -f "filter expression"
409        */
410       close(1);
411       dup(sync_pipe[PIPE_WRITE]);
412       close(sync_pipe[PIPE_READ]);
413       execvp(ethereal_path, argv);
414       snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
415                 ethereal_path, strerror(errno));
416       sync_pipe_errmsg_to_parent(errmsg);
417
418       /* Exit with "_exit()", so that we don't close the connection
419          to the X server (and cause stuff buffered up by our parent but
420          not yet sent to be sent, as that stuff should only be sent by
421          our parent). */
422       _exit(2);
423     }
424 #endif
425
426     /* Parent process - read messages from the child process over the
427        sync pipe. */
428     g_free(argv);       /* free up arg array */
429
430     /* Close the write side of the pipe, so that only the child has it
431        open, and thus it completely closes, and thus returns to us
432        an EOF indication, if the child closes it (either deliberately
433        or by exiting abnormally). */
434     close(sync_pipe[PIPE_WRITE]);
435
436     /* Close the save file FD, as we won't be using it - we'll be opening
437        it and reading the save file through Wiretap. */
438     if(capture_opts->save_file_fd != -1) {
439       close(capture_opts->save_file_fd);
440     }
441
442     if (capture_opts->fork_child == -1) {
443       /* We couldn't even create the child process. */
444       error = errno;
445       close(sync_pipe[PIPE_READ]);
446       unlink(capture_opts->save_file);
447       g_free(capture_opts->save_file);
448       capture_opts->save_file = NULL;
449       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
450                         "Couldn't create child process: %s", strerror(error));
451       return FALSE;
452     }
453
454     /* Read a byte count from "sync_pipe[PIPE_READ]", terminated with a
455        colon; if the count is 0, the child process created the
456        capture file and we should start reading from it, otherwise
457        the capture couldn't start and the count is a count of bytes
458        of error message, and we should display the message. */
459     byte_count = 0;
460     for (;;) {
461       i = read(sync_pipe[PIPE_READ], &c, 1);
462       if (i == 0) {
463         /* EOF - the child process died.
464            Close the read side of the sync pipe, remove the capture file,
465            and report the failure. */
466         close(sync_pipe[PIPE_READ]);
467         unlink(capture_opts->save_file);
468         g_free(capture_opts->save_file);
469         capture_opts->save_file = NULL;
470         sync_pipe_wait_for_child(capture_opts, TRUE);
471         return FALSE;
472       }
473       if (c == SP_CAPSTART || c == SP_ERROR_MSG)
474         break;
475       if (!isdigit(c)) {
476         /* Child process handed us crap.
477            Close the read side of the sync pipe, remove the capture file,
478            and report the failure. */
479         close(sync_pipe[PIPE_READ]);
480         unlink(capture_opts->save_file);
481         g_free(capture_opts->save_file);
482         capture_opts->save_file = NULL;
483         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
484                         "Capture child process sent us a bad message");
485         return FALSE;
486       }
487       byte_count = byte_count*10 + c - '0';
488     }
489     if (c != SP_CAPSTART) {
490       /* Failure - the child process sent us a message indicating
491          what the problem was. */
492       if (byte_count == 0) {
493         /* Zero-length message? */
494         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
495                 "Capture child process failed, but its error message was empty.");
496       } else {
497         msg = g_malloc(byte_count + 1);
498         if (msg == NULL) {
499           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
500                 "Capture child process failed, but its error message was too big.");
501         } else {
502           i = read(sync_pipe[PIPE_READ], msg, byte_count);
503           msg[byte_count] = '\0';
504           if (i < 0) {
505             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
506                   "Capture child process failed: Error %s reading its error message.",
507                   strerror(errno));
508           } else if (i == 0) {
509             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
510                   "Capture child process failed: EOF reading its error message.");
511             sync_pipe_wait_for_child(capture_opts, FALSE);
512           } else
513             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
514           g_free(msg);
515         }
516
517         /* Close the sync pipe. */
518         close(sync_pipe[PIPE_READ]);
519
520         /* Get rid of the save file - the capture never started. */
521         unlink(capture_opts->save_file);
522         g_free(capture_opts->save_file);
523         capture_opts->save_file = NULL;
524       }
525       return FALSE;
526     }
527
528     if(capture_opts->sync_mode) {
529         /* The child process started a capture.
530            Attempt to open the capture file and set up to read it. */
531         switch(cf_start_tail(capture_opts->cf, capture_opts->save_file, is_tempfile, &err)) {
532         case CF_OK:
533             /* We were able to open and set up to read the capture file;
534                arrange that our callback be called whenever it's possible
535                to read from the sync pipe, so that it's called when
536                the child process wants to tell us something. */
537             pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, &capture_opts->fork_child, sync_pipe_input_cb);
538
539             return TRUE;
540             break;
541         case CF_ERROR:
542             /* We weren't able to open the capture file; user has been
543             alerted. Close the sync pipe. */
544
545             close(sync_pipe[PIPE_READ]);
546
547             /* Don't unlink the save file - leave it around, for debugging
548             purposes. */
549             g_free(capture_opts->save_file);
550             capture_opts->save_file = NULL;
551             return FALSE;
552             break;
553         }
554
555         g_assert_not_reached();
556         return FALSE;
557     } else {
558         pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, &capture_opts->fork_child, sync_pipe_input_cb);
559         return TRUE;
560     }
561 }
562
563
564 static void
565 sync_pipe_closed(capture_options *capture_opts)
566 {
567     int  err;
568
569
570     /* The child has closed the sync pipe, meaning it's not going to be
571        capturing any more packets.  Pick up its exit status, and
572        complain if it did anything other than exit with status 0. */
573     sync_pipe_wait_for_child(capture_opts, FALSE);
574
575     if(capture_opts->sync_mode) {
576         /* Read what remains of the capture file, and finish the capture.
577            XXX - do something if this fails? */
578         switch (cf_finish_tail(capture_opts->cf, &err)) {
579
580         case CF_READ_OK:
581             if(cf_packet_count(capture_opts->cf) == 0) {
582               simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, 
583               "%sNo packets captured!%s\n\n"
584               "As no data was captured, closing the %scapture file!",
585               simple_dialog_primary_start(), simple_dialog_primary_end(),
586               cf_is_tempfile(capture_opts->cf) ? "temporary " : "");
587               cf_close(capture_opts->cf);
588             }
589             break;
590         case CF_READ_ERROR:
591           /* Just because we got an error, that doesn't mean we were unable
592              to read any of the file; we handle what we could get from the
593              file. */
594           break;
595
596         case CF_READ_ABORTED:
597           /* Exit by leaving the main loop, so that any quit functions
598              we registered get called. */
599           main_window_quit();
600         }
601
602         /* We're not doing a capture any more, so we don't have a save
603            file. */
604         g_free(capture_opts->save_file);
605         capture_opts->save_file = NULL;
606     } else {
607         /* this is a normal mode capture, read in the capture file data */
608         capture_read(capture_opts, cf_is_tempfile(capture_opts->cf), cf_get_drops_known(capture_opts->cf), cf_get_drops(capture_opts->cf));
609     }
610 }
611
612
613 /* There's stuff to read from the sync pipe, meaning the child has sent
614    us a message, or the sync pipe has closed, meaning the child has
615    closed it (perhaps because it exited). */
616 static gboolean 
617 sync_pipe_input_cb(gint source, gpointer user_data)
618 {
619   capture_options *capture_opts = (capture_options *)user_data;
620 #define BUFSIZE 4096
621   char buffer[BUFSIZE+1], *p = buffer, *q = buffer, *msg, *r;
622   int  nread, msglen, chars_to_copy;
623   int  to_read = 0;
624   int  err;
625
626
627   /* we are a capture parent */
628   g_assert(!capture_opts->capture_child);
629
630   if ((nread = read(source, buffer, BUFSIZE)) <= 0) {
631     /* The child has closed the sync pipe, meaning it's not going to be
632        capturing any more packets.  Pick up its exit status, and
633        complain if it did anything other than exit with status 0. */
634     sync_pipe_closed(capture_opts);
635     return FALSE;
636   }
637
638   buffer[nread] = '\0';
639
640   while (nread != 0) {
641     /* look for (possibly multiple) indications */
642     switch (*q) {
643     case SP_PACKET_COUNT :
644       to_read += atoi(p);
645       p = q + 1;
646       q++;
647       nread--;
648       break;
649     case SP_DROPS :
650       cf_set_drops_known(capture_opts->cf, TRUE);
651       cf_set_drops(capture_opts->cf, atoi(p));
652       p = q + 1;
653       q++;
654       nread--;
655       break;
656     case SP_ERROR_MSG :
657       msglen = atoi(p);
658       p = q + 1;
659       q++;
660       nread--;
661
662       /* Read the entire message.
663          XXX - if the child hasn't sent it all yet, this could cause us
664          to hang until they do. */
665       msg = g_malloc(msglen + 1);
666       r = msg;
667       while (msglen != 0) {
668         if (nread == 0) {
669           /* Read more. */
670           if ((nread = read(source, buffer, BUFSIZE)) <= 0)
671             break;
672           p = buffer;
673           q = buffer;
674         }
675         chars_to_copy = MIN(msglen, nread);
676         memcpy(r, q, chars_to_copy);
677         r += chars_to_copy;
678         q += chars_to_copy;
679         nread -= chars_to_copy;
680         msglen -= chars_to_copy;
681       }
682       *r = '\0';
683       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
684       g_free(msg);
685       break;
686     case SP_FILE :
687       msglen = atoi(p);
688       p = q + 1;
689       q++;
690       nread--;
691
692       /* Read the entire message.
693          XXX - if the child hasn't sent it all yet, this could cause us
694          to hang until they do. */
695       msg = g_malloc(msglen + 1);
696       r = msg;
697       while (msglen != 0) {
698         if (nread == 0) {
699           /* Read more. */
700           if ((nread = read(source, buffer, BUFSIZE)) <= 0)
701             break;
702           p = buffer;
703           q = buffer;
704         }
705         chars_to_copy = MIN(msglen, nread);
706         memcpy(r, q, chars_to_copy);
707         r += chars_to_copy;
708         q += chars_to_copy;
709         nread -= chars_to_copy;
710         msglen -= chars_to_copy;
711       }
712       *r = '\0';
713
714       /* save the new filename */
715       if(capture_opts->save_file != NULL) {
716         g_free(capture_opts->save_file);
717       }
718       capture_opts->save_file = g_strdup(msg);
719       g_free(msg);
720       break;
721     default :
722       q++;
723       nread--;
724       break;
725     }
726   }
727
728   if(capture_opts->sync_mode) {
729       /* Read from the capture file the number of records the child told us
730          it added.
731          XXX - do something if this fails? */
732       switch (cf_continue_tail(capture_opts->cf, to_read, &err)) {
733
734       case CF_READ_OK:
735       case CF_READ_ERROR:
736         /* Just because we got an error, that doesn't mean we were unable
737            to read any of the file; we handle what we could get from the
738            file.
739
740            XXX - abort on a read error? */
741         break;
742
743       case CF_READ_ABORTED:
744         /* Kill the child capture process; the user wants to exit, and we
745            shouldn't just leave it running. */
746         capture_kill_child(capture_opts);
747         break;
748       }
749   }
750
751   return TRUE;
752 }
753
754
755 /* the child process is going down, wait until it's completely terminated */
756 static void
757 sync_pipe_wait_for_child(capture_options *capture_opts, gboolean always_report)
758 {
759   int  wstatus;
760
761
762   g_assert(capture_opts->fork_child != -1);
763
764 #ifdef _WIN32
765   /* XXX - analyze the wait status and display more information
766      in the dialog box?
767      XXX - set "fork_child" to -1 if we find it exited? */
768   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
769     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
770                 "Child capture process stopped unexpectedly");
771   }
772 #else
773   if (wait(&wstatus) != -1) {
774     if (WIFEXITED(wstatus)) {
775       /* The child exited; display its exit status, if it's not zero,
776          and even if it's zero if "always_report" is true. */
777       if (always_report || WEXITSTATUS(wstatus) != 0) {
778         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
779                       "Child capture process exited: exit status %d",
780                       WEXITSTATUS(wstatus));
781       }
782     } else if (WIFSTOPPED(wstatus)) {
783       /* It stopped, rather than exiting.  "Should not happen." */
784       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
785                     "Child capture process stopped: %s",
786                     sync_pipe_signame(WSTOPSIG(wstatus)));
787     } else if (WIFSIGNALED(wstatus)) {
788       /* It died with a signal. */
789       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
790                     "Child capture process died: %s%s",
791                     sync_pipe_signame(WTERMSIG(wstatus)),
792                     WCOREDUMP(wstatus) ? " - core dumped" : "");
793     } else {
794       /* What?  It had to either have exited, or stopped, or died with
795          a signal; what happened here? */
796       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
797                     "Child capture process died: wait status %#o", wstatus);
798     }
799   }
800
801   /* No more child process. */
802   capture_opts->fork_child = -1;
803 #endif
804 }
805
806
807 #ifndef _WIN32
808 static char *
809 sync_pipe_signame(int sig)
810 {
811   char *sigmsg;
812   static char sigmsg_buf[6+1+3+1];
813
814   switch (sig) {
815
816   case SIGHUP:
817     sigmsg = "Hangup";
818     break;
819
820   case SIGINT:
821     sigmsg = "Interrupted";
822     break;
823
824   case SIGQUIT:
825     sigmsg = "Quit";
826     break;
827
828   case SIGILL:
829     sigmsg = "Illegal instruction";
830     break;
831
832   case SIGTRAP:
833     sigmsg = "Trace trap";
834     break;
835
836   case SIGABRT:
837     sigmsg = "Abort";
838     break;
839
840   case SIGFPE:
841     sigmsg = "Arithmetic exception";
842     break;
843
844   case SIGKILL:
845     sigmsg = "Killed";
846     break;
847
848   case SIGBUS:
849     sigmsg = "Bus error";
850     break;
851
852   case SIGSEGV:
853     sigmsg = "Segmentation violation";
854     break;
855
856   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
857      Linux is POSIX compliant.  These are not POSIX-defined signals ---
858      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
859
860         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
861         were omitted from POSIX.1 because their behavior is
862         implementation dependent and could not be adequately catego-
863         rized.  Conforming implementations may deliver these sig-
864         nals, but must document the circumstances under which they
865         are delivered and note any restrictions concerning their
866         delivery.''
867
868      So we only check for SIGSYS on those systems that happen to
869      implement them (a system can be POSIX-compliant and implement
870      them, it's just that POSIX doesn't *require* a POSIX-compliant
871      system to implement them).
872    */
873
874 #ifdef SIGSYS
875   case SIGSYS:
876     sigmsg = "Bad system call";
877     break;
878 #endif
879
880   case SIGPIPE:
881     sigmsg = "Broken pipe";
882     break;
883
884   case SIGALRM:
885     sigmsg = "Alarm clock";
886     break;
887
888   case SIGTERM:
889     sigmsg = "Terminated";
890     break;
891
892   default:
893     sprintf(sigmsg_buf, "Signal %d", sig);
894     sigmsg = sigmsg_buf;
895     break;
896   }
897   return sigmsg;
898 }
899 #endif
900
901
902 void
903 sync_pipe_stop(capture_options *capture_opts)
904 {
905   /* XXX - in which cases this will be 0? */
906   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
907 #ifndef _WIN32
908       kill(capture_opts->fork_child, SIGUSR1);
909 #else
910       /* XXX: this is not the preferred method of closing a process!
911        * the clean way would be getting the process id of the child process,
912        * then getting window handle hWnd of that process (using EnumChildWindows),
913        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
914        *
915        * Unfortunately, I don't know how to get the process id from the
916        * handle.  OpenProcess will get an handle (not a window handle)
917        * from the process ID; it will not get a window handle from the
918        * process ID.  (How could it?  A process can have more than one
919        * window.)
920        *
921        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
922        * running in the same console; that's not necessarily the case for
923        * us, as we might not be running in a console.
924        * And this also will require to have the process id.
925        */
926       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
927 #endif
928   }
929 }
930
931
932 void
933 sync_pipe_kill(capture_options *capture_opts)
934 {
935   /* XXX - in which cases this will be 0? */
936   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
937 #ifndef _WIN32
938       kill(capture_opts->fork_child, SIGTERM);  /* SIGTERM so it can clean up if necessary */
939 #else
940       /* XXX: this is not the preferred method of closing a process!
941        * the clean way would be getting the process id of the child process,
942        * then getting window handle hWnd of that process (using EnumChildWindows),
943        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
944        *
945        * Unfortunately, I don't know how to get the process id from the
946        * handle.  OpenProcess will get an handle (not a window handle)
947        * from the process ID; it will not get a window handle from the
948        * process ID.  (How could it?  A process can have more than one
949        * window.)
950        *
951        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
952        * running in the same console; that's not necessarily the case for
953        * us, as we might not be running in a console.
954        * And this also will require to have the process id.
955        */
956       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
957 #endif
958   }
959 }
960
961 #endif /* HAVE_LIBPCAP */