summary refs log tree commit diff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--daemon.c2
-rw-r--r--daemon.h5
-rw-r--r--service.c52
-rw-r--r--spawnd.85
4 files changed, 60 insertions, 4 deletions
diff --git a/daemon.c b/daemon.c
index a2ce4dc..d0a6579 100644
--- a/daemon.c
+++ b/daemon.c
@@ -18,6 +18,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <grp.h>
+#include <poll.h>
 #include <pwd.h>
 #include <stdarg.h>
 #include <stdbool.h>
@@ -122,7 +123,6 @@ int main(int argc, char *argv[]) {
 	setprogname(argv[0]);
 
 	bool daemonize = true;
-	setAdd(&stopExits, 127);
 	setAdd(&stopExits, EX_USAGE);
 	setAdd(&stopExits, EX_DATAERR);
 	setAdd(&stopExits, EX_NOINPUT);
diff --git a/daemon.h b/daemon.h
index a62f78f..09cda47 100644
--- a/daemon.h
+++ b/daemon.h
@@ -95,10 +95,13 @@ extern struct Services {
 } services;
 
 int serviceAdd(const char *name, const char *command);
+void serviceStart(struct Service *service);
 
 extern char configError[];
 int configParse(const char *path);
 
+extern int restartInterval;
+
 struct Set256 {
 	uint32_t bits[8];
 };
@@ -112,5 +115,5 @@ static inline uint32_t setTest(const struct Set256 *set, byte x) {
 	return set->bits[x / 32] & (1 << (uint32_t)(x & 31));
 }
 
-extern int restartInterval;
+enum { StopExit = 127 };
 extern struct Set256 stopExits;
diff --git a/service.c b/service.c
index f5038da..3472151 100644
--- a/service.c
+++ b/service.c
@@ -14,11 +14,15 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <assert.h>
+#include <err.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <paths.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <syslog.h>
 #include <unistd.h>
 
 #include "daemon.h"
@@ -100,3 +104,51 @@ err:
 	serviceFree(service);
 	return -1;
 }
+
+void serviceStart(struct Service *service) {
+	if (service->state == Start) return;
+	service->intent = Start;
+	// TODO: Reset restart interval.
+
+	service->pid = fork();
+	if (service->pid < 0) {
+		syslog(LOG_ERR, "fork: %m");
+		return;
+		// FIXME: Do we treat this as a restart condition?
+	}
+	if (service->pid) {
+		service->state = Start;
+		return;
+	}
+
+	closelog();
+	dup2(service->outPipe[1], STDOUT_FILENO);
+	dup2(service->errPipe[1], STDERR_FILENO);
+
+	int error = chdir(serviceDir);
+	if (error) err(StopExit, "%s", serviceDir);
+
+	error = setgid(serviceGID);
+	if (error) err(StopExit, "setgid");
+
+	error = setuid(serviceUID);
+	if (error) err(StopExit, "setuid");
+
+	size_t len = 0;
+	char command[ARG_MAX];
+	for (size_t i = 0; i < prepend.len; ++i) {
+		int n = snprintf(
+			&command[len], sizeof(command) - len, "%s;", prepend.commands[i]
+		);
+		assert(n > 0);
+		len += n;
+	}
+	snprintf(&command[len], sizeof(command) - len, "exec %s", service->command);
+
+	execle(
+		_PATH_BSHELL,
+		_PATH_BSHELL, "-c", command, service->name, NULL,
+		serviceEnviron
+	);
+	err(StopExit, "%s", _PATH_BSHELL);
+}
diff --git a/spawnd.8 b/spawnd.8
index fc97498..1981304 100644
--- a/spawnd.8
+++ b/spawnd.8
@@ -114,8 +114,9 @@ The default list contains the values of
 .Dv EX_CANTCREAT ,
 .Dv EX_CONFIG
 defined in
-.Xr sysexits 3 ,
-as well as 127.
+.Xr sysexits 3 .
+The exit status 127
+is always treated as a stop exit.
 .
 .It Fl t Ar interval
 Set the initial interval between restarts