recipes: x-apps/emacs: Enable emacs again, trying the -no-pie option
[dragora.git] / patches / tcp_wrappers / catch-sigchld
blob9fc64fbe78ae39f0c2997d8656fc21526ab06d3d
1 --- tcp_wrappers_7.6/shell_cmd.c.sigchld        1994-12-28 17:42:44.000000000 +0100
2 +++ tcp_wrappers_7.6/shell_cmd.c        2007-06-28 15:42:17.000000000 +0200
3 @@ -20,6 +20,11 @@
4  #include <stdio.h>
5  #include <syslog.h>
6  #include <string.h>
7 +#include <errno.h>
8 +#include <unistd.h>
9 +#include <sys/wait.h>
10 +#include <sys/stat.h>
11 +#include <fcntl.h>
13  extern void exit();
15 @@ -31,13 +36,42 @@
17  static void do_child();
19 +/*
20 + * The sigchld handler. If there is a SIGCHLD caused by a child other than
21 + * ours, we set a flag and raise the signal later.
22 + */
23 +volatile static int foreign_sigchld;
24 +volatile static int our_child_pid;
25 +static void sigchld(int sig, siginfo_t *si, void *unused)
27 +    if (si && si->si_pid != our_child_pid)
28 +       foreign_sigchld = 1;
31  /* shell_cmd - execute shell command */
33  void    shell_cmd(command)
34  char   *command;
35  {
36      int     child_pid;
37 -    int     wait_pid;
39 +    struct sigaction new_action, old_action;
40 +    sigset_t new_mask, old_mask, empty_mask;
42 +    new_action.sa_sigaction = &sigchld;
43 +    new_action.sa_flags = SA_SIGINFO;
44 +    sigemptyset(&new_action.sa_mask);
45 +    sigemptyset(&new_mask);
46 +    sigemptyset(&empty_mask);
47 +    sigaddset(&new_mask, SIGCHLD);
49 +    /*
50 +     * Set the variables for handler, set the handler and block the signal
51 +     * until we have the pid.
52 +     */
53 +    foreign_sigchld = 0; our_child_pid = 0;
54 +    sigprocmask(SIG_BLOCK, &new_mask, &old_mask);
55 +    sigaction(SIGCHLD, &new_action, &old_action);
57      /*
58       * Most of the work is done within the child process, to minimize the
59 @@ -49,12 +83,26 @@
60         tcpd_warn("cannot fork: %m");
61         break;
62      case 00:                                   /* child */
63 +       /* Clear the blocked mask for the child not to be surprised. */
64 +       sigprocmask(SIG_SETMASK, &empty_mask, 0);
65         do_child(command);
66         /* NOTREACHED */
67      default:                                   /* parent */
68 -       while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
69 -            /* void */ ;
70 +       our_child_pid = child_pid;
71 +       sigprocmask(SIG_UNBLOCK, &new_mask, 0);
72 +       while (waitpid(child_pid, (int *) 0, 0) == -1 && errno == EINTR);
73      }
75 +    /*
76 +     * Revert the signal mask and the SIGCHLD handler.
77 +     */
78 +    sigprocmask(SIG_SETMASK, &old_mask, 0);
79 +    sigaction(SIGCHLD, &old_action, 0);
81 +    /* If there was a foreign SIGCHLD, raise it after we have restored the old
82 +     * mask and handler. */
83 +    if (foreign_sigchld)
84 +       raise(SIGCHLD);
85  }
87  /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */