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