From bc6e03d73b4ff54f5562400c57ffa1e685ac971a Mon Sep 17 00:00:00 2001 From: turret Date: Thu, 18 Jan 2024 19:01:13 -0600 Subject: init: apply .env files we apply .env files from both the current working directory and the directory of the executable we're running from very simple .env format, KEY=VALUE, comments prepended with # on first character of line only. --- init/init.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/init/init.c b/init/init.c index 7fb229e..3457769 100644 --- a/init/init.c +++ b/init/init.c @@ -1,8 +1,11 @@ +#include #include #include #include +#include #include #include +#include #include #include @@ -62,7 +65,52 @@ static void do_initcalls(void) } } +static void doenv(char *path) +{ + int fd = open(path, O_RDONLY); + if(fd < 0) + return; + + struct stat statbuf; + if(fstat(fd, &statbuf) < 0) + return; + + char *file_mmap = mmap(NULL, statbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if(file_mmap == NULL) + return; + + char *file = malloc(statbuf.st_size + 1); + file[statbuf.st_size + 1] = 0; + memcpy(file, file_mmap, statbuf.st_size); + munmap(file_mmap, statbuf.st_size); + + int offset = 0; + while(1) { + char *line = &(file[offset]); + if(*line == '\0') + break; + + char *eol = strchrnul(line, '\n'); + *eol = '\0'; + if(*line == '#') + goto nextline; + + char *divider = strchr(line, '='); + if(divider == NULL) + goto nextline; + *divider = '\0'; + setenv(line, divider + 1, 0); + print(LOG_DEBUG "env: setting \"%s\" to \"%s\"", + line, divider + 1); + +nextline: + offset += (eol - line) + 1; + continue; + } + + free(file); +} int main(void) { @@ -89,6 +137,29 @@ int main(void) sigaddset(&set, SIGTERM); sigprocmask(SIG_BLOCK, &set, NULL); + /* use .env files if present */ + doenv(".env"); + + /* find directory of self and use env from there if it exists */ + char *buf = calloc(PATH_MAX, sizeof(char)); + ssize_t self_size = readlink("/proc/self/exe", buf, PATH_MAX); + if(self_size + strlen(".env") + 1 > PATH_MAX) + goto skip_self; + + char *lastslash = strrchr(buf, '/'); + *lastslash = '\0'; + + char *cwd = get_current_dir_name(); + int cwd_is_exec_dir = strcmp(buf, cwd) == 0; + free(cwd); + if(cwd_is_exec_dir) + goto skip_self; + + strcat(buf, "/.env"); + doenv(buf); +skip_self: + free(buf); + /* fetch token */ char *token_base = getenv("TOKEN"); if(!token_base) -- cgit v1.2.3