Move some #defines and #includes around, and add some other #includes,
[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 /* With MSVC and a libethereal.dll this file needs to import some variables 
26    in a special way. Therefore _NEED_VAR_IMPORT_ is defined. */
27 #define _NEED_VAR_IMPORT_
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #ifdef HAVE_LIBPCAP
34
35 #include <pcap.h>
36
37 #include <glib.h>
38 #include <stdio.h>
39 #include <ctype.h>
40 #include <string.h>
41
42 #ifdef HAVE_UNISTD_H
43 #include <unistd.h>
44 #endif
45
46 #include <signal.h>
47
48 #ifdef HAVE_SYS_WAIT_H
49 # include <sys/wait.h>
50 #endif
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
85 #include "capture.h"
86 #include "capture_sync.h"
87 #include "simple_dialog.h"
88
89 #ifdef _WIN32
90 #include "capture-wpcap.h"
91 #endif
92 #include "ui_util.h"
93
94 #ifdef HAVE_IO_H
95 # include <io.h>
96 #endif
97
98 int fork_child = -1;        /* If not -1, in parent, process ID of child */
99
100 #ifdef _WIN32
101 #include <process.h>    /* For spawning child process */
102 #endif
103
104 /* Win32 needs the O_BINARY flag for open() */
105 #ifndef O_BINARY
106 #define O_BINARY        0
107 #endif
108
109
110 #ifndef _WIN32
111 static char *sync_pipe_signame(int);
112 #endif
113
114
115 static gboolean sync_pipe_input_cb(gint source, gpointer user_data);
116 static void sync_pipe_wait_for_child(gboolean always_report);
117
118 /* Size of buffer to hold decimal representation of
119    signed/unsigned 64-bit int */
120 #define SP_DECISIZE 20
121
122 /*
123  * Indications sent out on the sync pipe.
124  */
125 #define SP_CAPSTART     ';'         /* capture start message */
126 #define SP_PACKET_COUNT '*'     /* followed by count of packets captured since last message */
127 #define SP_ERROR_MSG    '!'     /* followed by length of error message that follows */
128 #define SP_DROPS        '#'         /* followed by count of packets dropped in capture */
129
130
131
132 /* Add a string pointer to a NULL-terminated array of string pointers. */
133 static char **
134 sync_pipe_add_arg(char **args, int *argc, char *arg)
135 {
136   /* Grow the array; "*argc" currently contains the number of string
137      pointers, *not* counting the NULL pointer at the end, so we have
138      to add 2 in order to get the new size of the array, including the
139      new pointer and the terminating NULL pointer. */
140   args = g_realloc(args, (*argc + 2) * sizeof (char *));
141
142   /* Stuff the pointer into the penultimate element of the array, which
143      is the one at the index specified by "*argc". */
144   args[*argc] = arg;
145
146   /* Now bump the count. */
147   (*argc)++;
148
149   /* We overwrite the NULL pointer; put it back right after the
150      element we added. */
151   args[*argc] = NULL;
152
153   return args;
154 }
155
156 #ifdef _WIN32
157 /* Given a string, return a pointer to a quote-encapsulated version of
158    the string, so we can pass it as an argument with "spawnvp" even
159    if it contains blanks. */
160 char *
161 sync_pipe_quote_encapsulate(const char *string)
162 {
163   char *encapsulated_string;
164
165   encapsulated_string = g_new(char, strlen(string) + 3);
166   sprintf(encapsulated_string, "\"%s\"", string);
167   return encapsulated_string;
168 }
169 #endif
170
171
172
173 gboolean
174 sync_pipe_do_capture(gboolean is_tempfile) {
175     guint byte_count;
176     int  i;
177     guchar  c;
178     char *msg;
179     int  err;
180     char ssnap[24];
181     char scount[24];                    /* need a constant for len of numbers */
182     char sautostop_filesize[24];        /* need a constant for len of numbers */
183     char sautostop_duration[24];        /* need a constant for len of numbers */
184     char save_file_fd[24];
185 #ifndef _WIN32
186     char errmsg[1024+1];
187 #endif
188     int error;
189     int argc;
190     char **argv;
191 #ifdef _WIN32
192     char sync_pipe_fd[24];
193     char *fontstring;
194     char *filterstring;
195 #endif
196     enum PIPES { PIPE_READ, PIPE_WRITE };   /* Constants 0 and 1 for PIPE_READ and PIPE_WRITE */
197     int sync_pipe[2];                       /* pipes used to sync between instances */
198
199
200     fork_child = -1;
201
202     /* Allocate the string pointer array with enough space for the
203        terminating NULL pointer. */
204     argc = 0;
205     argv = g_malloc(sizeof (char *));
206     *argv = NULL;
207
208     /* Now add those arguments used on all platforms. */
209     argv = sync_pipe_add_arg(argv, &argc, CHILD_NAME);
210
211     argv = sync_pipe_add_arg(argv, &argc, "-i");
212     argv = sync_pipe_add_arg(argv, &argc, cfile.iface);
213
214     argv = sync_pipe_add_arg(argv, &argc, "-w");
215     argv = sync_pipe_add_arg(argv, &argc, cfile.save_file);
216
217     argv = sync_pipe_add_arg(argv, &argc, "-W");
218     sprintf(save_file_fd,"%d",cfile.save_file_fd);      /* in lieu of itoa */
219     argv = sync_pipe_add_arg(argv, &argc, save_file_fd);
220
221     if (capture_opts.has_autostop_packets) {
222       argv = sync_pipe_add_arg(argv, &argc, "-c");
223       sprintf(scount,"%d",capture_opts.autostop_packets);
224       argv = sync_pipe_add_arg(argv, &argc, scount);
225     }
226
227     if (capture_opts.has_snaplen) {
228       argv = sync_pipe_add_arg(argv, &argc, "-s");
229       sprintf(ssnap,"%d",capture_opts.snaplen);
230       argv = sync_pipe_add_arg(argv, &argc, ssnap);
231     }
232
233     if (capture_opts.linktype != -1) {
234       argv = sync_pipe_add_arg(argv, &argc, "-y");
235 #ifdef HAVE_PCAP_DATALINK_VAL_TO_NAME
236       sprintf(ssnap,"%s",pcap_datalink_val_to_name(capture_opts.linktype));
237 #else
238       /* XXX - just treat it as a number */
239       sprintf(ssnap,"%d",capture_opts.linktype);
240 #endif
241       argv = sync_pipe_add_arg(argv, &argc, ssnap);
242     }
243
244     if (capture_opts.has_autostop_filesize) {
245       argv = sync_pipe_add_arg(argv, &argc, "-a");
246       sprintf(sautostop_filesize,"filesize:%d",capture_opts.autostop_filesize);
247       argv = sync_pipe_add_arg(argv, &argc, sautostop_filesize);
248     }
249
250     if (capture_opts.has_autostop_duration) {
251       argv = sync_pipe_add_arg(argv, &argc, "-a");
252       sprintf(sautostop_duration,"duration:%d",capture_opts.autostop_duration);
253       argv = sync_pipe_add_arg(argv, &argc, sautostop_duration);
254     }
255
256     if (!capture_opts.show_info) {
257       argv = sync_pipe_add_arg(argv, &argc, "-H");
258     }
259
260     if (!capture_opts.promisc_mode)
261       argv = sync_pipe_add_arg(argv, &argc, "-p");
262
263 #ifdef _WIN32
264     /* Create a pipe for the child process */
265
266     if(_pipe(sync_pipe, 512, O_BINARY) < 0) {
267       /* Couldn't create the pipe between parent and child. */
268       error = errno;
269       unlink(cfile.save_file);
270       g_free(cfile.save_file);
271       cfile.save_file = NULL;
272       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
273                         strerror(error));
274       return FALSE;
275     }
276
277     /* Convert font name to a quote-encapsulated string and pass to child */
278     argv = sync_pipe_add_arg(argv, &argc, "-m");
279     fontstring = sync_pipe_quote_encapsulate(prefs.PREFS_GUI_FONT_NAME);
280     argv = sync_pipe_add_arg(argv, &argc, fontstring);
281
282     /* Convert pipe write handle to a string and pass to child */
283     argv = sync_pipe_add_arg(argv, &argc, "-Z");
284     itoa(sync_pipe[PIPE_WRITE], sync_pipe_fd, 10);
285     argv = sync_pipe_add_arg(argv, &argc, sync_pipe_fd);
286
287     /* Convert filter string to a quote delimited string and pass to child */
288     filterstring = NULL;
289     if (cfile.cfilter != NULL && strlen(cfile.cfilter) != 0) {
290       argv = sync_pipe_add_arg(argv, &argc, "-f");
291       filterstring = sync_pipe_quote_encapsulate(cfile.cfilter);
292       argv = sync_pipe_add_arg(argv, &argc, filterstring);
293     }
294
295     /* Spawn process */
296     fork_child = spawnvp(_P_NOWAIT, ethereal_path, argv);
297     g_free(fontstring);
298     if (filterstring) {
299       g_free(filterstring);
300     }
301 #else
302     if (pipe(sync_pipe) < 0) {
303       /* Couldn't create the pipe between parent and child. */
304       error = errno;
305       unlink(cfile.save_file);
306       g_free(cfile.save_file);
307       cfile.save_file = NULL;
308       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, "Couldn't create sync pipe: %s",
309                         strerror(error));
310       return FALSE;
311     }
312
313     argv = sync_pipe_add_arg(argv, &argc, "-m");
314     argv = sync_pipe_add_arg(argv, &argc, prefs.PREFS_GUI_FONT_NAME);
315
316     if (cfile.cfilter != NULL && strlen(cfile.cfilter) != 0) {
317       argv = sync_pipe_add_arg(argv, &argc, "-f");
318       argv = sync_pipe_add_arg(argv, &argc, cfile.cfilter);
319     }
320
321     if ((fork_child = fork()) == 0) {
322       /*
323        * Child process - run Ethereal with the right arguments to make
324        * it just pop up the live capture dialog box and capture with
325        * the specified capture parameters, writing to the specified file.
326        *
327        * args: -i interface specification
328        * -w file to write
329        * -W file descriptor to write
330        * -c count to capture
331        * -s snaplen
332        * -m / -b fonts
333        * -f "filter expression"
334        */
335       close(1);
336       dup(sync_pipe[PIPE_WRITE]);
337       close(sync_pipe[PIPE_READ]);
338       execvp(ethereal_path, argv);
339       snprintf(errmsg, sizeof errmsg, "Couldn't run %s in child process: %s",
340                 ethereal_path, strerror(errno));
341       sync_pipe_errmsg_to_parent(errmsg);
342
343       /* Exit with "_exit()", so that we don't close the connection
344          to the X server (and cause stuff buffered up by our parent but
345          not yet sent to be sent, as that stuff should only be sent by
346          our parent). */
347       _exit(2);
348     }
349 #endif
350
351     /* Parent process - read messages from the child process over the
352        sync pipe. */
353     g_free(argv);       /* free up arg array */
354
355     /* Close the write side of the pipe, so that only the child has it
356        open, and thus it completely closes, and thus returns to us
357        an EOF indication, if the child closes it (either deliberately
358        or by exiting abnormally). */
359     close(sync_pipe[PIPE_WRITE]);
360
361     /* Close the save file FD, as we won't be using it - we'll be opening
362        it and reading the save file through Wiretap. */
363     close(cfile.save_file_fd);
364
365     if (fork_child == -1) {
366       /* We couldn't even create the child process. */
367       error = errno;
368       close(sync_pipe[PIPE_READ]);
369       unlink(cfile.save_file);
370       g_free(cfile.save_file);
371       cfile.save_file = NULL;
372       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
373                         "Couldn't create child process: %s", strerror(error));
374       return FALSE;
375     }
376
377     /* Read a byte count from "sync_pipe[PIPE_READ]", terminated with a
378        colon; if the count is 0, the child process created the
379        capture file and we should start reading from it, otherwise
380        the capture couldn't start and the count is a count of bytes
381        of error message, and we should display the message. */
382     byte_count = 0;
383     for (;;) {
384       i = read(sync_pipe[PIPE_READ], &c, 1);
385       if (i == 0) {
386         /* EOF - the child process died.
387            Close the read side of the sync pipe, remove the capture file,
388            and report the failure. */
389         close(sync_pipe[PIPE_READ]);
390         unlink(cfile.save_file);
391         g_free(cfile.save_file);
392         cfile.save_file = NULL;
393         sync_pipe_wait_for_child(TRUE);
394         return FALSE;
395       }
396       if (c == SP_CAPSTART || c == SP_ERROR_MSG)
397         break;
398       if (!isdigit(c)) {
399         /* Child process handed us crap.
400            Close the read side of the sync pipe, remove the capture file,
401            and report the failure. */
402         close(sync_pipe[PIPE_READ]);
403         unlink(cfile.save_file);
404         g_free(cfile.save_file);
405         cfile.save_file = NULL;
406         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
407                         "Capture child process sent us a bad message");
408         return FALSE;
409       }
410       byte_count = byte_count*10 + c - '0';
411     }
412     if (c != SP_CAPSTART) {
413       /* Failure - the child process sent us a message indicating
414          what the problem was. */
415       if (byte_count == 0) {
416         /* Zero-length message? */
417         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
418                 "Capture child process failed, but its error message was empty.");
419       } else {
420         msg = g_malloc(byte_count + 1);
421         if (msg == NULL) {
422           simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
423                 "Capture child process failed, but its error message was too big.");
424         } else {
425           i = read(sync_pipe[PIPE_READ], msg, byte_count);
426           msg[byte_count] = '\0';
427           if (i < 0) {
428             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
429                   "Capture child process failed: Error %s reading its error message.",
430                   strerror(errno));
431           } else if (i == 0) {
432             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
433                   "Capture child process failed: EOF reading its error message.");
434             sync_pipe_wait_for_child(FALSE);
435           } else
436             simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
437           g_free(msg);
438         }
439
440         /* Close the sync pipe. */
441         close(sync_pipe[PIPE_READ]);
442
443         /* Get rid of the save file - the capture never started. */
444         unlink(cfile.save_file);
445         g_free(cfile.save_file);
446         cfile.save_file = NULL;
447       }
448       return FALSE;
449     }
450
451     /* The child process started a capture.
452        Attempt to open the capture file and set up to read it. */
453     err = cf_start_tail(cfile.save_file, is_tempfile, &cfile);
454     if (err != 0) {
455       /* We weren't able to open the capture file; user has been
456          alerted. Close the sync pipe. */
457
458       close(sync_pipe[PIPE_READ]);
459
460       /* Don't unlink the save file - leave it around, for debugging
461          purposes. */
462       g_free(cfile.save_file);
463       cfile.save_file = NULL;
464       return FALSE;
465     }
466     /* We were able to open and set up to read the capture file;
467        arrange that our callback be called whenever it's possible
468        to read from the sync pipe, so that it's called when
469        the child process wants to tell us something. */
470     pipe_input_set_handler(sync_pipe[PIPE_READ], (gpointer) &cfile, &fork_child, sync_pipe_input_cb);
471
472     return TRUE;
473 }
474
475
476 /* There's stuff to read from the sync pipe, meaning the child has sent
477    us a message, or the sync pipe has closed, meaning the child has
478    closed it (perhaps because it exited). */
479 static gboolean 
480 sync_pipe_input_cb(gint source, gpointer user_data)
481 {
482   capture_file *cf = (capture_file *)user_data;
483 #define BUFSIZE 4096
484   char buffer[BUFSIZE+1], *p = buffer, *q = buffer, *msg, *r;
485   int  nread, msglen, chars_to_copy;
486   int  to_read = 0;
487   int  err;
488
489
490   if ((nread = read(source, buffer, BUFSIZE)) <= 0) {
491     /* The child has closed the sync pipe, meaning it's not going to be
492        capturing any more packets.  Pick up its exit status, and
493        complain if it did anything other than exit with status 0. */
494     sync_pipe_wait_for_child(FALSE);
495
496     /* Read what remains of the capture file, and finish the capture.
497        XXX - do something if this fails? */
498     switch (cf_finish_tail(cf, &err)) {
499
500     case READ_SUCCESS:
501         if(cf->count == 0) {
502           simple_dialog(ESD_TYPE_INFO, ESD_BTN_OK, 
503           "%sNo packets captured!%s\n\n"
504           "As no data was captured, closing the %scapture file!",
505           simple_dialog_primary_start(), simple_dialog_primary_end(),
506           (cf->is_tempfile) ? "temporary " : "");
507           cf_close(cf);
508         }
509         break;
510     case READ_ERROR:
511       /* Just because we got an error, that doesn't mean we were unable
512          to read any of the file; we handle what we could get from the
513          file. */
514       break;
515
516     case READ_ABORTED:
517       /* Exit by leaving the main loop, so that any quit functions
518          we registered get called. */
519       main_window_quit();
520       return FALSE;
521     }
522
523     /* We're not doing a capture any more, so we don't have a save
524        file. */
525     g_free(cf->save_file);
526     cf->save_file = NULL;
527
528     return FALSE;
529   }
530
531   buffer[nread] = '\0';
532
533   while (nread != 0) {
534     /* look for (possibly multiple) indications */
535     switch (*q) {
536     case SP_PACKET_COUNT :
537       to_read += atoi(p);
538       p = q + 1;
539       q++;
540       nread--;
541       break;
542     case SP_DROPS :
543       cf->drops_known = TRUE;
544       cf->drops = atoi(p);
545       p = q + 1;
546       q++;
547       nread--;
548       break;
549     case SP_ERROR_MSG :
550       msglen = atoi(p);
551       p = q + 1;
552       q++;
553       nread--;
554
555       /* Read the entire message.
556          XXX - if the child hasn't sent it all yet, this could cause us
557          to hang until they do. */
558       msg = g_malloc(msglen + 1);
559       r = msg;
560       while (msglen != 0) {
561         if (nread == 0) {
562           /* Read more. */
563           if ((nread = read(source, buffer, BUFSIZE)) <= 0)
564             break;
565           p = buffer;
566           q = buffer;
567         }
568         chars_to_copy = MIN(msglen, nread);
569         memcpy(r, q, chars_to_copy);
570         r += chars_to_copy;
571         q += chars_to_copy;
572         nread -= chars_to_copy;
573         msglen -= chars_to_copy;
574       }
575       *r = '\0';
576       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK, msg);
577       g_free(msg);
578       break;
579     default :
580       q++;
581       nread--;
582       break;
583     }
584   }
585
586   /* Read from the capture file the number of records the child told us
587      it added.
588      XXX - do something if this fails? */
589   switch (cf_continue_tail(cf, to_read, &err)) {
590
591   case READ_SUCCESS:
592   case READ_ERROR:
593     /* Just because we got an error, that doesn't mean we were unable
594        to read any of the file; we handle what we could get from the
595        file.
596
597        XXX - abort on a read error? */
598     break;
599
600   case READ_ABORTED:
601     /* Kill the child capture process; the user wants to exit, and we
602        shouldn't just leave it running. */
603     kill_capture_child();
604     break;
605   }
606
607   return TRUE;
608 }
609
610 static void
611 sync_pipe_wait_for_child(gboolean always_report)
612 {
613   int  wstatus;
614
615 #ifdef _WIN32
616   /* XXX - analyze the wait status and display more information
617      in the dialog box?
618      XXX - set "fork_child" to -1 if we find it exited? */
619   if (_cwait(&wstatus, fork_child, _WAIT_CHILD) == -1) {
620     simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
621                 "Child capture process stopped unexpectedly");
622   }
623 #else
624   if (wait(&wstatus) != -1) {
625     if (WIFEXITED(wstatus)) {
626       /* The child exited; display its exit status, if it's not zero,
627          and even if it's zero if "always_report" is true. */
628       if (always_report || WEXITSTATUS(wstatus) != 0) {
629         simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
630                       "Child capture process exited: exit status %d",
631                       WEXITSTATUS(wstatus));
632       }
633     } else if (WIFSTOPPED(wstatus)) {
634       /* It stopped, rather than exiting.  "Should not happen." */
635       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
636                     "Child capture process stopped: %s",
637                     sync_pipe_signame(WSTOPSIG(wstatus)));
638     } else if (WIFSIGNALED(wstatus)) {
639       /* It died with a signal. */
640       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
641                     "Child capture process died: %s%s",
642                     sync_pipe_signame(WTERMSIG(wstatus)),
643                     WCOREDUMP(wstatus) ? " - core dumped" : "");
644     } else {
645       /* What?  It had to either have exited, or stopped, or died with
646          a signal; what happened here? */
647       simple_dialog(ESD_TYPE_ERROR, ESD_BTN_OK,
648                     "Child capture process died: wait status %#o", wstatus);
649     }
650   }
651
652   /* No more child process. */
653   fork_child = -1;
654 #endif
655 }
656
657 void
658 sync_pipe_errmsg_to_parent(const char *errmsg)
659 {
660     int msglen = strlen(errmsg);
661     char lenbuf[SP_DECISIZE+1+1];
662
663     sprintf(lenbuf, "%u%c", msglen, SP_ERROR_MSG);
664     write(1, lenbuf, strlen(lenbuf));
665     write(1, errmsg, msglen);
666 }
667
668 void
669 sync_pipe_drops_to_parent(int drops)
670 {
671         char tmp[SP_DECISIZE+1+1];
672         sprintf(tmp, "%d%c", drops, SP_DROPS);
673         write(1, tmp, strlen(tmp));
674 }
675
676 void
677 sync_pipe_packet_count_to_parent(int packet_count)
678 {
679     char tmp[SP_DECISIZE+1+1];
680     sprintf(tmp, "%d%c", packet_count, SP_PACKET_COUNT);
681     write(1, tmp, strlen(tmp));
682 }
683
684 void
685 sync_pipe_capstart_to_parent(void)
686 {
687     static const char capstart_msg = SP_CAPSTART;
688
689     write(1, &capstart_msg, 1);
690 }
691
692 #ifndef _WIN32
693 static char *
694 sync_pipe_signame(int sig)
695 {
696   char *sigmsg;
697   static char sigmsg_buf[6+1+3+1];
698
699   switch (sig) {
700
701   case SIGHUP:
702     sigmsg = "Hangup";
703     break;
704
705   case SIGINT:
706     sigmsg = "Interrupted";
707     break;
708
709   case SIGQUIT:
710     sigmsg = "Quit";
711     break;
712
713   case SIGILL:
714     sigmsg = "Illegal instruction";
715     break;
716
717   case SIGTRAP:
718     sigmsg = "Trace trap";
719     break;
720
721   case SIGABRT:
722     sigmsg = "Abort";
723     break;
724
725   case SIGFPE:
726     sigmsg = "Arithmetic exception";
727     break;
728
729   case SIGKILL:
730     sigmsg = "Killed";
731     break;
732
733   case SIGBUS:
734     sigmsg = "Bus error";
735     break;
736
737   case SIGSEGV:
738     sigmsg = "Segmentation violation";
739     break;
740
741   /* http://metalab.unc.edu/pub/Linux/docs/HOWTO/GCC-HOWTO
742      Linux is POSIX compliant.  These are not POSIX-defined signals ---
743      ISO/IEC 9945-1:1990 (IEEE Std 1003.1-1990), paragraph B.3.3.1.1 sez:
744
745         ``The signals SIGBUS, SIGEMT, SIGIOT, SIGTRAP, and SIGSYS
746         were omitted from POSIX.1 because their behavior is
747         implementation dependent and could not be adequately catego-
748         rized.  Conforming implementations may deliver these sig-
749         nals, but must document the circumstances under which they
750         are delivered and note any restrictions concerning their
751         delivery.''
752
753      So we only check for SIGSYS on those systems that happen to
754      implement them (a system can be POSIX-compliant and implement
755      them, it's just that POSIX doesn't *require* a POSIX-compliant
756      system to implement them).
757    */
758
759 #ifdef SIGSYS
760   case SIGSYS:
761     sigmsg = "Bad system call";
762     break;
763 #endif
764
765   case SIGPIPE:
766     sigmsg = "Broken pipe";
767     break;
768
769   case SIGALRM:
770     sigmsg = "Alarm clock";
771     break;
772
773   case SIGTERM:
774     sigmsg = "Terminated";
775     break;
776
777   default:
778     sprintf(sigmsg_buf, "Signal %d", sig);
779     sigmsg = sigmsg_buf;
780     break;
781   }
782   return sigmsg;
783 }
784 #endif
785
786
787 void
788 sync_pipe_stop(void)
789 {
790   if (fork_child != -1) {
791 #ifndef _WIN32
792       kill(fork_child, SIGUSR1);
793 #else
794       /* XXX: this is not the preferred method of closing a process!
795        * the clean way would be getting the process id of the child process,
796        * then getting window handle hWnd of that process (using EnumChildWindows),
797        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
798        *
799        * Unfortunately, I don't know how to get the process id from the handle */
800       /* Hint: OpenProcess will get an handle from the id, not vice versa :-(
801        *
802        * Hint: GenerateConsoleCtrlEvent() will only work, if both processes are 
803        * running in the same console, I don't know if that is true for our case.
804        * And this also will require to have the process id
805        */
806       TerminateProcess((HANDLE) fork_child, 0);
807 #endif
808   }
809 }
810
811
812 void
813 sync_pipe_kill(void)
814 {
815   if (fork_child != -1)
816 #ifndef _WIN32
817       kill(fork_child, SIGTERM);        /* SIGTERM so it can clean up if necessary */
818 #else
819       /* XXX: this is not the preferred method of closing a process!
820        * the clean way would be getting the process id of the child process,
821        * then getting window handle hWnd of that process (using EnumChildWindows),
822        * and then do a SendMessage(hWnd, WM_CLOSE, 0, 0) 
823        *
824        * Unfortunately, I don't know how to get the process id from the handle */
825       /* Hint: OpenProcess will get an handle from the id, not vice versa :-(
826        *
827        * Hint: GenerateConsoleCtrlEvent() will only work, if both processes are 
828        * running in the same console, I don't know if that is true for our case.
829        * And this also will require to have the process id
830        */
831       TerminateProcess((HANDLE) fork_child, 0);
832 #endif
833 }
834
835
836 #endif /* HAVE_LIBPCAP */