Allow "kore build" to produce single binaries.

Producing single binaries can now be done with building with
"kore build". To get started edit your build.conf and add the
following directives:

single_binary = yes
kore_source = /path/to/kore

optionally you can add kore_flavor to instruct how kore should
be built:

kore_flavor = NOTLS=1

When doing this your build.conf must also include the correct
linking options as the linking is now done fully by kore build.

The binary produced will include your configuration and takes
over a few of kore its command line flags (such as -f, -n or -r).
This commit is contained in:
Joris Vink 2016-07-06 16:16:15 +02:00
parent 7ac1ea379d
commit 39a5f21986
9 changed files with 431 additions and 80 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@ kore
*.module *.module
*.DSYM *.DSYM
cert cert
obj

View File

@ -2,6 +2,7 @@
CC?=gcc CC?=gcc
PREFIX?=/usr/local PREFIX?=/usr/local
OBJDIR?=obj
KORE=kore KORE=kore
INSTALL_DIR=$(PREFIX)/bin INSTALL_DIR=$(PREFIX)/bin
INCLUDE_DIR=$(PREFIX)/include/kore 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 \ 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/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 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+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes
CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual
@ -70,11 +70,18 @@ else
S_SRC+=src/bsd.c S_SRC+=src/bsd.c
endif endif
$(KORE): $(S_OBJS) S_OBJS= $(S_SRC:src/%.c=$(OBJDIR)/%.o)
$(KORE): $(OBJDIR) $(S_OBJS)
$(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE) $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE)
objects: $(OBJDIR) $(S_OBJS)
all: $(KORE) all: $(KORE)
$(OBJDIR):
@mkdir -p $(OBJDIR)
install: install:
mkdir -p $(INCLUDE_DIR) mkdir -p $(INCLUDE_DIR)
mkdir -p $(INSTALL_DIR) mkdir -p $(INSTALL_DIR)
@ -85,11 +92,11 @@ uninstall:
rm -f $(INSTALL_DIR)/$(KORE) rm -f $(INSTALL_DIR)/$(KORE)
rm -rf $(INCLUDE_DIR) rm -rf $(INCLUDE_DIR)
.c.o: $(OBJDIR)/%.o: src/%.c
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
clean: clean:
find . -type f -name \*.o -exec rm {} \; find . -type f -name \*.o -exec rm {} \;
rm -f $(KORE) rm -rf $(KORE) $(OBJDIR)
.PHONY: all clean .PHONY: all clean

View File

@ -399,6 +399,10 @@ struct kore_keyreq {
}; };
#endif #endif
#if !defined(KORE_SINGLE_BINARY)
extern char *config_file;
#endif
extern pid_t kore_pid; extern pid_t kore_pid;
extern int foreground; extern int foreground;
extern int kore_debug; extern int kore_debug;
@ -407,7 +411,6 @@ extern char *chroot_path;
extern int skip_runas; extern int skip_runas;
extern char *runas_user; extern char *runas_user;
extern char *kore_pidfile; extern char *kore_pidfile;
extern char *config_file;
extern char *kore_tls_cipher_list; extern char *kore_tls_cipher_list;
extern int tls_version; 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_run(void);
void kore_keymgr_cleanup(void); void kore_keymgr_cleanup(void);
#if defined(KORE_SINGLE_BINARY)
void kore_main(void);
#endif
#if defined(__cplusplus) #if defined(__cplusplus)
} }
#endif #endif

329
src/cli.c
View File

