init.c revision 35237d135807af84bf9b0e5b8d7f8633e58db6f5
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 <time.h>
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <errno.h>
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdarg.h>
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <mtd/mtd-user.h>
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/types.h>
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/socket.h>
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/un.h>
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/reboot.h>
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/sockets.h>
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <termios.h>
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <linux/kd.h>
404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/system_properties.h>
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "devices.h"
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "init.h"
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "property_service.h"
4635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project#include "bootchart.h"
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int property_triggers_enabled = 0;
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int   bootchart_count;
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char console[32];
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char serialno[32];
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootmode[32];
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char baseband[32];
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char carrier[32];
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootloader[32];
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char hardware[32];
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic unsigned revision = 0;
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char qemu[32];
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void drain_action_queue(void);
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void 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 Project/*
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * gettime() - returns the time in seconds of the system's monotonic clock or
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * zero on error.
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t gettime(void)
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct timespec ts;
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (ret < 0) {
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ts.tv_sec;
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void publish_socket(const char *name, int fd)
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char val[64];
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            name,
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(val, sizeof(val), "%d", fd);
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    add_environment(key, val);
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we don't close-on-exec */
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fcntl(fd, F_SETFD, 0);
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_start(struct service *svc)
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct stat s;
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int needs_console;
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* starting a service removes it from the disabled
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state and immediately takes it out of the restarting
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state if it was in there
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = 0;
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* running processes require no additional work -- if
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they're in the process of exiting, we've ensured
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that they will immediately restart on exit, unless
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they are ONESHOT
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_RUNNING) {
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (needs_console && (!have_console)) {
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("service '%s' requires console\n", svc->name);
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (stat(svc->args[0], &s) != 0) {
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("starting '%s'\n", svc->name);
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid = fork();
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid == 0) {
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct socketinfo *si;
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct svcenvinfo *ei;
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[32];
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int fd, sz;
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        get_property_workspace(&fd, &sz);
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        sprintf(tmp, "%d,%d", dup(fd), sz);
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (ei = svc->envvars; ei; ei = ei->next)
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            add_environment(ei->name, ei->value);
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = create_socket(si->name,
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  !strcmp(si->type, "dgram") ?
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  SOCK_DGRAM : SOCK_STREAM,
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  si->perm, si->uid, si->gid);
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (s >= 0) {
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                publish_socket(si->name, s);
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (needs_console) {
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setsid();
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            open_console();
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            zap_stdio();
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; svc->args[n]; n++) {
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("args[%d] = '%s'\n", n, svc->args[n]);
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; ENV[n]; n++) {
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("env[%d] = '%s'\n", n, ENV[n]);
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        setpgid(0, getpid());
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	/* as requested, set our gid, supplemental gids, and uid */
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->gid) {
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgid(svc->gid);
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->nr_supp_gids) {
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgroups(svc->nr_supp_gids, svc->supp_gids);
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->uid) {
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setuid(svc->uid);
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        execve(svc->args[0], (char**) svc->args, (char**) ENV);
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        _exit(127);
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid < 0) {
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("failed to start '%s'\n", svc->name);
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->pid = 0;
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = gettime();
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = pid;
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RUNNING;
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "running");
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_stop(struct service *svc)
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* we are no longer running, nor should we
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * attempt to restart
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* if the service has not yet started, prevent
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * it from auto-starting with its class
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_DISABLED;
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->pid) {
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("service '%s' is being killed\n", svc->name);
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-svc->pid, SIGTERM);
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopping");
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid property_changed(const char *name, const char *value)
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (property_triggers_enabled) {
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        queue_property_triggers(name, value);
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int wait_for_one_process(int block)
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int status;
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc;
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct socketinfo *si;
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t now;
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid <= 0) return -1;
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("waitpid returned pid %d, status = %08x\n", pid, status);
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc = service_find_by_pid(pid);
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!svc) {
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("untracked pid %d exited\n", pid);
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("process '%s', pid %d exited\n", svc->name, pid);
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!(svc->flags & SVC_ONESHOT)) {
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-pid, SIGKILL);
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("process '%s' killing any children in process group\n", svc->name);
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* remove any sockets we may have created */
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (si = svc->sockets; si; si = si->next) {
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[128];
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(tmp);
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = 0;
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~SVC_RUNNING);
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* oneshot processes go into the disabled state on exit */
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_ONESHOT) {
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* disabled processes do not get restarted automatically */
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_DISABLED) {
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    now = gettime();
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_CRITICAL) {
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("critical process '%s' exited %d times in %d minutes; "
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      "rebooting into recovery mode\n", svc->name,
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                sync();
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         LINUX_REBOOT_CMD_RESTART2, "recovery");
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return 0;
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->time_crashed = now;
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->nr_crashed = 1;
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Execute all onrestart commands for this service. */
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    list_for_each(node, &svc->onrestart.commands) {
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd = node_to_item(node, struct command, clist);
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd->func(cmd->nargs, cmd->args);
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RESTARTING;
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "restarting");
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_service_if_needed(struct service *svc)
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t next_start_time = svc->time_started + 5;
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (next_start_time <= gettime()) {
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags &= (~SVC_RESTARTING);
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_start(svc);
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((next_start_time < process_needs_restart) ||
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (process_needs_restart == 0)) {
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        process_needs_restart = next_start_time;
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_processes()
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    process_needs_restart = 0;
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    service_for_each_flags(SVC_RESTARTING,
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           restart_service_if_needed);
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int signal_fd = -1;
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void sigchld_handler(int s)
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    write(signal_fd, &s, 1);
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_start(const char *name)
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_start(svc);
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n", name);
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_stop(const char *name)
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_stop(svc);
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n");
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid handle_control_message(const char *msg, const char *arg)
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(msg,"start")) {
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_start(arg);
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (!strcmp(msg,"stop")) {
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_stop(arg);
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("unknown control msg '%s'\n", msg);
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define MAX_MTD_PARTITIONS 16
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic struct {
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char name[16];
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int number;
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} mtd_part_map[MAX_MTD_PARTITIONS];
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int mtd_part_count = -1;
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void find_mtd_partitions(void)
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char buf[1024];
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *pmtdbufp;
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ssize_t pmtdsize;
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int r;
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/mtd", O_RDONLY);
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0)
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    buf[sizeof(buf) - 1] = '\0';
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdsize = read(fd, buf, sizeof(buf) - 1);
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdbufp = buf;
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (pmtdsize > 0) {
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int mtdnum, mtdsize, mtderasesize;
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char mtdname[16];
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdname[0] = '\0';
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdnum = -1;
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((r == 4) && (mtdname[0] == '"')) {
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *x = strchr(mtdname + 1, '"');
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (x) {
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                *x = 0;
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mtd_part_count < MAX_MTD_PARTITIONS) {
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_map[mtd_part_count].number = mtdnum;
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_count++;
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("too many mtd partitions\n");
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        while (pmtdsize > 0 && *pmtdbufp != '\n') {
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pmtdsize > 0) {
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint mtd_name_to_number(const char *name)
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mtd_part_count < 0) {
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtd_part_count = 0;
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        find_mtd_partitions();
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < mtd_part_count; n++) {
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name, mtd_part_map[n].name)) {
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return mtd_part_map[n].number;
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return -1;
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_nv(char *name, int in_qemu)
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *value = strchr(name, '=');
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (value == 0) return;
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *value++ = 0;
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (*name == 0) return;
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!in_qemu)
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* on a real device, white-list the kernel options */
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name,"qemu")) {
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(qemu, value, sizeof(qemu));
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.console")) {
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(console, value, sizeof(console));
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.mode")) {
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootmode, value, sizeof(bootmode));
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.serialno")) {
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(serialno, value, sizeof(serialno));
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.baseband")) {
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(baseband, value, sizeof(baseband));
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.carrier")) {
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(carrier, value, sizeof(carrier));
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.bootloader")) {
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootloader, value, sizeof(bootloader));
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.hardware")) {
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(hardware, value, sizeof(hardware));
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            qemu_cmdline(name, value);
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* in the emulator, export any kernel option with the
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * ro.kernel. prefix */
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char  buff[32];
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (len < (int)sizeof(buff)) {
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            property_set( buff, value );
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_cmdline(int in_qemu)
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char cmdline[1024];
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ptr;
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cmdline", O_RDONLY);
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0) {
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int n = read(fd, cmdline, 1023);
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n < 0) n = 0;
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* get rid of trailing newline, it happens */
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n > 0 && cmdline[n-1] == '\n') n--;
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[n] = 0;
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        close(fd);
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[0] = 0;
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptr = cmdline;
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (ptr && *ptr) {
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *x = strchr(ptr, ' ');
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x != 0) *x++ = 0;
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_nv(ptr, in_qemu);
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ptr = x;
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* don't expose the raw commandline to nonpriv processes */
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    chmod("/proc/cmdline", 0440);
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void get_hardware_name(void)
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char data[1024];
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd, n;
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *x, *hw, *rev;
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Hardware string was provided on kernel command line */
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hardware[0])
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cpuinfo", O_RDONLY);
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0) return;
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    n = read(fd, data, 1023);
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (n < 0) return;
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    data[n] = 0;
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    hw = strstr(data, "\nHardware");
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    rev = strstr(data, "\nRevision");
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hw) {
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(hw, ": ");
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            x += 2;
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            n = 0;
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (*x && !isspace(*x)) {
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                hardware[n++] = tolower(*x);
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                x++;
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (n == 31) break;
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            hardware[n] = 0;
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (rev) {
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(rev, ": ");
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            revision = strtoul(x + 2, 0, 16);
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void drain_action_queue(void)
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct action *act;
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ((act = action_remove_queue_head())) {
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        INFO("processing action %p (%s)\n", act, act->name);
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        list_for_each(node, &act->commands) {
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cmd = node_to_item(node, struct command, clist);
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ret = cmd->func(cmd->nargs, cmd->args);
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("command '%s' r=%d\n", cmd->args[0], ret);
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid open_devnull_stdio(void)
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static const char *name = "/dev/__null__";
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open(name, O_RDWR);
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(name);
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (fd >= 0) {
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 0);
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 1);
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 2);
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (fd > 2) {
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                close(fd);
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    exit(1);
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint main(int argc, char **argv)
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int device_fd = -1;
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int property_set_fd = -1;
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int signal_recv_fd = -1;
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int s[2];
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct sigaction act;
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char tmp[PROP_VALUE_MAX];
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct pollfd ufds[4];
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *tmpdev;
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_handler = sigchld_handler;
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_flags = SA_NOCLDSTOP;
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_mask = 0;
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_restorer = NULL;
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    sigaction(SIGCHLD, &act, 0);
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* clear the umask */
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    umask(0);
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* Get the basic filesystem setup we need put
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * together in the initramdisk on / and then we'll
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * let the rc file figure out the rest.
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev", 0755);
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/proc", 0755);
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/sys", 0755);
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/pts", 0755);
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/socket", 0755);
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("devpts", "/dev/pts", "devpts", 0, NULL);
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("proc", "/proc", "proc", 0, NULL);
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("sysfs", "/sys", "sysfs", 0, NULL);
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* We must have some place other than / to create the
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * device nodes for kmsg and null, otherwise we won't
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * be able to remount / read-only later on.
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * Now that tmpfs is mounted on /dev, we can actually
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * talk to the outside world.
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    open_devnull_stdio();
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    log_init();
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("reading config file\n");
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file("/init.rc");
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* pull the kernel commandline and ramdisk properties file in */
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    qemu_init();
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    import_kernel_cmdline(0);
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    get_hardware_name();
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file(tmp);
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-init", action_add_queue_tail);
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
7194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("device init\n");
7214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    device_fd = device_init();
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_init();
7244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (console[0]) {
7264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
7274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        console_name = strdup(tmp);
7284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open(console_name, O_RDWR);
7314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0)
7324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        have_console = 1;
7334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
7344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if( load_565rle_image(INIT_IMAGE_FILE) ) {
7364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	fd = open("/dev/tty0", O_WRONLY);
7374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	if (fd >= 0) {
7384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	    const char *msg;
7394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            msg = "\n"
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"  // console is 40 cols x 30 lines
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"\n"
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project		"             A N D R O I D ";
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	    write(fd, msg, strlen(msg));
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	    close(fd);
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project	}
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (qemu[0])
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_cmdline(1);
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(bootmode,"factory"))
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "1");
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (!strcmp(bootmode,"factory2"))
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "2");
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "0");
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.serialno", serialno[0] ? serialno : "");
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.hardware", hardware);
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.revision", tmp);
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* execute all the boot actions to get us started */
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("init", action_add_queue_tail);
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* read any property files on system or data and
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * fire up the property service.  This must happen
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * after the ro.foo properties are set above so
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that /data/local.prop cannot interfere with them.
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set_fd = start_property_service();
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* create a signalling mechanism for the sigchld handler */
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_fd = s[0];
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_recv_fd = s[1];
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFD, FD_CLOEXEC);
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFL, O_NONBLOCK);
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFD, FD_CLOEXEC);
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFL, O_NONBLOCK);
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we actually have all the pieces we need */
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((device_fd < 0) ||
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (property_set_fd < 0) ||
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (signal_recv_fd < 0)) {
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("init startup failure\n");
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 1;
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* execute all the boot actions to get us started */
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-boot", action_add_queue_tail);
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("boot", action_add_queue_tail);
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* run all property triggers based on current state of the properties */
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    queue_all_property_triggers();
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* enable property triggers */
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_triggers_enabled = 1;
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].fd = device_fd;
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].events = POLLIN;
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].fd = property_set_fd;
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].events = POLLIN;
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].fd = signal_recv_fd;
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].events = POLLIN;
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
82835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    bootchart_count = bootchart_init();
82935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (bootchart_count < 0) {
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("bootcharting init failure\n");
83135237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (bootchart_count > 0) {
83235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
83335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
83435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting ignored\n");
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for(;;) {
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int nr, timeout = -1;
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ufds[0].revents = 0;
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ufds[1].revents = 0;
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ufds[2].revents = 0;
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        restart_processes();
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (process_needs_restart) {
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            timeout = (process_needs_restart - gettime()) * 1000;
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0)
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = 0;
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bootchart_count > 0) {
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = BOOTCHART_POLLING_MS;
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (bootchart_step() < 0 || --bootchart_count == 0) {
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_finish();
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_count = 0;
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        nr = poll(ufds, 3, timeout);
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (nr <= 0)
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[2].revents == POLLIN) {
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* we got a SIGCHLD - reap and restart as needed */
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            read(signal_recv_fd, tmp, sizeof(tmp));
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (!wait_for_one_process(0))
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ;
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[0].revents == POLLIN)
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_device_fd(device_fd);
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[1].revents == POLLIN)
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_property_set_fd(property_set_fd);
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
885