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