blob: a4a19d8b59327f83a67bfb7d195175f9991614ce [file] [log] [blame]
Brian Silvermanaf784862014-05-13 08:14:55 -07001#include "aos/common/util/run_command.h"
2
3#include <signal.h>
4#include <sys/types.h>
5#include <sys/wait.h>
6#include <unistd.h>
7#include <fcntl.h>
8#include <sys/stat.h>
9
10#include "aos/common/logging/logging.h"
11
12namespace aos {
13namespace util {
14namespace {
15
16// RAII class to block SIGCHLD and then restore it on destruction.
17class BlockSIGCHLD {
18 public:
19 BlockSIGCHLD() {
20 sigset_t to_block;
21 sigemptyset(&to_block);
22 sigaddset(&to_block, SIGCHLD);
23 if (sigprocmask(SIG_BLOCK, &to_block, &original_blocked_) == -1) {
24 PLOG(FATAL, "sigprocmask(SIG_BLOCK, %p, %p) failed",
25 &to_block, &original_blocked_);
26 }
27 }
28 ~BlockSIGCHLD() {
29 if (sigprocmask(SIG_SETMASK, &original_blocked_, nullptr) == -1) {
30 PLOG(FATAL, "sigprocmask(SIG_SETMASK, %p, nullptr) failed",
31 &original_blocked_);
32 }
33 }
34
35 private:
36 sigset_t original_blocked_;
37};
38
39} // namespace
40
41int RunCommand(const char *command) {
42 BlockSIGCHLD blocker;
43 const pid_t pid = fork();
44 switch (pid) {
45 case 0: // in child
46 {
47 int new_stdin = open("/dev/null", O_RDONLY);
48 if (new_stdin == -1) _exit(127);
49 int new_stdout = open("/dev/null", O_WRONLY);
50 if (new_stdout == -1) _exit(127);
51 int new_stderr = open("/dev/null", O_WRONLY);
52 if (new_stderr == -1) _exit(127);
53 if (dup2(new_stdin, 0) != 0) _exit(127);
54 if (dup2(new_stdout, 1) != 1) _exit(127);
55 if (dup2(new_stderr, 2) != 2) _exit(127);
56 execl("/bin/sh", "sh", "-c", command, nullptr);
57 _exit(127);
58 }
59 case -1:
60 return -1;
61 default:
62 int stat;
63 while (waitpid(pid, &stat, 0) == -1) {
64 if (errno != EINTR) {
65 return -1;
66 }
67 }
68 return stat;
69 }
70}
71
72} // namespace util
73} // namespace aos