1/*++ 2/* NAME 3/* exec_command 3 4/* SUMMARY 5/* execute command 6/* SYNOPSIS 7/* #include <exec_command.h> 8/* 9/* NORETURN exec_command(command) 10/* const char *command; 11/* DESCRIPTION 12/* \fIexec_command\fR() replaces the current process by an instance 13/* of \fIcommand\fR. This routine uses a simple heuristic to avoid 14/* the overhead of running a command shell interpreter. 15/* DIAGNOSTICS 16/* This routine never returns. All errors are fatal. 17/* LICENSE 18/* .ad 19/* .fi 20/* The Secure Mailer license must be distributed with this software. 21/* AUTHOR(S) 22/* Wietse Venema 23/* IBM T.J. Watson Research 24/* P.O. Box 704 25/* Yorktown Heights, NY 10598, USA 26/*--*/ 27 28/* System library. */ 29 30#include <sys_defs.h> 31#include <unistd.h> 32#include <string.h> 33#ifdef USE_PATHS_H 34#include <paths.h> 35#endif 36#include <errno.h> 37#include <string.h> 38 39/* Utility library. */ 40 41#include <msg.h> 42#include <argv.h> 43#include <exec_command.h> 44 45/* Application-specific. */ 46 47#define SPACE_TAB " \t" 48 49/* exec_command - exec command */ 50 51NORETURN exec_command(const char *command) 52{ 53 ARGV *argv; 54 55 /* 56 * Character filter. In this particular case, we allow space and tab in 57 * addition to the regular character set. 58 */ 59 static char ok_chars[] = "1234567890!@%-_=+:,./\ 60abcdefghijklmnopqrstuvwxyz\ 61ABCDEFGHIJKLMNOPQRSTUVWXYZ" SPACE_TAB; 62 63 /* 64 * See if this command contains any shell magic characters. 65 */ 66 if (command[strspn(command, ok_chars)] == 0) { 67 68 /* 69 * No shell meta characters found, so we can try to avoid the overhead 70 * of running a shell. Just split the command on whitespace and exec 71 * the result directly. 72 */ 73 argv = argv_split(command, SPACE_TAB); 74 (void) execvp(argv->argv[0], argv->argv); 75 76 /* 77 * Auch. Perhaps they're using some shell built-in command. 78 */ 79 if (errno != ENOENT || strchr(argv->argv[0], '/') != 0) 80 msg_fatal("execvp %s: %m", argv->argv[0]); 81 82 /* 83 * Not really necessary, but... 84 */ 85 argv_free(argv); 86 } 87 88 /* 89 * Pass the command to a shell. 90 */ 91 (void) execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0); 92 msg_fatal("execl %s: %m", _PATH_BSHELL); 93} 94 95#ifdef TEST 96 97 /* 98 * Yet another proof-of-concept test program. 99 */ 100#include <vstream.h> 101#include <msg_vstream.h> 102 103int main(int argc, char **argv) 104{ 105 msg_vstream_init(argv[0], VSTREAM_ERR); 106 if (argc != 2) 107 msg_fatal("usage: %s 'command'", argv[0]); 108 exec_command(argv[1]); 109} 110 111#endif 112