Postfix3.3.1
全て データ構造 ファイル 関数 変数 型定義 マクロ定義
exec_command.c
[詳解]
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 
51 NORETURN 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!@%-_=+:,./\
60 abcdefghijklmnopqrstuvwxyz\
61 ABCDEFGHIJKLMNOPQRSTUVWXYZ" 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 
104 int 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
ARGV * argv_free(ARGV *argvp)
Definition: argv.c:136
#define NORETURN
Definition: sys_defs.h:1583
Definition: argv.h:17
int main(int argc, char **argv)
Definition: anvil.c:1010
char ** argv
Definition: argv.h:20
#define SPACE_TAB
Definition: exec_command.c:47
NORETURN msg_fatal(const char *fmt,...)
Definition: msg.c:249
ARGV * argv_split(const char *, const char *)
Definition: argv_split.c:63
void msg_vstream_init(const char *name, VSTREAM *vp)
Definition: msg_vstream.c:77
NORETURN exec_command(const char *command)
Definition: exec_command.c:51
#define VSTREAM_ERR
Definition: vstream.h:68