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