diff options
author | Felix Fietkau <nbd@openwrt.org> | 2011-09-10 18:34:43 +0200 |
---|---|---|
committer | Felix Fietkau <nbd@openwrt.org> | 2011-09-10 18:34:43 +0200 |
commit | c601d036d6e9efce0c31eecd0fc66a716f41f2a3 (patch) | |
tree | ffd5a7d605f1c05f56f1264f49a1c8403863acfe /proto-shell.c | |
parent | 0e54c1a6088b7df98da521e4b60ac8b7e6429662 (diff) |
fix invoking shell protocol handler scripts
Diffstat (limited to 'proto-shell.c')
-rw-r--r-- | proto-shell.c | 62 |
1 files changed, 54 insertions, 8 deletions
diff --git a/proto-shell.c b/proto-shell.c index 351e0bf..84d1c9c 100644 --- a/proto-shell.c +++ b/proto-shell.c @@ -13,7 +13,7 @@ #include "proto.h" static LIST_HEAD(handlers); -static int proto_fd, main_fd; +static int proto_fd; struct proto_shell_handler { struct list_head list; @@ -25,21 +25,69 @@ struct proto_shell_handler { struct proto_shell_state { struct interface_proto_state proto; + struct proto_shell_handler *handler; struct blob_attr *config; }; -#define DUMP_SUFFIX " dump" +#define DUMP_SUFFIX " '' dump" + +static int run_script(const char **argv) +{ + int pid, ret; + + if ((pid = fork()) < 0) + return -1; + + if (!pid) { + fchdir(proto_fd); + execvp(argv[0], (char **) argv); + exit(127); + } + + if (waitpid(pid, &ret, 0) == -1) + ret = -1; + + if (ret > 0) + return -ret; + + return 0; +} static int proto_shell_handler(struct interface_proto_state *proto, enum interface_proto_cmd cmd, bool force) { + struct proto_shell_state *state; + struct proto_shell_handler *handler; + const char *argv[5]; + char *config; + int ret; + + state = container_of(proto, struct proto_shell_state, proto); + handler = state->handler; + + config = blobmsg_format_json(state->config, true); + if (!config) + return -1; + + argv[0] = handler->script_name; + argv[1] = handler->proto.name; + argv[2] = "teardown"; + argv[3] = config; + argv[4] = NULL; + switch(cmd) { case PROTO_CMD_SETUP: + argv[2] = "setup"; + /* fall through */ case PROTO_CMD_TEARDOWN: + ret = run_script(argv); break; } - return 0; + + free(config); + + return ret; } static void @@ -66,6 +114,7 @@ proto_shell_attach(const struct proto_handler *h, struct interface *iface, memcpy(state->config, attr, blob_pad_len(attr)); state->proto.free = proto_shell_free; state->proto.handler = proto_shell_handler; + state->handler = container_of(h, struct proto_shell_handler, proto); return &state->proto; @@ -228,6 +277,7 @@ static void proto_shell_add_script(const char *name) void __init proto_shell_init(void) { glob_t g; + int main_fd; int i; main_fd = open(".", O_RDONLY | O_DIRECTORY); @@ -250,11 +300,7 @@ void __init proto_shell_init(void) for (i = 0; i < g.gl_pathc; i++) proto_shell_add_script(g.gl_pathv[i]); - if (list_empty(&handlers)) - close(proto_fd); - close_cur: fchdir(main_fd); - if (list_empty(&handlers)) - close(main_fd); + close(main_fd); } |