init.c revision 3899e9fc01cf608f19f716749c54cc5c4d17e766
14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * you may not use this file except in compliance with the License.
64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * You may obtain a copy of the License at
74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * See the License for the specific language governing permissions and
144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * limitations under the License.
154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdio.h>
184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdlib.h>
194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <string.h>
204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <unistd.h>
214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <fcntl.h>
224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <ctype.h>
234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <signal.h>
244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/wait.h>
254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/mount.h>
264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/stat.h>
274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/poll.h>
284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <errno.h>
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdarg.h>
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <mtd/mtd-user.h>
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/types.h>
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/socket.h>
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/un.h>
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/sockets.h>
364e221f0077373b37ca70e862eface2987557295bSan Mehat#include <cutils/iosched_policy.h>
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <termios.h>
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/system_properties.h>
404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "devices.h"
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "init.h"
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "property_service.h"
4435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project#include "bootchart.h"
459c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Cross#include "signal_handler.h"
46a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include "keychords.h"
47ca7648ddfb46347c60014a849b0150a74df4e1d2Colin Cross#include "parser.h"
483899e9fc01cf608f19f716749c54cc5c4d17e766Colin Cross#include "util.h"
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int property_triggers_enabled = 0;
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int   bootchart_count;
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char console[32];
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char serialno[32];
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootmode[32];
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char baseband[32];
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char carrier[32];
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootloader[32];
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char hardware[32];
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic unsigned revision = 0;
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char qemu[32];
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
669c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Crossvoid notify_service_state(const char *name, const char *state)
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char pname[PROP_NAME_MAX];
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int len = strlen(name);
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((len + 10) > PROP_NAME_MAX)
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(pname, sizeof(pname), "init.svc.%s", name);
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set(pname, state);
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int have_console;
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char *console_name = "/dev/console";
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t process_needs_restart;
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic const char *ENV[32];
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* add_environment - add "key=value" to the current environment */
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint add_environment(const char *key, const char *val)
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < 31; n++) {
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!ENV[n]) {
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            size_t len = strlen(key) + strlen(val) + 2;
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *entry = malloc(len);
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            snprintf(entry, len, "%s=%s", key, val);
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ENV[n] = entry;
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return 0;
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 1;
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void zap_stdio(void)
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/dev/null", O_RDWR);
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void open_console()
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((fd = open(console_name, O_RDWR)) < 0) {
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open("/dev/null", O_RDWR);
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void publish_socket(const char *name, int fd)
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char val[64];
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            name,
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(val, sizeof(val), "%d", fd);
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    add_environment(key, val);
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we don't close-on-exec */
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fcntl(fd, F_SETFD, 0);
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
137f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehatvoid service_start(struct service *svc, const char *dynamic_args)
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct stat s;
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int needs_console;
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* starting a service removes it from the disabled
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state and immediately takes it out of the restarting
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state if it was in there
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = 0;
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* running processes require no additional work -- if
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they're in the process of exiting, we've ensured
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that they will immediately restart on exit, unless
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they are ONESHOT
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_RUNNING) {
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (needs_console && (!have_console)) {
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("service '%s' requires console\n", svc->name);
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (stat(svc->args[0], &s) != 0) {
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
173f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
174d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
175d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat               svc->args[0]);
176f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc->flags |= SVC_DISABLED;
177f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        return;
178f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
179f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("starting '%s'\n", svc->name);
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid = fork();
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid == 0) {
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct socketinfo *si;
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct svcenvinfo *ei;
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[32];
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int fd, sz;
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        get_property_workspace(&fd, &sz);
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        sprintf(tmp, "%d,%d", dup(fd), sz);
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (ei = svc->envvars; ei; ei = ei->next)
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            add_environment(ei->name, ei->value);
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = create_socket(si->name,
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  !strcmp(si->type, "dgram") ?
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  SOCK_DGRAM : SOCK_STREAM,
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  si->perm, si->uid, si->gid);
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (s >= 0) {
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                publish_socket(si->name, s);
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2074e221f0077373b37ca70e862eface2987557295bSan Mehat        if (svc->ioprio_class != IoSchedClass_NONE) {
2084e221f0077373b37ca70e862eface2987557295bSan Mehat            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
2094e221f0077373b37ca70e862eface2987557295bSan Mehat                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
2104e221f0077373b37ca70e862eface2987557295bSan Mehat                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
2114e221f0077373b37ca70e862eface2987557295bSan Mehat            }
2124e221f0077373b37ca70e862eface2987557295bSan Mehat        }
2134e221f0077373b37ca70e862eface2987557295bSan Mehat
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (needs_console) {
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setsid();
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            open_console();
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            zap_stdio();
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; svc->args[n]; n++) {
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("args[%d] = '%s'\n", n, svc->args[n]);
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; ENV[n]; n++) {
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("env[%d] = '%s'\n", n, ENV[n]);
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        setpgid(0, getpid());
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2325ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* as requested, set our gid, supplemental gids, and uid */
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->gid) {
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgid(svc->gid);
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->nr_supp_gids) {
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgroups(svc->nr_supp_gids, svc->supp_gids);
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->uid) {
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setuid(svc->uid);
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2438ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        if (!dynamic_args) {
2448ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
2458ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
2468ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            }
2478ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        } else {
248f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *arg_ptrs[SVC_MAXARGS+1];
249d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            int arg_idx = svc->nargs;
250f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *tmp = strdup(dynamic_args);
251d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *next = tmp;
252d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *bword;
253f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
254f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            /* Copy the static arguments */
255d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
256f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
257d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            while((bword = strsep(&next, " "))) {
258d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                arg_ptrs[arg_idx++] = bword;
259d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                if (arg_idx == SVC_MAXARGS)
260f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat                    break;
261f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            }
262f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            arg_ptrs[arg_idx] = '\0';
263f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
264165de92bf1bca1648b4df3047a8f274e0aff4ca9Ivan Djelic        }
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        _exit(127);
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid < 0) {
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("failed to start '%s'\n", svc->name);
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->pid = 0;
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = gettime();
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = pid;
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RUNNING;
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "running");
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_stop(struct service *svc)
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* we are no longer running, nor should we
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * attempt to restart
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* if the service has not yet started, prevent
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * it from auto-starting with its class
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_DISABLED;
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->pid) {
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("service '%s' is being killed\n", svc->name);
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-svc->pid, SIGTERM);
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopping");
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid property_changed(const char *name, const char *value)
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (property_triggers_enabled) {
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        queue_property_triggers(name, value);
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_service_if_needed(struct service *svc)
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t next_start_time = svc->time_started + 5;
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (next_start_time <= gettime()) {
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags &= (~SVC_RESTARTING);
316f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, NULL);
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((next_start_time < process_needs_restart) ||
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (process_needs_restart == 0)) {
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        process_needs_restart = next_start_time;
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_processes()
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    process_needs_restart = 0;
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    service_for_each_flags(SVC_RESTARTING,
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           restart_service_if_needed);
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_start(const char *name)
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
335f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    struct service *svc;
336f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *tmp = NULL;
337f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *args = NULL;
338f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
339f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (!strchr(name, ':'))
340f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(name);
341f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    else {
342f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        tmp = strdup(name);
343f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args = strchr(tmp, ':');
344f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        *args = '\0';
345f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args++;
346f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
347f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(tmp);
348f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
351f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, args);
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n", name);
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
355f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (tmp)
356f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        free(tmp);
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_stop(const char *name)
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_stop(svc);
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
366770354d7e6cd471daed426fcf04bf7246e7cb18bDima Zavin        ERROR("no such service '%s'\n", name);
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid handle_control_message(const char *msg, const char *arg)
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(msg,"start")) {
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_start(arg);
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (!strcmp(msg,"stop")) {
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_stop(arg);
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("unknown control msg '%s'\n", msg);
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_nv(char *name, int in_qemu)
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *value = strchr(name, '=');
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (value == 0) return;
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *value++ = 0;
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (*name == 0) return;
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!in_qemu)
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* on a real device, white-list the kernel options */
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name,"qemu")) {
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(qemu, value, sizeof(qemu));
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.console")) {
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(console, value, sizeof(console));
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.mode")) {
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootmode, value, sizeof(bootmode));
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.serialno")) {
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(serialno, value, sizeof(serialno));
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.baseband")) {
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(baseband, value, sizeof(baseband));
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.carrier")) {
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(carrier, value, sizeof(carrier));
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.bootloader")) {
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootloader, value, sizeof(bootloader));
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.hardware")) {
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(hardware, value, sizeof(hardware));
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            qemu_cmdline(name, value);
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* in the emulator, export any kernel option with the
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * ro.kernel. prefix */
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char  buff[32];
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (len < (int)sizeof(buff)) {
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            property_set( buff, value );
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_cmdline(int in_qemu)
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char cmdline[1024];
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ptr;
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cmdline", O_RDONLY);
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0) {
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int n = read(fd, cmdline, 1023);
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n < 0) n = 0;
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* get rid of trailing newline, it happens */
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n > 0 && cmdline[n-1] == '\n') n--;
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[n] = 0;
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        close(fd);
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[0] = 0;
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptr = cmdline;
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (ptr && *ptr) {
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *x = strchr(ptr, ' ');
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x != 0) *x++ = 0;
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_nv(ptr, in_qemu);
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ptr = x;
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* don't expose the raw commandline to nonpriv processes */
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    chmod("/proc/cmdline", 0440);
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void get_hardware_name(void)
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char data[1024];
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd, n;
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *x, *hw, *rev;
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Hardware string was provided on kernel command line */
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hardware[0])
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cpuinfo", O_RDONLY);
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0) return;
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    n = read(fd, data, 1023);
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (n < 0) return;
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    data[n] = 0;
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    hw = strstr(data, "\nHardware");
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    rev = strstr(data, "\nRevision");
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hw) {
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(hw, ": ");
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            x += 2;
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            n = 0;
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (*x && !isspace(*x)) {
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                hardware[n++] = tolower(*x);
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                x++;
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (n == 31) break;
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            hardware[n] = 0;
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (rev) {
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(rev, ": ");
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            revision = strtoul(x + 2, 0, 16);
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
49711e1c42df69b15c938aa1b7570e4370e6ab15a86Jay Freeman (saurik)void drain_action_queue(void)
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct action *act;
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ((act = action_remove_queue_head())) {
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        INFO("processing action %p (%s)\n", act, act->name);
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        list_for_each(node, &act->commands) {
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cmd = node_to_item(node, struct command, clist);
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ret = cmd->func(cmd->nargs, cmd->args);
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("command '%s' r=%d\n", cmd->args[0], ret);
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid open_devnull_stdio(void)
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static const char *name = "/dev/__null__";
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open(name, O_RDWR);
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(name);
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (fd >= 0) {
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 0);
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 1);
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 2);
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (fd > 2) {
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                close(fd);
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    exit(1);
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint main(int argc, char **argv)
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd_count;
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int s[2];
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct sigaction act;
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char tmp[PROP_VALUE_MAX];
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct pollfd ufds[4];
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *tmpdev;
5445ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    char* debuggable;
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* clear the umask */
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    umask(0);
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* Get the basic filesystem setup we need put
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * together in the initramdisk on / and then we'll
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * let the rc file figure out the rest.
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev", 0755);
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/proc", 0755);
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/sys", 0755);
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/pts", 0755);
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/socket", 0755);
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("devpts", "/dev/pts", "devpts", 0, NULL);
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("proc", "/proc", "proc", 0, NULL);
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("sysfs", "/sys", "sysfs", 0, NULL);
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* We must have some place other than / to create the
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * device nodes for kmsg and null, otherwise we won't
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * be able to remount / read-only later on.
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * Now that tmpfs is mounted on /dev, we can actually
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * talk to the outside world.
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    open_devnull_stdio();
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    log_init();
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("reading config file\n");
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file("/init.rc");
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* pull the kernel commandline and ramdisk properties file in */
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    qemu_init();
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    import_kernel_cmdline(0);
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    get_hardware_name();
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file(tmp);
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-init", action_add_queue_tail);
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("device init\n");
5880dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross    device_init();
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_init();
5915ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
5925ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    // only listen for keychords if ro.debuggable is true
593a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    keychord_init();
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (console[0]) {
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        console_name = strdup(tmp);
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open(console_name, O_RDWR);
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0)
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        have_console = 1;
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if( load_565rle_image(INIT_IMAGE_FILE) ) {
6065ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/tty0", O_WRONLY);
6075ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd >= 0) {
6085ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        const char *msg;
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            msg = "\n"
6105ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6115ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6125ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6135ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6145ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6155ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"  // console is 40 cols x 30 lines
6165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6185ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6225ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
6235ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "             A N D R O I D ";
6245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        write(fd, msg, strlen(msg));
6255ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
6265ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (qemu[0])
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_cmdline(1);
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(bootmode,"factory"))
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "1");
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (!strcmp(bootmode,"factory2"))
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "2");
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "0");
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.serialno", serialno[0] ? serialno : "");
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.hardware", hardware);
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.revision", tmp);
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* execute all the boot actions to get us started */
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("init", action_add_queue_tail);
65131712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("early-fs", action_add_queue_tail);
65231712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("fs", action_add_queue_tail);
65331712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("post-fs", action_add_queue_tail);
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* read any property files on system or data and
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * fire up the property service.  This must happen
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * after the ro.foo properties are set above so
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that /data/local.prop cannot interfere with them.
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
661d11beb2b1516144327c3f730f75e6b4bc65f1374Colin Cross    start_property_service();
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6639c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Cross    signal_init();
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we actually have all the pieces we need */
6660dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross    if ((get_device_fd() < 0) ||
667d11beb2b1516144327c3f730f75e6b4bc65f1374Colin Cross        (get_property_set_fd() < 0) ||
6689c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Cross        (get_signal_fd() < 0)) {
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("init startup failure\n");
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 1;
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* execute all the boot actions to get us started */
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-boot", action_add_queue_tail);
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("boot", action_add_queue_tail);
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* run all property triggers based on current state of the properties */
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    queue_all_property_triggers();
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* enable property triggers */
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_triggers_enabled = 1;
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6850dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross    ufds[0].fd = get_device_fd();
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].events = POLLIN;
687d11beb2b1516144327c3f730f75e6b4bc65f1374Colin Cross    ufds[1].fd = get_property_set_fd();
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].events = POLLIN;
6899c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Cross    ufds[2].fd = get_signal_fd();
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].events = POLLIN;
6915ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd_count = 3;
6925ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
693a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (get_keychord_fd() > 0) {
694a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        ufds[3].fd = get_keychord_fd();
6955ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = POLLIN;
6965ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd_count++;
6975ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    } else {
6985ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = 0;
6995ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].revents = 0;
7005ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
70335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    bootchart_count = bootchart_init();
70435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (bootchart_count < 0) {
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("bootcharting init failure\n");
70635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (bootchart_count > 0) {
70735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
70835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
70935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting ignored\n");
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for(;;) {
7145ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        int nr, i, timeout = -1;
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < fd_count; i++)
7175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ufds[i].revents = 0;
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        restart_processes();
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (process_needs_restart) {
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            timeout = (process_needs_restart - gettime()) * 1000;
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0)
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = 0;
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bootchart_count > 0) {
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = BOOTCHART_POLLING_MS;
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (bootchart_step() < 0 || --bootchart_count == 0) {
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_finish();
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_count = 0;
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
7385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        nr = poll(ufds, fd_count, timeout);
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (nr <= 0)
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[2].revents == POLLIN) {
7439c5366ba55b1553b2d66f48e3d14fbd274a2944dColin Cross            handle_signal();
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[0].revents == POLLIN)
7480dd7ca6e87abb689700c5e3a816a949b03b1154bColin Cross            handle_device_fd();
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[1].revents == POLLIN)
751d11beb2b1516144327c3f730f75e6b4bc65f1374Colin Cross            handle_property_set_fd();
7525ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (ufds[3].revents == POLLIN)
753a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            handle_keychord();
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
758