Create packet-dcom-cba-acco.h
[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 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 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 char **
284 sync_pipe_add_arg(char **args, int *argc, 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(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 #ifdef _WIN32
307 /* Given a string, return a pointer to a quote-encapsulated version of
308    the string, so we can pass it as an argument with "spawnvp" even
309    if it contains blanks. */
310 char *
311 sync_pipe_quote_encapsulate(const char *string)
312 {
313   char *encapsulated_string;
314
315   encapsulated_string = g_new(char, strlen(string) + 3);
316   sprintf(encapsulated_string, "\"%s\"", string);
317   return encapsulated_string;
318 }
319 #endif
320
321
322
323 #define ARGV_NUMBER_LEN 24
324
325 gboolean
326 sync_pipe_start(capture_options *capture_opts) {
327     char ssnap[ARGV_NUMBER_LEN];
328     char scount[ARGV_NUMBER_LEN];
329     char sfilesize[ARGV_NUMBER_LEN];
330     char sfile_duration[ARGV_NUMBER_LEN];
331     char sring_num_files[ARGV_NUMBER_LEN];
332     char sautostop_files[ARGV_NUMBER_LEN];
333     char sautostop_filesize[ARGV_NUMBER_LEN];
334     char sautostop_duration[ARGV_NUMBER_LEN];
335 #ifdef _WIN32
336     char buffer_size[ARGV_NUMBER_LEN];
337     char sync_pipe_fd[ARGV_NUMBER_LEN];
338     char signal_pipe_fd[ARGV_NUMBER_LEN];
339     char *fontstring;
340     char *filterstring;
341     char *savefilestring;
342     int signal_pipe[2];                     /* pipe used to send messages from parent to child (currently only stop) */
343 #else
344     char errmsg[1024+1];
345 #endif
346     int argc;
347     char **argv;
348     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
349     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
350
351
352     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
353 #ifdef LOG_CAPTURE_VERBOSE
354     capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
355 #endif
356
357     capture_opts->fork_child = -1;
358
359     /* Allocate the string pointer array with enough space for the
360        terminating NULL pointer. */
361     argc = 0;
362     argv = g_malloc(sizeof (char *));
363     *argv = NULL;
364
365     /* Now add those arguments used on all platforms. */
366     argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
367
368     argv = sync_pipe_add_arg(argv, &argc, "-i");
369     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
370
371     if (capture_opts->has_snaplen) {
372       argv = sync_pipe_add_arg(argv, &argc, "-s");
373       sprintf(ssnap,"%d",capture_opts->snaplen);
374       argv = sync_pipe_add_arg(argv, &argc, ssnap);
375     }
376
377     if (capture_opts->linktype != -1) {
378       argv = sync_pipe_add_arg(argv, &argc, "-y");
379 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
380       sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts->linktype));
381 #else
382       /* XXX - just treat it as a number */
383       sprintf(ssnap,"%d",capture_opts->linktype);
384 #endif
385       argv = sync_pipe_add_arg(argv, &argc, ssnap);
386     }
387
388     if(capture_opts->multi_files_on) {
389       if (capture_opts->has_autostop_filesize) {
390         argv = sync_pipe_add_arg(argv, &argc, "-b");
391         sprintf(sfilesize,"filesize:%d",capture_opts->autostop_filesize);
392         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
393       }
394
395       if (capture_opts->has_file_duration) {
396         argv = sync_pipe_add_arg(argv, &argc, "-b");
397         sprintf(sfile_duration,"duration:%d",capture_opts->file_duration);
398         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
399       }
400
401       if (capture_opts->has_ring_num_files) {
402         argv = sync_pipe_add_arg(argv, &argc, "-b");
403         sprintf(sring_num_files,"files:%d",capture_opts->ring_num_files);
404         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
405       }
406
407       if (capture_opts->has_autostop_files) {
408         argv = sync_pipe_add_arg(argv, &argc, "-a");
409         sprintf(sautostop_files,"files:%d",capture_opts->autostop_files);
410         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
411       }
412     } else {
413         if (capture_opts->has_autostop_filesize) {
414           argv = sync_pipe_add_arg(argv, &argc, "-a");
415           sprintf(sautostop_filesize,"filesize:%d",capture_opts->autostop_filesize);
416           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
417         }
418     }
419
420     if (capture_opts->has_autostop_packets) {
421       argv = sync_pipe_add_arg(argv, &argc, "-c");
422       sprintf(scount,"%d",capture_opts->autostop_packets);
423       argv = sync_pipe_add_arg(argv, &argc, scount);
424     }
425
426     if (capture_opts->has_autostop_duration) {
427       argv = sync_pipe_add_arg(argv, &argc, "-a");
428       sprintf(sautostop_duration,"duration:%d",capture_opts->autostop_duration);
429       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
430     }
431
432     if (!capture_opts->show_info) {
433       argv = sync_pipe_add_arg(argv, &argc, "-H");
434     }
435
436     if (!capture_opts->promisc_mode)
437       argv = sync_pipe_add_arg(argv, &argc, "-p");
438
439 #ifdef _WIN32
440     /* Create a pipe for the child process */
441     /* (inrease this value if you have trouble while fast capture file switches) */
442     if(_pipe(sync_pipe, 5120, O_BINARY) < 0) {
443       /* Couldn't create the pipe between parent and child. */
444       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
445                         strerror(errno));
446       g_free(argv);
447       return FALSE;
448     }
449
450     /* Create a pipe for the parent process */
451     if(_pipe(signal_pipe, 512, O_BINARY) < 0) {
452       /* Couldn't create the signal pipe between parent and child. */
453       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
454                         strerror(errno));
455       close(sync_pipe[PIPE_READ]);
456       close(sync_pipe[PIPE_WRITE]);
457       g_free(argv);
458       return FALSE;
459     }
460
461     capture_opts->signal_pipe_fd = signal_pipe[PIPE_WRITE];
462
463     argv = sync_pipe_add_arg(argv, &argc, "-B");
464     sprintf(buffer_size,"%d",capture_opts->buffer_size);
465     argv = sync_pipe_add_arg(argv, &argc, buffer_size);
466
467     /* Convert font name to a quote-encapsulated string and pass to child */
468     argv = sync_pipe_add_arg(argv, &argc, "-m");
469     fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
470     argv = sync_pipe_add_arg(argv, &argc, fontstring);
471
472     /* Convert sync pipe write handle to a string and pass to child */
473     argv = sync_pipe_add_arg(argv, &argc, "-Z");
474     sprintf(sync_pipe_fd,"sync:%d",sync_pipe[PIPE_WRITE]);
475     argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
476
477     /* Convert signal pipe read handle to a string and pass to child */
478     argv = sync_pipe_add_arg(argv, &argc, "-Z");
479     sprintf(signal_pipe_fd,"signal:%d",signal_pipe[PIPE_READ]);
480     argv = sync_pipe_add_arg(argv, &argc, signal_pipe_fd);
481
482     /* Convert filter string to a quote delimited string and pass to child */
483     filterstring = NULL;
484     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
485       argv = sync_pipe_add_arg(argv, &argc, "-f");
486       filterstring = sync_pipe_quote_encapsulate(capture_opts->cfilter);
487       argv = sync_pipe_add_arg(argv, &argc, filterstring);
488     }
489
490     /* Convert save file name to a quote delimited string and pass to child */
491     savefilestring = NULL;
492     if(capture_opts->save_file) {
493       argv = sync_pipe_add_arg(argv, &argc, "-w");
494       savefilestring = sync_pipe_quote_encapsulate(capture_opts->save_file);
495       argv = sync_pipe_add_arg(argv, &argc, savefilestring);
496     }
497
498     /* Spawn process */
499     capture_opts->fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
500     g_free(fontstring);
501     if (filterstring) {
502       g_free(filterstring);
503     }
504     if(savefilestring) {
505       g_free(savefilestring);
506     }
507
508     /* child own's the read side now, close our handle */
509     close(signal_pipe[PIPE_READ]);
510 #else
511     if (pipe(sync_pipe) < 0) {
512       /* Couldn't create the pipe between parent and child. */
513       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
514                         strerror(errno));
515       g_free(argv);
516       return FALSE;
517     }
518
519     argv = sync_pipe_add_arg(argv, &argc, "-m");
520     argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
521
522     if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
523       argv = sync_pipe_add_arg(argv, &argc, "-f");
524       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
525     }
526
527     if(capture_opts->save_file) {
528       argv = sync_pipe_add_arg(argv, &argc, "-w");
529       argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
530     }
531
532     if ((capture_opts->fork_child = fork()) == 0) {
533       /*
534        * Child process - run Ethereal with the right arguments to make
535        * it just pop up the live capture dialog box and capture with
536        * the specified capture parameters, writing to the specified file.
537        *
538        * args: -i interface specification
539        * -w file to write
540        * -W file descriptor to write
541        * -c count to capture
542        * -s snaplen
543        * -m / -b fonts
544        * -f "filter expression"
545        */
546       close(1);
547       dup(sync_pipe[PIPE_WRITE]);
548       close(sync_pipe[PIPE_READ]);
549       execvp(ethereal_path, argv);
550       snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
551                 ethereal_path, strerror(errno));
552       sync_pipe_errmsg_to_parent(errmsg);
553
554       /* Exit with "_exit()", so that we don't close the connection
555          to the X server (and cause stuff buffered up by our parent but
556          not yet sent to be sent, as that stuff should only be sent by
557          our parent). */
558       _exit(2);
559     }
560 #endif
561
562     /* Parent process - read messages from the child process over the
563        sync pipe. */
564     g_free(argv);       /* free up arg array */
565
566     /* Close the write side of the pipe, so that only the child has it
567        open, and thus it completely closes, and thus returns to us
568        an EOF indication, if the child closes it (either deliberately
569        or by exiting abnormally). */
570     close(sync_pipe[PIPE_WRITE]);
571
572     if (capture_opts->fork_child == -1) {
573       /* We couldn't even create the child process. */
574       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
575                         "Couldn't create child process: %s", strerror(errno));
576       close(sync_pipe[PIPE_READ]);
577 #ifdef _WIN32
578       close(signal_pipe[PIPE_WRITE]);
579 #endif
580       return FALSE;
581     }
582
583     /* we might wait for a moment till child is ready, so update screen now */
584     main_window_update();
585
586     /* We were able to set up to read the capture file;
587        arrange that our callback be called whenever it's possible
588        to read from the sync pipe, so that it's called when
589        the child process wants to tell us something. */
590
591     /* we have a running capture, now wait for the real capture filename */
592     pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) capture_opts, 
593         &capture_opts->fork_child, sync_pipe_input_cb);
594
595     return TRUE;
596 }
597
598 /* There's stuff to read from the sync pipe, meaning the child has sent
599    us a message, or the sync pipe has closed, meaning the child has
600    closed it (perhaps because it exited). */
601 static gboolean 
602 sync_pipe_input_cb(gint source, gpointer user_data)
603 {
604   capture_options *capture_opts = (capture_options *)user_data;
605 #define BUFSIZE 4096
606   char buffer[BUFSIZE+1];
607   int  nread;
608   char indicator;
609
610
611   nread = pipe_read_block(source, &indicator, BUFSIZE, buffer);
612   if(nread <= 0) {
613     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
614
615     /* The child has closed the sync pipe, meaning it's not going to be
616        capturing any more packets.  Pick up its exit status, and
617        complain if it did anything other than exit with status 0. */
618     sync_pipe_wait_for_child(capture_opts);
619
620 #ifdef _WIN32
621     close(capture_opts->signal_pipe_fd);
622 #endif
623     capture_input_closed(capture_opts);
624     return FALSE;
625   }
626
627   switch(indicator) {
628   case SP_FILE:
629       if(!capture_input_new_file(capture_opts, buffer)) {
630         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
631
632         /* We weren't able to open the new capture file; user has been
633            alerted. Close the sync pipe. */
634         /* XXX - is it safe to close the pipe inside this callback? */
635         close(source);
636
637         /* the child has send us a filename which we couldn't open.
638            this probably means, the child is creating files faster than we can handle it.
639            this should only be the case for very fast file switches
640            we can't do much more than telling the child to stop
641            (this is the emergency brake if user e.g. wants to switch files every second) */
642         sync_pipe_stop(capture_opts);
643       }
644       break;
645   case SP_PACKET_COUNT:
646     nread = atoi(buffer);
647     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
648     capture_input_new_packets(capture_opts, nread);
649     break;
650   case SP_ERROR_MSG:
651     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_MESSAGE, "Error message from child: \"%s\"", buffer);
652     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, buffer);
653     /* the capture child will close the sync_pipe, nothing to do for now */
654     break;
655   case SP_DROPS:
656     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_INFO, "%d packet%s dropped", atoi(buffer), plurality(atoi(buffer), "", "s"));
657     cf_set_drops_known(capture_opts->cf, TRUE);
658     cf_set_drops(capture_opts->cf, atoi(buffer));
659     break;
660   default:
661       g_assert_not_reached();
662   }
663
664   return TRUE;
665 }
666
667
668
669 /* the child process is going down, wait until it's completely terminated */
670 static void
671 sync_pipe_wait_for_child(capture_options *capture_opts)
672 {
673   int  wstatus;
674
675
676   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: wait till child closed");
677   g_assert(capture_opts->fork_child != -1);
678
679 #ifdef _WIN32
680   /* XXX - analyze the wait status and display more information
681      in the dialog box?
682      XXX - set "fork_child" to -1 if we find it exited? */
683   if (_cwait(&wstatus, capture_opts->fork_child, _WAIT_CHILD) == -1) {
684     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
685                 "Child capture process stopped unexpectedly");
686   }
687 #else
688   if (wait(&wstatus) != -1) {
689     if (WIFEXITED(wstatus)) {
690       /* The child exited; display its exit status, if it seems uncommon (0=ok, 1=error) */
691       /* the child will inform us about errors through the sync_pipe, which will popup */
692       /* an error message, so don't popup another one */
693
694       /* XXX - if there are situations where the child won't send us such an error message, */
695       /* this should be fixed in the child and not here! */
696       if (WEXITSTATUS(wstatus) != 0 && WEXITSTATUS(wstatus) != 1) {
697         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
698                       "Child capture process exited: exit status %d",
699                       WEXITSTATUS(wstatus));
700       }
701     } else if (WIFSTOPPED(wstatus)) {
702       /* It stopped, rather than exiting.  "Should not happen." */
703       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
704                     "Child capture process stopped: %s",
705                     sync_pipe_signame(WSTOPSIG(wstatus)));
706     } else if (WIFSIGNALED(wstatus)) {
707       /* It died with a signal. */
708       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
709                     "Child capture process died: %s%s",
710                     sync_pipe_signame(WTERMSIG(wstatus)),
711                     WCOREDUMP(wstatus) ? " - core dumped" : "");
712     } else {
713       /* What?  It had to either have exited, or stopped, or died with
714          a signal; what happened here? */
715       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
716                     "Child capture process died: wait status %#o", wstatus);
717     }
718   }
719
720   /* No more child process. */
721   capture_opts->fork_child = -1;
722 #endif
723
724   g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_wait_for_child: capture child closed");
725 }
726
727
728 #ifndef _WIN32
729 /* convert signal to corresponding name */
730 static char *
731 sync_pipe_signame(int sig)
732 {
733   char *sigmsg;
734   static char sigmsg_buf[6+1+3+1];
735
736   switch (sig) {
737
738   case SIGHUP:
739     sigmsg = "Hangup";
740     break;
741
742   case SIGINT:
743     sigmsg = "Interrupted";
744     break;
745
746   case SIGQUIT:
747     sigmsg = "Quit";
748     break;
749
750   case SIGILL:
751     sigmsg = "Illegal instruction";
752     break;
753
754   case SIGTRAP:
755     sigmsg = "Trace trap";
756     break;
757
758   case SIGABRT:
759     sigmsg = "Abort";
760     break;
761
762   case SIGFPE:
763     sigmsg = "Arithmetic exception";
764     break;
765
766   case SIGKILL:
767     sigmsg = "Killed";
768     break;
769
770   case SIGBUS:
771     sigmsg = "Bus error";
772     break;
773
774   case SIGSEGV:
775     sigmsg = "Segmentation violation";
776     break;
777
778   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
779      Linux is POSIX compliant.  These are not POSIX-defined signals ---
780      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
781
782         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
783         were omitted from POSIX.1 because their behavior is
784         implementation dependent and could not be adequately catego-
785         rized.  Conforming implementations may deliver these sig-
786         nals, but must document the circumstances under which they
787         are delivered and note any restrictions concerning their
788         delivery.''
789
790      So we only check for SIGSYS on those systems that happen to
791      implement them (a system can be POSIX-compliant and implement
792      them, it's just that POSIX doesn't *require* a POSIX-compliant
793      system to implement them).
794    */
795
796 #ifdef SIGSYS
797   case SIGSYS:
798     sigmsg = "Bad system call";
799     break;
800 #endif
801
802   case SIGPIPE:
803     sigmsg = "Broken pipe";
804     break;
805
806   case SIGALRM:
807     sigmsg = "Alarm clock";
808     break;
809
810   case SIGTERM:
811     sigmsg = "Terminated";
812     break;
813
814   default:
815     sprintf(sigmsg_buf, "Signal %d", sig);
816     sigmsg = sigmsg_buf;
817     break;
818   }
819   return sigmsg;
820 }
821 #endif
822
823
824 /* user wants to stop the capture run */
825 void
826 sync_pipe_stop(capture_options *capture_opts)
827 {
828   /* XXX - in which cases this will be 0? */
829   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
830 #ifndef _WIN32
831     /* send the SIGUSR1 signal to close the capture child gracefully. */
832     kill(capture_opts->fork_child, SIGUSR1);
833 #else
834     /* Win32 doesn't have the kill() system call, use the special signal pipe 
835        instead to close the capture child gracefully. */
836     signal_pipe_capquit_to_child(capture_opts);
837 #endif
838   }
839 }
840
841
842 /* Ethereal has to exit, force the capture child to close */
843 void
844 sync_pipe_kill(capture_options *capture_opts)
845 {
846   /* XXX - in which cases this will be 0? */
847   if (capture_opts->fork_child != -1 && capture_opts->fork_child != 0) {
848 #ifndef _WIN32
849       kill(capture_opts->fork_child, SIGTERM);  /* SIGTERM so it can clean up if necessary */
850 #else
851       /* XXX: this is not the preferred method of closing a process!
852        * the clean way would be getting the process id of the child process,
853        * then getting window handle hWnd of that process (using EnumChildWindows),
854        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
855        *
856        * Unfortunately, I don't know how to get the process id from the
857        * handle.  OpenProcess will get an handle (not a window handle)
858        * from the process ID; it will not get a window handle from the
859        * process ID.  (How could it?  A process can have more than one
860        * window.)
861        *
862        * Hint: GenerateConsoleCtrlEvent() will only work if both processes are 
863        * running in the same console; that's not necessarily the case for
864        * us, as we might not be running in a console.
865        * And this also will require to have the process id.
866        */
867       TerminateProcess((HANDLE) (capture_opts->fork_child), 0);
868 #endif
869   }
870 }
871
872 #endif /* HAVE_LIBPCAP */