commit 1c7f322771ce0ec8e4f0c937fb3210d0460f3271
parent 70471f1780f4ff9ec7605a357d134030a1879cbb
Author: Friedel Schön <[email protected]>
Date: Wed, 11 Oct 2023 15:42:42 +0200
some renaming, adding STATE_DONE
Diffstat:
27 files changed, 244 insertions(+), 200 deletions(-)
diff --git a/bin/chpst.c b/bin/chpst.c
@@ -5,11 +5,17 @@
#include <errno.h>
#include <fcntl.h>
+#include <grp.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/file.h>
+
+const char* current_prog(void) {
+ return "chpst";
+}
+
int main(int argc, char** argv) {
int opt, lockfd, lockflags, gid_len = 0;
char *arg0 = NULL, *root = NULL, *cd = NULL, *lock = NULL, *exec = NULL;
@@ -64,7 +70,7 @@ int main(int argc, char** argv) {
case 'r':
case 't':
case 'm': // ignored
- fprintf(stderr, "warning: '-%c' are ignored\n", optopt);
+ fprintf(stderr, "warning: '-%c' is ignored\n", optopt);
break;
case '?':
fprintf(stderr, "usage\n");
@@ -91,7 +97,7 @@ int main(int argc, char** argv) {
if (root) {
if (chroot(root) == -1)
- print_error("unable to change root directory: %s\n");
+ print_errno("unable to change root directory: %s\n");
// chdir to '/', otherwise the next command will complain 'directory not found'
chdir("/");
@@ -103,28 +109,28 @@ int main(int argc, char** argv) {
if (nicelevel != 0) {
if (nice(nicelevel) == -1)
- print_error("unable to set nice level: %s\n");
+ print_errno("unable to set nice level: %s\n");
}
if (lock) {
if ((lockfd = open(lock, O_WRONLY | O_APPEND)) == -1)
- print_error("unable to open lock: %s\n");
+ print_errno("unable to open lock: %s\n");
if (flock(lockfd, lockflags) == -1)
- print_error("unable to lock: %s\n");
+ print_errno("unable to lock: %s\n");
}
if (closestd[0] && close(0) == -1)
- print_error("unable to close stdin: %s\n");
+ print_errno("unable to close stdin: %s\n");
if (closestd[1] && close(1) == -1)
- print_error("unable to close stdout: %s\n");
+ print_errno("unable to close stdout: %s\n");
if (closestd[2] && close(2) == -1)
- print_error("unable to close stderr: %s\n");
+ print_errno("unable to close stderr: %s\n");
exec = argv[0];
if (arg0)
argv[0] = arg0;
execvp(exec, argv);
- print_error("cannot execute: %s\n");
+ print_errno("cannot execute: %s\n");
}
diff --git a/bin/finit.c b/bin/finit.c
@@ -1,6 +1,6 @@
// +objects: message.o util.o supervise.o service.o start.o stop.o
// +objects: register.o handle_exit.o handle_command.o
-// +objects: encode.o parse.o dependency.o status.o stage.o
+// +objects: encode.o dependency.o status.o stage.o
// +flags: -static
#include "config.h"
@@ -19,6 +19,10 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "finit";
+}
+
static bool do_reboot;
static int handle_initctl(int argc, const char** argv) {
@@ -33,7 +37,7 @@ static int handle_initctl(int argc, const char** argv) {
}
sig = argv[1][0] == '0' ? SIGTERM : SIGINT;
if (kill(1, sig) == -1) {
- print_error("error: unable to kill init: %s\n");
+ print_errno("error: unable to kill init: %s\n");
return 1;
}
return 0;
diff --git a/bin/fsvc.c b/bin/fsvc.c
@@ -16,6 +16,10 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "fsvc";
+}
+
static const char* const command_names[][2] = {
{ "up", "u" }, // starts the services, pin as started
{ "down", "d" }, // stops the service, pin as stopped
diff --git a/bin/fsvs.c b/bin/fsvs.c
@@ -13,6 +13,10 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "fsvs";
+}
+
static const struct option long_options[] = {
{ "version", no_argument, 0, 'V' },
{ "once", no_argument, 0, 'o' },
diff --git a/bin/halt.c b/bin/halt.c
@@ -10,6 +10,10 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "halt";
+}
+
int main(int argc, char* argv[]) {
bool do_sync = true,
do_force = false,
@@ -74,7 +78,7 @@ int main(int argc, char* argv[]) {
} else {
execl("/sbin/init", "init", initarg, NULL);
}
- print_error("reboot failed: %s\n");
+ print_errno("reboot failed: %s\n");
}
return 0;
diff --git a/bin/modules-load.c b/bin/modules-load.c
@@ -17,6 +17,10 @@
#define MAX_MODULE_COUNT 64
+const char* current_prog(void) {
+ return "modules-load";
+}
+
static char kernel_cmdline[MAX_CMDLINE_SIZE];
static char modules[MAX_MODULE_COUNT][MAX_MODULE_SIZE];
static int modules_size = 0;
@@ -30,7 +34,7 @@ static void read_cmdline(void) {
return;
if ((size = read(fd, kernel_cmdline, sizeof(kernel_cmdline))) == -1) {
- print_error("cannot read /proc/cmdline: %s\n");
+ print_errno("cannot read /proc/cmdline: %s\n");
close(fd);
return;
}
@@ -65,7 +69,7 @@ static void read_file(const char* path) {
char* comment;
if ((fd = open(path, O_RDONLY)) == -1) {
- print_error("unable to open %s: %s\n", path);
+ print_errno("unable to open %s: %s\n", path);
return;
}
@@ -136,6 +140,6 @@ int main(int argc, char** argv) {
execvp("modprobe", args);
- print_error("cannot exec modprobe: %s");
+ print_errno("cannot exec modprobe: %s");
return 1;
}
diff --git a/bin/seedrng.c b/bin/seedrng.c
@@ -18,6 +18,10 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "seedrng";
+}
+
#ifndef LOCALSTATEDIR
# define LOCALSTATEDIR "/var/lib"
#endif
diff --git a/bin/sigremap.c b/bin/sigremap.c
@@ -22,6 +22,7 @@
// +objects: message.o signame.o
+
#include "message.h"
#include "signame.h"
#include "util.h"
@@ -37,6 +38,11 @@
#include <sys/wait.h>
#include <unistd.h>
+
+const char* current_prog(void) {
+ return "sigremap";
+}
+
#define DEBUG(...) \
do { \
if (debug) \
@@ -243,14 +249,14 @@ int main(int argc, char* argv[]) {
child_pid = fork();
if (child_pid < 0) {
- print_error("error: unable to fork: %s\n");
+ print_errno("error: unable to fork: %s\n");
return 1;
} else if (child_pid == 0) {
/* child */
sigprocmask(SIG_UNBLOCK, &all_signals, NULL);
if (use_setsid) {
if (setsid() == -1) {
- print_error("error: unable to setsid: %s\n");
+ print_errno("error: unable to setsid: %s\n");
exit(1);
}
@@ -265,7 +271,7 @@ int main(int argc, char* argv[]) {
execvp(cmd[0], cmd);
// if this point is reached, exec failed, so we should exit nonzero
- print_error("error: unable to execute %s: %s\n", cmd[0]);
+ print_errno("error: unable to execute %s: %s\n", cmd[0]);
_exit(2);
}
diff --git a/bin/vlogger.c b/bin/vlogger.c
@@ -13,6 +13,11 @@
#include <sys/syslog.h>
#include <unistd.h>
+
+const char* current_prog(void) {
+ return "vlogger";
+}
+
static char pwd[PATH_MAX];
typedef struct ident {
@@ -114,7 +119,7 @@ int main(int argc, char* argv[]) {
switch (c) {
case 'f':
if (freopen(optarg, "r", stdin) == NULL) {
- print_error("error: unable to reopen %s: %s\n", optarg);
+ print_errno("error: unable to reopen %s: %s\n", optarg);
return 1;
}
break;
@@ -154,7 +159,7 @@ int main(int argc, char* argv[]) {
sfacility = ident->name;
}
execl("/etc/vlogger", argv0, tag ? tag : "", slevel, sfacility, NULL);
- print_error("error: unable to exec /etc/vlogger: %s\n");
+ print_errno("error: unable to exec /etc/vlogger: %s\n");
exit(1);
}
diff --git a/bin/zzz.c b/bin/zzz.c
@@ -10,15 +10,19 @@
#include <unistd.h>
+const char* current_prog(void) {
+ return "zzz";
+}
+
static int open_write(const char* path, const char* string) {
int fd;
if ((fd = open(path, O_WRONLY | O_TRUNC)) == -1) {
- print_error("cannot open %s: %s\n", path);
+ print_errno("cannot open %s: %s\n", path);
return -1;
}
if (write(fd, string, strlen(string)) == -1) {
- print_error("error writing to %s: %s\n", path);
+ print_errno("error writing to %s: %s\n", path);
close(fd);
return -1;
}
@@ -84,11 +88,11 @@ int main(int argc, char** argv) {
if (stat(SV_SUSPEND_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
if ((pid = fork()) == -1) {
- print_error("failed to fork for " SV_SUSPEND_EXEC ": %s\n");
+ print_errno("failed to fork for " SV_SUSPEND_EXEC ": %s\n");
return 1;
} else if (pid == 0) { // child
execl(SV_SUSPEND_EXEC, SV_SUSPEND_EXEC, NULL);
- print_error("failed to execute " SV_SUSPEND_EXEC ": %s\n");
+ print_errno("failed to execute " SV_SUSPEND_EXEC ": %s\n");
_exit(1);
}
@@ -107,11 +111,11 @@ int main(int argc, char** argv) {
if (stat(SV_RESUME_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
if ((pid = fork()) == -1) {
- print_error("failed to fork for " SV_RESUME_EXEC ": %s\n");
+ print_errno("failed to fork for " SV_RESUME_EXEC ": %s\n");
return 1;
} else if (pid == 0) { // child
execl(SV_RESUME_EXEC, SV_RESUME_EXEC, NULL);
- print_error("failed to execute " SV_RESUME_EXEC ": %s\n");
+ print_errno("failed to execute " SV_RESUME_EXEC ": %s\n");
_exit(1);
}
diff --git a/contrib/serialize.txt b/contrib/serialize.txt
@@ -9,7 +9,7 @@ RUNIT: | STATUS CHANGE | NANOSEC | PID |PS|WU|TR|SR|
STATUS CHANGE = unix seconds + 4611686018427387914ULL (tai, lower endian)
ST = state (see below)
-RC = last return code (0 if not exitted yet)
+RC = last return code (0 if not exited yet)
FC = fail count
FL = flags (see below)
PID = current pid (big endian)
@@ -24,13 +24,13 @@ FLAGS
-----
+--+--+--+--+--+--+--+--+
-| -- |TR|OC|RS|LSTEX|
+| -- |TR|OC|RS| LEX |
+--+--+--+--+--+--+--+--+
-TR = is terminating
-OC = started once
-RS = should restart
-LSTEX = last exit (0 = never exitted, 1 = normally, 2 = signaled)
--- = nothing yet
+TR = is terminating
+OC = started once
+RS = should restart
+LEX = last exit (0 = never exitted, 1 = normally, 2 = signaled)
+--- = nothing yet
; as dependency : wants-up != (restart || once)
diff --git a/include/parse.h b/include/parse.h
@@ -6,5 +6,5 @@
void parse_env_file(char** env);
-void parse_param_file(service_t* s, char* args[]);
+void parse_param_file(struct service* s, char* args[]);
int parse_ugid(char* str, uid_t* uid, gid_t* gids);
diff --git a/include/service.h b/include/service.h
@@ -35,6 +35,7 @@ enum service_state {
STATE_ACTIVE_DUMMY, // dependencies started
STATE_STOPPING, // ./stop running
STATE_FINISHING, // ./finish running
+ STATE_DONE, // ./stop finished
STATE_ERROR, // something went wrong
};
@@ -63,51 +64,49 @@ struct service_serial {
uint8_t state_runit;
};
-typedef struct service service_t;
-
struct service {
- char name[SV_NAME_MAX]; // name of service
- int state; // current state
- pid_t pid; // pid of run
- int dir; // dirfd
- int control; // fd to supervise/control
- time_t state_change; // last status change
- int restart; // should restart on exit
- int last_exit; // stopped signaled or exited
- int return_code; // return code or signal
- uint8_t fail_count; // current fail cound
- bool is_log_service; // is a log service
- bool paused; // is paused
- time_t stop_timeout; // stop start-time
- pipe_t log_pipe; // pipe for logging
- service_t* log_service; // has a log_server otherwise NULL
+ char name[SV_NAME_MAX]; // name of service
+ enum service_state state; // current state
+ pid_t pid; // pid of run
+ int dir; // dirfd
+ int control; // fd to supervise/control
+ time_t state_change; // last status change
+ int restart; // should restart on exit
+ enum service_exit last_exit; // stopped signaled or exited
+ int return_code; // return code or signal
+ uint8_t fail_count; // current fail cound
+ bool is_log_service; // is a log service
+ bool paused; // is paused
+ time_t stop_timeout; // stop start-time
+ pipe_t log_pipe; // pipe for logging
+ struct service* log_service; // has a log_server otherwise NULL
};
-extern service_t services[];
-extern int services_size;
-extern int service_dir;
-extern int null_fd;
-extern bool daemon_running;
-extern service_t* depends[][2];
-extern int depends_size;
-extern const char* service_dir_path;
+extern struct service services[];
+extern int services_size;
+extern int service_dir;
+extern int null_fd;
+extern bool daemon_running;
+extern struct service* depends[][2];
+extern int depends_size;
+extern const char* service_dir_path;
-void service_encode(service_t* s, void* buffer);
-service_t* service_get(const char* name);
-void service_handle_command(service_t* s, char command);
-void service_handle_exit(service_t* s, bool signaled, int return_code);
-void service_kill(service_t* s, int signal);
-bool service_need_restart(service_t* s);
-int service_refresh_directory(void);
-service_t* service_register(int dir, const char* name, bool is_log_service);
-void service_run(service_t* s);
-int service_send_command(char command, char extra, const char* service, service_t* response, int response_max);
-void service_start(service_t* s);
-const char* service_status_name(service_t* s);
-void service_stop(service_t* s);
-int service_supervise(const char* service_dir_, const char* service, bool once);
-void service_update_dependency(service_t* s);
-bool service_is_dependency(service_t* s);
-void service_update_state(service_t* s, int state);
-void service_write(service_t* s);
+void service_encode(struct service* s, struct service_serial* buffer);
+struct service* service_get(const char* name);
+void service_handle_command(struct service* s, char command);
+void service_handle_exit(struct service* s, bool signaled, int return_code);
+void service_kill(struct service* s, int signal);
+bool service_need_restart(struct service* s);
+int service_refresh_directory(void);
+struct service* service_register(int dir, const char* name, bool is_log_service);
+void service_run(struct service* s);
+int service_send_command(char command, char extra, const char* service, struct service* response, int response_max);
+void service_start(struct service* s);
+const char* service_status_name(struct service* s);
+void service_stop(struct service* s);
+int service_supervise(const char* service_dir_, const char* service, bool once);
+void service_update_dependency(struct service* s);
+bool service_is_dependency(struct service* s);
+void service_update_state(struct service* s, int state);
+void service_write(struct service* s);
diff --git a/include/util.h b/include/util.h
@@ -4,13 +4,16 @@
#define streq(a, b) (!strcmp((a), (b)))
-#define print_error(msg, ...) (fprintf(stderr, msg, ##__VA_ARGS__, strerror(errno)))
+#define print_errno(msg, ...) (fprintf(stderr, "%s: " msg, current_prog(), ##__VA_ARGS__, strerror(errno)))
+#define print_error(msg, ...) (fprintf(stderr, "%s: " msg, current_prog(), ##__VA_ARGS__))
typedef struct {
int read;
int write;
} pipe_t;
+const char* current_prog(void); // has to be defined per program
+
ssize_t dgetline(int fd, char* line, size_t line_buffer);
ssize_t readstr(int fd, char* str);
ssize_t writestr(int fd, const char* str);
diff --git a/mk/target.mk b/mk/target.mk
@@ -4,46 +4,46 @@ $(TARGET_DIRS):
$(SILENT)mkdir -p $@
$(TARGET_ASSETS_DIR): $(ASSETS_DIR) | $(TARGET_DOCS_DIR)
- @echo "[COPY] $@"
+ @echo "[COPY] $< -> $@"
$(SILENT)mkdir -p $@
$(SILENT)cp -r $</* $@
# Object rules
$(TARGET_OBJECT_DIR)/%.o: $(SRC_DIR)/%.c $(INCLUDE_FILES) | $(TARGET_OBJECT_DIR)
- @echo "[ CC ] $@"
+ @echo "[ CC ] $< -> $@"
$(SILENT)$(CC) -o $@ $< -c $(CFLAGS) $(shell mk/extract-flags.sh $< $(TARGET_OBJECT_DIR))
# Object rules
$(TARGET_OBJECT_DIR)/%.o: $(BIN_DIR)/%.c $(INCLUDE_FILES) | $(TARGET_OBJECT_DIR)
- @echo "[ CC ] $@"
+ @echo "[ CC ] $< -> $@"
$(SILENT)$(CC) -o $@ $< -c $(CFLAGS) $(shell mk/extract-flags.sh $<)
# Executables
$(TARGET_BIN_DIR)/%: $(TARGET_OBJECT_DIR)/%.o $(OBJ_FILES) | $(TARGET_BIN_DIR)
- @echo "[ LD ] $@"
+ @echo "[ LD ] $< -> $@"
$(SILENT)$(CC) -o $@ $< $(shell mk/extract-flags.sh $(patsubst $(TARGET_BIN_DIR)/%,$(BIN_DIR)/%.c,$@) $(TARGET_OBJECT_DIR)) $(LDFLAGS)
$(TARGET_BIN_DIR)/%: $(BIN_DIR)/%.sh | $(TARGET_BIN_DIR)
- @echo "[COPY] $@"
+ @echo "[COPY] $< -> $@"
$(SILENT)cp $< $@
$(SILENT)chmod +x $@
$(TARGET_BIN_DIR)/%: $(BIN_DIR)/%.lnk | $(TARGET_BIN_DIR)
- @echo "[LINK] $@"
+ @echo "[LINK] $< -> $@"
$(SILENT)ln -sf $(shell cat $<) $@
# Documentation and Manual
$(TARGET_DOCS_DIR)/%.html: $(DOCS_DIR)/%.txt $(TARGET_ASSETS_DIR) $(MAKE_DOCS) | $(TARGET_DOCS_DIR)
- @echo "[MDOC] $@"
+ @echo "[MDOC] $< -> $@"
$(SILENT)$(SED) 's/%VERSION%/$(VERSION)/' $< | $(PYTHON) $(MAKE_DOCS) > $@
$(TARGET_DOCS_DIR)/%.html: $(MAN_DIR)/%.txt $(TARGET_ASSETS_DIR) $(MAKE_DOCS) | $(TARGET_DOCS_DIR)
- @echo "[MDOC] $@"
+ @echo "[MDOC] $< -> $@"
$(SILENT)$(SED) 's/%VERSION%/$(VERSION)/' $< | $(PYTHON) $(MAKE_DOCS) > $@
$(TARGET_MAN_DIR)/%: $(MAN_DIR)/%.txt $(MAKE_MAN) | $(TARGET_MAN_DIR)
- @echo "[MMAN] $@"
+ @echo "[MMAN] $< -> $@"
$(SILENT)$(SED) 's/%VERSION%/$(VERSION)/' $< | $(PYTHON) $(MAKE_MAN) | $(AWK) '/./ { print }' > $@
# Debug
diff --git a/src/dependency.c b/src/dependency.c
@@ -9,7 +9,7 @@
#include <unistd.h>
-void service_add_dependency(service_t* s, service_t* d) {
+void service_add_dependency(struct service* s, struct service* d) {
if (s == d)
return;
@@ -18,10 +18,10 @@ void service_add_dependency(service_t* s, service_t* d) {
depends_size++;
}
-void service_update_dependency(service_t* s) {
- service_t* dep;
- int depends_file;
- char line[SV_NAME_MAX];
+void service_update_dependency(struct service* s) {
+ struct service* dep;
+ int depends_file;
+ char line[SV_NAME_MAX];
if (s->log_service) { // aka keep first entry (the log service) if a log service is used
service_add_dependency(s, s->log_service);
diff --git a/src/encode.c b/src/encode.c
@@ -1,29 +1,8 @@
#include "service.h"
-void service_encode(service_t* s, void* buffer_ptr) {
- struct service_serial* buffer = buffer_ptr;
-
- uint64_t tai = (uint64_t) s->state_change + 4611686018427387914ULL;
- int state_runit;
-
- switch (s->state) {
- case STATE_INACTIVE:
- case STATE_ERROR:
- state_runit = 0;
- break;
- case STATE_SETUP:
- case STATE_STARTING:
- case STATE_ACTIVE_DUMMY:
- case STATE_ACTIVE_FOREGROUND:
- case STATE_ACTIVE_BACKGROUND:
- case STATE_STOPPING:
- state_runit = 1;
- break;
- case STATE_FINISHING:
- state_runit = 2;
- break;
- }
+void service_encode(struct service* s, struct service_serial* buffer) {
+ uint64_t tai = (uint64_t) s->state_change + 4611686018427387914llu;
buffer->status_change[0] = (tai >> 56) & 0xff;
buffer->status_change[1] = (tai >> 48) & 0xff;
@@ -48,8 +27,26 @@ void service_encode(service_t* s, void* buffer_ptr) {
buffer->pid[2] = (s->pid >> 16) & 0xff;
buffer->pid[3] = (s->pid >> 24) & 0xff;
- buffer->paused = s->paused;
- buffer->restart = service_need_restart(s) ? 'u' : 'd';
- buffer->force_down = 0;
- buffer->state_runit = state_runit;
+ buffer->paused = s->paused;
+ buffer->restart = service_need_restart(s) ? 'u' : 'd';
+ buffer->force_down = 0;
+
+ switch (s->state) {
+ case STATE_INACTIVE:
+ case STATE_ERROR:
+ case STATE_DONE:
+ buffer->state_runit = 0; // inactive
+ break;
+ case STATE_SETUP:
+ case STATE_STARTING:
+ case STATE_ACTIVE_DUMMY:
+ case STATE_ACTIVE_FOREGROUND:
+ case STATE_ACTIVE_BACKGROUND:
+ case STATE_STOPPING:
+ buffer->state_runit = 1; // running
+ break;
+ case STATE_FINISHING:
+ buffer->state_runit = 2; // finishing
+ break;
+ }
}
diff --git a/src/handle_command.c b/src/handle_command.c
@@ -17,7 +17,7 @@ static int runit_signals[] = {
[X_USR2] = SIGUSR2,
};
-void service_handle_command(service_t* s, char command) {
+void service_handle_command(struct service* s, char command) {
switch ((enum service_command) command) {
case X_UP:
s->restart = S_RESTART;
diff --git a/src/handle_exit.c b/src/handle_exit.c
@@ -10,12 +10,12 @@
#include <unistd.h>
-static void do_finish(service_t* s) {
+static void do_finish(struct service* s) {
struct stat st;
if (fstatat(s->dir, "finish", &st, 0) != -1 && st.st_mode & S_IXUSR) {
if ((s->pid = fork_dup_cd_exec(s->dir, "./finish", null_fd, null_fd, null_fd)) == -1) {
- print_error("error: cannot execute ./finish: %s\n");
+ print_errno("error: cannot execute ./finish: %s\n");
service_update_state(s, STATE_INACTIVE);
} else {
service_update_state(s, STATE_FINISHING);
@@ -24,12 +24,12 @@ static void do_finish(service_t* s) {
service_update_state(s, STATE_ERROR);
printf("%s died\n", s->name);
} else {
- service_update_state(s, STATE_INACTIVE);
+ service_update_state(s, s->restart == S_ONCE ? STATE_DONE : STATE_INACTIVE);
}
}
-void service_handle_exit(service_t* s, bool signaled, int return_code) {
+void service_handle_exit(struct service* s, bool signaled, int return_code) {
struct stat st;
s->pid = 0;
@@ -74,7 +74,7 @@ void service_handle_exit(service_t* s, bool signaled, int return_code) {
service_update_state(s, STATE_ERROR);
printf("%s died\n", s->name);
} else {
- service_update_state(s, STATE_INACTIVE);
+ service_update_state(s, s->restart == S_ONCE ? STATE_DONE : STATE_INACTIVE);
}
break;
case STATE_STARTING:
@@ -99,6 +99,7 @@ void service_handle_exit(service_t* s, bool signaled, int return_code) {
case STATE_ERROR:
case STATE_INACTIVE:
- printf("warn: %s died but was set to inactive\n", s->name);
+ case STATE_DONE:
+ printf("unexpected error: %s died but it's inactive\n", s->name);
}
}
diff --git a/src/register.c b/src/register.c
@@ -11,7 +11,7 @@
#include <unistd.h>
-static int init_supervise(service_t* s) {
+static int init_supervise(struct service* s) {
int fd;
struct stat st;
@@ -20,27 +20,27 @@ static int init_supervise(service_t* s) {
}
if (fstatat(s->dir, "supervise/ok", &st, 0) == -1 && mkfifoat(s->dir, "supervise/ok", 0666) == -1) {
- print_error("cannot create fifo at supervise/ok: %s\n");
+ print_errno("cannot create fifo at supervise/ok: %s\n");
return -1;
}
if (fstatat(s->dir, "supervise/control", &st, 0) == -1 && mkfifoat(s->dir, "supervise/control", 0644) == -1) {
- print_error("cannot create fifo at supervise/control: %s\n");
+ print_errno("cannot create fifo at supervise/control: %s\n");
return -1;
}
if (openat(s->dir, "supervise/ok", O_RDONLY | O_NONBLOCK) == -1) {
- print_error("cannot open supervise/ok: %s\n");
+ print_errno("cannot open supervise/ok: %s\n");
return -1;
}
if ((s->control = openat(s->dir, "supervise/control", O_RDONLY | O_NONBLOCK)) == -1) {
- print_error("cannot open supervise/ok: %s\n");
+ print_errno("cannot open supervise/ok: %s\n");
return -1;
}
if ((fd = openat(s->dir, "supervise/lock", O_CREAT | O_WRONLY, 0644)) == -1) {
- print_error("cannot create supervise/lock: %s\n");
+ print_errno("cannot create supervise/lock: %s\n");
return -1;
}
close(fd);
@@ -48,9 +48,9 @@ static int init_supervise(service_t* s) {
return 0;
}
-service_t* service_register(int dir, const char* name, bool is_log_service) {
- service_t* s;
- struct stat st;
+struct service* service_register(int dir, const char* name, bool is_log_service) {
+ struct service* s;
+ struct stat st;
if ((s = service_get(name)) == NULL) {
s = &services[services_size++];
@@ -67,7 +67,7 @@ service_t* service_register(int dir, const char* name, bool is_log_service) {
s->stop_timeout = 0;
if ((s->dir = openat(dir, name, O_DIRECTORY)) == -1) {
- print_error("error: cannot open '%s': %s\n", name);
+ print_errno("error: cannot open '%s': %s\n", name);
services_size--;
return NULL;
}
diff --git a/src/service.c b/src/service.c
@@ -10,18 +10,18 @@
#include <unistd.h>
-service_t services[SV_SERVICE_MAX];
-int services_size = 0;
-char runlevel[SV_NAME_MAX];
-int service_dir;
-const char* service_dir_path;
-int control_socket;
-int null_fd;
-service_t* depends[SV_DEPENDENCY_MAX][2];
-int depends_size;
-bool daemon_running;
-
-service_t* service_get(const char* name) {
+struct service services[SV_SERVICE_MAX];
+int services_size = 0;
+char runlevel[SV_NAME_MAX];
+int service_dir;
+const char* service_dir_path;
+int control_socket;
+int null_fd;
+struct service* depends[SV_DEPENDENCY_MAX][2];
+int depends_size;
+bool daemon_running;
+
+struct service* service_get(const char* name) {
for (int i = 0; i < services_size; i++) {
if (streq(services[i].name, name))
return &services[i];
@@ -30,13 +30,13 @@ service_t* service_get(const char* name) {
}
int service_refresh_directory(void) {
- DIR* dp;
- struct dirent* ep;
- struct stat st;
- service_t* s;
+ DIR* dp;
+ struct dirent* ep;
+ struct stat st;
+ struct service* s;
if ((dp = opendir(service_dir_path)) == NULL) {
- print_error("error: cannot open service directory: %s\n");
+ print_errno("error: cannot open service directory: %s\n");
return -1;
}
@@ -69,8 +69,8 @@ int service_refresh_directory(void) {
}
-bool service_need_restart(service_t* s) {
- service_t* d;
+bool service_need_restart(struct service* s) {
+ struct service* d;
if (!daemon_running)
return false;
diff --git a/src/stage.c b/src/stage.c
@@ -25,7 +25,7 @@ bool handle_stage(int stage) {
bool cont = true;
while ((pid = fork()) == -1) {
- print_error("error: unable to fork for stage1: %s\n");
+ print_errno("error: unable to fork for stage1: %s\n");
sleep(5);
}
if (pid == 0) {
@@ -34,7 +34,7 @@ bool handle_stage(int stage) {
if (stage == 0) {
/* stage 1 gets full control of console */
if ((ttyfd = open("/dev/console", O_RDWR)) == -1) {
- print_error("error: unable to open /dev/console: %s\n");
+ print_errno("error: unable to open /dev/console: %s\n");
} else {
ioctl(ttyfd, TIOCSCTTY, NULL); // make the controlling process
dup2(ttyfd, 0);
@@ -46,7 +46,7 @@ bool handle_stage(int stage) {
printf("enter stage %d\n", stage);
execv(stage_exec[stage][0], stage_exec[stage]);
- print_error("error: unable to exec stage %d: %s\n", stage);
+ print_errno("error: unable to exec stage %d: %s\n", stage);
_exit(1);
}
@@ -61,7 +61,7 @@ bool handle_stage(int stage) {
kill(pid, SIGTERM);
if (waitpid(pid, &exitstat, 0) == -1) {
- print_error("warn: waitpid failed: %s");
+ print_errno("warn: waitpid failed: %s");
sleep(5);
}
diff --git a/src/start.c b/src/start.c
@@ -12,7 +12,7 @@
#include <unistd.h>
-static void set_pipes(service_t* s) {
+static void set_pipes(struct service* s) {
if (s->is_log_service) {
close(s->log_pipe.write);
dup2(s->log_pipe.read, STDIN_FILENO);
@@ -52,7 +52,7 @@ static void set_pipes(service_t* s) {
}
}
-void service_run(service_t* s) {
+void service_run(struct service* s) {
struct stat st;
if (fstatat(s->dir, "run", &st, 0) != -1 && st.st_mode & S_IXUSR) {
@@ -68,11 +68,11 @@ void service_run(service_t* s) {
if (s->state != STATE_ACTIVE_DUMMY) {
if ((s->pid = fork()) == -1) {
- print_error("error: cannot fork process: %s\n");
+ print_errno("error: cannot fork process: %s\n");
exit(1);
} else if (s->pid == 0) { // child
if (setsid() == -1)
- print_error("error: cannot setsid: %s\n");
+ print_errno("error: cannot setsid: %s\n");
fchdir(s->dir);
set_pipes(s);
@@ -82,13 +82,13 @@ void service_run(service_t* s) {
} else {
execl("./run", "./run", NULL);
}
- print_error("error: cannot execute service: %s\n");
+ print_errno("error: cannot execute service: %s\n");
_exit(1);
}
}
}
-void service_start(service_t* s) {
+void service_start(struct service* s) {
struct stat st;
if (!daemon_running || s->state != STATE_INACTIVE)
@@ -102,7 +102,7 @@ void service_start(service_t* s) {
if (fstatat(s->dir, "setup", &st, 0) != -1 && st.st_mode & S_IXUSR) {
if ((s->pid = fork_dup_cd_exec(s->dir, "./setup", null_fd, null_fd, null_fd)) == -1) {
- print_error("error: cannot execute ./setup: %s\n");
+ print_errno("error: cannot execute ./setup: %s\n");
service_update_state(s, STATE_INACTIVE);
} else {
service_update_state(s, STATE_SETUP);
diff --git a/src/status.c b/src/status.c
@@ -11,7 +11,7 @@
#include <unistd.h>
-void service_update_state(service_t* s, int state) {
+void service_update_state(struct service* s, int state) {
if (state != -1)
s->state = state;
@@ -20,40 +20,40 @@ void service_update_state(service_t* s, int state) {
service_write(s);
}
-void service_write(service_t* s) {
+void service_write(struct service* s) {
int fd;
const char* stat_human;
struct service_serial stat_runit;
if ((fd = openat(s->dir, "supervise/status.new", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot open supervise/status: %s\n");
+ print_errno("cannot open supervise/status: %s\n");
return;
}
service_encode(s, &stat_runit);
if (write(fd, &stat_runit, sizeof(stat_runit)) == -1) {
- print_error("cannot write to supervise/status: %s\n");
+ print_errno("cannot write to supervise/status: %s\n");
return;
}
close(fd);
if ((fd = openat(s->dir, "supervise/stat.new", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot create supervise/stat: %s\n");
+ print_errno("cannot create supervise/stat: %s\n");
return;
}
stat_human = service_status_name(s);
if (write(fd, stat_human, strlen(stat_human)) == -1) {
- print_error("cannot write to supervise/stat: %s\n");
+ print_errno("cannot write to supervise/stat: %s\n");
return;
}
close(fd);
if ((fd = openat(s->dir, "supervise/pid.new", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot create supervise/stat: %s\n");
+ print_errno("cannot create supervise/stat: %s\n");
return;
}
@@ -66,7 +66,7 @@ void service_write(service_t* s) {
renameat(s->dir, "supervise/pid.new", s->dir, "supervise/pid");
}
-const char* service_status_name(service_t* s) {
+const char* service_status_name(struct service* s) {
switch (s->state) {
case STATE_SETUP:
return "setup";
@@ -84,6 +84,8 @@ const char* service_status_name(service_t* s) {
return "stopping";
case STATE_INACTIVE:
return "down";
+ case STATE_DONE:
+ return "done";
case STATE_ERROR:
return "dead (error)";
default:
diff --git a/src/stop.c b/src/stop.c
@@ -9,17 +9,14 @@
#include <unistd.h>
-void service_stop(service_t* s) {
- if (s->stop_timeout > 0)
- return;
-
+void service_stop(struct service* s) {
switch (s->state) {
case STATE_ACTIVE_DUMMY:
service_handle_exit(s, false, 0);
break;
case STATE_ACTIVE_BACKGROUND:
if ((s->pid = fork_dup_cd_exec(s->dir, "./stop", null_fd, null_fd, null_fd)) == -1) {
- print_error("error: cannot execute ./stop: %s\n");
+ print_errno("error: cannot execute ./stop: %s\n");
service_update_state(s, STATE_INACTIVE);
} else {
service_update_state(s, STATE_STOPPING);
@@ -30,17 +27,19 @@ void service_stop(service_t* s) {
case STATE_STARTING:
case STATE_STOPPING:
case STATE_FINISHING:
- kill(s->pid, SIGTERM);
s->stop_timeout = time(NULL);
+ kill(s->pid, SIGTERM);
service_update_state(s, -1);
break;
+ case STATE_DONE:
+ s->state = STATE_INACTIVE;
case STATE_INACTIVE:
case STATE_ERROR:
break;
}
}
-void service_kill(service_t* s, int signal) {
+void service_kill(struct service* s, int signal) {
if (!s->pid)
return;
diff --git a/src/supervise.c b/src/supervise.c
@@ -18,12 +18,12 @@
static void signal_child(int unused) {
(void) unused;
- int status;
- pid_t died_pid;
- service_t* s = NULL;
+ int status;
+ pid_t died_pid;
+ struct service* s = NULL;
if ((died_pid = wait(&status)) == -1) {
- print_error("error: cannot wait for process: %s\n");
+ print_errno("error: cannot wait for process: %s\n");
return;
}
@@ -43,33 +43,31 @@ static void signal_child(int unused) {
}
static void update_services(void) {
- service_t* s;
+ struct service* s;
for (int i = 0; i < services_size; i++) {
s = &services[i];
+ if (s->state == STATE_INACTIVE || s->state == STATE_ERROR)
+ s->stop_timeout = 0;
+
if (s->state == STATE_ERROR)
continue;
if (s->stop_timeout != 0) {
- if (s->state == STATE_INACTIVE || s->state == STATE_ERROR) {
- s->stop_timeout = 0;
- } else if (time(NULL) - s->stop_timeout >= SV_STOP_TIMEOUT) {
+ if (time(NULL) - s->stop_timeout >= SV_STOP_TIMEOUT) {
printf(":: service '%s' doesn't terminate, killing...\n", s->name);
service_kill(s, SIGKILL);
s->stop_timeout = 0;
}
- continue;
- }
-
- if (s->state == STATE_INACTIVE && service_need_restart(s)) {
+ } else if (s->state == STATE_INACTIVE && service_need_restart(s)) {
service_start(s);
}
}
}
static void control_sockets(void) {
- service_t* s;
- char cmd;
+ struct service* s;
+ char cmd;
for (int i = 0; i < services_size; i++) {
s = &services[i];
@@ -103,7 +101,7 @@ void stop_dummies(void) {
int service_supervise(const char* service_dir_, const char* service, bool once) {
struct sigaction sigact = { 0 };
- service_t* s;
+ struct service* s;
daemon_running = true;
@@ -114,12 +112,12 @@ int service_supervise(const char* service_dir_, const char* service, bool once)
service_dir_path = service_dir_;
if ((service_dir = open(service_dir_, O_DIRECTORY)) == -1) {
- print_error("error: cannot open directory %s: %s\n", service_dir_);
+ print_errno("error: cannot open directory %s: %s\n", service_dir_);
return 1;
}
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
- print_error("error: cannot open /dev/null: %s\n");
+ print_errno("error: cannot open /dev/null: %s\n");
null_fd = 1;
}
diff --git a/src/util.c b/src/util.c
@@ -65,7 +65,7 @@ int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2) {
pid_t pid;
if ((pid = fork()) == -1) {
- print_error("error: cannot fork process: %s\n");
+ print_errno("error: cannot fork process: %s\n");
return -1;
} else if (pid == 0) {
dup2(fd0, STDIN_FILENO);
@@ -75,7 +75,7 @@ int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2) {
fchdir(dir);
execl(path, path, NULL);
- print_error("error: cannot execute stop process: %s\n");
+ print_errno("error: cannot execute stop process: %s\n");
_exit(1);
}
return pid;