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