commit b5261e475dfdc8521ef7dee6db8eaa477c56f6fa
parent 6d8e3c1c6a6955a68539f870357669ed0bb0d9c1
Author: Friedel Schön <[email protected]>
Date: Thu, 25 May 2023 15:03:39 +0200
formatting C-like (defs on top)
Diffstat:
23 files changed, 199 insertions(+), 455 deletions(-)
diff --git a/include/config.h b/include/config.h
@@ -1,10 +1,5 @@
#pragma once
-// environment variable where the current runlevel is stored
-#ifndef SV_RUNLEVEL_DEFAULT_ENV
-# define SV_RUNLEVEL_DEFAULT_ENV "SERVICE_RUNLEVEL"
-#endif
-
// seconds to wait for a service before it gets killed
#ifndef SV_STOP_TIMEOUT
# define SV_STOP_TIMEOUT 5
@@ -12,7 +7,7 @@
// maximal characters a service-dir can have
#ifndef SV_NAME_MAX
-# define SV_NAME_MAX 512
+# define SV_NAME_MAX 128
#endif
// maximal dependencies a service can have
diff --git a/include/util.h b/include/util.h
@@ -13,15 +13,12 @@ typedef struct {
int write;
} pipe_t;
-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);
-
+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);
unsigned int stat_mode(const char* format, ...);
-
-int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2);
-
-int reclaim_console(void);
-void sigblock_all(int unblock);
-
-long parse_long(const char* str, const char* name);
+int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2);
+int reclaim_console(void);
+void sigblock_all(int unblock);
+long parse_long(const char* str, const char* name);
+char* progname(char* path);
diff --git a/src/dependency.c b/src/dependency.c
@@ -20,16 +20,16 @@ void service_add_dependency(service_t* s, service_t* d) {
void service_update_dependency(service_t* s) {
service_t* 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);
}
- int depends_file;
if ((depends_file = openat(s->dir, "depends", O_RDONLY)) == -1)
return;
- char line[SV_NAME_MAX];
while (dgetline(depends_file, line, sizeof(line)) > 0) {
if (streq(s->name, line)) {
fprintf(stderr, "warning: %s depends on itself\n", s->name);
diff --git a/src/exec/chpst.c b/src/exec/chpst.c
@@ -27,19 +27,6 @@ int main(int argc, char** argv) {
case 'b':
arg0 = optarg;
break;
- case 'e': // ignored
- fprintf(stderr, "`envdir` is ignored\n");
- break;
- case 'd':
- case 'o':
- case 'p':
- case 'f':
- case 'c':
- case 'r':
- case 't':
- case 'm': // ignored
- fprintf(stderr, "limits are ignored\n");
- break;
case '/':
root = optarg;
break;
@@ -67,6 +54,17 @@ int main(int argc, char** argv) {
case '2':
closestd[opt - '0'] = true;
break;
+ case 'e':
+ case 'd':
+ case 'o':
+ case 'p':
+ case 'f':
+ case 'c':
+ case 'r':
+ case 't':
+ case 'm': // ignored
+ fprintf(stderr, "warning: '-%c' are ignored\n", optopt);
+ break;
case '?':
fprintf(stderr, "usage\n");
return 1;
diff --git a/src/exec/finit.c b/src/exec/finit.c
@@ -14,6 +14,8 @@
int handle_initctl(int argc, const char** argv) {
+ int sig;
+
if (argc != 2 || argv[1][1] != '\0' || (argv[1][0] != '0' && argv[1][0] != '6')) {
print_usage_exit(PROG_FINIT, 1);
}
@@ -21,7 +23,7 @@ int handle_initctl(int argc, const char** argv) {
fprintf(stderr, "error: can only be run as root...\n");
return 1;
}
- int sig = argv[1][0] == '0' ? SIGTERM : SIGINT;
+ sig = argv[1][0] == '0' ? SIGTERM : SIGINT;
if (kill(1, sig) == -1) {
print_error("error: unable to kill init: %s\n");
return 1;
@@ -40,6 +42,7 @@ static void signal_interrupt(int signum) {
int main(int argc, const char** argv) {
sigset_t ss;
+ pid_t pid;
if (getpid() != 1) {
return handle_initctl(argc, argv);
@@ -61,10 +64,11 @@ int main(int argc, const char** argv) {
// stage 2
if (daemon_running) { // stage1 succeed
+ struct sigaction sigact = { 0 };
+
sigblock_all(true);
- struct sigaction sigact = { 0 };
- sigact.sa_handler = signal_interrupt;
+ sigact.sa_handler = signal_interrupt;
sigaction(SIGTERM, &sigact, NULL);
sigaction(SIGINT, &sigact, NULL);
@@ -79,7 +83,6 @@ int main(int argc, const char** argv) {
/* fallthrough stage 3 */
printf("sending KILL signal to all processes...\n");
kill(-1, SIGKILL);
- pid_t pid;
if ((pid = fork()) <= 0) {
if (do_reboot) {
diff --git a/src/exec/fsvc.c b/src/exec/fsvc.c
@@ -49,22 +49,9 @@ static const struct option long_options[] = {
{ 0 }
};
-static char* progname(char* path) {
- char* match;
- for (;;) {
- if ((match = strrchr(path, '/')) == NULL)
- return path;
-
- if (match[1] != '\0')
- return match + 1;
-
- *match = '\0';
- }
- return path;
-}
-
static int check_service(int dir) {
int fd;
+
if ((fd = openat(dir, "supervise/ok", O_WRONLY | O_NONBLOCK)) == -1)
return -1;
close(fd);
@@ -114,8 +101,9 @@ int status(int dir) {
}
int main(int argc, char** argv) {
- int opt;
- int timeout = SV_STATUS_WAIT;
+ int opt, dir,
+ timeout = SV_STATUS_WAIT;
+ time_t mod, start;
const char* command = NULL;
@@ -168,8 +156,6 @@ int main(int argc, char** argv) {
command++;
}
- int dir;
- time_t mod, start;
for (int i = 0; i < argc; i++) {
if ((dir = open(argv[i], O_DIRECTORY)) == -1) {
fprintf(stderr, "warning: '%s' is not a valid directory\n", argv[0]);
diff --git a/src/exec/halt.c b/src/exec/halt.c
@@ -14,27 +14,22 @@ int main(int argc, char* argv[]) {
do_wtmp = true,
noop = false;
int opt;
- char* progname;
int rebootnum;
const char* initarg;
- if ((progname = strrchr(argv[0], '/')) != NULL) {
- progname++; // to hide '/'
- } else {
- progname = argv[0];
- }
+ char* prog = progname(argv[0]);
- if (streq(progname, "halt")) {
+ if (streq(prog, "halt")) {
rebootnum = RB_HALT_SYSTEM;
initarg = "0";
- } else if (streq(progname, "poweroff")) {
+ } else if (streq(prog, "poweroff")) {
rebootnum = RB_POWER_OFF;
initarg = "0";
- } else if (streq(progname, "reboot")) {
+ } else if (streq(prog, "reboot")) {
rebootnum = RB_AUTOBOOT;
initarg = "6";
} else {
- fprintf(stderr, "invalid mode: %s\n", progname);
+ fprintf(stderr, "invalid mode: %s\n", prog);
return 1;
}
diff --git a/src/exec/shutdown.sh b/src/exec/shutdown.sh
@@ -1,10 +1,6 @@
#!/bin/sh
# shutdown - shutdown(8) lookalike for fiss
-single() {
- fsvc chlevel single
-}
-
abort() {
printf '%s\n' "$1" >&2
exit 1
@@ -14,7 +10,7 @@ usage() {
abort "Usage: ${0##*/} [-fF] [-kchPr] time [warning message]"
}
-action=single
+action=:
while getopts akrhPHfFnct: opt; do
case "$opt" in
diff --git a/src/exec/sigremap.c b/src/exec/sigremap.c
@@ -20,15 +20,6 @@
THE SOFTWARE.
*/
-/*
- * sigremap is a simple wrapper program designed to run as PID 1 and pass
- * signals to its children.
- *
- * Usage:
- * ./sigremap python -c 'while True: pass'
- *
- * To get debug output on stderr, run with '-v'.
- */
#include "message.h"
#include "signame.h"
@@ -63,28 +54,14 @@
// Indices are one-indexed (signal 1 is at index 1). Index zero is unused.
// User-specified signal rewriting.
-int signal_remap[MAXSIG + 1];
+static int signal_remap[MAXSIG + 1];
// One-time ignores due to TTY quirks. 0 = no skip, 1 = skip the next-received signal.
-bool signal_temporary_ignores[MAXSIG + 1];
-
-int child_pid = -1;
-bool debug = false;
-bool use_setsid = true;
-
-void forward_signal(int signum) {
- if (signum >= 0 && signum <= MAXSIG && signal_remap[signum] != -1) {
- DEBUG("Translating signal %d to %d.\n", signum, signal_remap[signum]);
- signum = signal_remap[signum];
- }
+static bool signal_temporary_ignores[MAXSIG + 1];
- if (signum == 0) {
- DEBUG("Not forwarding signal %d to children (ignored).\n", signum);
- return;
- }
+static int child_pid = -1;
+static bool debug = false;
+static bool use_setsid = true;
- kill(use_setsid ? -child_pid : child_pid, signum);
- DEBUG("Forwarded signal %d to children.\n", signum);
-}
/*
* The sigremap signal handler.
@@ -106,7 +83,7 @@ void forward_signal(int signum) {
* https://www.gnu.org/software/libc/manual/html_node/Job-Control-Signals.html
*
*/
-void handle_signal(int signum) {
+static void handle_signal(int signum) {
DEBUG("Received signal %d.\n", signum);
if (signal_temporary_ignores[signum] == 1) {
@@ -147,7 +124,7 @@ void handle_signal(int signum) {
}
}
-char** parse_command(int argc, char* argv[]) {
+static char** parse_command(int argc, char* argv[]) {
int opt;
struct option long_options[] = {
{ "single", no_argument, NULL, 's' },
@@ -155,6 +132,9 @@ char** parse_command(int argc, char* argv[]) {
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 },
};
+ char *old, *new;
+ int oldsig, newsig;
+
while ((opt = getopt_long(argc, argv, "+:hvVs", long_options, NULL)) != -1) {
switch (opt) {
case 'v':
@@ -173,7 +153,6 @@ char** parse_command(int argc, char* argv[]) {
argc -= optind, argv += optind;
while (argc > 0) {
- char *old, *new;
if ((new = strchr(argv[0], '=')) == NULL)
break;
@@ -181,8 +160,6 @@ char** parse_command(int argc, char* argv[]) {
*new = '\0';
new ++;
- int oldsig, newsig;
-
if ((oldsig = signame(old)) == -1) {
fprintf(stderr, "error: invalid old signal '%s'\n", old);
exit(1);
@@ -213,13 +190,15 @@ char** parse_command(int argc, char* argv[]) {
// On the FreeBSD kernel, ignored signals cannot be waited on by `sigwait` (but
// they can be on Linux). We must provide a dummy handler.
// https://lists.freebsd.org/pipermail/freebsd-ports/2009-October/057340.html
-void dummy(int signum) {
+static void dummy(int signum) {
(void) signum;
}
int main(int argc, char* argv[]) {
char** cmd = parse_command(argc, argv);
sigset_t all_signals;
+ int signum;
+
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);
@@ -292,7 +271,6 @@ int main(int argc, char* argv[]) {
/* parent */
DEBUG("Child spawned with PID %d.\n", child_pid);
for (;;) {
- int signum;
sigwait(&all_signals, &signum);
handle_signal(signum);
}
diff --git a/src/exec/zzz.c b/src/exec/zzz.c
@@ -4,8 +4,6 @@
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
-#include <stdbool.h>
-#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/wait.h>
@@ -21,6 +19,7 @@ static int open_write(const char* path, const char* string) {
}
if (write(fd, string, strlen(string)) == -1) {
print_error("error writing to %s: %s\n", path);
+ close(fd);
return -1;
}
return close(fd);
@@ -28,8 +27,9 @@ static int open_write(const char* path, const char* string) {
int main(int argc, char** argv) {
- int opt;
-
+ int opt;
+ pid_t pid;
+ struct stat st;
const char *new_state = "mem",
*new_disk = NULL;
@@ -81,10 +81,8 @@ int main(int argc, char** argv) {
argc -= optind, argv += optind;
- struct stat st;
if (stat(SV_SUSPEND_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
- pid_t pid;
if ((pid = fork()) == -1) {
print_error("failed to fork for " SV_SUSPEND_EXEC ": %s\n");
return 1;
@@ -108,7 +106,6 @@ int main(int argc, char** argv) {
}
if (stat(SV_RESUME_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
- pid_t pid;
if ((pid = fork()) == -1) {
print_error("failed to fork for " SV_RESUME_EXEC ": %s\n");
return 1;
diff --git a/src/handle_command.c b/src/handle_command.c
@@ -8,180 +8,6 @@
#include <unistd.h>
-#if 0
-int service_handle_command(service_t* s, service_command_t command) {
- bool changed = false;
- char path_buffer[PATH_MAX];
- int fd;
-
- switch (command) {
- case S_STATUS:
- if (s != NULL) {
- response[0] = s;
- return 1;
- }
- for (int i = 0; i < services_size; i++) {
- response[i] = &services[i];
- }
- return services_size;
-
- case S_START:
- if (s == NULL)
- return -ENOSV;
- if (extra > 1) {
- return -EBEXT;
- }
- if (s->state != STATE_INACTIVE)
- return 0;
-
- if (extra == 1) { // pin
- changed = s->restart_manual != S_RESTART;
- s->restart_manual = S_RESTART;
- } else {
- changed = s->restart_manual != S_ONCE;
- s->restart_manual = S_ONCE;
- }
- if (extra == 0 || extra == 1)
- service_start(s, &changed);
-
- if (!changed)
- return 0;
-
- s->status_change = time(NULL);
- service_update_status(s);
-
- response[0] = s;
- return 1;
-
- case S_STOP:
- if (s == NULL)
- return -ENOSV;
- if (extra > 1) {
- return -EBEXT;
- }
- if (s->state == STATE_INACTIVE)
- return 0;
- if (extra == 1) { // pin
- changed = s->restart_manual != S_FORCE_DOWN;
- s->restart_manual = S_FORCE_DOWN;
- } else {
- changed = s->restart_manual != S_DOWN;
- s->restart_manual = S_DOWN;
- }
- if (extra == 0 || extra == 1)
- service_stop(s, &changed);
-
- if (!changed)
- return 0;
-
- s->status_change = time(NULL);
- service_update_status(s);
-
- response[0] = s;
- return 1;
-
- case S_SEND:
- if (s == NULL)
- return -ENOSV;
-
- service_kill(s, extra);
- response[0] = s;
- return 1;
-
- case S_PAUSE:
- if (s == NULL)
- return -ENOSV;
-
- if (s->state == STATE_INACTIVE || s->paused)
- return 0;
-
- s->paused = true;
- service_kill(s, SIGSTOP);
-
- s->status_change = time(NULL);
- service_update_status(s);
-
- response[0] = s;
- return 1;
-
- case S_RESUME:
- if (s == NULL)
- return -ENOSV;
-
- if (s->state == STATE_INACTIVE || s->state == STATE_DEAD || s->pid == 0 || !s->paused)
- return 0;
-
- s->paused = false;
- service_kill(s, SIGCONT);
-
- s->status_change = time(NULL);
- service_update_status(s);
-
- response[0] = s;
- return 1;
-
- case S_RESET:
- if (s == NULL)
- return -ENOSV;
-
- if (s->paused) {
- s->paused = false;
- service_kill(s, SIGCONT);
- }
-
- s->fail_count = 0;
- if (s->state == STATE_DEAD)
- s->state = STATE_INACTIVE;
-
- s->status_change = time(NULL);
- service_update_status(s);
-
- response[0] = s;
- return 1;
-
- case S_EXIT:
- daemon_running = false;
- return 0;
-
- case S_SWITCH:
- if (argv == NULL)
- return -ENOSV;
-
- strncpy(runlevel, argv, SV_NAME_MAX);
-
- if (extra == 1) {
- for (int i = 0; i < services_size; i++) {
- services[i].restart_manual = S_DOWN;
- }
- }
-
- return 0;
-
- case S_ENABLE:
- case S_DISABLE:
- if (argv == NULL)
- return -ENOSV;
-
- strcpy(path_buffer, extra == 1 ? "once-" : "up-");
- strcat(path_buffer, runlevel);
-
- if (command == S_ENABLE) {
- if ((fd = openat(s->dir, path_buffer, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1)
- return 0;
- close(fd);
- } else {
- if (remove(path_buffer) == -1)
- return 0;
- }
-
- response[0] = s;
- return 1;
- }
- fprintf(stderr, "warning: handling command: unknown command 0x%2x%2x\n", command, extra);
- return -EBADSV;
-}
-#endif
-
static int runit_signals[] = {
[X_ALARM] = SIGALRM,
[X_HUP] = SIGHUP,
diff --git a/src/handle_exit.c b/src/handle_exit.c
@@ -12,6 +12,7 @@
static void do_finish(service_t* s) {
struct stat st;
+
if (fstatat(s->dir, "finish", &st, 0) != -1 && st.st_mode & S_IXUSR) {
s->state = STATE_FINISHING;
if ((s->pid = fork_dup_cd_exec(s->dir, "./finish", null_fd, null_fd, null_fd)) == -1) {
@@ -31,14 +32,14 @@ static void do_finish(service_t* s) {
void service_handle_exit(service_t* s, bool signaled, int return_code) {
+ struct stat st;
+
s->pid = 0;
if (s->restart_file == S_ONCE)
s->restart_file = S_DOWN;
if (s->restart_manual == S_ONCE)
s->restart_manual = S_DOWN;
- struct stat st;
-
switch (s->state) {
case STATE_SETUP:
service_run(s);
diff --git a/src/parse.c b/src/parse.c
@@ -15,10 +15,10 @@ void parse_param_file(service_t* s, char* args[]) {
int args_size = 0;
int line_size = 0;
char c;
+ bool start = true;
strcpy(args[args_size++], "./run");
- bool start = true;
if ((param_file = openat(s->dir, "params", O_RDONLY)) != -1) {
while (read(param_file, &c, 1) > 0) {
if (start && c == '%') {
@@ -68,9 +68,9 @@ void parse_env_file(char** env) {
/* uid:gid[:gid[:gid]...] */
static int parse_ugid_num(char* str, uid_t* uid, gid_t* gids) {
- int i;
-
+ int i;
char* end;
+
*uid = strtoul(str, &end, 10);
if (*end != ':')
@@ -98,6 +98,7 @@ int parse_ugid(char* str, uid_t* uid, gid_t* gids) {
char* end;
char* groupstr = NULL;
int gid_size = 0;
+ char* next;
if (str[0] == ':')
return parse_ugid_num(str + 1, uid, gids);
@@ -117,7 +118,7 @@ int parse_ugid(char* str, uid_t* uid, gid_t* gids) {
return 1;
}
- char* next = groupstr;
+ next = groupstr;
while (next && gid_size < 60) {
groupstr = next;
diff --git a/src/register.c b/src/register.c
@@ -13,6 +13,7 @@
static int fd_set_flag(int fd, int flags) {
int rc;
+
if ((rc = fcntl(fd, F_GETFL)) == -1)
return -1;
@@ -55,7 +56,13 @@ static void init_supervise(service_t* s) {
}
service_t* service_register(int dir, const char* name, bool is_log_service) {
- service_t* s;
+ service_t* s;
+ struct stat st;
+ bool autostart, autostart_once;
+
+ char up_path[SV_NAME_MAX] = "up-",
+ once_path[SV_NAME_MAX] = "once-";
+
if ((s = service_get(name)) == NULL) {
s = &services[services_size++];
@@ -84,8 +91,6 @@ service_t* service_register(int dir, const char* name, bool is_log_service) {
service_update_status(s);
}
- struct stat st;
-
if (s->is_log_service) {
if (s->log_pipe.read == 0 || s->log_pipe.write == 0)
pipe((int*) &s->log_pipe);
@@ -96,11 +101,6 @@ service_t* service_register(int dir, const char* name, bool is_log_service) {
s->log_service = service_register(s->dir, "log", true);
}
- bool autostart, autostart_once;
-
- char up_path[SV_NAME_MAX] = "up-";
- char once_path[SV_NAME_MAX] = "once-";
-
strcat(up_path, runlevel);
strcat(once_path, runlevel);
diff --git a/src/runit.c b/src/runit.c
@@ -1,112 +0,0 @@
-#include "service.h"
-#include "util.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <string.h>
-#include <sys/file.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-
-static int runit_signals[] = {
- [X_ALARM] = SIGALRM,
- [X_HUP] = SIGHUP,
- [X_INT] = SIGINT,
- [X_QUIT] = SIGQUIT,
- [X_USR1] = SIGUSR1,
- [X_USR2] = SIGUSR2,
-};
-
-void service_update_status(service_t* s) {
- int fd;
- if ((fd = openat(s->dir, "supervise/status", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot open supervise/status: %s\n");
- return;
- }
-
- service_serial_t stat_runit;
- service_encode(s, &stat_runit);
-
- if (write(fd, &stat_runit, sizeof(stat_runit)) == -1) {
- print_error("cannot write to supervise/status: %s\n");
- return;
- }
-
- close(fd);
-
- if ((fd = openat(s->dir, "supervise/stat", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot create supervise/stat: %s\n");
- return;
- }
-
- const char* stat_human = service_status_name(s);
- if (write(fd, stat_human, strlen(stat_human)) == -1) {
- print_error("cannot write to supervise/stat: %s\n");
- return;
- }
-
- close(fd);
-
- if ((fd = openat(s->dir, "supervise/pid", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
- print_error("cannot create supervise/stat: %s\n");
- return;
- }
-
- dprintf(fd, "%d", s->pid);
-
- close(fd);
-}
-
-#if 0
-void service_handle_command_runit(service_t* s, sv_command_runit_t command) {
-# if SV_RUNIT_COMPAT != 0
- switch (command) {
- case R_DOWN:
- case R_TERM:
- s->restart_manual = S_FORCE_DOWN;
- service_stop(s, NULL);
- break;
- case R_UP:
- s->restart_manual = S_RESTART;
- service_start(s, NULL);
- break;
- case R_ONCE:
- s->restart_manual = S_ONCE;
- service_start(s, NULL);
- break;
- case R_KILL:
- s->restart_manual = S_FORCE_DOWN;
- service_kill(s, SIGKILL);
- break;
- case R_PAUSE:
- if (!s->paused) {
- s->paused = true;
- service_kill(s, SIGSTOP);
- }
- break;
- case R_CONT:
- if (s->paused) {
- s->paused = false;
- service_kill(s, SIGCONT);
- }
- break;
- case R_ALARM:
- case R_HUP:
- case R_INT:
- case R_QUIT:
- case R_USR1:
- case R_USR2:
- service_kill(s, runit_signals[command]);
- break;
- case R_EXIT:
- // ignored
- return;
- }
-
- s->status_change = time(NULL);
- service_update_status(s);
-# endif
-}
-#endif
diff --git a/src/service.c b/src/service.c
@@ -33,6 +33,7 @@ service_t* service_get(const char* name) {
int service_pattern(const char* name, service_t** dest, int dest_max) {
int size = 0;
+
for (int i = 0; i < services_size && size < dest_max; i++) {
if (pattern_test(name, services[i].name))
dest[size++] = &services[i];
@@ -43,15 +44,16 @@ int service_pattern(const char* name, service_t** dest, int dest_max) {
int service_refresh_directory(void) {
DIR* dp;
struct dirent* ep;
+ struct stat st;
+ service_t* s;
if ((dp = opendir(service_dir_path)) == NULL) {
print_error("error: cannot open service directory: %s\n");
return -1;
}
- struct stat st;
for (int i = 0; i < services_size; i++) {
- service_t* s = &services[i];
+ s = &services[i];
if (fstat(s->dir, &st) == -1 || !S_ISDIR(st.st_mode)) {
if (s->pid)
kill(s->pid, SIGKILL);
@@ -87,6 +89,7 @@ int service_refresh_directory(void) {
static bool is_dependency(service_t* d) {
service_t* s;
+
for (int i = 0; i < depends_size; i++) {
s = depends[i][0];
if (depends[i][1] == d && (s->state != STATE_INACTIVE || service_need_restart(s)))
@@ -98,6 +101,7 @@ static bool is_dependency(service_t* d) {
bool service_need_restart(service_t* s) {
if (s->restart_manual == S_FORCE_DOWN)
return is_dependency(s);
+
return s->restart_file == S_ONCE ||
s->restart_file == S_RESTART ||
s->restart_manual == S_ONCE ||
diff --git a/src/signame.c b/src/signame.c
@@ -176,9 +176,9 @@ static signal_name_t signal_names[] = {
int signame(char const* name) {
char* endptr;
int signum;
- if ((signum = strtol(name, &endptr, 10)) && endptr == strchr(name, '\0')) {
+
+ if ((signum = strtol(name, &endptr, 10)) && endptr == strchr(name, '\0'))
return signum;
- }
// startswith SIG, remove that so -SIGKILL == -KILL
if (strncmp(name, "SIG", 3) == 0) {
diff --git a/src/stage.c b/src/stage.c
@@ -17,12 +17,14 @@ static const char* stage_exec[] = {
void service_stage(int stage) {
+ int pid, ttyfd, exitstat, sig = 0;
+ sigset_t ss;
+ struct sigaction sigact = { 0 };
+
+ // stage = 0 | 2
if (stage != 0 && stage != 2)
return;
- // stage = 0 | 2
- int pid, ttyfd, exitstat;
- sigset_t ss;
while ((pid = fork()) == -1) {
print_error("error: unable to fork for stage1: %s\n");
sleep(5);
@@ -44,8 +46,7 @@ void service_stage(int stage) {
sigblock_all(true);
- struct sigaction sigact = { 0 };
- sigact.sa_handler = SIG_DFL;
+ sigact.sa_handler = SIG_DFL;
sigaction(SIGCHLD, &sigact, NULL);
sigaction(SIGINT, &sigact, NULL);
@@ -58,8 +59,6 @@ void service_stage(int stage) {
_exit(1);
}
- int sig = 0;
-
sigemptyset(&ss);
sigaddset(&ss, SIGCHLD);
sigaddset(&ss, SIGCONT);
diff --git a/src/start.c b/src/start.c
@@ -39,9 +39,10 @@ static void set_pipes(service_t* s) {
dup2(null_fd, STDERR_FILENO);
} else {
char service_log[PATH_MAX];
+ int log_fd;
+
snprintf(service_log, PATH_MAX, "%s/%s-%s.log", SV_LOG_DIR, s->name, runlevel);
- int log_fd;
if ((log_fd = open(service_log, O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1)
log_fd = null_fd;
@@ -52,35 +53,38 @@ static void set_pipes(service_t* s) {
}
static void set_user(void) {
- char buffer[SV_USER_BUFFER];
- int user_file;
- if ((user_file = open("user", O_RDONLY)) != -1) {
- ssize_t n;
- if ((n = read(user_file, buffer, sizeof(buffer))) == -1) {
- print_error("error: failed reading ./user: %s\n");
- close(user_file);
- return;
- }
- buffer[n] = '\0';
-
- uid_t uid;
- gid_t gids[SV_USER_GROUP_MAX];
- if ((n = parse_ugid(buffer, &uid, gids)) <= 0) {
- fprintf(stderr, "warn: malformatted user file\n");
- close(user_file);
- return;
- }
+ char buffer[SV_USER_BUFFER];
+ int user_file;
+ ssize_t n;
+ uid_t uid;
+ gid_t gids[SV_USER_GROUP_MAX];
- setgroups(n, gids);
- setgid(gids[0]);
- setuid(uid);
+ if ((user_file = open("user", O_RDONLY)) == -1)
+ return;
+
+ if ((n = read(user_file, buffer, sizeof(buffer))) == -1) {
+ print_error("error: failed reading ./user: %s\n");
+ close(user_file);
+ return;
+ }
+ buffer[n] = '\0';
+ if ((n = parse_ugid(buffer, &uid, gids)) <= 0) {
+ fprintf(stderr, "warn: malformatted user file\n");
close(user_file);
+ return;
}
+
+ setgroups(n, gids);
+ setgid(gids[0]);
+ setuid(uid);
+
+ close(user_file);
}
void service_run(service_t* s) {
struct stat st;
+
if (fstatat(s->dir, "run", &st, 0) != -1 && st.st_mode & S_IXUSR) {
s->state = STATE_ACTIVE_FOREGROUND;
} else if (fstatat(s->dir, "start", &st, 0) != -1 && st.st_mode & S_IXUSR) {
@@ -132,6 +136,8 @@ void service_run(service_t* s) {
}
void service_start(service_t* s) {
+ struct stat st;
+
if (s->state != STATE_INACTIVE)
return;
@@ -141,7 +147,6 @@ void service_start(service_t* s) {
service_start(depends[i][1]);
}
- struct stat st;
if (fstatat(s->dir, "setup", &st, 0) != -1 && st.st_mode & S_IXUSR) {
s->state = STATE_SETUP;
if ((s->pid = fork_dup_cd_exec(s->dir, "./setup", null_fd, null_fd, null_fd)) == -1) {
diff --git a/src/status.c b/src/status.c
@@ -0,0 +1,53 @@
+#include "service.h"
+#include "util.h"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <string.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+
+void service_update_status(service_t* s) {
+ int fd;
+ const char* stat_human;
+ service_serial_t stat_runit;
+
+ if ((fd = openat(s->dir, "supervise/status", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
+ print_error("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");
+ return;
+ }
+
+ close(fd);
+
+ if ((fd = openat(s->dir, "supervise/stat", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
+ print_error("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");
+ return;
+ }
+
+ close(fd);
+
+ if ((fd = openat(s->dir, "supervise/pid", O_CREAT | O_WRONLY | O_TRUNC, 0644)) == -1) {
+ print_error("cannot create supervise/stat: %s\n");
+ return;
+ }
+
+ dprintf(fd, "%d", s->pid);
+
+ close(fd);
+}
diff --git a/src/supervise.c b/src/supervise.c
@@ -46,6 +46,7 @@ static void signal_child(int unused) {
static void check_services(void) {
service_t* s;
+
for (int i = 0; i < services_size; i++) {
s = &services[i];
if (s->state == STATE_DEAD)
@@ -71,6 +72,7 @@ static void control_sockets(void) {
service_t* s;
char cmd, chr;
bool read_signo = false;
+
for (int i = 0; i < services_size; i++) {
s = &services[i];
while (read(s->control, &chr, 1) == 1) {
@@ -90,7 +92,11 @@ static void control_sockets(void) {
int service_supervise(const char* service_dir_, const char* runlevel_) {
struct sigaction sigact = { 0 };
- sigact.sa_handler = signal_child;
+ service_t* s;
+ time_t start;
+ int running;
+
+ sigact.sa_handler = signal_child;
sigaction(SIGCHLD, &sigact, NULL);
sigact.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sigact, NULL);
@@ -102,8 +108,6 @@ int service_supervise(const char* service_dir_, const char* runlevel_) {
return 1;
}
- // setenv("SERVICE_RUNLEVEL", runlevel, true);
-
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
print_error("error: cannot open /dev/null: %s\n");
null_fd = 1;
@@ -122,14 +126,12 @@ int service_supervise(const char* service_dir_, const char* runlevel_) {
printf(":: terminating\n");
- service_t* s;
for (int i = 0; i < services_size; i++) {
s = &services[i];
service_stop(s);
}
- time_t start = time(NULL);
- int running;
+ start = time(NULL);
do {
sleep(1); // sleep for one second
running = 0;
diff --git a/src/util.c b/src/util.c
@@ -15,6 +15,7 @@ ssize_t dgetline(int fd, char* line, size_t line_buffer) {
ssize_t line_size = 0;
ssize_t rc;
char c;
+
while (line_size < (ssize_t) line_buffer - 1 && (rc = read(fd, &c, 1)) == 1) {
if (c == '\r')
continue;
@@ -48,8 +49,8 @@ ssize_t writestr(int fd, const char* str) {
unsigned int stat_mode(const char* format, ...) {
char path[PATH_MAX];
struct stat st;
+ va_list args;
- va_list args;
va_start(args, format);
vsnprintf(path, PATH_MAX, format, args);
va_end(args);
@@ -62,6 +63,7 @@ unsigned int stat_mode(const char* format, ...) {
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");
return -1;
@@ -81,6 +83,7 @@ int fork_dup_cd_exec(int dir, const char* path, int fd0, int fd1, int fd2) {
int reclaim_console(void) {
int ttyfd;
+
if ((ttyfd = open("/dev/console", O_RDWR)) == -1)
return -1;
@@ -95,6 +98,7 @@ int reclaim_console(void) {
void sigblock_all(int unblock) {
sigset_t ss;
+
sigemptyset(&ss);
sigfillset(&ss);
/* sigaddset(&ss, SIGALRM);
@@ -111,9 +115,25 @@ void sigblock_all(int unblock) {
long parse_long(const char* str, const char* name) {
char* end;
long l = strtol(str, &end, 10);
+
if (*end != '\0') {
fprintf(stderr, "error: invalid %s '%s'\n", name, optarg);
exit(1);
}
return l;
}
+
+char* progname(char* path) {
+ char* match;
+
+ for (;;) {
+ if ((match = strrchr(path, '/')) == NULL)
+ return path;
+
+ if (match[1] != '\0')
+ return match + 1;
+
+ *match = '\0';
+ }
+ return path;
+}
diff --git a/src/wtmp.c b/src/wtmp.c
@@ -10,13 +10,13 @@
void write_wtmp(int boot) {
int fd;
- if ((fd = open(OUR_WTMP, O_WRONLY | O_APPEND)) < 0)
- return;
-
struct utmp utmp = { 0 };
struct utsname uname_buf;
struct timeval tv;
+ if ((fd = open(OUR_WTMP, O_WRONLY | O_APPEND)) < 0)
+ return;
+
gettimeofday(&tv, 0);
utmp.ut_tv.tv_sec = tv.tv_sec;
utmp.ut_tv.tv_usec = tv.tv_usec;