diff --git a/system/nxinit/action.c b/system/nxinit/action.c index 81716e571e7..0975682b7e3 100644 --- a/system/nxinit/action.c +++ b/system/nxinit/action.c @@ -29,10 +29,10 @@ #include #include #include -#include #include #include #include +#include #include "action.h" #include "builtin.h" diff --git a/system/nxinit/action.h b/system/nxinit/action.h index 672621d1351..908b907b44d 100644 --- a/system/nxinit/action.h +++ b/system/nxinit/action.h @@ -29,6 +29,8 @@ #include +#include + #include "parser.h" /**************************************************************************** diff --git a/system/nxinit/builtin.c b/system/nxinit/builtin.c index d300457f72b..ba7a41bcf68 100644 --- a/system/nxinit/builtin.c +++ b/system/nxinit/builtin.c @@ -183,6 +183,10 @@ static int cmd_exec(FAR struct action_manager_s *am, int init_builtin_run(FAR struct action_manager_s *am, int argc, FAR char **argv) { + char cmd[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX]; + posix_spawnattr_t attr; + FAR char *args[4]; + sigset_t mask; pid_t pid; size_t i; int ret; @@ -203,35 +207,65 @@ int init_builtin_run(FAR struct action_manager_s *am, } } - ret = posix_spawnp(&pid, argv[0], NULL, NULL, argv, NULL); + ret = posix_spawnattr_init(&attr); if (ret != 0) { -#ifdef CONFIG_SYSTEM_SYSTEM - char cmd[CONFIG_SYSTEM_NXINIT_RC_LINE_MAX]; + init_err("posix_spawnattr_init %d", ret); + return -ret; + } - for (i = 0, cmd[i] = '\0'; i < argc; i++) + ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); + if (ret != 0) + { + init_err("posix_spawnattr_setflags %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + sigemptyset(&mask); + ret = posix_spawnattr_setsigmask(&attr, &mask); + if (ret != 0) + { + init_err("posix_spawnattr_setsigmask %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + for (i = 0, cmd[i] = '\0'; i < argc; i++) + { + strlcat(cmd, argv[i], sizeof(cmd)); + if (i < argc - 1) { - strlcat(cmd, argv[i], sizeof(cmd)); - if (i < argc - 1) - { - strcat(cmd, " "); - } + strcat(cmd, " "); + } + } + + for (; ; ) + { + ret = posix_spawnp(&pid, argv[0], NULL, &attr, argv, NULL); + if (ret == 0) + { + init_debug("executed command '%s' pid %d", cmd, pid); + break; } - init_debug("Executing nsh command '%s'", cmd); - ret = system(cmd); - if (WIFEXITED(ret)) + if (!strcmp("sh", argv[0])) { - init_debug("NSH command '%s' exited %d", cmd, WEXITSTATUS(ret)); - return -WEXITSTATUS(ret); + init_err("executing command '%s': %d", cmd, ret); + init_dump_args(argc, argv); + pid = -ret; + break; } -#endif - init_err("Executing command '%s': %d", argv[0], ret); - init_dump_args(argc, argv); - return -ret; + init_debug("command '%s': %d", argv[0], ret); + args[0] = "sh"; + args[1] = "-c"; + args[2] = cmd; + args[3] = NULL; + argc = nitems(args) - 1; + argv = args; } - init_debug("Executed command '%s' pid %d", argv[0], pid); + posix_spawnattr_destroy(&attr); return pid; } diff --git a/system/nxinit/import.c b/system/nxinit/import.c index ca389d396b1..2b656c05937 100644 --- a/system/nxinit/import.c +++ b/system/nxinit/import.c @@ -42,7 +42,13 @@ int init_import_parse(FAR const struct parser_s *parser, if (create) { - init_parse_arguments(buf, false, nitems(argv), argv); + ret = init_parse_arguments(buf, false, nitems(argv), argv); + if (ret < 2) + { + init_err("parse import: %s", buf); + return -EINVAL; + } + ret = init_parse_config_file(parser, argv[1]); if (ret < 0) { diff --git a/system/nxinit/init.c b/system/nxinit/init.c index 1a542f79612..6c7291e5e60 100644 --- a/system/nxinit/init.c +++ b/system/nxinit/init.c @@ -78,6 +78,11 @@ static void reap_process(FAR struct service_manager_s *sm, int ret; int pid; + /* prevent unused warning */ + + UNUSED(name); + UNUSED(status); + for (; ; ) { pid = waitpid(-1, &wstatus, WNOHANG); @@ -90,7 +95,7 @@ static void reap_process(FAR struct service_manager_s *sm, status = "status"; ret = WEXITSTATUS(wstatus); } - else if (WIFSIGNALED(wtatus)) + else if (WIFSIGNALED(wstatus)) { status = "signal"; ret = WTERMSIG(wstatus); @@ -154,9 +159,19 @@ int main(int argc, FAR char *argv[]) }; struct pollfd pfds[nitems(ev)]; + sigset_t mask; size_t i; int r; + sigfillset(&mask); + r = sigprocmask(SIG_BLOCK, &mask, NULL); + sigemptyset(&mask); + if (r < 0) + { + init_err("sigprocmask failed %d", errno); + return r; + } + #ifdef CONFIG_USBDEV_TRACE usbtrace_enable(TRACE_BITSET); #endif @@ -215,7 +230,7 @@ int main(int argc, FAR char *argv[]) break; } - r = ppoll(pfds, nitems(pfds), MS2TIMESPEC(&timeout, t), NULL); + r = ppoll(pfds, nitems(pfds), MS2TIMESPEC(&timeout, t), &mask); if (r < 0 && errno != EINTR) { init_err("Wait event"); diff --git a/system/nxinit/parser.c b/system/nxinit/parser.c index 3ffe4a5a6f2..60b189afd4a 100644 --- a/system/nxinit/parser.c +++ b/system/nxinit/parser.c @@ -46,7 +46,7 @@ int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv) bool new = true; int i = 0; - while (*buf != '\0') + for (; ; ) { while (isblank(*buf)) { @@ -82,6 +82,7 @@ int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv) if (quote) { quote = false; + buf++; } else { @@ -91,6 +92,11 @@ int init_parse_arguments(FAR char *buf, bool dup, int argc, FAR char **argv) } } + if (*buf == '\0') + { + break; + } + if (new) { argv[i++] = buf; @@ -178,6 +184,10 @@ int init_parse_config_file(FAR const struct parser_s *parser, *(nl++) = '\0'; n -= nl - buf; init_debug("Line %3d: '%s'", ++line, buf); + if (*buf == '\0') + { + continue; + } for (ret = 0; parser[ret].key; ret++) { diff --git a/system/nxinit/service.c b/system/nxinit/service.c index 7f582e6e4fb..7e840e7e722 100644 --- a/system/nxinit/service.c +++ b/system/nxinit/service.c @@ -427,6 +427,8 @@ void init_service_reap(FAR struct service_s *service, int status) int init_service_start(FAR struct service_s *service) { + posix_spawnattr_t attr; + sigset_t mask; int ret; int pid; @@ -439,8 +441,33 @@ int init_service_start(FAR struct service_s *service) return service->pid; } - ret = posix_spawnp(&pid, service->argv[2], NULL, NULL, &service->argv[2], + ret = posix_spawnattr_init(&attr); + if (ret != 0) + { + init_err("posix_spawnattr_init %d", ret); + return -ret; + } + + ret = posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSIGMASK); + if (ret != 0) + { + init_err("posix_spawnattr_setflags %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + sigemptyset(&mask); + ret = posix_spawnattr_setsigmask(&attr, &mask); + if (ret != 0) + { + init_err("posix_spawnattr_setsigmask %d", ret); + posix_spawnattr_destroy(&attr); + return -ret; + } + + ret = posix_spawnp(&pid, service->argv[2], NULL, &attr, &service->argv[2], environ); + posix_spawnattr_destroy(&attr); if (ret != 0) { init_err("Starting service '%s': %d", service->argv[1], ret);