source: trunk/third/tcp_wrappers/shell_cmd.c @ 11717

Revision 11717, 2.1 KB checked in by danw, 26 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r11716, which included commits to RCS files with non-trunk default branches.
Line 
1 /*
2  * shell_cmd() takes a shell command after %<character> substitutions. The
3  * command is executed by a /bin/sh child process, with standard input,
4  * standard output and standard error connected to /dev/null.
5  *
6  * Diagnostics are reported through syslog(3).
7  *
8  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
9  */
10
11#ifndef lint
12static char sccsid[] = "@(#) shell_cmd.c 1.5 94/12/28 17:42:44";
13#endif
14
15/* System libraries. */
16
17#include <sys/types.h>
18#include <sys/param.h>
19#include <signal.h>
20#include <stdio.h>
21#include <syslog.h>
22#include <string.h>
23
24extern void exit();
25
26/* Local stuff. */
27
28#include "tcpd.h"
29
30/* Forward declarations. */
31
32static void do_child();
33
34/* shell_cmd - execute shell command */
35
36void    shell_cmd(command)
37char   *command;
38{
39    int     child_pid;
40    int     wait_pid;
41
42    /*
43     * Most of the work is done within the child process, to minimize the
44     * risk of damage to the parent.
45     */
46
47    switch (child_pid = fork()) {
48    case -1:                                    /* error */
49        tcpd_warn("cannot fork: %m");
50        break;
51    case 00:                                    /* child */
52        do_child(command);
53        /* NOTREACHED */
54    default:                                    /* parent */
55        while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
56             /* void */ ;
57    }
58}
59
60/* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
61
62static void do_child(command)
63char   *command;
64{
65    char   *error;
66    int     tmp_fd;
67
68    /*
69     * Systems with POSIX sessions may send a SIGHUP to grandchildren if the
70     * child exits first. This is sick, sessions were invented for terminals.
71     */
72
73    signal(SIGHUP, SIG_IGN);
74
75    /* Set up new stdin, stdout, stderr, and exec the shell command. */
76
77    for (tmp_fd = 0; tmp_fd < 3; tmp_fd++)
78        (void) close(tmp_fd);
79    if (open("/dev/null", 2) != 0) {
80        error = "open /dev/null: %m";
81    } else if (dup(0) != 1 || dup(0) != 2) {
82        error = "dup: %m";
83    } else {
84        (void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
85        error = "execl /bin/sh: %m";
86    }
87
88    /* Something went wrong. We MUST terminate the child process. */
89
90    tcpd_warn(error);
91    _exit(0);
92}
Note: See TracBrowser for help on using the repository browser.