kore

An easy to use, scalable and secure web application framework for writing web APIs in C.
Commits | Files | Refs | README | LICENSE | git clone https://git.kore.io/kore.git

commit fc6b3bf7405fd37f7ea0337b11b0bb9ea50e90a1
parent a0c545884fa71d0e37fd24d7d73ebb9fb6bfe833
Author: Joris Vink <joris@coders.se>
Date:   Sun, 19 Feb 2017 00:52:29 -0500

Split up kore cli tools into new binary.

Having the create, build, run tools baked into the kore binary
made things harder then they had to be for multiple projects with
each different build flavors.

So move away this functionality into a new "kodev" (name may change)
binary that is installed next to kore.

The new build tools will automatically pick up the correct flavors
the kore binary it points to is installed with. Or for single builds
what flavors where enabled.

The new tool also will honor looking into PREFIX for the kore binary
when doing a `kodev run`.

Additionally add a new command "info" that shows some basic info
about your project and how it will be built. For example it will
show you the flavors of the kore binary installed on the system
or the flavors you configured for a single binary build.

Obligitory, hacking on a plane comment.

Diffstat:
Makefile | 33+++++++++++++++++++++++----------
includes/http.h | 6+-----
includes/kore.h | 3---
kodev/Makefile | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
src/cli.c | 761++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------
src/http.c | 4++++
src/kore.c | 16++--------------
7 files changed, 584 insertions(+), 292 deletions(-)

