forked from ElementsProject/lightning
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathplugin_control.c
137 lines (123 loc) · 4.1 KB
/
plugin_control.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#include <ccan/tal/path/path.h>
#include <common/json_command.h>
#include <common/jsonrpc_errors.h>
#include <common/param.h>
#include <dirent.h>
#include <errno.h>
#include <lightningd/plugin_control.h>
#include <lightningd/plugin_hook.h>
#include <unistd.h>
/**
* A plugin command which permits to control plugins without restarting
* lightningd. It takes a subcommand, and an optional subcommand parameter.
*/
static struct command_result *json_plugin_control(struct command *cmd,
const char *buffer,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
const char *subcmd;
subcmd = param_subcommand(cmd, buffer, params,
"start", "stop", "startdir", "rescan", "list", NULL);
if (!subcmd)
return command_param_failed();
struct plugin *p;
struct json_stream *response;
if (streq(subcmd, "stop")) {
const char *plugin_name;
bool plugin_found;
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
p_req("plugin", param_string, &plugin_name),
NULL))
return command_param_failed();
plugin_found = false;
list_for_each(&cmd->ld->plugins->plugins, p, list) {
if (plugin_paths_match(p->cmd, plugin_name)) {
if (!p->dynamic)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s plugin cannot be managed when lightningd is up",
plugin_name);
plugin_found = true;
plugin_hook_unregister_all(p);
plugin_kill(p, "%s stopped by lightningd via RPC",
plugin_name);
break;
}
}
if (!plugin_found)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Could not find plugin %s", plugin_name);
} else if (streq(subcmd, "start")) {
const char *plugin_path;
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
p_req("plugin", param_string, &plugin_path),
NULL))
return command_param_failed();
if (access(plugin_path, X_OK) == 0)
plugin_register(cmd->ld->plugins, plugin_path);
else
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"%s is not executable: %s",
plugin_path, strerror(errno));
} else if (streq(subcmd, "startdir")) {
const char *dir_path;
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
p_req("directory", param_string, &dir_path),
NULL))
return command_param_failed();
if (access(dir_path, F_OK) == 0)
add_plugin_dir(cmd->ld->plugins, dir_path, true);
else
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Could not open %s", dir_path);
} else if (streq(subcmd, "rescan")) {
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
NULL))
return command_param_failed();
plugins_add_default_dir(cmd->ld->plugins,
path_join(tmpctx, cmd->ld->config_dir, "plugins"));
} else if (streq(subcmd, "list")) {
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
NULL))
return command_param_failed();
/* Don't do anything as we return the plugin list anyway */
}
/* The config function is called once we got the manifest,
* in 'plugin_manifest_cb'.*/
plugins_start(cmd->ld->plugins, cmd->ld->dev_debug_subprocess);
response = json_stream_success(cmd);
json_array_start(response, "plugins");
list_for_each(&cmd->ld->plugins->plugins, p, list) {
json_object_start(response, NULL);
json_add_string(response, "name", p->cmd);
json_add_bool(response, "active",
p->plugin_state == CONFIGURED);
json_object_end(response);
}
json_array_end(response);
return command_success(cmd, response);
}
static const struct json_command plugin_control_command = {
"plugin",
"plugin",
json_plugin_control,
"Control plugins (start, stop, startdir, rescan, list)",
.verbose = "Usage :\n"
"plugin start /path/to/a/plugin\n"
" adds a new plugin to c-lightning\n"
"plugin stop plugin_name\n"
" stops an already registered plugin\n"
"plugin startdir /path/to/a/plugin_dir/\n"
" adds a new plugin directory\n"
"plugin rescan\n"
" loads not-already-loaded plugins from the default plugins dir\n"
"plugin list\n"
" lists all active plugins\n"
"\n"
};
AUTODATA(json_command, &plugin_control_command);