@ -68,6 +68,9 @@
struct buildopt { struct buildopt {
char *name; char *name;
char *kore_source;
char *kore_flavor;
int single_binary;
struct kore_buf *cflags; struct kore_buf *cflags;
struct kore_buf *cxxflags; struct kore_buf *cxxflags;
struct kore_buf *ldflags; struct kore_buf *ldflags;
@ -99,9 +102,10 @@ TAILQ_HEAD(cfile_list, cfile);
static void cli_fatal(const char *, ...) __attribute__((noreturn)); static void cli_fatal(const char *, ...) __attribute__((noreturn));
static void cli_file_close(int); 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_generate_certs(void);
static void cli_link_library(void *); static void cli_link_library(void *);
static void cli_compile_kore(void *);
static void cli_compile_source_file(void *); static void cli_compile_source_file(void *);
static void cli_mkdir(const char *, int); static void cli_mkdir(const char *, int);
static int cli_dir_exists(const char *); 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 int cli_vasprintf(char **, const char *, ...);
static void cli_spawn_proc(void (*cb)(void *), void *); static void cli_spawn_proc(void (*cb)(void *), void *);
static void cli_write_asset(const char *, const char *); 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_register_source_file(char *, struct dirent *);
static void cli_file_create(const char *, const char *, size_t); static void cli_file_create(const char *, const char *, size_t);
static int cli_file_requires_build(struct stat *, const char *); 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 *, static void cli_add_source_file(char *, char *, char *,
struct stat *, int); struct stat *, int);
static struct buildopt *cli_buildopt_default(void);
static struct buildopt *cli_buildopt_new(const char *); static struct buildopt *cli_buildopt_new(const char *);
static struct buildopt *cli_buildopt_find(const char *); static struct buildopt *cli_buildopt_find(const char *);
static void cli_buildopt_cleanup(void); 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_cflags(struct buildopt *, const char *);
static void cli_buildopt_cxxflags(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_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_load(void);
static void cli_flavor_change(const char *); static void cli_flavor_change(const char *);
@ -209,6 +221,14 @@ static const char *build_data =
"# %s build config\n" "# %s build config\n"
"# You can switch flavors using: kore flavor [newflavor]\n" "# You can switch flavors using: kore flavor [newflavor]\n"
"\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" "# The flags below are shared between flavors\n"
"cflags=-Wall -Wmissing-declarations -Wshadow\n" "cflags=-Wall -Wmissing-declarations -Wshadow\n"
"cflags=-Wstrict-prototypes -Wmissing-prototypes\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 int s_fd = -1;
static char *appl = NULL; static char *appl = NULL;
static int run_after = 0;
static char *rootdir = NULL; static char *rootdir = NULL;
static char *compiler_c = "gcc"; static char *compiler_c = "gcc";
static char *compiler_cpp = "g++"; static char *compiler_cpp = "g++";
@ -393,6 +414,7 @@ cli_flavor(int argc, char **argv)
static void static void
cli_build(int argc, char **argv) cli_build(int argc, char **argv)
{ {
struct dirent dp;
struct cfile *cf; struct cfile *cf;
struct buildopt *bopt; struct buildopt *bopt;
struct timeval times[2]; struct timeval times[2];
@ -427,7 +449,6 @@ cli_build(int argc, char **argv)
if (!cli_dir_exists(src_path) || !cli_file_exists(config)) if (!cli_dir_exists(src_path) || !cli_file_exists(config))
cli_fatal("%s doesn't appear to be a kore app", appl); cli_fatal("%s doesn't appear to be a kore app", appl);
free(config);
cli_flavor_load(); cli_flavor_load();
bopt = cli_buildopt_new("_default"); bopt = cli_buildopt_new("_default");
@ -437,38 +458,62 @@ cli_build(int argc, char **argv)
free(data); free(data);
} }
cli_buildopt_parse(build_path);
free(build_path);
/* Build all source files. */
cli_find_files(src_path, cli_register_source_file); cli_find_files(src_path, cli_register_source_file);
free(src_path); free(src_path);
printf("building %s (%s)\n", appl, flavor); cli_buildopt_parse(build_path);
cli_build_cflags(bopt); free(build_path);
cli_build_cxxflags(bopt);
cli_build_ldflags(bopt);
(void)cli_vasprintf(&obj_path, "%s/.objs", rootdir); (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir);
if (!cli_dir_exists(obj_path)) if (!cli_dir_exists(obj_path))
cli_mkdir(obj_path, 0755); cli_mkdir(obj_path, 0755);
free(obj_path); 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); (void)unlink(assets_header);
/* Generate the assets. */ /* 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, cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n");
O_CREAT | O_TRUNC | O_WRONLY, &s_fd); cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n");
cli_file_writef(s_fd, "#ifndef __H_KORE_ASSETS_H\n"); if (cli_dir_exists(assets_path))
cli_file_writef(s_fd, "#define __H_KORE_ASSETS_H\n");
cli_find_files(assets_path, cli_build_asset); 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(assets_path);
free(config);
if (cxx_files_count > 0)
compiler_ld = compiler_cpp;
requires_relink = 0; requires_relink = 0;
TAILQ_FOREACH(cf, &source_files, list) { TAILQ_FOREACH(cf, &source_files, list) {
@ -485,10 +530,6 @@ cli_build(int argc, char **argv)
if (utimes(cf->opath, times) == -1) if (utimes(cf->opath, times) == -1)
printf("utime(%s): %s\n", cf->opath, errno_s); printf("utime(%s): %s\n", cf->opath, errno_s);
if (cf->build == BUILD_CXX) {
compiler_ld = compiler_cpp;
}
requires_relink++; requires_relink++;
} }
@ -502,18 +543,26 @@ cli_build(int argc, char **argv)
} }
free(cpath); 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)) if (!cli_file_exists(sofile))
requires_relink++; requires_relink++;
free(sofile); free(sofile);
if (requires_relink) { if (requires_relink) {
cli_spawn_proc(cli_link_library, NULL); cli_spawn_proc(cli_link_library, bopt);
printf("%s built successfully!\n", appl); printf("%s built successfully!\n", appl);
} else { } else {
printf("nothing to be done!\n"); printf("nothing to be done!\n");
} }
cli_buildopt_cleanup();
if (run_after == 0)
cli_buildopt_cleanup();
} }
static void static void
@ -538,6 +587,7 @@ cli_clean(int argc, char **argv)
static void static void
cli_run(int argc, char **argv) cli_run(int argc, char **argv)
{ {
run_after = 1;
cli_build(argc, argv); cli_build(argc, argv);
if (chdir(rootdir) == -1) 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 * We are exec()'ing kore again, while we could technically set
* the right cli options manually and just continue running. * the right cli options manually and just continue running.
*/ */
cli_run_kore(NULL); cli_run_kore();
} }
static void static void
@ -850,12 +900,14 @@ cli_register_source_file(char *fpath, struct dirent *dp)
if (stat(fpath, &st) == -1) if (stat(fpath, &st) == -1)
cli_fatal("stat(%s): %s", fpath, errno_s); 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); (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name);
if (!cli_file_requires_build(&st, opath)) { if (!cli_file_requires_build(&st, opath)) {
build = BUILD_NOBUILD; build = BUILD_NOBUILD;
} else if (!strcmp(ext, ".cpp")) { } else if (!strcmp(ext, ".cpp")) {
build = BUILD_CXX; build = BUILD_CXX;
cxx_files_count++;
} else { } else {
build = BUILD_C; 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); 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 static void
cli_file_remove(char *fpath, struct dirent *dp) cli_file_remove(char *fpath, struct dirent *dp)
{ {
@ -1049,17 +1128,24 @@ cli_compile_source_file(void *arg)
args[idx] = NULL; args[idx] = NULL;
execvp(compiler, args); execvp(compiler, args);
cli_fatal("failed to start '%s': %s", compiler, errno_s);
} }
static void static void
cli_link_library(void *arg) cli_link_library(void *arg)
{ {
struct cfile *cf; struct cfile *cf;
struct buildopt *bopt;
int idx, i; int idx, i;
char *libname; char *output;
char *args[source_files_count + 11 + LD_FLAGS_MAX]; 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; idx = 0;
args[idx++] = compiler_ld; args[idx++] = compiler_ld;
@ -1070,26 +1156,95 @@ cli_link_library(void *arg)
for (i = 0; i < ldflags_count; i++) for (i = 0; i < ldflags_count; i++)
args[idx++] = ldflags[i]; args[idx++] = ldflags[i];
if (bopt->single_binary) {
args[idx++] = "-rdynamic";
#if defined(__linux__)
args[idx++] = "-ldl";
#endif
}
args[idx++] = "-o"; args[idx++] = "-o";
args[idx++] = libname; args[idx++] = output;
args[idx] = NULL; args[idx] = NULL;
execvp(compiler_ld, args); execvp(compiler_ld, args);
cli_fatal("failed to start '%s': %s", compiler_ld, errno_s);
} }
static void 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"; (void)cli_vasprintf(&obj, "OBJDIR=%s/.objs", pwd);
args[1] = "-fnrc";
args[2] = cpath;
args[3] = NULL;
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 static void
@ -1142,8 +1297,14 @@ parse_option:
cli_buildopt_cxxflags(bopt, t); cli_buildopt_cxxflags(bopt, t);
} else if (!strcasecmp(p, "ldflags")) { } else if (!strcasecmp(p, "ldflags")) {
cli_buildopt_ldflags(bopt, t); 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 { } 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->cflags = NULL;
bopt->cxxflags = NULL; bopt->cxxflags = NULL;
bopt->ldflags = NULL; bopt->ldflags = NULL;
bopt->single_binary = 0;
bopt->kore_source = NULL;
bopt->kore_flavor = NULL;
bopt->name = kore_strdup(name); bopt->name = kore_strdup(name);
TAILQ_INSERT_TAIL(&build_options, bopt, list); TAILQ_INSERT_TAIL(&build_options, bopt, list);
@ -1176,6 +1340,17 @@ cli_buildopt_find(const char *name)
return (NULL); 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 static void
cli_buildopt_cleanup(void) cli_buildopt_cleanup(void)
{ {
@ -1191,6 +1366,10 @@ cli_buildopt_cleanup(void)
kore_buf_free(bopt->cxxflags); kore_buf_free(bopt->cxxflags);
if (bopt->ldflags != NULL) if (bopt->ldflags != NULL)
kore_buf_free(bopt->ldflags); 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); kore_mem_free(bopt);
} }
} }
@ -1198,10 +1377,8 @@ cli_buildopt_cleanup(void)
static void static void
cli_buildopt_cflags(struct buildopt *bopt, const char *string) cli_buildopt_cflags(struct buildopt *bopt, const char *string)
{ {
if (bopt == NULL) { if (bopt == NULL)
if ((bopt = cli_buildopt_find("_default")) == NULL) bopt = cli_buildopt_default();
cli_fatal("no _default build options");
}
if (bopt->cflags == NULL) if (bopt->cflags == NULL)
bopt->cflags = kore_buf_create(128); bopt->cflags = kore_buf_create(128);
@ -1212,10 +1389,8 @@ cli_buildopt_cflags(struct buildopt *bopt, const char *string)
static void static void
cli_buildopt_cxxflags(struct buildopt *bopt, const char *string) cli_buildopt_cxxflags(struct buildopt *bopt, const char *string)
{ {
if (bopt == NULL) { if (bopt == NULL)
if ((bopt = cli_buildopt_find("_default")) == NULL) bopt = cli_buildopt_default();
cli_fatal("no _default build options");
}
if (bopt->cxxflags == NULL) if (bopt->cxxflags == NULL)
bopt->cxxflags = kore_buf_create(128); bopt->cxxflags = kore_buf_create(128);
@ -1226,10 +1401,8 @@ cli_buildopt_cxxflags(struct buildopt *bopt, const char *string)
static void static void
cli_buildopt_ldflags(struct buildopt *bopt, const char *string) cli_buildopt_ldflags(struct buildopt *bopt, const char *string)
{ {
if (bopt == NULL) { if (bopt == NULL)
if ((bopt = cli_buildopt_find("_default")) == NULL) bopt = cli_buildopt_default();
cli_fatal("no _default build options");
}
if (bopt->ldflags == NULL) if (bopt->ldflags == NULL)
bopt->ldflags = kore_buf_create(128); 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); 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 static void
cli_build_flags_common(struct kore_buf* buf) cli_build_flags_common(struct kore_buf* buf)
{ {
@ -1282,6 +1497,9 @@ cli_build_cflags(struct buildopt *bopt)
obopt->cflags->offset); obopt->cflags->offset);
} }
if (bopt->single_binary)
kore_buf_appendf(bopt->cflags, "-DKORE_SINGLE_BINARY");
string = kore_buf_stringify(bopt->cflags, NULL); string = kore_buf_stringify(bopt->cflags, NULL);
printf("CFLAGS=%s\n", string); printf("CFLAGS=%s\n", string);
cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX); cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX);
@ -1324,12 +1542,14 @@ cli_build_ldflags(struct buildopt *bopt)
if (bopt->ldflags == NULL) if (bopt->ldflags == NULL)
bopt->ldflags = kore_buf_create(128); bopt->ldflags = kore_buf_create(128);
if (bopt->single_binary == 0) {
#if defined(__MACH__) #if defined(__MACH__)
kore_buf_appendf(bopt->ldflags, kore_buf_appendf(bopt->ldflags,
"-dynamiclib -undefined suppress -flat_namespace "); "-dynamiclib -undefined suppress -flat_namespace ");
#else #else
kore_buf_appendf(bopt->ldflags, "-shared "); kore_buf_appendf(bopt->ldflags, "-shared ");
#endif #endif
}
if (obopt != NULL && obopt->ldflags != NULL) { if (obopt != NULL && obopt->ldflags != NULL) {
kore_buf_append(bopt->ldflags, obopt->ldflags->data, 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); cli_fatal("could not get cwd: %s", errno_s);
appl = basename(pwd); appl = basename(pwd);
if (appl == NULL)
cli_fatal("basename: %s", errno_s);
appl = kore_strdup(appl);
(void)cli_vasprintf(&conf, "conf/%s.conf", appl); (void)cli_vasprintf(&conf, "conf/%s.conf", appl);
if (!cli_dir_exists("conf") || !cli_file_exists(conf)) if (!cli_dir_exists("conf") || !cli_file_exists(conf))

View File

@ -14,6 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <stdio.h> #include <stdio.h>
@ -36,9 +37,16 @@
/* XXX - This is becoming a clusterfuck. Fix it. */ /* 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_include(char *);
static int configure_bind(char *); static int configure_bind(char *);
static int configure_load(char *);
static int configure_domain(char *); static int configure_domain(char *);
static int configure_chroot(char *); static int configure_chroot(char *);
static int configure_runas(char *); static int configure_runas(char *);
@ -100,7 +108,9 @@ static struct {
} config_names[] = { } config_names[] = {
{ "include", configure_include }, { "include", configure_include },
{ "bind", configure_bind }, { "bind", configure_bind },
#if !defined(KORE_SINGLE_BINARY)
{ "load", configure_load }, { "load", configure_load },
#endif
{ "domain", configure_domain }, { "domain", configure_domain },
{ "chroot", configure_chroot }, { "chroot", configure_chroot },
{ "runas", configure_runas }, { "runas", configure_runas },
@ -150,7 +160,9 @@ static struct {
{ NULL, NULL }, { NULL, NULL },
}; };
#if !defined(KORE_SINGLE_BINARY)
char *config_file = NULL; char *config_file = NULL;
#endif
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
static u_int8_t current_method = 0; 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; static struct kore_module_handle *current_handler = NULL;
#endif #endif
extern const char *__progname;
static struct kore_domain *current_domain = NULL; static struct kore_domain *current_domain = NULL;
void void
kore_parse_config(void) kore_parse_config(void)
{ {
#if !defined(KORE_SINGLE_BINARY)
kore_parse_config_file(config_file); kore_parse_config_file(config_file);
#else
kore_parse_config_file(NULL);
#endif
if (!kore_module_loaded()) if (!kore_module_loaded())
fatal("no site module was loaded"); fatal("no application module was loaded");
if (skip_chroot != 1 && chroot_path == NULL) { if (skip_chroot != 1 && chroot_path == NULL) {
fatal("missing a chroot path"); fatal("missing a chroot path");
@ -192,8 +209,12 @@ kore_parse_config_file(const char *fpath)
int i, lineno; int i, lineno;
char buf[BUFSIZ], *p, *t; char buf[BUFSIZ], *p, *t;
#if !defined(KORE_SINGLE_BINARY)
if ((fp = fopen(fpath, "r")) == NULL) if ((fp = fopen(fpath, "r")) == NULL)
fatal("configuration given cannot be opened: %s", fpath); fatal("configuration given cannot be opened: %s", fpath);
#else
fp = config_file_write();
#endif
kore_debug("parsing configuration file '%s'", fpath); 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])); return (kore_server_bind(argv[0], argv[1], argv[2]));
} }
#if !defined(KORE_SINGLE_BINARY)
static int static int
configure_load(char *options) configure_load(char *options)
{ {
@ -294,6 +316,46 @@ configure_load(char *options)
kore_module_load(argv[0], argv[1]); kore_module_load(argv[0], argv[1]);
return (KORE_RESULT_OK); 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) #if !defined(KORE_NO_TLS)
static int static int

View File

@ -47,6 +47,8 @@ u_int32_t kore_socket_backlog = 5000;
char *kore_pidfile = KORE_PIDFILE_DEFAULT; char *kore_pidfile = KORE_PIDFILE_DEFAULT;
char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST; char *kore_tls_cipher_list = KORE_DEFAULT_CIPHER_LIST;
extern char *__progname;
static void usage(void); static void usage(void);
static void version(void); static void version(void);
static void kore_server_start(void); static void kore_server_start(void);
@ -56,24 +58,37 @@ static void kore_server_sslstart(void);
static void static void
usage(void) usage(void)
{ {
#if !defined(KORE_SINGLE_BINARY)
fprintf(stderr, "Usage: kore [options | command]\n"); fprintf(stderr, "Usage: kore [options | command]\n");
#else
fprintf(stderr, "Usage: %s [options]\n", __progname);
#endif
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fprintf(stderr, "Available options:\n"); fprintf(stderr, "Available options:\n");
fprintf(stderr, "\t-c\tspecify the configuration file to use\n"); #if !defined(KORE_SINGLE_BINARY)
fprintf(stderr, "\t-d\trun with debug on (if compiled in)\n"); fprintf(stderr, "\t-c\tconfiguration to use\n");
fprintf(stderr, "\t-f\tstart kore in foreground mode\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-h\tthis help text\n");
fprintf(stderr, "\t-n\tdo not chroot\n"); fprintf(stderr, "\t-n\tdo not chroot\n");
fprintf(stderr, "\t-r\tdo not drop privs\n"); fprintf(stderr, "\t-r\tdo not drop privileges\n");
fprintf(stderr, "\t-v\tdisplay kore's version information\n"); fprintf(stderr, "\t-v\tdisplay kore build information\n");
#if !defined(KORE_SINGLE_BINARY)
kore_cli_usage(0); kore_cli_usage(0);
#else
fprintf(stderr, "\nbuilt with https://kore.io\n");
exit(1);
#endif
} }
static void static void
version(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); KORE_VERSION_PATCH, KORE_VERSION_STATE);
#if defined(KORE_NO_TLS) #if defined(KORE_NO_TLS)
printf("no-tls "); printf("no-tls ");
@ -89,6 +104,9 @@ version(void)
#endif #endif
#if defined(KORE_DEBUG) #if defined(KORE_DEBUG)
printf("debug "); printf("debug ");
#endif
#if defined(KORE_SINGLE_BINARY)
printf("single ");
#endif #endif
printf("\n"); printf("\n");
@ -99,22 +117,29 @@ int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
int ch, flags; int ch, flags;
#if defined(KORE_SINGLE_BINARY)
void (*kmain)(void);
#endif
flags = 0; flags = 0;
#if !defined(KORE_SINGLE_BINARY)
while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) { while ((ch = getopt(argc, argv, "c:dfhnrv")) != -1) {
#else
while ((ch = getopt(argc, argv, "dfhnrv")) != -1) {
#endif
flags++; flags++;
switch (ch) { switch (ch) {
#if !defined(KORE_SINGLE_BINARY)
case 'c': case 'c':
config_file = optarg; config_file = optarg;
break; break;
case 'd':
#if defined(KORE_DEBUG)
kore_debug = 1;
#else
printf("kore not compiled with debug support\n");
#endif #endif
#if defined(KORE_DEBUG)
case 'd':
kore_debug = 1;
break; break;
#endif
case 'f': case 'f':
foreground = 1; foreground = 1;
break; break;
@ -140,11 +165,13 @@ main(int argc, char *argv[])
kore_mem_init(); kore_mem_init();
#if !defined(KORE_SINGLE_BINARY)
if (argc > 0) { if (argc > 0) {
if (flags) if (flags)
fatal("You cannot specify kore flags and a command"); fatal("You cannot specify kore flags and a command");
return (kore_cli_main(argc, argv)); return (kore_cli_main(argc, argv));
} }
#endif
kore_pid = getpid(); kore_pid = getpid();
nlisteners = 0; nlisteners = 0;
@ -159,8 +186,15 @@ main(int argc, char *argv[])
kore_module_init(); kore_module_init();
kore_server_sslstart(); kore_server_sslstart();
#if !defined(KORE_SINGLE_BINARY)
if (config_file == NULL) if (config_file == NULL)
usage(); usage();
#else
kore_module_load(NULL, NULL);
*(void **)&(kmain) = kore_module_getsym("kore_main");
if (kmain != NULL)
kmain();
#endif
kore_parse_config(); kore_parse_config();
kore_platform_init(); kore_platform_init();
@ -380,7 +414,7 @@ kore_server_start(void)
if (!foreground) if (!foreground)
kore_write_kore_pid(); 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) #if defined(KORE_USE_PGSQL)
kore_log(LOG_NOTICE, "pgsql built-in enabled"); kore_log(LOG_NOTICE, "pgsql built-in enabled");
#endif #endif
@ -407,8 +441,10 @@ kore_server_start(void)
if (sig_recv != 0) { if (sig_recv != 0) {
switch (sig_recv) { switch (sig_recv) {
case SIGHUP: case SIGHUP:
#if !defined(KORE_SINGLE_BINARY)
kore_worker_dispatch_signal(sig_recv); kore_worker_dispatch_signal(sig_recv);
kore_module_reload(0); kore_module_reload(0);
#endif
break; break;
case SIGINT: case SIGINT:
case SIGQUIT: case SIGQUIT:

View File

@ -46,19 +46,27 @@ kore_module_cleanup(void)
void void
kore_module_load(const char *path, const char *onload) kore_module_load(const char *path, const char *onload)
{ {
#if !defined(KORE_SINGLE_BINARY)
struct stat st; struct stat st;
#endif
struct kore_module *module; struct kore_module *module;
kore_debug("kore_module_load(%s, %s)", path, onload); 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) if (stat(path, &st) == -1)
fatal("stat(%s): %s", path, errno_s); fatal("stat(%s): %s", path, errno_s);
module = kore_malloc(sizeof(struct kore_module));
module->path = kore_strdup(path); module->path = kore_strdup(path);
module->mtime = st.st_mtime; module->mtime = st.st_mtime;
module->onload = NULL; #else
module->ocb = NULL; module->path = NULL;
module->mtime = 0;
#endif
module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL); module->handle = dlopen(module->path, RTLD_NOW | RTLD_GLOBAL);
if (module->handle == NULL) if (module->handle == NULL)
@ -77,6 +85,7 @@ kore_module_load(const char *path, const char *onload)
void void
kore_module_onload(void) kore_module_onload(void)
{ {
#if !defined(KORE_SINGLE_BINARY)
struct kore_module *module; struct kore_module *module;
TAILQ_FOREACH(module, &modules, list) { TAILQ_FOREACH(module, &modules, list) {
@ -85,11 +94,13 @@ kore_module_onload(void)
(void)module->ocb(KORE_MODULE_LOAD); (void)module->ocb(KORE_MODULE_LOAD);
} }
#endif
} }
void void
kore_module_reload(int cbs) kore_module_reload(int cbs)
{ {
#if !defined(KORE_SINGLE_BINARY)
struct stat st; struct stat st;
struct kore_domain *dom; struct kore_domain *dom;
struct kore_module_handle *hdlr; struct kore_module_handle *hdlr;
@ -148,6 +159,7 @@ kore_module_reload(int cbs)
#if !defined(KORE_NO_HTTP) #if !defined(KORE_NO_HTTP)
kore_validator_reload(); kore_validator_reload();
#endif #endif
#endif
} }
int int

View File

@ -521,8 +521,8 @@ kore_text_trim(char *string, size_t len)
if (len == 0) if (len == 0)
return (string); return (string);
end = string + len; end = (string + len) - 1;
while (isspace(*string)) while (isspace(*string) && string < end)
string++; string++;
while (isspace(*end) && end > string) while (isspace(*end) && end > string)
@ -561,8 +561,9 @@ kore_read_line(FILE *fp, char *in, size_t len)
void void
fatal(const char *fmt, ...) fatal(const char *fmt, ...)
{ {
va_list args; va_list args;
char buf[2048]; char buf[2048];
extern const char *__progname;
va_start(args, fmt); va_start(args, fmt);
(void)vsnprintf(buf, sizeof(buf), fmt, args); (void)vsnprintf(buf, sizeof(buf), fmt, args);
@ -576,6 +577,6 @@ fatal(const char *fmt, ...)
kore_keymgr_cleanup(); kore_keymgr_cleanup();
#endif #endif
printf("kore: %s\n", buf); printf("%s: %s\n", __progname, buf);
exit(1); exit(1);
} }

View File

@ -333,7 +333,9 @@ kore_worker_entry(struct kore_worker *kw)
if (sig_recv != 0) { if (sig_recv != 0) {
switch (sig_recv) { switch (sig_recv) {
case SIGHUP: case SIGHUP:
#if !defined(KORE_SINGLE_BINARY)
kore_module_reload(1); kore_module_reload(1);
#endif
break; break;
case SIGQUIT: case SIGQUIT:
case SIGINT: case SIGINT: