aboutsummaryrefslogtreecommitdiff
path: root/src/com_start.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-15 08:50:08 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-05-15 09:05:31 +0300
commitb5f4388a2da1b94ce8c8e45a990fd51b2f52dae4 (patch)
tree28bcf8cf313309636357c470faed4456837db7c8 /src/com_start.c
downloadgenrc-b5f4388a2da1b94ce8c8e45a990fd51b2f52dae4.tar.gz
genrc-b5f4388a2da1b94ce8c8e45a990fd51b2f52dae4.tar.bz2
Initial commit
Diffstat (limited to 'src/com_start.c')
-rw-r--r--src/com_start.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/src/com_start.c b/src/com_start.c
new file mode 100644
index 0000000..73bb2ec
--- /dev/null
+++ b/src/com_start.c
@@ -0,0 +1,121 @@
+#include "genrc.h"
+
+void
+report_exec_error(int rc, char const *program)
+{
+ if (WIFEXITED(rc)) {
+ if (WEXITSTATUS(rc)) {
+ genrc_error("%s exited with status %d",
+ program, WEXITSTATUS(rc));
+ }
+ } else if (WIFSIGNALED(rc)) {
+ char const *coremsg = "";
+#ifdef WCOREDUMP
+ if (WCOREDUMP(rc))
+ coremsg = " (core dumped)";
+#endif
+ genrc_error("%s terminated on signal %d%s",
+ program, WTERMSIG(rc), coremsg);
+ } else if (WIFSTOPPED(rc)) {
+ genrc_error("%s stopped on signal %d",
+ program, WSTOPSIG(rc));
+ } else {
+ genrc_error("%s terminated with unrecognized status: %d",
+ program, rc);
+ }
+}
+
+typedef void (*SIGHANDLER)(int);
+
+void
+sigchld(int sig)
+{
+}
+
+int
+timedwaitpid(pid_t pid, int *status)
+{
+ struct timeval now, stoptime, ttw;
+ int rc = -1;
+ SIGHANDLER oldsig;
+
+ oldsig = signal(SIGCHLD, sigchld);
+ gettimeofday(&stoptime, NULL);
+ stoptime.tv_sec += genrc_timeout;
+ while (1) {
+ pid_t p;
+
+ p = waitpid(pid, status, WNOHANG);
+ if (p == pid) {
+ rc = 0;
+ break;
+ }
+ if (p < 0 && errno != EINTR) {
+ system_error(errno, "waitpid");
+ break;
+ }
+
+ gettimeofday(&now, NULL);
+ if (timercmp(&now, &stoptime, >=))
+ break;
+ timersub(&stoptime, &now, &ttw);
+ if (select(0, NULL, NULL, NULL, &ttw) < 0) {
+ if (errno != EINTR) {
+ system_error(errno, "select");
+ break;
+ }
+ }
+
+ }
+ signal(SIGCHLD, oldsig);
+ if (rc) {
+ kill(pid, SIGKILL);
+ }
+ return rc;
+}
+
+int
+com_start(void)
+{
+ pid_t pid;
+ int status;
+ PIDLIST pids;
+ char *p;
+
+ pidlist_init(&pids);
+ if (get_pid_list(genrc_pid_closure, &pids) == 0) {
+ int running = pids.pidc > 0;
+ pidlist_free(&pids);
+ if (running) {
+ genrc_error("%s is already running", genrc_program);
+ return 1;
+ }
+ }
+
+ if ((p = getenv("GENRC_SENTINEL")) && *p == '1')
+ return sentinel();
+
+ pid = fork();
+ if (pid == -1) {
+ system_error(errno, "fork");
+ return 1;
+ }
+ if (pid == 0) {
+ char *argv[] = { SHELL, "-c", NULL, NULL };
+ argv[2] = genrc_command;
+ execvp(SHELL, argv);
+ system_error(errno, "failed to exec %s", genrc_program);
+ exit(127);
+ }
+
+ if (timedwaitpid(pid, &status)) {
+ genrc_error("timed out waiting for %s to return",
+ genrc_program);
+ return 1;
+ }
+ if (!(WIFEXITED(status) && WEXITSTATUS(status) == 0)) {
+ report_exec_error(status, genrc_program);
+ return 1;
+ }
+ return 0;
+}

Return to:

Send suggestions and report system problems to the System administrator.