parser.c revision dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0
1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <fcntl.h>
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdarg.h>
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stddef.h>
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <ctype.h>
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "init.h"
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "property_service.h"
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/_system_properties.h>
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic list_declare(service_list);
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic list_declare(action_list);
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic list_declare(action_queue);
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define RAW(x...) log_write(6, x)
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid DUMP(void)
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#if 0
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act;
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct command *cmd;
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node2;
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct socketinfo *si;
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("service %s\n", svc->name);
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("  class '%s'\n", svc->classname);
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("  exec");
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (n = 0; n < svc->nargs; n++) {
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            RAW(" '%s'", svc->args[n]);
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("\n");
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            RAW("  socket %s %s 0%o\n", si->name, si->type, si->perm);
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &action_list) {
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        act = node_to_item(node, struct action, alist);
49dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("on %s\n", act->name);
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_for_each(node2, &act->commands) {
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            cmd = node_to_item(node2, struct command, clist);
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            RAW("  %p", cmd->func);
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (n = 0; n < cmd->nargs; n++) {
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                RAW(" %s", cmd->args[n]);
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            RAW("\n");
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        RAW("\n");
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define MAXARGS 64
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define T_EOF 0
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define T_TEXT 1
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define T_NEWLINE 2
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct parse_state
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *ptr;
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *text;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int line;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int nexttoken;
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void *context;
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    void (*parse_line)(struct parse_state *state, int nargs, char **args);
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *filename;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *parse_service(struct parse_state *state, int nargs, char **args);
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void parse_line_service(struct parse_state *state, int nargs, char **args);
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *parse_action(struct parse_state *state, int nargs, char **args);
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void parse_line_action(struct parse_state *state, int nargs, char **args);
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid parse_error(struct parse_state *state, const char *fmt, ...)
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_list ap;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char buf[128];
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int off;
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(buf, 128, "%s: %d: ", state->filename, state->line);
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buf[127] = 0;
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    off = strlen(buf);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_start(ap, fmt);
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    vsnprintf(buf + off, 128 - off, fmt, ap);
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    va_end(ap);
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    buf[127] = 0;
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ERROR("%s", buf);
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define SECTION 0x01
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define COMMAND 0x02
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define OPTION  0x04
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "keywords.h"
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define KEYWORD(symbol, flags, nargs, func) \
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct {
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *name;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int (*func)(int nargs, char **args);
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned char nargs;
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    unsigned char flags;
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project} keyword_info[KEYWORD_COUNT] = {
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include "keywords.h"
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project};
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#undef KEYWORD
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define kw_is(kw, type) (keyword_info[kw].flags & (type))
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define kw_name(kw) (keyword_info[kw].name)
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define kw_func(kw) (keyword_info[kw].func)
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define kw_nargs(kw) (keyword_info[kw].nargs)
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint lookup_keyword(const char *s)
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch (*s++) {
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'c':
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "apability")) return K_capability;
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "lass")) return K_class;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "lass_start")) return K_class_start;
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "lass_stop")) return K_class_stop;
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "onsole")) return K_console;
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "hown")) return K_chown;
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "hmod")) return K_chmod;
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ritical")) return K_critical;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'd':
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "isabled")) return K_disabled;
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "omainname")) return K_domainname;
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "evice")) return K_device;
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'e':
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "xec")) return K_exec;
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "xport")) return K_export;
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'g':
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "roup")) return K_group;
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'h':
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ostname")) return K_hostname;
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'i':
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "fup")) return K_ifup;
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "nsmod")) return K_insmod;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "mport")) return K_import;
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'k':
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "eycodes")) return K_keycodes;
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'l':
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "oglevel")) return K_loglevel;
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'm':
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "kdir")) return K_mkdir;
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ount")) return K_mount;
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'o':
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "n")) return K_on;
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "neshot")) return K_oneshot;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "nrestart")) return K_onrestart;
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'r':
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "estart")) return K_restart;
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 's':
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ervice")) return K_service;
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "etenv")) return K_setenv;
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "etkey")) return K_setkey;
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "etprop")) return K_setprop;
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "etrlimit")) return K_setrlimit;
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ocket")) return K_socket;
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "tart")) return K_start;
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "top")) return K_stop;
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ymlink")) return K_symlink;
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ysclktz")) return K_sysclktz;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 't':
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "rigger")) return K_trigger;
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'u':
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "ser")) return K_user;
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case 'w':
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(s, "rite")) return K_write;
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return K_UNKNOWN;
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid parse_line_no_op(struct parse_state *state, int nargs, char **args)
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint next_token(struct parse_state *state)
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *x = state->ptr;
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *s;
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (state->nexttoken) {
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int t = state->nexttoken;
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        state->nexttoken = 0;
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return t;
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (;;) {
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch (*x) {
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 0:
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->ptr = x;
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return T_EOF;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\n':
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->line++;
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->ptr = x;
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return T_NEWLINE;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ' ':
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\t':
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\r':
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '#':
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            while (*x && (*x != '\n')) x++;
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->line++;
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->ptr = x;
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return T_NEWLINE;
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto text;
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttextdone:
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state->ptr = x;
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    *s = 0;
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return T_TEXT;
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttext:
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state->text = s = x;
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projecttextresume:
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (;;) {
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch (*x) {
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case 0:
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto textdone;
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case ' ':
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\t':
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\r':
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto textdone;
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\n':
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->nexttoken = T_NEWLINE;
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            goto textdone;
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '"':
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (;;) {
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                switch (*x) {
268dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case 0:
269dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        /* unterminated quoted thing */
270dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    state->ptr = x;
271dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    return T_EOF;
272dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                case '"':
273dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    x++;
274dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    goto textresume;
275dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                default:
276dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    *s++ = *x++;
277dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
278dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
279dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
280dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case '\\':
281dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            x++;
282dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            switch (*x) {
283dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case 0:
284dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                goto textdone;
285dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case 'n':
286dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *s++ = '\n';
287dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
288dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case 'r':
289dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *s++ = '\r';
290dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
291dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case 't':
292dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *s++ = '\t';
293dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
294dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case '\\':
295dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *s++ = '\\';
296dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                break;
297dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case '\r':
298dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* \ <cr> <lf> -> line continuation */
299dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (x[1] != '\n') {
300dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    x++;
301dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    continue;
302dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
303dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            case '\n':
304dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* \ <lf> -> line continuation */
305dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                state->line++;
306dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                x++;
307dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* eat any extra whitespace */
308dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                while((*x == ' ') || (*x == '\t')) x++;
309dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                continue;
310dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            default:
311dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* unknown escape -- just copy */
312dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                *s++ = *x++;
313dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
314dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            continue;
315dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        default:
316dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *s++ = *x++;
317dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
318dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
319dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return T_EOF;
320dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
321dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
322dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid parse_line(int nargs, char **args)
323dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
324dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int n;
325dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int id = lookup_keyword(args[0]);
326dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("%s(%d)", args[0], id);
327dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (n = 1; n < nargs; n++) {
328dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        printf(" '%s'", args[n]);
329dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
330dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("\n");
331dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
332dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
333dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid parse_new_section(struct parse_state *state, int kw,
334dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                       int nargs, char **args)
335dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
336dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    printf("[ %s %s ]\n", args[0],
337dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project           nargs > 1 ? args[1] : "");
338dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch(kw) {
339dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_service:
340dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        state->context = parse_service(state, nargs, args);
341dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (state->context) {
342dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->parse_line = parse_line_service;
343dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
344dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
345dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
346dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_on:
347dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        state->context = parse_action(state, nargs, args);
348dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (state->context) {
349dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state->parse_line = parse_line_action;
350dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
351dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
352dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
353dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
354dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state->parse_line = parse_line_no_op;
355dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
356dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
357dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void parse_config(const char *fn, char *s)
358dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
359dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct parse_state state;
360dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *args[MAXARGS];
361dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int nargs;
362dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
363dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    nargs = 0;
364dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state.filename = fn;
365dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state.line = 1;
366dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state.ptr = s;
367dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state.nexttoken = 0;
368dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    state.parse_line = parse_line_no_op;
369dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (;;) {
370dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        switch (next_token(&state)) {
371dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case T_EOF:
372dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            state.parse_line(&state, 0, 0);
373dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return;
374dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case T_NEWLINE:
375dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (nargs) {
376dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int kw = lookup_keyword(args[0]);
377dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (kw_is(kw, SECTION)) {
378dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    state.parse_line(&state, 0, 0);
379dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    parse_new_section(&state, kw, nargs, args);
380dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
381dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    state.parse_line(&state, nargs, args);
382dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
383dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                nargs = 0;
384dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
385dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
386dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        case T_TEXT:
387dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (nargs < MAXARGS) {
388dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                args[nargs++] = state.text;
389dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
390dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
391dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
392dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
393dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
394dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
395dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint parse_config_file(const char *fn)
396dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
397dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char *data;
398dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    data = read_file(fn, 0);
399dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!data) return -1;
400dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
401dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    parse_config(fn, data);
402dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    DUMP();
403dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
404dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
405dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
406dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int valid_name(const char *name)
407dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
408dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (strlen(name) > 16) {
409dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
410dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
411dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    while (*name) {
412dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!isalnum(*name) && (*name != '_') && (*name != '-')) {
413dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return 0;
414dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
415dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        name++;
416dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
417dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 1;
418dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
419dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
420dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct service *service_find_by_name(const char *name)
421dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
422dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
423dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
424dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
425dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
426dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(svc->name, name)) {
427dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return svc;
428dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
429dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
430dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
431dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
432dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
433dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct service *service_find_by_pid(pid_t pid)
434dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
435dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
436dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
437dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
438dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
439dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (svc->pid == pid) {
440dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return svc;
441dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
442dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
443dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
444dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
445dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
446dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct service *service_find_by_keychord(int keychord_id)
447dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
448dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
449dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
450dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
451dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
452dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (svc->keychord_id == keychord_id) {
453dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return svc;
454dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
455dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
456dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
457dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
458dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
459dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid service_for_each(void (*func)(struct service *svc))
460dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
461dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
462dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
463dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
464dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
465dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        func(svc);
466dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
467dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
468dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
469dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid service_for_each_class(const char *classname,
470dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            void (*func)(struct service *svc))
471dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
472dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
473dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
474dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
475dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
476dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(svc->classname, classname)) {
477dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            func(svc);
478dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
479dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
480dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
481dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
482dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid service_for_each_flags(unsigned matchflags,
483dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                            void (*func)(struct service *svc))
484dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
485dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
486dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
487dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &service_list) {
488dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc = node_to_item(node, struct service, slist);
489dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (svc->flags & matchflags) {
490dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            func(svc);
491dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
492dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
493dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
494dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
495dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid action_for_each_trigger(const char *trigger,
496dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                             void (*func)(struct action *act))
497dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
498dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
499dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act;
500dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &action_list) {
501dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        act = node_to_item(node, struct action, alist);
502dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strcmp(act->name, trigger)) {
503dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            func(act);
504dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
505dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
506dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
507dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
508dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid queue_property_triggers(const char *name, const char *value)
509dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
510dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
511dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act;
512dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &action_list) {
513dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        act = node_to_item(node, struct action, alist);
514dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(act->name, "property:", strlen("property:"))) {
515dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const char *test = act->name + strlen("property:");
516dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int name_length = strlen(name);
517dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
518dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!strncmp(name, test, name_length) &&
519dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    test[name_length] == '=' &&
520dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    !strcmp(test + name_length + 1, value)) {
521dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                action_add_queue_tail(act);
522dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
523dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
524dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
525dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
526dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
527dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid queue_all_property_triggers()
528dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
529dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct listnode *node;
530dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act;
531dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_for_each(node, &action_list) {
532dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        act = node_to_item(node, struct action, alist);
533dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!strncmp(act->name, "property:", strlen("property:"))) {
534dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            /* parse property name and value
535dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project               syntax is property:<name>=<value> */
536dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const char* name = act->name + strlen("property:");
537dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            const char* equals = strchr(name, '=');
538dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (equals) {
539dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                char* prop_name[PROP_NAME_MAX + 1];
540dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                const char* value;
541dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                int length = equals - name;
542dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                if (length > PROP_NAME_MAX) {
543dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    ERROR("property name too long in trigger %s", act->name);
544dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                } else {
545dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    memcpy(prop_name, name, length);
546dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    prop_name[length] = 0;
547dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
548dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    /* does the property exist, and match the trigger value? */
549dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    value = property_get((const char *)&prop_name[0]);
550dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    if (value && !strcmp(equals + 1, value)) {
551dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        action_add_queue_tail(act);
552dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    }
553dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
554dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
555dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
556dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
557dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
558dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
559dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectvoid action_add_queue_tail(struct action *act)
560dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
561dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_add_tail(&action_queue, &act->qlist);
562dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
563dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
564dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstruct action *action_remove_queue_head(void)
565dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
566dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (list_empty(&action_queue)) {
567dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
568dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } else {
569dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct listnode *node = list_head(&action_queue);
570dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct action *act = node_to_item(node, struct action, qlist);
571dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_remove(node);
572dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return act;
573dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
574dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
575dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
576dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *parse_service(struct parse_state *state, int nargs, char **args)
577dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
578dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc;
579dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs < 3) {
580dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "services must have a name and a program\n");
581dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
582dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
583dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!valid_name(args[1])) {
584dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "invalid service name '%s'\n", args[1]);
585dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
586dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
587dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
588dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc = service_find_by_name(args[1]);
589dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (svc) {
590dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);
591dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
592dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
593dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
594dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    nargs -= 2;
595dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
596dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!svc) {
597dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "out of memory\n");
598dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
599dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
600dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc->name = args[1];
601dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc->classname = "default";
602dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(svc->args, args + 2, sizeof(char*) * nargs);
603dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc->args[nargs] = 0;
604dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc->nargs = nargs;
605dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    svc->onrestart.name = "onrestart";
606dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_init(&svc->onrestart.commands);
607dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_add_tail(&service_list, &svc->slist);
608dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return svc;
609dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
610dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
611dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void parse_line_service(struct parse_state *state, int nargs, char **args)
612dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
613dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct service *svc = state->context;
614dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct command *cmd;
615dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i, kw, kw_nargs;
616dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
617dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs == 0) {
618dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
619dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
620dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
621dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kw = lookup_keyword(args[0]);
622dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    switch (kw) {
623dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_capability:
624dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
625dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_class:
626dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs != 2) {
627dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "class option requires a classname\n");
628dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
629dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            svc->classname = args[1];
630dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
631dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
632dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_console:
633dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->flags |= SVC_CONSOLE;
634dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
635dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_disabled:
636dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->flags |= SVC_DISABLED;
637dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
638dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_group:
639dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs < 2) {
640dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "group option requires a group id\n");
641dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else if (nargs > NR_SVC_SUPP_GIDS + 2) {
642dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "group option accepts at most %d supp. groups\n",
643dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                        NR_SVC_SUPP_GIDS);
644dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
645dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            int n;
646dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            svc->gid = decode_uid(args[1]);
647dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            for (n = 2; n < nargs; n++) {
648dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                svc->supp_gids[n-2] = decode_uid(args[n]);
649dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
650dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            svc->nr_supp_gids = n - 2;
651dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
652dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
653dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_keycodes:
654dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs < 2) {
655dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "keycodes option requires atleast one keycode\n");
656dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
657dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0]));
658dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            if (!svc->keycodes) {
659dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                parse_error(state, "could not allocate keycodes\n");
660dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } else {
661dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                svc->nkeycodes = nargs - 1;
662dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                for (i = 1; i < nargs; i++) {
663dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                    svc->keycodes[i - 1] = atoi(args[i]);
664dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                }
665dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            }
666dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
667dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
668dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_oneshot:
669dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->flags |= SVC_ONESHOT;
670dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
671dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_onrestart:
672dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        nargs--;
673dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        args++;
674dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kw = lookup_keyword(args[0]);
675dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!kw_is(kw, COMMAND)) {
676dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "invalid command '%s'\n", args[0]);
677dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
678dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
679dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        kw_nargs = kw_nargs(kw);
680dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs < kw_nargs) {
681dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,
682dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                kw_nargs > 2 ? "arguments" : "argument");
683dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
684dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
685dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
686dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
687dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmd->func = kw_func(kw);
688dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmd->nargs = nargs;
689dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        memcpy(cmd->args, args, sizeof(char*) * nargs);
690dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        list_add_tail(&svc->onrestart.commands, &cmd->clist);
691dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
692dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_critical:
693dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->flags |= SVC_CRITICAL;
694dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
695dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_setenv: { /* name value */
696dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct svcenvinfo *ei;
697dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs < 2) {
698dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "setenv option requires name and value arguments\n");
699dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
700dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
701dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ei = calloc(1, sizeof(*ei));
702dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!ei) {
703dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "out of memory\n");
704dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
705dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
706dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ei->name = args[1];
707dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ei->value = args[2];
708dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ei->next = svc->envvars;
709dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->envvars = ei;
710dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
711dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
712dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_socket: {/* name type perm [ uid gid ] */
713dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        struct socketinfo *si;
714dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs < 4) {
715dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "socket option requires name, type, perm arguments\n");
716dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
717dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
718dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (strcmp(args[2],"dgram") && strcmp(args[2],"stream")) {
719dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "socket type must be 'dgram' or 'stream'\n");
720dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
721dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
722dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        si = calloc(1, sizeof(*si));
723dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (!si) {
724dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "out of memory\n");
725dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            break;
726dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
727dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        si->name = args[1];
728dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        si->type = args[2];
729dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        si->perm = strtoul(args[3], 0, 8);
730dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs > 4)
731dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            si->uid = decode_uid(args[4]);
732dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs > 5)
733dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            si->gid = decode_uid(args[5]);
734dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        si->next = svc->sockets;
735dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        svc->sockets = si;
736dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
737dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
738dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    case K_user:
739dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (nargs != 2) {
740dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            parse_error(state, "user option requires a user id\n");
741dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } else {
742dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            svc->uid = decode_uid(args[1]);
743dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
744dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        break;
745dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    default:
746dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "invalid option '%s'\n", args[0]);
747dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
748dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
749dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
750dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void *parse_action(struct parse_state *state, int nargs, char **args)
751dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
752dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act;
753dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs < 2) {
754dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "actions must have a trigger\n");
755dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
756dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
757dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs > 2) {
758dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "actions may not have extra parameters\n");
759dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return 0;
760dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
761dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    act = calloc(1, sizeof(*act));
762dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    act->name = args[1];
763dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_init(&act->commands);
764dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_add_tail(&action_list, &act->alist);
765dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        /* XXX add to hash */
766dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return act;
767dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
768dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
769dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void parse_line_action(struct parse_state* state, int nargs, char **args)
770dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
771dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct command *cmd;
772dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct action *act = state->context;
773dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int (*func)(int nargs, char **args);
774dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int kw, n;
775dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
776dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs == 0) {
777dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
778dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
779dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
780dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    kw = lookup_keyword(args[0]);
781dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (!kw_is(kw, COMMAND)) {
782dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "invalid command '%s'\n", args[0]);
783dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
784dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
785dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
786dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    n = kw_nargs(kw);
787dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (nargs < n) {
788dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        parse_error(state, "%s requires %d %s\n", args[0], n - 1,
789dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            n > 2 ? "arguments" : "argument");
790dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return;
791dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
792dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
793dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cmd->func = kw_func(kw);
794dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    cmd->nargs = nargs;
795dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(cmd->args, args, sizeof(char*) * nargs);
796dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    list_add_tail(&act->commands, &cmd->clist);
797dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
798