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     /*
     57      * init sets the umask to 077 for forked processes. We need to
     58      * create files with exact permissions, without modification by
     59      * the umask.
     60      */
     61     umask(000);
     62 
     63     /* Prevent fire-and-forget children from becoming zombies.
     64      * If we should need to wait() for some children in the future
     65      * (as opposed to none right now), double-forking here instead
     66      * of ignoring SIGCHLD may be the better solution.
     67      */
     68     signal(SIGCHLD, SIG_IGN);
     69 
     70     open_devnull_stdio();
     71     klog_init();
     72 
     73     INFO("starting ueventd\n");
     74 
     75     /* Respect hardware passed in through the kernel cmd line. Here we will look
     76      * for androidboot.hardware param in kernel cmdline, and save its value in
     77      * hardware[]. */
     78     import_kernel_cmdline(0, import_kernel_nv);
     79 
     80     get_hardware_name(hardware, &revision);
     81 
     82     ueventd_parse_config_file("/ueventd.rc");
     83 
     84     snprintf(tmp, sizeof(tmp), "/ueventd.%s.rc", hardware);
     85     ueventd_parse_config_file(tmp);
     86 
     87     device_init();
     88 
     89     ufd.events = POLLIN;
     90     ufd.fd = get_device_fd();
     91 
     92     while(1) {
     93         ufd.revents = 0;
     94         nr = poll(&ufd, 1, -1);
     95         if (nr <= 0)
     96             continue;
     97         if (ufd.revents == POLLIN)
     98                handle_device_fd();
     99     }
    100 }
    101 
    102 static int get_android_id(const char *id)
    103 {
    104     unsigned int i;
    105     for (i = 0; i < ARRAY_SIZE(android_ids); i++)
    106         if (!strcmp(id, android_ids[i].name))
    107             return android_ids[i].aid;
    108     return 0;
    109 }
    110 
    111 void set_device_permission(int nargs, char **args)
    112 {
    113     char *name;
    114     char *attr = 0;
    115     mode_t perm;
    116     uid_t uid;
    117     gid_t gid;
    118     int prefix = 0;
    119     char *endptr;
    120     int ret;
    121     char *tmp = 0;
    122 
    123     if (nargs == 0)
    124         return;
    125 
    126     if (args[0][0] == '#')
    127         return;
    128 
    129     name = args[0];
    130 
    131     if (!strncmp(name,"/sys/", 5) && (nargs == 5)) {
    132         INFO("/sys/ rule %s %s\n",args[0],args[1]);
    133         attr = args[1];
    134         args++;
    135         nargs--;
    136     }
    137 
    138     if (nargs != 4) {
    139         ERROR("invalid line ueventd.rc line for '%s'\n", args[0]);
    140         return;
    141     }
    142 
    143     /* If path starts with mtd@ lookup the mount number. */
    144     if (!strncmp(name, "mtd@", 4)) {
    145         int n = mtd_name_to_number(name + 4);
    146         if (n >= 0)
    147             asprintf(&tmp, "/dev/mtd/mtd%d", n);
    148         name = tmp;
    149     } else {
    150         int len = strlen(name);
    151         if (name[len - 1] == '*') {
    152             prefix = 1;
    153             name[len - 1] = '\0';
    154         }
    155     }
    156 
    157     perm = strtol(args[1], &endptr, 8);
    158     if (!endptr || *endptr != '\0') {
    159         ERROR("invalid mode '%s'\n", args[1]);
    160         free(tmp);
    161         return;
    162     }
    163 
    164     ret = get_android_id(args[2]);
    165     if (ret < 0) {
    166         ERROR("invalid uid '%s'\n", args[2]);
    167         free(tmp);
    168         return;
    169     }
    170     uid = ret;
    171 
    172     ret = get_android_id(args[3]);
    173     if (ret < 0) {
    174         ERROR("invalid gid '%s'\n", args[3]);
    175         free(tmp);
    176         return;
    177     }
    178     gid = ret;
    179 
    180     add_dev_perms(name, attr, perm, uid, gid, prefix);
    181     free(tmp);
    182 }
    183