From b5896ba9f6047e7031e2bdee0622d543e11a6734 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Mon, 6 May 2024 03:46:30 +0200 Subject: Adding upstream version 3.4.23. Signed-off-by: Daniel Baumann --- src/util/exec_command.c | 112 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) create mode 100644 src/util/exec_command.c (limited to 'src/util/exec_command.c') diff --git a/src/util/exec_command.c b/src/util/exec_command.c new file mode 100644 index 0000000..8629b0c --- /dev/null +++ b/src/util/exec_command.c @@ -0,0 +1,112 @@ +/*++ +/* NAME +/* exec_command 3 +/* SUMMARY +/* execute command +/* SYNOPSIS +/* #include +/* +/* NORETURN exec_command(command) +/* const char *command; +/* DESCRIPTION +/* \fIexec_command\fR() replaces the current process by an instance +/* of \fIcommand\fR. This routine uses a simple heuristic to avoid +/* the overhead of running a command shell interpreter. +/* DIAGNOSTICS +/* This routine never returns. All errors are fatal. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include +#include +#include +#ifdef USE_PATHS_H +#include +#endif +#include +#include + +/* Utility library. */ + +#include +#include +#include + +/* Application-specific. */ + +#define SPACE_TAB " \t" + +/* exec_command - exec command */ + +NORETURN exec_command(const char *command) +{ + ARGV *argv; + + /* + * Character filter. In this particular case, we allow space and tab in + * addition to the regular character set. + */ + static char ok_chars[] = "1234567890!@%-_=+:,./\ +abcdefghijklmnopqrstuvwxyz\ +ABCDEFGHIJKLMNOPQRSTUVWXYZ" SPACE_TAB; + + /* + * See if this command contains any shell magic characters. + */ + if (command[strspn(command, ok_chars)] == 0 + && command[strspn(command, SPACE_TAB)] != 0) { + + /* + * No shell meta characters found, so we can try to avoid the overhead + * of running a shell. Just split the command on whitespace and exec + * the result directly. + */ + argv = argv_split(command, SPACE_TAB); + (void) execvp(argv->argv[0], argv->argv); + + /* + * Auch. Perhaps they're using some shell built-in command. + */ + if (errno != ENOENT || strchr(argv->argv[0], '/') != 0) + msg_fatal("execvp %s: %m", argv->argv[0]); + + /* + * Not really necessary, but... + */ + argv_free(argv); + } + + /* + * Pass the command to a shell. + */ + (void) execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0); + msg_fatal("execl %s: %m", _PATH_BSHELL); +} + +#ifdef TEST + + /* + * Yet another proof-of-concept test program. + */ +#include +#include + +int main(int argc, char **argv) +{ + msg_vstream_init(argv[0], VSTREAM_ERR); + if (argc != 2) + msg_fatal("usage: %s 'command'", argv[0]); + exec_command(argv[1]); +} + +#endif -- cgit v1.2.3