X-Git-Url: http://git.archive.openwrt.org/?p=project%2Frpcd.git;a=blobdiff_plain;f=luci2.c;h=ece2af38f4e5861f0041dd3ba8fbfbc64f91ddd5;hp=4420658b4f5e2498b792496a9f45e24a70c0693e;hb=f1aa60efc5435d0897417959793794d4ec195ad2;hpb=0b1a426e7919eee34529267ad6f56ae9d690634c diff --git a/luci2.c b/luci2.c index 4420658..ece2af3 100644 --- a/luci2.c +++ b/luci2.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include @@ -41,6 +43,17 @@ static const struct blobmsg_policy rpc_signal_policy[__RPC_S_MAX] = { [RPC_S_SIGNAL] = { .name = "signal", .type = BLOBMSG_TYPE_INT32 }, }; +enum { + RPC_I_NAME, + RPC_I_ACTION, + __RPC_I_MAX, +}; + +static const struct blobmsg_policy rpc_init_policy[__RPC_I_MAX] = { + [RPC_I_NAME] = { .name = "name", .type = BLOBMSG_TYPE_STRING }, + [RPC_I_ACTION] = { .name = "action", .type = BLOBMSG_TYPE_STRING }, +}; + static int rpc_errno_status(void) @@ -285,6 +298,148 @@ rpc_luci2_process_signal(struct ubus_context *ctx, struct ubus_object *obj, return 0; } +static int +rpc_luci2_init_list(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + int n; + void *c, *t; + char *p, path[PATH_MAX]; + struct stat s; + struct dirent *e; + FILE *f; + DIR *d; + + if (!(d = opendir("/etc/init.d"))) + return rpc_errno_status(); + + blob_buf_init(&buf, 0); + c = blobmsg_open_array(&buf, "initscripts"); + + while ((e = readdir(d)) != NULL) + { + snprintf(path, sizeof(path) - 1, "/etc/init.d/%s", e->d_name); + + if (stat(path, &s) || !S_ISREG(s.st_mode) || !(s.st_mode & S_IXUSR)) + continue; + + if ((f = fopen(path, "r")) != NULL) + { + n = -1; + p = fgets(path, sizeof(path) - 1, f); + + if (!p || !strstr(p, "/etc/rc.common")) + goto skip; + + t = blobmsg_open_table(&buf, NULL); + + blobmsg_add_string(&buf, "name", e->d_name); + + while (fgets(path, sizeof(path) - 1, f)) + { + p = strtok(path, "= \t"); + + if (!strcmp(p, "START") && !!(p = strtok(NULL, "= \t\n"))) + { + n = atoi(p); + blobmsg_add_u32(&buf, "start", n); + } + else if (!strcmp(p, "STOP") && !!(p = strtok(NULL, "= \t\n"))) + { + blobmsg_add_u32(&buf, "stop", atoi(p)); + break; + } + } + + if (n > -1) + { + snprintf(path, sizeof(path) - 1, "/etc/rc.d/S%02d%s", + n, e->d_name); + + blobmsg_add_u8(&buf, "enabled", + (!stat(path, &s) && (s.st_mode & S_IXUSR))); + } + else + { + blobmsg_add_u8(&buf, "enabled", 0); + } + + blobmsg_close_table(&buf, t); + +skip: + fclose(f); + } + } + + closedir(d); + blobmsg_close_array(&buf, c); + + ubus_send_reply(ctx, req, buf.head); + return 0; +} + +static int +rpc_luci2_init_action(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + int fd; + pid_t pid; + struct stat s; + char path[PATH_MAX]; + const char *action; + struct blob_attr *tb[__RPC_I_MAX]; + + blobmsg_parse(rpc_init_policy, __RPC_I_MAX, tb, + blob_data(msg), blob_len(msg)); + + if (!tb[RPC_I_NAME] || !tb[RPC_I_ACTION]) + return UBUS_STATUS_INVALID_ARGUMENT; + + action = blobmsg_data(tb[RPC_I_ACTION]); + + if (strcmp(action, "start") && strcmp(action, "stop") && + strcmp(action, "reload") && strcmp(action, "restart") && + strcmp(action, "enable") && strcmp(action, "disable")) + return UBUS_STATUS_INVALID_ARGUMENT; + + snprintf(path, sizeof(path) - 1, "/etc/init.d/%s", + (char *)blobmsg_data(tb[RPC_I_NAME])); + + if (stat(path, &s)) + return rpc_errno_status(); + + if (!(s.st_mode & S_IXUSR)) + return UBUS_STATUS_PERMISSION_DENIED; + + switch ((pid = fork())) + { + case -1: + return rpc_errno_status(); + + case 0: + uloop_done(); + + if ((fd = open("/dev/null", O_RDWR)) > -1) + { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + + close(fd); + } + + chdir("/"); + + if (execl(path, path, action, NULL)) + return rpc_errno_status(); + + default: + return 0; + } +} + static FILE * dnsmasq_leasefile(void) @@ -814,6 +969,9 @@ int rpc_luci2_api_init(struct ubus_context *ctx) UBUS_METHOD_NOARG("process_list", rpc_luci2_process_list), UBUS_METHOD("process_signal", rpc_luci2_process_signal, rpc_signal_policy), + UBUS_METHOD_NOARG("init_list", rpc_luci2_init_list), + UBUS_METHOD("init_action", rpc_luci2_init_action, + rpc_init_policy) }; static struct ubus_object_type luci2_system_type =