📄 parser.c
字号:
nargs = 0; } break; case T_TEXT: if (nargs < MAXARGS) { args[nargs++] = state.text; } break; } }}int parse_config_file(const char *fn){ char *data; data = read_file(fn, 0); if (!data) return -1; parse_config(fn, data); DUMP(); return 0;}static int valid_name(const char *name){ if (strlen(name) > 16) { return 0; } while (*name) { if (!isalnum(*name) && (*name != '_') && (*name != '-')) { return 0; } name++; } return 1;}struct service *service_find_by_name(const char *name){ struct listnode *node; struct service *svc; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (!strcmp(svc->name, name)) { return svc; } } return 0;}struct service *service_find_by_pid(pid_t pid){ struct listnode *node; struct service *svc; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (svc->pid == pid) { return svc; } } return 0;}void service_for_each_class(const char *classname, void (*func)(struct service *svc)){ struct listnode *node; struct service *svc; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (!strcmp(svc->classname, classname)) { func(svc); } }}void service_for_each_flags(unsigned matchflags, void (*func)(struct service *svc)){ struct listnode *node; struct service *svc; list_for_each(node, &service_list) { svc = node_to_item(node, struct service, slist); if (svc->flags & matchflags) { func(svc); } }}void action_for_each_trigger(const char *trigger, void (*func)(struct action *act)){ struct listnode *node; struct action *act; list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); if (!strcmp(act->name, trigger)) { func(act); } }}void queue_property_triggers(const char *name, const char *value){ struct listnode *node; struct action *act; list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); if (!strncmp(act->name, "property:", strlen("property:"))) { const char *test = act->name + strlen("property:"); int name_length = strlen(name); if (!strncmp(name, test, name_length) && test[name_length] == '=' && !strcmp(test + name_length + 1, value)) { action_add_queue_tail(act); } } }}void queue_all_property_triggers(){ struct listnode *node; struct action *act; list_for_each(node, &action_list) { act = node_to_item(node, struct action, alist); if (!strncmp(act->name, "property:", strlen("property:"))) { /* parse property name and value syntax is property:<name>=<value> */ const char* name = act->name + strlen("property:"); const char* equals = strchr(name, '='); if (equals) { char* prop_name[PROP_NAME_MAX + 1]; const char* value; int length = equals - name; if (length > PROP_NAME_MAX) { ERROR("property name too long in trigger %s", act->name); } else { memcpy(prop_name, name, length); prop_name[length] = 0; /* does the property exist, and match the trigger value? */ value = property_get((const char *)&prop_name[0]); if (value && !strcmp(equals + 1, value)) { action_add_queue_tail(act); } } } } }}void action_add_queue_tail(struct action *act){ list_add_tail(&action_queue, &act->qlist);}struct action *action_remove_queue_head(void){ if (list_empty(&action_queue)) { return 0; } else { struct listnode *node = list_head(&action_queue); struct action *act = node_to_item(node, struct action, qlist); list_remove(node); return act; }}static void *parse_service(struct parse_state *state, int nargs, char **args){ struct service *svc; if (nargs < 3) { parse_error(state, "services must have a name and a program\n"); return 0; } if (!valid_name(args[1])) { parse_error(state, "invalid service name '%s'\n", args[1]); return 0; } svc = service_find_by_name(args[1]); if (svc) { parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]); return 0; } nargs -= 2; svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs); if (!svc) { parse_error(state, "out of memory\n"); return 0; } svc->name = args[1]; svc->classname = "default"; memcpy(svc->args, args + 2, sizeof(char*) * nargs); svc->args[nargs] = 0; svc->nargs = nargs; svc->onrestart.name = "onrestart"; list_init(&svc->onrestart.commands); list_add_tail(&service_list, &svc->slist); return svc;}static void parse_line_service(struct parse_state *state, int nargs, char **args){ struct service *svc = state->context; struct command *cmd; int kw, kw_nargs; if (nargs == 0) { return; } kw = lookup_keyword(args[0]); switch (kw) { case K_capability: break; case K_class: if (nargs != 2) { parse_error(state, "class option requires a classname\n"); } else { svc->classname = args[1]; } break; case K_console: svc->flags |= SVC_CONSOLE; break; case K_disabled: svc->flags |= SVC_DISABLED; break; case K_group: if (nargs < 2) { parse_error(state, "group option requires a group id\n"); } else if (nargs > NR_SVC_SUPP_GIDS + 2) { parse_error(state, "group option accepts at most %d supp. groups\n", NR_SVC_SUPP_GIDS); } else { int n; svc->gid = decode_uid(args[1]); for (n = 2; n < nargs; n++) { svc->supp_gids[n-2] = decode_uid(args[n]); } svc->nr_supp_gids = n - 2; } break; case K_oneshot: svc->flags |= SVC_ONESHOT; break; case K_onrestart: nargs--; args++; kw = lookup_keyword(args[0]); if (!kw_is(kw, COMMAND)) { parse_error(state, "invalid command '%s'\n", args[0]); break; } kw_nargs = kw_nargs(kw); if (nargs < kw_nargs) { parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1, kw_nargs > 2 ? "arguments" : "argument"); break; } cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); cmd->func = kw_func(kw); cmd->nargs = nargs; memcpy(cmd->args, args, sizeof(char*) * nargs); list_add_tail(&svc->onrestart.commands, &cmd->clist); break; case K_critical: svc->flags |= SVC_CRITICAL; break; case K_setenv: { /* name value */ struct svcenvinfo *ei; if (nargs < 2) { parse_error(state, "setenv option requires name and value arguments\n"); break; } ei = calloc(1, sizeof(*ei)); if (!ei) { parse_error(state, "out of memory\n"); break; } ei->name = args[1]; ei->value = args[2]; ei->next = svc->envvars; svc->envvars = ei; break; } case K_socket: {/* name type perm [ uid gid ] */ struct socketinfo *si; if (nargs < 4) { parse_error(state, "socket option requires name, type, perm arguments\n"); break; } if (strcmp(args[2],"dgram") && strcmp(args[2],"stream")) { parse_error(state, "socket type must be 'dgram' or 'stream'\n"); break; } si = calloc(1, sizeof(*si)); if (!si) { parse_error(state, "out of memory\n"); break; } si->name = args[1]; si->type = args[2]; si->perm = strtoul(args[3], 0, 8); if (nargs > 4) si->uid = decode_uid(args[4]); if (nargs > 5) si->gid = decode_uid(args[5]); si->next = svc->sockets; svc->sockets = si; break; } case K_user: if (nargs != 2) { parse_error(state, "user option requires a user id\n"); } else { svc->uid = decode_uid(args[1]); } break; default: parse_error(state, "invalid option '%s'\n", args[0]); }}static void *parse_action(struct parse_state *state, int nargs, char **args){ struct action *act; if (nargs < 2) { parse_error(state, "actions must have a trigger\n"); return 0; } if (nargs > 2) { parse_error(state, "actions may not have extra parameters\n"); return 0; } act = calloc(1, sizeof(*act)); act->name = args[1]; list_init(&act->commands); list_add_tail(&action_list, &act->alist); /* XXX add to hash */ return act;}static void parse_line_action(struct parse_state* state, int nargs, char **args){ struct command *cmd; struct action *act = state->context; int (*func)(int nargs, char **args); int kw, n; if (nargs == 0) { return; } kw = lookup_keyword(args[0]); if (!kw_is(kw, COMMAND)) { parse_error(state, "invalid command '%s'\n", args[0]); return; } n = kw_nargs(kw); if (nargs < n) { parse_error(state, "%s requires %d %s\n", args[0], n - 1, n > 2 ? "arguments" : "argument"); return; } cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs); cmd->func = kw_func(kw); cmd->nargs = nargs; memcpy(cmd->args, args, sizeof(char*) * nargs); list_add_tail(&act->commands, &cmd->clist);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -