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