diff --git a/.gitignore b/.gitignore index 178d7a2..8642070 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ kore *.module *.DSYM cert +obj diff --git a/Makefile b/Makefile index 036f6d2..7b3f505 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,7 @@ CC?=gcc PREFIX?=/usr/local +OBJDIR?=obj KORE=kore INSTALL_DIR=$(PREFIX)/bin INCLUDE_DIR=$(PREFIX)/include/kore @@ -9,7 +10,6 @@ INCLUDE_DIR=$(PREFIX)/include/kore S_SRC= src/kore.c src/buf.c src/cli.c src/config.c src/connection.c \ src/domain.c src/mem.c src/msg.c src/module.c src/net.c \ src/pool.c src/timer.c src/utils.c src/worker.c src/keymgr.c -S_OBJS= $(S_SRC:.c=.o) CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual @@ -70,11 +70,18 @@ else S_SRC+=src/bsd.c endif -$(KORE): $(S_OBJS) +S_OBJS= $(S_SRC:src/%.c=$(OBJDIR)/%.o) + +$(KORE): $(OBJDIR) $(S_OBJS) $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE) +objects: $(OBJDIR) $(S_OBJS) + all: $(KORE) +$(OBJDIR): + @mkdir -p $(OBJDIR) + install: mkdir -p $(INCLUDE_DIR) mkdir -p $(INSTALL_DIR) @@ -85,11 +92,11 @@ uninstall: rm -f $(INSTALL_DIR)/$(KORE) rm -rf $(INCLUDE_DIR) -.c.o: +$(OBJDIR)/%.o: src/%.c $(CC) $(CFLAGS) -c $< -o $@ clean: find . -type f -name \*.o -exec rm {} \; - rm -f $(KORE) + rm -rf $(KORE) $(OBJDIR) .PHONY: all clean diff --git a/includes/kore.h b/includes/kore.h index c54accf..16d10cf 100644 --- a/includes/kore.h +++ b/includes/kore.h @@ -399,6 +399,10 @@ struct kore_keyreq { }; #endif +#if !defined(KORE_SINGLE_BINARY) +extern char *config_file; +#endif + extern pid_t kore_pid; extern int foreground; extern int kore_debug; @@ -407,7 +411,6 @@ extern char *chroot_path; extern int skip_runas; extern char *runas_user; extern char *kore_pidfile; -extern char *config_file; extern char *kore_tls_cipher_list; extern int tls_version; @@ -631,6 +634,10 @@ void kore_buf_replace_string(struct kore_buf *, char *, void *, size_t); void kore_keymgr_run(void); void kore_keymgr_cleanup(void); +#if defined(KORE_SINGLE_BINARY) +void kore_main(void); +#endif + #if defined(__cplusplus) } #endif diff --git a/src/cli.c b/src/cli.c index 09093bd..c8d7974 100644 --- a/src/cli.c +++ b/src/cli.c @@ -68,6 +68,9 @@ struct buildopt { char *name; + char *kore_source; + char *kore_flavor; + int single_binary; struct kore_buf *cflags; struct kore_buf *cxxflags; struct kore_buf *ldflags; @@ -99,9 +102,10 @@ TAILQ_HEAD(cfile_list, cfile); static void cli_fatal(const char *, ...) __attribute__((noreturn)); static void cli_file_close(int); -static void cli_run_kore(void *); +static void cli_run_kore(void); static void cli_generate_certs(void); static void cli_link_library(void *); +static void cli_compile_kore(void *); static void cli_compile_source_file(void *); static void cli_mkdir(const char *, int); static int cli_dir_exists(const char *); @@ -118,6 +122,7 @@ static void cli_file_write(int, const void *, size_t); static int cli_vasprintf(char **, const char *, ...); static void cli_spawn_proc(void (*cb)(void *), void *); static void cli_write_asset(const char *, const char *); +static void cli_register_kore_file(char *, struct dirent *); static void cli_register_source_file(char *, struct dirent *); static void cli_file_create(const char *, const char *, size_t); static int cli_file_requires_build(struct stat *, const char *); @@ -126,6 +131,7 @@ static void cli_find_files(const char *, static void cli_add_source_file(char *, char *, char *, struct stat *, int); +static struct buildopt *cli_buildopt_default(void); static struct buildopt *cli_buildopt_new(const char *); static struct buildopt *cli_buildopt_find(const char *); static void cli_buildopt_cleanup(void); @@ -133,6 +139,12 @@ static void cli_buildopt_parse(const char *); static void cli_buildopt_cflags(struct buildopt *, const char *); static void cli_buildopt_cxxflags(struct buildopt *, const char *); static void cli_buildopt_ldflags(struct buildopt *, const char *); +static void cli_buildopt_single_binary(struct buildopt *, + const char *); +static void cli_buildopt_kore_source(struct buildopt *, + const char *); +static void cli_buildopt_kore_flavor(struct buildopt *, + const char *); static void cli_flavor_load(void); static void cli_flavor_change(const char *); @@ -209,6 +221,14 @@ static const char *build_data = "# %s build config\n" "# You can switch flavors using: kore flavor [newflavor]\n" "\n" + "# Set to yes if you wish to produce a single binary instead\n" + "# of a dynamic library. If you set this to yes you must also\n" + "# set kore_source together with kore_flavor and update ldflags\n" + "# to include the appropriate libraries you will be linking with.\n" + "#single_binary=no\n" + "#kore_source=/home/joris/src/kore\n" + "#kore_flavor=\n" + "\n" "# The flags below are shared between flavors\n" "cflags=-Wall -Wmissing-declarations -Wshadow\n" "cflags=-Wstrict-prototypes -Wmissing-prototypes\n" @@ -245,6 +265,7 @@ static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n"; static int s_fd = -1; static char *appl = NULL; +static int run_after = 0; static char *rootdir = NULL; static char *compiler_c = "gcc"; static char *compiler_cpp = "g++"; @@ -393,6 +414,7 @@ cli_flavor(int argc, char **argv) static void cli_build(int argc, char **argv) { + struct dirent dp; struct cfile *cf; struct buildopt *bopt; struct timeval times[2]; @@ -427,7 +449,6 @@ cli_build(int argc, char **argv) if (!cli_dir_exists(src_path) || !cli_file_exists(config)) cli_fatal("%s doesn't appear to be a kore app", appl); - free(config); cli_flavor_load(); bopt = cli_buildopt_new("_default"); @@ -437,38 +458,62 @@ cli_build(int argc, char **argv) free(data); } - cli_buildopt_parse(build_path); - free(build_path); - - /* Build all source files. */ cli_find_files(src_path, cli_register_source_file); free(src_path); - printf("building %s (%s)\n", appl, flavor); - cli_build_cflags(bopt); - cli_build_cxxflags(bopt); - cli_build_ldflags(bopt); + cli_buildopt_parse(build_path); + free(build_path); (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir); if (!cli_dir_exists(obj_path)) cli_mkdir(obj_path, 0755); free(obj_path); + if (bopt->single_binary) { + if (bopt->kore_source == NULL) + cli_fatal("single_binary set but not kore_source"); + + printf("building kore (%s)\n", bopt->kore_source); + cli_spawn_proc(cli_compile_kore, bopt); + + (void)cli_vasprintf(&src_path, "%s/src", bopt->kore_source); + cli_find_files(src_path, cli_register_kore_file); + free(src_path); + } + + printf("building %s (%s)\n", appl, flavor); + + cli_build_cflags(bopt); + cli_build_cxxflags(bopt); + cli_build_ldflags(bopt); + (void)unlink(assets_header); /* Generate the assets. */ - if (cli_dir_exists(assets_path)) { - cli_file_open(assets_header, - O_CREAT | O_TRUNC | O_WRONLY, &s_fd); + cli_file_open(assets_header, O_CREAT | O_TRUNC | O_WRONLY, &s_fd); + cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n"); + cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n"); - cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n"); - cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n"); + if (cli_dir_exists(assets_path)) cli_find_files(assets_path, cli_build_asset); - cli_file_writef(s_fd, "\n#endif\n"); - cli_file_close(s_fd); + + if (bopt->single_binary) { + memset(&dp, 0, sizeof(dp)); + dp.d_type = DT_REG; + printf("adding config %s\n", config); + (void)snprintf(dp.d_name, + sizeof(dp.d_name), "builtin_kore.conf"); + cli_build_asset(config, &dp); } + cli_file_writef(s_fd, "\n#endif\n"); + cli_file_close(s_fd); + free(assets_path); + free(config); + + if (cxx_files_count > 0) + compiler_ld = compiler_cpp; requires_relink = 0; TAILQ_FOREACH(cf, &source_files, list) { @@ -485,10 +530,6 @@ cli_build(int argc, char **argv) if (utimes(cf->opath, times) == -1) printf("utime(%s): %s\n", cf->opath, errno_s); - if (cf->build == BUILD_CXX) { - compiler_ld = compiler_cpp; - } - requires_relink++; } @@ -502,18 +543,26 @@ cli_build(int argc, char **argv) } free(cpath); - (void)cli_vasprintf(&sofile, "%s.so", appl); + if (bopt->single_binary) { + requires_relink++; + (void)cli_vasprintf(&sofile, "%s", appl); + } else { + (void)cli_vasprintf(&sofile, "%s.so", appl); + } + if (!cli_file_exists(sofile)) requires_relink++; free(sofile); if (requires_relink) { - cli_spawn_proc(cli_link_library, NULL); + cli_spawn_proc(cli_link_library, bopt); printf("%s built successfully!\n", appl); } else { printf("nothing to be done!\n"); } - cli_buildopt_cleanup(); + + if (run_after == 0) + cli_buildopt_cleanup(); } static void @@ -538,6 +587,7 @@ cli_clean(int argc, char **argv) static void cli_run(int argc, char **argv) { + run_after = 1; cli_build(argc, argv); if (chdir(rootdir) == -1) @@ -547,7 +597,7 @@ cli_run(int argc, char **argv) * We are exec()'ing kore again, while we could technically set * the right cli options manually and just continue running. */ - cli_run_kore(NULL); + cli_run_kore(); } static void @@ -850,12 +900,14 @@ cli_register_source_file(char *fpath, struct dirent *dp) if (stat(fpath, &st) == -1) cli_fatal("stat(%s): %s", fpath, errno_s); + if (!strcmp(ext, ".cpp")) + cxx_files_count++; + (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name); if (!cli_file_requires_build(&st, opath)) { build = BUILD_NOBUILD; } else if (!strcmp(ext, ".cpp")) { build = BUILD_CXX; - cxx_files_count++; } else { build = BUILD_C; } @@ -863,6 +915,33 @@ cli_register_source_file(char *fpath, struct dirent *dp) cli_add_source_file(dp->d_name, fpath, opath, &st, build); } +static void +cli_register_kore_file(char *fpath, struct dirent *dp) +{ + struct stat st, ost; + char *opath, *ext, *fname; + + if ((ext = strrchr(fpath, '.')) == NULL || strcmp(ext, ".c")) + return; + + if (stat(fpath, &st) == -1) + cli_fatal("stat(%s): %s", fpath, errno_s); + + *ext = '\0'; + if ((fname = basename(fpath)) == NULL) + cli_fatal("basename failed"); + + (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, fname); + + /* Silently ignore non existing object files for kore source files. */ + if (stat(opath, &ost) == -1) { + free(opath); + return; + } + + cli_add_source_file(dp->d_name, fpath, opath, &st, BUILD_NOBUILD); +} + static void cli_file_remove(char *fpath, struct dirent *dp) { @@ -1049,17 +1128,24 @@ cli_compile_source_file(void *arg) args[idx] = NULL; execvp(compiler, args); + cli_fatal("failed to start '%s': %s", compiler, errno_s); } static void cli_link_library(void *arg) { struct cfile *cf; + struct buildopt *bopt; int idx, i; - char *libname; + char *output; char *args[source_files_count + 11 + LD_FLAGS_MAX]; - (void)cli_vasprintf(&libname, "%s/%s.so", rootdir, appl); + bopt = arg; + + if (bopt->single_binary) + (void)cli_vasprintf(&output, "%s/%s", rootdir, appl); + else + (void)cli_vasprintf(&output, "%s/%s.so", rootdir, appl); idx = 0; args[idx++] = compiler_ld; @@ -1070,26 +1156,95 @@ cli_link_library(void *arg) for (i = 0; i < ldflags_count; i++) args[idx++] = ldflags[i]; + if (bopt->single_binary) { + args[idx++] = "-rdynamic"; +#if defined(__linux__) + args[idx++] = "-ldl"; +#endif + } + args[idx++] = "-o"; - args[idx++] = libname; + args[idx++] = output; args[idx] = NULL; execvp(compiler_ld, args); + cli_fatal("failed to start '%s': %s", compiler_ld, errno_s); } static void -cli_run_kore(void *arg) +cli_compile_kore(void *arg) { - char *args[4], *cpath; + struct buildopt *bopt = arg; + int idx, i, fcnt; + char *obj, *args[16], pwd[MAXPATHLEN], *flavors[7]; - (void)cli_vasprintf(&cpath, "conf/%s.conf", appl); + if (getcwd(pwd, sizeof(pwd)) == NULL) + cli_fatal("could not get cwd: %s", errno_s); - args[0] = "kore"; - args[1] = "-fnrc"; - args[2] = cpath; - args[3] = NULL; + (void)cli_vasprintf(&obj, "OBJDIR=%s/.objs", pwd); - execvp("kore", args); + if (putenv(obj) != 0) + cli_fatal("cannot set OBJDIR for building kore"); + + if (putenv("CFLAGS=-DKORE_SINGLE_BINARY") != 0) + cli_fatal("cannot set CFLAGS for building kore"); + + fcnt = kore_split_string(bopt->kore_flavor, " ", flavors, 7); + +#if defined(OpenBSD) || defined(__FreeBSD_version) || \ + defined(NetBSD) || defined(__DragonFly_version) + args[0] = "gmake"; +#else + args[0] = "make"; +#endif + + args[1] = "-s"; + args[2] = "-C"; + args[3] = bopt->kore_source; + args[4] = "objects"; + + idx = 5; + for (i = 0; i < fcnt; i++) { + printf("using flavor %s\n", flavors[i]); + args[idx++] = flavors[i]; + } + + args[idx] = NULL; + + execvp(args[0], args); + cli_fatal("failed to start '%s': %s", args[0], errno_s); +} + +static void +cli_run_kore(void) +{ + struct buildopt *bopt; + char *args[4], *cpath, *cmd, *flags; + + bopt = cli_buildopt_default(); + + if (bopt->single_binary) { + cpath = NULL; + flags = "-fnr"; + (void)cli_vasprintf(&cmd, "./%s", appl); + } else { + cmd = "kore"; + flags = "-fnrc"; + (void)cli_vasprintf(&cpath, "conf/%s.conf", appl); + } + + args[0] = cmd; + args[1] = flags; + + if (cpath != NULL) { + args[2] = cpath; + args[3] = NULL; + } else { + args[2] = NULL; + } + + execvp(args[0], args); + cli_fatal("failed to start '%s': %s", args[0], errno_s); } static void @@ -1142,8 +1297,14 @@ parse_option: cli_buildopt_cxxflags(bopt, t); } else if (!strcasecmp(p, "ldflags")) { cli_buildopt_ldflags(bopt, t); + } else if (!strcasecmp(p, "single_binary")) { + cli_buildopt_single_binary(bopt, t); + } else if (!strcasecmp(p, "kore_source")) { + cli_buildopt_kore_source(bopt, t); + } else if (!strcasecmp(p, "kore_flavor")) { + cli_buildopt_kore_flavor(bopt, t); } else { - printf("ignoring unknown option %s\n", p); + printf("ignoring unknown option '%s'\n", p); } } } @@ -1157,6 +1318,9 @@ cli_buildopt_new(const char *name) bopt->cflags = NULL; bopt->cxxflags = NULL; bopt->ldflags = NULL; + bopt->single_binary = 0; + bopt->kore_source = NULL; + bopt->kore_flavor = NULL; bopt->name = kore_strdup(name); TAILQ_INSERT_TAIL(&build_options, bopt, list); @@ -1176,6 +1340,17 @@ cli_buildopt_find(const char *name) return (NULL); } +static struct buildopt * +cli_buildopt_default(void) +{ + struct buildopt *bopt; + + if ((bopt = cli_buildopt_find("_default")) == NULL) + fatal("no _default buildopt options"); + + return (bopt); +} + static void cli_buildopt_cleanup(void) { @@ -1191,6 +1366,10 @@ cli_buildopt_cleanup(void) kore_buf_free(bopt->cxxflags); if (bopt->ldflags != NULL) kore_buf_free(bopt->ldflags); + if (bopt->kore_source != NULL) + kore_mem_free(bopt->kore_source); + if (bopt->kore_flavor != NULL) + kore_mem_free(bopt->kore_flavor); kore_mem_free(bopt); } } @@ -1198,10 +1377,8 @@ cli_buildopt_cleanup(void) static void cli_buildopt_cflags(struct buildopt *bopt, const char *string) { - if (bopt == NULL) { - if ((bopt = cli_buildopt_find("_default")) == NULL) - cli_fatal("no _default build options"); - } + if (bopt == NULL) + bopt = cli_buildopt_default(); if (bopt->cflags == NULL) bopt->cflags = kore_buf_create(128); @@ -1212,10 +1389,8 @@ cli_buildopt_cflags(struct buildopt *bopt, const char *string) static void cli_buildopt_cxxflags(struct buildopt *bopt, const char *string) { - if (bopt == NULL) { - if ((bopt = cli_buildopt_find("_default")) == NULL) - cli_fatal("no _default build options"); - } + if (bopt == NULL) + bopt = cli_buildopt_default(); if (bopt->cxxflags == NULL) bopt->cxxflags = kore_buf_create(128); @@ -1226,10 +1401,8 @@ cli_buildopt_cxxflags(struct buildopt *bopt, const char *string) static void cli_buildopt_ldflags(struct buildopt *bopt, const char *string) { - if (bopt == NULL) { - if ((bopt = cli_buildopt_find("_default")) == NULL) - cli_fatal("no _default build options"); - } + if (bopt == NULL) + bopt = cli_buildopt_default(); if (bopt->ldflags == NULL) bopt->ldflags = kore_buf_create(128); @@ -1237,6 +1410,48 @@ cli_buildopt_ldflags(struct buildopt *bopt, const char *string) kore_buf_appendf(bopt->ldflags, "%s ", string); } +static void +cli_buildopt_single_binary(struct buildopt *bopt, const char *string) +{ + if (bopt == NULL) + bopt = cli_buildopt_default(); + else + cli_fatal("single_binary only supported in global context"); + + if (!strcmp(string, "yes")) + bopt->single_binary = 1; + else + bopt->single_binary = 0; +} + +static void +cli_buildopt_kore_source(struct buildopt *bopt, const char *string) +{ + if (bopt == NULL) + bopt = cli_buildopt_default(); + else + cli_fatal("kore_source only supported in global context"); + + if (bopt->kore_source != NULL) + kore_mem_free(bopt->kore_source); + + bopt->kore_source = kore_strdup(string); +} + +static void +cli_buildopt_kore_flavor(struct buildopt *bopt, const char *string) +{ + if (bopt == NULL) + bopt = cli_buildopt_default(); + else + cli_fatal("kore_flavor only supported in global context"); + + if (bopt->kore_flavor != NULL) + kore_mem_free(bopt->kore_flavor); + + bopt->kore_flavor = kore_strdup(string); +} + static void cli_build_flags_common(struct kore_buf* buf) { @@ -1282,6 +1497,9 @@ cli_build_cflags(struct buildopt *bopt) obopt->cflags->offset); } + if (bopt->single_binary) + kore_buf_appendf(bopt->cflags, "-DKORE_SINGLE_BINARY"); + string = kore_buf_stringify(bopt->cflags, NULL); printf("CFLAGS=%s\n", string); cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX); @@ -1324,12 +1542,14 @@ cli_build_ldflags(struct buildopt *bopt) if (bopt->ldflags == NULL) bopt->ldflags = kore_buf_create(128); + if (bopt->single_binary == 0) { #if defined(__MACH__) - kore_buf_appendf(bopt->ldflags, - "-dynamiclib -undefined suppress -flat_namespace "); + kore_buf_appendf(bopt->ldflags, + "-dynamiclib -undefined suppress -flat_namespace "); #else - kore_buf_appendf(bopt->ldflags, "-shared "); + kore_buf_appendf(bopt->ldflags, "-shared "); #endif + } if (obopt != NULL && obopt->ldflags != NULL) { kore_buf_append(bopt->ldflags, obopt->ldflags->data, @@ -1351,6 +1571,9 @@ cli_flavor_load(void) cli_fatal("could not get cwd: %s", errno_s); appl = basename(pwd); + if (appl == NULL) + cli_fatal("basename: %s", errno_s); + appl = kore_strdup(appl); (void)cli_vasprintf(&conf, "conf/%s.conf", appl); if (!cli_dir_exists("conf") || !cli_file_exists(conf)) diff --git a/src/config.c b/src/config.c index a8e0aeb..bfee9d3 100644 --- a/src/config.c +++ b/src/config.c @@ -14,6 +14,7 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include @@ -36,9 +37,16 @@ /* XXX - This is becoming a clusterfuck. Fix it. */ +#if !defined(KORE_SINGLE_BINARY) +static int configure_load(char *); +#else +static FILE *config_file_write(void); +extern u_int8_t asset_builtin_kore_conf[]; +extern u_int32_t asset_len_builtin_kore_conf; +#endif + static int configure_include(char *); static int configure_bind(char *); -static int configure_load(char *); static int configure_domain(char *); static int configure_chroot(char *); static int configure_runas(char *); @@ -100,7 +108,9 @@ static struct { } config_names[] = { { "include", configure_include }, { "bind", configure_bind }, +#if !defined(KORE_SINGLE_BINARY) { "load", configure_load }, +#endif { "domain", configure_domain }, { "chroot", configure_chroot }, { "runas", configure_runas }, @@ -150,7 +160,9 @@ static struct { { NULL, NULL }, }; +#if !defined(KORE_SINGLE_BINARY) char *config_file = NULL; +#endif #if !defined(KORE_NO_HTTP) static u_int8_t current_method = 0; @@ -158,15 +170,20 @@ static struct kore_auth *current_auth = NULL; static struct kore_module_handle *current_handler = NULL; #endif +extern const char *__progname; static struct kore_domain *current_domain = NULL; void kore_parse_config(void) { +#if !defined(KORE_SINGLE_BINARY) kore_parse_config_file(config_file); +#else + kore_parse_config_file(NULL); +#endif if (!kore_module_loaded()) - fatal("no site module was loaded"); + fatal("no application module was loaded"); if (skip_chroot != 1 && chroot_path == NULL) { fatal("missing a chroot path"); @@ -192,8 +209,12 @@ kore_parse_config_file(const char *fpath) int i, lineno; char buf[BUFSIZ], *p, *t; +#if !defined(KORE_SINGLE_BINARY) if ((fp = fopen(fpath, "r")) == NULL) fatal("configuration given cannot be opened: %s", fpath); +#else + fp = config_file_write(); +#endif kore_debug("parsing configuration file '%s'", fpath); @@ -282,6 +303,7 @@ configure_bind(char *options) return (kore_server_bind(argv[0], argv[1], argv[2])); } +#if !defined(KORE_SINGLE_BINARY) static int configure_load(char *options) { @@ -294,6 +316,46 @@ configure_load(char *options) kore_module_load(argv[0], argv[1]); return (KORE_RESULT_OK); } +#else +static FILE * +config_file_write(void) +{ + FILE *fp; + ssize_t ret; + int fd, len; + char fpath[MAXPATHLEN]; + + len = snprintf(fpath, sizeof(fpath), "/tmp/%s.XXXXXX", __progname); + if (len == -1 || (size_t)len >= sizeof(fpath)) + fatal("failed to create temporary path"); + + if ((fd = mkstemp(fpath)) == -1) + fatal("mkstemp(%s): %s", fpath, errno_s); + + (void)unlink(fpath); + + for (;;) { + ret = write(fd, asset_builtin_kore_conf, + asset_len_builtin_kore_conf); + if (ret == -1) { + if (errno == EINTR) + continue; + fatal("failed to write temporary config: %s", errno_s); + } + + if ((size_t)ret != asset_len_builtin_kore_conf) + fatal("failed to write temporary config"); + break; + } + + if ((fp = fdopen(fd, "w+")) == NULL) + fatal("fdopen(): %s", errno_s); + + rewind(fp); + + return (fp); +} +#endif #if !defined(KORE_NO_TLS) static int diff --git a/src/kore.c b/src/kore.c index 4f48a58..91140d3 100644 --- a/src/kore.c +++ b/src/kore.c @@ -47,6 +47,8 @@ u_int32_t kore_socket_backlog = 5000; char *kore_pidfile = KORE_PIDFILE_DEFAULT; char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST; +extern char *__progname; + static void usage(void); static void version(void); static void kore_server_start(void); @@ -56,24 +58,37 @@ static void kore_server_sslstart(void); static void usage(void) { +#if !defined(KORE_SINGLE_BINARY) fprintf(stderr, "Usage: kore [options | command]\n"); +#else + fprintf(stderr, "Usage: %s [options]\n", __progname); +#endif fprintf(stderr, "\n"); fprintf(stderr, "Available options:\n"); - fprintf(stderr, "\t-c\tspecify the configuration file to use\n"); - fprintf(stderr, "\t-d\trun with debug on (if compiled in)\n"); - fprintf(stderr, "\t-f\tstart kore in foreground mode\n"); +#if !defined(KORE_SINGLE_BINARY) + fprintf(stderr, "\t-c\tconfiguration to use\n"); +#endif +#if defined(KORE_DEBUG) + fprintf(stderr, "\t-d\trun with debug on)\n"); +#endif + fprintf(stderr, "\t-f\tstart in foreground\n"); fprintf(stderr, "\t-h\tthis help text\n"); fprintf(stderr, "\t-n\tdo not chroot\n"); - fprintf(stderr, "\t-r\tdo not drop privs\n"); - fprintf(stderr, "\t-v\tdisplay kore's version information\n"); + fprintf(stderr, "\t-r\tdo not drop privileges\n"); + fprintf(stderr, "\t-v\tdisplay kore build information\n"); +#if !defined(KORE_SINGLE_BINARY) kore_cli_usage(0); +#else + fprintf(stderr, "\nbuilt with https://kore.io\n"); + exit(1); +#endif } static void version(void) { - printf("kore %d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, + printf("%d.%d.%d-%s ", KORE_VERSION_MAJOR, KORE_VERSION_MINOR, KORE_VERSION_PATCH, KORE_VERSION_STATE); #if defined(KORE_NO_TLS) printf("no-tls "); @@ -89,6 +104,9 @@ version(void) #endif #if defined(KORE_DEBUG) printf("debug "); +#endif +#if defined(KORE_SINGLE_BINARY) + printf("single "); #endif printf("\n"); @@ -99,22 +117,29 @@ int main(int argc, char *argv[]) { int ch, flags; +#if defined(KORE_SINGLE_BINARY) + void (*kmain)(void); +#endif flags = 0; +#if !defined(KORE_SINGLE_BINARY) while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) { +#else + while ((ch = getopt(argc, argv, "dfhnrv")) != -1) { +#endif flags++; switch (ch) { +#if !defined(KORE_SINGLE_BINARY) case 'c': config_file = optarg; break; - case 'd': -#if defined(KORE_DEBUG) - kore_debug = 1; -#else - printf("kore not compiled with debug support\n"); #endif +#if defined(KORE_DEBUG) + case 'd': + kore_debug = 1; break; +#endif case 'f': foreground = 1; break; @@ -140,11 +165,13 @@ main(int argc, char *argv[]) kore_mem_init(); +#if !defined(KORE_SINGLE_BINARY) if (argc > 0) { if (flags) fatal("You cannot specify kore flags and a command"); return (kore_cli_main(argc, argv)); } +#endif kore_pid = getpid(); nlisteners = 0; @@ -159,8 +186,15 @@ main(int argc, char *argv[]) kore_module_init(); kore_server_sslstart(); +#if !defined(KORE_SINGLE_BINARY) if (config_file == NULL) usage(); +#else + kore_module_load(NULL, NULL); + *(void **)&(kmain) = kore_module_getsym("kore_main"); + if (kmain != NULL) + kmain(); +#endif kore_parse_config(); kore_platform_init(); @@ -380,7 +414,7 @@ kore_server_start(void) if (!foreground) kore_write_kore_pid(); - kore_log(LOG_NOTICE, "kore is starting up"); + kore_log(LOG_NOTICE, "%s is starting up", __progname); #if defined(KORE_USE_PGSQL) kore_log(LOG_NOTICE, "pgsql built-in enabled"); #endif @@ -407,8 +441,10 @@ kore_server_start(void) if (sig_recv != 0) { switch (sig_recv) { case SIGHUP: +#if !defined(KORE_SINGLE_BINARY) kore_worker_dispatch_signal(sig_recv); kore_module_reload(0); +#endif break; case SIGINT: case SIGQUIT: diff --git a/src/module.c b/src/module.c index 45d270b..79c74f7 100644 --- a/src/module.c +++ b/src/module.c @@ -46,19 +46,27 @@ kore_module_cleanup(void) void kore_module_load(const char *path, const char *onload) { +#if !defined(KORE_SINGLE_BINARY) struct stat st; +#endif struct kore_module *module; kore_debug("kore_module_load(%s, %s)", path, onload); + module = kore_malloc(sizeof(struct kore_module)); + module->onload = NULL; + module->ocb = NULL; + +#if !defined(KORE_SINGLE_BINARY) if (stat(path, &st) == -1) fatal("stat(%s): %s", path, errno_s); - module = kore_malloc(sizeof(struct kore_module)); module->path = kore_strdup(path); module->mtime = st.st_mtime; - module->onload = NULL; - module->ocb = NULL; +#else + module->path = NULL; + module->mtime = 0; +#endif module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); if (module->handle == NULL) @@ -77,6 +85,7 @@ kore_module_load(const char *path, const char *onload) void kore_module_onload(void) { +#if !defined(KORE_SINGLE_BINARY) struct kore_module *module; TAILQ_FOREACH(module, &modules, list) { @@ -85,11 +94,13 @@ kore_module_onload(void) (void)module->ocb(KORE_MODULE_LOAD); } +#endif } void kore_module_reload(int cbs) { +#if !defined(KORE_SINGLE_BINARY) struct stat st; struct kore_domain *dom; struct kore_module_handle *hdlr; @@ -148,6 +159,7 @@ kore_module_reload(int cbs) #if !defined(KORE_NO_HTTP) kore_validator_reload(); #endif +#endif } int diff --git a/src/utils.c b/src/utils.c index 5597758..622eee1 100644 --- a/src/utils.c +++ b/src/utils.c @@ -521,8 +521,8 @@ kore_text_trim(char *string, size_t len) if (len == 0) return (string); - end = string + len; - while (isspace(*string)) + end = (string + len) - 1; + while (isspace(*string) && string < end) string++; while (isspace(*end) && end > string) @@ -561,8 +561,9 @@ kore_read_line(FILE *fp, char *in, size_t len) void fatal(const char *fmt, ...) { - va_list args; - char buf[2048]; + va_list args; + char buf[2048]; + extern const char *__progname; va_start(args, fmt); (void)vsnprintf(buf, sizeof(buf), fmt, args); @@ -576,6 +577,6 @@ fatal(const char *fmt, ...) kore_keymgr_cleanup(); #endif - printf("kore: %s\n", buf); + printf("%s: %s\n", __progname, buf); exit(1); } diff --git a/src/worker.c b/src/worker.c index a046fef..efb43b1 100644 --- a/src/worker.c +++ b/src/worker.c @@ -333,7 +333,9 @@ kore_worker_entry(struct kore_worker *kw) if (sig_recv != 0) { switch (sig_recv) { case SIGHUP: +#if !defined(KORE_SINGLE_BINARY) kore_module_reload(1); +#endif break; case SIGQUIT: case SIGINT: