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 }