mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-19 05:44:12 +01:00
lightningd: move listconfigs into configs.c
It mainly clutters up options.c. The deprecated handling was very tied to it, so it stays there. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
parent
d09d0112f4
commit
9f9f2f1493
@ -40,6 +40,7 @@ LIGHTNINGD_SRC := \
|
||||
lightningd/watch.c
|
||||
|
||||
LIGHTNINGD_SRC_NOHDR := \
|
||||
lightningd/configs.c \
|
||||
lightningd/datastore.c \
|
||||
lightningd/ping.c \
|
||||
lightningd/offer.c \
|
||||
|
307
lightningd/configs.c
Normal file
307
lightningd/configs.c
Normal file
@ -0,0 +1,307 @@
|
||||
#include "config.h"
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/opt/opt.h>
|
||||
#include <ccan/opt/private.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/configdir.h>
|
||||
#include <common/configvar.h>
|
||||
#include <common/json_command.h>
|
||||
#include <common/json_param.h>
|
||||
#include <common/version.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
#include <lightningd/options.h>
|
||||
#include <lightningd/plugin.h>
|
||||
|
||||
static void json_add_source(struct json_stream *result,
|
||||
const char *fieldname,
|
||||
const struct configvar *cv)
|
||||
{
|
||||
const char *source;
|
||||
|
||||
if (!cv) {
|
||||
source = "default";
|
||||
} else {
|
||||
source = NULL;
|
||||
switch (cv->src) {
|
||||
case CONFIGVAR_CMDLINE:
|
||||
case CONFIGVAR_CMDLINE_SHORT:
|
||||
source = "cmdline";
|
||||
break;
|
||||
case CONFIGVAR_EXPLICIT_CONF:
|
||||
case CONFIGVAR_BASE_CONF:
|
||||
case CONFIGVAR_NETWORK_CONF:
|
||||
source = tal_fmt(tmpctx, "%s:%u", cv->file, cv->linenum);
|
||||
break;
|
||||
case CONFIGVAR_PLUGIN_START:
|
||||
source = "pluginstart";
|
||||
break;
|
||||
}
|
||||
}
|
||||
json_add_string(result, fieldname, source);
|
||||
}
|
||||
|
||||
static const char *configval_fieldname(const struct opt_table *ot)
|
||||
{
|
||||
bool multi = (ot->type & OPT_MULTI);
|
||||
if (ot->type & OPT_SHOWBOOL)
|
||||
return multi ? "values_bool" : "value_bool";
|
||||
if (ot->type & OPT_SHOWINT)
|
||||
return multi ? "values_int" : "value_int";
|
||||
if (ot->type & OPT_SHOWMSATS)
|
||||
return multi ? "values_msat" : "value_msat";
|
||||
return multi ? "values_str" : "value_str";
|
||||
}
|
||||
|
||||
#define CONFIG_SHOW_BUFSIZE 4096
|
||||
|
||||
static const char *get_opt_val(const struct opt_table *ot,
|
||||
char buf[],
|
||||
const struct configvar *cv)
|
||||
{
|
||||
if (ot->show == (void *)opt_show_charp) {
|
||||
/* Don't truncate or quote! */
|
||||
return *(char **)ot->u.carg;
|
||||
}
|
||||
if (ot->show) {
|
||||
/* Plugins options' show only shows defaults, so show val if
|
||||
* we have it */
|
||||
if (is_plugin_opt(ot) && cv)
|
||||
return cv->optarg;
|
||||
strcpy(buf + CONFIG_SHOW_BUFSIZE, "...");
|
||||
if (ot->show(buf, CONFIG_SHOW_BUFSIZE, ot->u.carg))
|
||||
return buf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For everything else we only display if it's set,
|
||||
* BUT we check here to make sure you've handled
|
||||
* everything! */
|
||||
if (is_known_opt_cb_arg(ot->cb_arg)
|
||||
|| is_restricted_print_if_nonnull(ot->cb_arg)) {
|
||||
/* Only if set! */
|
||||
if (cv)
|
||||
return cv->optarg;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert more decodes here! */
|
||||
errx(1, "Unknown decode for %s", ot->names);
|
||||
}
|
||||
|
||||
static void check_literal(const char *name, const char *val)
|
||||
{
|
||||
if (streq(val, "true") || streq(val, "false"))
|
||||
return;
|
||||
if (!streq(val, "") && strspn(val, "-0123456789.") == strlen(val))
|
||||
return;
|
||||
errx(1, "Bad literal for %s: %s", name, val);
|
||||
}
|
||||
|
||||
static void json_add_configval(struct json_stream *result,
|
||||
const char *fieldname,
|
||||
const struct opt_table *ot,
|
||||
const char *str)
|
||||
{
|
||||
if (ot->type & OPT_SHOWBOOL) {
|
||||
json_add_bool(result, fieldname, opt_canon_bool(str));
|
||||
} else if (ot->type & (OPT_SHOWMSATS|OPT_SHOWINT)) {
|
||||
check_literal(ot->names, str);
|
||||
json_add_primitive(result, fieldname, str);
|
||||
} else
|
||||
json_add_string(result, fieldname, str);
|
||||
}
|
||||
|
||||
/* Config vars can have multiple names ("--large-channels|--wumbo"), but first
|
||||
* is preferred */
|
||||
static void json_add_config(struct lightningd *ld,
|
||||
struct json_stream *response,
|
||||
bool always_include,
|
||||
const struct opt_table *ot,
|
||||
const char **names)
|
||||
{
|
||||
char buf[CONFIG_SHOW_BUFSIZE + sizeof("...")];
|
||||
const char *val;
|
||||
struct configvar *cv;
|
||||
|
||||
/* This tells us if they actually set the option */
|
||||
cv = configvar_first(ld->configvars, names);
|
||||
|
||||
/* Ignore dev/hidden options (deprecated) unless they actually used it */
|
||||
if (!cv
|
||||
&& (ot->desc == opt_hidden || (ot->type & OPT_DEV))
|
||||
&& !always_include) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore options which simply exit */
|
||||
if (ot->type & OPT_EXITS)
|
||||
return;
|
||||
|
||||
if (ot->type & OPT_NOARG) {
|
||||
json_object_start(response, names[0]);
|
||||
json_add_bool(response, "set", cv != NULL);
|
||||
json_add_source(response, "source", cv);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ot->type & OPT_HASARG);
|
||||
if (ot->type & OPT_MULTI) {
|
||||
json_object_start(response, names[0]);
|
||||
json_array_start(response, configval_fieldname(ot));
|
||||
while (cv) {
|
||||
val = get_opt_val(ot, buf, cv);
|
||||
json_add_configval(response, NULL, ot, val);
|
||||
cv = configvar_next(ld->configvars, cv, names);
|
||||
}
|
||||
json_array_end(response);
|
||||
|
||||
/* Iterate again, for sources */
|
||||
json_array_start(response, "sources");
|
||||
for (cv = configvar_first(ld->configvars, names);
|
||||
cv;
|
||||
cv = configvar_next(ld->configvars, cv, names)) {
|
||||
json_add_source(response, NULL, cv);
|
||||
}
|
||||
json_array_end(response);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns NULL if we don't want to print it */
|
||||
val = get_opt_val(ot, buf, cv);
|
||||
if (!val)
|
||||
return;
|
||||
|
||||
json_object_start(response, names[0]);
|
||||
json_add_configval(response, configval_fieldname(ot), ot, val);
|
||||
json_add_source(response, "source", cv);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
static struct command_result *param_opt_config(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
const struct opt_table **config)
|
||||
{
|
||||
const char *name0 = json_strdup(tmpctx, buffer, tok);
|
||||
*config = opt_find_long(name0, NULL);
|
||||
if (*config)
|
||||
return NULL;
|
||||
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"Unknown config option");
|
||||
}
|
||||
|
||||
/* FIXME: This is a hack! Expose somehow in ccan/opt.*/
|
||||
/* Returns string after first '-'. */
|
||||
static const char *first_name(const char *names, unsigned *len)
|
||||
{
|
||||
*len = strcspn(names + 1, "|= ");
|
||||
return names + 1;
|
||||
}
|
||||
|
||||
static const char *next_name(const char *names, unsigned *len)
|
||||
{
|
||||
names += *len;
|
||||
if (names[0] == ' ' || names[0] == '=' || names[0] == '\0')
|
||||
return NULL;
|
||||
return first_name(names + 1, len);
|
||||
}
|
||||
|
||||
static struct command_result *json_listconfigs(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct json_stream *response = NULL;
|
||||
const struct opt_table *config;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_opt("config", param_opt_config, &config),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
|
||||
if (!deprecated_apis)
|
||||
goto modern;
|
||||
|
||||
if (!config)
|
||||
json_add_string(response, "# version", version());
|
||||
|
||||
for (size_t i = 0; i < opt_count; i++) {
|
||||
unsigned int len;
|
||||
const char *name;
|
||||
|
||||
/* FIXME: Print out comment somehow? */
|
||||
if (opt_table[i].type == OPT_SUBTABLE)
|
||||
continue;
|
||||
|
||||
for (name = first_name(opt_table[i].names, &len);
|
||||
name;
|
||||
name = next_name(name, &len)) {
|
||||
/* Skips over first -, so just need to look for one */
|
||||
if (name[0] != '-')
|
||||
continue;
|
||||
|
||||
if (!config || config == &opt_table[i]) {
|
||||
add_config_deprecated(cmd->ld, response, &opt_table[i],
|
||||
name+1, len-1);
|
||||
}
|
||||
/* If we have more than one long name, first
|
||||
* is preferred */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modern:
|
||||
json_object_start(response, "configs");
|
||||
for (size_t i = 0; i < opt_count; i++) {
|
||||
unsigned int len;
|
||||
const char *name;
|
||||
const char **names;
|
||||
|
||||
/* FIXME: Print out comment somehow? */
|
||||
if (opt_table[i].type == OPT_SUBTABLE)
|
||||
continue;
|
||||
|
||||
if (config && config != &opt_table[i])
|
||||
continue;
|
||||
|
||||
names = tal_arr(tmpctx, const char *, 0);
|
||||
for (name = first_name(opt_table[i].names, &len);
|
||||
name;
|
||||
name = next_name(name, &len)) {
|
||||
/* Skips over first -, so just need to look for one */
|
||||
if (name[0] != '-')
|
||||
continue;
|
||||
tal_arr_expand(&names,
|
||||
tal_strndup(names, name+1, len-1));
|
||||
}
|
||||
/* We don't usually print dev or deprecated options, unless
|
||||
* they explicitly ask, or they're set. */
|
||||
json_add_config(cmd->ld, response, config != NULL,
|
||||
&opt_table[i], names);
|
||||
}
|
||||
json_object_end(response);
|
||||
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command listconfigs_command = {
|
||||
"listconfigs",
|
||||
"utility",
|
||||
json_listconfigs,
|
||||
"List all configuration options, or with [config], just that one.",
|
||||
.verbose = "listconfigs [config]\n"
|
||||
"Outputs an object, with each field a config options\n"
|
||||
"(Option names which start with # are comments)\n"
|
||||
"With [config], object only has that field"
|
||||
};
|
||||
AUTODATA(json_command, &listconfigs_command);
|
@ -1648,22 +1648,6 @@ void handle_opts(struct lightningd *ld)
|
||||
check_config(ld);
|
||||
}
|
||||
|
||||
/* FIXME: This is a hack! Expose somehow in ccan/opt.*/
|
||||
/* Returns string after first '-'. */
|
||||
static const char *first_name(const char *names, unsigned *len)
|
||||
{
|
||||
*len = strcspn(names + 1, "|= ");
|
||||
return names + 1;
|
||||
}
|
||||
|
||||
static const char *next_name(const char *names, unsigned *len)
|
||||
{
|
||||
names += *len;
|
||||
if (names[0] == ' ' || names[0] == '=' || names[0] == '\0')
|
||||
return NULL;
|
||||
return first_name(names + 1, len);
|
||||
}
|
||||
|
||||
static void json_add_opt_addrs(struct json_stream *response,
|
||||
const char *name0,
|
||||
const struct wireaddr_internal *wireaddrs,
|
||||
@ -1720,19 +1704,10 @@ bool opt_canon_bool(const char *val)
|
||||
return b;
|
||||
}
|
||||
|
||||
static void check_literal(const char *name, const char *val)
|
||||
{
|
||||
if (streq(val, "true") || streq(val, "false"))
|
||||
return;
|
||||
if (!streq(val, "") && strspn(val, "-0123456789.") == strlen(val))
|
||||
return;
|
||||
errx(1, "Bad literal for %s: %s", name, val);
|
||||
}
|
||||
|
||||
static void add_config_deprecated(struct lightningd *ld,
|
||||
struct json_stream *response,
|
||||
const struct opt_table *opt,
|
||||
const char *name, size_t len)
|
||||
void add_config_deprecated(struct lightningd *ld,
|
||||
struct json_stream *response,
|
||||
const struct opt_table *opt,
|
||||
const char *name, size_t len)
|
||||
{
|
||||
char *name0 = tal_strndup(tmpctx, name, len);
|
||||
char *answer = NULL;
|
||||
@ -1922,294 +1897,31 @@ static void add_config_deprecated(struct lightningd *ld,
|
||||
}
|
||||
}
|
||||
|
||||
static void json_add_source(struct json_stream *result,
|
||||
const char *fieldname,
|
||||
const struct configvar *cv)
|
||||
bool is_known_opt_cb_arg(char *(*cb_arg)(const char *, void *))
|
||||
{
|
||||
const char *source;
|
||||
|
||||
if (!cv) {
|
||||
source = "default";
|
||||
} else {
|
||||
source = NULL;
|
||||
switch (cv->src) {
|
||||
case CONFIGVAR_CMDLINE:
|
||||
case CONFIGVAR_CMDLINE_SHORT:
|
||||
source = "cmdline";
|
||||
break;
|
||||
case CONFIGVAR_EXPLICIT_CONF:
|
||||
case CONFIGVAR_BASE_CONF:
|
||||
case CONFIGVAR_NETWORK_CONF:
|
||||
source = tal_fmt(tmpctx, "%s:%u", cv->file, cv->linenum);
|
||||
break;
|
||||
case CONFIGVAR_PLUGIN_START:
|
||||
source = "pluginstart";
|
||||
break;
|
||||
}
|
||||
}
|
||||
json_add_string(result, fieldname, source);
|
||||
}
|
||||
|
||||
static const char *configval_fieldname(const struct opt_table *ot)
|
||||
{
|
||||
bool multi = (ot->type & OPT_MULTI);
|
||||
if (ot->type & OPT_SHOWBOOL)
|
||||
return multi ? "values_bool" : "value_bool";
|
||||
if (ot->type & OPT_SHOWINT)
|
||||
return multi ? "values_int" : "value_int";
|
||||
if (ot->type & OPT_SHOWMSATS)
|
||||
return multi ? "values_msat" : "value_msat";
|
||||
return multi ? "values_str" : "value_str";
|
||||
}
|
||||
|
||||
#define CONFIG_SHOW_BUFSIZE 4096
|
||||
|
||||
static const char *get_opt_val(const struct opt_table *ot,
|
||||
char buf[],
|
||||
const struct configvar *cv)
|
||||
{
|
||||
if (ot->show == (void *)opt_show_charp) {
|
||||
/* Don't truncate or quote! */
|
||||
return *(char **)ot->u.carg;
|
||||
}
|
||||
if (ot->show) {
|
||||
/* Plugins options' show only shows defaults, so show val if
|
||||
* we have it */
|
||||
if (is_plugin_opt(ot) && cv)
|
||||
return cv->optarg;
|
||||
strcpy(buf + CONFIG_SHOW_BUFSIZE, "...");
|
||||
if (ot->show(buf, CONFIG_SHOW_BUFSIZE, ot->u.carg))
|
||||
return buf;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* For everything else we only display if it's set,
|
||||
* BUT we check here to make sure you've handled
|
||||
* everything! */
|
||||
if (ot->cb_arg == (void *)opt_set_talstr
|
||||
|| ot->cb_arg == (void *)opt_add_proxy_addr
|
||||
|| ot->cb_arg == (void *)opt_force_feerates
|
||||
|| ot->cb_arg == (void *)opt_set_accept_extra_tlv_types
|
||||
|| ot->cb_arg == (void *)opt_set_websocket_port
|
||||
|| ot->cb_arg == (void *)opt_add_plugin
|
||||
|| ot->cb_arg == (void *)opt_add_plugin_dir
|
||||
|| ot->cb_arg == (void *)opt_important_plugin
|
||||
|| ot->cb_arg == (void *)opt_disable_plugin
|
||||
|| ot->cb_arg == (void *)opt_add_addr
|
||||
|| ot->cb_arg == (void *)opt_add_bind_addr
|
||||
|| ot->cb_arg == (void *)opt_add_announce_addr
|
||||
|| ot->cb_arg == (void *)opt_subdaemon
|
||||
|| ot->cb_arg == (void *)opt_set_db_upgrade
|
||||
|| ot->cb_arg == (void *)arg_log_to_file
|
||||
|| ot->cb_arg == (void *)opt_add_accept_htlc_tlv
|
||||
return cb_arg == (void *)opt_set_talstr
|
||||
|| cb_arg == (void *)opt_add_proxy_addr
|
||||
|| cb_arg == (void *)opt_force_feerates
|
||||
|| cb_arg == (void *)opt_set_accept_extra_tlv_types
|
||||
|| cb_arg == (void *)opt_set_websocket_port
|
||||
|| cb_arg == (void *)opt_add_plugin
|
||||
|| cb_arg == (void *)opt_add_plugin_dir
|
||||
|| cb_arg == (void *)opt_important_plugin
|
||||
|| cb_arg == (void *)opt_disable_plugin
|
||||
|| cb_arg == (void *)opt_add_addr
|
||||
|| cb_arg == (void *)opt_add_bind_addr
|
||||
|| cb_arg == (void *)opt_add_announce_addr
|
||||
|| cb_arg == (void *)opt_subdaemon
|
||||
|| cb_arg == (void *)opt_set_db_upgrade
|
||||
|| cb_arg == (void *)arg_log_to_file
|
||||
|| cb_arg == (void *)opt_add_accept_htlc_tlv
|
||||
#if DEVELOPER
|
||||
|| ot->cb_arg == (void *)opt_subd_dev_disconnect
|
||||
|| ot->cb_arg == (void *)opt_force_featureset
|
||||
|| ot->cb_arg == (void *)opt_force_privkey
|
||||
|| ot->cb_arg == (void *)opt_force_bip32_seed
|
||||
|| ot->cb_arg == (void *)opt_force_channel_secrets
|
||||
|| ot->cb_arg == (void *)opt_force_tmp_channel_id
|
||||
|| cb_arg == (void *)opt_subd_dev_disconnect
|
||||
|| cb_arg == (void *)opt_force_featureset
|
||||
|| cb_arg == (void *)opt_force_privkey
|
||||
|| cb_arg == (void *)opt_force_bip32_seed
|
||||
|| cb_arg == (void *)opt_force_channel_secrets
|
||||
|| cb_arg == (void *)opt_force_tmp_channel_id
|
||||
#endif
|
||||
|| is_restricted_print_if_nonnull(ot->cb_arg)) {
|
||||
/* Only if set! */
|
||||
if (cv)
|
||||
return cv->optarg;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Insert more decodes here! */
|
||||
errx(1, "Unknown decode for %s", ot->names);
|
||||
;
|
||||
}
|
||||
|
||||
static void json_add_configval(struct json_stream *result,
|
||||
const char *fieldname,
|
||||
const struct opt_table *ot,
|
||||
const char *str)
|
||||
{
|
||||
if (ot->type & OPT_SHOWBOOL) {
|
||||
json_add_bool(result, fieldname, opt_canon_bool(str));
|
||||
} else if (ot->type & (OPT_SHOWMSATS|OPT_SHOWINT)) {
|
||||
check_literal(ot->names, str);
|
||||
json_add_primitive(result, fieldname, str);
|
||||
} else
|
||||
json_add_string(result, fieldname, str);
|
||||
}
|
||||
|
||||
/* Config vars can have multiple names ("--large-channels|--wumbo"), but first
|
||||
* is preferred */
|
||||
static void json_add_config(struct lightningd *ld,
|
||||
struct json_stream *response,
|
||||
bool always_include,
|
||||
const struct opt_table *ot,
|
||||
const char **names)
|
||||
{
|
||||
char buf[CONFIG_SHOW_BUFSIZE + sizeof("...")];
|
||||
const char *val;
|
||||
struct configvar *cv;
|
||||
|
||||
/* This tells us if they actually set the option */
|
||||
cv = configvar_first(ld->configvars, names);
|
||||
|
||||
/* Ignore dev/hidden options (deprecated) unless they actually used it */
|
||||
if (!cv
|
||||
&& (ot->desc == opt_hidden || (ot->type & OPT_DEV))
|
||||
&& !always_include) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ignore options which simply exit */
|
||||
if (ot->type & OPT_EXITS)
|
||||
return;
|
||||
|
||||
if (ot->type & OPT_NOARG) {
|
||||
json_object_start(response, names[0]);
|
||||
json_add_bool(response, "set", cv != NULL);
|
||||
json_add_source(response, "source", cv);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ot->type & OPT_HASARG);
|
||||
if (ot->type & OPT_MULTI) {
|
||||
json_object_start(response, names[0]);
|
||||
json_array_start(response, configval_fieldname(ot));
|
||||
while (cv) {
|
||||
val = get_opt_val(ot, buf, cv);
|
||||
json_add_configval(response, NULL, ot, val);
|
||||
cv = configvar_next(ld->configvars, cv, names);
|
||||
}
|
||||
json_array_end(response);
|
||||
|
||||
/* Iterate again, for sources */
|
||||
json_array_start(response, "sources");
|
||||
for (cv = configvar_first(ld->configvars, names);
|
||||
cv;
|
||||
cv = configvar_next(ld->configvars, cv, names)) {
|
||||
json_add_source(response, NULL, cv);
|
||||
}
|
||||
json_array_end(response);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Returns NULL if we don't want to print it */
|
||||
val = get_opt_val(ot, buf, cv);
|
||||
if (!val)
|
||||
return;
|
||||
|
||||
json_object_start(response, names[0]);
|
||||
json_add_configval(response, configval_fieldname(ot), ot, val);
|
||||
json_add_source(response, "source", cv);
|
||||
json_add_config_plugin(response, ld->plugins, "plugin", ot);
|
||||
json_object_end(response);
|
||||
}
|
||||
|
||||
static struct command_result *param_opt_config(struct command *cmd,
|
||||
const char *name,
|
||||
const char *buffer,
|
||||
const jsmntok_t *tok,
|
||||
const struct opt_table **config)
|
||||
{
|
||||
const char *name0 = json_strdup(tmpctx, buffer, tok);
|
||||
*config = opt_find_long(name0, NULL);
|
||||
if (*config)
|
||||
return NULL;
|
||||
|
||||
return command_fail_badparam(cmd, name, buffer, tok,
|
||||
"Unknown config option");
|
||||
}
|
||||
|
||||
static struct command_result *json_listconfigs(struct command *cmd,
|
||||
const char *buffer,
|
||||
const jsmntok_t *obj UNNEEDED,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
struct json_stream *response = NULL;
|
||||
const struct opt_table *config;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
p_opt("config", param_opt_config, &config),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
response = json_stream_success(cmd);
|
||||
|
||||
if (!deprecated_apis)
|
||||
goto modern;
|
||||
|
||||
if (!config)
|
||||
json_add_string(response, "# version", version());
|
||||
|
||||
for (size_t i = 0; i < opt_count; i++) {
|
||||
unsigned int len;
|
||||
const char *name;
|
||||
|
||||
/* FIXME: Print out comment somehow? */
|
||||
if (opt_table[i].type == OPT_SUBTABLE)
|
||||
continue;
|
||||
|
||||
for (name = first_name(opt_table[i].names, &len);
|
||||
name;
|
||||
name = next_name(name, &len)) {
|
||||
/* Skips over first -, so just need to look for one */
|
||||
if (name[0] != '-')
|
||||
continue;
|
||||
|
||||
if (!config || config == &opt_table[i]) {
|
||||
add_config_deprecated(cmd->ld, response, &opt_table[i],
|
||||
name+1, len-1);
|
||||
}
|
||||
/* If we have more than one long name, first
|
||||
* is preferred */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
modern:
|
||||
json_object_start(response, "configs");
|
||||
for (size_t i = 0; i < opt_count; i++) {
|
||||
unsigned int len;
|
||||
const char *name;
|
||||
const char **names;
|
||||
|
||||
/* FIXME: Print out comment somehow? */
|
||||
if (opt_table[i].type == OPT_SUBTABLE)
|
||||
continue;
|
||||
|
||||
if (config && config != &opt_table[i])
|
||||
continue;
|
||||
|
||||
names = tal_arr(tmpctx, const char *, 0);
|
||||
for (name = first_name(opt_table[i].names, &len);
|
||||
name;
|
||||
name = next_name(name, &len)) {
|
||||
/* Skips over first -, so just need to look for one */
|
||||
if (name[0] != '-')
|
||||
continue;
|
||||
tal_arr_expand(&names,
|
||||
tal_strndup(names, name+1, len-1));
|
||||
}
|
||||
/* We don't usually print dev or deprecated options, unless
|
||||
* they explicitly ask, or they're set. */
|
||||
json_add_config(cmd->ld, response, config != NULL,
|
||||
&opt_table[i], names);
|
||||
}
|
||||
json_object_end(response);
|
||||
|
||||
return command_success(cmd, response);
|
||||
}
|
||||
|
||||
static const struct json_command listconfigs_command = {
|
||||
"listconfigs",
|
||||
"utility",
|
||||
json_listconfigs,
|
||||
"List all configuration options, or with [config], just that one.",
|
||||
.verbose = "listconfigs [config]\n"
|
||||
"Outputs an object, with each field a config options\n"
|
||||
"(Option names which start with # are comments)\n"
|
||||
"With [config], object only has that field"
|
||||
};
|
||||
AUTODATA(json_command, &listconfigs_command);
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include "config.h"
|
||||
#include <ccan/ccan/opt/opt.h>
|
||||
|
||||
struct json_stream;
|
||||
struct lightningd;
|
||||
|
||||
/* After this, early config file and cmdline options parsed. */
|
||||
@ -24,4 +25,10 @@ bool opt_show_autobool(char *buf, size_t len, const enum opt_autobool *b);
|
||||
|
||||
/* opt_bool is quite loose; you should use this if wanting to add it to JSON */
|
||||
bool opt_canon_bool(const char *val);
|
||||
|
||||
void add_config_deprecated(struct lightningd *ld,
|
||||
struct json_stream *response,
|
||||
const struct opt_table *opt,
|
||||
const char *name, size_t len);
|
||||
bool is_known_opt_cb_arg(char *(*cb_arg)(const char *, void *));
|
||||
#endif /* LIGHTNING_LIGHTNINGD_OPTIONS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user