commit d3507d1843999cbff35d2d0b9aae61dca14dcff2
parent c83032aecece458b8cfa69107e0a19c0396dcca3
Author: Friedel Schön <[email protected]>
Date: Mon, 8 May 2023 13:43:08 +0200
consistent prints
Diffstat:
16 files changed, 217 insertions(+), 212 deletions(-)
diff --git a/include/message.h b/include/message.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#define FISS_VERSION "0.1.1"
+
+#define FISS_VERSION_STRING "fiss version v" FISS_VERSION ""
+
+typedef enum prog {
+ PROG_FINIT,
+ PROG_FSVC,
+ PROG_FSVS,
+ PROG_HALT,
+ PROG_POWEROFF,
+ PROG_REBOOT,
+ PROG_SEEDRNG,
+ PROG_SIGREMAP,
+ PROG_VLOGGER,
+ PROG_ZZZ
+} prog_t;
+
+void print_usage_exit(prog_t prog, int status) __attribute__((noreturn));
+void print_version_exit() __attribute__((noreturn));
+\ No newline at end of file
diff --git a/include/util.h b/include/util.h
@@ -2,13 +2,11 @@
#include <stdio.h>
-#define streq(a, b) (!strcmp((a), (b)))
-#define stringify(s) #s
+#define streq(a, b) (!strcmp((a), (b)))
+#define stringify(s) #s
#define static_stringify(s) stringify(s)
-#define print_error(msg, ...) (fprintf(stderr, "error: " msg ": %s\n", ##__VA_ARGS__, strerror(errno)))
-#define print_warning(msg, ...) (fprintf(stderr, "warning: " msg ": %s\n", ##__VA_ARGS__, strerror(errno)))
-
+#define print_error(msg, ...) (fprintf(stderr, msg, ##__VA_ARGS__, strerror(errno)))
typedef struct {
int read;
diff --git a/src/command.c b/src/command.c
@@ -23,7 +23,7 @@ int service_command(char command, char extra, const char* service, service_t* re
int sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sockfd == -1) {
- print_error("cannot connect to socket");
+ print_error("error: cannot connect to socket: %s\n");
exit(1);
}
@@ -34,7 +34,7 @@ int service_command(char command, char extra, const char* service, service_t* re
int ret = connect(sockfd, (struct sockaddr*) &addr, sizeof(addr));
if (ret == -1) {
- print_error("cannot connect to %s", addr.sun_path);
+ print_error("error: cannot connect to %s: %s\n", addr.sun_path);
exit(EXIT_FAILURE);
}
diff --git a/src/exec/finit.c b/src/exec/finit.c
@@ -1,4 +1,5 @@
#include "config.h"
+#include "message.h"
#include "service.h"
#include "util.h"
@@ -16,16 +17,15 @@ void sigblock_all(bool unblock);
int handle_initctl(int argc, const char** argv) {
if (argc != 2 || argv[1][1] != '\0' || (argv[1][0] != '0' && argv[1][0] != '6')) {
- printf("Usage: %s <0|6>\n", argv[0]);
- return 1;
+ print_usage_exit(PROG_FINIT, 1);
}
if (getuid() != 0) {
- printf("can only be run as root...\n");
+ fprintf(stderr, "error: can only be run as root...\n");
return 1;
}
int sig = argv[1][0] == '0' ? SIGTERM : SIGINT;
if (kill(1, sig) == -1) {
- print_error("unable to kill init");
+ print_error("error: unable to kill init: %s\n");
return 1;
}
return 0;
@@ -39,12 +39,12 @@ static bool do_reboot;
static void signal_interrupt(int signum) {
daemon_running = false;
- do_reboot = signum == SIGINT;
+ do_reboot = signum == SIGINT;
}
int main(int argc, const char** argv) {
- int ttyfd;
+ int ttyfd;
sigset_t ss;
if (getpid() != 1) {
@@ -69,11 +69,11 @@ int main(int argc, const char** argv) {
handle_stage1();
- if (daemon_running) { // stage1 succeed
+ if (daemon_running) { // stage1 succeed
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);
diff --git a/src/exec/fsvs.c b/src/exec/fsvs.c
@@ -1,6 +1,7 @@
// daemon manager
#include "config.h"
+#include "message.h"
#include "service.h"
#include "util.h"
@@ -14,30 +15,7 @@
#define SV_STOP_TIMEOUT_STR static_stringify(SV_STOP_TIMEOUT)
-static const char HELP_MESSAGE[] =
- "Usage:\n"
- " %s [options] <runlevel>\n"
- "\n"
- "Options:\n"
- " -h, --help ........ prints this and exits\n"
- " -v, --verbose ..... print more info\n"
- " -V, --version ..... prints current version and exits\n"
- " -f, --force ....... forces socket\n"
- "\n";
-
-static const char VERSION_MESSAGE[] =
- "FISS v" SV_VERSION "\n"
- "\n"
- "Features:\n"
- " service directory: " SV_SERVICE_DIR "\n"
- " service control socket: " SV_CONTROL_SOCKET "\n"
- " max. services: " MAX_SERVICE_STR "\n"
- " max. dependencies: " SV_DEPENDS_MAX_STR "\n"
- " stop timeout: " SV_STOP_TIMEOUT_STR "sec\n"
- "\n";
-
static const struct option long_options[] = {
- { "help", no_argument, 0, 'h' },
{ "verbose", no_argument, 0, 'v' },
{ "version", no_argument, 0, 'V' },
{ "force", no_argument, 0, 'f' },
@@ -54,18 +32,13 @@ int main(int argc, char** argv) {
bool force_socket = false;
int c;
- while ((c = getopt_long(argc, argv, ":hvVf", long_options, NULL)) > 0) {
+ while ((c = getopt_long(argc, argv, ":vVf", long_options, NULL)) > 0) {
switch (c) {
- case 'h':
- printf(VERSION_MESSAGE, "<runlevel>");
- printf(HELP_MESSAGE, argv[0]);
- return 0;
case 'v':
verbose = true;
break;
case 'V':
- printf(VERSION_MESSAGE, "<runlevel>");
- return 0;
+ print_version_exit();
case 'f':
force_socket = true;
break;
@@ -74,7 +47,7 @@ int main(int argc, char** argv) {
fprintf(stderr, "error: invalid option -%c\n", optopt);
else
fprintf(stderr, "error: invalid option %s\n", argv[optind - 1]);
- return 1;
+ print_usage_exit(PROG_FSVC, 1);
}
}
@@ -82,13 +55,13 @@ int main(int argc, char** argv) {
argc -= optind;
if (argc == 0) {
fprintf(stderr, "error: missing <service-dir>\n");
- return 1;
+ print_usage_exit(PROG_FSVC, 1);
} else if (argc == 1) {
fprintf(stderr, "error: missing <runlevel>\n");
- return 1;
+ print_usage_exit(PROG_FSVC, 1);
} else if (argc > 2) {
fprintf(stderr, "error: too many arguments\n");
- return 1;
+ print_usage_exit(PROG_FSVC, 1);
}
signal(SIGINT, signal_interrupt);
diff --git a/src/exec/sigremap.c b/src/exec/sigremap.c
@@ -1,24 +1,24 @@
/* Copyright (c) 2015 Yelp, Inc.
- With modification 2023 Friedel Schon
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
- */
+ With modification 2023 Friedel Schon
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
/*
* sigremap is a simple wrapper program designed to run as PID 1 and pass
@@ -30,7 +30,9 @@
* To get debug output on stderr, run with '-v'.
*/
+#include "message.h"
#include "signame.h"
+#include "util.h"
#include <assert.h>
#include <errno.h>
@@ -43,13 +45,10 @@
#include <sys/wait.h>
#include <unistd.h>
-#define PRINTERR(...) \
- fprintf(stderr, "[sigremap] " __VA_ARGS__)
-
-#define DEBUG(...) \
- do { \
- if (debug) \
- PRINTERR(__VA_ARGS__); \
+#define DEBUG(...) \
+ do { \
+ if (debug) \
+ fprintf(stderr, __VA_ARGS__); \
} while (0)
#define set_signal_undefined(old, new) \
@@ -68,8 +67,8 @@ int signal_remap[MAXSIG + 1] = { [0 ... MAXSIG] = -1 };
// One-time ignores due to TTY quirks. 0 = no skip, 1 = skip the next-received signal.
bool signal_temporary_ignores[MAXSIG + 1] = { [0 ... MAXSIG] = false };
-pid_t child_pid = -1;
-bool debug = false;
+pid_t child_pid = -1;
+bool debug = false;
bool use_setsid = true;
void forward_signal(int signum) {
@@ -114,7 +113,7 @@ void handle_signal(int signum) {
DEBUG("Ignoring tty hand-off signal %d.\n", signum);
signal_temporary_ignores[signum] = 0;
} else if (signum == SIGCHLD) {
- int status, exit_status;
+ int status, exit_status;
pid_t killed_pid;
while ((killed_pid = waitpid(-1, &status, WNOHANG)) > 0) {
if (WIFEXITED(status)) {
@@ -127,7 +126,7 @@ void handle_signal(int signum) {
}
if (killed_pid == child_pid) {
- kill(use_setsid ? -child_pid : child_pid, SIGTERM); // send SIGTERM to any remaining children
+ kill(use_setsid ? -child_pid : child_pid, SIGTERM); // send SIGTERM to any remaining children
DEBUG("Child exited with status %d. Goodbye.\n", exit_status);
exit(exit_status);
}
@@ -148,54 +147,26 @@ void handle_signal(int signum) {
}
}
-void print_help(char* argv[]) {
- fprintf(stderr,
- "Usage: %s [option] [old-signal=new-signal] command [[arg] ...]\n"
- "\n"
- "sigremap is a simple process supervisor that forwards signals to children.\n"
- "It is designed to run as PID1 in minimal container environments.\n"
- "\n"
- "Optional arguments:\n"
- " -s, --single Run in single-child mode.\n"
- " In this mode, signals are only proxied to the\n"
- " direct child and not any of its descendants.\n"
- " -r, --remap s:r remap received signal s to new signal r before proxying.\n"
- " To ignore (not proxy) a signal, remap it to 0.\n"
- " This option can be specified multiple times.\n"
- " -v, --verbose Print debugging information to stderr.\n"
- " -h, --help Print this help message and exit.\n"
- " -V, --version Print the current version and exit.\n"
- "\n"
- "Full help is available online at https://github.com/Yelp/dumb-init\n",
- argv[0]);
-}
-
-
char** parse_command(int argc, char* argv[]) {
- int opt;
+ int opt;
struct option long_options[] = {
- { "help", no_argument, NULL, 'h' },
{ "single", no_argument, NULL, 's' },
{ "verbose", no_argument, NULL, 'v' },
{ "version", no_argument, NULL, 'V' },
{ NULL, 0, NULL, 0 },
};
- while ((opt = getopt_long(argc, argv, "+hvVs", long_options, NULL)) != -1) {
+ while ((opt = getopt_long(argc, argv, "+:hvVs", long_options, NULL)) != -1) {
switch (opt) {
- case 'h':
- print_help(argv);
- exit(0);
case 'v':
debug = true;
break;
case 'V':
- // fprintf(stderr, "sigremap v%.*s", VERSION_len, VERSION);
- exit(0);
+ print_version_exit();
case 'c':
use_setsid = false;
break;
default:
- exit(1);
+ print_usage_exit(PROG_SIGREMAP, 1);
}
}
@@ -206,7 +177,7 @@ char** parse_command(int argc, char* argv[]) {
if ((new = strchr(argv[0], '=')) == NULL)
break;
- old = argv[0];
+ old = argv[0];
*new = '\0';
new ++;
@@ -226,12 +197,7 @@ char** parse_command(int argc, char* argv[]) {
}
if (argc < 1) {
- fprintf(
- stderr,
- "Usage: %s [option] program [args]\n"
- "Try %s --help for full usage.\n",
- argv[0], argv[0]);
- exit(1);
+ print_usage_exit(PROG_SIGREMAP, 1);
}
if (use_setsid) {
@@ -252,7 +218,7 @@ void dummy(int signum) {
}
int main(int argc, char* argv[]) {
- char** cmd = parse_command(argc, argv);
+ char** cmd = parse_command(argc, argv);
sigset_t all_signals;
sigfillset(&all_signals);
sigprocmask(SIG_BLOCK, &all_signals, NULL);
@@ -271,9 +237,9 @@ int main(int argc, char* argv[]) {
if (use_setsid) {
if (ioctl(STDIN_FILENO, TIOCNOTTY) == -1) {
DEBUG(
- "Unable to detach from controlling tty (errno=%d %s).\n",
- errno,
- strerror(errno));
+ "Unable to detach from controlling tty (errno=%d %s).\n",
+ errno,
+ strerror(errno));
} else {
/*
* When the session leader detaches from its controlling tty via
@@ -294,32 +260,29 @@ int main(int argc, char* argv[]) {
child_pid = fork();
if (child_pid < 0) {
- PRINTERR("Unable to fork. Exiting.\n");
+ print_error("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) {
- PRINTERR(
- "Unable to setsid (errno=%d %s). Exiting.\n",
- errno,
- strerror(errno));
+ print_error("error: unable to setsid: %s\n");
exit(1);
}
if (ioctl(STDIN_FILENO, TIOCSCTTY, 0) == -1) {
DEBUG(
- "Unable to attach to controlling tty (errno=%d %s).\n",
- errno,
- strerror(errno));
+ "Unable to attach to controlling tty (errno=%d %s).\n",
+ errno,
+ strerror(errno));
}
DEBUG("setsid complete.\n");
}
execvp(cmd[0], cmd);
// if this point is reached, exec failed, so we should exit nonzero
- PRINTERR("%s: %s\n", cmd[0], strerror(errno));
+ print_error("error: unable to execute %s: %s\n", cmd[0]);
_exit(2);
}
diff --git a/src/exec/vlogger.c b/src/exec/vlogger.c
@@ -1,3 +1,4 @@
+#include "message.h"
#include "util.h"
#include <errno.h>
@@ -110,7 +111,7 @@ int main(int argc, char* argv[]) {
switch (c) {
case 'f':
if (freopen(optarg, "r", stdin) == NULL) {
- fprintf(stderr, "vlogger: %s: %s\n", optarg, strerror(errno));
+ print_error("error: unable to reopen %s: %s\n", optarg);
return 1;
}
break;
@@ -130,8 +131,7 @@ int main(int argc, char* argv[]) {
tag = optarg;
break;
default:
- fprintf(stderr, "usage: vlogger [-isS] [-f file] [-p pri] [-t tag] [message ...]\n");
- exit(1);
+ print_usage_exit(PROG_VLOGGER, 1);
}
argc -= optind;
argv += optind;
@@ -151,7 +151,7 @@ int main(int argc, char* argv[]) {
sfacility = ident->name;
}
execl("/etc/vlogger", argv0, tag ?: "", slevel, sfacility, NULL);
- fprintf(stderr, "vlogger: exec: %s\n", strerror(errno));
+ print_error("error: unable to exec /etc/vlogger: %s\n");
exit(1);
}
diff --git a/src/exec/zzz.c b/src/exec/zzz.c
@@ -67,11 +67,11 @@ int main(int argc, char** argv) {
if (stat(SV_SUSPEND_EXEC, &st) == 0 && st.st_mode & S_IXUSR) {
pid_t pid;
if ((pid = fork()) == -1) {
- fprintf(stderr, "failed to fork for " SV_SUSPEND_EXEC ": %s\n", strerror(errno));
+ print_error("failed to fork for " SV_SUSPEND_EXEC ": %s\n");
return 1;
} else if (pid == 0) { // child
execl(SV_SUSPEND_EXEC, SV_SUSPEND_EXEC, NULL);
- fprintf(stderr, "failed to execute " SV_SUSPEND_EXEC ": %s\n", strerror(errno));
+ print_error("failed to execute " SV_SUSPEND_EXEC ": %s\n");
_exit(1);
}
@@ -80,22 +80,22 @@ int main(int argc, char** argv) {
if (new_disk) {
if ((sys_disk = open("/sys/power/disk", O_WRONLY | O_TRUNC)) == -1) {
- fprintf(stderr, "cannot open /sys/power/disk: %s\n", strerror(errno));
+ print_error("cannot open /sys/power/disk: %s\n");
return 1;
}
if (write(sys_disk, new_disk, strlen(new_disk)) == -1)
- fprintf(stderr, "error writing to /sys/power/disk: %s\n", strerror(errno));
+ print_error("error writing to /sys/power/disk: %s\n");
close(sys_disk);
}
if (new_state) {
if ((sys_state = open("/sys/power/state", O_WRONLY | O_TRUNC)) == -1) {
- fprintf(stderr, "cannot open /sys/power/state: %s\n", strerror(errno));
+ print_error("cannot open /sys/power/state: %s\n");
return 1;
}
if (write(sys_state, new_state, strlen(new_state)) == -1)
- fprintf(stderr, "error writing to /sys/power/state: %s\n", strerror(errno));
+ print_error("error writing to /sys/power/state: %s\n");
close(sys_state);
} else {
@@ -105,11 +105,11 @@ 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) {
- fprintf(stderr, "failed to fork for " SV_RESUME_EXEC ": %s\n", strerror(errno));
+ print_error("failed to fork for " SV_RESUME_EXEC ": %s\n");
return 1;
} else if (pid == 0) { // child
execl(SV_RESUME_EXEC, SV_RESUME_EXEC, NULL);
- fprintf(stderr, "failed to execute " SV_RESUME_EXEC ": %s\n", strerror(errno));
+ print_error("failed to execute " SV_RESUME_EXEC ": %s\n");
_exit(1);
}
diff --git a/src/message.c b/src/message.c
@@ -0,0 +1,50 @@
+#include "message.h"
+
+#include <libgen.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static const char* prog_usage[] = {
+ [PROG_FINIT] = "init <0|6>",
+ [PROG_FSVC] = "fsvc <command> [-v --verbose] [-V --version] [-r --runlevel <level>] [-s --service-dir <path>]\n"
+ " fsvc start [-p --pin] <service>\n"
+ " fsvc stop [-p --pin] <service>\n"
+ " fsvc enable [-o --once] <service>\n"
+ " fsvc disable [-o --once] <service>\n"
+ " fsvc kill <service> <signal|signum>\n"
+ " fsvc status [-c --check] <service>\n"
+ " fsvc pause <service>\n"
+ " fsvc resume <service>\n"
+ " fsvc switch [-f --reset] <runlevel>",
+ [PROG_FSVS] = "fsvs [-V --version] [-v --verbose] [-f --force] <service-dir> <runlevel>",
+ [PROG_HALT] = "halt [-n] [-f] [-d] [-w] [-B]",
+ [PROG_POWEROFF] = "poweroff [-n] [-f] [-d] [-w] [-B]",
+ [PROG_REBOOT] = "reboot [-n] [-f] [-d] [-w] [-B]",
+ [PROG_SEEDRNG] = "seedrng",
+ [PROG_SIGREMAP] = "sigremap [-s --single] [-v --verbose] [-V --version] <old-signal=new-signal...> <command> [args...]",
+ [PROG_VLOGGER] = "vlogger [-isS] [-f file] [-p pri] [-t tag] [message ...]",
+ [PROG_ZZZ] = "zzz [-n --noop] [-S --freeze] [-z --suspend] [-Z --hibernate] [-R --reboot] [-H --hybrid]"
+};
+
+static const char* prog_manual[] = {
+ [PROG_FINIT] = "finit 8",
+ [PROG_FSVC] = "fsvc 8",
+ [PROG_FSVS] = "fsvs 8",
+ [PROG_HALT] = "halt 8",
+ [PROG_POWEROFF] = "poweroff 8",
+ [PROG_REBOOT] = "reboot 8",
+ [PROG_SEEDRNG] = "seedrng 8",
+ [PROG_SIGREMAP] = "sigremap 1",
+ [PROG_VLOGGER] = "vlogger 8",
+ [PROG_ZZZ] = "zzz 8"
+};
+
+void print_usage_exit(prog_t prog, int status) {
+ fprintf(status ? stderr : stdout, "Usage: %s\n\nCheck manual '%s' for more information.\n", prog_usage[prog], prog_manual[prog]);
+ exit(status);
+}
+
+void print_version_exit() {
+ printf(FISS_VERSION_STRING);
+ exit(0);
+}
+\ No newline at end of file
diff --git a/src/restart.c b/src/restart.c
@@ -11,9 +11,9 @@
/*void stat_mode(const char* path_format, ...) __attribute__((format(printf, 1, 0))) {
- va_list va;
- va_start(va, path_format);
- vsnprintf(char *, unsigned long, const char *, struct __va_list_tag *)
+ va_list va;
+ va_start(va, path_format);
+ vsnprintf(char *, unsigned long, const char *, struct __va_list_tag *)
}*/
static void do_finish(service_t* s) {
@@ -23,19 +23,19 @@ static void do_finish(service_t* s) {
if (stat_mode("%s/%s/finish", service_dir, s->name) & S_IEXEC) {
s->state = STATE_FINISHING;
if ((s->pid = fork()) == -1) {
- print_error("cannot fork process");
+ print_error("error: cannot fork process: %s\n");
} else if (s->pid == 0) {
dup2(null_fd, STDIN_FILENO);
dup2(null_fd, STDOUT_FILENO);
dup2(null_fd, STDERR_FILENO);
execl(path_buffer, path_buffer, NULL);
- print_error("cannot execute finish process");
+ print_error("error: cannot execute finish process: %s\n");
_exit(1);
}
} else if (s->fail_count == SV_FAIL_MAX) {
s->state = STATE_DEAD;
- printf(":: %s died\n", s->name);
+ printf("%s died\n", s->name);
} else {
s->state = STATE_INACTIVE;
}
@@ -44,7 +44,7 @@ static void do_finish(service_t* s) {
void service_check_state(service_t* s, bool signaled, int return_code) {
s->status_change = time(NULL);
- s->pid = 0;
+ s->pid = 0;
if (s->restart_file == S_ONCE)
s->restart_file = S_DOWN;
if (s->restart_manual == S_ONCE)
@@ -60,7 +60,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) {
s->return_code = return_code;
s->fail_count++;
- printf(":: %s killed thought signal %d\n", s->name, s->return_code);
+ printf("%s killed thought signal %d\n", s->name, s->return_code);
} else {
s->last_exit = EXIT_NORMAL;
s->return_code = return_code;
@@ -69,7 +69,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) {
else
s->fail_count = 0;
- printf(":: %s exited with code %d\n", s->name, s->return_code);
+ printf("%s exited with code %d\n", s->name, s->return_code);
}
do_finish(s);
@@ -85,7 +85,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) {
case STATE_FINISHING:
if (s->fail_count == SV_FAIL_MAX) {
s->state = STATE_DEAD;
- printf(":: %s died\n", s->name);
+ printf("%s died\n", s->name);
} else {
s->state = STATE_INACTIVE;
}
@@ -95,7 +95,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) {
if (stat_mode("%s/%s/stop", service_dir, s->name) & S_IXUSR) {
s->state = STATE_ACTIVE_BACKGROUND;
} else if (stat_mode("%s/%s/stop", service_dir, s->name) & S_IRUSR) {
- s->pid = parse_pid_file(s);
+ s->pid = parse_pid_file(s);
s->state = STATE_ACTIVE_PID;
} else {
do_finish(s);
@@ -105,7 +105,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) {
s->return_code = return_code;
do_finish(s);
- } else { // signaled
+ } else { // signaled
s->last_exit = EXIT_SIGNALED;
s->return_code = return_code;
diff --git a/src/service.c b/src/service.c
@@ -44,7 +44,7 @@ int service_refresh() {
struct dirent* ep;
dp = opendir(service_dir);
if (dp == NULL) {
- print_error("cannot open directory %s", service_dir);
+ print_error("error: cannot open directory %s: %s\n", service_dir);
return -1;
}
diff --git a/src/socket_handler.c b/src/socket_handler.c
@@ -10,11 +10,12 @@ void service_handle_socket(int client) {
read(client, command, sizeof(command));
- printf("command: %c\n", command[0]);
-
ssize_t service_len = readstr(client, service_name);
- printf("command: %c-%02x with service '%s'\n", command[0], command[1], service_name);
+ if (service_len)
+ printf("command issued by user: %c-%02x with service '%s'\n", command[0], command[1], service_name);
+ else
+ printf("command issued by user: %c-%02x without service\n", command[0], command[1]);
int res = 0;
int res_off = 0;
diff --git a/src/stage.c b/src/stage.c
@@ -26,7 +26,7 @@ void handle_stage1() {
int pid, ttyfd, exitstat;
sigset_t ss;
while ((pid = fork()) == -1) {
- print_error("unable to fork for stage1");
+ print_error("error: unable to fork for stage1: %s\n");
sleep(5);
}
if (pid == 0) {
@@ -34,7 +34,7 @@ void handle_stage1() {
/* stage 1 gets full control of console */
if ((ttyfd = open("/dev/console", O_RDWR)) == -1) {
- print_error("unable to open /dev/console");
+ print_error("error: unable to open /dev/console: %s\n");
} else {
ioctl(ttyfd, TIOCSCTTY, NULL); // make the controlling process
dup2(ttyfd, 0);
@@ -52,9 +52,8 @@ void handle_stage1() {
sigact.sa_handler = SIG_IGN;
sigaction(SIGCONT, &sigact, NULL);
- printf("enter stage1\n");
execl(SV_START_EXEC, SV_START_EXEC, NULL);
- print_error("unable to exec stage1");
+ print_error("error: unable to exec stage1: %s\n");
_exit(1);
}
bool dont_wait = false;
@@ -77,7 +76,7 @@ void handle_stage1() {
} while (child > 0 && child != pid);
if (child == -1) {
- print_error("waitpid failed, pausing");
+ print_error("warn: waitpid failed: %s");
sleep(5);
}
@@ -91,16 +90,14 @@ void handle_stage1() {
if (child == pid) {
if (!WIFEXITED(exitstat) || WEXITSTATUS(exitstat) != 0) {
- printf("child failed\n");
if (WIFSIGNALED(exitstat)) {
/* this is stage 1 */
- printf("leave stage 1\n");
- printf("skipping stage 2\n");
+ fprintf(stderr, "stage 1 failed: skip stage 2\n");
daemon_running = false;
break;
}
}
- printf("leave stage1\n");
+ printf("leave stage 1\n");
break;
}
if (child != 0) {
@@ -115,7 +112,7 @@ void handle_stage1() {
continue;
}
- printf("signals only work in stage 2\n");
+ fprintf(stderr, "warn: signals only work in stage 2, ignoring...\n");
}
}
@@ -124,7 +121,7 @@ void handle_stage3() {
int pid, ttyfd, exitstat;
sigset_t ss;
while ((pid = fork()) == -1) {
- print_error("unable to fork for state3");
+ print_error("warn: unable to fork for state3: %s");
sleep(5);
}
if (pid == 0) {
@@ -145,7 +142,7 @@ void handle_stage3() {
printf("enter stage3\n");
execl(SV_STOP_EXEC, SV_STOP_EXEC, NULL);
- print_error("unable to exec stage3");
+ print_error("error: unable to exec stage3: %s\n");
_exit(1);
}
bool dont_wait = false;
@@ -168,7 +165,7 @@ void handle_stage3() {
} while (child > 0 && child != pid);
if (child == -1) {
- print_error("waitpid failed, pausing");
+ print_error("error: waitpid failed, pausing: %s\n");
sleep(5);
}
@@ -181,9 +178,9 @@ void handle_stage3() {
}
if (child == pid) {
- if (!WIFEXITED(exitstat) || WEXITSTATUS(exitstat) != 0) {
- printf("child failed\n");
- }
+ // if (!WIFEXITED(exitstat) || WEXITSTATUS(exitstat) != 0) {
+ // printf("child failed\n");
+ // }
printf("leave stage: stage3\n");
break;
}
@@ -197,6 +194,6 @@ void handle_stage3() {
if (sig != SIGCONT && sig != SIGINT) {
continue;
}
- printf("signals only work in stage 2\n");
+ fprintf(stderr, "warn: signals only work in stage 2\n");
}
}
diff --git a/src/start.c b/src/start.c
@@ -20,13 +20,13 @@ static void set_pipes(service_t* s) {
close(s->log_pipe.read);
dup2(null_fd, STDOUT_FILENO);
dup2(null_fd, STDERR_FILENO);
- } else if (s->log_service) { // aka has_log_service
+ } else if (s->log_service) { // aka has_log_service
close(s->log_service->log_pipe.read);
dup2(s->log_service->log_pipe.write, STDOUT_FILENO);
dup2(s->log_service->log_pipe.write, STDERR_FILENO);
close(s->log_service->log_pipe.write);
dup2(null_fd, STDIN_FILENO);
- } else if (stat_mode("log") & S_IWRITE) { // is not
+ } else if (stat_mode("log") & S_IWRITE) { // is not
int log_fd;
if ((log_fd = open("log", O_WRONLY | O_TRUNC)) == -1)
log_fd = null_fd;
@@ -54,11 +54,11 @@ static void set_pipes(service_t* s) {
static void set_user() {
char buffer[1024];
- int user_file;
+ int user_file;
if ((user_file = open("user", O_RDONLY)) != -1) {
ssize_t n;
if ((n = read(user_file, buffer, sizeof(buffer))) == -1) {
- printf("failed reading user\n");
+ print_error("error: failed reading ./user: %s\n");
close(user_file);
return;
}
@@ -67,7 +67,7 @@ static void set_user() {
uid_t uid;
gid_t gids[60];
if ((n = parse_ugid(buffer, &uid, gids)) <= 0) {
- printf("error parsing user\n");
+ fprintf(stderr, "warn: malformatted user file\n");
close(user_file);
return;
}
@@ -88,22 +88,22 @@ void service_run(service_t* s) {
} else if (stat_mode("%s/%s/depends", service_dir, s->name) & S_IREAD) {
s->state = STATE_ACTIVE_DUMMY;
} else {
- printf("error in %s: `run`, `start` or `depends` not found\n", s->name);
+ fprintf(stderr, "warn: %s: `run`, `start` or `depends` not found\n", s->name);
s->state = STATE_INACTIVE;
}
if (s->state != STATE_ACTIVE_DUMMY) {
if ((s->pid = fork()) == -1) {
- print_error("cannot fork process");
+ print_error("error: cannot fork process: %s\n");
exit(1);
- } else if (s->pid == 0) { // child
+ } else if (s->pid == 0) { // child
if (setsid() == -1)
- print_error("cannot setsid");
+ print_error("error: cannot setsid: %s\n");
char dir_path[PATH_MAX];
snprintf(dir_path, PATH_MAX, "%s/%s", service_dir, s->name);
if (chdir(dir_path) == -1)
- print_error("chdir failed");
+ print_error("error: chdir failed: %s\n");
set_pipes(s);
@@ -111,6 +111,7 @@ void service_run(service_t* s) {
char* argv[SV_ARGUMENTS_MAX];
for (int i = 0; i < SV_ARGUMENTS_MAX; i++)
argv[i] = args[i];
+
char envs[SV_ENV_MAX][SV_ENV_FILE_LINE_MAX];
char* envv[SV_ENV_MAX];
for (int i = 0; i < SV_ENV_MAX; i++)
@@ -126,7 +127,7 @@ void service_run(service_t* s) {
} else {
execve("./run", argv, envv);
}
- print_error("cannot execute service");
+ print_error("error: cannot execute service: %s\n");
_exit(1);
}
}
@@ -140,7 +141,7 @@ void service_start(service_t* s, bool* changed) {
if (changed)
*changed = true;
- printf(":: starting %s \n", s->name);
+ printf("starting %s\n", s->name);
for (int i = 0; i < depends_size; i++) {
if (depends[i].service == s)
service_start(depends[i].depends, NULL);
@@ -157,18 +158,18 @@ void service_start(service_t* s, bool* changed) {
if (stat_mode("%s/%s/setup", service_dir, s->name) & S_IXUSR) {
s->state = STATE_SETUP;
if ((s->pid = fork()) == -1) {
- print_error("cannot fork process");
+ print_error("error: cannot fork process: %s\n");
} else if (s->pid == 0) {
dup2(null_fd, STDIN_FILENO);
dup2(null_fd, STDOUT_FILENO);
dup2(null_fd, STDERR_FILENO);
execl(path_buf, path_buf, NULL);
- print_error("cannot execute finish process");
+ print_error("error: cannot execute setup process: %s\n");
_exit(1);
}
} else {
service_run(s);
}
- printf(":: started %s \n", s->name);
+ printf("started %s \n", s->name);
}
diff --git a/src/stop.c b/src/stop.c
@@ -29,14 +29,14 @@ void service_stop(service_t* s, bool* changed) {
s->state = STATE_STOPPING;
if ((s->pid = fork()) == -1) {
- print_error("cannot fork process");
+ print_error("error: cannot fork process: %s\n");
} else if (s->pid == 0) {
dup2(null_fd, STDIN_FILENO);
dup2(null_fd, STDOUT_FILENO);
dup2(null_fd, STDERR_FILENO);
execl(path_buffer, path_buffer, NULL);
- print_error("cannot execute stop process");
+ print_error("error: cannot execute stop process: %s\n");
_exit(1);
}
if (changed)
diff --git a/src/supervise.c b/src/supervise.c
@@ -19,12 +19,12 @@ bool daemon_running = true;
static void signal_child(int unused) {
(void) unused;
- int status;
- pid_t died_pid;
+ int status;
+ pid_t died_pid;
service_t* s = NULL;
if ((died_pid = wait(&status)) == -1) {
- print_error("cannot wait for process");
+ print_error("error: cannot wait for process: %s\n");
return;
}
@@ -78,7 +78,7 @@ static void accept_socket() {
if (errno == EWOULDBLOCK) {
sleep(SV_ACCEPT_INTERVAL);
} else {
- print_error("cannot accept client from control-socket");
+ print_error("error: cannot accept client from control-socket: %s\n");
}
} else {
service_handle_socket(client_fd);
@@ -87,7 +87,7 @@ static void accept_socket() {
int service_supervise(const char* service_dir_, const char* runlevel_, bool force_socket) {
struct sigaction sigact = { 0 };
- sigact.sa_handler = signal_child;
+ sigact.sa_handler = signal_child;
sigaction(SIGCHLD, &sigact, NULL);
sigact.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sigact, NULL);
@@ -101,7 +101,7 @@ int service_supervise(const char* service_dir_, const char* runlevel_, bool forc
snprintf(socket_path, PATH_MAX, SV_CONTROL_SOCKET, runlevel);
if ((null_fd = open("/dev/null", O_RDWR)) == -1) {
- print_error("cannot open /dev/null");
+ print_error("error: cannot open /dev/null: %s\n");
null_fd = 1;
}
@@ -115,7 +115,7 @@ int service_supervise(const char* service_dir_, const char* runlevel_, bool forc
struct stat socket_stat;
if (force_socket) {
if (unlink(socket_path) == -1 && errno != ENOENT) {
- print_error("cannot unlink socket");
+ print_error("error: cannot unlink socket: %s\n");
}
} else if (stat(socket_path, &socket_stat) != -1 && S_ISREG(socket_stat.st_mode)) {
printf("error: %s exist and is locking supervision,\nrun this program with '-f' flag if you are sure no other superviser is running.", socket_path);
@@ -123,31 +123,30 @@ int service_supervise(const char* service_dir_, const char* runlevel_, bool forc
}
// create socket
if ((control_socket = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
- print_error("cannot create socket");
+ print_error("error: cannot create socket: %s\n");
return 1;
}
// bind socket to address
struct sockaddr_un addr = { 0 };
- addr.sun_family = AF_UNIX;
+ addr.sun_family = AF_UNIX;
strcpy(addr.sun_path, socket_path);
if (bind(control_socket, (struct sockaddr*) &addr, sizeof(addr)) == -1) {
- print_error("cannot bind %s to socket", socket_path);
+ print_error("error: cannot bind %s to socket: %s\n", socket_path);
return 1;
}
// listen for connections
if (listen(control_socket, 5) == -1) {
- print_error("cannot listen to control socket");
+ print_error("error: cannot listen to control socket: %s\n");
return 1;
}
int sockflags = fcntl(control_socket, F_GETFL, 0);
if (sockflags == -1) {
- print_warning("fcntl-getflags on control-socket failed");
- } else {
- if (fcntl(control_socket, F_SETFL, sockflags | O_NONBLOCK) == -1)
- print_warning("fcntl-setflags on control-socket failed");
+ print_error("warn: fcntl-getflags on control-socket failed: %s\n");
+ } else if (fcntl(control_socket, F_SETFL, sockflags | O_NONBLOCK) == -1) {
+ print_error("warn: fcntl-setflags on control-socket failed: %s\n");
}
// accept connections and handle requests
@@ -161,7 +160,7 @@ int service_supervise(const char* service_dir_, const char* runlevel_, bool forc
close(control_socket);
if (unlink(socket_path) == -1 && errno != ENOENT) {
- print_error("cannot unlink socket");
+ print_error("error: cannot unlink socket: %s\n");
}
printf(":: terminating\n");
@@ -173,9 +172,9 @@ int service_supervise(const char* service_dir_, const char* runlevel_, bool forc
}
time_t start = time(NULL);
- int running;
+ int running;
do {
- sleep(1); // sleep for one second
+ sleep(1); // sleep for one second
running = 0;
for (int i = 0; i < services_size; i++) {
if (services[i].state != STATE_INACTIVE)