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