1/* $NetBSD$ */ 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 53NORETURN 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!@%-_=+:,./\ 62abcdefghijklmnopqrstuvwxyz\ 63ABCDEFGHIJKLMNOPQRSTUVWXYZ" 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 105int 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