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 <poll.h>
     18 #include <fcntl.h>
     19 #include <string.h>
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include <ctype.h>
     23 #include <signal.h>
     24 
     25 #include <private/android_filesystem_config.h>
     26 
     27 #include "ueventd.h"
     28 #include "log.h"
     29 #include "util.h"
     30 #include "devices.h"
     31 #include "ueventd_parser.h"
     32 
     33 static char hardware[32];
     34 static unsigned revision = 0;
     35 
     36 static void import_kernel_nv(char *name, int in_qemu)
     37 {
     38     if (*name != '\0') {
     39         char *value = strchr(name, '=');
     40         if (value != NULL) {
     41             *value++ = 0;
     42             if (!strcmp(name,"androidboot.hardware"))
     43             {
     44                 strlcpy(hardware, value, sizeof(hardware));
     45             }
     46         }
     47     }
     48 }
     49 
     50 int ueventd_main(int argc, char **argv)
     51 {
     52     struct pollfd ufd;
     53     int nr;
     54     char tmp[32];
     55 
     56         /* Prevent fire-and-forget children from becoming zombies.
     57          * If we should need to wait() for some children in the future
     58          * (as opposed to none right now), double-forking here instead
     59          * of ignoring SIGCHLD may be the better solution.
     60          */
     61     signal(SIGCHLD, SIG_IGN);
     62 
     63     open_devnull_stdio();
     64     klog_init();
     65 
     66     INFO("starting ueventd\n");
     67 
     68     /* Respect hardware passed in through the kernel cmd line. Here we will look
     69      * for androidboot.hardware param in kernel cmdline, and save its value in
     70      * hardware[]. */
     71     import_kernel_cmdline(0, import_kernel_nv);
     72 
     73     get_hardware_name(hardware, &revision);
     74 
     75     ueventd_parse_config_file("/ueventd.rc");
     76 
     77     snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
     78     ueventd_parse_config_file(tmp);
     79 
     80     device_init();
     81 
     82     ufd.events = POLLIN;
     83     ufd.fd = get_device_fd();
     84 
     85     while(1) {
     86         ufd.revents = 0;
     87         nr = poll(&ufd, 1, -1);
     88         if (nr <= 0)
     89             continue;
     90         if (ufd.revents == POLLIN)
     91                handle_device_fd();
     92     }
     93 }
     94 
     95 static int get_android_id(const char *id)
     96 {
     97     unsigned int i;
     98     for (i = 0; i < ARRAY_SIZE(android_ids); i++)
     99         if (!strcmp(id, android_ids[i].name))
    100             return android_ids[i].aid;
    101     return 0;
    102 }
    103 
    104 void set_device_permission(int nargs, char **args)
    105 {
    106     char *name;
    107     char *attr = 0;
    108     mode_t perm;
    109     uid_t uid;
    110     gid_t gid;
    111     int prefix = 0;
    112     char *endptr;
    113     int ret;
    114     char *tmp = 0;
    115 
    116     if (nargs == 0)
    117         return;
    118 
    119     if (args[0][0] == '#')
    120         return;
    121 
    122     name = args[0];
    123 
    124     if (!strncmp(name,"/sys/", 5) && (nargs == 5)) {
    125         INFO("/sys/ rule %s %s\n",args[0],args[1]);
    126         attr = args[1];
    127         args++;
    128         nargs--;
    129     }
    130 
    131     if (nargs != 4) {
    132         ERROR("invalid line ueventd.rc line for '%s'\n", args[0]);
    133         return;
    134     }
    135 
    136     /* If path starts with mtd@ lookup the mount number. */
    137     if (!strncmp(name, "mtd@", 4)) {
    138         int n = mtd_name_to_number(name + 4);
    139         if (n >= 0)
    140             asprintf(&tmp, "/dev/mtd/mtd%d", n);
    141         name = tmp;
    142     } else {
    143         int len = strlen(name);
    144         if (name[len - 1] == '*') {
    145             prefix = 1;
    146             name[len - 1] = '\0';
    147         }
    148     }
    149 
    150     perm = strtol(args[1], &endptr, 8);
    151     if (!endptr || *endptr != '\0') {
    152         ERROR("invalid mode '%s'\n", args[1]);
    153         free(tmp);
    154         return;
    155     }
    156 
    157     ret = get_android_id(args[2]);
    158     if (ret < 0) {
    159         ERROR("invalid uid '%s'\n", args[2]);
    160         free(tmp);
    161         return;
    162     }
    163     uid = ret;
    164 
    165     ret = get_android_id(args[3]);
    166     if (ret < 0) {
    167         ERROR("invalid gid '%s'\n", args[3]);
    168         free(tmp);
    169         return;
    170     }
    171     gid = ret;
    172 
    173     add_dev_perms(name, attr, perm, uid, gid, prefix);
    174     free(tmp);
    175 }
    176