xref: /onnv-gate/usr/src/lib/libwrap/shell_cmd.c (revision 0:68f95e015346)
1*0Sstevel@tonic-gate /*
2*0Sstevel@tonic-gate  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
3*0Sstevel@tonic-gate  * Use is subject to license terms.
4*0Sstevel@tonic-gate  */
5*0Sstevel@tonic-gate 
6*0Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
7*0Sstevel@tonic-gate 
8*0Sstevel@tonic-gate  /*
9*0Sstevel@tonic-gate   * shell_cmd() takes a shell command after %<character> substitutions. The
10*0Sstevel@tonic-gate   * command is executed by a /bin/sh child process, with standard input,
11*0Sstevel@tonic-gate   * standard output and standard error connected to /dev/null.
12*0Sstevel@tonic-gate   *
13*0Sstevel@tonic-gate   * Diagnostics are reported through syslog(3).
14*0Sstevel@tonic-gate   *
15*0Sstevel@tonic-gate   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
16*0Sstevel@tonic-gate   */
17*0Sstevel@tonic-gate 
18*0Sstevel@tonic-gate #ifndef lint
19*0Sstevel@tonic-gate static char sccsid[] = "@(#) shell_cmd.c 1.5 94/12/28 17:42:44";
20*0Sstevel@tonic-gate #endif
21*0Sstevel@tonic-gate 
22*0Sstevel@tonic-gate /* System libraries. */
23*0Sstevel@tonic-gate 
24*0Sstevel@tonic-gate #include <sys/types.h>
25*0Sstevel@tonic-gate #include <sys/param.h>
26*0Sstevel@tonic-gate #include <signal.h>
27*0Sstevel@tonic-gate #include <stdio.h>
28*0Sstevel@tonic-gate #include <stdlib.h>
29*0Sstevel@tonic-gate #include <unistd.h>
30*0Sstevel@tonic-gate #include <wait.h>
31*0Sstevel@tonic-gate #include <fcntl.h>
32*0Sstevel@tonic-gate #include <syslog.h>
33*0Sstevel@tonic-gate #include <string.h>
34*0Sstevel@tonic-gate 
35*0Sstevel@tonic-gate extern void exit();
36*0Sstevel@tonic-gate 
37*0Sstevel@tonic-gate /* Local stuff. */
38*0Sstevel@tonic-gate 
39*0Sstevel@tonic-gate #include "tcpd.h"
40*0Sstevel@tonic-gate 
41*0Sstevel@tonic-gate /* Forward declarations. */
42*0Sstevel@tonic-gate 
43*0Sstevel@tonic-gate static void do_child();
44*0Sstevel@tonic-gate 
45*0Sstevel@tonic-gate /* shell_cmd - execute shell command */
46*0Sstevel@tonic-gate 
shell_cmd(command)47*0Sstevel@tonic-gate void    shell_cmd(command)
48*0Sstevel@tonic-gate char   *command;
49*0Sstevel@tonic-gate {
50*0Sstevel@tonic-gate     int     child_pid;
51*0Sstevel@tonic-gate     int     wait_pid;
52*0Sstevel@tonic-gate 
53*0Sstevel@tonic-gate     /*
54*0Sstevel@tonic-gate      * Most of the work is done within the child process, to minimize the
55*0Sstevel@tonic-gate      * risk of damage to the parent.
56*0Sstevel@tonic-gate      */
57*0Sstevel@tonic-gate 
58*0Sstevel@tonic-gate     switch (child_pid = fork()) {
59*0Sstevel@tonic-gate     case -1:					/* error */
60*0Sstevel@tonic-gate 	tcpd_warn("cannot fork: %m");
61*0Sstevel@tonic-gate 	break;
62*0Sstevel@tonic-gate     case 00:					/* child */
63*0Sstevel@tonic-gate 	do_child(command);
64*0Sstevel@tonic-gate 	/* NOTREACHED */
65*0Sstevel@tonic-gate     default:					/* parent */
66*0Sstevel@tonic-gate 	while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
67*0Sstevel@tonic-gate 	     /* void */ ;
68*0Sstevel@tonic-gate     }
69*0Sstevel@tonic-gate }
70*0Sstevel@tonic-gate 
71*0Sstevel@tonic-gate /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
72*0Sstevel@tonic-gate 
do_child(command)73*0Sstevel@tonic-gate static void do_child(command)
74*0Sstevel@tonic-gate char   *command;
75*0Sstevel@tonic-gate {
76*0Sstevel@tonic-gate     char   *error;
77*0Sstevel@tonic-gate     int     tmp_fd;
78*0Sstevel@tonic-gate 
79*0Sstevel@tonic-gate     /*
80*0Sstevel@tonic-gate      * Systems with POSIX sessions may send a SIGHUP to grandchildren if the
81*0Sstevel@tonic-gate      * child exits first. This is sick, sessions were invented for terminals.
82*0Sstevel@tonic-gate      */
83*0Sstevel@tonic-gate 
84*0Sstevel@tonic-gate     signal(SIGHUP, SIG_IGN);
85*0Sstevel@tonic-gate 
86*0Sstevel@tonic-gate     /* Set up new stdin, stdout, stderr, and exec the shell command. */
87*0Sstevel@tonic-gate 
88*0Sstevel@tonic-gate     for (tmp_fd = 0; tmp_fd < 3; tmp_fd++)
89*0Sstevel@tonic-gate 	(void) close(tmp_fd);
90*0Sstevel@tonic-gate     if (open("/dev/null", 2) != 0) {
91*0Sstevel@tonic-gate 	error = "open /dev/null: %m";
92*0Sstevel@tonic-gate     } else if (dup(0) != 1 || dup(0) != 2) {
93*0Sstevel@tonic-gate 	error = "dup: %m";
94*0Sstevel@tonic-gate     } else {
95*0Sstevel@tonic-gate 	(void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
96*0Sstevel@tonic-gate 	error = "execl /bin/sh: %m";
97*0Sstevel@tonic-gate     }
98*0Sstevel@tonic-gate 
99*0Sstevel@tonic-gate     /* Something went wrong. We MUST terminate the child process. */
100*0Sstevel@tonic-gate 
101*0Sstevel@tonic-gate     tcpd_warn(error);
102*0Sstevel@tonic-gate     _exit(0);
103*0Sstevel@tonic-gate }
104