144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross/*
244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * Copyright (C) 2010 The Android Open Source Project
344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross *
444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * Licensed under the Apache License, Version 2.0 (the "License");
544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * you may not use this file except in compliance with the License.
644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * You may obtain a copy of the License at
744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross *
844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross *      http://www.apache.org/licenses/LICENSE-2.0
944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross *
1044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * Unless required by applicable law or agreed to in writing, software
1144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * distributed under the License is distributed on an "AS IS" BASIS,
1244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * See the License for the specific language governing permissions and
1444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross * limitations under the License.
1544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross */
1644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
173312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include <ctype.h>
183312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include <errno.h>
1944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <stdio.h>
2044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <unistd.h>
2144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <stdarg.h>
223312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include <stdlib.h>
2344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include <string.h>
2444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
253312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include "ueventd.h"
2644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include "ueventd_parser.h"
2744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include "parser.h"
2844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include "log.h"
2944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross#include "util.h"
3044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
313312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic list_declare(subsystem_list);
323312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
3344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossstatic void parse_line_device(struct parse_state *state, int nargs, char **args);
3444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
353312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#define SECTION 0x01
363312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#define OPTION  0x02
373312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
383312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include "ueventd_keywords.h"
393312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
403312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#define KEYWORD(symbol, flags, nargs) \
413312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    [ K_##symbol ] = { #symbol, nargs + 1, flags, },
423312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
433312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic struct {
443312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    const char *name;
453312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    unsigned char nargs;
463312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    unsigned char flags;
473312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann} keyword_info[KEYWORD_COUNT] = {
483312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    [ K_UNKNOWN ] = { "unknown", 0, 0 },
493312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#include "ueventd_keywords.h"
503312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann};
513312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#undef KEYWORD
523312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
533312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#define kw_is(kw, type) (keyword_info[kw].flags & (type))
543312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann#define kw_nargs(kw) (keyword_info[kw].nargs)
553312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
563312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic int lookup_keyword(const char *s)
573312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
583312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    switch (*s++) {
593312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    case 'd':
603312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!strcmp(s, "evname")) return K_devname;
613312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!strcmp(s, "irname")) return K_dirname;
623312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        break;
633312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    case 's':
643312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!strcmp(s, "ubsystem")) return K_subsystem;
653312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        break;
663312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
673312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    return K_UNKNOWN;
683312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
693312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
703312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void parse_line_no_op(struct parse_state *state __attribute__((unused)),
713312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        int nargs __attribute__((unused)), char **args  __attribute__((unused)))
723312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
733312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
743312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
753312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic int valid_name(const char *name)
763312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
773312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    while (*name) {
783312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!isalnum(*name) && (*name != '_') && (*name != '-')) {
793312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            return 0;
803312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        }
813312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        name++;
823312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
833312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    return 1;
843312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
853312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
863312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstruct ueventd_subsystem *ueventd_subsystem_find_by_name(const char *name)
873312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
883312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    struct listnode *node;
893312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    struct ueventd_subsystem *s;
903312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
913312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    list_for_each(node, &subsystem_list) {
923312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        s = node_to_item(node, struct ueventd_subsystem, slist);
933312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!strcmp(s->name, name)) {
943312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            return s;
953312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        }
963312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
973312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    return 0;
983312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
993312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1003312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void *parse_subsystem(struct parse_state *state,
1013312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        int nargs __attribute__((unused)), char **args)
1023312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
1033312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    struct ueventd_subsystem *s;
1043312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1053312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (!valid_name(args[1])) {
1063312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_error(state, "invalid subsystem name '%s'\n", args[1]);
1073312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        return 0;
1083312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1093312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1103312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    s = ueventd_subsystem_find_by_name(args[1]);
1113312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (s) {
1123312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_error(state, "ignored duplicate definition of subsystem '%s'\n",
1133312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann                args[1]);
1143312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        return 0;
1153312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1163312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1173312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    s = calloc(1, sizeof(*s));
1183312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (!s) {
1193312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_error(state, "out of memory\n");
1203312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        return 0;
1213312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1223312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    s->name = args[1];
1233312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    s->dirname = "/dev";
1243312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    list_add_tail(&subsystem_list, &s->slist);
1253312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    return s;
1263312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
1273312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1283312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void parse_line_subsystem(struct parse_state *state, int nargs,
1293312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        char **args)
1303312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
1313312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    struct ueventd_subsystem *s = state->context;
1323312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    int kw;
1333312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1343312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (nargs == 0) {
1353312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        return;
1363312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1373312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1383312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    kw = lookup_keyword(args[0]);
1393312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    switch (kw) {
1403312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    case K_devname:
1413312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (!strcmp(args[1], "uevent_devname"))
1423312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            s->devname_src = DEVNAME_UEVENT_DEVNAME;
1433312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        else if (!strcmp(args[1], "uevent_devpath"))
1443312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            s->devname_src = DEVNAME_UEVENT_DEVPATH;
1453312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        else
1463312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            parse_error(state, "invalid devname '%s'\n", args[1]);
1473312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        break;
1483312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1493312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    case K_dirname:
1503312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (args[1][0] == '/')
1513312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            s->dirname = args[1];
1523312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        else
1533312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            parse_error(state, "dirname '%s' does not start with '/'\n",
1543312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann                    args[1]);
1553312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        break;
1563312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1573312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    default:
1583312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_error(state, "invalid option '%s'\n", args[0]);
1593312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1603312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
1613312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1623312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void parse_new_section(struct parse_state *state, int kw,
1633312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann                       int nargs, char **args)
1643312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
1653312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    printf("[ %s %s ]\n", args[0],
1663312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann           nargs > 1 ? args[1] : "");
1673312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1683312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    switch(kw) {
1693312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    case K_subsystem:
1703312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        state->context = parse_subsystem(state, nargs, args);
1713312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        if (state->context) {
1723312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            state->parse_line = parse_line_subsystem;
1733312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            return;
1743312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        }
1753312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        break;
1763312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1773312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    state->parse_line = parse_line_no_op;
1783312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
1793312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1803312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void parse_line(struct parse_state *state, char **args, int nargs)
1813312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann{
1823312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    int kw = lookup_keyword(args[0]);
1833312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    int kw_nargs = kw_nargs(kw);
1843312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1853312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (nargs < kw_nargs) {
1863312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,
1873312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            kw_nargs > 2 ? "arguments" : "argument");
1883312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        return;
1893312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1903312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
1913312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    if (kw_is(kw, SECTION)) {
1923312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_new_section(state, kw, nargs, args);
1933312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    } else if (kw_is(kw, OPTION)) {
1943312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        state->parse_line(state, nargs, args);
1953312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    } else {
1963312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        parse_line_device(state, nargs, args);
1973312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    }
1983312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann}
1993312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann
20044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossstatic void parse_config(const char *fn, char *s)
20144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{
20244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    struct parse_state state;
20344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    char *args[UEVENTD_PARSER_MAXARGS];
20444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    int nargs;
20544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    nargs = 0;
20644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    state.filename = fn;
20744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    state.line = 1;
20844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    state.ptr = s;
20944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    state.nexttoken = 0;
2103312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann    state.parse_line = parse_line_no_op;
21144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    for (;;) {
21244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        int token = next_token(&state);
21344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        switch (token) {
21444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        case T_EOF:
2153312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            parse_line(&state, args, nargs);
21644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            return;
21744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        case T_NEWLINE:
21844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            if (nargs) {
2193312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann                parse_line(&state, args, nargs);
22044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross                nargs = 0;
22144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            }
2223312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann            state.line++;
22344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            break;
22444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        case T_TEXT:
22544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            if (nargs < UEVENTD_PARSER_MAXARGS) {
22644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross                args[nargs++] = state.text;
22744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            }
22844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross            break;
22944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross        }
23044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    }
23144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross}
23244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
23344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Crossint ueventd_parse_config_file(const char *fn)
23444b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{
23544b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    char *data;
23644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    data = read_file(fn, 0);
23744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    if (!data) return -1;
23844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
23944b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    parse_config(fn, data);
24044b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    DUMP();
24144b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    return 0;
24244b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross}
24344b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross
2443312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmannstatic void parse_line_device(struct parse_state *state __attribute__((unused)),
2453312aa8379d877044def52f3b3be5c912a5e61a2Greg Hackmann        int nargs, char **args)
24644b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross{
24744b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross    set_device_permission(nargs, args);
24844b65d047cc39baf30e21bfd8dd438f6bc1f77f5Colin Cross}
249