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