diff options
Diffstat (limited to 'init')
-rw-r--r-- | init/init.c | 26 | ||||
-rw-r--r-- | init/log.c | 33 | ||||
-rw-r--r-- | init/subsys.c | 66 |
3 files changed, 100 insertions, 25 deletions
diff --git a/init/init.c b/init/init.c index 7c2d6a6..97461ef 100644 --- a/init/init.c +++ b/init/init.c @@ -1,9 +1,14 @@ #include <signal.h> #include <sys/wait.h> +#include <config.h> #include <init.h> +#include <log.h> #include <util.h> +extern int subsystem_handle_term(int pid); +int mainpid = 0; + /* For some reason, I get SIGSEGV'd when running because a random-ass byte was inserted where it isnt supposed to be. Added a safety byte because I cannot be asked to try to figure out how to do this cleanly. */ @@ -48,20 +53,27 @@ static void do_initcalls(void) int main(void) { + print("init: Hello world! Running " NAME " v" VERSION "!"); + + mainpid = getpid(); + + /* Rest of the program.. */ do_initcalls(); /* Reaper. Much like init. */ - // BUG: doesnt actually work?? we have defunct processes still - // TODO: fix bug + siginfo_t siginfo; static sigset_t set; sigaddset(&set, SIGCHLD); sigprocmask(SIG_BLOCK, &set, NULL); while(1) { - int sig; - sigwait(&set, &sig); - if(sig == SIGCHLD) - while(waitpid(0, NULL, WNOHANG) > 0) - ; + sigwaitinfo(&set, &siginfo); + int sig = siginfo.si_signo; + if(sig == SIGCHLD) { + int process = 0; + while((process = waitpid(-1, NULL, WNOHANG)) > 0) + if(subsystem_handle_term(process) > 0) + print("init: failed to reap process %d", process); + } } } @@ -2,32 +2,38 @@ #include <stdio.h> #include <string.h> #include <sys/file.h> +#include <sys/time.h> #include <unistd.h> #include <log.h> #include <util.h> static const char *colors[] = { - [0] = ANSI_BLINK ANSI_REVERSE ANSI_BOLD ANSI_RED, - [1] = ANSI_REVERSE ANSI_BOLD ANSI_RED, - [2] = ANSI_BOLD ANSI_RED, - [3] = ANSI_RED, - [4] = ANSI_BOLD, - [5] = ANSI_BRIGHT_WHITE, - [6] = ANSI_RESET, - [7] = ANSI_ITALIC ANSI_BRIGHT_BLUE, + [EMERG_LOGLEVEL] = ANSI_BLINK ANSI_REVERSE ANSI_BOLD ANSI_RED, + [ALERT_LOGLEVEL] = ANSI_REVERSE ANSI_BOLD ANSI_RED, + [CRIT_LOGLEVEL] = ANSI_BOLD ANSI_RED, + [ERR_LOGLEVEL] = ANSI_RED, + [WARNING_LOGLEVEL] = ANSI_BOLD, + [NOTICE_LOGLEVEL] = ANSI_BRIGHT_WHITE, + [INFO_LOGLEVEL] = ANSI_RESET, + [DEBUG_LOGLEVEL] = ANSI_ITALIC ANSI_BRIGHT_BLUE, }; +int start_time = 0; int console_lock = 0; int print(const char *fmt, ...) { - int loglevel = 5; + int loglevel = DEFAULT_LOGLEVEL; if(fmt[0] == LOG_SOH_ASCII) { loglevel = (fmt[1] - 0x30) % 10; fmt += 2; } + /* not going to be printed? dont bother! */ + if(loglevel > CONSOLE_LOGLEVEL) + return 0; + /* we essentially print the user's raw input to its own buffer, later we will parse it and print out ANSI colors and what not */ char buf[512]; @@ -44,6 +50,11 @@ int print(const char *fmt, ...) break; } + char tsbuf[64] = "\0"; + struct timeval time; + gettimeofday(&time, NULL); + snprintf(tsbuf, sizeof(tsbuf), "[%5ld.%06ld] ", (long)time.tv_sec % 100000, (long)time.tv_usec); + /* spin lock, at the cost of architecture portability concurrency is something that we need to adjust for, and the console will be scrambled and unreadable if we allow writing all @@ -58,8 +69,10 @@ int print(const char *fmt, ...) /* we want to support stuff without colons, but frankly I havent tested this at time of writing. will find out later */ + writeputs(ANSI_RESET ANSI_GREEN); + writeputs(tsbuf); + writeputs(ANSI_RESET); if(buf[colon] == ':') { - writeputs(ANSI_RESET); writeputs(colors[loglevel]); writeputs(ANSI_YELLOW); write(STDOUT_FILENO, buf, colon); diff --git a/init/subsys.c b/init/subsys.c index 62ee54e..a88046d 100644 --- a/init/subsys.c +++ b/init/subsys.c @@ -1,5 +1,6 @@ #include <errno.h> #include <sched.h> +#include <signal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -13,13 +14,20 @@ #include <util.h> #define STACK_SIZE 8192 * 512 +#define MAX_SUBSYSTEMS 32 struct subsystem_info { char *fn_name; int (*fn)(void); + int pid; + void *stack; }; -int __subsystem_entry(struct subsystem_info *info) +extern int mainpid; +static struct subsystem_info *subsystems[MAX_SUBSYSTEMS + 1]; +static int subsystem_count = 0; + +static int __subsystem_entry(struct subsystem_info *info) { /* entry point from clone(). we setup the process name so we know what we are looking at from a glance in a ps view or htop or @@ -30,21 +38,51 @@ int __subsystem_entry(struct subsystem_info *info) prctl(PR_SET_NAME, name); free(name); - int ret = info->fn(); + print(LOG_DEBUG "subsys: starting subsystem %s (%d)", info->fn_name, getpid()); - /* we are expected to free info before exiting */ - free(info); + int ret = info->fn(); return ret; } +int subsystem_handle_term(int pid) +{ + for(int i = 0; i < MAX_SUBSYSTEMS; ++i) { + struct subsystem_info *subsystem = subsystems[i]; + if(!subsystem || subsystem->pid != pid) + continue; + + print(LOG_DEBUG "subsys: subsystem terminated %s (%d)", subsystem->fn_name, pid); + + if(munmap(subsystem->stack, STACK_SIZE) < 0) + print(LOG_EMERG "subsys: failed to deallocate stack for subsystem %s (%d) (errno %d)", subsystem->fn_name, pid, errno); + subsystems[i] = 0; + free(subsystem); + + return 0; + } + + return 1; +} + int __impl_start_subsystem(char *fn_name, int (*fn)(void)) { + if(getpid() != mainpid) { + print(LOG_CRIT "subsys: cannot perform subsystem inception (attempted from %d)", getpid()); + return 1; + } + if(subsystem_count >= MAX_SUBSYSTEMS) { + print(LOG_CRIT "subsys: cannot start subsystem %s: reached maximum number of subsystems", fn_name); + return 1; + } + /* because CLONE_VM is being set, our stack is not duplicated and therefore we need to map a stack */ void *stack = mmap(NULL, STACK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK | MAP_PRIVATE, -1, 0); - if((long)stack < 0) - die("subsys mmap:"); + if((long)stack <= 0) { + print(LOG_CRIT "subsys: cannot start subsystem %s: failed to allocate stack (errno %d)", fn_name, errno); + return 1; + } /* the libc gods have graced us with the ability to pass one (1) arg to the function. struct required. the absence of a free is not a @@ -52,11 +90,23 @@ int __impl_start_subsystem(char *fn_name, int (*fn)(void)) struct subsystem_info *info = malloc(sizeof(struct subsystem_info)); info->fn_name = fn_name; info->fn = fn; + info->stack = stack; - int pid = clone((int (*)(void *))__subsystem_entry, (void *)((long)stack + STACK_SIZE), CLONE_FILES | CLONE_VM, info); + int pid = clone((int (*)(void *))__subsystem_entry, (void *)((long)stack + STACK_SIZE), CLONE_FILES | CLONE_VM | SIGCHLD, info); + info->pid = pid; if(pid < 0) { + print(LOG_CRIT "subsys: cannot start subsystem %s: clone failed (errno %d)", fn_name, errno); munmap(stack, STACK_SIZE); - die("subsys clone:"); + free(info); + return 1; + } + + for(int i = 0; i < MAX_SUBSYSTEMS; ++i) { + if(!subsystems[i]) { + subsystems[i] = info; + ++subsystem_count; + break; + } } return 0; |