we still need sync_pipe_errmsg_to_parent() for the *NIX build
[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 #include <epan/filesystem.h>
82
83 #include "capture.h"
84 #include "capture_sync.h"
85 #include "simple_dialog.h"
86
87 #ifdef _WIN32
88 #include "capture-wpcap.h"
89 #endif
90 #include "ui_util.h"
91 #include "file_util.h"
92 #include "log.h"
93
94 #ifdef _WIN32
95 #include <process.h>    /* For spawning child process */
96 #endif
97
98
99 #ifndef _WIN32
100 static const char *sync_pipe_signame(int);
101 #endif
102
103
104 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
105 static void sync_pipe_wait_for_child(capture_options *capture_opts);
106
107 /*
108  * Maximum length of sync pipe message data.  Must be < 2^24, as the
109  * message length is 3 bytes.
110  * XXX - this must be large enough to handle a Really Big Filter
111  * Expression, as the error message for an incorrect filter expression
112  * is a bit larger than the filter expression.
113  */
114 #define SP_MAX_MSG_LEN  4096
115
116
117  /* write a message to the recipient pipe in the standard format 
118    (3 digit message length (excluding length and indicator field), 
119    1 byte message indicator and the rest is the message) */
120 static void
121 pipe_write_block(int pipe, char indicator, int len, const char *msg)
122 {
123     guchar header[3+1]; /* indicator + 3-byte len */
124     int ret;
125
126     /*g_warning("write %d enter", pipe);*/
127
128     g_assert(indicator < '0' || indicator > '9');
129     g_assert(len <= SP_MAX_MSG_LEN);
130
131     /* write header (indicator + 3-byte len) */
132     header[0] = indicator;
133     header[1] = (len >> 16) & 0xFF;
134     header[2] = (len >> 8) & 0xFF;
135     header[3] = (len >> 0) & 0xFF;
136
137     ret = write(pipe, header, sizeof header);
138     if(ret == -1) {
139         return;
140     }
141
142     /* write value (if we have one) */
143     if(len) {
144         /*g_warning("write %d indicator: %c value len: %u msg: %s", pipe, indicator, len, msg);*/
145         ret = write(pipe, msg, len);
146         if(ret == -1) {
147             return;
148         }
149     } else {
150         /*g_warning("write %d indicator: %c no value", pipe, indicator);*/
151     }
152
153     /*g_warning("write %d leave", pipe);*/
154 }
155
156
157 #ifndef _WIN32
158 void
159 sync_pipe_errmsg_to_parent(const char *errmsg)
160 {
161     g_log(LOG_DOMAIN_CAPTURE_CHILD, G_LOG_LEVEL_DEBUG, "sync_pipe_errmsg_to_parent: %s", errmsg);
162
163     pipe_write_block(1, SP_ERROR_MSG, strlen(errmsg)+1, errmsg);
164 }
165 #endif
166
167
168 #ifdef _WIN32
169 static void
170 signal_pipe_capquit_to_child(capture_options *capture_opts)
171 {
172
173     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "signal_pipe_capquit_to_child");
174
175     pipe_write_block(capture_opts->signal_pipe_write_fd, SP_QUIT, 0, NULL);
176 }
177 #endif
178
179
180
181 /* read a message from the sending pipe in the standard format 
182    (1-byte message indicator, 3-byte message length (excluding length
183    and indicator field), and the rest is the message) */
184 static int
185 pipe_read_block(int pipe, char *indicator, int len, char *msg) {
186     int required;
187     int newly;
188     guchar header[4];
189     int offset;
190
191
192     /* read header (indicator and 3-byte length) */
193     required = 4;
194     offset = 0;
195     while(required) {
196         newly = read(pipe, &header[offset], required);
197         if (newly == 0) {
198             /* EOF */
199             /*g_warning("read %d header empty (capture closed)", pipe);*/
200             return newly;
201         }
202         if (newly < 0) {
203             /* error */
204             /*g_warning("read %d header error: %s", pipe, strerror(errno));*/
205             return newly;
206         }
207
208         required -= newly;
209         offset += newly;
210     }
211
212     /* convert header values */
213     *indicator = header[0];
214     required = header[1]<<16 | header[2]<<8 | header[3];
215
216     /* only indicator with no value? */
217     if(required == 0) {
218         /*g_warning("read %d indicator: %c empty value", pipe, *indicator);*/
219         return 4;
220     }
221
222     if(required > len) {
223         return -1;
224     }
225     len = required;
226
227     /* read value */
228     offset = 0;
229     while(required) {
230         newly = read(pipe, &msg[offset], required);
231         if (newly == -1) {
232             /* error */
233             /*g_warning("read %d value error, indicator: %u", pipe, *indicator);*/
234             return newly;
235         }
236
237         required -= newly;
238         offset += newly;
239     }
240
241     /*g_warning("read %d ok indicator: %c len: %u msg: %s", pipe, *indicator, len, msg);*/
242     return len + 4;
243 }
244
245
246
247 /* Add a string pointer to a NULL-terminated array of string pointers. */
248 static const char **
249 sync_pipe_add_arg(const char **args, int *argc, const char *arg)
250 {
251   /* Grow the array; "*argc" currently contains the number of string
252      pointers, *not* counting the NULL pointer at the end, so we have
253      to add 2 in order to get the new size of the array, including the
254      new pointer and the terminating NULL pointer. */
255   args = g_realloc( (gpointer) args, (*argc + 2) * sizeof (char *));
256
257   /* Stuff the pointer into the penultimate element of the array, which
258      is the one at the index specified by "*argc". */
259   args[*argc] = arg;
260
261   /* Now bump the count. */
262   (*argc)++;
263
264   /* We overwrite the NULL pointer; put it back right after the
265      element we added. */
266   args[*argc] = NULL;
267
268   return args;
269 }
270
271
272
273 #define ARGV_NUMBER_LEN 24
274
275 gboolean
276 sync_pipe_start(capture_options *capture_opts) {
277     char ssnap[ARGV_NUMBER_LEN];
278     char scount[ARGV_NUMBER_LEN];
279     char sfilesize[ARGV_NUMBER_LEN];
280     char sfile_duration[ARGV_NUMBER_LEN];
281     char sring_num_files[ARGV_NUMBER_LEN];
282     char sautostop_files[ARGV_NUMBER_LEN];
283     char sautostop_filesize[ARGV_NUMBER_LEN];
284     char sautostop_duration[ARGV_NUMBER_LEN];
285 #ifdef _WIN32
286     char buffer_size[ARGV_NUMBER_LEN];
287     char *filterstring;
288     char *savefilestring;
289     HANDLE sync_pipe_read;                  /* pipe used to send messages from child to parent */
290     HANDLE sync_pipe_write;                 /* pipe used to send messages from child to parent */
291     HANDLE signal_pipe_read;                /* pipe used to send messages from parent to child (currently only stop) */
292     HANDLE signal_pipe_write;               /* pipe used to send messages from parent to child (currently only stop) */
293     GString *args = g_string_sized_new(200);
294     SECURITY_ATTRIBUTES sa; 
295     STARTUPINFO si;
296     PROCESS_INFORMATION pi;
297     int i;
298 #else
299     char errmsg[1024+1];
300     int sync_pipe[2];                       /* pipe used to send messages from child to parent */
301     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
302 #endif
303     int sync_pipe_read_fd;
304     char *dirname;
305     char *exename;
306     int argc;
307     const char **argv;
308
309
310     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_start");
311     capture_opts_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, capture_opts);
312
313     capture_opts->fork_child = -1;
314
315     /* Allocate the string pointer array with enough space for the
316        terminating NULL pointer. */
317     argc = 0;
318     argv = g_malloc(sizeof (char *));
319     *argv = NULL;
320
321     argv = sync_pipe_add_arg(argv, &argc, "-i");
322     argv = sync_pipe_add_arg(argv, &argc, capture_opts->iface);
323
324     if (capture_opts->has_snaplen) {
325       argv = sync_pipe_add_arg(argv, &argc, "-s");
326       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->snaplen);
327       argv = sync_pipe_add_arg(argv, &argc, ssnap);
328     }
329
330     if (capture_opts->linktype != -1) {
331       argv = sync_pipe_add_arg(argv, &argc, "-y");
332 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
333       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%s",pcap_datalink_val_to_name(capture_opts->linktype));
334 #else
335       /* XXX - just treat it as a number */
336       g_snprintf(ssnap, ARGV_NUMBER_LEN, "%d",capture_opts->linktype);
337 #endif
338       argv = sync_pipe_add_arg(argv, &argc, ssnap);
339     }
340
341     if(capture_opts->multi_files_on) {
342       if (capture_opts->has_autostop_filesize) {
343         argv = sync_pipe_add_arg(argv, &argc, "-b");
344         g_snprintf(sfilesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
345         argv = sync_pipe_add_arg(argv, &argc, sfilesize);
346       }
347
348       if (capture_opts->has_file_duration) {
349         argv = sync_pipe_add_arg(argv, &argc, "-b");
350         g_snprintf(sfile_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->file_duration);
351         argv = sync_pipe_add_arg(argv, &argc, sfile_duration);
352       }
353
354       if (capture_opts->has_ring_num_files) {
355         argv = sync_pipe_add_arg(argv, &argc, "-b");
356         g_snprintf(sring_num_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->ring_num_files);
357         argv = sync_pipe_add_arg(argv, &argc, sring_num_files);
358       }
359
360       if (capture_opts->has_autostop_files) {
361         argv = sync_pipe_add_arg(argv, &argc, "-a");
362         g_snprintf(sautostop_files, ARGV_NUMBER_LEN, "files:%d",capture_opts->autostop_files);
363         argv = sync_pipe_add_arg(argv, &argc, sautostop_files);
364       }
365     } else {
366         if (capture_opts->has_autostop_filesize) {
367           argv = sync_pipe_add_arg(argv, &argc, "-a");
368           g_snprintf(sautostop_filesize, ARGV_NUMBER_LEN, "filesize:%d",capture_opts->autostop_filesize);
369           argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
370         }
371     }
372
373     if (capture_opts->has_autostop_packets) {
374       argv = sync_pipe_add_arg(argv, &argc, "-c");
375       g_snprintf(scount, ARGV_NUMBER_LEN, "%d",capture_opts->autostop_packets);
376       argv = sync_pipe_add_arg(argv, &argc, scount);
377     }
378
379     if (capture_opts->has_autostop_duration) {
380       argv = sync_pipe_add_arg(argv, &argc, "-a");
381       g_snprintf(sautostop_duration, ARGV_NUMBER_LEN, "duration:%d",capture_opts->autostop_duration);
382       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
383     }
384
385     if (!capture_opts->promisc_mode)
386       argv = sync_pipe_add_arg(argv, &argc, "-p");
387
388     /* dumpcap should be running in capture child mode (hidden feature) */
389 #ifndef DEBUG_CHILD
390     argv = sync_pipe_add_arg(argv, &argc, "-Z");
391 #endif
392
393     /* take ethereal's absolute program path and replace ethereal with dumpcap */
394     dirname = get_dirname(g_strdup(ethereal_path));
395     exename = g_strdup_printf("\"%s" G_DIR_SEPARATOR_S "dumpcap\"", dirname);
396     g_free(dirname);
397
398 #ifdef _WIN32
399     argv = sync_pipe_add_arg(argv, &argc, "-B");
400     g_snprintf(buffer_size, ARGV_NUMBER_LEN, "%d",capture_opts->buffer_size);
401     argv = sync_pipe_add_arg(argv, &argc, buffer_size);
402
403     /* Convert filter string to a quote delimited string and pass to child */
404     filterstring = NULL;
405     if (capture_opts->cfilter != NULL && strlen(capture_opts->cfilter) != 0) {
406       argv = sync_pipe_add_arg(argv, &argc, "-f");
407       filterstring = g_strdup_printf("\"%s\"", capture_opts->cfilter);
408       argv = sync_pipe_add_arg(argv, &argc, filterstring);
409     }
410
411     /* Convert save file name to a quote delimited string and pass to child */
412     savefilestring = NULL;
413     if(capture_opts->save_file) {
414       argv = sync_pipe_add_arg(argv, &argc, "-w");
415       savefilestring = g_strdup_printf("\"%s\"", capture_opts->save_file);
416       argv = sync_pipe_add_arg(argv, &argc, savefilestring);
417     }
418
419     /* init SECURITY_ATTRIBUTES */
420     sa.nLength = sizeof(SECURITY_ATTRIBUTES); 
421     sa.bInheritHandle = TRUE; 
422     sa.lpSecurityDescriptor = NULL; 
423
424     /* Create a pipe for the child process */
425     /* (inrease this value if you have trouble while fast capture file switches) */
426     if (! CreatePipe(&sync_pipe_read, &sync_pipe_write, &sa, 5120)) {
427       /* Couldn't create the pipe between parent and child. */
428       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
429                         strerror(errno));
430       g_free( (gpointer) argv);
431       return FALSE;
432     }
433
434     /* Create a pipe for the parent process */
435     if (! CreatePipe(&signal_pipe_read, &signal_pipe_write, &sa, 512)) {
436       /* Couldn't create the signal pipe between parent and child. */
437       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create signal pipe: %s",
438                         strerror(errno));
439       CloseHandle(sync_pipe_read);
440       CloseHandle(sync_pipe_write);
441       g_free( (gpointer) argv);
442       return FALSE;
443     }
444
445     /* init STARTUPINFO */
446     memset(&si, 0, sizeof(si));
447     si.cb           = sizeof(si);
448 #ifdef DEBUG_CHILD
449     si.dwFlags = STARTF_USESHOWWINDOW;
450     si.wShowWindow  = SW_SHOW;
451 #else
452     si.dwFlags = STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW;
453     si.wShowWindow  = SW_HIDE;  /* this hides the console window */
454     si.hStdInput = signal_pipe_read;
455     si.hStdOutput = sync_pipe_write;
456     si.hStdError = sync_pipe_write;
457 #endif
458
459     g_string_append(args, exename);
460
461     /* convert args array into a single string */
462     /* XXX - could change sync_pipe_add_arg() instead */
463     /* there is a drawback here: the length is internally limited to 1024 bytes */
464     for(i=0; argv[i] != 0; i++) {
465         g_string_append_c(args, ' ');
466         g_string_append(args, argv[i]);
467     }
468
469     /* call dumpcap */
470         if(!CreateProcess(NULL, args->str, NULL, NULL, TRUE,
471         CREATE_NEW_CONSOLE,
472         NULL,
473         NULL,
474         &si,
475         &pi)) {
476         g_error("couldn't open dumpcap.exe!");
477     }
478     capture_opts->fork_child = (int) pi.hProcess;
479     g_string_free(args, TRUE);
480
481     /* associate the operating system filehandle to a C run-time file handle */
482     sync_pipe_read_fd = _open_osfhandle( (long) sync_pipe_read, _O_BINARY);
483
484     /* associate the operating system filehandle to a C run-time file handle */
485     capture_opts->signal_pipe_write_fd = _open_osfhandle( (long) signal_pipe_write, _O_BINARY);
486
487     if (filterstring) {
488       g_free(filterstring);
489     }
490     if(savefilestring) {
491       g_free(savefilestring);
492     }
493
494     /* child own's the read side now, close our handle */
495     CloseHandle(signal_pipe_read);
496 #else /* _WIN32 */
497     if (pipe(sync_pipe) < 0) {
498       /* Couldn't create the pipe between parent and child. */
499       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
500                         strerror(errno));
501       g_free(argv);
502       return FALSE;
503     }
504
505     if (capture_opts->cfilter != NULL && capture_opts->cfilter != 0) {
506       argv = sync_pipe_add_arg(argv, &argc, "-f");
507       argv = sync_pipe_add_arg(argv, &argc, capture_opts->cfilter);
508     }
509
510     if(capture_opts->save_file) {
511       argv = sync_pipe_add_arg(argv, &argc, "-w");
512       argv = sync_pipe_add_arg(argv, &argc, capture_opts->save_file);
513     }
514
515     if ((capture_opts->fork_child = fork()) == 0) {
516       /*
517        * Child process - run Ethereal with the right arguments to make
518        * it just pop up the live capture dialog box and capture with
519        * the specified capture parameters, writing to the specified file.
520        *
521        * args: -i interface specification
522        * -w file to write
523        * -c count to capture
524        * -s snaplen
525        * -m / -b fonts
526        * -f "filter expression"
527        */
528       eth_close(1);
529       dup(sync_pipe[PIPE_WRITE]);
530       eth_close(sync_pipe[PIPE_READ]);
531       execvp(exename, argv);
532       g_snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
533                 exename, strerror(errno));
534       sync_pipe_errmsg_to_parent(errmsg);
535
536       /* Exit with "_exit()", so that we don't close the connection
537          to the X server (and cause stuff buffered up by our parent but
538          not yet sent to be sent, as that stuff should only be sent by
539          our parent). */
540       _exit(2);
541     }
542
543     sync_pipe_read_fd = sync_pipe[PIPE_READ];
544 #endif
545
546     g_free(exename);
547
548     /* Parent process - read messages from the child process over the
549        sync pipe. */
550     g_free( (gpointer) argv);   /* free up arg array */
551
552     /* Close the write side of the pipe, so that only the child has it
553        open, and thus it completely closes, and thus returns to us
554        an EOF indication, if the child closes it (either deliberately
555        or by exiting abnormally). */
556 #ifdef _WIN32
557     CloseHandle(sync_pipe_write);
558 #else
559     eth_close(sync_pipe[PIPE_WRITE]);
560 #endif
561
562     if (capture_opts->fork_child == -1) {
563       /* We couldn't even create the child process. */
564       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
565                         "Couldn't create child process: %s", strerror(errno));
566       eth_close(sync_pipe_read_fd);
567 #ifdef _WIN32
568       eth_close(capture_opts->signal_pipe_write_fd);
569 #endif
570       return FALSE;
571     }
572
573     /* we might wait for a moment till child is ready, so update screen now */
574     main_window_update();
575
576     /* We were able to set up to read the capture file;
577        arrange that our callback be called whenever it's possible
578        to read from the sync pipe, so that it's called when
579        the child process wants to tell us something. */
580
581     /* we have a running capture, now wait for the real capture filename */
582     pipe_input_set_handler(sync_pipe_read_fd, (gpointer) capture_opts, 
583         &capture_opts->fork_child, sync_pipe_input_cb);
584
585     return TRUE;
586 }
587
588 /* There's stuff to read from the sync pipe, meaning the child has sent
589    us a message, or the sync pipe has closed, meaning the child has
590    closed it (perhaps because it exited). */
591 static gboolean 
592 sync_pipe_input_cb(gint source, gpointer user_data)
593 {
594   capture_options *capture_opts = (capture_options *)user_data;
595   char buffer[SP_MAX_MSG_LEN+1];
596   int  nread;
597   char indicator;
598
599
600   nread = pipe_read_block(source, &indicator, SP_MAX_MSG_LEN, buffer);
601   if(nread <= 0) {
602     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: child has closed sync_pipe");
603
604     /* The child has closed the sync pipe, meaning it's not going to be
605        capturing any more packets.  Pick up its exit status, and
606        complain if it did anything other than exit with status 0. */
607     sync_pipe_wait_for_child(capture_opts);
608
609 #ifdef _WIN32
610     eth_close(capture_opts->signal_pipe_write_fd);
611 #endif
612     capture_input_closed(capture_opts);
613     return FALSE;
614   }
615
616   switch(indicator) {
617   case SP_FILE:
618       if(!capture_input_new_file(capture_opts, buffer)) {
619         g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: file failed, closing capture");
620
621         /* We weren't able to open the new capture file; user has been
622            alerted. Close the sync pipe. */
623         eth_close(source);
624
625         /* the child has send us a filename which we couldn't open.
626            this probably means, the child is creating files faster than we can handle it.
627            this should only be the case for very fast file switches
628            we can't do much more than telling the child to stop
629            (this is the "emergency brake" if user e.g. wants to switch files every second) */
630         sync_pipe_stop(capture_opts);
631       }
632       break;
633   case SP_PACKET_COUNT:
634     nread = atoi(buffer);
635     g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_DEBUG, "sync_pipe_input_cb: new packets %u", nread);
636     capture_input_new_packets(capture_opts, nread);
637     break;
638   case SP_ERROR_MSG:
639     capture_input_error_message(capture_opts, buffer);
640     /* the capture child will close the sync_pipe, nothing to do for now */
641     break;
642   case SP_DROPS:
643     capture_input_drops(capture_opts, 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 */