9e02b26c4448a9ffa0a80427c225e2f7ed8eadd8
[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 #include "log.h"
91
92 #ifdef HAVE_IO_H
93 # include <io.h>
94 #endif
95
96 #ifdef _WIN32
97 #include <process.h>    /* For spawning child process */
98 #endif
99
100 /* Win32 needs the O_BINARY flag for open() */
101 #ifndef O_BINARY
102 #define O_BINARY        0
103 #endif
104
105
106 #ifndef _WIN32
107 static const char *sync_pipe_signame(int);
108 #endif
109
110
111 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
112 static void sync_pipe_wait_for_child(capture_options *capture_opts);
113
114 /* Size of buffer to hold decimal representation of
115    signed/unsigned 64-bit int */
116 #define SP_DECISIZE 20
117
118 /*
119  * Indications sent out on the sync pipe.
120  */
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) */
126
127
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) */
131 static void
132 pipe_write_block(int pipe, char indicator, int len, const char *msg)
133 {
134     char lenbuf[3+1+1]; /* 3 digit len + indicator + zero terminator */
135     int ret;
136
137     /*g_warning("write %d enter", pipe);*/
138
139     g_assert(len < 1000);
140     g_assert(indicator < '0' || indicator > '9');
141
142     /* write header (3 digit len + indicator) */
143     g_snprintf(lenbuf, 5, "%03u%c", len, indicator);
144
145     ret = write(pipe, lenbuf, strlen(lenbuf));
146     if(ret == -1) {
147         return;
148     }
149
150     /* write value (if we have one) */
151     if(len) {
152         /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
153         ret = write(pipe, msg, len);
154         if(ret == -1) {
155             return;
156         }
157     } else {
158         /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
159     }
160
161     /*g_warning("write %d leave", pipe);*/
162 }
163
164
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) */
168 static int
169 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
170     int required;
171     int newly;
172     char header[4];
173     int offset;
174
175
176     /* read header (3 digit len and indicator) */
177     required = 4;
178     offset = 0;
179     while(required) {
180         newly = read(pipe, &header[offset], required);
181         if (newly == 0) {
182             /* EOF */
183             /*g_warning("read %d header empty (capture closed)", pipe);*/
184             return newly;
185         }
186         if (newly < 0) {
187             /* error */
188             /*g_warning("read %d header error: %s", pipe, strerror(errno));*/
189             return newly;
190         }
191
192         required -= newly;
193         offset += newly;
194     }
195
196     /* convert header values */
197     *indicator = header[3];
198     required = atoi(header);
199
200     /* only indicator with no value? */
201     if(required == 0) {
202         /*g_warning("read %d indicator: %c empty value", pipe, *indicator);*/
203         return 4;
204     }
205
206     g_assert(required <= len);
207     len = required;
208
209     /* read value */
210     offset = 0;
211     while(required) {
212         newly = read(pipe, &msg[offset], required);
213         if (newly == -1) {
214             /* error */
215             /*g_warning("read %d value error, indicator: %u", pipe, *indicator);*/
216             return newly;
217         }
218
219         required -= newly;
220         offset += newly;
221     }
222
223     /*g_warning("read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg);*/
224     return len + 4;
225 }
226
227 void
228 sync_pipe_packet_count_to_parent(int packet_count)
229 {
230     char tmp[SP_DECISIZE+1+1];
231
232     g_snprintf(tmp, sizeof(tmp), "%d", packet_count);
233
234     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_packet_count_to_parent: %s", tmp);
235
236     pipe_write_block(1, SP_PACKET_COUNT, strlen(tmp)+1, tmp);
237 }
238
239 void
240 sync_pipe_filename_to_parent(const char *filename)
241 {
242     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_filename_to_parent: %s", filename);
243
244     pipe_write_block(1, SP_FILE, strlen(filename)+1, filename);
245 }
246
247 void
248 sync_pipe_errmsg_to_parent(const char *errmsg)
249 {
250     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
251
252     pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
253 }
254
255 void
256 sync_pipe_drops_to_parent(int drops)
257 {
258         char tmp[SP_DECISIZE+1+1];
259
260
261     g_snprintf(tmp, sizeof(tmp), "%d", drops);
262
263     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_drops_to_parent: %s", tmp);
264
265     pipe_write_block(1, SP_DROPS, strlen(tmp)+1, tmp);
266 }
267
268
269 #ifdef _WIN32
270
271 static void
272 signal_pipe_capquit_to_child(capture_options *capture_opts)
273 {
274
275     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
276
277     pipe_write_block(capture_opts->signal_pipe_fd, SP_QUIT, 0, NULL);
278 }
279 #endif
280
281
282 /* Add a string pointer to a NULL-terminated array of string pointers. */
283 static const char **
284 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
285 {
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 *));
291
292   /* Stuff the pointer into the penultimate element of the array, which
293      is the one at the index specified by "*argc". */
294   args[*argc] = arg;
295
296   /* Now bump the count. */
297   (*argc)++;
298
299   /* We overwrite the NULL pointer; put it back right after the
300      element we added. */
301   args[*argc] = NULL;
302
303   return args;
304 }
305
306
307
308 #define ARGV_NUMBER_LEN 24
309
310 gboolean
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];
320 #ifdef _WIN32
321     char buffer_size[ARGV_NUMBER_LEN];
322     char sync_pipe_fd[ARGV_NUMBER_LEN];
323     char signal_pipe_fd[ARGV_NUMBER_LEN];
324     char *fontstring;
325     char *filterstring;
326     char *savefilestring;
327     int signal_pipe[2];                     /* pipe used to send messages from parent to child (currently only stop) */
328 #else
329     char errmsg[1024+1];
330 #endif
331     int argc;
332     const char **argv;
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 */
335
336
337     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
338     capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
339
340     capture_opts->fork_child = -1;
341
342     /* Allocate the string pointer array with enough space for the
343        terminating NULL pointer. */
344     argc = 0;
345     argv = g_malloc(sizeof (char *));
346     *argv = NULL;
347
348     /* Now add those arguments used on all platforms. */
349     argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
350
351     argv = sync_pipe_add_arg(argv, &argc, "-i");
352     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
353
354     if (capture_opts->has_snaplen) {
355       argv = sync_pipe_add_arg(argv, &argc, "-s");
356       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
357       argv = sync_pipe_add_arg(argv, &argc, ssnap);
358     }
359
360     if (capture_opts->linktype != -1) {
361       argv = sync_pipe_add_arg(argv, &argc, "-y");
362 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
363       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",pcap_datalink_val_to_name(capture_opts->linktype));
364 #else
365       /* XXX - just treat it as a number */
366       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
367 #endif
368       argv = sync_pipe_add_arg(argv, &argc, ssnap);
369     }
370
371     if(capture_opts->multi_files_on) {
372       if (capture_opts->has_autostop_filesize) {
373         argv = sync_pipe_add_arg(argv, &argc, "-b");
374         g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
375         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
376       }
377
378       if (capture_opts->has_file_duration) {
379         argv = sync_pipe_add_arg(argv, &argc, "-b");
380         g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
381         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
382       }
383
384       if (capture_opts->has_ring_num_files) {
385         argv = sync_pipe_add_arg(argv, &argc, "-b");
386         g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
387         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
388       }
389
390       if (capture_opts->has_autostop_files) {
391         argv = sync_pipe_add_arg(argv, &argc, "-a");
392         g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
393         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
394       }
395     } else {
396         if (capture_opts->has_autostop_filesize) {
397           argv = sync_pipe_add_arg(argv, &argc, "-a");
398           g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
399           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
400         }
401     }
402
403     if (capture_opts->has_autostop_packets) {
404       argv = sync_pipe_add_arg(argv, &argc, "-c");
405       g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
406       argv = sync_pipe_add_arg(argv, &argc, scount);
407     }
408
409     if (capture_opts->has_autostop_duration) {
410       argv = sync_pipe_add_arg(argv, &argc, "-a");
411       g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
412       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
413     }
414
415     if (!capture_opts->show_info) {
416       argv = sync_pipe_add_arg(argv, &argc, "-H");
417     }
418
419     if (!capture_opts->promisc_mode)
420       argv = sync_pipe_add_arg(argv, &argc, "-p");
421
422 #ifdef _WIN32
423     /* Create a pipe for the child process */
424     /* (inrease this value if you have trouble while fast capture file switches) */
425     if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
426       /* Couldn't create the pipe between parent and child. */
427       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
428                         strerror(errno));
429       g_free( (gpointer) argv);
430       return FALSE;
431     }
432
433     /* Create a pipe for the parent process */
434     if(_pipe(signal_pipe, 512, O_BINARY) < 0) {
435       /* Couldn't create the signal pipe between parent and child. */
436       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
437                         strerror(errno));
438       close(sync_pipe[PIPE_READ]);
439       close(sync_pipe[PIPE_WRITE]);
440       g_free( (gpointer) argv);
441       return FALSE;
442     }
443
444     capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
445
446     argv = sync_pipe_add_arg(argv, &argc, "-B");
447     g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
448     argv = sync_pipe_add_arg(argv, &argc, buffer_size);
449
450     /* Convert font name to a quote-encapsulated string and pass to child */
451     argv = sync_pipe_add_arg(argv, &argc, "-m");
452     fontstring = g_strdup_printf("\"%s\"", prefs.PREFS_GUI_FONT_NAME);
453     argv = sync_pipe_add_arg(argv, &argc, fontstring);
454
455     /* Convert sync pipe write handle to a string and pass to child */
456     argv = sync_pipe_add_arg(argv, &argc, "-Z");
457     g_snprintf(sync_pipe_fd, ARGV_NUMBER_LEN, "sync:%d",sync_pipe[PIPE_WRITE]);
458     argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
459
460     /* Convert signal pipe read handle to a string and pass to child */
461     argv = sync_pipe_add_arg(argv, &argc, "-Z");
462     g_snprintf(signal_pipe_fd, ARGV_NUMBER_LEN, "signal:%d",signal_pipe[PIPE_READ]);
463     argv = sync_pipe_add_arg(argv, &argc, signal_pipe_fd);
464
465     /* Convert filter string to a quote delimited string and pass to child */
466     filterstring = NULL;
467     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
468       argv = sync_pipe_add_arg(argv, &argc, "-f");
469       filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
470       argv = sync_pipe_add_arg(argv, &argc, filterstring);
471     }
472
473     /* Convert save file name to a quote delimited string and pass to child */
474     savefilestring = NULL;
475     if(capture_opts->save_file) {
476       argv = sync_pipe_add_arg(argv, &argc, "-w");
477       savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
478       argv = sync_pipe_add_arg(argv, &argc, savefilestring);
479     }
480
481     /* Spawn process */
482     capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
483     g_free(fontstring);
484     if (filterstring) {
485       g_free(filterstring);
486     }
487     if(savefilestring) {
488       g_free(savefilestring);
489     }
490
491     /* child own's the read side now, close our handle */
492     close(signal_pipe[PIPE_READ]);
493 #else
494     if (pipe(sync_pipe) < 0) {
495       /* Couldn't create the pipe between parent and child. */
496       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
497                         strerror(errno));
498       g_free(argv);
499       return FALSE;
500     }
501
502     argv = sync_pipe_add_arg(argv, &argc, "-m");
503     argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
504
505     if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
506       argv = sync_pipe_add_arg(argv, &argc, "-f");
507       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
508     }
509
510     if(capture_opts->save_file) {
511       argv = sync_pipe_add_arg(argv, &argc, "-w");
512       argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
513     }
514
515     if ((capture_opts->fork_child = fork()) == 0) {
516       /*
517        * Child process - run Ethereal with the right arguments to make
518        * it just pop up the live capture dialog box and capture with
519        * the specified capture parameters, writing to the specified file.
520        *
521        * args: -i interface specification
522        * -w file to write
523        * -W file descriptor to write
524        * -c count to capture
525        * -s snaplen
526        * -m / -b fonts
527        * -f "filter expression"
528        */
529       close(1);
530       dup(sync_pipe[PIPE_WRITE]);
531       close(sync_pipe[PIPE_READ]);
532       execvp(ethereal_path, argv);
533       g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
534                 ethereal_path, strerror(errno));
535       sync_pipe_errmsg_to_parent(errmsg);
536
537       /* Exit with "_exit()", so that we don't close the connection
538          to the X server (and cause stuff buffered up by our parent but
539          not yet sent to be sent, as that stuff should only be sent by
540          our parent). */
541       _exit(2);
542     }
543 #endif
544
545     /* Parent process - read messages from the child process over the
546        sync pipe. */
547     g_free( (gpointer) argv);   /* free up arg array */
548
549     /* Close the write side of the pipe, so that only the child has it
550        open, and thus it completely closes, and thus returns to us
551        an EOF indication, if the child closes it (either deliberately
552        or by exiting abnormally). */
553     close(sync_pipe[PIPE_WRITE]);
554
555     if (capture_opts->fork_child == -1) {
556       /* We couldn't even create the child process. */
557       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
558                         "Couldn't create child process: %s", strerror(errno));
559       close(sync_pipe[PIPE_READ]);
560 #ifdef _WIN32
561       close(signal_pipe[PIPE_WRITE]);
562 #endif
563       return FALSE;
564     }
565
566     /* we might wait for a moment till child is ready, so update screen now */
567     main_window_update();
568
569     /* We were able to set up to read the capture file;
570        arrange that our callback be called whenever it's possible
571        to read from the sync pipe, so that it's called when
572        the child process wants to tell us something. */
573
574     /* we have a running capture, now wait for the real capture filename */
575     pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, 
576         &capture_opts->fork_child, sync_pipe_input_cb);
577
578     return TRUE;
579 }
580
581 /* There's stuff to read from the sync pipe, meaning the child has sent
582    us a message, or the sync pipe has closed, meaning the child has
583    closed it (perhaps because it exited). */
584 static gboolean 
585 sync_pipe_input_cb(gint source, gpointer user_data)
586 {
587   capture_options *capture_opts = (capture_options *)user_data;
588 #define BUFSIZE 4096
589   char buffer[BUFSIZE+1];
590   int  nread;
591   char indicator;
592
593
594   nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
595   if(nread <= 0) {
596     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
597
598     /* The child has closed the sync pipe, meaning it's not going to be
599        capturing any more packets.  Pick up its exit status, and
600        complain if it did anything other than exit with status 0. */
601     sync_pipe_wait_for_child(capture_opts);
602
603 #ifdef _WIN32
604     close(capture_opts->signal_pipe_fd);
605 #endif
606     capture_input_closed(capture_opts);
607     return FALSE;
608   }
609
610   switch(indicator) {
611   case SP_FILE:
612       if(!capture_input_new_file(capture_opts, buffer)) {
613         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
614
615         /* We weren't able to open the new capture file; user has been
616            alerted. Close the sync pipe. */
617         /* XXX - is it safe to close the pipe inside this callback? */
618         close(source);
619
620         /* the child has send us a filename which we couldn't open.
621            this probably means, the child is creating files faster than we can handle it.
622            this should only be the case for very fast file switches
623            we can't do much more than telling the child to stop
624            (this is the emergency brake if user e.g. wants to switch files every second) */
625         sync_pipe_stop(capture_opts);
626       }
627       break;
628   case SP_PACKET_COUNT:
629     nread = atoi(buffer);
630     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
631     capture_input_new_packets(capture_opts, nread);
632     break;
633   case SP_ERROR_MSG:
634     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\"", buffer);
635     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
636     /* the capture child will close the sync_pipe, nothing to do for now */
637     break;
638   case SP_DROPS:
639     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", atoi(buffer), plurality(atoi(buffer), "", "s"));
640     cf_set_drops_known(capture_opts->cf, TRUE);
641     cf_set_drops(capture_opts->cf, atoi(buffer));
642     break;
643   default:
644       g_assert_not_reached();
645   }
646
647   return TRUE;
648 }
649
650
651
652 /* the child process is going down, wait until it's completely terminated */
653 static void
654 sync_pipe_wait_for_child(capture_options *capture_opts)
655 {
656   int  wstatus;
657
658
659   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
660   g_assert(capture_opts->fork_child != -1);
661
662 #ifdef _WIN32
663   /* XXX - analyze the wait status and display more information
664      in the dialog box?
665      XXX - set "fork_child" to -1 if we find it exited? */
666   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
667     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
668                 "Child capture process stopped unexpectedly");
669   }
670 #else
671   if (wait(&wstatus) != -1) {
672     if (WIFEXITED(wstatus)) {
673       /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
674       /* the child will inform us about errors through the sync_pipe, which will popup */
675       /* an error message, so don't popup another one */
676
677       /* XXX - if there are situations where the child won't send us such an error message, */
678       /* this should be fixed in the child and not here! */
679       if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
680         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
681                       "Child capture process exited: exit status %d",
682                       WEXITSTATUS(wstatus));
683       }
684     } else if (WIFSTOPPED(wstatus)) {
685       /* It stopped, rather than exiting.  "Should not happen." */
686       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
687                     "Child capture process stopped: %s",
688                     sync_pipe_signame(WSTOPSIG(wstatus)));
689     } else if (WIFSIGNALED(wstatus)) {
690       /* It died with a signal. */
691       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
692                     "Child capture process died: %s%s",
693                     sync_pipe_signame(WTERMSIG(wstatus)),
694                     WCOREDUMP(wstatus) ? " - core dumped" : "");
695     } else {
696       /* What?  It had to either have exited, or stopped, or died with
697          a signal; what happened here? */
698       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
699                     "Child capture process died: wait status %#o", wstatus);
700     }
701   }
702
703   /* No more child process. */
704   capture_opts->fork_child = -1;
705 #endif
706
707   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
708 }
709
710
711 #ifndef _WIN32
712 /* convert signal to corresponding name */
713 static const char *
714 sync_pipe_signame(int sig)
715 {
716   const char *sigmsg;
717   static char sigmsg_buf[6+1+3+1];
718
719   switch (sig) {
720
721   case SIGHUP:
722     sigmsg = "Hangup";
723     break;
724
725   case SIGINT:
726     sigmsg = "Interrupted";
727     break;
728
729   case SIGQUIT:
730     sigmsg = "Quit";
731     break;
732
733   case SIGILL:
734     sigmsg = "Illegal instruction";
735     break;
736
737   case SIGTRAP:
738     sigmsg = "Trace trap";
739     break;
740
741   case SIGABRT:
742     sigmsg = "Abort";
743     break;
744
745   case SIGFPE:
746     sigmsg = "Arithmetic exception";
747     break;
748
749   case SIGKILL:
750     sigmsg = "Killed";
751     break;
752
753   case SIGBUS:
754     sigmsg = "Bus error";
755     break;
756
757   case SIGSEGV:
758     sigmsg = "Segmentation violation";
759     break;
760
761   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
762      Linux is POSIX compliant.  These are not POSIX-defined signals ---
763      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
764
765         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
766         were omitted from POSIX.1 because their behavior is
767         implementation dependent and could not be adequately catego-
768         rized.  Conforming implementations may deliver these sig-
769         nals, but must document the circumstances under which they
770         are delivered and note any restrictions concerning their
771         delivery.''
772
773      So we only check for SIGSYS on those systems that happen to
774      implement them (a system can be POSIX-compliant and implement
775      them, it's just that POSIX doesn't *require* a POSIX-compliant
776      system to implement them).
777    */
778
779 #ifdef SIGSYS
780   case SIGSYS:
781     sigmsg = "Bad system call";
782     break;
783 #endif
784
785   case SIGPIPE:
786     sigmsg = "Broken pipe";
787     break;
788
789   case SIGALRM:
790     sigmsg = "Alarm clock";
791     break;
792
793   case SIGTERM:
794     sigmsg = "Terminated";
795     break;
796
797   default:
798         /* XXX - returning a static buffer is ok in the context we use it here */
799     g_snprintf(sigmsg_buf, sizeof sigmsg_buf, "Signal %d", sig);
800     sigmsg = sigmsg_buf;
801     break;
802   }
803   return sigmsg;
804 }
805 #endif
806
807
808 /* user wants to stop the capture run */
809 void
810 sync_pipe_stop(capture_options *capture_opts)
811 {
812   /* XXX - in which cases this will be 0? */
813   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
814 #ifndef _WIN32
815     /* send the SIGUSR1 signal to close the capture child gracefully. */
816     kill(capture_opts->fork_child, SIGUSR1);
817 #else
818     /* Win32 doesn't have the kill() system call, use the special signal pipe 
819        instead to close the capture child gracefully. */
820     signal_pipe_capquit_to_child(capture_opts);
821 #endif
822   }
823 }
824
825
826 /* Ethereal has to exit, force the capture child to close */
827 void
828 sync_pipe_kill(capture_options *capture_opts)
829 {
830   /* XXX - in which cases this will be 0? */
831   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
832 #ifndef _WIN32
833       kill(capture_opts->fork_child, SIGTERM);  /* SIGTERM so it can clean up if necessary */
834 #else
835       /* XXX: this is not the preferred method of closing a process!
836        * the clean way would be getting the process id of the child process,
837        * then getting window handle hWnd of that process (using EnumChildWindows),
838        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
839        *
840        * Unfortunately, I don't know how to get the process id from the
841        * handle.  OpenProcess will get an handle (not a window handle)
842        * from the process ID; it will not get a window handle from the
843        * process ID.  (How could it?  A process can have more than one
844        * window.)
845        *
846        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
847        * running in the same console; that's not necessarily the case for
848        * us, as we might not be running in a console.
849        * And this also will require to have the process id.
850        */
851       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
852 #endif
853   }
854 }
855
856 #endif /* HAVE_LIBPCAP */