2014-07-31 23:12:14 +02:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2014 Joris Vink <joris@coders.se>
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, and distribute this software for any
|
|
|
|
* purpose with or without fee is hereby granted, provided that the above
|
|
|
|
* copyright notice and this permission notice appear in all copies.
|
|
|
|
*
|
|
|
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
|
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
|
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
|
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
|
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
|
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
|
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <sys/param.h>
|
2015-05-09 14:14:49 +02:00
|
|
|
#include <sys/types.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/queue.h>
|
|
|
|
#include <sys/wait.h>
|
2014-08-01 15:55:09 +02:00
|
|
|
#include <sys/mman.h>
|
2016-01-22 12:08:13 +01:00
|
|
|
#include <sys/time.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 17:10:47 +02:00
|
|
|
#include <openssl/pem.h>
|
|
|
|
#include <openssl/x509v3.h>
|
|
|
|
|
2014-08-11 13:08:26 +02:00
|
|
|
#include <ctype.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
#include <errno.h>
|
|
|
|
#include <dirent.h>
|
|
|
|
#include <libgen.h>
|
2014-08-01 15:55:09 +02:00
|
|
|
#include <inttypes.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
#include <fcntl.h>
|
2014-08-11 16:11:37 +02:00
|
|
|
#include <time.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
#include <stdarg.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
2014-08-03 16:36:16 +02:00
|
|
|
#include <utime.h>
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
#include "kore.h"
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2015-06-14 16:54:44 +02:00
|
|
|
#if defined(OpenBSD) || defined(__FreeBSD_version) || \
|
2015-06-14 17:21:16 +02:00
|
|
|
defined(NetBSD) || defined(__DragonFly_version)
|
2014-08-01 15:55:09 +02:00
|
|
|
#define PRI_TIME_T "d"
|
|
|
|
#endif
|
|
|
|
|
2016-02-01 15:33:40 +01:00
|
|
|
#if defined(__linux__)
|
2014-08-01 15:55:09 +02:00
|
|
|
#if defined(__x86_64__)
|
|
|
|
#define PRI_TIME_T PRIu64
|
|
|
|
#else
|
|
|
|
#define PRI_TIME_T "ld"
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(__MACH__)
|
|
|
|
#define PRI_TIME_T "ld"
|
|
|
|
#endif
|
|
|
|
|
2015-12-04 15:16:56 +01:00
|
|
|
#define LD_FLAGS_MAX 30
|
|
|
|
#define CFLAGS_MAX 30
|
2016-06-29 16:25:52 +02:00
|
|
|
#define CXXFLAGS_MAX CFLAGS_MAX
|
2016-06-26 22:47:35 +02:00
|
|
|
|
|
|
|
#define BUILD_NOBUILD 0
|
2016-06-29 16:25:52 +02:00
|
|
|
#define BUILD_C 1
|
2016-06-26 22:47:35 +02:00
|
|
|
#define BUILD_CXX 2
|
2014-08-03 17:44:29 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
struct buildopt {
|
|
|
|
char *name;
|
2016-07-06 16:16:15 +02:00
|
|
|
char *kore_source;
|
|
|
|
char *kore_flavor;
|
|
|
|
int single_binary;
|
2016-01-27 21:32:57 +01:00
|
|
|
struct kore_buf *cflags;
|
2016-06-26 22:47:35 +02:00
|
|
|
struct kore_buf *cxxflags;
|
2016-01-27 21:32:57 +01:00
|
|
|
struct kore_buf *ldflags;
|
|
|
|
TAILQ_ENTRY(buildopt) list;
|
|
|
|
};
|
|
|
|
|
|
|
|
TAILQ_HEAD(buildopt_list, buildopt);
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
struct cmd {
|
|
|
|
const char *name;
|
|
|
|
const char *descr;
|
|
|
|
void (*cb)(int, char **);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct filegen {
|
|
|
|
void (*cb)(void);
|
|
|
|
};
|
|
|
|
|
|
|
|
struct cfile {
|
2014-08-03 16:36:16 +02:00
|
|
|
struct stat st;
|
2015-04-02 13:30:43 +02:00
|
|
|
int build;
|
2014-08-01 15:55:09 +02:00
|
|
|
char *name;
|
2014-07-31 23:12:14 +02:00
|
|
|
char *fpath;
|
|
|
|
char *opath;
|
|
|
|
TAILQ_ENTRY(cfile) list;
|
|
|
|
};
|
|
|
|
|
|
|
|
TAILQ_HEAD(cfile_list, cfile);
|
|
|
|
|
2015-05-19 09:45:04 +02:00
|
|
|
static void cli_fatal(const char *, ...) __attribute__((noreturn));
|
2014-08-01 15:55:09 +02:00
|
|
|
static void cli_file_close(int);
|
2016-07-06 16:16:15 +02:00
|
|
|
static void cli_run_kore(void);
|
2014-08-01 17:10:47 +02:00
|
|
|
static void cli_generate_certs(void);
|
2014-08-01 13:59:47 +02:00
|
|
|
static void cli_link_library(void *);
|
2016-07-06 16:16:15 +02:00
|
|
|
static void cli_compile_kore(void *);
|
2016-06-26 22:47:35 +02:00
|
|
|
static void cli_compile_source_file(void *);
|
2014-08-01 13:59:47 +02:00
|
|
|
static void cli_mkdir(const char *, int);
|
|
|
|
static int cli_dir_exists(const char *);
|
2014-08-03 15:30:53 +02:00
|
|
|
static int cli_file_exists(const char *);
|
2014-08-01 15:55:09 +02:00
|
|
|
static void cli_cleanup_files(const char *);
|
2016-01-27 21:32:57 +01:00
|
|
|
static void cli_build_cflags(struct buildopt *);
|
2016-06-26 22:47:35 +02:00
|
|
|
static void cli_build_cxxflags(struct buildopt *);
|
2016-01-27 21:32:57 +01:00
|
|
|
static void cli_build_ldflags(struct buildopt *);
|
2014-08-01 15:55:09 +02:00
|
|
|
static void cli_file_writef(int, const char *, ...);
|
|
|
|
static void cli_file_open(const char *, int, int *);
|
2014-08-03 16:36:16 +02:00
|
|
|
static void cli_file_remove(char *, struct dirent *);
|
2014-08-03 16:55:16 +02:00
|
|
|
static void cli_build_asset(char *, struct dirent *);
|
2014-08-01 13:59:47 +02:00
|
|
|
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 *);
|
2014-08-03 16:55:16 +02:00
|
|
|
static void cli_write_asset(const char *, const char *);
|
2016-07-06 16:16:15 +02:00
|
|
|
static void cli_register_kore_file(char *, struct dirent *);
|
2016-06-28 05:33:51 +02:00
|
|
|
static void cli_register_source_file(char *, struct dirent *);
|
2014-08-01 13:59:47 +02:00
|
|
|
static void cli_file_create(const char *, const char *, size_t);
|
2014-08-03 16:36:16 +02:00
|
|
|
static int cli_file_requires_build(struct stat *, const char *);
|
2014-08-01 15:55:09 +02:00
|
|
|
static void cli_find_files(const char *,
|
|
|
|
void (*cb)(char *, struct dirent *));
|
2016-06-26 22:47:35 +02:00
|
|
|
static void cli_add_source_file(char *, char *, char *,
|
2016-01-27 21:32:57 +01:00
|
|
|
struct stat *, int);
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
static struct buildopt *cli_buildopt_default(void);
|
2016-01-27 21:32:57 +01:00
|
|
|
static struct buildopt *cli_buildopt_new(const char *);
|
|
|
|
static struct buildopt *cli_buildopt_find(const char *);
|
|
|
|
static void cli_buildopt_cleanup(void);
|
|
|
|
static void cli_buildopt_parse(const char *);
|
|
|
|
static void cli_buildopt_cflags(struct buildopt *, const char *);
|
2016-06-26 22:47:35 +02:00
|
|
|
static void cli_buildopt_cxxflags(struct buildopt *, const char *);
|
2016-01-27 21:32:57 +01:00
|
|
|
static void cli_buildopt_ldflags(struct buildopt *, const char *);
|
2016-07-06 16:16:15 +02:00
|
|
|
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 *);
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
static void cli_flavor_load(void);
|
|
|
|
static void cli_flavor_change(const char *);
|
2015-04-01 13:02:53 +02:00
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
static void cli_run(int, char **);
|
|
|
|
static void cli_help(int, char **);
|
|
|
|
static void cli_build(int, char **);
|
2014-08-03 16:36:16 +02:00
|
|
|
static void cli_clean(int, char **);
|
2014-08-01 13:59:47 +02:00
|
|
|
static void cli_create(int, char **);
|
2016-01-27 21:32:57 +01:00
|
|
|
static void cli_flavor(int, char **);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
static void file_create_src(void);
|
|
|
|
static void file_create_config(void);
|
|
|
|
static void file_create_gitignore(void);
|
|
|
|
|
|
|
|
static struct cmd cmds[] = {
|
2014-08-03 16:36:16 +02:00
|
|
|
{ "help", "this help text", cli_help },
|
2015-05-18 21:34:39 +02:00
|
|
|
{ "run", "run an application (-fnr implied)", cli_run },
|
2014-08-03 16:36:16 +02:00
|
|
|
{ "build", "build an application", cli_build },
|
|
|
|
{ "clean", "cleanup the build files", cli_clean },
|
|
|
|
{ "create", "create a new application skeleton", cli_create },
|
2016-01-27 21:32:57 +01:00
|
|
|
{ "flavor", "switch build flavor", cli_flavor },
|
2014-08-01 13:59:47 +02:00
|
|
|
{ NULL, NULL, NULL }
|
2014-07-31 23:12:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static struct filegen gen_files[] = {
|
|
|
|
{ file_create_src },
|
|
|
|
{ file_create_config },
|
|
|
|
{ file_create_gitignore },
|
|
|
|
{ NULL }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *gen_dirs[] = {
|
|
|
|
"src",
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2014-08-01 17:10:47 +02:00
|
|
|
"cert",
|
2014-08-01 17:17:34 +02:00
|
|
|
#endif
|
2014-07-31 23:12:14 +02:00
|
|
|
"conf",
|
2014-08-03 16:55:16 +02:00
|
|
|
"assets",
|
2014-07-31 23:12:14 +02:00
|
|
|
NULL
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *src_data =
|
|
|
|
"#include <kore/kore.h>\n"
|
|
|
|
"#include <kore/http.h>\n"
|
|
|
|
"\n"
|
|
|
|
"int\t\tpage(struct http_request *);\n"
|
|
|
|
"\n"
|
|
|
|
"int\n"
|
|
|
|
"page(struct http_request *req)\n"
|
|
|
|
"{\n"
|
|
|
|
"\thttp_response(req, 200, NULL, 0);\n"
|
|
|
|
"\treturn (KORE_RESULT_OK);\n"
|
|
|
|
"}\n";
|
|
|
|
|
|
|
|
static const char *config_data =
|
2016-01-27 21:32:57 +01:00
|
|
|
"# %s configuration\n"
|
2014-07-31 23:12:14 +02:00
|
|
|
"\n"
|
|
|
|
"bind\t\t127.0.0.1 8888\n"
|
|
|
|
"load\t\t./%s.so\n"
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2015-05-06 10:59:43 +02:00
|
|
|
"tls_dhparam\tdh2048.pem\n"
|
2015-02-03 13:17:59 +01:00
|
|
|
#endif
|
2014-07-31 23:12:14 +02:00
|
|
|
"\n"
|
2016-07-07 12:36:08 +02:00
|
|
|
"domain * {\n"
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2014-08-01 17:10:47 +02:00
|
|
|
"\tcertfile\tcert/server.crt\n"
|
|
|
|
"\tcertkey\t\tcert/server.key\n"
|
2014-08-01 17:17:34 +02:00
|
|
|
#endif
|
2014-07-31 23:12:14 +02:00
|
|
|
"\tstatic\t/\tpage\n"
|
|
|
|
"}\n";
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static const char *build_data =
|
|
|
|
"# %s build config\n"
|
|
|
|
"# You can switch flavors using: kore flavor [newflavor]\n"
|
|
|
|
"\n"
|
2016-07-06 16:16:15 +02:00
|
|
|
"# 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"
|
2016-06-26 22:47:35 +02:00
|
|
|
"# The flags below are shared between flavors\n"
|
2016-01-27 21:32:57 +01:00
|
|
|
"cflags=-Wall -Wmissing-declarations -Wshadow\n"
|
|
|
|
"cflags=-Wstrict-prototypes -Wmissing-prototypes\n"
|
|
|
|
"cflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n"
|
|
|
|
"\n"
|
2016-06-26 22:47:35 +02:00
|
|
|
"cxxflags=-Wall -Wmissing-declarations -Wshadow\n"
|
|
|
|
"cxxflags=-Wpointer-arith -Wcast-qual -Wsign-compare\n"
|
|
|
|
"\n"
|
2016-01-27 21:32:57 +01:00
|
|
|
"dev {\n"
|
2016-06-26 22:47:35 +02:00
|
|
|
" # These flags are added to the shared ones when\n"
|
2016-01-27 21:32:57 +01:00
|
|
|
" # you build the \"dev\" flavor.\n"
|
|
|
|
" cflags=-g\n"
|
2016-06-26 22:47:35 +02:00
|
|
|
" cxxflags=-g\n"
|
2016-01-27 21:32:57 +01:00
|
|
|
"}\n"
|
|
|
|
"\n"
|
|
|
|
"#prod {\n"
|
2016-06-26 22:47:35 +02:00
|
|
|
"# You can specify additional flags here which are only\n"
|
2016-01-27 21:32:57 +01:00
|
|
|
"# included if you build with the \"prod\" flavor.\n"
|
|
|
|
"#}\n";
|
|
|
|
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2015-02-03 13:17:59 +01:00
|
|
|
static const char *dh2048_data =
|
|
|
|
"-----BEGIN DH PARAMETERS-----\n"
|
|
|
|
"MIIBCAKCAQEAn4f4Qn5SudFjEYPWTbUaOTLUH85YWmmPFW1+b5bRa9ygr+1wfamv\n"
|
|
|
|
"VKVT7jO8c4msSNikUf6eEfoH0H4VTCaj+Habwu+Sj+I416r3mliMD4SjNsUJrBrY\n"
|
|
|
|
"Y0QV3ZUgZz4A8ARk/WwQcRl8+ZXJz34IaLwAcpyNhoV46iHVxW0ty8ND0U4DIku/\n"
|
|
|
|
"PNayKimu4BXWXk4RfwNVP59t8DQKqjshZ4fDnbotskmSZ+e+FHrd+Kvrq/WButvV\n"
|
|
|
|
"Bzy9fYgnUlJ82g/bziCI83R2xAdtH014fR63MpElkqdNeChb94pPbEdFlNUvYIBN\n"
|
|
|
|
"xx2vTUQMqRbB4UdG2zuzzr5j98HDdblQ+wIBAg==\n"
|
|
|
|
"-----END DH PARAMETERS-----";
|
2015-02-04 19:40:49 +01:00
|
|
|
#endif
|
2015-02-03 13:17:59 +01:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static const char *gitignore = "*.o\n.flavor\n.objs\n%s.so\nassets.h\ncert\n";
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
static int s_fd = -1;
|
2014-07-31 23:12:14 +02:00
|
|
|
static char *appl = NULL;
|
2016-07-06 16:16:15 +02:00
|
|
|
static int run_after = 0;
|
2014-07-31 23:12:14 +02:00
|
|
|
static char *rootdir = NULL;
|
2016-06-26 22:47:35 +02:00
|
|
|
static char *compiler_c = "gcc";
|
|
|
|
static char *compiler_cpp = "g++";
|
|
|
|
static char *compiler_ld = "gcc";
|
2014-07-31 23:12:14 +02:00
|
|
|
static struct cfile_list source_files;
|
2016-01-27 21:32:57 +01:00
|
|
|
static struct buildopt_list build_options;
|
2016-06-28 05:33:51 +02:00
|
|
|
static int source_files_count;
|
|
|
|
static int cxx_files_count;
|
2014-07-31 23:12:14 +02:00
|
|
|
static struct cmd *command = NULL;
|
2016-01-27 21:32:57 +01:00
|
|
|
static int cflags_count = 0;
|
2016-06-26 22:47:35 +02:00
|
|
|
static int cxxflags_count = 0;
|
2016-01-27 21:32:57 +01:00
|
|
|
static int ldflags_count = 0;
|
|
|
|
static char *flavor = NULL;
|
|
|
|
static char *cflags[CFLAGS_MAX];
|
2016-06-26 22:47:35 +02:00
|
|
|
static char *cxxflags[CXXFLAGS_MAX];
|
2016-01-27 21:32:57 +01:00
|
|
|
static char *ldflags[LD_FLAGS_MAX];
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
void
|
|
|
|
kore_cli_usage(int local)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
if (local)
|
|
|
|
fprintf(stderr, "Usage: kore [command]\n");
|
|
|
|
|
|
|
|
fprintf(stderr, "\nAvailable commands:\n");
|
2014-07-31 23:12:14 +02:00
|
|
|
for (i = 0; cmds[i].name != NULL; i++)
|
2014-08-01 13:59:47 +02:00
|
|
|
printf("\t%s\t%s\n", cmds[i].name, cmds[i].descr);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-03 15:22:08 +02:00
|
|
|
fprintf(stderr, "\nThe commands mostly exist for your convenience\n");
|
2014-08-01 15:55:09 +02:00
|
|
|
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");
|
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
fprintf(stderr, "\nFind more information on https://kore.io\n");
|
2014-07-31 23:12:14 +02:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2014-08-01 13:59:47 +02:00
|
|
|
kore_cli_main(int argc, char **argv)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
if (argc < 1)
|
|
|
|
kore_cli_usage(1);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2015-05-09 14:14:49 +02:00
|
|
|
(void)umask(S_IWGRP|S_IWOTH);
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
if ((flavor = strchr(argv[0], ':')) != NULL)
|
|
|
|
*(flavor)++ = '\0';
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
for (i = 0; cmds[i].name != NULL; i++) {
|
|
|
|
if (!strcmp(argv[0], cmds[i].name)) {
|
|
|
|
argc--;
|
|
|
|
argv++;
|
|
|
|
command = &cmds[i];
|
|
|
|
cmds[i].cb(argc, argv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmds[i].name == NULL) {
|
|
|
|
fprintf(stderr, "No such command: %s\n", argv[0]);
|
2014-08-01 13:59:47 +02:00
|
|
|
kore_cli_usage(1);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_help(int argc, char **argv)
|
|
|
|
{
|
|
|
|
kore_cli_usage(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_create(int argc, char **argv)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
char *fpath;
|
|
|
|
|
|
|
|
if (argc != 1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("missing application name");
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
appl = argv[0];
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_mkdir(appl, 0755);
|
2015-02-06 09:02:52 +01:00
|
|
|
rootdir = appl;
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
for (i = 0; gen_dirs[i] != NULL; i++) {
|
2014-08-01 15:55:09 +02:00
|
|
|
(void)cli_vasprintf(&fpath, "%s/%s", appl, gen_dirs[i]);
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_mkdir(fpath, 0755);
|
2014-07-31 23:12:14 +02:00
|
|
|
free(fpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (i = 0; gen_files[i].cb != NULL; i++)
|
|
|
|
gen_files[i].cb();
|
2014-08-01 17:10:47 +02:00
|
|
|
|
|
|
|
cli_generate_certs();
|
2014-08-01 17:13:38 +02:00
|
|
|
|
2015-11-04 02:52:39 +01:00
|
|
|
printf("%s created successfully!\n", appl);
|
2014-08-01 17:17:34 +02:00
|
|
|
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2015-02-03 13:17:59 +01:00
|
|
|
printf("note: do NOT use the created DH parameters/certificates in production\n");
|
2014-08-01 17:17:34 +02:00
|
|
|
#endif
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-01-27 21:32:57 +01:00
|
|
|
cli_flavor(int argc, char **argv)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2016-01-27 21:32:57 +01:00
|
|
|
struct buildopt *bopt;
|
|
|
|
char pwd[MAXPATHLEN], *conf;
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
if (getcwd(pwd, sizeof(pwd)) == NULL)
|
|
|
|
cli_fatal("could not get cwd: %s", errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
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);
|
|
|
|
free(conf);
|
|
|
|
|
|
|
|
TAILQ_INIT(&build_options);
|
|
|
|
(void)cli_buildopt_new("_default");
|
|
|
|
cli_buildopt_parse("conf/build.conf");
|
|
|
|
|
|
|
|
if (argc == 0) {
|
|
|
|
cli_flavor_load();
|
|
|
|
TAILQ_FOREACH(bopt, &build_options, list) {
|
|
|
|
if (!strcmp(bopt->name, "_default"))
|
|
|
|
continue;
|
|
|
|
if (!strcmp(bopt->name, flavor)) {
|
|
|
|
printf("* %s\n", bopt->name);
|
|
|
|
} else {
|
|
|
|
printf(" %s\n", bopt->name);
|
|
|
|
}
|
|
|
|
}
|
2014-07-31 23:12:14 +02:00
|
|
|
} else {
|
2016-01-27 21:32:57 +01:00
|
|
|
cli_flavor_change(argv[0]);
|
|
|
|
printf("changed build flavor to: %s\n", argv[0]);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
cli_buildopt_cleanup();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_build(int argc, char **argv)
|
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
struct dirent dp;
|
2016-01-27 21:32:57 +01:00
|
|
|
struct cfile *cf;
|
|
|
|
struct buildopt *bopt;
|
|
|
|
struct timeval times[2];
|
|
|
|
char *build_path;
|
|
|
|
int requires_relink, l;
|
|
|
|
char *sofile, *config, *data;
|
|
|
|
char *assets_path, *p, *obj_path, *cpath;
|
|
|
|
char pwd[PATH_MAX], *src_path, *assets_header;
|
|
|
|
|
|
|
|
if (getcwd(pwd, sizeof(pwd)) == NULL)
|
|
|
|
cli_fatal("could not get cwd: %s", errno_s);
|
|
|
|
|
|
|
|
rootdir = ".";
|
|
|
|
appl = basename(pwd);
|
|
|
|
|
2014-10-22 17:44:43 +02:00
|
|
|
if ((p = getenv("CC")) != NULL)
|
2016-06-26 22:47:35 +02:00
|
|
|
compiler_c = p;
|
|
|
|
|
|
|
|
if ((p = getenv("CXX")) != NULL)
|
|
|
|
compiler_cpp = p;
|
2014-08-01 14:09:57 +02:00
|
|
|
|
2016-06-28 05:33:51 +02:00
|
|
|
source_files_count = 0;
|
|
|
|
cxx_files_count = 0;
|
2014-07-31 23:12:14 +02:00
|
|
|
TAILQ_INIT(&source_files);
|
2016-01-27 21:32:57 +01:00
|
|
|
TAILQ_INIT(&build_options);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
(void)cli_vasprintf(&src_path, "%s/src", rootdir);
|
2014-08-03 16:55:16 +02:00
|
|
|
(void)cli_vasprintf(&assets_path, "%s/assets", rootdir);
|
2014-08-03 15:30:53 +02:00
|
|
|
(void)cli_vasprintf(&config, "%s/conf/%s.conf", rootdir, appl);
|
2014-08-03 16:55:16 +02:00
|
|
|
(void)cli_vasprintf(&assets_header, "%s/src/assets.h", rootdir);
|
2016-01-27 21:32:57 +01:00
|
|
|
(void)cli_vasprintf(&build_path, "%s/conf/build.conf", rootdir);
|
|
|
|
|
2014-08-03 15:30:53 +02:00
|
|
|
if (!cli_dir_exists(src_path) || !cli_file_exists(config))
|
|
|
|
cli_fatal("%s doesn't appear to be a kore app", appl);
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
cli_flavor_load();
|
|
|
|
bopt = cli_buildopt_new("_default");
|
|
|
|
if (!cli_file_exists(build_path)) {
|
|
|
|
l = cli_vasprintf(&data, build_data, appl);
|
|
|
|
cli_file_create("conf/build.conf", data, l);
|
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
2016-06-28 05:33:51 +02:00
|
|
|
cli_find_files(src_path, cli_register_source_file);
|
|
|
|
free(src_path);
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_buildopt_parse(build_path);
|
|
|
|
free(build_path);
|
2016-01-27 21:32:57 +01:00
|
|
|
|
2014-08-03 15:30:53 +02:00
|
|
|
(void)cli_vasprintf(&obj_path, "%s/.objs", rootdir);
|
|
|
|
if (!cli_dir_exists(obj_path))
|
|
|
|
cli_mkdir(obj_path, 0755);
|
2014-08-03 16:36:16 +02:00
|
|
|
free(obj_path);
|
2014-08-01 12:40:37 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
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);
|
|
|
|
|
2014-08-03 16:55:16 +02:00
|
|
|
(void)unlink(assets_header);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2014-08-03 16:55:16 +02:00
|
|
|
/* Generate the assets. */
|
2016-07-06 16:16:15 +02:00
|
|
|
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");
|
2014-08-03 16:55:16 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (cli_dir_exists(assets_path))
|
2014-08-03 16:55:16 +02:00
|
|
|
cli_find_files(assets_path, cli_build_asset);
|
2016-07-06 16:16:15 +02:00
|
|
|
|
|
|
|
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);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_file_writef(s_fd, "\n#endif\n");
|
|
|
|
cli_file_close(s_fd);
|
|
|
|
|
2014-08-03 16:55:16 +02:00
|
|
|
free(assets_path);
|
2016-07-06 16:16:15 +02:00
|
|
|
free(config);
|
|
|
|
|
|
|
|
if (cxx_files_count > 0)
|
|
|
|
compiler_ld = compiler_cpp;
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
requires_relink = 0;
|
2014-07-31 23:12:14 +02:00
|
|
|
TAILQ_FOREACH(cf, &source_files, list) {
|
2016-06-26 22:47:35 +02:00
|
|
|
if (cf->build == BUILD_NOBUILD)
|
2014-08-03 18:18:48 +02:00
|
|
|
continue;
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
printf("compiling %s\n", cf->name);
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_spawn_proc(cli_compile_source_file, cf);
|
2014-08-03 16:36:16 +02:00
|
|
|
|
|
|
|
times[0].tv_usec = 0;
|
|
|
|
times[0].tv_sec = cf->st.st_mtime;
|
|
|
|
times[1] = times[0];
|
|
|
|
|
|
|
|
if (utimes(cf->opath, times) == -1)
|
|
|
|
printf("utime(%s): %s\n", cf->opath, errno_s);
|
|
|
|
|
|
|
|
requires_relink++;
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
2014-08-01 12:45:31 +02:00
|
|
|
|
2014-08-03 16:55:16 +02:00
|
|
|
(void)unlink(assets_header);
|
|
|
|
free(assets_header);
|
2014-08-01 12:45:31 +02:00
|
|
|
|
2014-08-03 15:17:03 +02:00
|
|
|
(void)cli_vasprintf(&cpath, "%s/cert", rootdir);
|
|
|
|
if (!cli_dir_exists(cpath)) {
|
|
|
|
cli_mkdir(cpath, 0700);
|
|
|
|
cli_generate_certs();
|
|
|
|
}
|
|
|
|
free(cpath);
|
2014-08-03 16:36:16 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->single_binary) {
|
|
|
|
requires_relink++;
|
|
|
|
(void)cli_vasprintf(&sofile, "%s", appl);
|
|
|
|
} else {
|
|
|
|
(void)cli_vasprintf(&sofile, "%s.so", appl);
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
if (!cli_file_exists(sofile))
|
|
|
|
requires_relink++;
|
|
|
|
free(sofile);
|
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
if (requires_relink) {
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_spawn_proc(cli_link_library, bopt);
|
2015-11-04 02:52:39 +01:00
|
|
|
printf("%s built successfully!\n", appl);
|
2014-08-03 16:36:16 +02:00
|
|
|
} else {
|
2016-01-27 21:32:57 +01:00
|
|
|
printf("nothing to be done!\n");
|
2014-08-03 16:36:16 +02:00
|
|
|
}
|
2016-07-06 16:16:15 +02:00
|
|
|
|
|
|
|
if (run_after == 0)
|
|
|
|
cli_buildopt_cleanup();
|
2014-08-03 16:36:16 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_clean(int argc, char **argv)
|
|
|
|
{
|
|
|
|
char pwd[PATH_MAX], *sofile;
|
|
|
|
|
|
|
|
if (cli_dir_exists(".objs"))
|
|
|
|
cli_cleanup_files(".objs");
|
|
|
|
|
|
|
|
if (getcwd(pwd, sizeof(pwd)) == NULL)
|
|
|
|
cli_fatal("could not get cwd: %s", errno_s);
|
|
|
|
|
|
|
|
appl = basename(pwd);
|
|
|
|
(void)cli_vasprintf(&sofile, "%s.so", appl);
|
|
|
|
if (unlink(sofile) == -1 && errno != ENOENT)
|
|
|
|
printf("couldn't unlink %s: %s", sofile, errno_s);
|
|
|
|
|
|
|
|
free(sofile);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_run(int argc, char **argv)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
run_after = 1;
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_build(argc, argv);
|
2014-08-01 09:05:14 +02:00
|
|
|
|
|
|
|
if (chdir(rootdir) == -1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("couldn't change directory to %s", rootdir);
|
2014-08-01 09:05:14 +02:00
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
/*
|
|
|
|
* We are exec()'ing kore again, while we could technically set
|
|
|
|
* the right cli options manually and just continue running.
|
|
|
|
*/
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_run_kore();
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
file_create_src(void)
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
(void)cli_vasprintf(&name, "src/%s.c", appl);
|
|
|
|
cli_file_create(name, src_data, strlen(src_data));
|
2014-07-31 23:12:14 +02:00
|
|
|
free(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
file_create_config(void)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
char *name, *data;
|
|
|
|
|
2014-08-01 13:59:47 +02:00
|
|
|
(void)cli_vasprintf(&name, "conf/%s.conf", appl);
|
2016-01-27 21:32:57 +01:00
|
|
|
l = cli_vasprintf(&data, config_data, appl, appl);
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_create(name, data, l);
|
2014-07-31 23:12:14 +02:00
|
|
|
free(name);
|
|
|
|
free(data);
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
l = cli_vasprintf(&data, build_data, appl);
|
|
|
|
cli_file_create("conf/build.conf", data, l);
|
|
|
|
free(data);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
file_create_gitignore(void)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
char *data;
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
l = cli_vasprintf(&data, gitignore, appl);
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_create(".gitignore", data, l);
|
2014-07-31 23:12:14 +02:00
|
|
|
free(data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_mkdir(const char *fpath, int mode)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
if (mkdir(fpath, mode) == -1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_mkdir(%s): %s", fpath, errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
2014-08-03 15:30:53 +02:00
|
|
|
static int
|
|
|
|
cli_file_exists(const char *fpath)
|
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(fpath, &st) == -1)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (!S_ISREG(st.st_mode))
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
static int
|
|
|
|
cli_file_requires_build(struct stat *fst, const char *opath)
|
|
|
|
{
|
|
|
|
struct stat ost;
|
|
|
|
|
|
|
|
if (stat(opath, &ost) == -1) {
|
|
|
|
if (errno == ENOENT)
|
|
|
|
return (1);
|
|
|
|
cli_fatal("stat(%s): %s", opath, errno_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (fst->st_mtime != ost.st_mtime);
|
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static int
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_dir_exists(const char *fpath)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
struct stat st;
|
|
|
|
|
|
|
|
if (stat(fpath, &st) == -1)
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
if (!S_ISDIR(st.st_mode))
|
|
|
|
return (0);
|
|
|
|
|
|
|
|
return (1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 15:55:09 +02:00
|
|
|
cli_file_open(const char *fpath, int flags, int *fd)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2015-05-08 16:40:51 +02:00
|
|
|
if ((*fd = open(fpath, flags, 0644)) == -1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_file_open(%s): %s", fpath, errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_close(int fd)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
if (close(fd) == -1)
|
|
|
|
printf("warning: close() %s\n", errno_s);
|
|
|
|
}
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
static void
|
|
|
|
cli_file_writef(int fd, const char *fmt, ...)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
char *buf;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
l = vasprintf(&buf, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
if (l == -1)
|
|
|
|
cli_fatal("cli_file_writef");
|
|
|
|
|
|
|
|
cli_file_write(fd, buf, l);
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_write(int fd, const void *buf, size_t len)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
ssize_t r;
|
2014-08-01 10:46:50 +02:00
|
|
|
const u_int8_t *d;
|
2014-07-31 23:12:14 +02:00
|
|
|
size_t written;
|
|
|
|
|
2014-08-01 10:46:50 +02:00
|
|
|
d = buf;
|
2014-07-31 23:12:14 +02:00
|
|
|
written = 0;
|
|
|
|
while (written != len) {
|
2014-08-01 10:46:50 +02:00
|
|
|
r = write(fd, d + written, len - written);
|
2014-07-31 23:12:14 +02:00
|
|
|
if (r == -1) {
|
|
|
|
if (errno == EINTR)
|
|
|
|
continue;
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_file_write: %s", errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
written += r;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_create(const char *name, const char *data, size_t len)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
char *fpath;
|
|
|
|
|
2015-02-06 09:02:52 +01:00
|
|
|
(void)cli_vasprintf(&fpath, "%s/%s", rootdir, name);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
cli_file_open(fpath, O_CREAT | O_TRUNC | O_WRONLY, &fd);
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_file_write(fd, data, len);
|
|
|
|
cli_file_close(fd);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
printf("created %s\n", fpath);
|
|
|
|
free(fpath);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2014-08-03 16:55:16 +02:00
|
|
|
cli_write_asset(const char *n, const char *e)
|
|
|
|
{
|
|
|
|
cli_file_writef(s_fd, "extern u_int8_t asset_%s_%s[];\n", n, e);
|
|
|
|
cli_file_writef(s_fd, "extern u_int32_t asset_len_%s_%s;\n", n, e);
|
|
|
|
cli_file_writef(s_fd, "extern time_t asset_mtime_%s_%s;\n", n, e);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_build_asset(char *fpath, struct dirent *dp)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2014-08-01 15:55:09 +02:00
|
|
|
struct stat st;
|
|
|
|
u_int8_t *d;
|
|
|
|
off_t off;
|
|
|
|
void *base;
|
|
|
|
int in, out;
|
2014-08-11 13:08:26 +02:00
|
|
|
char *cpath, *ext, *opath, *p, *name;
|
|
|
|
|
|
|
|
name = kore_strdup(dp->d_name);
|
2014-08-03 16:36:16 +02:00
|
|
|
|
2014-08-03 16:55:16 +02:00
|
|
|
/* Grab the extension as we're using it in the symbol name. */
|
2014-08-11 13:08:26 +02:00
|
|
|
if ((ext = strrchr(name, '.')) == NULL)
|
|
|
|
cli_fatal("couldn't find ext in %s", name);
|
|
|
|
|
|
|
|
/* Replace dots, spaces, etc etc with underscores. */
|
|
|
|
for (p = name; *p != '\0'; p++) {
|
2014-08-21 23:06:40 +02:00
|
|
|
if (*p == '.' || isspace(*p) || *p == '-')
|
2014-08-11 13:08:26 +02:00
|
|
|
*p = '_';
|
|
|
|
}
|
2014-08-03 16:55:16 +02:00
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
/* Grab inode information. */
|
|
|
|
if (stat(fpath, &st) == -1)
|
|
|
|
cli_fatal("stat: %s %s", fpath, errno_s);
|
|
|
|
|
2015-06-11 19:33:30 +02:00
|
|
|
/* If this file was empty, skip it. */
|
|
|
|
if (st.st_size == 0) {
|
|
|
|
printf("skipping empty asset %s\n", name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-08-11 13:08:26 +02:00
|
|
|
(void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, name);
|
|
|
|
(void)cli_vasprintf(&cpath, "%s/.objs/%s.c", rootdir, name);
|
2014-08-03 18:18:48 +02:00
|
|
|
|
|
|
|
/* Check if the file needs to be built. */
|
2014-08-03 16:36:16 +02:00
|
|
|
if (!cli_file_requires_build(&st, opath)) {
|
2014-08-03 16:55:16 +02:00
|
|
|
*(ext)++ = '\0';
|
2014-08-11 13:08:26 +02:00
|
|
|
cli_write_asset(name, ext);
|
|
|
|
*ext = '_';
|
2016-06-26 22:47:35 +02:00
|
|
|
|
|
|
|
cli_add_source_file(name, cpath, opath, &st, BUILD_NOBUILD);
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(name);
|
2014-08-03 16:36:16 +02:00
|
|
|
return;
|
|
|
|
}
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2015-05-08 16:53:59 +02:00
|
|
|
/* Open the file we're converting. */
|
2014-08-01 15:55:09 +02:00
|
|
|
cli_file_open(fpath, O_RDONLY, &in);
|
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
/* mmap our in file. */
|
2014-08-01 15:55:09 +02:00
|
|
|
if ((base = mmap(NULL, st.st_size,
|
|
|
|
PROT_READ, MAP_PRIVATE, in, 0)) == MAP_FAILED)
|
|
|
|
cli_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);
|
|
|
|
|
2014-08-11 13:08:26 +02:00
|
|
|
/* No longer need name so cut off the extension. */
|
2014-08-11 16:11:37 +02:00
|
|
|
printf("building asset %s\n", dp->d_name);
|
2014-08-01 15:55:09 +02:00
|
|
|
*(ext)++ = '\0';
|
|
|
|
|
|
|
|
/* Start generating the file. */
|
|
|
|
cli_file_writef(out, "/* Auto generated */\n");
|
2016-06-23 16:18:36 +02:00
|
|
|
cli_file_writef(out, "#include <sys/types.h>\n\n");
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2014-08-11 13:08:26 +02:00
|
|
|
/* Write the file data as a byte array. */
|
|
|
|
cli_file_writef(out, "u_int8_t asset_%s_%s[] = {\n", name, ext);
|
2014-08-01 15:55:09 +02:00
|
|
|
d = base;
|
|
|
|
for (off = 0; off < st.st_size; off++)
|
2014-08-01 20:25:02 +02:00
|
|
|
cli_file_writef(out, "0x%02x,", *d++);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2014-08-18 13:57:06 +02:00
|
|
|
/*
|
|
|
|
* Always NUL-terminate the asset, even if this NUL is not included in
|
|
|
|
* the actual length. This way assets can be cast to char * without
|
|
|
|
* any additional thinking for the developer.
|
|
|
|
*/
|
|
|
|
cli_file_writef(out, "0x00");
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
/* Add the meta data. */
|
|
|
|
cli_file_writef(out, "};\n\n");
|
2014-08-03 16:55:16 +02:00
|
|
|
cli_file_writef(out, "u_int32_t asset_len_%s_%s = %" PRIu32 ";\n",
|
2014-08-11 13:08:26 +02:00
|
|
|
name, ext, (u_int32_t)st.st_size);
|
2014-08-03 16:55:16 +02:00
|
|
|
cli_file_writef(out, "time_t asset_mtime_%s_%s = %" PRI_TIME_T ";\n",
|
2014-08-11 13:08:26 +02:00
|
|
|
name, ext, st.st_mtime);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2014-08-03 18:22:12 +02:00
|
|
|
/* Write the file symbols into assets.h so they can be used. */
|
2014-08-11 13:08:26 +02:00
|
|
|
cli_write_asset(name, ext);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
|
|
|
/* Cleanup static file source. */
|
|
|
|
if (munmap(base, st.st_size) == -1)
|
|
|
|
cli_fatal("munmap: %s %s", fpath, errno_s);
|
|
|
|
|
|
|
|
/* Cleanup fds */
|
|
|
|
cli_file_close(in);
|
|
|
|
cli_file_close(out);
|
|
|
|
|
2014-08-11 13:08:26 +02:00
|
|
|
/* Restore the original name */
|
2014-08-01 15:55:09 +02:00
|
|
|
*--ext = '.';
|
|
|
|
|
|
|
|
/* Register the .c file now (cpath is free'd later). */
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_add_source_file(name, cpath, opath, &st, BUILD_C);
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(name);
|
2014-08-03 18:18:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_add_source_file(char *name, char *fpath, char *opath, struct stat *st,
|
2016-01-27 21:32:57 +01:00
|
|
|
int build)
|
2014-08-03 18:18:48 +02:00
|
|
|
{
|
|
|
|
struct cfile *cf;
|
|
|
|
|
2016-06-28 05:33:51 +02:00
|
|
|
source_files_count++;
|
2014-08-01 15:55:09 +02:00
|
|
|
cf = kore_malloc(sizeof(*cf));
|
2014-08-03 18:18:48 +02:00
|
|
|
|
|
|
|
cf->st = *st;
|
|
|
|
cf->build = build;
|
|
|
|
cf->fpath = fpath;
|
2014-08-03 16:36:16 +02:00
|
|
|
cf->opath = opath;
|
2014-08-03 18:18:48 +02:00
|
|
|
cf->name = kore_strdup(name);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&source_files, cf, list);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-06-28 05:33:51 +02:00
|
|
|
cli_register_source_file(char *fpath, struct dirent *dp)
|
2014-08-01 15:55:09 +02:00
|
|
|
{
|
2014-08-03 16:36:16 +02:00
|
|
|
struct stat st;
|
|
|
|
char *ext, *opath;
|
2016-06-26 22:47:35 +02:00
|
|
|
int build;
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2015-04-02 13:30:43 +02:00
|
|
|
if ((ext = strrchr(fpath, '.')) == NULL ||
|
|
|
|
(strcmp(ext, ".c") && strcmp(ext, ".cpp")))
|
2014-08-01 15:55:09 +02:00
|
|
|
return;
|
2015-04-02 13:30:43 +02:00
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
if (stat(fpath, &st) == -1)
|
|
|
|
cli_fatal("stat(%s): %s", fpath, errno_s);
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (!strcmp(ext, ".cpp"))
|
|
|
|
cxx_files_count++;
|
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
(void)cli_vasprintf(&opath, "%s/.objs/%s.o", rootdir, dp->d_name);
|
|
|
|
if (!cli_file_requires_build(&st, opath)) {
|
2016-06-26 22:47:35 +02:00
|
|
|
build = BUILD_NOBUILD;
|
|
|
|
} else if (!strcmp(ext, ".cpp")) {
|
|
|
|
build = BUILD_CXX;
|
|
|
|
} else {
|
|
|
|
build = BUILD_C;
|
2014-08-03 16:36:16 +02:00
|
|
|
}
|
2015-04-02 13:30:43 +02:00
|
|
|
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_add_source_file(dp->d_name, fpath, opath, &st, build);
|
2014-08-01 15:55:09 +02:00
|
|
|
}
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2014-08-03 16:36:16 +02:00
|
|
|
static void
|
|
|
|
cli_file_remove(char *fpath, struct dirent *dp)
|
|
|
|
{
|
|
|
|
if (unlink(fpath) == -1)
|
|
|
|
fprintf(stderr, "couldn't unlink %s: %s", fpath, errno_s);
|
|
|
|
}
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
static void
|
|
|
|
cli_find_files(const char *path, void (*cb)(char *, struct dirent *))
|
|
|
|
{
|
|
|
|
DIR *d;
|
2015-04-07 09:27:58 +02:00
|
|
|
struct stat st;
|
2014-07-31 23:12:14 +02:00
|
|
|
struct dirent *dp;
|
|
|
|
char *fpath;
|
|
|
|
|
|
|
|
if ((d = opendir(path)) == NULL)
|
2014-08-01 15:55:09 +02:00
|
|
|
cli_fatal("cli_find_files: opendir(%s): %s", path, errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
while ((dp = readdir(d)) != NULL) {
|
|
|
|
if (!strcmp(dp->d_name, ".") ||
|
|
|
|
!strcmp(dp->d_name, ".."))
|
|
|
|
continue;
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
(void)cli_vasprintf(&fpath, "%s/%s", path, dp->d_name);
|
2015-04-07 09:27:58 +02:00
|
|
|
if (stat(fpath, &st) == -1) {
|
|
|
|
fprintf(stderr, "stat(%s): %s\n", fpath, errno_s);
|
|
|
|
free(fpath);
|
|
|
|
continue;
|
|
|
|
}
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2015-04-07 09:27:58 +02:00
|
|
|
if (S_ISDIR(st.st_mode)) {
|
2014-08-01 15:55:09 +02:00
|
|
|
cli_find_files(fpath, cb);
|
2014-07-31 23:12:14 +02:00
|
|
|
free(fpath);
|
2015-04-07 09:27:58 +02:00
|
|
|
} else if (S_ISREG(st.st_mode)) {
|
2014-08-01 15:55:09 +02:00
|
|
|
cb(fpath, dp);
|
2015-04-07 09:27:58 +02:00
|
|
|
} else {
|
|
|
|
fprintf(stderr, "ignoring %s\n", fpath);
|
|
|
|
free(fpath);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-13 14:32:57 +02:00
|
|
|
|
|
|
|
closedir(d);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
2014-08-01 17:10:47 +02:00
|
|
|
static void
|
|
|
|
cli_generate_certs(void)
|
|
|
|
{
|
2015-05-25 15:42:34 +02:00
|
|
|
#if !defined(KORE_NO_TLS)
|
2014-08-01 17:10:47 +02:00
|
|
|
BIGNUM *e;
|
|
|
|
FILE *fp;
|
2014-08-11 16:11:37 +02:00
|
|
|
time_t now;
|
2014-08-01 17:10:47 +02:00
|
|
|
X509_NAME *name;
|
|
|
|
EVP_PKEY *pkey;
|
|
|
|
X509 *x509;
|
|
|
|
RSA *kpair;
|
2014-08-11 16:11:37 +02:00
|
|
|
char *fpath, issuer[64];
|
2014-08-01 17:10:47 +02:00
|
|
|
|
2015-05-06 10:21:54 +02:00
|
|
|
/* Write out DH parameters. */
|
|
|
|
cli_file_create("dh2048.pem", dh2048_data, strlen(dh2048_data));
|
|
|
|
|
2014-08-01 17:10:47 +02:00
|
|
|
/* Create new certificate. */
|
|
|
|
if ((x509 = X509_new()) == NULL)
|
|
|
|
cli_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);
|
|
|
|
|
|
|
|
/* Generate RSA keys. */
|
|
|
|
if ((pkey = EVP_PKEY_new()) == NULL)
|
|
|
|
cli_fatal("EVP_PKEY_new(): %s", ssl_errno_s);
|
|
|
|
if ((kpair = RSA_new()) == NULL)
|
|
|
|
cli_fatal("RSA_new(): %s", ssl_errno_s);
|
|
|
|
if ((e = BN_new()) == NULL)
|
|
|
|
cli_fatal("BN_new(): %s", ssl_errno_s);
|
|
|
|
|
|
|
|
if (!BN_set_word(e, 65537))
|
|
|
|
cli_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);
|
|
|
|
|
|
|
|
BN_free(e);
|
|
|
|
|
|
|
|
if (!EVP_PKEY_assign_RSA(pkey, kpair))
|
|
|
|
cli_fatal("EVP_PKEY_assign_RSA(): %s", ssl_errno_s);
|
|
|
|
|
2014-08-11 16:11:37 +02:00
|
|
|
/* Set serial number to current timestamp. */
|
|
|
|
time(&now);
|
|
|
|
if (!ASN1_INTEGER_set(X509_get_serialNumber(x509), now))
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_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);
|
2014-08-11 16:11:37 +02:00
|
|
|
if (!X509_gmtime_adj(X509_get_notAfter(x509),
|
|
|
|
(long)60 * 60 * 24 * 3000))
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_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);
|
|
|
|
|
|
|
|
/* Set certificate information. */
|
|
|
|
if ((name = X509_get_subject_name(x509)) == NULL)
|
|
|
|
cli_fatal("X509_get_subject_name(): %s", ssl_errno_s);
|
|
|
|
|
2014-08-11 16:11:37 +02:00
|
|
|
(void)snprintf(issuer, sizeof(issuer), "kore autogen: %s", appl);
|
2014-08-01 17:10:47 +02:00
|
|
|
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);
|
|
|
|
if (!X509_NAME_add_entry_by_txt(name, "O",
|
2014-08-11 16:11:37 +02:00
|
|
|
MBSTRING_ASC, (const unsigned char *)issuer, -1, -1, 0))
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_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);
|
|
|
|
|
|
|
|
if (!X509_set_issuer_name(x509, name))
|
|
|
|
cli_fatal("X509_set_issuer_name(): %s", ssl_errno_s);
|
|
|
|
|
2014-10-18 01:28:47 +02:00
|
|
|
if (!X509_sign(x509, pkey, EVP_sha256()))
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_fatal("X509_sign(): %s", ssl_errno_s);
|
|
|
|
|
|
|
|
(void)cli_vasprintf(&fpath, "%s/cert/server.key", rootdir);
|
2015-05-08 16:41:48 +02:00
|
|
|
if ((fp = fopen(fpath, "w")) == NULL)
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_fatal("fopen(%s): %s", fpath, errno_s);
|
|
|
|
free(fpath);
|
|
|
|
|
|
|
|
if (!PEM_write_PrivateKey(fp, pkey, NULL, NULL, 0, NULL, NULL))
|
|
|
|
cli_fatal("PEM_write_PrivateKey(): %s", ssl_errno_s);
|
|
|
|
fclose(fp);
|
|
|
|
|
|
|
|
(void)cli_vasprintf(&fpath, "%s/cert/server.crt", rootdir);
|
2015-05-08 16:41:48 +02:00
|
|
|
if ((fp = fopen(fpath, "w")) == NULL)
|
2014-08-01 17:10:47 +02:00
|
|
|
cli_fatal("fopen(%s): %s", fpath, errno_s);
|
|
|
|
free(fpath);
|
|
|
|
|
|
|
|
if (!PEM_write_X509(fp, x509))
|
2014-09-19 15:01:56 +02:00
|
|
|
cli_fatal("PEM_write_X509(%s)", errno_s);
|
2014-08-03 17:17:11 +02:00
|
|
|
fclose(fp);
|
2014-08-01 17:10:47 +02:00
|
|
|
|
|
|
|
EVP_PKEY_free(pkey);
|
|
|
|
X509_free(x509);
|
2014-08-01 17:17:34 +02:00
|
|
|
#endif
|
2014-08-01 17:10:47 +02:00
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static void
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_compile_source_file(void *arg)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2016-01-27 21:32:57 +01:00
|
|
|
int idx, i;
|
2014-07-31 23:12:14 +02:00
|
|
|
struct cfile *cf = arg;
|
2016-01-27 21:32:57 +01:00
|
|
|
char *args[32 + CFLAGS_MAX];
|
2016-06-26 22:47:35 +02:00
|
|
|
char *compiler;
|
|
|
|
char **flags;
|
|
|
|
int flags_count;
|
|
|
|
|
|
|
|
switch (cf->build) {
|
2016-06-29 16:25:52 +02:00
|
|
|
case BUILD_C:
|
|
|
|
compiler = compiler_c;
|
|
|
|
flags = cflags;
|
|
|
|
flags_count = cflags_count;
|
|
|
|
break;
|
|
|
|
case BUILD_CXX:
|
|
|
|
compiler = compiler_cpp;
|
|
|
|
flags = cxxflags;
|
|
|
|
flags_count = cxxflags_count;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
cli_fatal("cli_compile_file: unexpected file type: %d",
|
|
|
|
cf->build);
|
|
|
|
break;
|
2016-06-26 22:47:35 +02:00
|
|
|
}
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-08-03 17:33:40 +02:00
|
|
|
idx = 0;
|
|
|
|
args[idx++] = compiler;
|
2015-06-11 19:20:08 +02:00
|
|
|
|
2016-06-26 22:47:35 +02:00
|
|
|
for (i = 0; i < flags_count; i++)
|
|
|
|
args[idx++] = flags[i];
|
2015-04-02 13:30:43 +02:00
|
|
|
|
2015-04-01 14:59:27 +02:00
|
|
|
args[idx++] = "-c";
|
|
|
|
args[idx++] = cf->fpath;
|
|
|
|
args[idx++] = "-o";
|
|
|
|
args[idx++] = cf->opath;
|
|
|
|
args[idx] = NULL;
|
2015-04-02 13:30:43 +02:00
|
|
|
|
|
|
|
execvp(compiler, args);
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_fatal("failed to start '%s': %s", compiler, errno_s);
|
2015-04-01 09:28:03 +02:00
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_link_library(void *arg)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
struct cfile *cf;
|
2016-07-06 16:16:15 +02:00
|
|
|
struct buildopt *bopt;
|
2016-01-27 21:32:57 +01:00
|
|
|
int idx, i;
|
2016-07-06 16:16:15 +02:00
|
|
|
char *output;
|
2016-06-28 05:33:51 +02:00
|
|
|
char *args[source_files_count + 11 + LD_FLAGS_MAX];
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
bopt = arg;
|
|
|
|
|
|
|
|
if (bopt->single_binary)
|
|
|
|
(void)cli_vasprintf(&output, "%s/%s", rootdir, appl);
|
|
|
|
else
|
|
|
|
(void)cli_vasprintf(&output, "%s/%s.so", rootdir, appl);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2014-07-31 23:19:18 +02:00
|
|
|
idx = 0;
|
2016-06-26 22:47:35 +02:00
|
|
|
args[idx++] = compiler_ld;
|
2014-07-31 23:19:18 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
TAILQ_FOREACH(cf, &source_files, list)
|
2014-07-31 23:12:14 +02:00
|
|
|
args[idx++] = cf->opath;
|
2015-04-02 13:30:43 +02:00
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
for (i = 0; i < ldflags_count; i++)
|
|
|
|
args[idx++] = ldflags[i];
|
2014-11-19 14:20:31 +01:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->single_binary) {
|
|
|
|
args[idx++] = "-rdynamic";
|
|
|
|
#if defined(__linux__)
|
|
|
|
args[idx++] = "-ldl";
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
args[idx++] = "-o";
|
2016-07-06 16:16:15 +02:00
|
|
|
args[idx++] = output;
|
2014-07-31 23:12:14 +02:00
|
|
|
args[idx] = NULL;
|
|
|
|
|
2016-06-26 22:47:35 +02:00
|
|
|
execvp(compiler_ld, args);
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_fatal("failed to start '%s': %s", compiler_ld, errno_s);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_compile_kore(void *arg)
|
|
|
|
{
|
|
|
|
struct buildopt *bopt = arg;
|
|
|
|
int idx, i, fcnt;
|
|
|
|
char *obj, *args[16], pwd[MAXPATHLEN], *flavors[7];
|
|
|
|
|
|
|
|
if (getcwd(pwd, sizeof(pwd)) == NULL)
|
|
|
|
cli_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");
|
|
|
|
|
|
|
|
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);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2016-07-06 16:16:15 +02:00
|
|
|
cli_run_kore(void)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
struct buildopt *bopt;
|
|
|
|
char *args[4], *cpath, *cmd, *flags;
|
|
|
|
|
|
|
|
bopt = cli_buildopt_default();
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
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);
|
|
|
|
}
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
args[0] = cmd;
|
|
|
|
args[1] = flags;
|
|
|
|
|
|
|
|
if (cpath != NULL) {
|
|
|
|
args[2] = cpath;
|
|
|
|
args[3] = NULL;
|
|
|
|
} else {
|
|
|
|
args[2] = NULL;
|
|
|
|
}
|
2014-07-31 23:12:14 +02:00
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
execvp(args[0], args);
|
|
|
|
cli_fatal("failed to start '%s': %s", args[0], errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static void
|
|
|
|
cli_buildopt_parse(const char *path)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
struct buildopt *bopt;
|
2016-02-01 21:33:51 +01:00
|
|
|
char buf[BUFSIZ], *p, *t;
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if ((fp = fopen(path, "r")) == NULL)
|
|
|
|
cli_fatal("cli_buildopt_parse: fopen(%s): %s", path, errno_s);
|
|
|
|
|
|
|
|
bopt = NULL;
|
|
|
|
|
2016-02-01 22:10:10 +01:00
|
|
|
while ((p = kore_read_line(fp, buf, sizeof(buf))) != NULL) {
|
|
|
|
if (strlen(p) == 0)
|
2016-01-27 21:32:57 +01:00
|
|
|
continue;
|
|
|
|
|
|
|
|
if (bopt != NULL && !strcmp(p, "}")) {
|
|
|
|
bopt = NULL;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bopt == NULL) {
|
|
|
|
if ((t = strchr(p, '=')) != NULL)
|
|
|
|
goto parse_option;
|
|
|
|
if ((t = strchr(p, ' ')) == NULL)
|
|
|
|
cli_fatal("unexpected '%s'", p);
|
|
|
|
*(t)++ = '\0';
|
|
|
|
if (strcmp(t, "{"))
|
|
|
|
cli_fatal("expected '{', got '%s'", t);
|
|
|
|
bopt = cli_buildopt_new(p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((t = strchr(p, '=')) == NULL) {
|
|
|
|
printf("bad buildopt line: '%s'\n", p);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
parse_option:
|
|
|
|
*(t)++ = '\0';
|
|
|
|
|
2016-02-01 21:33:51 +01:00
|
|
|
p = kore_text_trim(p, strlen(p));
|
|
|
|
t = kore_text_trim(t, strlen(t));
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if (!strcasecmp(p, "cflags")) {
|
|
|
|
cli_buildopt_cflags(bopt, t);
|
2016-06-26 22:47:35 +02:00
|
|
|
} else if (!strcasecmp(p, "cxxflags")) {
|
|
|
|
cli_buildopt_cxxflags(bopt, t);
|
2016-01-27 21:32:57 +01:00
|
|
|
} else if (!strcasecmp(p, "ldflags")) {
|
|
|
|
cli_buildopt_ldflags(bopt, t);
|
2016-07-06 16:16:15 +02:00
|
|
|
} 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);
|
2016-01-27 21:32:57 +01:00
|
|
|
} else {
|
2016-07-06 16:16:15 +02:00
|
|
|
printf("ignoring unknown option '%s'\n", p);
|
2016-01-27 21:32:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct buildopt *
|
|
|
|
cli_buildopt_new(const char *name)
|
|
|
|
{
|
|
|
|
struct buildopt *bopt;
|
|
|
|
|
|
|
|
bopt = kore_malloc(sizeof(*bopt));
|
|
|
|
bopt->cflags = NULL;
|
2016-06-26 22:47:35 +02:00
|
|
|
bopt->cxxflags = NULL;
|
2016-01-27 21:32:57 +01:00
|
|
|
bopt->ldflags = NULL;
|
2016-07-06 16:16:15 +02:00
|
|
|
bopt->single_binary = 0;
|
|
|
|
bopt->kore_source = NULL;
|
|
|
|
bopt->kore_flavor = NULL;
|
2016-01-27 21:32:57 +01:00
|
|
|
bopt->name = kore_strdup(name);
|
|
|
|
|
|
|
|
TAILQ_INSERT_TAIL(&build_options, bopt, list);
|
|
|
|
return (bopt);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct buildopt *
|
|
|
|
cli_buildopt_find(const char *name)
|
|
|
|
{
|
|
|
|
struct buildopt *bopt;
|
|
|
|
|
|
|
|
TAILQ_FOREACH(bopt, &build_options, list) {
|
|
|
|
if (!strcmp(bopt->name, name))
|
|
|
|
return (bopt);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (NULL);
|
|
|
|
}
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
static struct buildopt *
|
|
|
|
cli_buildopt_default(void)
|
|
|
|
{
|
|
|
|
struct buildopt *bopt;
|
|
|
|
|
|
|
|
if ((bopt = cli_buildopt_find("_default")) == NULL)
|
|
|
|
fatal("no _default buildopt options");
|
|
|
|
|
|
|
|
return (bopt);
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static void
|
|
|
|
cli_buildopt_cleanup(void)
|
|
|
|
{
|
|
|
|
struct buildopt *bopt, *next;
|
|
|
|
|
|
|
|
for (bopt = TAILQ_FIRST(&build_options); bopt != NULL; bopt = next) {
|
|
|
|
next = TAILQ_NEXT(bopt, list);
|
|
|
|
TAILQ_REMOVE(&build_options, bopt, list);
|
|
|
|
|
|
|
|
if (bopt->cflags != NULL)
|
|
|
|
kore_buf_free(bopt->cflags);
|
2016-06-26 22:47:35 +02:00
|
|
|
if (bopt->cxxflags != NULL)
|
|
|
|
kore_buf_free(bopt->cxxflags);
|
2016-01-27 21:32:57 +01:00
|
|
|
if (bopt->ldflags != NULL)
|
|
|
|
kore_buf_free(bopt->ldflags);
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->kore_source != NULL)
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(bopt->kore_source);
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->kore_flavor != NULL)
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(bopt->kore_flavor);
|
|
|
|
kore_free(bopt);
|
2016-01-27 21:32:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_buildopt_cflags(struct buildopt *bopt, const char *string)
|
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt == NULL)
|
|
|
|
bopt = cli_buildopt_default();
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if (bopt->cflags == NULL)
|
|
|
|
bopt->cflags = kore_buf_create(128);
|
|
|
|
|
|
|
|
kore_buf_appendf(bopt->cflags, "%s ", string);
|
|
|
|
}
|
|
|
|
|
2016-06-26 22:47:35 +02:00
|
|
|
static void
|
|
|
|
cli_buildopt_cxxflags(struct buildopt *bopt, const char *string)
|
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt == NULL)
|
|
|
|
bopt = cli_buildopt_default();
|
2016-06-26 22:47:35 +02:00
|
|
|
|
|
|
|
if (bopt->cxxflags == NULL)
|
|
|
|
bopt->cxxflags = kore_buf_create(128);
|
|
|
|
|
|
|
|
kore_buf_appendf(bopt->cxxflags, "%s ", string);
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static void
|
|
|
|
cli_buildopt_ldflags(struct buildopt *bopt, const char *string)
|
|
|
|
{
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt == NULL)
|
|
|
|
bopt = cli_buildopt_default();
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if (bopt->ldflags == NULL)
|
|
|
|
bopt->ldflags = kore_buf_create(128);
|
|
|
|
|
|
|
|
kore_buf_appendf(bopt->ldflags, "%s ", string);
|
|
|
|
}
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
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)
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(bopt->kore_source);
|
2016-07-06 16:16:15 +02:00
|
|
|
|
|
|
|
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)
|
2016-07-12 13:54:14 +02:00
|
|
|
kore_free(bopt->kore_flavor);
|
2016-07-06 16:16:15 +02:00
|
|
|
|
|
|
|
bopt->kore_flavor = kore_strdup(string);
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static void
|
2016-06-26 22:47:35 +02:00
|
|
|
cli_build_flags_common(struct kore_buf* buf)
|
2016-01-27 21:32:57 +01:00
|
|
|
{
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf,
|
2016-01-27 21:32:57 +01:00
|
|
|
"-fPIC -I%s/src -I%s/src/includes ", rootdir, rootdir);
|
|
|
|
#if defined(PREFIX)
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-I%s/include ", PREFIX);
|
2016-01-27 21:32:57 +01:00
|
|
|
#else
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-I/usr/local/include ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
|
|
|
#if defined(__MACH__)
|
|
|
|
/* Add default openssl include path from homebrew / ports under OSX. */
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-I/opt/local/include ");
|
|
|
|
kore_buf_appendf(buf, "-I/usr/local/opt/openssl/include ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
|
|
|
#if defined(KORE_USE_PGSQL)
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-I%s ", PGSQL_INCLUDE_PATH);
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
|
|
|
#if defined(KORE_NO_HTTP)
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-DKORE_NO_HTTP ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
|
|
|
#if defined(KORE_NO_TLS)
|
2016-06-26 22:47:35 +02:00
|
|
|
kore_buf_appendf(buf, "-DKORE_NO_TLS ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
2016-06-26 22:47:35 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_build_cflags(struct buildopt *bopt)
|
|
|
|
{
|
|
|
|
struct buildopt *obopt;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
if ((obopt = cli_buildopt_find(flavor)) == NULL)
|
|
|
|
cli_fatal("no such build flavor: %s", flavor);
|
|
|
|
|
|
|
|
if (bopt->cflags == NULL)
|
|
|
|
bopt->cflags = kore_buf_create(128);
|
|
|
|
|
|
|
|
cli_build_flags_common(bopt->cflags);
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if (obopt != NULL && obopt->cflags != NULL) {
|
|
|
|
kore_buf_append(bopt->cflags, obopt->cflags->data,
|
|
|
|
obopt->cflags->offset);
|
|
|
|
}
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->single_binary)
|
|
|
|
kore_buf_appendf(bopt->cflags, "-DKORE_SINGLE_BINARY");
|
|
|
|
|
2016-06-02 07:08:19 +02:00
|
|
|
string = kore_buf_stringify(bopt->cflags, NULL);
|
2016-01-27 21:37:59 +01:00
|
|
|
printf("CFLAGS=%s\n", string);
|
2016-01-27 21:32:57 +01:00
|
|
|
cflags_count = kore_split_string(string, " ", cflags, CFLAGS_MAX);
|
|
|
|
}
|
|
|
|
|
2016-06-26 22:47:35 +02:00
|
|
|
static void
|
|
|
|
cli_build_cxxflags(struct buildopt *bopt)
|
|
|
|
{
|
|
|
|
struct buildopt *obopt;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
if ((obopt = cli_buildopt_find(flavor)) == NULL)
|
|
|
|
cli_fatal("no such build flavor: %s", flavor);
|
|
|
|
|
|
|
|
if (bopt->cxxflags == NULL)
|
|
|
|
bopt->cxxflags = kore_buf_create(128);
|
|
|
|
|
|
|
|
cli_build_flags_common(bopt->cxxflags);
|
|
|
|
|
|
|
|
if (obopt != NULL && obopt->cxxflags != NULL) {
|
|
|
|
kore_buf_append(bopt->cxxflags, obopt->cxxflags->data,
|
|
|
|
obopt->cxxflags->offset);
|
|
|
|
}
|
|
|
|
|
|
|
|
string = kore_buf_stringify(bopt->cxxflags, NULL);
|
2016-06-28 05:33:51 +02:00
|
|
|
if (cxx_files_count > 0)
|
|
|
|
printf("CXXFLAGS=%s\n", string);
|
2016-06-26 22:47:35 +02:00
|
|
|
cxxflags_count = kore_split_string(string, " ", cxxflags, CXXFLAGS_MAX);
|
|
|
|
}
|
|
|
|
|
2016-01-27 21:32:57 +01:00
|
|
|
static void
|
|
|
|
cli_build_ldflags(struct buildopt *bopt)
|
|
|
|
{
|
|
|
|
struct buildopt *obopt;
|
|
|
|
char *string;
|
|
|
|
|
|
|
|
if ((obopt = cli_buildopt_find(flavor)) == NULL)
|
|
|
|
cli_fatal("no such build flavor: %s", flavor);
|
|
|
|
|
|
|
|
if (bopt->ldflags == NULL)
|
|
|
|
bopt->ldflags = kore_buf_create(128);
|
|
|
|
|
2016-07-06 16:16:15 +02:00
|
|
|
if (bopt->single_binary == 0) {
|
2016-01-27 21:32:57 +01:00
|
|
|
#if defined(__MACH__)
|
2016-07-06 16:16:15 +02:00
|
|
|
kore_buf_appendf(bopt->ldflags,
|
|
|
|
"-dynamiclib -undefined suppress -flat_namespace ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#else
|
2016-07-06 16:16:15 +02:00
|
|
|
kore_buf_appendf(bopt->ldflags, "-shared ");
|
2016-01-27 21:32:57 +01:00
|
|
|
#endif
|
2016-07-06 16:16:15 +02:00
|
|
|
}
|
2016-01-27 21:32:57 +01:00
|
|
|
|
|
|
|
if (obopt != NULL && obopt->ldflags != NULL) {
|
|
|
|
kore_buf_append(bopt->ldflags, obopt->ldflags->data,
|
|
|
|
obopt->ldflags->offset);
|
|
|
|
}
|
|
|
|
|
2016-06-02 07:08:19 +02:00
|
|
|
string = kore_buf_stringify(bopt->ldflags, NULL);
|
2016-01-27 21:37:59 +01:00
|
|
|
printf("LDFLAGS=%s\n", string);
|
2016-01-27 21:32:57 +01:00
|
|
|
ldflags_count = kore_split_string(string, " ", ldflags, LD_FLAGS_MAX);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_flavor_load(void)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
char buf[BUFSIZ], pwd[MAXPATHLEN], *p, *conf;
|
|
|
|
|
|
|
|
if (getcwd(pwd, sizeof(pwd)) == NULL)
|
|
|
|
cli_fatal("could not get cwd: %s", errno_s);
|
|
|
|
|
|
|
|
appl = basename(pwd);
|
2016-07-06 16:16:15 +02:00
|
|
|
if (appl == NULL)
|
|
|
|
cli_fatal("basename: %s", errno_s);
|
|
|
|
appl = kore_strdup(appl);
|
2016-01-27 21:32:57 +01:00
|
|
|
(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);
|
|
|
|
free(conf);
|
|
|
|
|
|
|
|
if ((fp = fopen(".flavor", "r")) == NULL) {
|
|
|
|
flavor = kore_strdup("dev");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fgets(buf, sizeof(buf), fp) == NULL)
|
|
|
|
cli_fatal("failed to read flavor from file");
|
|
|
|
|
|
|
|
if ((p = strchr(buf, '\n')) != NULL)
|
|
|
|
*p = '\0';
|
|
|
|
|
|
|
|
flavor = kore_strdup(buf);
|
|
|
|
(void)fclose(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
cli_flavor_change(const char *name)
|
|
|
|
{
|
|
|
|
FILE *fp;
|
|
|
|
int ret;
|
|
|
|
struct buildopt *bopt;
|
|
|
|
|
|
|
|
if ((bopt = cli_buildopt_find(name)) == NULL)
|
|
|
|
cli_fatal("no such flavor: %s", name);
|
|
|
|
|
|
|
|
if ((fp = fopen(".flavor.tmp", "w")) == NULL)
|
|
|
|
cli_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");
|
|
|
|
|
|
|
|
(void)fclose(fp);
|
|
|
|
|
|
|
|
if (rename(".flavor.tmp", ".flavor") == -1)
|
|
|
|
cli_fatal("failed to replace build flavor");
|
|
|
|
|
|
|
|
cli_clean(0, NULL);
|
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_spawn_proc(void (*cb)(void *), void *arg)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
pid_t pid;
|
|
|
|
int status;
|
|
|
|
|
|
|
|
pid = fork();
|
|
|
|
switch (pid) {
|
|
|
|
case -1:
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_compile_cfile: fork() %s", errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
/* NOTREACHED */
|
|
|
|
case 0:
|
|
|
|
cb(arg);
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_spawn_proc: %s", errno_s);
|
2014-07-31 23:12:14 +02:00
|
|
|
/* NOTREACHED */
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (waitpid(pid, &status, 0) == -1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("couldn't wait for child %d", pid);
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
if (WEXITSTATUS(status) || WTERMSIG(status) || WCOREDUMP(status))
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("subprocess trouble, check output");
|
2014-07-31 23:12:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_vasprintf(char **out, const char *fmt, ...)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
int l;
|
|
|
|
va_list args;
|
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
l = vasprintf(out, fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
if (l == -1)
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal("cli_vasprintf");
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
return (l);
|
|
|
|
}
|
|
|
|
|
2014-08-01 15:55:09 +02:00
|
|
|
static void
|
|
|
|
cli_cleanup_files(const char *spath)
|
|
|
|
{
|
2014-08-03 16:36:16 +02:00
|
|
|
cli_find_files(spath, cli_file_remove);
|
2014-08-01 15:55:09 +02:00
|
|
|
|
2014-08-03 15:30:53 +02:00
|
|
|
if (rmdir(spath) == -1 && errno != ENOENT)
|
2014-08-01 15:55:09 +02:00
|
|
|
printf("couldn't rmdir %s\n", spath);
|
|
|
|
}
|
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
static void
|
2014-08-01 13:59:47 +02:00
|
|
|
cli_fatal(const char *fmt, ...)
|
2014-07-31 23:12:14 +02:00
|
|
|
{
|
|
|
|
va_list args;
|
2014-08-03 16:36:16 +02:00
|
|
|
char buf[2048];
|
2014-07-31 23:12:14 +02:00
|
|
|
|
|
|
|
va_start(args, fmt);
|
|
|
|
(void)vsnprintf(buf, sizeof(buf), fmt, args);
|
|
|
|
va_end(args);
|
|
|
|
|
|
|
|
if (command != NULL)
|
2014-08-01 13:59:47 +02:00
|
|
|
printf("kore %s: %s\n", command->name, buf);
|
2014-07-31 23:12:14 +02:00
|
|
|
else
|
2014-08-01 13:59:47 +02:00
|
|
|
printf("kore: %s\n", buf);
|
2014-08-03 16:36:16 +02:00
|
|
|
|
2014-07-31 23:12:14 +02:00
|
|
|
exit(1);
|
|
|
|
}
|