diff --git a/Makefile b/Makefile @@ -4,7 +4,9 @@ CC?=gcc PREFIX?=/usr/local OBJDIR?=obj KORE=kore +KODEV=kodev/kodev INSTALL_DIR=$(PREFIX)/bin +SHARE_DIR=$(PREFIX)/share/kore INCLUDE_DIR=$(PREFIX)/include/kore S_SRC= src/kore.c src/buf.c src/config.c src/connection.c \ @@ -13,6 +15,7 @@ S_SRC= src/kore.c src/buf.c src/config.c src/connection.c \ src/keymgr.c FEATURES= +FEATURES_INC= CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual @@ -20,9 +23,7 @@ CFLAGS+=-Wsign-compare -Iincludes -std=c99 -pedantic CFLAGS+=-DPREFIX='"$(PREFIX)"' LDFLAGS=-rdynamic -lssl -lcrypto -ifeq ("$(KORE_SINGLE_BINARY)", "") - S_SRC+=src/cli.c -else +ifneq ("$(KORE_SINGLE_BINARY)", "") CFLAGS+=-DKORE_SINGLE_BINARY FEATURES+=-DKORE_SINGLE_BINARY endif @@ -62,7 +63,8 @@ ifneq ("$(PGSQL)", "") LDFLAGS+=-L$(shell pg_config --libdir) -lpq CFLAGS+=-I$(shell pg_config --includedir) -DKORE_USE_PGSQL \ -DPGSQL_INCLUDE_PATH="\"$(shell pg_config --includedir)\"" - FEATURES+=-I$(shell pg_config --includedir) -DKORE_USE_PGSQL + FEATURES+=-DKORE_USE_PGSQL + FEATURES_INC+=-I$(shell pg_config --includedir) endif ifneq ("$(TASKS)", "") @@ -83,7 +85,8 @@ ifneq ("$(PYTHON)", "") S_SRC+=src/python.c LDFLAGS+=$(shell python3-config --ldflags) CFLAGS+=$(shell python3-config --includes) -DKORE_USE_PYTHON - FEATURES+=$(shell python3-config --includes) -DKORE_USE_PYTHON + FEATURES+=-DKORE_USE_PYTHON + FEATURES_INC+=$(shell python3-config --includes) endif OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) @@ -105,33 +108,43 @@ endif S_OBJS= $(S_SRC:src/%.c=$(OBJDIR)/%.o) +all: $(KORE) $(KODEV) + +$(KODEV): + $(MAKE) -C kodev + $(KORE): $(OBJDIR) $(S_OBJS) $(CC) $(S_OBJS) $(LDFLAGS) -o $(KORE) + @echo $(FEATURES) > kore.features objects: $(OBJDIR) $(S_OBJS) @echo $(LDFLAGS) > $(OBJDIR)/ldflags - @echo $(FEATURES) > $(OBJDIR)/features - -all: $(KORE) + @echo "$(FEATURES) $(FEATURES_INC)" > $(OBJDIR)/features $(OBJDIR): @mkdir -p $(OBJDIR) -install: +install: $(KORE) $(KODEV) + mkdir -p $(SHARE_DIR) mkdir -p $(INCLUDE_DIR) mkdir -p $(INSTALL_DIR) install -m 555 $(KORE) $(INSTALL_DIR)/$(KORE) + install -m 644 kore.features $(SHARE_DIR)/features install -m 644 includes/*.h $(INCLUDE_DIR) + $(MAKE) -C kodev install uninstall: rm -f $(INSTALL_DIR)/$(KORE) rm -rf $(INCLUDE_DIR) + rm -rf $(SHARE_DIR) + $(MAKE) -C kodev uninstall $(OBJDIR)/%.o: src/%.c $(CC) $(CFLAGS) -c $< -o $@ clean: find . -type f -name \*.o -exec rm {} \; - rm -rf $(KORE) $(OBJDIR) + rm -rf $(KORE) $(OBJDIR) kore.features + $(MAKE) -C kodev clean .PHONY: all clean diff --git a/includes/http.h b/includes/http.h @@ -19,10 +19,6 @@ #ifndef __H_HTTP_H #define __H_HTTP_H -#if defined(KORE_USE_PYTHON) -#include "python_api.h" -#endif - #include <sys/types.h> #include <sys/queue.h> @@ -212,7 +208,7 @@ struct http_request { struct kore_module_handle *hdlr; #if defined(KORE_USE_PYTHON) - PyObject *py_coro; + void *py_coro; #endif LIST_HEAD(, kore_task) tasks; diff --git a/includes/kore.h b/includes/kore.h @@ -477,9 +477,6 @@ extern struct kore_domain_h domains; extern struct kore_domain *primary_dom; extern struct kore_pool nb_pool; -void kore_cli_usage(int); -int kore_cli_main(int, char **); - void kore_signal(int); void kore_worker_wait(int); void kore_worker_init(void); diff --git a/kodev/Makefile b/kodev/Makefile @@ -0,0 +1,53 @@ +# kodev Makefile + +CC?=gcc +PREFIX?=/usr/local +OBJDIR?=obj +KODEV=kodev +INSTALL_DIR=$(PREFIX)/bin + +S_SRC= ../src/cli.c + +CFLAGS+=-Wall -Werror -Wstrict-prototypes -Wmissing-prototypes +CFLAGS+=-Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-qual +CFLAGS+=-Wsign-compare -Iincludes -std=c99 -pedantic +CFLAGS+=-DPREFIX='"$(PREFIX)"' +LDFLAGS=-rdynamic -lcrypto + +ifneq ("$(NOOPT)", "") + CFLAGS+=-O0 +else + CFLAGS+=-O2 +endif + +OSNAME=$(shell uname -s | sed -e 's/[-_].*//g' | tr A-Z a-z) +ifeq ("$(OSNAME)", "darwin") + CFLAGS+=-I/opt/local/include/ -I/usr/local/opt/openssl/include + LDFLAGS+=-L/opt/local/lib -L/usr/local/opt/openssl/lib +else ifeq ("$(OSNAME)", "linux") + CFLAGS+=-D_GNU_SOURCE=1 +endif + +S_OBJS= $(S_SRC:../src/%.c=$(OBJDIR)/%.o) + +$(KODEV): $(OBJDIR) $(S_OBJS) + $(CC) $(S_OBJS) $(LDFLAGS) -o $(KODEV) + +$(OBJDIR): + @mkdir -p $(OBJDIR) + +install: $(KODEV) + mkdir -p $(INSTALL_DIR) + install -m 555 $(KODEV) $(INSTALL_DIR)/$(KODEV) + +uninstall: + rm -f $(INSTALL_DIR)/$(KODEV) + +$(OBJDIR)/%.o: ../src/%.c + $(CC) $(CFLAGS) -c $< -o $@ + +clean: + find . -type f -name \*.o -exec rm {} \; + rm -rf $(KODEV) $(OBJDIR) + +.PHONY: all clean diff --git a/src/cli.c b/src/cli.c @@ -22,6 +22,7 @@ #include <sys/mman.h> #include <sys/time.h> +#include <openssl/err.h> #include <openssl/pem.h> #include <openssl/x509v3.h> @@ -39,7 +40,8 @@ #include <unistd.h> #include <utime.h> -#include "kore.h" +#define errno_s strerror(errno) +#define ssl_errno_s ERR_error_string(ERR_get_error(), NULL) #if defined(OpenBSD) || defined(__FreeBSD_version) || \ defined(NetBSD) || defined(__DragonFly_version) @@ -66,6 +68,12 @@ #define BUILD_C 1 #define BUILD_CXX 2 +struct cli_buf { + u_int8_t *data; + size_t length; + size_t offset; +}; + struct mime_type { char *ext; char *type; @@ -80,9 +88,9 @@ struct buildopt { char *kore_flavor; int flavor_nohttp; int single_binary; - struct kore_buf *cflags; - struct kore_buf *cxxflags; - struct kore_buf *ldflags; + struct cli_buf *cflags; + struct cli_buf *cxxflags; + struct cli_buf *ldflags; TAILQ_ENTRY(buildopt) list; }; @@ -109,7 +117,25 @@ struct cfile { TAILQ_HEAD(cfile_list, cfile); -static void cli_fatal(const char *, ...) __attribute__((noreturn)); +static struct cli_buf *cli_buf_alloc(size_t); +static void cli_buf_free(struct cli_buf *); +static char *cli_buf_stringify(struct cli_buf *, size_t *); +static void cli_buf_append(struct cli_buf *, const void *, size_t); +static void cli_buf_appendf(struct cli_buf *, const char *, ...); +static void cli_buf_appendv(struct cli_buf *, const char *, + va_list); + +static void *cli_malloc(size_t); +static char *cli_strdup(const char *); +static void *cli_realloc(void *, size_t); + +static char *cli_text_trim(char *, size_t); +static char *cli_read_line(FILE *, char *, size_t); +static int cli_split_string(char *, const char *, char **, size_t); + +static void usage(void) __attribute__((noreturn)); +static void fatal(const char *, ...) __attribute__((noreturn)); + static void cli_file_close(int); static void cli_run_kore(void); static void cli_generate_certs(void); @@ -160,9 +186,11 @@ static void cli_buildopt_mime(struct buildopt *, const char *); static void cli_flavor_load(void); static void cli_flavor_change(const char *); +static void cli_kore_features(struct buildopt *, char **, size_t *); static void cli_run(int, char **); static void cli_help(int, char **); +static void cli_info(int, char **); static void cli_build(int, char **); static void cli_clean(int, char **); static void cli_create(int, char **); @@ -175,6 +203,7 @@ static void file_create_gitignore(void); static struct cmd cmds[] = { { "help", "this help text", cli_help }, { "run", "run an application (-fnr implied)", cli_run }, + { "info", "show info on kore on this system", cli_info }, { "build", "build an application", cli_build }, { "clean", "cleanup the build files", cli_clean }, { "create", "create a new application skeleton", cli_create }, @@ -226,18 +255,13 @@ static const char *config_data = "\n" "bind\t\t127.0.0.1 8888\n" "load\t\t./%s.so\n" -#if defined(KORE_USE_PYTHON) - "\n#python_import src/handler.py\n" -#endif -#if !defined(KORE_NO_TLS) + "\n" "tls_dhparam\tdh2048.pem\n" -#endif "\n" "domain * {\n" -#if !defined(KORE_NO_TLS) - "\tcertfile\tcert/server.crt\n" - "\tcertkey\t\tcert/server.key\n" -#endif + "\tcertfile\tcert/server.pem\n" + "\tcertkey\t\tcert/key.pem\n" + "\n" "\tstatic\t/\tpage\n" "}\n"; @@ -294,7 +318,6 @@ 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++"; static char *compiler_ld = "gcc"; @@ -312,40 +335,33 @@ static char *cflags[CFLAGS_MAX]; static char *cxxflags[CXXFLAGS_MAX]; static char *ldflags[LD_FLAGS_MAX]; -void -kore_cli_usage(int local) +static void +usage(void) { int i; - if (local) - fprintf(stderr, "Usage: kore [command]\n"); - + fprintf(stderr, "Usage: kodev [command]\n"); fprintf(stderr, "\nAvailable commands:\n"); + for (i = 0; cmds[i].name != NULL; i++) printf("\t%s\t%s\n", cmds[i].name, cmds[i].descr); - fprintf(stderr, "\nThe commands mostly exist for your convenience\n"); - fprintf(stderr, "when hacking on your Kore applications.\n"); - fprintf(stderr, "\n"); - fprintf(stderr, "Production servers should be started using "); - fprintf(stderr, "the options.\n"); - fprintf(stderr, "\nFind more information on https://kore.io\n"); exit(1); } int -kore_cli_main(int argc, char **argv) +main(int argc, char **argv) { int i; - if (argc < 1) - kore_cli_usage(1); + if (argc < 2) + usage(); - (void)umask(S_IWGRP|S_IWOTH); + argc--; + argv++; - if ((flavor = strchr(argv[0], ':')) != NULL) - *(flavor)++ = '\0'; + (void)umask(S_IWGRP | S_IWOTH); for (i = 0; cmds[i].name != NULL; i++) { if (!strcmp(argv[0], cmds[i].name)) { @@ -359,7 +375,7 @@ kore_cli_main(int argc, char **argv) if (cmds[i].name == NULL) { fprintf(stderr, "No such command: %s\n", argv[0]); - kore_cli_usage(1); + usage(); } return (0); @@ -368,7 +384,7 @@ kore_cli_main(int argc, char **argv) static void cli_help(int argc, char **argv) { - kore_cli_usage(1); + usage(); } static void @@ -378,11 +394,10 @@ cli_create(int argc, char **argv) char *fpath; if (argc != 1) - cli_fatal("missing application name"); + fatal("missing application name"); appl = argv[0]; cli_mkdir(appl, 0755); - rootdir = appl; for (i = 0; gen_dirs[i] != NULL; i++) { (void)cli_vasprintf(&fpath, "%s/%s", appl, gen_dirs[i]); @@ -393,6 +408,9 @@ cli_create(int argc, char **argv) for (i = 0; gen_files[i].cb != NULL; i++) gen_files[i].cb(); + if (chdir(appl) == -1) + fatal("chdir(%s): %s", appl, errno_s); + cli_generate_certs(); printf("%s created successfully!\n", appl); @@ -409,12 +427,12 @@ cli_flavor(int argc, char **argv) char pwd[MAXPATHLEN], *conf; if (getcwd(pwd, sizeof(pwd)) == NULL) - cli_fatal("could not get cwd: %s", errno_s); + fatal("could not get cwd: %s", errno_s); appl = basename(pwd); (void)cli_vasprintf(&conf, "conf/%s.conf", appl); if (!cli_dir_exists("conf") || !cli_file_exists(conf)) - cli_fatal("%s doesn't appear to be a kore app", appl); + fatal("%s doesn't appear to be a kore app", appl); free(conf); TAILQ_INIT(&build_options); @@ -451,13 +469,12 @@ cli_build(int argc, char **argv) char *build_path; int requires_relink, l; char *sofile, *config, *data; - char *assets_path, *p, *obj_path, *cpath; + char *assets_path, *p, *obj_path; char pwd[PATH_MAX], *src_path, *assets_header; if (getcwd(pwd, sizeof(pwd)) == NULL) - cli_fatal("could not get cwd: %s", errno_s); + fatal("could not get cwd: %s", errno_s); - rootdir = "."; appl = basename(pwd); if ((p = getenv("CC")) != NULL) { @@ -476,14 +493,14 @@ cli_build(int argc, char **argv) TAILQ_INIT(&build_options); TAILQ_INIT(&mime_types); - (void)cli_vasprintf(&src_path, "%s/src", rootdir); - (void)cli_vasprintf(&assets_path, "%s/assets", rootdir); - (void)cli_vasprintf(&config, "%s/conf/%s.conf", rootdir, appl); - (void)cli_vasprintf(&assets_header, "%s/src/assets.h", rootdir); - (void)cli_vasprintf(&build_path, "%s/conf/build.conf", rootdir); + (void)cli_vasprintf(&src_path, "src"); + (void)cli_vasprintf(&assets_path, "assets"); + (void)cli_vasprintf(&config, "conf/%s.conf", appl); + (void)cli_vasprintf(&assets_header, "src/assets.h"); + (void)cli_vasprintf(&build_path, "conf/build.conf"); if (!cli_dir_exists(src_path) || !cli_file_exists(config)) - cli_fatal("%s doesn't appear to be a kore app", appl); + fatal("%s doesn't appear to be a kore app", appl); cli_flavor_load(); bopt = cli_buildopt_new("_default"); @@ -499,14 +516,14 @@ cli_build(int argc, char **argv) cli_buildopt_parse(build_path); free(build_path); - (void)cli_vasprintf(&obj_path, "%s/.objs", rootdir); + (void)cli_vasprintf(&obj_path, ".objs"); 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"); + fatal("single_binary set but not kore_source"); printf("building kore (%s)\n", bopt->kore_source); cli_spawn_proc(cli_compile_kore, bopt); @@ -571,12 +588,10 @@ cli_build(int argc, char **argv) (void)unlink(assets_header); free(assets_header); - (void)cli_vasprintf(&cpath, "%s/cert", rootdir); - if (!cli_dir_exists(cpath)) { - cli_mkdir(cpath, 0700); + if (!cli_dir_exists("cert")) { + cli_mkdir("cert", 0700); cli_generate_certs(); } - free(cpath); if (bopt->single_binary) { requires_relink++; @@ -610,7 +625,7 @@ cli_clean(int argc, char **argv) cli_cleanup_files(".objs"); if (getcwd(pwd, sizeof(pwd)) == NULL) - cli_fatal("could not get cwd: %s", errno_s); + fatal("could not get cwd: %s", errno_s); appl = basename(pwd); (void)cli_vasprintf(&sofile, "%s.so", appl); @@ -626,9 +641,6 @@ cli_run(int argc, char **argv) run_after = 1; cli_build(argc, argv); - if (chdir(rootdir) == -1) - cli_fatal("couldn't change directory to %s", rootdir); - /* * We are exec()'ing kore again, while we could technically set * the right cli options manually and just continue running. @@ -637,11 +649,40 @@ cli_run(int argc, char **argv) } static void +cli_info(int argc, char **argv) +{ + size_t len; + struct buildopt *bopt; + char *features; + + TAILQ_INIT(&mime_types); + TAILQ_INIT(&build_options); + + cli_flavor_load(); + bopt = cli_buildopt_new("_default"); + cli_buildopt_parse("conf/build.conf"); + + printf("active flavor\t %s\n", flavor); + printf("output type \t %s\n", + (bopt->single_binary) ? "binary" : "dso"); + + if (bopt->single_binary) { + printf("kore source \t %s\n", bopt->kore_source); + printf("kore features\t %s\n", bopt->kore_flavor); + } else { + cli_kore_features(bopt, &features, &len); + printf("kore binary \t %s/bin/kore\n", PREFIX); + printf("kore features\t %.*s\n", (int)len, features); + free(features); + } +} + +static void file_create_src(void) { char *name; - (void)cli_vasprintf(&name, "src/%s.c", appl); + (void)cli_vasprintf(&name, "%s/src/%s.c", appl, appl); cli_file_create(name, src_data, strlen(src_data)); free(name); } @@ -652,14 +693,16 @@ file_create_config(void) int l; char *name, *data; - (void)cli_vasprintf(&name, "conf/%s.conf", appl); + (void)cli_vasprintf(&name, "%s/conf/%s.conf", appl, appl); l = cli_vasprintf(&data, config_data, appl, appl); cli_file_create(name, data, l); free(name); free(data); + (void)cli_vasprintf(&name, "%s/conf/build.conf", appl); l = cli_vasprintf(&data, build_data, appl); - cli_file_create("conf/build.conf", data, l); + cli_file_create(name, data, l); + free(name); free(data); } @@ -667,10 +710,12 @@ static void file_create_gitignore(void) { int l; - char *data; + char *name, *data; + (void)cli_vasprintf(&name, "%s/.gitignore", appl); l = cli_vasprintf(&data, gitignore, appl); - cli_file_create(".gitignore", data, l); + cli_file_create(name, data, l); + free(name); free(data); } @@ -678,7 +723,7 @@ static void cli_mkdir(const char *fpath, int mode) { if (mkdir(fpath, mode) == -1) - cli_fatal("cli_mkdir(%s): %s", fpath, errno_s); + fatal("cli_mkdir(%s): %s", fpath, errno_s); } static int @@ -703,7 +748,7 @@ cli_file_requires_build(struct stat *fst, const char *opath) if (stat(opath, &ost) == -1) { if (errno == ENOENT) return (1); - cli_fatal("stat(%s): %s", opath, errno_s); + fatal("stat(%s): %s", opath, errno_s); } return (fst->st_mtime != ost.st_mtime); @@ -727,7 +772,7 @@ static void cli_file_open(const char *fpath, int flags, int *fd) { if ((*fd = open(fpath, flags, 0644)) == -1) - cli_fatal("cli_file_open(%s): %s", fpath, errno_s); + fatal("cli_file_open(%s): %s", fpath, errno_s); } static void @@ -739,25 +784,25 @@ cli_file_read(int fd, char **buf, size_t *len) size_t offset, bytes; if (fstat(fd, &st) == -1) - cli_fatal("fstat(): %s", errno_s); + fatal("fstat(): %s", errno_s); if (st.st_size > USHRT_MAX) - cli_fatal("cli_file_read: way too big"); + fatal("cli_file_read: way too big"); offset = 0; bytes = st.st_size; - p = kore_malloc(bytes); + p = cli_malloc(bytes); while (offset != bytes) { ret = read(fd, p + offset, bytes - offset); if (ret == -1) { if (errno == EINTR) continue; - cli_fatal("read(): %s", errno_s); + fatal("read(): %s", errno_s); } if (ret == 0) - cli_fatal("unexpected EOF"); + fatal("unexpected EOF"); offset += (size_t)ret; } @@ -785,7 +830,7 @@ cli_file_writef(int fd, const char *fmt, ...) va_end(args); if (l == -1) - cli_fatal("cli_file_writef"); + fatal("cli_file_writef"); cli_file_write(fd, buf, l); free(buf); @@ -805,7 +850,7 @@ cli_file_write(int fd, const void *buf, size_t len) if (r == -1) { if (errno == EINTR) continue; - cli_fatal("cli_file_write: %s", errno_s); + fatal("cli_file_write: %s", errno_s); } written += r; @@ -816,16 +861,12 @@ static void cli_file_create(const char *name, const char *data, size_t len) { int fd; - char *fpath; - - (void)cli_vasprintf(&fpath, "%s/%s", rootdir, name); - cli_file_open(fpath, O_CREAT | O_TRUNC | O_WRONLY, &fd); + cli_file_open(name, O_CREAT | O_TRUNC | O_WRONLY, &fd); cli_file_write(fd, data, len); cli_file_close(fd); - printf("created %s\n", fpath); - free(fpath); + printf("created %s\n", name); } static void @@ -858,11 +899,11 @@ cli_build_asset(char *fpath, struct dirent *dp) char hash[(SHA_DIGEST_LENGTH * 2) + 1]; bopt = cli_buildopt_default(); - name = kore_strdup(dp->d_name); + name = cli_strdup(dp->d_name); /* Grab the extension as we're using it in the symbol name. */ if ((ext = strrchr(name, '.')) == NULL) - cli_fatal("couldn't find ext in %s", name); + fatal("couldn't find ext in %s", name); /* Replace dots, spaces, etc etc with underscores. */ for (p = name; *p != '\0'; p++) { @@ -872,7 +913,7 @@ cli_build_asset(char *fpath, struct dirent *dp) /* Grab inode information. */ if (stat(fpath, &st) == -1) - cli_fatal("stat: %s %s", fpath, errno_s); + fatal("stat: %s %s", fpath, errno_s); /* If this file was empty, skip it. */ if (st.st_size == 0) { @@ -880,8 +921,8 @@ cli_build_asset(char *fpath, struct dirent *dp) return; } - (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, name); - (void)cli_vasprintf(&cpath, "%s/.objs/%s.c", rootdir, name); + (void)cli_vasprintf(&opath, ".objs/%s.o", name); + (void)cli_vasprintf(&cpath, ".objs/%s.c", name); /* Check if the file needs to be built. */ if (!cli_file_requires_build(&st, opath)) { @@ -890,7 +931,7 @@ cli_build_asset(char *fpath, struct dirent *dp) *ext = '_'; cli_add_source_file(name, cpath, opath, &st, BUILD_NOBUILD); - kore_free(name); + free(name); return; } @@ -900,7 +941,7 @@ cli_build_asset(char *fpath, struct dirent *dp) /* mmap our in file. */ if ((base = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, in, 0)) == MAP_FAILED) - cli_fatal("mmap: %s %s", fpath, errno_s); + fatal("mmap: %s %s", fpath, errno_s); /* Create the c file where we will write too. */ cli_file_open(cpath, O_CREAT | O_TRUNC | O_WRONLY, &out); @@ -938,7 +979,7 @@ cli_build_asset(char *fpath, struct dirent *dp) len = snprintf(hash + (i * 2), sizeof(hash) - (i * 2), "%02x", digest[i]); if (len == -1 || (size_t)len >= sizeof(hash)) - cli_fatal("failed to convert SHA1 digest to hex"); + fatal("failed to convert SHA1 digest to hex"); } mime = NULL; @@ -972,7 +1013,7 @@ cli_build_asset(char *fpath, struct dirent *dp) /* Cleanup static file source. */ if (munmap(base, st.st_size) == -1) - cli_fatal("munmap: %s %s", fpath, errno_s); + fatal("munmap: %s %s", fpath, errno_s); /* Cleanup fds */ cli_file_close(in); @@ -983,7 +1024,7 @@ cli_build_asset(char *fpath, struct dirent *dp) /* Register the .c file now (cpath is free'd later). */ cli_add_source_file(name, cpath, opath, &st, BUILD_C); - kore_free(name); + free(name); } static void @@ -993,13 +1034,13 @@ cli_add_source_file(char *name, char *fpath, char *opath, struct stat *st, struct cfile *cf; source_files_count++; - cf = kore_malloc(sizeof(*cf)); + cf = cli_malloc(sizeof(*cf)); cf->st = *st; cf->build = build; cf->fpath = fpath; cf->opath = opath; - cf->name = kore_strdup(name); + cf->name = cli_strdup(name); TAILQ_INSERT_TAIL(&source_files, cf, list); } @@ -1016,12 +1057,12 @@ cli_register_source_file(char *fpath, struct dirent *dp) return; if (stat(fpath, &st) == -1) - cli_fatal("stat(%s): %s", fpath, errno_s); + 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, ".objs/%s.o", dp->d_name); if (!cli_file_requires_build(&st, opath)) { build = BUILD_NOBUILD; } else if (!strcmp(ext, ".cpp")) { @@ -1043,13 +1084,13 @@ cli_register_kore_file(char *fpath, struct dirent *dp) return; if (stat(fpath, &st) == -1) - cli_fatal("stat(%s): %s", fpath, errno_s); + fatal("stat(%s): %s", fpath, errno_s); *ext = '\0'; if ((fname = basename(fpath)) == NULL) - cli_fatal("basename failed"); + fatal("basename failed"); - (void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, fname); + (void)cli_vasprintf(&opath, ".objs/%s.o", fname); /* Silently ignore non existing object files for kore source files. */ if (stat(opath, &ost) == -1) { @@ -1076,7 +1117,7 @@ cli_find_files(const char *path, void (*cb)(char *, struct dirent *)) char *fpath; if ((d = opendir(path)) == NULL) - cli_fatal("cli_find_files: opendir(%s): %s", path, errno_s); + fatal("cli_find_files: opendir(%s): %s", path, errno_s); while ((dp = readdir(d)) != NULL) { if (!strcmp(dp->d_name, ".") || @@ -1115,90 +1156,84 @@ cli_generate_certs(void) EVP_PKEY *pkey; X509 *x509; RSA *kpair; - char *fpath, issuer[64]; + char issuer[64]; /* Write out DH parameters. */ cli_file_create("dh2048.pem", dh2048_data, strlen(dh2048_data)); /* Create new certificate. */ if ((x509 = X509_new()) == NULL) - cli_fatal("X509_new(): %s", ssl_errno_s); + fatal("X509_new(): %s", ssl_errno_s); /* Generate version 3. */ if (!X509_set_version(x509, 2)) - cli_fatal("X509_set_version(): %s", ssl_errno_s); + fatal("X509_set_version(): %s", ssl_errno_s); /* Generate RSA keys. */ if ((pkey = EVP_PKEY_new()) == NULL) - cli_fatal("EVP_PKEY_new(): %s", ssl_errno_s); + fatal("EVP_PKEY_new(): %s", ssl_errno_s); if ((kpair = RSA_new()) == NULL) - cli_fatal("RSA_new(): %s", ssl_errno_s); + fatal("RSA_new(): %s", ssl_errno_s); if ((e = BN_new()) == NULL) - cli_fatal("BN_new(): %s", ssl_errno_s); + fatal("BN_new(): %s", ssl_errno_s); if (!BN_set_word(e, 65537)) - cli_fatal("BN_set_word(): %s", ssl_errno_s); + fatal("BN_set_word(): %s", ssl_errno_s); if (!RSA_generate_key_ex(kpair, 2048, e, NULL)) - cli_fatal("RSA_generate_key_ex(): %s", ssl_errno_s); + fatal("RSA_generate_key_ex(): %s", ssl_errno_s); BN_free(e); if (!EVP_PKEY_assign_RSA(pkey, kpair)) - cli_fatal("EVP_PKEY_assign_RSA(): %s", ssl_errno_s); + fatal("EVP_PKEY_assign_RSA(): %s", ssl_errno_s); /* Set serial number to current timestamp. */ time(&now); if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), now)) - cli_fatal("ASN1_INTEGER_set(): %s", ssl_errno_s); + fatal("ASN1_INTEGER_set(): %s", ssl_errno_s); /* Not before and not after dates. */ if (!X509_gmtime_adj(X509_get_notBefore(x509), 0)) - cli_fatal("X509_gmtime_adj(): %s", ssl_errno_s); + fatal("X509_gmtime_adj(): %s", ssl_errno_s); if (!X509_gmtime_adj(X509_get_notAfter(x509), (long)60 * 60 * 24 * 3000)) - cli_fatal("X509_gmtime_adj(): %s", ssl_errno_s); + fatal("X509_gmtime_adj(): %s", ssl_errno_s); /* Attach the pkey to the certificate. */ if (!X509_set_pubkey(x509, pkey)) - cli_fatal("X509_set_pubkey(): %s", ssl_errno_s); + fatal("X509_set_pubkey(): %s", ssl_errno_s); /* Set certificate information. */ if ((name = X509_get_subject_name(x509)) == NULL) - cli_fatal("X509_get_subject_name(): %s", ssl_errno_s); + fatal("X509_get_subject_name(): %s", ssl_errno_s); (void)snprintf(issuer, sizeof(issuer), "kore autogen: %s", appl); if (!X509_NAME_add_entry_by_txt(name, "C", MBSTRING_ASC, (const unsigned char *)"SE", -1, -1, 0)) - cli_fatal("X509_NAME_add_entry_by_txt(): C %s", ssl_errno_s); + fatal("X509_NAME_add_entry_by_txt(): C %s", ssl_errno_s); if (!X509_NAME_add_entry_by_txt(name, "O", MBSTRING_ASC, (const unsigned char *)issuer, -1, -1, 0)) - cli_fatal("X509_NAME_add_entry_by_txt(): O %s", ssl_errno_s); + fatal("X509_NAME_add_entry_by_txt(): O %s", ssl_errno_s); if (!X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (const unsigned char *)"localhost", -1, -1, 0)) - cli_fatal("X509_NAME_add_entry_by_txt(): CN %s", ssl_errno_s); + fatal("X509_NAME_add_entry_by_txt(): CN %s", ssl_errno_s); if (!X509_set_issuer_name(x509, name)) - cli_fatal("X509_set_issuer_name(): %s", ssl_errno_s); + fatal("X509_set_issuer_name(): %s", ssl_errno_s); if (!X509_sign(x509, pkey, EVP_sha256())) - cli_fatal("X509_sign(): %s", ssl_errno_s); - - (void)cli_vasprintf(&fpath, "%s/cert/server.key", rootdir); - if ((fp = fopen(fpath, "w")) == NULL) - cli_fatal("fopen(%s): %s", fpath, errno_s); - free(fpath); + fatal("X509_sign(): %s", ssl_errno_s); + if ((fp = fopen("cert/key.pem", "w")) == NULL) + fatal("fopen(cert/key.pem): %s", errno_s); if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL)) - cli_fatal("PEM_write_PrivateKey(): %s", ssl_errno_s); + fatal("PEM_write_PrivateKey(): %s", ssl_errno_s); fclose(fp); - (void)cli_vasprintf(&fpath, "%s/cert/server.crt", rootdir); - if ((fp = fopen(fpath, "w")) == NULL) - cli_fatal("fopen(%s): %s", fpath, errno_s); - free(fpath); - + if ((fp = fopen("cert/server.pem", "w")) == NULL) + fatal("fopen(cert/server.pem): %s", errno_s); if (!PEM_write_X509(fp, x509)) - cli_fatal("PEM_write_X509(%s)", errno_s); + fatal("PEM_write_X509(%s)", errno_s); fclose(fp); EVP_PKEY_free(pkey); @@ -1209,12 +1244,14 @@ cli_generate_certs(void) static void cli_compile_source_file(void *arg) { - int idx, i; - struct cfile *cf = arg; - char *args[32 + CFLAGS_MAX]; - char *compiler; - char **flags; - int flags_count; + struct cfile *cf; + int idx, i; + char **flags; + char *compiler; + int flags_count; + char *args[32 + CFLAGS_MAX]; + + cf = arg; switch (cf->build) { case BUILD_C: @@ -1228,7 +1265,7 @@ cli_compile_source_file(void *arg) flags_count = cxxflags_count; break; default: - cli_fatal("cli_compile_file: unexpected file type: %d", + fatal("cli_compile_file: unexpected file type: %d", cf->build); break; } @@ -1246,7 +1283,7 @@ cli_compile_source_file(void *arg) args[idx] = NULL; execvp(compiler, args); - cli_fatal("failed to start '%s': %s", compiler, errno_s); + fatal("failed to start '%s': %s", compiler, errno_s); } static void @@ -1261,9 +1298,9 @@ cli_link_application(void *arg) bopt = arg; if (bopt->single_binary) - (void)cli_vasprintf(&output, "%s/%s", rootdir, appl); + (void)cli_vasprintf(&output, "%s", appl); else - (void)cli_vasprintf(&output, "%s/%s.so", rootdir, appl); + (void)cli_vasprintf(&output, "%s.so", appl); idx = 0; args[idx++] = compiler_ld; @@ -1279,7 +1316,7 @@ cli_link_application(void *arg) args[idx] = NULL; execvp(compiler_ld, args); - cli_fatal("failed to start '%s': %s", compiler_ld, errno_s); + fatal("failed to start '%s': %s", compiler_ld, errno_s); } static void @@ -1290,14 +1327,14 @@ cli_compile_kore(void *arg) char *obj, *args[20], pwd[MAXPATHLEN], *flavors[7]; if (getcwd(pwd, sizeof(pwd)) == NULL) - cli_fatal("could not get cwd: %s", errno_s); + fatal("could not get cwd: %s", errno_s); (void)cli_vasprintf(&obj, "OBJDIR=%s/.objs", pwd); if (putenv(obj) != 0) - cli_fatal("cannot set OBJDIR for building kore"); + fatal("cannot set OBJDIR for building kore"); - fcnt = kore_split_string(bopt->kore_flavor, " ", flavors, 7); + fcnt = cli_split_string(bopt->kore_flavor, " ", flavors, 7); #if defined(OpenBSD) || defined(__FreeBSD_version) || \ defined(NetBSD) || defined(__DragonFly_version) @@ -1321,7 +1358,7 @@ cli_compile_kore(void *arg) args[idx] = NULL; execvp(args[0], args); - cli_fatal("failed to start '%s': %s", args[0], errno_s); + fatal("failed to start '%s': %s", args[0], errno_s); } static void @@ -1337,8 +1374,8 @@ cli_run_kore(void) flags = "-fnr"; (void)cli_vasprintf(&cmd, "./%s", appl); } else { - cmd = "kore"; flags = "-fnrc"; + (void)cli_vasprintf(&cmd, "%s/bin/kore", PREFIX); (void)cli_vasprintf(&cpath, "conf/%s.conf", appl); } @@ -1353,7 +1390,7 @@ cli_run_kore(void) } execvp(args[0], args); - cli_fatal("failed to start '%s': %s", args[0], errno_s); + fatal("failed to start '%s': %s", args[0], errno_s); } static void @@ -1364,11 +1401,11 @@ cli_buildopt_parse(const char *path) char buf[BUFSIZ], *p, *t; if ((fp = fopen(path, "r")) == NULL) - cli_fatal("cli_buildopt_parse: fopen(%s): %s", path, errno_s); + fatal("cli_buildopt_parse: fopen(%s): %s", path, errno_s); bopt = NULL; - while ((p = kore_read_line(fp, buf, sizeof(buf))) != NULL) { + while ((p = cli_read_line(fp, buf, sizeof(buf))) != NULL) { if (strlen(p) == 0) continue; @@ -1381,10 +1418,10 @@ cli_buildopt_parse(const char *path) if ((t = strchr(p, '=')) != NULL) goto parse_option; if ((t = strchr(p, ' ')) == NULL) - cli_fatal("unexpected '%s'", p); + fatal("unexpected '%s'", p); *(t)++ = '\0'; if (strcmp(t, "{")) - cli_fatal("expected '{', got '%s'", t); + fatal("expected '{', got '%s'", t); bopt = cli_buildopt_new(p); continue; } @@ -1397,8 +1434,8 @@ cli_buildopt_parse(const char *path) parse_option: *(t)++ = '\0'; - p = kore_text_trim(p, strlen(p)); - t = kore_text_trim(t, strlen(t)); + p = cli_text_trim(p, strlen(p)); + t = cli_text_trim(t, strlen(t)); if (!strcasecmp(p, "cflags")) { cli_buildopt_cflags(bopt, t); @@ -1427,7 +1464,7 @@ cli_buildopt_new(const char *name) { struct buildopt *bopt; - bopt = kore_malloc(sizeof(*bopt)); + bopt = cli_malloc(sizeof(*bopt)); bopt->cflags = NULL; bopt->cxxflags = NULL; bopt->ldflags = NULL; @@ -1435,7 +1472,7 @@ cli_buildopt_new(const char *name) bopt->single_binary = 0; bopt->kore_source = NULL; bopt->kore_flavor = NULL; - bopt->name = kore_strdup(name); + bopt->name = cli_strdup(name); TAILQ_INSERT_TAIL(&build_options, bopt, list); return (bopt); @@ -1476,24 +1513,24 @@ cli_buildopt_cleanup(void) TAILQ_REMOVE(&build_options, bopt, list); if (bopt->cflags != NULL) - kore_buf_free(bopt->cflags); + cli_buf_free(bopt->cflags); if (bopt->cxxflags != NULL) - kore_buf_free(bopt->cxxflags); + cli_buf_free(bopt->cxxflags); if (bopt->ldflags != NULL) - kore_buf_free(bopt->ldflags); + cli_buf_free(bopt->ldflags); if (bopt->kore_source != NULL) - kore_free(bopt->kore_source); + free(bopt->kore_source); if (bopt->kore_flavor != NULL) - kore_free(bopt->kore_flavor); - kore_free(bopt); + free(bopt->kore_flavor); + free(bopt); } for (mime = TAILQ_FIRST(&mime_types); mime != NULL; mime = mnext) { mnext = TAILQ_NEXT(mime, list); TAILQ_REMOVE(&mime_types, mime, list); - kore_free(mime->type); - kore_free(mime->ext); - kore_free(mime); + free(mime->type); + free(mime->ext); + free(mime); } } @@ -1504,9 +1541,9 @@ cli_buildopt_cflags(struct buildopt *bopt, const char *string) bopt = cli_buildopt_default(); if (bopt->cflags == NULL) - bopt->cflags = kore_buf_alloc(128); + bopt->cflags = cli_buf_alloc(128); - kore_buf_appendf(bopt->cflags, "%s ", string); + cli_buf_appendf(bopt->cflags, "%s ", string); } static void @@ -1516,9 +1553,9 @@ cli_buildopt_cxxflags(struct buildopt *bopt, const char *string) bopt = cli_buildopt_default(); if (bopt->cxxflags == NULL) - bopt->cxxflags = kore_buf_alloc(128); + bopt->cxxflags = cli_buf_alloc(128); - kore_buf_appendf(bopt->cxxflags, "%s ", string); + cli_buf_appendf(bopt->cxxflags, "%s ", string); } static void @@ -1528,9 +1565,9 @@ cli_buildopt_ldflags(struct buildopt *bopt, const char *string) bopt = cli_buildopt_default(); if (bopt->ldflags == NULL) - bopt->ldflags = kore_buf_alloc(128); + bopt->ldflags = cli_buf_alloc(128); - kore_buf_appendf(bopt->ldflags, "%s ", string); + cli_buf_appendf(bopt->ldflags, "%s ", string); } static void @@ -1539,7 +1576,7 @@ 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"); + fatal("single_binary only supported in global context"); if (!strcmp(string, "yes")) bopt->single_binary = 1; @@ -1553,12 +1590,12 @@ 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"); + fatal("kore_source only supported in global context"); if (bopt->kore_source != NULL) - kore_free(bopt->kore_source); + free(bopt->kore_source); - bopt->kore_source = kore_strdup(string); + bopt->kore_source = cli_strdup(string); } static void @@ -1570,17 +1607,17 @@ 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"); + fatal("kore_flavor only supported in global context"); if (bopt->kore_flavor != NULL) - kore_free(bopt->kore_flavor); + free(bopt->kore_flavor); - copy = kore_strdup(string); - cnt = kore_split_string(copy, " ", flavors, 10); + copy = cli_strdup(string); + cnt = cli_split_string(copy, " ", flavors, 10); for (i = 0; i < cnt; i++) { if ((p = strchr(flavors[i], '=')) == NULL) - cli_fatal("invalid flavor %s", string); + fatal("invalid flavor %s", string); *p = '\0'; @@ -1588,8 +1625,8 @@ cli_buildopt_kore_flavor(struct buildopt *bopt, const char *string) bopt->flavor_nohttp = 1; } - bopt->kore_flavor = kore_strdup(string); - kore_free(copy); + bopt->kore_flavor = cli_strdup(string); + free(copy); } static void @@ -1601,89 +1638,75 @@ cli_buildopt_mime(struct buildopt *bopt, const char *ext) if (bopt == NULL) bopt = cli_buildopt_default(); else - cli_fatal("mime_add only supported in global context"); + fatal("mime_add only supported in global context"); if ((type = strchr(ext, ':')) == NULL) - cli_fatal("no type given in %s", ext); + fatal("no type given in %s", ext); *(type)++ = '\0'; TAILQ_FOREACH(mime, &mime_types, list) { if (!strcmp(mime->ext, ext)) - cli_fatal("duplicate extension %s found", ext); + fatal("duplicate extension %s found", ext); } - mime = kore_malloc(sizeof(*mime)); - mime->ext = kore_strdup(ext); - mime->type = kore_strdup(type); + mime = cli_malloc(sizeof(*mime)); + mime->ext = cli_strdup(ext); + mime->type = cli_strdup(type); TAILQ_INSERT_TAIL(&mime_types, mime, list); } static void -cli_build_flags_common(struct kore_buf* buf) +cli_build_flags_common(struct buildopt *bopt, struct cli_buf *buf) { - kore_buf_appendf(buf, - "-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir); -#if defined(PREFIX) - kore_buf_appendf(buf, "-I%s/include ", PREFIX); -#else - kore_buf_appendf(buf, "-I/usr/local/include "); -#endif + size_t len; + char *data; + + cli_buf_appendf(buf, "-fPIC -Isrc -Isrc/includes "); + cli_buf_appendf(buf, "-I%s/include ", PREFIX); #if defined(__MACH__) /* Add default openssl include path from homebrew / ports under OSX. */ - kore_buf_appendf(buf, "-I/opt/local/include "); - kore_buf_appendf(buf, "-I/usr/local/opt/openssl/include "); -#endif -#if defined(KORE_USE_PGSQL) - kore_buf_appendf(buf, "-I%s ", PGSQL_INCLUDE_PATH); -#endif -#if defined(KORE_NO_HTTP) - kore_buf_appendf(buf, "-DKORE_NO_HTTP "); -#endif -#if defined(KORE_NO_TLS) - kore_buf_appendf(buf, "-DKORE_NO_TLS "); + cli_buf_appendf(buf, "-I/opt/local/include "); + cli_buf_appendf(buf, "-I/usr/local/opt/openssl/include "); #endif + if (bopt->single_binary == 0) { + cli_kore_features(bopt, &data, &len); + cli_buf_append(buf, data, len); + cli_buf_appendf(buf, " "); + free(data); + } } static void cli_build_cflags(struct buildopt *bopt) { - int fd; size_t len; struct buildopt *obopt; - char *string, *buf, *path; + char *string, *buf; if ((obopt = cli_buildopt_find(flavor)) == NULL) - cli_fatal("no such build flavor: %s", flavor); + fatal("no such build flavor: %s", flavor); if (bopt->cflags == NULL) - bopt->cflags = kore_buf_alloc(128); + bopt->cflags = cli_buf_alloc(128); - cli_build_flags_common(bopt->cflags); + cli_build_flags_common(bopt, bopt->cflags); if (obopt != NULL && obopt->cflags != NULL) { - kore_buf_append(bopt->cflags, obopt->cflags->data, + cli_buf_append(bopt->cflags, obopt->cflags->data, obopt->cflags->offset); } if (bopt->single_binary) { - (void)cli_vasprintf(&path, "%s/.objs/features", rootdir); - cli_file_open(path, O_RDONLY, &fd); - cli_file_read(fd, &buf, &len); - cli_file_close(fd); - free(path); - - if (buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - kore_buf_append(bopt->cflags, buf, len); - kore_buf_appendf(bopt->cflags, " "); - kore_free(buf); + cli_kore_features(bopt, &buf, &len); + cli_buf_append(bopt->cflags, buf, len); + cli_buf_appendf(bopt->cflags, " "); + free(buf); } - string = kore_buf_stringify(bopt->cflags, NULL); + string = cli_buf_stringify(bopt->cflags, NULL); printf("CFLAGS=%s\n", string); - cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX); + cflags_count = cli_split_string(string, " ", cflags, CFLAGS_MAX); } static void @@ -1693,22 +1716,22 @@ cli_build_cxxflags(struct buildopt *bopt) char *string; if ((obopt = cli_buildopt_find(flavor)) == NULL) - cli_fatal("no such build flavor: %s", flavor); + fatal("no such build flavor: %s", flavor); if (bopt->cxxflags == NULL) - bopt->cxxflags = kore_buf_alloc(128); + bopt->cxxflags = cli_buf_alloc(128); - cli_build_flags_common(bopt->cxxflags); + cli_build_flags_common(bopt, bopt->cxxflags); if (obopt != NULL && obopt->cxxflags != NULL) { - kore_buf_append(bopt->cxxflags, obopt->cxxflags->data, + cli_buf_append(bopt->cxxflags, obopt->cxxflags->data, obopt->cxxflags->offset); } - string = kore_buf_stringify(bopt->cxxflags, NULL); + string = cli_buf_stringify(bopt->cxxflags, NULL); if (cxx_files_count > 0) printf("CXXFLAGS=%s\n", string); - cxxflags_count = kore_split_string(string, " ", cxxflags, CXXFLAGS_MAX); + cxxflags_count = cli_split_string(string, " ", cxxflags, CXXFLAGS_MAX); } static void @@ -1717,44 +1740,42 @@ cli_build_ldflags(struct buildopt *bopt) int fd; size_t len; struct buildopt *obopt; - char *string, *buf, *path; + char *string, *buf; if ((obopt = cli_buildopt_find(flavor)) == NULL) - cli_fatal("no such build flavor: %s", flavor); + fatal("no such build flavor: %s", flavor); if (bopt->ldflags == NULL) - bopt->ldflags = kore_buf_alloc(128); + bopt->ldflags = cli_buf_alloc(128); if (bopt->single_binary == 0) { #if defined(__MACH__) - kore_buf_appendf(bopt->ldflags, + cli_buf_appendf(bopt->ldflags, "-dynamiclib -undefined suppress -flat_namespace "); #else - kore_buf_appendf(bopt->ldflags, "-shared "); + cli_buf_appendf(bopt->ldflags, "-shared "); #endif } else { - (void)cli_vasprintf(&path, "%s/.objs/ldflags", rootdir); - cli_file_open(path, O_RDONLY, &fd); + cli_file_open(".objs/ldflags", O_RDONLY, &fd); cli_file_read(fd, &buf, &len); cli_file_close(fd); - free(path); if (buf[len - 1] == '\n') buf[len - 1] = '\0'; - kore_buf_append(bopt->ldflags, buf, len); - kore_buf_appendf(bopt->ldflags, " "); - kore_free(buf); + cli_buf_append(bopt->ldflags, buf, len); + cli_buf_appendf(bopt->ldflags, " "); + free(buf); } if (obopt != NULL && obopt->ldflags != NULL) { - kore_buf_append(bopt->ldflags, obopt->ldflags->data, + cli_buf_append(bopt->ldflags, obopt->ldflags->data, obopt->ldflags->offset); } - string = kore_buf_stringify(bopt->ldflags, NULL); + string = cli_buf_stringify(bopt->ldflags, NULL); printf("LDFLAGS=%s\n", string); - ldflags_count = kore_split_string(string, " ", ldflags, LD_FLAGS_MAX); + ldflags_count = cli_split_string(string, " ", ldflags, LD_FLAGS_MAX); } static void @@ -1764,34 +1785,59 @@ cli_flavor_load(void) char buf[BUFSIZ], pwd[MAXPATHLEN], *p, *conf; if (getcwd(pwd, sizeof(pwd)) == NULL) - cli_fatal("could not get cwd: %s", errno_s); + fatal("could not get cwd: %s", errno_s); appl = basename(pwd); if (appl == NULL) - cli_fatal("basename: %s", errno_s); - appl = kore_strdup(appl); + fatal("basename: %s", errno_s); + appl = cli_strdup(appl); (void)cli_vasprintf(&conf, "conf/%s.conf", appl); if (!cli_dir_exists("conf") || !cli_file_exists(conf)) - cli_fatal("%s doesn't appear to be a kore app", appl); + fatal("%s doesn't appear to be a kore app", appl); free(conf); if ((fp = fopen(".flavor", "r")) == NULL) { - flavor = kore_strdup("dev"); + flavor = cli_strdup("dev"); return; } if (fgets(buf, sizeof(buf), fp) == NULL) - cli_fatal("failed to read flavor from file"); + fatal("failed to read flavor from file"); if ((p = strchr(buf, '\n')) != NULL) *p = '\0'; - flavor = kore_strdup(buf); + flavor = cli_strdup(buf); (void)fclose(fp); } static void +cli_kore_features(struct buildopt *bopt, char **out, size_t *outlen) +{ + int fd; + size_t len; + char *path, *data; + + if (bopt->single_binary) { + (void)cli_vasprintf(&path, ".objs/features"); + } else { + (void)cli_vasprintf(&path, "%s/share/kore/features", PREFIX); + } + + cli_file_open(path, O_RDONLY, &fd); + cli_file_read(fd, &data, &len); + cli_file_close(fd); + free(path); + + if (data[len - 1] == '\n') + data[len - 1] = '\0'; + + *out = data; + *outlen = len; +} + +static void cli_flavor_change(const char *name) { FILE *fp; @@ -1799,19 +1845,19 @@ cli_flavor_change(const char *name) struct buildopt *bopt; if ((bopt = cli_buildopt_find(name)) == NULL) - cli_fatal("no such flavor: %s", name); + fatal("no such flavor: %s", name); if ((fp = fopen(".flavor.tmp", "w")) == NULL) - cli_fatal("failed to open temporary file to save flavor"); + fatal("failed to open temporary file to save flavor"); ret = fprintf(fp, "%s\n", name); if (ret == -1 || (size_t)ret != (strlen(name) + 1)) - cli_fatal("failed to write new build flavor"); + fatal("failed to write new build flavor"); (void)fclose(fp); if (rename(".flavor.tmp", ".flavor") == -1) - cli_fatal("failed to replace build flavor"); + fatal("failed to replace build flavor"); cli_clean(0, NULL); } @@ -1825,21 +1871,21 @@ cli_spawn_proc(void (*cb)(void *), void *arg) pid = fork(); switch (pid) { case -1: - cli_fatal("cli_compile_cfile: fork() %s", errno_s); + fatal("cli_compile_cfile: fork() %s", errno_s); /* NOTREACHED */ case 0: cb(arg); - cli_fatal("cli_spawn_proc: %s", errno_s); + fatal("cli_spawn_proc: %s", errno_s); /* NOTREACHED */ default: break; } if (waitpid(pid, &status, 0) == -1) - cli_fatal("couldn't wait for child %d", pid); + fatal("couldn't wait for child %d", pid); if (WEXITSTATUS(status) || WTERMSIG(status) || WCOREDUMP(status)) - cli_fatal("subprocess trouble, check output"); + fatal("subprocess trouble, check output"); } static int @@ -1853,7 +1899,7 @@ cli_vasprintf(char **out, const char *fmt, ...) va_end(args); if (l == -1) - cli_fatal("cli_vasprintf"); + fatal("cli_vasprintf"); return (l); } @@ -1867,8 +1913,203 @@ cli_cleanup_files(const char *spath) printf("couldn't rmdir %s\n", spath); } +static void * +cli_malloc(size_t len) +{ + void *ptr; + + if ((ptr = calloc(1, len)) == NULL) + fatal("calloc: %s", errno_s); + + return (ptr); +} + +static void * +cli_realloc(void *ptr, size_t len) +{ + void *nptr; + + if ((nptr = realloc(ptr, len)) == NULL) + fatal("realloc: %s", errno_s); + + return (nptr); +} + +static char * +cli_strdup(const char *string) +{ + char *copy; + + if ((copy = strdup(string)) == NULL) + fatal("strdup: %s", errno_s); + + return (copy); +} + +struct cli_buf * +cli_buf_alloc(size_t initial) +{ + struct cli_buf *buf; + + buf = cli_malloc(sizeof(*buf)); + + if (initial > 0) + buf->data = cli_malloc(initial); + else + buf->data = NULL; + + buf->length = initial; + buf->offset = 0; + + return (buf); +} + +void +cli_buf_free(struct cli_buf *buf) +{ + free(buf->data); + buf->data = NULL; + buf->offset = 0; + buf->length = 0; + free(buf); +} + +void +cli_buf_append(struct cli_buf *buf, const void *d, size_t len) +{ + if ((buf->offset + len) < len) + fatal("overflow in cli_buf_append"); + + if ((buf->offset + len) > buf->length) { + buf->length += len; + buf->data = cli_realloc(buf->data, buf->length); + } + + memcpy((buf->data + buf->offset), d, len); + buf->offset += len; +} + +void +cli_buf_appendv(struct cli_buf *buf, const char *fmt, va_list args) +{ + int l; + va_list copy; + char *b, sb[BUFSIZ]; + + va_copy(copy, args); + + l = vsnprintf(sb, sizeof(sb), fmt, args); + if (l == -1) + fatal("cli_buf_appendv(): vsnprintf error"); + + if ((size_t)l >= sizeof(sb)) { + l = vasprintf(&b, fmt, copy); + if (l == -1) + fatal("cli_buf_appendv(): error or truncation"); + } else { + b = sb; + } + + cli_buf_append(buf, b, l); + if (b != sb) + free(b); + + va_end(copy); +} + +void +cli_buf_appendf(struct cli_buf *buf, const char *fmt, ...) +{ + va_list args; + + va_start(args, fmt); + cli_buf_appendv(buf, fmt, args); + va_end(args); +} + +char * +cli_buf_stringify(struct cli_buf *buf, size_t *len) +{ + char c; + + if (len != NULL) + *len = buf->offset; + + c = '\0'; + cli_buf_append(buf, &c, sizeof(c)); + + return ((char *)buf->data); +} + +static int +cli_split_string(char *input, const char *delim, char **out, size_t ele) +{ + int count; + char **ap; + + if (ele == 0) + return (0); + + count = 0; + for (ap = out; ap < &out[ele - 1] && + (*ap = strsep(&input, delim)) != NULL;) { + if (**ap != '\0') { + ap++; + count++; + } + } + + *ap = NULL; + return (count); +} + +static char * +cli_read_line(FILE *fp, char *in, size_t len) +{ + char *p, *t; + + if (fgets(in, len, fp) == NULL) + return (NULL); + + p = in; + in[strcspn(in, "\n")] = '\0'; + + while (isspace(*(unsigned char *)p)) + p++; + + if (p[0] == '#' || p[0] == '\0') { + p[0] = '\0'; + return (p); + } + + for (t = p; *t != '\0'; t++) { + if (*t == '\t') + *t = ' '; + } + + return (p); +} + +static char * +cli_text_trim(char *string, size_t len) +{ + char *end; + + if (len == 0) + return (string); + + end = (string + len) - 1; + while (isspace(*(unsigned char *)string) && string < end) + string++; + + while (isspace(*(unsigned char *)end) && end > string) + *(end)-- = '\0'; + + return (string); +} + static void -cli_fatal(const char *fmt, ...) +fatal(const char *fmt, ...) { va_list args; char buf[2048]; diff --git a/src/http.c b/src/http.c @@ -29,6 +29,10 @@ #include "kore.h" #include "http.h" +#if defined(KORE_USE_PYTHON) +#include "python_api.h" +#endif + #if defined(KORE_USE_PGSQL) #include "pgsql.h" #endif diff --git a/src/kore.c b/src/kore.c @@ -63,7 +63,7 @@ static void usage(void) { #if !defined(KORE_SINGLE_BINARY) - fprintf(stderr, "Usage: kore [options | command]\n"); + fprintf(stderr, "Usage: kore [options]\n"); #else fprintf(stderr, "Usage: %s [options]\n", __progname); #endif @@ -81,12 +81,8 @@ usage(void) 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"); + fprintf(stderr, "\nFind more information on https://kore.io\n"); exit(1); -#endif } static void @@ -171,14 +167,6 @@ 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; LIST_INIT(&listeners);