diff options
| author | Elliott Hughes <enh@google.com> | 2015-02-03 17:12:07 -0800 |
|---|---|---|
| committer | Elliott Hughes <enh@google.com> | 2015-02-04 08:59:10 -0800 |
| commit | f3cf438714aa1284d8a58e2f3b108ba93f6d3abb (patch) | |
| tree | 3a1b726c6805315c280d745e8b742ec9542d58e9 /init/ueventd_parser.cpp | |
| parent | 5204b1580e0d0f38272c7da166eee9b88c14dc50 (diff) | |
| download | core-f3cf438714aa1284d8a58e2f3b108ba93f6d3abb.tar.gz core-f3cf438714aa1284d8a58e2f3b108ba93f6d3abb.tar.bz2 core-f3cf438714aa1284d8a58e2f3b108ba93f6d3abb.zip | |
Build init as C++.
This is just the minimal change to keep it building.
Change-Id: I245c5b8413a1db114576c81462eb5737f5ffcef2
Diffstat (limited to 'init/ueventd_parser.cpp')
| -rw-r--r-- | init/ueventd_parser.cpp | 246 |
1 files changed, 246 insertions, 0 deletions
diff --git a/init/ueventd_parser.cpp b/init/ueventd_parser.cpp new file mode 100644 index 000000000..f54a90ba0 --- /dev/null +++ b/init/ueventd_parser.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) 2010 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> + +#include "ueventd.h" +#include "ueventd_parser.h" +#include "parser.h" +#include "log.h" +#include "util.h" + +static list_declare(subsystem_list); + +static void parse_line_device(struct parse_state *state, int nargs, char **args); + +#define SECTION 0x01 +#define OPTION 0x02 + +#include "ueventd_keywords.h" + +#define KEYWORD(symbol, flags, nargs) \ + [ K_##symbol ] = { #symbol, nargs + 1, flags, }, + +static struct { + const char *name; + unsigned char nargs; + unsigned char flags; +} keyword_info[KEYWORD_COUNT] = { + [ K_UNKNOWN ] = { "unknown", 0, 0 }, +#include "ueventd_keywords.h" +}; +#undef KEYWORD + +#define kw_is(kw, type) (keyword_info[kw].flags & (type)) +#define kw_nargs(kw) (keyword_info[kw].nargs) + +static int lookup_keyword(const char *s) +{ + switch (*s++) { + case 'd': + if (!strcmp(s, "evname")) return K_devname; + if (!strcmp(s, "irname")) return K_dirname; + break; + case 's': + if (!strcmp(s, "ubsystem")) return K_subsystem; + break; + } + return K_UNKNOWN; +} + +static void parse_line_no_op(struct parse_state *state __attribute__((unused)), + int nargs __attribute__((unused)), char **args __attribute__((unused))) +{ +} + +static int valid_name(const char *name) +{ + while (*name) { + if (!isalnum(*name) && (*name != '_') && (*name != '-')) { + return 0; + } + name++; + } + return 1; +} + +struct ueventd_subsystem *ueventd_subsystem_find_by_name(const char *name) +{ + struct listnode *node; + struct ueventd_subsystem *s; + + list_for_each(node, &subsystem_list) { + s = node_to_item(node, struct ueventd_subsystem, slist); + if (!strcmp(s->name, name)) { + return s; + } + } + return 0; +} + +static void *parse_subsystem(struct parse_state *state, + int nargs __attribute__((unused)), char **args) +{ + if (!valid_name(args[1])) { + parse_error(state, "invalid subsystem name '%s'\n", args[1]); + return 0; + } + + ueventd_subsystem* s = ueventd_subsystem_find_by_name(args[1]); + if (s) { + parse_error(state, "ignored duplicate definition of subsystem '%s'\n", + args[1]); + return 0; + } + + s = (ueventd_subsystem*) calloc(1, sizeof(*s)); + if (!s) { + parse_error(state, "out of memory\n"); + return 0; + } + s->name = args[1]; + s->dirname = "/dev"; + list_add_tail(&subsystem_list, &s->slist); + return s; +} + +static void parse_line_subsystem(struct parse_state *state, int nargs, + char **args) +{ + struct ueventd_subsystem *s = (ueventd_subsystem*) state->context; + int kw; + + if (nargs == 0) { + return; + } + + kw = lookup_keyword(args[0]); + switch (kw) { + case K_devname: + if (!strcmp(args[1], "uevent_devname")) + s->devname_src = DEVNAME_UEVENT_DEVNAME; + else if (!strcmp(args[1], "uevent_devpath")) + s->devname_src = DEVNAME_UEVENT_DEVPATH; + else + parse_error(state, "invalid devname '%s'\n", args[1]); + break; + + case K_dirname: + if (args[1][0] == '/') + s->dirname = args[1]; + else + parse_error(state, "dirname '%s' does not start with '/'\n", + args[1]); + break; + + default: + parse_error(state, "invalid option '%s'\n", args[0]); + } +} + +static void parse_new_section(struct parse_state *state, int kw, + int nargs, char **args) +{ + printf("[ %s %s ]\n", args[0], + nargs > 1 ? args[1] : ""); + + switch(kw) { + case K_subsystem: + state->context = parse_subsystem(state, nargs, args); + if (state->context) { + state->parse_line = parse_line_subsystem; + return; + } + break; + } + state->parse_line = parse_line_no_op; +} + +static void parse_line(struct parse_state *state, char **args, int nargs) +{ + int kw = lookup_keyword(args[0]); + int 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"); + return; + } + + if (kw_is(kw, SECTION)) { + parse_new_section(state, kw, nargs, args); + } else if (kw_is(kw, OPTION)) { + state->parse_line(state, nargs, args); + } else { + parse_line_device(state, nargs, args); + } +} + +static void parse_config(const char *fn, char *s) +{ + struct parse_state state; + char *args[UEVENTD_PARSER_MAXARGS]; + int nargs; + nargs = 0; + state.filename = fn; + state.line = 1; + state.ptr = s; + state.nexttoken = 0; + state.parse_line = parse_line_no_op; + for (;;) { + int token = next_token(&state); + switch (token) { + case T_EOF: + parse_line(&state, args, nargs); + return; + case T_NEWLINE: + if (nargs) { + parse_line(&state, args, nargs); + nargs = 0; + } + state.line++; + break; + case T_TEXT: + if (nargs < UEVENTD_PARSER_MAXARGS) { + args[nargs++] = state.text; + } + break; + } + } +} + +int ueventd_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 void parse_line_device(struct parse_state *state __attribute__((unused)), + int nargs, char **args) +{ + set_device_permission(nargs, args); +} |
