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 && command[strspn(command, SPACE_TAB)] != 0) { 68 69 /* 70 * No shell meta characters found, so we can try to avoid the overhead 71 * of running a shell. Just split the command on whitespace and exec 72 * the result directly. 73 */ 74 argv = argv_split(command, SPACE_TAB); 75 (void) execvp(argv->argv[0], argv->argv); 76 77 /* 78 * Auch. Perhaps they're using some shell built-in command. 79 */ 80 if (errno != ENOENT || strchr(argv->argv[0], '/') != 0) 81 msg_fatal("execvp %s: %m", argv->argv[0]); 82 83 /* 84 * Not really necessary, but... 85 */ 86 argv_free(argv); 87 } 88 89 /* 90 * Pass the command to a shell. 91 */ 92 (void) execl(_PATH_BSHELL, "sh", "-c", command, (char *) 0); 93 msg_fatal("execl %s: %m", _PATH_BSHELL); 94} 95 96#ifdef TEST 97 98 /* 99 * Yet another proof-of-concept test program. 100 */ 101#include <vstream.h> 102#include <msg_vstream.h> 103 104int main(int argc, char **argv) 105{ 106 msg_vstream_init(argv[0], VSTREAM_ERR); 107 if (argc != 2) 108 msg_fatal("usage: %s 'command'", argv[0]); 109 exec_command(argv[1]); 110} 111 112#endif 113