fiss

Friedel's Initialization and Service Supervision
Log | Files | Refs | LICENSE

start.c (3073B)


      1 #include "service.h"
      2 
      3 #include <errno.h>
      4 #include <fcntl.h>
      5 #include <grp.h>
      6 #include <limits.h>
      7 #include <stdio.h>
      8 #include <stdlib.h>
      9 #include <string.h>
     10 #include <sys/stat.h>
     11 #include <unistd.h>
     12 
     13 
     14 static void set_pipes(struct service* s) {
     15 	if (s->is_log_service) {
     16 		close(s->log_pipe.write);
     17 		dup2(s->log_pipe.read, STDIN_FILENO);
     18 		close(s->log_pipe.read);
     19 		dup2(null_fd, STDOUT_FILENO);
     20 		dup2(null_fd, STDERR_FILENO);
     21 	} else if (s->log_service) {    // aka has_log_service
     22 		close(s->log_service->log_pipe.read);
     23 		dup2(s->log_service->log_pipe.write, STDOUT_FILENO);
     24 		dup2(s->log_service->log_pipe.write, STDERR_FILENO);
     25 		close(s->log_service->log_pipe.write);
     26 		dup2(null_fd, STDIN_FILENO);
     27 	} else if (stat_mode("log") & S_IWRITE) {    // is not
     28 		int log_fd;
     29 		if ((log_fd = open("log", O_WRONLY | O_TRUNC)) == -1)
     30 			log_fd = null_fd;
     31 
     32 		dup2(null_fd, STDIN_FILENO);
     33 		dup2(log_fd, STDOUT_FILENO);
     34 		dup2(log_fd, STDERR_FILENO);
     35 	} else if (S_ISREG(stat_mode("nolog"))) {
     36 		dup2(null_fd, STDIN_FILENO);
     37 		dup2(null_fd, STDOUT_FILENO);
     38 		dup2(null_fd, STDERR_FILENO);
     39 	} else {
     40 		char service_log[PATH_MAX];
     41 		int  log_fd;
     42 
     43 		snprintf(service_log, PATH_MAX, "%s/%s.log", SV_LOG_DIR, s->name);
     44 
     45 		if ((log_fd = open(service_log, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1)
     46 			log_fd = null_fd;
     47 
     48 		dup2(null_fd, STDIN_FILENO);
     49 		dup2(log_fd, STDOUT_FILENO);
     50 		dup2(log_fd, STDERR_FILENO);
     51 	}
     52 }
     53 
     54 void service_run(struct service* s) {
     55 	struct stat st;
     56 
     57 	if (fstatat(s->dir, "run", &st, 0) != -1 && st.st_mode & S_IXUSR) {
     58 		service_update_state(s, STATE_ACTIVE_FOREGROUND);
     59 	} else if (fstatat(s->dir, "start", &st, 0) != -1 && st.st_mode & S_IXUSR) {
     60 		service_update_state(s, STATE_STARTING);
     61 	} else if (fstatat(s->dir, "depends", &st, 0) != -1 && st.st_mode & S_IREAD) {
     62 		service_update_state(s, STATE_ACTIVE_DUMMY);
     63 	} else {
     64 		//		fprint(1, "warn: %s: `run`, `start` or `depends` not found\n", s->name);
     65 		service_update_state(s, STATE_INACTIVE);
     66 	}
     67 
     68 	if (s->state != STATE_ACTIVE_DUMMY) {
     69 		if ((s->pid = fork()) == -1) {
     70 			fprint(1, "error: cannot fork process: %r\n");
     71 			exit(1);
     72 		} else if (s->pid == 0) {    // child
     73 			if (setsid() == -1)
     74 				fprint(1, "error: cannot setsid: %r\n");
     75 
     76 			fchdir(s->dir);
     77 			set_pipes(s);
     78 
     79 			if (s->state == STATE_STARTING) {
     80 				execl("./start", "./start", NULL);
     81 			} else {
     82 				execl("./run", "./run", NULL);
     83 			}
     84 			fprint(1, "error: cannot execute service: %r\n");
     85 			_exit(1);
     86 		}
     87 	}
     88 }
     89 
     90 void service_start(struct service* s) {
     91 	struct stat st;
     92 
     93 	if (!daemon_running || s->state != STATE_INACTIVE)
     94 		return;
     95 
     96 	print("starting %s\n", s->name);
     97 	for (int i = 0; i < s->children_size; i++) {
     98 		service_start(s->children[i]);
     99 	}
    100 
    101 	if (fstatat(s->dir, "setup", &st, 0) != -1 && st.st_mode & S_IXUSR) {
    102 		if ((s->pid = fork_dup_cd_exec(s->dir, "./setup", null_fd, null_fd, null_fd)) == -1) {
    103 			fprint(1, "error: cannot execute ./setup: %r\n");
    104 			service_update_state(s, STATE_INACTIVE);
    105 		} else {
    106 			service_update_state(s, STATE_SETUP);
    107 		}
    108 	} else {
    109 		service_run(s);
    110 	}
    111 	print("started %s \n", s->name);
    112 }