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