X-Git-Url: http://git.openwrt.org/?a=blobdiff_plain;f=rc.c;h=3d192f17a587115b81eeb3b5604d4322cdb5ead7;hb=HEAD;hp=b4787d582b252a0c1ee782dbcc63665ee301ee20;hpb=646daa0bec742e4c0af010ca85eda9021d95e4cf;p=project%2Frpcd.git diff --git a/rc.c b/rc.c index b4787d5..3d192f1 100644 --- a/rc.c +++ b/rc.c @@ -20,6 +20,17 @@ #define RC_LIST_EXEC_TIMEOUT_MS 3000 +enum { + RC_LIST_NAME, + RC_LIST_SKIP_RUNNING_CHECK, + __RC_LIST_MAX +}; + +static const struct blobmsg_policy rc_list_policy[] = { + [RC_LIST_NAME] = { "name", BLOBMSG_TYPE_STRING }, + [RC_LIST_SKIP_RUNNING_CHECK] = { "skip_running_check", BLOBMSG_TYPE_BOOL }, +}; + enum { RC_INIT_NAME, RC_INIT_ACTION, @@ -38,15 +49,18 @@ struct rc_list_context { struct ubus_request_data req; struct blob_buf *buf; DIR *dir; + bool skip_running_check; + const char *req_name; /* Info about currently processed init.d entry */ struct { char path[PATH_MAX]; const char *d_name; - unsigned int start; - unsigned int stop; + int start; + int stop; bool enabled; bool running; + bool use_procd; } entry; }; @@ -76,12 +90,13 @@ static void rc_list_add_table(struct rc_list_context *c) e = blobmsg_open_table(c->buf, c->entry.d_name); - if (c->entry.start) + if (c->entry.start >= 0) blobmsg_add_u16(c->buf, "start", c->entry.start); - if (c->entry.stop) + if (c->entry.stop >= 0) blobmsg_add_u16(c->buf, "stop", c->entry.stop); blobmsg_add_u8(c->buf, "enabled", c->entry.enabled); - blobmsg_add_u8(c->buf, "running", c->entry.running); + if (!c->skip_running_check && c->entry.use_procd) + blobmsg_add_u8(c->buf, "running", c->entry.running); blobmsg_close_table(c->buf, e); } @@ -112,6 +127,12 @@ static int rc_list_exec(struct rc_list_context *c, const char *action, uloop_pro case -1: return -errno; case 0: + if (c->skip_running_check) + exit(-EFAULT); + + if (!c->entry.use_procd) + exit(-EOPNOTSUPP); + /* Set stdin, stdout & stderr to /dev/null */ fd = open("/dev/null", O_RDWR); if (fd >= 0) { @@ -163,7 +184,12 @@ static void rc_list_readdir(struct rc_list_context *c) FILE *fp; e = readdir(c->dir); - if (!e) { + /* + * If scanning for a specific script and entry.d_name is set + * we can assume we found a matching one in the previous + * iteration since entry.d_name is set only if a match is found. + */ + if (!e || (c->req_name && c->entry.d_name)) { closedir(c->dir); ubus_send_reply(c->ctx, &c->req, c->buf->head); ubus_complete_deferred_request(c->ctx, &c->req, UBUS_STATUS_OK); @@ -173,7 +199,12 @@ static void rc_list_readdir(struct rc_list_context *c) if (!strcmp(e->d_name, ".") || !strcmp(e->d_name, "..")) goto next; + if (c->req_name && strcmp(e->d_name, c->req_name)) + goto next; + memset(&c->entry, 0, sizeof(c->entry)); + c->entry.start = -1; + c->entry.stop = -1; snprintf(c->entry.path, sizeof(c->entry.path), "/etc/init.d/%s", e->d_name); if (rc_check_script(c->entry.path)) @@ -185,26 +216,34 @@ static void rc_list_readdir(struct rc_list_context *c) if (fp) { struct stat s; char path[PATH_MAX]; - char line[32]; + char line[255]; bool beginning; + int count = 0; beginning = true; - while (!c->entry.start && !c->entry.stop && fgets(line, sizeof(line), fp)) { + while ((c->entry.start < 0 || c->entry.stop < 0 || + (!c->skip_running_check && !c->entry.use_procd)) && + count <= 10 && fgets(line, sizeof(line), fp)) { if (beginning) { if (!strncmp(line, "START=", 6)) { c->entry.start = strtoul(line + 6, NULL, 0); } else if (!strncmp(line, "STOP=", 5)) { c->entry.stop = strtoul(line + 5, NULL, 0); + } else if (!c->skip_running_check && !strncmp(line, "USE_PROCD=", 10)) { + c->entry.use_procd = !!strtoul(line + 10, NULL, 0); } + count++; } beginning = !!strchr(line, '\n'); } fclose(fp); - snprintf(path, sizeof(path), "/etc/rc.d/S%02d%s", c->entry.start, c->entry.d_name); - if (!stat(path, &s) && (s.st_mode & S_IXUSR)) - c->entry.enabled = true; + if (c->entry.start >= 0) { + snprintf(path, sizeof(path), "/etc/rc.d/S%02d%s", c->entry.start, c->entry.d_name); + if (!stat(path, &s) && (s.st_mode & S_IXUSR)) + c->entry.enabled = true; + } } if (rc_list_exec(c, "running", rc_list_exec_running_cb)) @@ -222,9 +261,12 @@ static int rc_list(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { + struct blob_attr *tb[__RC_LIST_MAX]; static struct blob_buf buf; struct rc_list_context *c; + blobmsg_parse(rc_list_policy, __RC_LIST_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); + blob_buf_init(&buf, 0); c = calloc(1, sizeof(*c)); @@ -238,6 +280,10 @@ static int rc_list(struct ubus_context *ctx, struct ubus_object *obj, free(c); return UBUS_STATUS_UNKNOWN_ERROR; } + if (tb[RC_LIST_SKIP_RUNNING_CHECK]) + c->skip_running_check = blobmsg_get_bool(tb[RC_LIST_SKIP_RUNNING_CHECK]); + if (tb[RC_LIST_NAME]) + c->req_name = blobmsg_get_string(tb[RC_LIST_NAME]); ubus_defer_request(ctx, req, &c->req); @@ -345,7 +391,7 @@ static int rc_init(struct ubus_context *ctx, struct ubus_object *obj, int rpc_rc_api_init(struct ubus_context *ctx) { static const struct ubus_method rc_methods[] = { - UBUS_METHOD_NOARG("list", rc_list), + UBUS_METHOD("list", rc_list, rc_list_policy), UBUS_METHOD("init", rc_init, rc_init_policy), };