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