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> 19*46bcf11dSSean 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> 24*46bcf11dSSean Bruno #include <unistd.h> 25*46bcf11dSSean 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 352aef6930SMark Murray static void do_child(); 362aef6930SMark Murray 372aef6930SMark Murray /* shell_cmd - execute shell command */ 382aef6930SMark Murray 392aef6930SMark Murray void shell_cmd(command) 402aef6930SMark Murray char *command; 412aef6930SMark Murray { 422aef6930SMark Murray int child_pid; 432aef6930SMark Murray int wait_pid; 442aef6930SMark Murray 452aef6930SMark Murray /* 462aef6930SMark Murray * Most of the work is done within the child process, to minimize the 472aef6930SMark Murray * risk of damage to the parent. 482aef6930SMark Murray */ 492aef6930SMark Murray 502aef6930SMark Murray switch (child_pid = fork()) { 512aef6930SMark Murray case -1: /* error */ 522aef6930SMark Murray tcpd_warn("cannot fork: %m"); 532aef6930SMark Murray break; 542aef6930SMark Murray case 00: /* child */ 552aef6930SMark Murray do_child(command); 562aef6930SMark Murray /* NOTREACHED */ 572aef6930SMark Murray default: /* parent */ 582aef6930SMark Murray while ((wait_pid = wait((int *) 0)) != -1 && wait_pid != child_pid) 592aef6930SMark Murray /* void */ ; 602aef6930SMark Murray } 612aef6930SMark Murray } 622aef6930SMark Murray 632aef6930SMark Murray /* do_child - exec command with { stdin, stdout, stderr } to /dev/null */ 642aef6930SMark Murray 652aef6930SMark Murray static void do_child(command) 662aef6930SMark Murray char *command; 672aef6930SMark Murray { 682aef6930SMark Murray char *error; 692aef6930SMark Murray int tmp_fd; 702aef6930SMark Murray 712aef6930SMark Murray /* 722aef6930SMark Murray * Systems with POSIX sessions may send a SIGHUP to grandchildren if the 732aef6930SMark Murray * child exits first. This is sick, sessions were invented for terminals. 742aef6930SMark Murray */ 752aef6930SMark Murray 762aef6930SMark Murray signal(SIGHUP, SIG_IGN); 772aef6930SMark Murray 782aef6930SMark Murray /* Set up new stdin, stdout, stderr, and exec the shell command. */ 792aef6930SMark Murray 802aef6930SMark Murray for (tmp_fd = 0; tmp_fd < 3; tmp_fd++) 812aef6930SMark Murray (void) close(tmp_fd); 822aef6930SMark Murray if (open("/dev/null", 2) != 0) { 832aef6930SMark Murray error = "open /dev/null: %m"; 842aef6930SMark Murray } else if (dup(0) != 1 || dup(0) != 2) { 852aef6930SMark Murray error = "dup: %m"; 862aef6930SMark Murray } else { 872aef6930SMark Murray (void) execl("/bin/sh", "sh", "-c", command, (char *) 0); 882aef6930SMark Murray error = "execl /bin/sh: %m"; 892aef6930SMark Murray } 902aef6930SMark Murray 912aef6930SMark Murray /* Something went wrong. We MUST terminate the child process. */ 922aef6930SMark Murray 932aef6930SMark Murray tcpd_warn(error); 942aef6930SMark Murray _exit(0); 952aef6930SMark Murray } 96