summary refs log tree commit diff
path: root/service.c
diff options
context:
space:
mode:
Diffstat (limited to 'service.c')
-rw-r--r--service.c52
1 files changed, 52 insertions, 0 deletions
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);
+}