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