diff --git a/cli/Makefile b/cli/Makefile
index 1bd4d43ab..d594533bb 100644
--- a/cli/Makefile
+++ b/cli/Makefile
@@ -2,6 +2,7 @@ LIGHTNING_CLI_SRC := cli/lightning-cli.c
LIGHTNING_CLI_OBJS := $(LIGHTNING_CLI_SRC:.c=.o)
LIGHTNING_CLI_COMMON_OBJS := \
+ bitcoin/chainparams.o \
common/configdir.o \
common/json.o \
common/memleak.o \
diff --git a/cli/lightning-cli.c b/cli/lightning-cli.c
index bb120f1b2..e827ad090 100644
--- a/cli/lightning-cli.c
+++ b/cli/lightning-cli.c
@@ -29,25 +29,6 @@
#define ERROR_TALKING_TO_LIGHTNINGD 2
#define ERROR_USAGE 3
-/* Tal wrappers for opt. */
-static void *opt_allocfn(size_t size)
-{
- return tal_arr_label(NULL, char, size, TAL_LABEL("opt_allocfn", ""));
-}
-
-static void *tal_reallocfn(void *ptr, size_t size)
-{
- if (!ptr)
- return opt_allocfn(size);
- tal_resize_(&ptr, 1, size, false);
- return ptr;
-}
-
-static void tal_freefn(void *ptr)
-{
- tal_free(ptr);
-}
-
struct netaddr;
/* Returns number of tokens digested */
@@ -450,8 +431,7 @@ int main(int argc, char *argv[])
jsmntok_t *toks;
const jsmntok_t *result, *error, *id;
const tal_t *ctx = tal(NULL, char);
- char *lightning_dir = default_configdir(ctx);
- char *rpc_filename = default_rpcfile(ctx);
+ char *config_filename, *lightning_dir, *rpc_filename;
jsmn_parser parser;
int parserr;
enum format format = DEFAULT_FORMAT;
@@ -462,15 +442,11 @@ int main(int argc, char *argv[])
jsmn_init(&parser);
tal_set_backend(NULL, NULL, NULL, tal_error);
- opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
- opt_register_arg("--lightning-dir=
", opt_set_talstr, opt_show_charp,
- &lightning_dir,
- "Set working directory. All other files are relative to this");
+ setup_option_allocators();
- opt_register_arg("--rpc-file", opt_set_talstr, opt_show_charp,
- &rpc_filename,
- "Set JSON-RPC socket (or /dev/tty)");
+ initial_config_opts(ctx, argc, argv,
+ &config_filename, &lightning_dir, &rpc_filename);
opt_register_noarg("--help|-h", opt_usage_and_exit,
" [...]", "Show this message. Use the command help (without hyphens -- \"lightning-cli help\") to get a list of all RPC commands");
diff --git a/cli/test/run-remove-hint.c b/cli/test/run-remove-hint.c
index 4e03dd16e..cd0b6040d 100644
--- a/cli/test/run-remove-hint.c
+++ b/cli/test/run-remove-hint.c
@@ -114,6 +114,7 @@ int main(int argc UNUSED, char *argv[])
output = tal_strdup(NULL, "");
assert(test_main(3, fake_argv) == 0);
+ assert(!taken_any());
assert(streq(output, "channels=\n"
"\n"
@@ -129,5 +130,6 @@ int main(int argc UNUSED, char *argv[])
"num_channels=1\n"
"num_connected=1\n"));
tal_free(output);
+ take_cleanup();
return 0;
}
diff --git a/common/configdir.c b/common/configdir.c
index ee0d822cd..4c2b1fb99 100644
--- a/common/configdir.c
+++ b/common/configdir.c
@@ -1,17 +1,155 @@
#include "configdir.h"
+#include
+#include
+#include
+#include
#include
+#include
#include
#include
+#include
+#include
#include
+/* The regrettable globals */
+static const tal_t *options_ctx;
+
/* Override a tal string; frees the old one. */
char *opt_set_talstr(const char *arg, char **p)
{
tal_free(*p);
- return opt_set_charp(tal_strdup(NULL, arg), p);
+ return opt_set_charp(tal_strdup(options_ctx, arg), p);
}
-char *default_configdir(const tal_t *ctx)
+static char *opt_set_abspath(const char *arg, char **p)
+{
+ tal_free(*p);
+ return opt_set_charp(path_join(options_ctx, take(path_cwd(NULL)), arg),
+ p);
+}
+
+/* Tal wrappers for opt. */
+static void *opt_allocfn(size_t size)
+{
+ return tal_arr_label(NULL, char, size,
+ TAL_LABEL(opt_allocfn_notleak, ""));
+}
+
+static void *tal_reallocfn(void *ptr, size_t size)
+{
+ if (!ptr)
+ return opt_allocfn(size);
+ tal_resize_(&ptr, 1, size, false);
+ return ptr;
+}
+
+static void tal_freefn(void *ptr)
+{
+ tal_free(ptr);
+}
+
+static int config_parse_line_number;
+
+static void config_log_stderr_exit(const char *fmt, ...)
+{
+ char *msg;
+ va_list ap;
+
+ va_start(ap, fmt);
+
+ /* This is the format we expect:*/
+ 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 *);
+
+ assert(argv0 != NULL);
+ assert(arg != NULL);
+ assert(problem != NULL);
+ /*mangle it to remove '--' and add the line number.*/
+ msg = tal_fmt(NULL, "%s line %d: %.*s: %s",
+ argv0,
+ config_parse_line_number, len-2, arg+2, problem);
+ } else {
+ msg = tal_vfmt(NULL, fmt, ap);
+ }
+ va_end(ap);
+
+ errx(1, "%s", msg);
+}
+
+void parse_include(const char *filename, bool must_exist, bool early)
+{
+ char *contents, **lines;
+ char **all_args; /*For each line: either `--`argument, include file, or NULL*/
+ char *argv[3];
+ int i, argc;
+
+ contents = grab_file(NULL, filename);
+
+ /* The default config doesn't have to exist, but if the config was
+ * specified on the command line it has to exist. */
+ if (!contents) {
+ if (must_exist)
+ err(1, "Opening and reading %s", filename);
+ return;
+ }
+
+ lines = tal_strsplit(contents, contents, "\r\n", STR_EMPTY_OK);
+
+ /* We have to keep all_args around, since opt will point into it: use
+ * magic tal name to tell memleak this isn't one. */
+ all_args = tal_arr_label(options_ctx, char *, tal_count(lines) - 1,
+ TAL_LABEL(options_array_notleak, ""));
+
+ for (i = 0; i < tal_count(lines) - 1; i++) {
+ if (strstarts(lines[i], "#")) {
+ all_args[i] = NULL;
+ } else if (strstarts(lines[i], "include ")) {
+ /* If relative, it's relative to current config file */
+ all_args[i] = path_join(all_args,
+ take(path_dirname(NULL,
+ filename)),
+ lines[i] + strlen("include "));
+ } else {
+ /* Only valid forms are "foo" and "foo=bar" */
+ all_args[i] = tal_fmt(all_args, "--%s", lines[i]);
+ }
+ }
+
+ /*
+ For each line we construct a fake argc,argv commandline.
+ argv[1] is the only element that changes between iterations.
+ */
+ argc = 2;
+ argv[0] = cast_const(char *, filename);
+ argv[argc] = NULL;
+
+ for (i = 0; i < tal_count(all_args); i++) {
+ if (all_args[i] == NULL)
+ continue;
+
+ if (!strstarts(all_args[i], "--")) {
+ parse_include(all_args[i], true, early);
+ continue;
+ }
+
+ config_parse_line_number = i + 1;
+ argv[1] = all_args[i];
+ if (early) {
+ opt_early_parse_incomplete(argc, argv,
+ config_log_stderr_exit);
+ } else {
+ opt_parse(&argc, argv, config_log_stderr_exit);
+ argc = 2; /* opt_parse might have changed it */
+ }
+ }
+
+ tal_free(contents);
+}
+
+static char *default_configdir(const tal_t *ctx)
{
char *path;
const char *env = getenv("HOME");
@@ -22,7 +160,139 @@ char *default_configdir(const tal_t *ctx)
return path;
}
-char *default_rpcfile(const tal_t *ctx)
+static char *default_rpcfile(const tal_t *ctx)
{
return tal_strdup(ctx, "lightning-rpc");
}
+
+static char *opt_set_network(const char *arg, void *unused)
+{
+ assert(arg != NULL);
+
+ /* Set the global chainparams instance */
+ chainparams = chainparams_for_network(arg);
+ if (!chainparams)
+ return tal_fmt(NULL, "Unknown network name '%s'", arg);
+ return NULL;
+}
+
+static char *opt_set_specific_network(const char *network)
+{
+ return opt_set_network(network, NULL);
+}
+
+static void opt_show_network(char buf[OPT_SHOW_LEN], const void *unused)
+{
+ snprintf(buf, OPT_SHOW_LEN, "%s", chainparams->network_name);
+}
+
+/* Special option to ignore stuff we've parsed really early on */
+char *opt_ignore(const char *arg, void *unused)
+{
+ return NULL;
+}
+
+char *opt_ignore_noarg(void *unused)
+{
+ return NULL;
+}
+
+void setup_option_allocators(void)
+{
+ /*~ These functions make ccan/opt use tal for allocations */
+ opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
+}
+
+void initial_config_opts(const tal_t *ctx,
+ int argc, char *argv[],
+ char **config_filename,
+ char **config_dir,
+ char **rpc_filename)
+{
+ options_ctx = ctx;
+
+ /* First, they could specify a config, which specifies a lightning dir
+ * or a network. */
+ *config_filename = NULL;
+ opt_register_early_arg("--conf=", opt_set_abspath, NULL,
+ config_filename,
+ "Specify configuration file (default: /config)");
+
+ /* Handle --version (and exit) here too */
+ opt_register_version();
+
+ opt_early_parse_incomplete(argc, argv, opt_log_stderr_exit);
+
+ /* Now, reset and ignore --conf option from now on. */
+ opt_free_table();
+
+ opt_register_early_arg("--conf=", opt_ignore, NULL,
+ config_filename,
+ "Specify configuration file (default: /config)");
+
+ /* Now, config file (or cmdline) can set network and lightning-dir */
+ *config_dir = NULL;
+ opt_register_early_arg("--lightning-dir=",
+ opt_set_talstr, NULL,
+ config_dir,
+ "Set working directory. All other files are relative to this");
+
+ /* We need to know network early, so we can set defaults (which normal
+ * options can change) and default config_dir */
+ opt_register_early_arg("--network", opt_set_network, opt_show_network,
+ NULL,
+ "Select the network parameters (bitcoin, testnet,"
+ " regtest, litecoin or litecoin-testnet)");
+ opt_register_early_noarg("--testnet",
+ opt_set_specific_network, "testnet",
+ "Alias for --network=testnet");
+ opt_register_early_noarg("--signet",
+ opt_set_specific_network, "signet",
+ "Alias for --network=signet");
+ opt_register_early_noarg("--mainnet",
+ opt_set_specific_network, "bitcoin",
+ "Alias for --network=bitcoin");
+
+ /* Read config file first, since cmdline must override */
+ if (*config_filename)
+ parse_include(*config_filename, true, true);
+ opt_early_parse_incomplete(argc, argv, opt_log_stderr_exit);
+
+ /* We use a global (in common/utils.h) for the chainparams.
+ * We default to testnet for now. */
+ if (!chainparams)
+ chainparams = chainparams_for_network("testnet");
+
+ if (!*config_dir)
+ *config_dir = default_configdir(ctx);
+
+ /* Make sure it's absolute */
+ *config_dir = path_join(ctx, take(path_cwd(NULL)), take(*config_dir));
+
+ /* Now, reset and ignore those options from now on. */
+ opt_free_table();
+
+ opt_register_early_arg("--conf=", opt_ignore, NULL,
+ config_filename,
+ "Specify configuration file (default: /config)");
+ opt_register_early_arg("--lightning-dir=",
+ opt_ignore, opt_show_charp,
+ config_dir,
+ "Set working directory. All other files are relative to this");
+ opt_register_early_arg("--network", opt_ignore, opt_show_network,
+ NULL,
+ "Select the network parameters (bitcoin, testnet,"
+ " regtest, litecoin or litecoin-testnet)");
+ opt_register_early_noarg("--testnet", opt_ignore_noarg, NULL,
+ "Alias for --network=testnet");
+ opt_register_early_noarg("--signet", opt_ignore_noarg, NULL,
+ "Alias for --network=signet");
+ opt_register_early_noarg("--mainnet", opt_ignore_noarg, NULL,
+ "Alias for --network=bitcoin");
+
+ /* Set this up for when they parse cmdline proper. */
+ *rpc_filename = default_rpcfile(ctx);
+ opt_register_arg("--rpc-file", opt_set_talstr, opt_show_charp,
+ rpc_filename,
+ "Set JSON-RPC socket (or /dev/tty)");
+}
diff --git a/common/configdir.h b/common/configdir.h
index 9bd3f8d51..13bf0b699 100644
--- a/common/configdir.h
+++ b/common/configdir.h
@@ -6,10 +6,21 @@
/* Helper for options which are tal() strings. */
char *opt_set_talstr(const char *arg, char **p);
-/* The default configuration dir: ~/.lightning */
-char *default_configdir(const tal_t *ctx);
+/* Initial options setup */
+void setup_option_allocators(void);
-/* The default rpc filename: lightning-rpc */
-char *default_rpcfile(const tal_t *ctx);
+/* Parse minimal config options and files */
+void initial_config_opts(const tal_t *ctx,
+ int argc, char *argv[],
+ char **config_filename,
+ char **config_dir,
+ char **rpc_filename);
+
+/* Parse a specific include file */
+void parse_include(const char *filename, bool must_exist, bool early);
+
+/* For listconfigs to access. */
+char *opt_ignore(const char *arg, void *unused);
+char *opt_ignore_noarg(void *unused);
#endif /* LIGHTNING_COMMON_CONFIGDIR_H */
diff --git a/common/memleak.c b/common/memleak.c
index 09a4b2d62..0b1b4b9cc 100644
--- a/common/memleak.c
+++ b/common/memleak.c
@@ -75,6 +75,10 @@ static void children_into_htable(const void *exclude1, const void *exclude2,
if (strends(name, "struct io_plan *[]") && !tal_parent(i))
continue;
+ /* Other notleak internals. */
+ if (strends(name, "_notleak"))
+ continue;
+
/* Don't add tmpctx. */
if (streq(name, "tmpctx"))
continue;
diff --git a/devtools/checkchannels.c b/devtools/checkchannels.c
index 93e5ec65b..9bd558872 100644
--- a/devtools/checkchannels.c
+++ b/devtools/checkchannels.c
@@ -111,7 +111,7 @@ static void copy_column(void *dst, size_t size,
int main(int argc, char *argv[])
{
- char *config_dir, *hsmfile, *dbfile;
+ char *config_dir, *config_filename, *rpc_filename, *hsmfile, *dbfile;
sqlite3 *sql;
sqlite3_stmt *stmt;
int flags = SQLITE_OPEN_READONLY, dberr;
@@ -123,11 +123,11 @@ int main(int argc, char *argv[])
wally_init(0);
secp256k1_ctx = wally_get_secp_context();
- config_dir = default_configdir(NULL);
- opt_register_arg("--lightning-dir=",
- opt_set_talstr, opt_show_charp,
- &config_dir,
- "Where to find hsm_secret and lightningd.sqlite3");
+ setup_option_allocators();
+
+ initial_config_opts(NULL, argc, argv,
+ &config_filename, &config_dir, &rpc_filename);
+
opt_register_noarg("-v|--verbose", opt_set_bool, &verbose,
"Print everything");
diff --git a/doc/lightning-cli.1 b/doc/lightning-cli.1
index e3055cff7..1b23af3ad 100644
--- a/doc/lightning-cli.1
+++ b/doc/lightning-cli.1
@@ -16,6 +16,17 @@ Set the directory for the lightning daemon we’re talking to; defaults to
\fI$HOME/\.lightning\fR\.
+ \fB--conf\fR=\fIPATH\fR
+Sets configuration file (default: \fBlightning-dir\fR/\fIconfig\fR )\.
+
+
+ \fB--network\fR=\fInetwork\fR
+ \fB--mainnet\fR
+ \fB--testnet\fR
+ \fB--signet\fR
+Sets network explicitly\.
+
+
\fB--rpc-file\fR=\fIFILE\fR
Named pipe to use to talk to lightning daemon: default is
\fIlightning-rpc\fR in the lightning directory\.
diff --git a/doc/lightning-cli.1.md b/doc/lightning-cli.1.md
index e56acd793..f03c4ace4 100644
--- a/doc/lightning-cli.1.md
+++ b/doc/lightning-cli.1.md
@@ -18,6 +18,15 @@ OPTIONS
Set the directory for the lightning daemon we’re talking to; defaults to
*$HOME/.lightning*.
+ **--conf**=*PATH*
+Sets configuration file (default: **lightning-dir**/*config* ).
+
+ **--network**=*network*
+ **--mainnet**
+ **--testnet**
+ **--signet**
+Sets network explicitly.
+
**--rpc-file**=*FILE*
Named pipe to use to talk to lightning daemon: default is
*lightning-rpc* in the lightning directory.
diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c
index 14f27f8aa..f76e7dc68 100644
--- a/lightningd/jsonrpc.c
+++ b/lightningd/jsonrpc.c
@@ -1006,7 +1006,6 @@ void jsonrpc_setup(struct lightningd *ld)
{
struct json_command **commands = get_cmdlist();
- ld->rpc_filename = default_rpcfile(ld);
ld->jsonrpc = tal(ld, struct jsonrpc);
strmap_init(&ld->jsonrpc->usagemap);
ld->jsonrpc->commands = tal_arr(ld->jsonrpc, struct json_command *, 0);
diff --git a/lightningd/lightningd.c b/lightningd/lightningd.c
index 6707d1371..75f250a4a 100644
--- a/lightningd/lightningd.c
+++ b/lightningd/lightningd.c
@@ -205,8 +205,6 @@ static struct lightningd *new_lightningd(const tal_t *ctx)
/*~ This is detailed in chaintopology.c */
ld->topology = new_topology(ld, ld->log);
ld->daemon_parent_fd = -1;
- ld->config_filename = NULL;
- ld->pidfile = NULL;
ld->proxyaddr = NULL;
ld->use_proxy_always = false;
ld->pure_tor_setup = false;
@@ -658,10 +656,6 @@ int main(int argc, char *argv[])
* backtraces when we crash (if supported on this platform). */
daemon_setup(argv[0], log_backtrace_print, log_backtrace_exit);
- /*~ We use a global (in common/utils.h) for the chainparams.
- * We default to testnet for now. */
- chainparams = chainparams_for_network("testnet");
-
/*~ There's always a battle between what a constructor like this
* should do, and what should be added later by the caller. In
* general, because we use valgrind heavily for testing, we prefer not
diff --git a/lightningd/options.c b/lightningd/options.c
index 3efad419f..bc5be5b01 100644
--- a/lightningd/options.c
+++ b/lightningd/options.c
@@ -7,7 +7,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -44,38 +43,12 @@
#include
bool deprecated_apis = true;
-static bool opt_table_alloced = false;
/* Declare opt_add_addr here, because we we call opt_add_addr
* and opt_announce_addr vice versa
*/
static char *opt_add_addr(const char *arg, struct lightningd *ld);
-/* Tal wrappers for opt. */
-static void *opt_allocfn(size_t size)
-{
- return tal_arr_label(NULL, char, size, TAL_LABEL("opt_allocfn", ""));
-}
-
-static void *tal_reallocfn(void *ptr, size_t size)
-{
- if (!ptr) {
- /* realloc(NULL) call is to allocate opt_table */
- if (!opt_table_alloced) {
- opt_table_alloced = true;
- return notleak(opt_allocfn(size));
- }
- return opt_allocfn(size);
- }
- tal_resize_(&ptr, 1, size, false);
- return ptr;
-}
-
-static void tal_freefn(void *ptr)
-{
- tal_free(ptr);
-}
-
/* FIXME: Put into ccan/time. */
#define TIME_FROM_SEC(sec) { { .tv_nsec = 0, .tv_sec = sec } }
#define TIME_FROM_MSEC(msec) \
@@ -250,38 +223,6 @@ static void opt_show_s32(char buf[OPT_SHOW_LEN], const s32 *u)
snprintf(buf, OPT_SHOW_LEN, "%"PRIi32, *u);
}
-static char *opt_set_network(const char *arg, struct lightningd *ld)
-{
- assert(arg != NULL);
-
- /* Set the global chainparams instance */
- chainparams = chainparams_for_network(arg);
- if (!chainparams)
- return tal_fmt(NULL, "Unknown network name '%s'", arg);
- return NULL;
-}
-
-static char *opt_set_testnet(struct lightningd *ld)
-{
- return opt_set_network("testnet", ld);
-}
-
-static char *opt_set_signet(struct lightningd *ld)
-{
- return opt_set_network("signet", ld);
-}
-
-static char *opt_set_mainnet(struct lightningd *ld)
-{
- return opt_set_network("bitcoin", ld);
-}
-
-static void opt_show_network(char buf[OPT_SHOW_LEN],
- const struct lightningd *ld)
-{
- snprintf(buf, OPT_SHOW_LEN, "%s", chainparams->network_name);
-}
-
static char *opt_set_rgb(const char *arg, struct lightningd *ld)
{
assert(arg != NULL);
@@ -688,121 +629,6 @@ static void check_config(struct lightningd *ld)
fatal("--always-use-proxy needs --proxy");
}
-static void setup_default_config(struct lightningd *ld)
-{
- if (chainparams->testnet)
- ld->config = testnet_config;
- else
- ld->config = mainnet_config;
-
- /* Set default PID file name to be per-network */
- tal_free(ld->pidfile);
- ld->pidfile = tal_fmt(ld, "lightningd-%s.pid", chainparams->network_name);
-}
-
-static int config_parse_line_number;
-
-static void config_log_stderr_exit(const char *fmt, ...)
-{
- char *msg;
- va_list ap;
-
- va_start(ap, fmt);
-
- /* This is the format we expect:*/
- 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 *);
-
- assert(argv0 != NULL);
- assert(arg != NULL);
- assert(problem != NULL);
- /*mangle it to remove '--' and add the line number.*/
- msg = tal_fmt(NULL, "%s line %d: %.*s: %s",
- argv0,
- config_parse_line_number, len-2, arg+2, problem);
- } else {
- msg = tal_vfmt(NULL, fmt, ap);
- }
- va_end(ap);
-
- fatal("%s", msg);
-}
-
-static void parse_include(struct lightningd *ld,
- const char *filename,
- bool must_exist,
- bool early)
-{
- char *contents, **lines;
- char **all_args; /*For each line: either `--`argument, include file, or NULL*/
- char *argv[3];
- int i, argc;
-
- contents = grab_file(ld, filename);
-
- /* The default config doesn't have to exist, but if the config was
- * specified on the command line it has to exist. */
- if (!contents) {
- if (must_exist)
- fatal("Opening and reading %s: %s",
- filename, strerror(errno));
- return;
- }
-
- lines = tal_strsplit(contents, contents, "\r\n", STR_EMPTY_OK);
-
- /* We have to keep all_args around, since opt will point into it */
- all_args = notleak(tal_arr(ld, char *, tal_count(lines) - 1));
-
- for (i = 0; i < tal_count(lines) - 1; i++) {
- if (strstarts(lines[i], "#")) {
- all_args[i] = NULL;
- } else if (strstarts(lines[i], "include ")) {
- /* If relative, it's relative to current config file */
- all_args[i] = path_join(all_args,
- take(path_dirname(NULL,
- filename)),
- lines[i] + strlen("include "));
- } else {
- /* Only valid forms are "foo" and "foo=bar" */
- all_args[i] = tal_fmt(all_args, "--%s", lines[i]);
- }
- }
-
- /*
- For each line we construct a fake argc,argv commandline.
- argv[1] is the only element that changes between iterations.
- */
- argc = 2;
- argv[0] = cast_const(char *, filename);
- argv[argc] = NULL;
-
- for (i = 0; i < tal_count(all_args); i++) {
- if (all_args[i] == NULL)
- continue;
-
- if (!strstarts(all_args[i], "--")) {
- parse_include(ld, all_args[i], true, early);
- continue;
- }
-
- config_parse_line_number = i + 1;
- argv[1] = all_args[i];
- if (early) {
- opt_early_parse_incomplete(argc, argv,
- config_log_stderr_exit);
- } else {
- opt_parse(&argc, argv, config_log_stderr_exit);
- argc = 2; /* opt_parse might have changed it */
- }
- }
-
- tal_free(contents);
-}
-
/**
* We turn the config file into cmdline arguments. @early tells us
* whether to parse early options only (and ignore any unknown ones),
@@ -819,7 +645,7 @@ static void opt_parse_from_config(struct lightningd *ld, bool early)
else
filename = path_join(tmpctx, ld->config_dir, "config");
- parse_include(ld, filename, ld->config_filename != NULL, early);
+ parse_include(filename, ld->config_filename != NULL, early);
}
static char *test_subdaemons_and_exit(struct lightningd *ld)
@@ -839,9 +665,6 @@ static char *list_features_and_exit(struct lightningd *ld)
static char *opt_lightningd_usage(struct lightningd *ld)
{
- /* Reload config so that --help has the correct network defaults
- * to display before it exits */
- setup_default_config(ld);
char *extra = tal_fmt(NULL, "\nA bitcoin lightning daemon (default "
"values shown for network: %s).", chainparams->network_name);
opt_usage_and_exit(extra);
@@ -884,73 +707,6 @@ static char *opt_start_daemon(struct lightningd *ld)
errx(1, "Died with signal %u", WTERMSIG(exitcode));
}
-static char *opt_ignore_talstr(const char *arg, char **p)
-{
- return NULL;
-}
-
-static char *opt_set_conf(const char *arg, struct lightningd *ld)
-{
- /* This is a pass-through if arg is absolute */
- tal_free(ld->config_filename);
- ld->config_filename = path_join(ld, path_cwd(tmpctx), arg);
- return NULL;
-}
-
-/* Just enough parsing to find config file, and other maintenance options
- * which don't want us to create the lightning dir */
-static void handle_minimal_config_opts(struct lightningd *ld,
- int argc, char *argv[])
-{
- /* First, they could specify a config, which specifies a lightning dir */
- opt_register_early_arg("--conf=", opt_set_conf, NULL,
- ld,
- "Specify configuration file (default: /config)");
-
- ld->config_dir = NULL;
- opt_register_early_arg("--lightning-dir=",
- opt_set_talstr, NULL,
- &ld->config_dir,
- "Set working directory. All other files are relative to this");
-
- /* List features immediately, before doing anything interesting */
- opt_register_early_noarg("--list-features-only",
- list_features_and_exit,
- ld, opt_hidden);
-
- /* Handle --version (and exit) here too: don't create lightning-dir for this */
- opt_register_version();
-
- opt_early_parse_incomplete(argc, argv, opt_log_stderr_exit);
-
- /* Corner case: if they specified a config filename, and didn't set
- * set lightning-dir, read config file to get it! */
- if (ld->config_filename && !ld->config_dir)
- opt_parse_from_config(ld, true);
-
- if (!ld->config_dir)
- ld->config_dir = default_configdir(ld);
-
- /* Now, reset and ignore those options from now on. */
- opt_free_table();
- opt_table_alloced = false;
-
- opt_register_early_arg("--conf=", opt_ignore_talstr, NULL,
- &ld->config_filename,
- "Specify configuration file (default: /config)");
- opt_register_early_arg("--lightning-dir=",
- opt_ignore_talstr, opt_show_charp,
- &ld->config_dir,
- "Set working directory. All other files are relative to this");
-
- ld->config_dir = path_join(ld, path_cwd(tmpctx), take(ld->config_dir));
-
- ld->wallet_dsn = tal_fmt(ld, "sqlite3://%s/lightningd.sqlite3", ld->config_dir);
- opt_register_early_arg("--wallet", opt_set_talstr, NULL,
- &ld->wallet_dsn,
- "Location of the wallet database.");
-}
-
static void register_opts(struct lightningd *ld)
{
/* This happens before plugins started */
@@ -971,19 +727,6 @@ static void register_opts(struct lightningd *ld)
NULL, ld,
"Disable a particular plugin by filename/name");
- /* We need to know network early, so we can set defaults (which normal
- * options can change) */
- opt_register_early_arg("--network", opt_set_network, opt_show_network,
- ld,
- "Select the network parameters (bitcoin, testnet,"
- " regtest, litecoin or litecoin-testnet)");
- opt_register_early_noarg("--testnet", opt_set_testnet, ld,
- "Alias for --network=testnet");
- opt_register_early_noarg("--signet", opt_set_signet, ld,
- "Alias for --network=signet");
- opt_register_early_noarg("--mainnet", opt_set_mainnet, ld,
- "Alias for --network=bitcoin");
-
/* This can effect commandline parsing */
opt_register_early_arg("--allow-deprecated-apis",
opt_set_bool_arg, opt_show_bool,
@@ -998,10 +741,10 @@ static void register_opts(struct lightningd *ld)
/* This immediately makes is a daemon. */
opt_register_early_noarg("--daemon", opt_start_daemon, ld,
"Run in the background, suppress stdout/stderr");
+ opt_register_early_arg("--wallet", opt_set_talstr, NULL,
+ &ld->wallet_dsn,
+ "Location of the wallet database.");
- opt_register_arg("--rpc-file", opt_set_talstr, opt_show_charp,
- &ld->rpc_filename,
- "Set JSON-RPC socket (or /dev/tty)");
opt_register_noarg("--help|-h", opt_lightningd_usage, ld,
"Print this message.");
opt_register_arg("--bitcoin-datadir", opt_set_talstr, NULL,
@@ -1177,11 +920,33 @@ void setup_color_and_alias(struct lightningd *ld)
void handle_early_opts(struct lightningd *ld, int argc, char *argv[])
{
- /*~ These functions make ccan/opt use tal for allocations */
- opt_set_alloc(opt_allocfn, tal_reallocfn, tal_freefn);
+ /* Make ccan/opt use tal for allocations */
+ setup_option_allocators();
- /*~ Handle --conf and --lightning-dir super-early. */
- handle_minimal_config_opts(ld, argc, argv);
+ /*~ List features immediately, before doing anything interesting */
+ opt_register_early_noarg("--list-features-only",
+ list_features_and_exit,
+ ld, opt_hidden);
+
+ /*~ This does enough parsing to get us the base configuration options */
+ initial_config_opts(ld, argc, argv,
+ &ld->config_filename,
+ &ld->config_dir,
+ &ld->rpc_filename);
+
+ /* Copy in default config, to be modified by further options */
+ if (chainparams->testnet)
+ ld->config = testnet_config;
+ else
+ ld->config = mainnet_config;
+
+ /* Now we can initialize wallet_dsn */
+ ld->wallet_dsn = tal_fmt(ld, "sqlite3://%s/lightningd.sqlite3",
+ ld->config_dir);
+
+ /* Set default PID file name to be per-network */
+ ld->pidfile = tal_fmt(ld, "lightningd-%s.pid",
+ chainparams->network_name);
/*~ Move into config dir: this eases path manipulation and also
* gives plugins a good place to store their stuff. */
@@ -1207,9 +972,6 @@ void handle_early_opts(struct lightningd *ld, int argc, char *argv[])
/* Early cmdline options now override config file options. */
opt_early_parse_incomplete(argc, argv, opt_log_stderr_exit);
- /* Now we know what network we're on, initialize defaults. */
- setup_default_config(ld);
-
/* Finalize the logging subsystem now. */
logging_options_parsed(ld->log_book);
}
@@ -1282,10 +1044,7 @@ static void add_config(struct lightningd *ld,
/* Ignore hidden options (deprecated) */
} else if (opt->cb == (void *)opt_usage_and_exit
|| opt->cb == (void *)version_and_exit
- /* These two show up as --network= */
- || opt->cb == (void *)opt_set_testnet
- || opt->cb == (void *)opt_set_signet
- || opt->cb == (void *)opt_set_mainnet
+ || opt->cb == (void *)opt_ignore_noarg
|| opt->cb == (void *)opt_lightningd_usage
|| opt->cb == (void *)test_subdaemons_and_exit
/* FIXME: we can't recover this. */
@@ -1335,7 +1094,7 @@ static void add_config(struct lightningd *ld,
answer = buf;
} else if (opt->cb_arg == (void *)opt_set_talstr
|| opt->cb_arg == (void *)opt_set_charp
- || opt->cb_arg == (void *)opt_ignore_talstr) {
+ || opt->cb_arg == (void *)opt_ignore) {
const char *arg = *(char **)opt->u.carg;
if (arg)
answer = tal_fmt(name0, "%s", arg);
diff --git a/lightningd/test/run-jsonrpc.c b/lightningd/test/run-jsonrpc.c
index 27608053d..8078fa82c 100644
--- a/lightningd/test/run-jsonrpc.c
+++ b/lightningd/test/run-jsonrpc.c
@@ -9,9 +9,6 @@ size_t bigsize_get(const u8 *p UNNEEDED, size_t max UNNEEDED, bigsize_t *val UNN
/* Generated stub for bigsize_put */
size_t bigsize_put(u8 buf[BIGSIZE_MAX_LEN] UNNEEDED, bigsize_t v UNNEEDED)
{ fprintf(stderr, "bigsize_put called!\n"); abort(); }
-/* Generated stub for default_rpcfile */
-char *default_rpcfile(const tal_t *ctx UNNEEDED)
-{ fprintf(stderr, "default_rpcfile called!\n"); abort(); }
/* Generated stub for fatal */
void fatal(const char *fmt UNNEEDED, ...)
{ fprintf(stderr, "fatal called!\n"); abort(); }