/*++ /* 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