diff --git a/plugins/bkpr/test/run-bkpr_db.c b/plugins/bkpr/test/run-bkpr_db.c index 04ffe463f..848480a6a 100644 --- a/plugins/bkpr/test/run-bkpr_db.c +++ b/plugins/bkpr/test/run-bkpr_db.c @@ -167,12 +167,19 @@ bool json_to_u16(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, /* Generated stub for json_tok_bin_from_hex */ u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED) { fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); } +/* Generated stub for json_tok_copy */ +jsmntok_t *json_tok_copy(const tal_t *ctx UNNEEDED, const jsmntok_t *tok UNNEEDED) +{ fprintf(stderr, "json_tok_copy called!\n"); abort(); } /* Generated stub for json_tok_full */ const char *json_tok_full(const char *buffer UNNEEDED, const jsmntok_t *t UNNEEDED) { fprintf(stderr, "json_tok_full called!\n"); abort(); } /* Generated stub for json_tok_full_len */ int json_tok_full_len(const jsmntok_t *t UNNEEDED) { fprintf(stderr, "json_tok_full_len called!\n"); abort(); } +/* Generated stub for json_tok_remove */ +void json_tok_remove(jsmntok_t **tokens UNNEEDED, + jsmntok_t *obj_or_array UNNEEDED, const jsmntok_t *tok UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "json_tok_remove called!\n"); abort(); } /* Generated stub for json_tok_streq */ bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED) { fprintf(stderr, "json_tok_streq called!\n"); abort(); } @@ -193,6 +200,11 @@ struct channel_event *new_channel_event(const tal_t *ctx UNNEEDED, u32 part_id UNNEEDED, u64 timestamp UNNEEDED) { fprintf(stderr, "new_channel_event called!\n"); abort(); } +/* Generated stub for param_check */ +bool param_check(struct command *cmd UNNEEDED, + const char *buffer UNNEEDED, + const jsmntok_t tokens[] UNNEEDED, ...) +{ fprintf(stderr, "param_check called!\n"); abort(); } /* Generated stub for toks_alloc */ jsmntok_t *toks_alloc(const tal_t *ctx UNNEEDED) { fprintf(stderr, "toks_alloc called!\n"); abort(); } diff --git a/plugins/bkpr/test/run-recorder.c b/plugins/bkpr/test/run-recorder.c index 73fcf54a8..b953cd820 100644 --- a/plugins/bkpr/test/run-recorder.c +++ b/plugins/bkpr/test/run-recorder.c @@ -173,12 +173,19 @@ bool json_to_u16(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, /* Generated stub for json_tok_bin_from_hex */ u8 *json_tok_bin_from_hex(const tal_t *ctx UNNEEDED, const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED) { fprintf(stderr, "json_tok_bin_from_hex called!\n"); abort(); } +/* Generated stub for json_tok_copy */ +jsmntok_t *json_tok_copy(const tal_t *ctx UNNEEDED, const jsmntok_t *tok UNNEEDED) +{ fprintf(stderr, "json_tok_copy called!\n"); abort(); } /* Generated stub for json_tok_full */ const char *json_tok_full(const char *buffer UNNEEDED, const jsmntok_t *t UNNEEDED) { fprintf(stderr, "json_tok_full called!\n"); abort(); } /* Generated stub for json_tok_full_len */ int json_tok_full_len(const jsmntok_t *t UNNEEDED) { fprintf(stderr, "json_tok_full_len called!\n"); abort(); } +/* Generated stub for json_tok_remove */ +void json_tok_remove(jsmntok_t **tokens UNNEEDED, + jsmntok_t *obj_or_array UNNEEDED, const jsmntok_t *tok UNNEEDED, size_t num UNNEEDED) +{ fprintf(stderr, "json_tok_remove called!\n"); abort(); } /* Generated stub for json_tok_streq */ bool json_tok_streq(const char *buffer UNNEEDED, const jsmntok_t *tok UNNEEDED, const char *str UNNEEDED) { fprintf(stderr, "json_tok_streq called!\n"); abort(); } @@ -199,6 +206,11 @@ struct channel_event *new_channel_event(const tal_t *ctx UNNEEDED, u32 part_id UNNEEDED, u64 timestamp UNNEEDED) { fprintf(stderr, "new_channel_event called!\n"); abort(); } +/* Generated stub for param_check */ +bool param_check(struct command *cmd UNNEEDED, + const char *buffer UNNEEDED, + const jsmntok_t tokens[] UNNEEDED, ...) +{ fprintf(stderr, "param_check called!\n"); abort(); } /* Generated stub for toks_alloc */ jsmntok_t *toks_alloc(const tal_t *ctx UNNEEDED) { fprintf(stderr, "toks_alloc called!\n"); abort(); } diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 9cb374cd7..d7657d15e 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -595,15 +596,18 @@ bool command_dev_apis(const struct command *cmd) return cmd->plugin->developer; } -/* FIXME: would be good to support this! */ bool command_check_only(const struct command *cmd) { - return false; + return cmd->check; } struct command_result *command_check_done(struct command *cmd) { - abort(); + assert(command_check_only(cmd)); + + return command_success(cmd, + json_out_obj(cmd, "command_to_check", + cmd->methodname)); } void command_set_usage(struct command *cmd, const char *usage TAKES) @@ -1098,6 +1102,7 @@ handle_getmanifest(struct command *getmanifest_cmd, json_add_bool(params, "dynamic", p->restartability == PLUGIN_RESTARTABLE); json_add_bool(params, "nonnumericids", true); + json_add_bool(params, "cancheck", true); json_array_start(params, "notifications"); for (size_t i = 0; p->notif_topics && i < p->num_notif_topics; i++) { @@ -1681,6 +1686,14 @@ bool command_deprecated_ok_flag(const struct command *cmd) return cmd->plugin->deprecated_ok; } +static struct command_result *param_tok(struct command *cmd, const char *name, + const char *buffer, const jsmntok_t * tok, + const jsmntok_t **out) +{ + *out = tok; + return NULL; +} + static void ld_command_handle(struct plugin *plugin, const jsmntok_t *toks) { @@ -1778,6 +1791,34 @@ static void ld_command_handle(struct plugin *plugin, return; } + /* Is this actually a check command? */ + cmd->check = streq(cmd->methodname, "check"); + if (cmd->check) { + const jsmntok_t *method; + jsmntok_t *mod_params; + + /* We're going to mangle it, so make a copy */ + mod_params = json_tok_copy(cmd, paramstok); + if (!param_check(cmd, plugin->buffer, mod_params, + p_req("command_to_check", param_tok, &method), + p_opt_any(), + NULL)) { + plugin_err(plugin, + "lightningd check without command_to_check: %.*s", + json_tok_full_len(toks), + json_tok_full(plugin->buffer, toks)); + } + tal_free(cmd->methodname); + cmd->methodname = json_strdup(cmd, plugin->buffer, method); + + /* Point method to the name, not the value */ + if (mod_params->type == JSMN_OBJECT) + method--; + + json_tok_remove(&mod_params, mod_params, method, 1); + paramstok = mod_params; + } + for (size_t i = 0; i < plugin->num_commands; i++) { if (streq(cmd->methodname, plugin->commands[i].name)) { plugin->commands[i].handle(cmd, @@ -1809,6 +1850,12 @@ static void ld_command_handle(struct plugin *plugin, "lightningd setconfig non-dynamic option '%s'?", config); } + /* FIXME: allow checking into handler! */ + if (command_check_only(cmd)) { + ret = command_check_done(cmd); + return; + } + valtok = json_get_member(plugin->buffer, paramstok, "val"); if (valtok) val = json_strdup(tmpctx, plugin->buffer, valtok); diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 6f63e4214..3e24391d1 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -53,6 +53,7 @@ struct command { const char *id; const char *methodname; bool usage_only; + bool check; struct plugin *plugin; /* Optional output field filter. */ struct json_filter *filter;