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