xref: /freebsd/contrib/tcp_wrappers/shell_cmd.c (revision 14f102eacc8434a5a1f96466752578a4167140c9)
12aef6930SMark Murray  /*
22aef6930SMark Murray   * shell_cmd() takes a shell command after %<character> substitutions. The
32aef6930SMark Murray   * command is executed by a /bin/sh child process, with standard input,
42aef6930SMark Murray   * standard output and standard error connected to /dev/null.
52aef6930SMark Murray   *
62aef6930SMark Murray   * Diagnostics are reported through syslog(3).
72aef6930SMark Murray   *
82aef6930SMark Murray   * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
92aef6930SMark Murray   */
102aef6930SMark Murray 
112aef6930SMark Murray #ifndef lint
122aef6930SMark Murray static char sccsid[] = "@(#) shell_cmd.c 1.5 94/12/28 17:42:44";
132aef6930SMark Murray #endif
142aef6930SMark Murray 
152aef6930SMark Murray /* System libraries. */
162aef6930SMark Murray 
172aef6930SMark Murray #include <sys/types.h>
182aef6930SMark Murray #include <sys/param.h>
1946bcf11dSSean Bruno #include <sys/wait.h>
202aef6930SMark Murray #include <signal.h>
212aef6930SMark Murray #include <stdio.h>
222aef6930SMark Murray #include <syslog.h>
232aef6930SMark Murray #include <string.h>
2446bcf11dSSean Bruno #include <unistd.h>
2546bcf11dSSean Bruno #include <fcntl.h>
262aef6930SMark Murray 
272aef6930SMark Murray extern void exit();
282aef6930SMark Murray 
292aef6930SMark Murray /* Local stuff. */
302aef6930SMark Murray 
312aef6930SMark Murray #include "tcpd.h"
322aef6930SMark Murray 
332aef6930SMark Murray /* Forward declarations. */
342aef6930SMark Murray 
35068ad27dSBrooks Davis static void do_child(char *command);
362aef6930SMark Murray 
372aef6930SMark Murray /* shell_cmd - execute shell command */
382aef6930SMark Murray 
shell_cmd(char * command)39*14f102eaSEd Maste void    shell_cmd(char *command)
402aef6930SMark Murray {
412aef6930SMark Murray     int     child_pid;
422aef6930SMark Murray     int     wait_pid;
432aef6930SMark Murray 
442aef6930SMark Murray     /*
452aef6930SMark Murray      * Most of the work is done within the child process, to minimize the
462aef6930SMark Murray      * risk of damage to the parent.
472aef6930SMark Murray      */
482aef6930SMark Murray 
492aef6930SMark Murray     switch (child_pid = fork()) {
502aef6930SMark Murray     case -1:					/* error */
512aef6930SMark Murray 	tcpd_warn("cannot fork: %m");
522aef6930SMark Murray 	break;
532aef6930SMark Murray     case 00:					/* child */
542aef6930SMark Murray 	do_child(command);
552aef6930SMark Murray 	/* NOTREACHED */
562aef6930SMark Murray     default:					/* parent */
572aef6930SMark Murray 	while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid)
582aef6930SMark Murray 	     /* void */ ;
592aef6930SMark Murray     }
602aef6930SMark Murray }
612aef6930SMark Murray 
622aef6930SMark Murray /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */
632aef6930SMark Murray 
do_child(char * command)64068ad27dSBrooks Davis static void do_child(char *command)
652aef6930SMark Murray {
662aef6930SMark Murray     char   *error;
672aef6930SMark Murray     int     tmp_fd;
682aef6930SMark Murray 
692aef6930SMark Murray     /*
702aef6930SMark Murray      * Systems with POSIX sessions may send a SIGHUP to grandchildren if the
712aef6930SMark Murray      * child exits first. This is sick, sessions were invented for terminals.
722aef6930SMark Murray      */
732aef6930SMark Murray 
742aef6930SMark Murray     signal(SIGHUP, SIG_IGN);
752aef6930SMark Murray 
762aef6930SMark Murray     /* Set up new stdin, stdout, stderr, and exec the shell command. */
772aef6930SMark Murray 
782aef6930SMark Murray     for (tmp_fd = 0; tmp_fd < 3; tmp_fd++)
792aef6930SMark Murray 	(void) close(tmp_fd);
802aef6930SMark Murray     if (open("/dev/null", 2) != 0) {
812aef6930SMark Murray 	error = "open /dev/null: %m";
822aef6930SMark Murray     } else if (dup(0) != 1 || dup(0) != 2) {
832aef6930SMark Murray 	error = "dup: %m";
842aef6930SMark Murray     } else {
852aef6930SMark Murray 	(void) execl("/bin/sh", "sh", "-c", command, (char *) 0);
862aef6930SMark Murray 	error = "execl /bin/sh: %m";
872aef6930SMark Murray     }
882aef6930SMark Murray 
892aef6930SMark Murray     /* Something went wrong. We MUST terminate the child process. */
902aef6930SMark Murray 
912aef6930SMark Murray     tcpd_warn(error);
922aef6930SMark Murray     _exit(0);
932aef6930SMark Murray }
94