unix/fiss

adding setup (a1a8b486bdc5fc997964b3c4be5bebe62033d4db)
Repositories | LICENSE

commit a1a8b486bdc5fc997964b3c4be5bebe62033d4db
parent 39e4016d97c4ee78180fd9d73d6fa44c9c365025
Author: Friedel Schon <[email protected]>
Date:   Fri, 28 Apr 2023 01:01:45 +0200

adding setup

Diffstat:
Minclude/service.h112++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msrc/restart.c21++++++++++++++++-----
Msrc/start.c74+++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
3 files changed, 122 insertions(+), 85 deletions(-)

diff --git a/include/service.h b/include/service.h @@ -7,30 +7,31 @@ #include <stdint.h> #include <time.h> -#define SV_SERIAL_LEN 17 +#define SV_SERIAL_LEN 17 #define SV_HAS_LOGSERVICE ((void*) 1) -#define EBADCMD 1 // command not found -#define ENOSV 2 // service required -#define EBADSV 3 // no matching services -#define EBEXT 4 // invalid extra +#define EBADCMD 1 // command not found +#define ENOSV 2 // service required +#define EBADSV 3 // no matching services +#define EBEXT 4 // invalid extra typedef enum { - S_START = 'u', // start if not running and restart if failed - S_STOP = 'd', // stop if running and not restart if failed - S_SEND = 'k', // + signal | send signal to service - S_PAUSE = 'p', // pause service (send SIGSTOP) - S_RESUME = 'c', // unpause service (send SIGCONT) - S_REVIVE = 'v', // revive died service - S_EXIT = 'x', // kill the fsvs instance - S_STATUS = 'a', // get status of all services - S_SWITCH = 'l', // change runlevel - S_ENABLE = 'E', // of extra disable - S_DISABLE = 'D', // of extra disable + S_START = 'u', // start if not running and restart if failed + S_STOP = 'd', // stop if running and not restart if failed + S_SEND = 'k', // + signal | send signal to service + S_PAUSE = 'p', // pause service (send SIGSTOP) + S_RESUME = 'c', // unpause service (send SIGCONT) + S_REVIVE = 'v', // revive died service + S_EXIT = 'x', // kill the fsvs instance + S_STATUS = 'a', // get status of all services + S_SWITCH = 'l', // change runlevel + S_ENABLE = 'E', // of extra disable + S_DISABLE = 'D', // of extra disable } sv_command_t; typedef enum service_state { STATE_INACTIVE, + STATE_SETUP, STATE_STARTING, STATE_ACTIVE_DUMMY, STATE_ACTIVE_FOREGROUND, @@ -49,25 +50,25 @@ typedef enum service_exit { typedef enum service_restart { S_DOWN, - S_FORCE_DOWN, // force down (manual) + S_FORCE_DOWN, // force down (manual) S_ONCE, S_RESTART, } service_restart_t; typedef struct service { - char name[SV_NAME_MAX]; // name of service - service_state_t state; - pid_t pid; // pid of run - time_t status_change; // last status change - pipe_t log_pipe; // pipe for logging - service_restart_t restart_manual; // should restart on exit - service_restart_t restart_file; // should restart on exit - service_exit_t 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; - struct service* log_service; + char name[SV_NAME_MAX]; // name of service + service_state_t state; + pid_t pid; // pid of run + time_t status_change; // last status change + pipe_t log_pipe; // pipe for logging + service_restart_t restart_manual; // should restart on exit + service_restart_t restart_file; // should restart on exit + service_exit_t 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; + struct service* log_service; } service_t; typedef struct dependency { @@ -79,32 +80,33 @@ typedef struct dependency { extern const char* command_error[]; extern const char* command_string[]; -extern service_t services[]; -extern int services_size; -extern char runlevel[]; -extern const char* service_dir; -extern int null_fd; -extern int control_socket; -extern bool daemon_running; -extern bool verbose; +extern service_t services[]; +extern int services_size; +extern char runlevel[]; +extern const char* service_dir; +extern int null_fd; +extern int control_socket; +extern bool daemon_running; +extern bool verbose; extern dependency_t depends[]; -extern int depends_size; +extern int depends_size; -char service_get_command(const char* command); -int service_command(char command, char extra, const char* service, service_t* response, int response_max); -int service_handle_command(void* s, sv_command_t command, uint8_t extra, service_t** response); -int service_pattern(const char* name, service_t** dest, int dest_max); -int service_refresh(); -int service_supervise(const char* service_dir, const char* runlevel, bool force_socket); +char service_get_command(const char* command); +int service_command(char command, char extra, const char* service, service_t* response, int response_max); +int service_handle_command(void* s, sv_command_t command, uint8_t extra, service_t** response); +int service_pattern(const char* name, service_t** dest, int dest_max); +int service_refresh(); +int service_supervise(const char* service_dir, const char* runlevel, bool force_socket); service_t* service_get(const char* name); service_t* service_register(const char* name, bool is_log_service); -void service_check_state(service_t* s, bool signaled, int return_code); -void service_handle_socket(int client); -void service_load(service_t* s, const uint8_t* buffer); // for fsvc -void service_send(service_t* s, int signal); -void service_start(service_t* s, bool* changed); -void service_stop(service_t* s, bool* changed); -void service_store(service_t* s, uint8_t* buffer); // for fsvs -void service_update_dependency(service_t* s); -bool service_need_restart(service_t* s); -\ No newline at end of file +void service_check_state(service_t* s, bool signaled, int return_code); +void service_handle_socket(int client); +void service_load(service_t* s, const uint8_t* buffer); // for fsvc +void service_send(service_t* s, int signal); +void service_start(service_t* s, bool* changed); +void service_stop(service_t* s, bool* changed); +void service_store(service_t* s, uint8_t* buffer); // for fsvs +void service_update_dependency(service_t* s); +bool service_need_restart(service_t* s); +void service_run(service_t* s); +\ No newline at end of file diff --git a/src/restart.c b/src/restart.c @@ -1,14 +1,22 @@ #include "config_parser.h" +#include "service.h" #include <errno.h> #include <limits.h> +#include <stdarg.h> #include <stdio.h> #include <string.h> #include <sys/stat.h> +/*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 *) +}*/ + static void do_finish(service_t* s) { - char path_buffer[PATH_MAX]; + char path_buffer[PATH_MAX]; struct stat stat_buffer; snprintf(path_buffer, PATH_MAX, "%s/%s/finish", service_dir, s->name); @@ -36,16 +44,19 @@ 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) s->restart_manual = S_DOWN; - char path_buffer[PATH_MAX]; + char path_buffer[PATH_MAX]; struct stat stat_buffer; switch (s->state) { + case STATE_SETUP: + service_run(s); + break; case STATE_ACTIVE_FOREGROUND: if (signaled) { s->last_exit = EXIT_SIGNALED; @@ -87,7 +98,7 @@ void service_check_state(service_t* s, bool signaled, int return_code) { if (snprintf(path_buffer, PATH_MAX, "%s/%s/stop", service_dir, s->name) && stat(path_buffer, &stat_buffer) == 0 && stat_buffer.st_mode & S_IXUSR) { s->state = STATE_ACTIVE_BACKGROUND; } else if (snprintf(path_buffer, PATH_MAX, "%s/%s/pid", service_dir, s->name) && stat(path_buffer, &stat_buffer) == 0 && stat_buffer.st_mode & S_IRUSR) { - s->pid = parse_pid_file(s); + s->pid = parse_pid_file(s); s->state = STATE_ACTIVE_PID; } else { do_finish(s); @@ -97,7 +108,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/start.c b/src/start.c @@ -1,4 +1,5 @@ #include "config_parser.h" +#include "service.h" #include "user_group.h" #include <errno.h> @@ -9,6 +10,7 @@ #include <stdlib.h> #include <string.h> #include <sys/stat.h> +#include <unistd.h> static void set_pipes(service_t* s) { @@ -20,13 +22,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("log", &estat) == 0 && estat.st_mode & S_IWRITE) { // is not + } else if (stat("log", &estat) == 0 && estat.st_mode & S_IWRITE) { // is not int log_fd; if ((log_fd = open("log", O_WRONLY | O_TRUNC)) == -1) log_fd = null_fd; @@ -54,7 +56,7 @@ 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) { @@ -80,28 +82,10 @@ static void set_user() { } } - -void service_start(service_t* s, bool* changed) { - if (s->state != STATE_INACTIVE) - return; - - if (changed) - *changed = true; - - 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); - } - - for (int i = 0; i < depends_size; i++) { - if (depends[i].service == s) - service_start(depends[i].depends, NULL); - } - - char path_buf[PATH_MAX]; - +void service_run(service_t* s) { + char path_buf[PATH_MAX]; struct stat estat; + if (snprintf(path_buf, PATH_MAX, "%s/%s/run", service_dir, s->name) && stat(path_buf, &estat) == 0 && estat.st_mode & S_IXUSR) { s->state = STATE_ACTIVE_FOREGROUND; } else if (snprintf(path_buf, PATH_MAX, "%s/%s/start", service_dir, s->name) && stat(path_buf, &estat) == 0 && estat.st_mode & S_IXUSR) { @@ -110,13 +94,14 @@ void service_start(service_t* s, bool* changed) { s->state = STATE_ACTIVE_DUMMY; } else { printf("error in %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"); exit(1); - } else if (s->pid == 0) { // child + } else if (s->pid == 0) { // child if (setsid() == -1) print_error("cannot setsid"); @@ -151,5 +136,44 @@ void service_start(service_t* s, bool* changed) { } } s->status_change = time(NULL); +} + +void service_start(service_t* s, bool* changed) { + if (s->state != STATE_INACTIVE) + return; + + if (changed) + *changed = true; + + 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); + } + + for (int i = 0; i < depends_size; i++) { + if (depends[i].service == s) + service_start(depends[i].depends, NULL); + } + + char path_buf[PATH_MAX]; + struct stat estat; + + if (snprintf(path_buf, PATH_MAX, "%s/%s/setup", service_dir, s->name) && stat(path_buf, &estat) == 0 && estat.st_mode & S_IXUSR) { + s->state = STATE_FINISHING; + if ((s->pid = fork()) == -1) { + print_error("cannot fork process"); + } 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"); + _exit(1); + } + } else { + service_run(s); + } printf(":: started %s \n", s->name); }