diff --git a/Makefile b/Makefile index b5571eac5..48eb1fa61 100644 --- a/Makefile +++ b/Makefile @@ -89,6 +89,7 @@ CCAN_OBJS := \ ccan-str.o \ ccan-take.o \ ccan-tal-grab_file.o \ + ccan-tal-path.o \ ccan-tal-str.o \ ccan-tal.o \ ccan-time.o \ @@ -333,6 +334,8 @@ ccan-tal.o: $(CCANDIR)/ccan/tal/tal.c $(CC) $(CFLAGS) -c -o $@ $< ccan-tal-str.o: $(CCANDIR)/ccan/tal/str/str.c $(CC) $(CFLAGS) -c -o $@ $< +ccan-tal-path.o: $(CCANDIR)/ccan/tal/path/path.c + $(CC) $(CFLAGS) -c -o $@ $< ccan-tal-grab_file.o: $(CCANDIR)/ccan/tal/grab_file/grab_file.c $(CC) $(CFLAGS) -c -o $@ $< ccan-take.o: $(CCANDIR)/ccan/take/take.c diff --git a/daemon/Makefile b/daemon/Makefile index bd1ac6360..51cca3fb3 100644 --- a/daemon/Makefile +++ b/daemon/Makefile @@ -7,12 +7,14 @@ daemon-wrongdir: daemon-all: daemon/lightningd DAEMON_SRC := \ + daemon/configdir.c \ daemon/lightningd.c \ daemon/log.c \ daemon/pseudorand.c DAEMON_OBJS := $(DAEMON_SRC:.c=.o) DAEMON_HEADERS := \ + daemon/configdir.h \ daemon/lightningd.h \ daemon/log.h \ daemon/pseudorand.h diff --git a/daemon/configdir.c b/daemon/configdir.c new file mode 100644 index 000000000..10cf6656a --- /dev/null +++ b/daemon/configdir.c @@ -0,0 +1,95 @@ +#include "configdir.h" +#include "log.h" +#include +#include +#include +#include +#include + +static char *default_configdir(const tal_t *ctx) +{ + char *path; + const char *env = getenv("HOME"); + if (!env) + return "."; + + path = path_join(ctx, env, ".lightning"); + return path; +} + +void configdir_register_opts(const tal_t *ctx, + char **configdir, char **rpc_filename) +{ + *configdir = default_configdir(ctx); + *rpc_filename = "lightning-rpc"; + + opt_register_early_arg("--lightning-dir", opt_set_charp, opt_show_charp, + configdir, + "working directory: all other files are relative to this"); + + opt_register_arg("--rpc-file", opt_set_charp, opt_show_charp, + rpc_filename, + "Set JSON-RPC socket (or /dev/tty)"); +} + +/* FIXME: make this nicer! */ +static void config_log_stderr_exit(const char *fmt, ...) +{ + char *msg; + va_list ap; + + va_start(ap, fmt); + + /* This is the format we expect: mangle it to remove '--'. */ + if (streq(fmt, "%s: %.*s: %s")) { + const char *argv0 = va_arg(ap, const char *); + unsigned int len = va_arg(ap, unsigned int); + const char *arg = va_arg(ap, const char *); + const char *problem = va_arg(ap, const char *); + + msg = tal_fmt(NULL, "%s line %s: %.*s: %s", + argv0, arg+strlen(arg)+1, len-2, arg+2, problem); + } else { + msg = tal_vfmt(NULL, fmt, ap); + } + va_end(ap); + + fatal("%s", msg); +} + +/* We turn the config file into cmdline arguments. */ +void opt_parse_from_config(const tal_t *ctx) +{ + char *contents, **lines; + char **argv; + int i, argc; + + contents = grab_file(ctx, "config"); + /* Doesn't have to exist. */ + if (!contents) { + if (errno != ENOENT) + fatal("Opening and reading config: %s", + strerror(errno)); + return; + } + + lines = tal_strsplit(contents, contents, "\r\n", STR_NO_EMPTY); + + /* We have to keep argv around, since opt will point into it */ + argv = tal_arr(ctx, char *, argc = 1); + argv[0] = "lightning config file"; + + for (i = 0; i < tal_count(lines) - 1; i++) { + if (strstarts(lines[i], "#")) + continue; + /* Only valid forms are "foo" and "foo=bar" */ + tal_resize(&argv, argc+1); + /* Stash line number after nul. */ + argv[argc++] = tal_fmt(argv, "--%s%c%u", lines[i], 0, i+1); + } + tal_resize(&argv, argc+1); + argv[argc] = NULL; + + opt_parse(&argc, argv, config_log_stderr_exit); + tal_free(contents); +} diff --git a/daemon/configdir.h b/daemon/configdir.h new file mode 100644 index 000000000..57cdc2b86 --- /dev/null +++ b/daemon/configdir.h @@ -0,0 +1,11 @@ +#ifndef LIGHTNING_DAEMON_CONFIGDIR_H +#define LIGHTNING_DAEMON_CONFIGDIR_H +#include "config.h" +#include + +void configdir_register_opts(const tal_t *ctx, + char **config_dir, char **rpc_filename); + +void opt_parse_from_config(const tal_t *ctx); + +#endif /* LIGHTNING_DAEMON_CONFIGDIR_H */ diff --git a/daemon/lightningd.c b/daemon/lightningd.c index 596c69a88..a337aed4f 100644 --- a/daemon/lightningd.c +++ b/daemon/lightningd.c @@ -1,3 +1,4 @@ +#include "configdir.h" #include "lightningd.h" #include "log.h" #include @@ -6,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -54,11 +56,34 @@ int main(int argc, char *argv[]) opt_register_logging(state->base_log); opt_register_version(); + configdir_register_opts(state, + &state->config_dir, &state->rpc_filename); + + /* Get any configdir options first. */ + opt_early_parse(argc, argv, opt_log_stderr_exit); + + /* Move to config dir, to save ourselves the hassle of path manip. */ + if (chdir(state->config_dir) != 0) { + log_unusual(state->base_log, "Creating lightningd dir %s" + " (because chdir gave %s)", + state->config_dir, strerror(errno)); + if (mkdir(state->config_dir, 0700) != 0) + fatal("Could not make directory %s: %s", + state->config_dir, strerror(errno)); + if (chdir(state->config_dir) != 0) + fatal("Could not change directory %s: %s", + state->config_dir, strerror(errno)); + } + /* Activate crash log now we're in the right place. */ + crashlog_activate(state->base_log); + + /* Now look for config file */ + opt_parse_from_config(state); + opt_parse(&argc, argv, opt_log_stderr_exit); if (argc != 1) errx(1, "no arguments accepted"); - crashlog_activate(state->base_log); log_info(state->base_log, "Hello world!"); tal_free(state); opt_free_table(); diff --git a/daemon/lightningd.h b/daemon/lightningd.h index c9a2a6611..48667a7a5 100644 --- a/daemon/lightningd.h +++ b/daemon/lightningd.h @@ -9,5 +9,9 @@ struct lightningd_state { struct log_record *log_record; struct log *base_log; FILE *logf; + + /* Our config dir, and rpc file */ + char *config_dir; + char *rpc_filename; }; #endif /* LIGHTNING_DAEMON_LIGHTNING_H */