Home | History | Annotate | Download | only in init
      1 /*
      2  * Copyright (C) 2010 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdlib.h>
     19 #include <unistd.h>
     20 #include <fcntl.h>
     21 #include <stdarg.h>
     22 #include <string.h>
     23 #include <stddef.h>
     24 #include <ctype.h>
     25 
     26 #include "init.h"
     27 #include "parser.h"
     28 #include "init_parser.h"
     29 #include "log.h"
     30 #include "property_service.h"
     31 #include "util.h"
     32 
     33 #include <cutils/iosched_policy.h>
     34 #include <cutils/list.h>
     35 
     36 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
     37 #include <sys/_system_properties.h>
     38 
     39 static list_declare(service_list);
     40 static list_declare(action_list);
     41 static list_declare(action_queue);
     42 
     43 static void *parse_service(struct parse_state *state, int nargs, char **args);
     44 static void parse_line_service(struct parse_state *state, int nargs, char **args);
     45 
     46 static void *parse_action(struct parse_state *state, int nargs, char **args);
     47 static void parse_line_action(struct parse_state *state, int nargs, char **args);
     48 
     49 #define SECTION 0x01
     50 #define COMMAND 0x02
     51 #define OPTION  0x04
     52 
     53 #include "keywords.h"
     54 
     55 #define KEYWORD(symbol, flags, nargs, func) \
     56     [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
     57 
     58 struct {
     59     const char *name;
     60     int (*func)(int nargs, char **args);
     61     unsigned char nargs;
     62     unsigned char flags;
     63 } keyword_info[KEYWORD_COUNT] = {
     64     [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
     65 #include "keywords.h"
     66 };
     67 #undef KEYWORD
     68 
     69 #define kw_is(kw, type) (keyword_info[kw].flags & (type))
     70 #define kw_name(kw) (keyword_info[kw].name)
     71 #define kw_func(kw) (keyword_info[kw].func)
     72 #define kw_nargs(kw) (keyword_info[kw].nargs)
     73 
     74 int lookup_keyword(const char *s)
     75 {
     76     switch (*s++) {
     77     case 'c':
     78     if (!strcmp(s, "opy")) return K_copy;
     79         if (!strcmp(s, "apability")) return K_capability;
     80         if (!strcmp(s, "hdir")) return K_chdir;
     81         if (!strcmp(s, "hroot")) return K_chroot;
     82         if (!strcmp(s, "lass")) return K_class;
     83         if (!strcmp(s, "lass_start")) return K_class_start;
     84         if (!strcmp(s, "lass_stop")) return K_class_stop;
     85         if (!strcmp(s, "lass_reset")) return K_class_reset;
     86         if (!strcmp(s, "onsole")) return K_console;
     87         if (!strcmp(s, "hown")) return K_chown;
     88         if (!strcmp(s, "hmod")) return K_chmod;
     89         if (!strcmp(s, "ritical")) return K_critical;
     90         break;
     91     case 'd':
     92         if (!strcmp(s, "isabled")) return K_disabled;
     93         if (!strcmp(s, "omainname")) return K_domainname;
     94         break;
     95     case 'e':
     96         if (!strcmp(s, "xec")) return K_exec;
     97         if (!strcmp(s, "xport")) return K_export;
     98         break;
     99     case 'g':
    100         if (!strcmp(s, "roup")) return K_group;
    101         break;
    102     case 'h':
    103         if (!strcmp(s, "ostname")) return K_hostname;
    104         break;
    105     case 'i':
    106         if (!strcmp(s, "oprio")) return K_ioprio;
    107         if (!strcmp(s, "fup")) return K_ifup;
    108         if (!strcmp(s, "nsmod")) return K_insmod;
    109         if (!strcmp(s, "mport")) return K_import;
    110         break;
    111     case 'k':
    112         if (!strcmp(s, "eycodes")) return K_keycodes;
    113         break;
    114     case 'l':
    115         if (!strcmp(s, "oglevel")) return K_loglevel;
    116         if (!strcmp(s, "oad_persist_props")) return K_load_persist_props;
    117         break;
    118     case 'm':
    119         if (!strcmp(s, "kdir")) return K_mkdir;
    120         if (!strcmp(s, "ount")) return K_mount;
    121         break;
    122     case 'o':
    123         if (!strcmp(s, "n")) return K_on;
    124         if (!strcmp(s, "neshot")) return K_oneshot;
    125         if (!strcmp(s, "nrestart")) return K_onrestart;
    126         break;
    127     case 'r':
    128         if (!strcmp(s, "estart")) return K_restart;
    129         if (!strcmp(s, "mdir")) return K_rmdir;
    130         if (!strcmp(s, "m")) return K_rm;
    131         break;
    132     case 's':
    133         if (!strcmp(s, "ervice")) return K_service;
    134         if (!strcmp(s, "etenv")) return K_setenv;
    135         if (!strcmp(s, "etkey")) return K_setkey;
    136         if (!strcmp(s, "etprop")) return K_setprop;
    137         if (!strcmp(s, "etrlimit")) return K_setrlimit;
    138         if (!strcmp(s, "ocket")) return K_socket;
    139         if (!strcmp(s, "tart")) return K_start;
    140         if (!strcmp(s, "top")) return K_stop;
    141         if (!strcmp(s, "ymlink")) return K_symlink;
    142         if (!strcmp(s, "ysclktz")) return K_sysclktz;
    143         break;
    144     case 't':
    145         if (!strcmp(s, "rigger")) return K_trigger;
    146         break;
    147     case 'u':
    148         if (!strcmp(s, "ser")) return K_user;
    149         break;
    150     case 'w':
    151         if (!strcmp(s, "rite")) return K_write;
    152         if (!strcmp(s, "ait")) return K_wait;
    153         break;
    154     }
    155     return K_UNKNOWN;
    156 }
    157 
    158 void parse_line_no_op(struct parse_state *state, int nargs, char **args)
    159 {
    160 }
    161 
    162 void parse_new_section(struct parse_state *state, int kw,
    163                        int nargs, char **args)
    164 {
    165     printf("[ %s %s ]\n", args[0],
    166            nargs > 1 ? args[1] : "");
    167     switch(kw) {
    168     case K_service:
    169         state->context = parse_service(state, nargs, args);
    170         if (state->context) {
    171             state->parse_line = parse_line_service;
    172             return;
    173         }
    174         break;
    175     case K_on:
    176         state->context = parse_action(state, nargs, args);
    177         if (state->context) {
    178             state->parse_line = parse_line_action;
    179             return;
    180         }
    181         break;
    182     case K_import:
    183         if (nargs != 2) {
    184             ERROR("single argument needed for import\n");
    185         } else {
    186             int ret = init_parse_config_file(args[1]);
    187             if (ret)
    188                 ERROR("could not import file %s\n", args[1]);
    189         }
    190     }
    191     state->parse_line = parse_line_no_op;
    192 }
    193 
    194 static void parse_config(const char *fn, char *s)
    195 {
    196     struct parse_state state;
    197     char *args[INIT_PARSER_MAXARGS];
    198     int nargs;
    199 
    200     nargs = 0;
    201     state.filename = fn;
    202     state.line = 0;
    203     state.ptr = s;
    204     state.nexttoken = 0;
    205     state.parse_line = parse_line_no_op;
    206     for (;;) {
    207         switch (next_token(&state)) {
    208         case T_EOF:
    209             state.parse_line(&state, 0, 0);
    210             return;
    211         case T_NEWLINE:
    212             state.line++;
    213             if (nargs) {
    214                 int kw = lookup_keyword(args[0]);
    215                 if (kw_is(kw, SECTION)) {
    216                     state.parse_line(&state, 0, 0);
    217                     parse_new_section(&state, kw, nargs, args);
    218                 } else {
    219                     state.parse_line(&state, nargs, args);
    220                 }
    221                 nargs = 0;
    222             }
    223             break;
    224         case T_TEXT:
    225             if (nargs < INIT_PARSER_MAXARGS) {
    226                 args[nargs++] = state.text;
    227             }
    228             break;
    229         }
    230     }
    231 }
    232 
    233 int init_parse_config_file(const char *fn)
    234 {
    235     char *data;
    236     data = read_file(fn, 0);
    237     if (!data) return -1;
    238 
    239     parse_config(fn, data);
    240     DUMP();
    241     return 0;
    242 }
    243 
    244 static int valid_name(const char *name)
    245 {
    246     if (strlen(name) > 16) {
    247         return 0;
    248     }
    249     while (*name) {
    250         if (!isalnum(*name) && (*name != '_') && (*name != '-')) {
    251             return 0;
    252         }
    253         name++;
    254     }
    255     return 1;
    256 }
    257 
    258 struct service *service_find_by_name(const char *name)
    259 {
    260     struct listnode *node;
    261     struct service *svc;
    262     list_for_each(node, &service_list) {
    263         svc = node_to_item(node, struct service, slist);
    264         if (!strcmp(svc->name, name)) {
    265             return svc;
    266         }
    267     }
    268     return 0;
    269 }
    270 
    271 struct service *service_find_by_pid(pid_t pid)
    272 {
    273     struct listnode *node;
    274     struct service *svc;
    275     list_for_each(node, &service_list) {
    276         svc = node_to_item(node, struct service, slist);
    277         if (svc->pid == pid) {
    278             return svc;
    279         }
    280     }
    281     return 0;
    282 }
    283 
    284 struct service *service_find_by_keychord(int keychord_id)
    285 {
    286     struct listnode *node;
    287     struct service *svc;
    288     list_for_each(node, &service_list) {
    289         svc = node_to_item(node, struct service, slist);
    290         if (svc->keychord_id == keychord_id) {
    291             return svc;
    292         }
    293     }
    294     return 0;
    295 }
    296 
    297 void service_for_each(void (*func)(struct service *svc))
    298 {
    299     struct listnode *node;
    300     struct service *svc;
    301     list_for_each(node, &service_list) {
    302         svc = node_to_item(node, struct service, slist);
    303         func(svc);
    304     }
    305 }
    306 
    307 void service_for_each_class(const char *classname,
    308                             void (*func)(struct service *svc))
    309 {
    310     struct listnode *node;
    311     struct service *svc;
    312     list_for_each(node, &service_list) {
    313         svc = node_to_item(node, struct service, slist);
    314         if (!strcmp(svc->classname, classname)) {
    315             func(svc);
    316         }
    317     }
    318 }
    319 
    320 void service_for_each_flags(unsigned matchflags,
    321                             void (*func)(struct service *svc))
    322 {
    323     struct listnode *node;
    324     struct service *svc;
    325     list_for_each(node, &service_list) {
    326         svc = node_to_item(node, struct service, slist);
    327         if (svc->flags & matchflags) {
    328             func(svc);
    329         }
    330     }
    331 }
    332 
    333 void action_for_each_trigger(const char *trigger,
    334                              void (*func)(struct action *act))
    335 {
    336     struct listnode *node;
    337     struct action *act;
    338     list_for_each(node, &action_list) {
    339         act = node_to_item(node, struct action, alist);
    340         if (!strcmp(act->name, trigger)) {
    341             func(act);
    342         }
    343     }
    344 }
    345 
    346 void queue_property_triggers(const char *name, const char *value)
    347 {
    348     struct listnode *node;
    349     struct action *act;
    350     list_for_each(node, &action_list) {
    351         act = node_to_item(node, struct action, alist);
    352         if (!strncmp(act->name, "property:", strlen("property:"))) {
    353             const char *test = act->name + strlen("property:");
    354             int name_length = strlen(name);
    355 
    356             if (!strncmp(name, test, name_length) &&
    357                     test[name_length] == '=' &&
    358                     (!strcmp(test + name_length + 1, value) ||
    359                      !strcmp(test + name_length + 1, "*"))) {
    360                 action_add_queue_tail(act);
    361             }
    362         }
    363     }
    364 }
    365 
    366 void queue_all_property_triggers()
    367 {
    368     struct listnode *node;
    369     struct action *act;
    370     list_for_each(node, &action_list) {
    371         act = node_to_item(node, struct action, alist);
    372         if (!strncmp(act->name, "property:", strlen("property:"))) {
    373             /* parse property name and value
    374                syntax is property:<name>=<value> */
    375             const char* name = act->name + strlen("property:");
    376             const char* equals = strchr(name, '=');
    377             if (equals) {
    378                 char prop_name[PROP_NAME_MAX + 1];
    379                 const char* value;
    380                 int length = equals - name;
    381                 if (length > PROP_NAME_MAX) {
    382                     ERROR("property name too long in trigger %s", act->name);
    383                 } else {
    384                     memcpy(prop_name, name, length);
    385                     prop_name[length] = 0;
    386 
    387                     /* does the property exist, and match the trigger value? */
    388                     value = property_get(prop_name);
    389                     if (value && (!strcmp(equals + 1, value) ||
    390                                   !strcmp(equals + 1, "*"))) {
    391                         action_add_queue_tail(act);
    392                     }
    393                 }
    394             }
    395         }
    396     }
    397 }
    398 
    399 void queue_builtin_action(int (*func)(int nargs, char **args), char *name)
    400 {
    401     struct action *act;
    402     struct command *cmd;
    403 
    404     act = calloc(1, sizeof(*act));
    405     act->name = name;
    406     list_init(&act->commands);
    407 
    408     cmd = calloc(1, sizeof(*cmd));
    409     cmd->func = func;
    410     cmd->args[0] = name;
    411     list_add_tail(&act->commands, &cmd->clist);
    412 
    413     list_add_tail(&action_list, &act->alist);
    414     action_add_queue_tail(act);
    415 }
    416 
    417 void action_add_queue_tail(struct action *act)
    418 {
    419     list_add_tail(&action_queue, &act->qlist);
    420 }
    421 
    422 struct action *action_remove_queue_head(void)
    423 {
    424     if (list_empty(&action_queue)) {
    425         return 0;
    426     } else {
    427         struct listnode *node = list_head(&action_queue);
    428         struct action *act = node_to_item(node, struct action, qlist);
    429         list_remove(node);
    430         return act;
    431     }
    432 }
    433 
    434 int action_queue_empty()
    435 {
    436     return list_empty(&action_queue);
    437 }
    438 
    439 static void *parse_service(struct parse_state *state, int nargs, char **args)
    440 {
    441     struct service *svc;
    442     if (nargs < 3) {
    443         parse_error(state, "services must have a name and a program\n");
    444         return 0;
    445     }
    446     if (!valid_name(args[1])) {
    447         parse_error(state, "invalid service name '%s'\n", args[1]);
    448         return 0;
    449     }
    450 
    451     svc = service_find_by_name(args[1]);
    452     if (svc) {
    453         parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);
    454         return 0;
    455     }
    456 
    457     nargs -= 2;
    458     svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
    459     if (!svc) {
    460         parse_error(state, "out of memory\n");
    461         return 0;
    462     }
    463     svc->name = args[1];
    464     svc->classname = "default";
    465     memcpy(svc->args, args + 2, sizeof(char*) * nargs);
    466     svc->args[nargs] = 0;
    467     svc->nargs = nargs;
    468     svc->onrestart.name = "onrestart";
    469     list_init(&svc->onrestart.commands);
    470     list_add_tail(&service_list, &svc->slist);
    471     return svc;
    472 }
    473 
    474 static void parse_line_service(struct parse_state *state, int nargs, char **args)
    475 {
    476     struct service *svc = state->context;
    477     struct command *cmd;
    478     int i, kw, kw_nargs;
    479 
    480     if (nargs == 0) {
    481         return;
    482     }
    483 
    484     svc->ioprio_class = IoSchedClass_NONE;
    485 
    486     kw = lookup_keyword(args[0]);
    487     switch (kw) {
    488     case K_capability:
    489         break;
    490     case K_class:
    491         if (nargs != 2) {
    492             parse_error(state, "class option requires a classname\n");
    493         } else {
    494             svc->classname = args[1];
    495         }
    496         break;
    497     case K_console:
    498         svc->flags |= SVC_CONSOLE;
    499         break;
    500     case K_disabled:
    501         svc->flags |= SVC_DISABLED;
    502         svc->flags |= SVC_RC_DISABLED;
    503         break;
    504     case K_ioprio:
    505         if (nargs != 3) {
    506             parse_error(state, "ioprio optin usage: ioprio <rt|be|idle> <ioprio 0-7>\n");
    507         } else {
    508             svc->ioprio_pri = strtoul(args[2], 0, 8);
    509 
    510             if (svc->ioprio_pri < 0 || svc->ioprio_pri > 7) {
    511                 parse_error(state, "priority value must be range 0 - 7\n");
    512                 break;
    513             }
    514 
    515             if (!strcmp(args[1], "rt")) {
    516                 svc->ioprio_class = IoSchedClass_RT;
    517             } else if (!strcmp(args[1], "be")) {
    518                 svc->ioprio_class = IoSchedClass_BE;
    519             } else if (!strcmp(args[1], "idle")) {
    520                 svc->ioprio_class = IoSchedClass_IDLE;
    521             } else {
    522                 parse_error(state, "ioprio option usage: ioprio <rt|be|idle> <0-7>\n");
    523             }
    524         }
    525         break;
    526     case K_group:
    527         if (nargs < 2) {
    528             parse_error(state, "group option requires a group id\n");
    529         } else if (nargs > NR_SVC_SUPP_GIDS + 2) {
    530             parse_error(state, "group option accepts at most %d supp. groups\n",
    531                         NR_SVC_SUPP_GIDS);
    532         } else {
    533             int n;
    534             svc->gid = decode_uid(args[1]);
    535             for (n = 2; n < nargs; n++) {
    536                 svc->supp_gids[n-2] = decode_uid(args[n]);
    537             }
    538             svc->nr_supp_gids = n - 2;
    539         }
    540         break;
    541     case K_keycodes:
    542         if (nargs < 2) {
    543             parse_error(state, "keycodes option requires atleast one keycode\n");
    544         } else {
    545             svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0]));
    546             if (!svc->keycodes) {
    547                 parse_error(state, "could not allocate keycodes\n");
    548             } else {
    549                 svc->nkeycodes = nargs - 1;
    550                 for (i = 1; i < nargs; i++) {
    551                     svc->keycodes[i - 1] = atoi(args[i]);
    552                 }
    553             }
    554         }
    555         break;
    556     case K_oneshot:
    557         svc->flags |= SVC_ONESHOT;
    558         break;
    559     case K_onrestart:
    560         nargs--;
    561         args++;
    562         kw = lookup_keyword(args[0]);
    563         if (!kw_is(kw, COMMAND)) {
    564             parse_error(state, "invalid command '%s'\n", args[0]);
    565             break;
    566         }
    567         kw_nargs = kw_nargs(kw);
    568         if (nargs < kw_nargs) {
    569             parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,
    570                 kw_nargs > 2 ? "arguments" : "argument");
    571             break;
    572         }
    573 
    574         cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
    575         cmd->func = kw_func(kw);
    576         cmd->nargs = nargs;
    577         memcpy(cmd->args, args, sizeof(char*) * nargs);
    578         list_add_tail(&svc->onrestart.commands, &cmd->clist);
    579         break;
    580     case K_critical:
    581         svc->flags |= SVC_CRITICAL;
    582         break;
    583     case K_setenv: { /* name value */
    584         struct svcenvinfo *ei;
    585         if (nargs < 2) {
    586             parse_error(state, "setenv option requires name and value arguments\n");
    587             break;
    588         }
    589         ei = calloc(1, sizeof(*ei));
    590         if (!ei) {
    591             parse_error(state, "out of memory\n");
    592             break;
    593         }
    594         ei->name = args[1];
    595         ei->value = args[2];
    596         ei->next = svc->envvars;
    597         svc->envvars = ei;
    598         break;
    599     }
    600     case K_socket: {/* name type perm [ uid gid ] */
    601         struct socketinfo *si;
    602         if (nargs < 4) {
    603             parse_error(state, "socket option requires name, type, perm arguments\n");
    604             break;
    605         }
    606         if (strcmp(args[2],"dgram") && strcmp(args[2],"stream")
    607                 && strcmp(args[2],"seqpacket")) {
    608             parse_error(state, "socket type must be 'dgram', 'stream' or 'seqpacket'\n");
    609             break;
    610         }
    611         si = calloc(1, sizeof(*si));
    612         if (!si) {
    613             parse_error(state, "out of memory\n");
    614             break;
    615         }
    616         si->name = args[1];
    617         si->type = args[2];
    618         si->perm = strtoul(args[3], 0, 8);
    619         if (nargs > 4)
    620             si->uid = decode_uid(args[4]);
    621         if (nargs > 5)
    622             si->gid = decode_uid(args[5]);
    623         si->next = svc->sockets;
    624         svc->sockets = si;
    625         break;
    626     }
    627     case K_user:
    628         if (nargs != 2) {
    629             parse_error(state, "user option requires a user id\n");
    630         } else {
    631             svc->uid = decode_uid(args[1]);
    632         }
    633         break;
    634     default:
    635         parse_error(state, "invalid option '%s'\n", args[0]);
    636     }
    637 }
    638 
    639 static void *parse_action(struct parse_state *state, int nargs, char **args)
    640 {
    641     struct action *act;
    642     if (nargs < 2) {
    643         parse_error(state, "actions must have a trigger\n");
    644         return 0;
    645     }
    646     if (nargs > 2) {
    647         parse_error(state, "actions may not have extra parameters\n");
    648         return 0;
    649     }
    650     act = calloc(1, sizeof(*act));
    651     act->name = args[1];
    652     list_init(&act->commands);
    653     list_add_tail(&action_list, &act->alist);
    654         /* XXX add to hash */
    655     return act;
    656 }
    657 
    658 static void parse_line_action(struct parse_state* state, int nargs, char **args)
    659 {
    660     struct command *cmd;
    661     struct action *act = state->context;
    662     int (*func)(int nargs, char **args);
    663     int kw, n;
    664 
    665     if (nargs == 0) {
    666         return;
    667     }
    668 
    669     kw = lookup_keyword(args[0]);
    670     if (!kw_is(kw, COMMAND)) {
    671         parse_error(state, "invalid command '%s'\n", args[0]);
    672         return;
    673     }
    674 
    675     n = kw_nargs(kw);
    676     if (nargs < n) {
    677         parse_error(state, "%s requires %d %s\n", args[0], n - 1,
    678             n > 2 ? "arguments" : "argument");
    679         return;
    680     }
    681     cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
    682     cmd->func = kw_func(kw);
    683     cmd->nargs = nargs;
    684     memcpy(cmd->args, args, sizeof(char*) * nargs);
    685     list_add_tail(&act->commands, &cmd->clist);
    686 }
    687