diff options
| author | itojun <itojun@NetBSD.org> | 2001-03-13 17:57:13 +0000 |
|---|---|---|
| committer | itojun <itojun@NetBSD.org> | 2001-03-13 17:57:13 +0000 |
| commit | e8a3065dbc24f95326a3ed4fdf1b76a604f5d8b8 (patch) | |
| tree | 9a9351637cbe4d65750fba7baaa831d9796c87c2 /gnu/dist/postfix/util/spawn_command.c | |
| parent | 6b37581cf513aaf61bef62e603aa4baed53630eb (diff) | |
remove files that have gone, mostly due to pathname change in original
(postfix/foo -> postfix/src/foo)
Diffstat (limited to 'gnu/dist/postfix/util/spawn_command.c')
| -rw-r--r-- | gnu/dist/postfix/util/spawn_command.c | 298 |
1 files changed, 0 insertions, 298 deletions
diff --git a/gnu/dist/postfix/util/spawn_command.c b/gnu/dist/postfix/util/spawn_command.c deleted file mode 100644 index 10dc2841b36..00000000000 --- a/gnu/dist/postfix/util/spawn_command.c +++ /dev/null @@ -1,298 +0,0 @@ -/*++ -/* NAME -/* spawn_command 3 -/* SUMMARY -/* run external command -/* SYNOPSIS -/* #include <spawn_command.h> -/* -/* WAIT_STATUS_T spawn_command(key, value, ...) -/* int key; -/* DESCRIPTION -/* spawn_command() runs a command in a child process and returns -/* the command exit status. -/* -/* Arguments: -/* .IP key -/* Specifies what value will follow. spawn_command() takes a list -/* of (key, value) arguments, terminated by SPAWN_CMD_END. The -/* following is a listing of key codes together with the expected -/* value type. -/* .RS -/* .IP "SPAWN_CMD_COMMAND (char *)" -/* Specifies the command to execute as a string. The string is -/* passed to the shell when it contains shell meta characters -/* or when it appears to be a shell built-in command, otherwise -/* the command is executed without invoking a shell. -/* One of SPAWN_CMD_COMMAND or SPAWN_CMD_ARGV must be specified. -/* See also the SPAWN_CMD_SHELL attribute below. -/* .IP "SPAWN_CMD_ARGV (char **)" -/* The command is specified as an argument vector. This vector is -/* passed without further inspection to the \fIexecvp\fR() routine. -/* One of SPAWN_CMD_COMMAND or SPAWN_CMD_ARGV must be specified. -/* .IP "SPAWN_CMD_ENV (char **)" -/* Additional environment information, in the form of a null-terminated -/* list of name, value, name, value, ... elements. By default only the -/* command search path is initialized to _PATH_DEFPATH. -/* .IP "SPAWN_CMD_STDIN (int)" -/* .IP "SPAWN_CMD_STDOUT (int)" -/* .IP "SPAWN_CMD_STDERR (int)" -/* Each of these specifies I/O redirection of one of the standard file -/* descriptors for the command. -/* .IP "SPAWN_CMD_UID (int)" -/* The user ID to execute the command as. -/* .IP "SPAWN_CMD_GID (int)" -/* The group ID to execute the command as. -/* .IP "SPAWN_CMD_TIME_LIMIT (int)" -/* The amount of time in seconds the command is allowed to run before -/* it is terminated with SIGKILL. The default is no time limit. -/* .IP "SPAWN_CMD_SHELL (char *)" -/* The shell to use when executing the command specified with -/* SPAWN_CMD_COMMAND. This shell is invoked regardless of the -/* command content. -/* .RE -/* DIAGNOSTICS -/* Panic: interface violations (for example, a missing command). -/* -/* Fatal error: fork() failure, other system call failures. -/* -/* spawn_command() returns the exit status as defined by wait(2). -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* SEE ALSO -/* exec_command(3) execute command -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System library. */ - -#include <sys_defs.h> -#include <sys/wait.h> -#include <signal.h> -#include <unistd.h> -#include <errno.h> -#include <stdarg.h> -#include <stdlib.h> -#ifdef USE_PATHS_H -#include <paths.h> -#endif -#include <syslog.h> - -/* Utility library. */ - -#include <msg.h> -#include <timed_wait.h> -#include <set_ugid.h> -#include <argv.h> -#include <spawn_command.h> -#include <exec_command.h> -#include <clean_env.h> - -/* Application-specific. */ - -struct spawn_args { - char **argv; /* argument vector */ - char *command; /* or a plain string */ - int stdin_fd; /* read stdin here */ - int stdout_fd; /* write stdout here */ - int stderr_fd; /* write stderr here */ - uid_t uid; /* privileges */ - gid_t gid; /* privileges */ - char **env; /* extra environment */ - char *shell; /* command shell */ - int time_limit; /* command time limit */ -}; - -/* get_spawn_args - capture the variadic argument list */ - -static void get_spawn_args(struct spawn_args * args, int init_key, va_list ap) -{ - const char *myname = "get_spawn_args"; - int key; - - /* - * First, set the default values. - */ - args->argv = 0; - args->command = 0; - args->stdin_fd = -1; - args->stdout_fd = -1; - args->stderr_fd = -1; - args->uid = (uid_t) - 1; - args->gid = (gid_t) - 1; - args->env = 0; - args->shell = 0; - args->time_limit = 0; - - /* - * Then, override the defaults with user-supplied inputs. - */ - for (key = init_key; key != SPAWN_CMD_END; key = va_arg(ap, int)) { - switch (key) { - case SPAWN_CMD_ARGV: - if (args->command) - msg_panic("%s: specify SPAWN_CMD_ARGV or SPAWN_CMD_COMMAND", - myname); - args->argv = va_arg(ap, char **); - break; - case SPAWN_CMD_COMMAND: - if (args->argv) - msg_panic("%s: specify SPAWN_CMD_ARGV or SPAWN_CMD_COMMAND", - myname); - args->command = va_arg(ap, char *); - break; - case SPAWN_CMD_STDIN: - args->stdin_fd = va_arg(ap, int); - break; - case SPAWN_CMD_STDOUT: - args->stdout_fd = va_arg(ap, int); - break; - case SPAWN_CMD_STDERR: - args->stderr_fd = va_arg(ap, int); - break; - case SPAWN_CMD_UID: - args->uid = va_arg(ap, int); /* in case uid_t is short */ - break; - case SPAWN_CMD_GID: - args->gid = va_arg(ap, int); /* in case gid_t is short */ - break; - case SPAWN_CMD_TIME_LIMIT: - args->time_limit = va_arg(ap, int); - break; - case SPAWN_CMD_ENV: - args->env = va_arg(ap, char **); - break; - case SPAWN_CMD_SHELL: - args->shell = va_arg(ap, char *); - break; - default: - msg_panic("%s: unknown key: %d", myname, key); - } - } - if (args->command == 0 && args->argv == 0) - msg_panic("%s: missing SPAWN_CMD_ARGV or SPAWN_CMD_COMMAND", myname); - if (args->command == 0 && args->shell != 0) - msg_panic("%s: SPAWN_CMD_ARGV cannot be used with SPAWN_CMD_SHELL", - myname); -} - -/* spawn_command - execute command with extreme prejudice */ - -WAIT_STATUS_T spawn_command(int key,...) -{ - const char *myname = "spawn_comand"; - va_list ap; - pid_t pid; - WAIT_STATUS_T wait_status; - struct spawn_args args; - char **cpp; - ARGV *argv; - int err; - - /* - * Process the variadic argument list. This also does sanity checks on - * what data the caller is passing to us. - */ - va_start(ap, key); - get_spawn_args(&args, key, ap); - va_end(ap); - - /* - * For convenience... - */ - if (args.command == 0) - args.command = args.argv[0]; - - /* - * Spawn off a child process and irrevocably change privilege to the - * user. This includes revoking all rights on open files (via the close - * on exec flag). If we cannot run the command now, try again some time - * later. - */ - switch (pid = fork()) { - - /* - * Error. Instead of trying again right now, back off, give the - * system a chance to recover, and try again later. - */ - case -1: - msg_fatal("fork: %m"); - - /* - * Child. Run the child in a separate process group so that the - * parent can kill not just the child but also its offspring. - */ - case 0: - if (args.uid != (uid_t) - 1 || args.gid != (gid_t) - 1) - set_ugid(args.uid, args.gid); - setsid(); - - /* - * Pipe plumbing. - */ - if ((args.stdin_fd >= 0 && DUP2(args.stdin_fd, STDIN_FILENO) < 0) - || (args.stdout_fd >= 0 && DUP2(args.stdout_fd, STDOUT_FILENO) < 0) - || (args.stderr_fd >= 0 && DUP2(args.stderr_fd, STDERR_FILENO) < 0)) - msg_fatal("%s: dup2: %m", myname); - - /* - * Environment plumbing. Always reset the command search path. XXX - * That should probably be done by clean_env(). - */ - clean_env(); - if (setenv("PATH", _PATH_DEFPATH, 1)) - msg_fatal("%s: setenv: %m", myname); - if (args.env) - for (cpp = args.env; *cpp; cpp += 2) - if (setenv(cpp[0], cpp[1], 1)) - msg_fatal("setenv: %m"); - - /* - * Process plumbing. If possible, avoid running a shell. - */ - closelog(); - if (args.argv) { - execvp(args.argv[0], args.argv); - msg_fatal("%s: execvp %s: %m", myname, args.argv[0]); - } else if (args.shell && *args.shell) { - argv = argv_split(args.shell, " \t\r\n"); - argv_add(argv, args.command, (char *) 0); - argv_terminate(argv); - execvp(argv->argv[0], argv->argv); - msg_fatal("%s: execvp %s: %m", myname, argv->argv[0]); - } else { - exec_command(args.command); - } - /* NOTREACHED */ - - /* - * Parent. - */ - default: - - /* - * Be prepared for the situation that the child does not terminate. - * Make sure that the child terminates before the parent attempts to - * retrieve its exit status, otherwise the parent could become stuck, - * and the mail system would eventually run out of exec daemons. Do a - * thorough job, and kill not just the child process but also its - * offspring. - */ - if ((err = timed_waitpid(pid, &wait_status, 0, args.time_limit)) < 0 - && errno == ETIMEDOUT) { - msg_warn("%s: process id %d: command time limit exceeded", - args.command, pid); - kill(-pid, SIGKILL); - err = waitpid(pid, &wait_status, 0); - } - if (err < 0) - msg_fatal("wait: %m"); - return (wait_status); - } -} |
