init.c revision a866695ebe3a396a0ec411c0f99e0921c74c0fd2
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>
384e221f0077373b37ca70e862eface2987557295bSan Mehat#include <cutils/iosched_policy.h>
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <termios.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"
47a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross#include "keychords.h"
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int property_triggers_enabled = 0;
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int   bootchart_count;
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char console[32];
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char serialno[32];
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootmode[32];
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char baseband[32];
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char carrier[32];
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootloader[32];
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char hardware[32];
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic unsigned revision = 0;
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char qemu[32];
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void notify_service_state(const char *name, const char *state)
664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char pname[PROP_NAME_MAX];
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int len = strlen(name);
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((len + 10) > PROP_NAME_MAX)
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(pname, sizeof(pname), "init.svc.%s", name);
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set(pname, state);
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int have_console;
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char *console_name = "/dev/console";
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t process_needs_restart;
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic const char *ENV[32];
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* add_environment - add "key=value" to the current environment */
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint add_environment(const char *key, const char *val)
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < 31; n++) {
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!ENV[n]) {
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            size_t len = strlen(key) + strlen(val) + 2;
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *entry = malloc(len);
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            snprintf(entry, len, "%s=%s", key, val);
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ENV[n] = entry;
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return 0;
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 1;
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void zap_stdio(void)
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/dev/null", O_RDWR);
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void open_console()
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((fd = open(console_name, O_RDWR)) < 0) {
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open("/dev/null", O_RDWR);
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * gettime() - returns the time in seconds of the system's monotonic clock or
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * zero on error.
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t gettime(void)
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct timespec ts;
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (ret < 0) {
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ts.tv_sec;
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void publish_socket(const char *name, int fd)
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char val[64];
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            name,
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(val, sizeof(val), "%d", fd);
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    add_environment(key, val);
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we don't close-on-exec */
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fcntl(fd, F_SETFD, 0);
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
154f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehatvoid service_start(struct service *svc, const char *dynamic_args)
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct stat s;
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int needs_console;
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* starting a service removes it from the disabled
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state and immediately takes it out of the restarting
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state if it was in there
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = 0;
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* running processes require no additional work -- if
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they're in the process of exiting, we've ensured
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that they will immediately restart on exit, unless
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they are ONESHOT
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_RUNNING) {
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (needs_console && (!have_console)) {
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("service '%s' requires console\n", svc->name);
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (stat(svc->args[0], &s) != 0) {
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
190f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
191d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
192d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat               svc->args[0]);
193f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc->flags |= SVC_DISABLED;
194f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        return;
195f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
196f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("starting '%s'\n", svc->name);
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid = fork();
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid == 0) {
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct socketinfo *si;
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct svcenvinfo *ei;
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[32];
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int fd, sz;
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        get_property_workspace(&fd, &sz);
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        sprintf(tmp, "%d,%d", dup(fd), sz);
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (ei = svc->envvars; ei; ei = ei->next)
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            add_environment(ei->name, ei->value);
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = create_socket(si->name,
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  !strcmp(si->type, "dgram") ?
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  SOCK_DGRAM : SOCK_STREAM,
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  si->perm, si->uid, si->gid);
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (s >= 0) {
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                publish_socket(si->name, s);
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2244e221f0077373b37ca70e862eface2987557295bSan Mehat        if (svc->ioprio_class != IoSchedClass_NONE) {
2254e221f0077373b37ca70e862eface2987557295bSan Mehat            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
2264e221f0077373b37ca70e862eface2987557295bSan Mehat                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
2274e221f0077373b37ca70e862eface2987557295bSan Mehat                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
2284e221f0077373b37ca70e862eface2987557295bSan Mehat            }
2294e221f0077373b37ca70e862eface2987557295bSan Mehat        }
2304e221f0077373b37ca70e862eface2987557295bSan Mehat
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (needs_console) {
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setsid();
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            open_console();
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            zap_stdio();
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; svc->args[n]; n++) {
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("args[%d] = '%s'\n", n, svc->args[n]);
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; ENV[n]; n++) {
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("env[%d] = '%s'\n", n, ENV[n]);
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        setpgid(0, getpid());
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2495ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* as requested, set our gid, supplemental gids, and uid */
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->gid) {
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgid(svc->gid);
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->nr_supp_gids) {
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgroups(svc->nr_supp_gids, svc->supp_gids);
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->uid) {
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setuid(svc->uid);
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2608ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        if (!dynamic_args) {
2618ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
2628ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
2638ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            }
2648ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        } else {
265f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *arg_ptrs[SVC_MAXARGS+1];
266d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            int arg_idx = svc->nargs;
267f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *tmp = strdup(dynamic_args);
268d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *next = tmp;
269d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *bword;
270f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
271f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            /* Copy the static arguments */
272d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
273f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
274d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            while((bword = strsep(&next, " "))) {
275d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                arg_ptrs[arg_idx++] = bword;
276d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                if (arg_idx == SVC_MAXARGS)
277f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat                    break;
278f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            }
279f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            arg_ptrs[arg_idx] = '\0';
280f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
281165de92bf1bca1648b4df3047a8f274e0aff4ca9Ivan Djelic        }
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        _exit(127);
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid < 0) {
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("failed to start '%s'\n", svc->name);
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->pid = 0;
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = gettime();
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = pid;
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RUNNING;
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "running");
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_stop(struct service *svc)
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* we are no longer running, nor should we
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * attempt to restart
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* if the service has not yet started, prevent
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * it from auto-starting with its class
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_DISABLED;
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->pid) {
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("service '%s' is being killed\n", svc->name);
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-svc->pid, SIGTERM);
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopping");
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid property_changed(const char *name, const char *value)
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (property_triggers_enabled) {
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        queue_property_triggers(name, value);
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int wait_for_one_process(int block)
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int status;
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc;
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct socketinfo *si;
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t now;
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid <= 0) return -1;
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("waitpid returned pid %d, status = %08x\n", pid, status);
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc = service_find_by_pid(pid);
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!svc) {
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("untracked pid %d exited\n", pid);
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("process '%s', pid %d exited\n", svc->name, pid);
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!(svc->flags & SVC_ONESHOT)) {
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-pid, SIGKILL);
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("process '%s' killing any children in process group\n", svc->name);
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* remove any sockets we may have created */
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (si = svc->sockets; si; si = si->next) {
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[128];
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(tmp);
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = 0;
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~SVC_RUNNING);
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* oneshot processes go into the disabled state on exit */
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_ONESHOT) {
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* disabled processes do not get restarted automatically */
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_DISABLED) {
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    now = gettime();
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_CRITICAL) {
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("critical process '%s' exited %d times in %d minutes; "
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      "rebooting into recovery mode\n", svc->name,
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                sync();
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         LINUX_REBOOT_CMD_RESTART2, "recovery");
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return 0;
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->time_crashed = now;
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->nr_crashed = 1;
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
396dc816d5dcd87a3578e47eade55db80b99b802c62Ben Gruver    svc->flags |= SVC_RESTARTING;
397dc816d5dcd87a3578e47eade55db80b99b802c62Ben Gruver
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Execute all onrestart commands for this service. */
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    list_for_each(node, &svc->onrestart.commands) {
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd = node_to_item(node, struct command, clist);
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd->func(cmd->nargs, cmd->args);
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "restarting");
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_service_if_needed(struct service *svc)
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t next_start_time = svc->time_started + 5;
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (next_start_time <= gettime()) {
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags &= (~SVC_RESTARTING);
413f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, NULL);
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((next_start_time < process_needs_restart) ||
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (process_needs_restart == 0)) {
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        process_needs_restart = next_start_time;
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_processes()
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    process_needs_restart = 0;
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    service_for_each_flags(SVC_RESTARTING,
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           restart_service_if_needed);
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int signal_fd = -1;
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void sigchld_handler(int s)
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    write(signal_fd, &s, 1);
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_start(const char *name)
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
439f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    struct service *svc;
440f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *tmp = NULL;
441f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *args = NULL;
442f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
443f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (!strchr(name, ':'))
444f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(name);
445f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    else {
446f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        tmp = strdup(name);
447f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args = strchr(tmp, ':');
448f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        *args = '\0';
449f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args++;
450f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
451f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(tmp);
452f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
455f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, args);
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n", name);
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
459f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (tmp)
460f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        free(tmp);
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_stop(const char *name)
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_stop(svc);
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
470770354d7e6cd471daed426fcf04bf7246e7cb18bDima Zavin        ERROR("no such service '%s'\n", name);
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid handle_control_message(const char *msg, const char *arg)
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(msg,"start")) {
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_start(arg);
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (!strcmp(msg,"stop")) {
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_stop(arg);
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("unknown control msg '%s'\n", msg);
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_nv(char *name, int in_qemu)
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *value = strchr(name, '=');
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (value == 0) return;
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *value++ = 0;
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (*name == 0) return;
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!in_qemu)
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* on a real device, white-list the kernel options */
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name,"qemu")) {
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(qemu, value, sizeof(qemu));
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.console")) {
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(console, value, sizeof(console));
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.mode")) {
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootmode, value, sizeof(bootmode));
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.serialno")) {
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(serialno, value, sizeof(serialno));
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.baseband")) {
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(baseband, value, sizeof(baseband));
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.carrier")) {
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(carrier, value, sizeof(carrier));
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.bootloader")) {
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootloader, value, sizeof(bootloader));
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.hardware")) {
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(hardware, value, sizeof(hardware));
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            qemu_cmdline(name, value);
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* in the emulator, export any kernel option with the
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * ro.kernel. prefix */
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char  buff[32];
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (len < (int)sizeof(buff)) {
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            property_set( buff, value );
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_cmdline(int in_qemu)
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char cmdline[1024];
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ptr;
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cmdline", O_RDONLY);
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0) {
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int n = read(fd, cmdline, 1023);
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n < 0) n = 0;
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* get rid of trailing newline, it happens */
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n > 0 && cmdline[n-1] == '\n') n--;
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[n] = 0;
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        close(fd);
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[0] = 0;
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptr = cmdline;
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (ptr && *ptr) {
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *x = strchr(ptr, ' ');
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x != 0) *x++ = 0;
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_nv(ptr, in_qemu);
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ptr = x;
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* don't expose the raw commandline to nonpriv processes */
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    chmod("/proc/cmdline", 0440);
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void get_hardware_name(void)
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char data[1024];
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd, n;
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *x, *hw, *rev;
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Hardware string was provided on kernel command line */
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hardware[0])
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cpuinfo", O_RDONLY);
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0) return;
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    n = read(fd, data, 1023);
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (n < 0) return;
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    data[n] = 0;
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    hw = strstr(data, "\nHardware");
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    rev = strstr(data, "\nRevision");
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hw) {
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(hw, ": ");
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            x += 2;
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            n = 0;
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (*x && !isspace(*x)) {
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                hardware[n++] = tolower(*x);
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                x++;
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (n == 31) break;
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            hardware[n] = 0;
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (rev) {
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(rev, ": ");
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            revision = strtoul(x + 2, 0, 16);
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
60111e1c42df69b15c938aa1b7570e4370e6ab15a86Jay Freeman (saurik)void drain_action_queue(void)
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct action *act;
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ((act = action_remove_queue_head())) {
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        INFO("processing action %p (%s)\n", act, act->name);
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        list_for_each(node, &act->commands) {
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cmd = node_to_item(node, struct command, clist);
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ret = cmd->func(cmd->nargs, cmd->args);
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("command '%s' r=%d\n", cmd->args[0], ret);
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid open_devnull_stdio(void)
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static const char *name = "/dev/__null__";
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open(name, O_RDWR);
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(name);
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (fd >= 0) {
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 0);
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 1);
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 2);
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (fd > 2) {
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                close(fd);
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    exit(1);
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint main(int argc, char **argv)
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int device_fd = -1;
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int property_set_fd = -1;
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int signal_recv_fd = -1;
6445ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd_count;
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int s[2];
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct sigaction act;
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char tmp[PROP_VALUE_MAX];
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct pollfd ufds[4];
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *tmpdev;
6515ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    char* debuggable;
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_handler = sigchld_handler;
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_flags = SA_NOCLDSTOP;
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_mask = 0;
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_restorer = NULL;
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    sigaction(SIGCHLD, &act, 0);
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* clear the umask */
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    umask(0);
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* Get the basic filesystem setup we need put
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * together in the initramdisk on / and then we'll
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * let the rc file figure out the rest.
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev", 0755);
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/proc", 0755);
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/sys", 0755);
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/pts", 0755);
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/socket", 0755);
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("devpts", "/dev/pts", "devpts", 0, NULL);
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("proc", "/proc", "proc", 0, NULL);
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("sysfs", "/sys", "sysfs", 0, NULL);
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* We must have some place other than / to create the
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * device nodes for kmsg and null, otherwise we won't
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * be able to remount / read-only later on.
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * Now that tmpfs is mounted on /dev, we can actually
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * talk to the outside world.
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    open_devnull_stdio();
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    log_init();
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("reading config file\n");
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file("/init.rc");
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* pull the kernel commandline and ramdisk properties file in */
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    qemu_init();
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    import_kernel_cmdline(0);
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    get_hardware_name();
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file(tmp);
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-init", action_add_queue_tail);
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("device init\n");
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    device_fd = device_init();
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_init();
7045ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7055ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    // only listen for keychords if ro.debuggable is true
706a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    keychord_init();
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (console[0]) {
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        console_name = strdup(tmp);
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open(console_name, O_RDWR);
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0)
7154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        have_console = 1;
7164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
7174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if( load_565rle_image(INIT_IMAGE_FILE) ) {
7195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/tty0", O_WRONLY);
7205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd >= 0) {
7215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        const char *msg;
7224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            msg = "\n"
7235ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7255ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7265ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7275ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7285ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"  // console is 40 cols x 30 lines
7295ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7305ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7315ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7325ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7335ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7345ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7355ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
7365ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "             A N D R O I D ";
7375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        write(fd, msg, strlen(msg));
7385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
7395ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (qemu[0])
7434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_cmdline(1);
7444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(bootmode,"factory"))
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "1");
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (!strcmp(bootmode,"factory2"))
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "2");
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "0");
7514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.serialno", serialno[0] ? serialno : "");
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.hardware", hardware);
7594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.revision", tmp);
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* execute all the boot actions to get us started */
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("init", action_add_queue_tail);
76431712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("early-fs", action_add_queue_tail);
76531712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("fs", action_add_queue_tail);
76631712beaf7de127a1249b909cdefffbc25fff076Colin Cross    action_for_each_trigger("post-fs", action_add_queue_tail);
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* read any property files on system or data and
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * fire up the property service.  This must happen
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * after the ro.foo properties are set above so
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that /data/local.prop cannot interfere with them.
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set_fd = start_property_service();
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* create a signalling mechanism for the sigchld handler */
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_fd = s[0];
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_recv_fd = s[1];
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFD, FD_CLOEXEC);
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFL, O_NONBLOCK);
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFD, FD_CLOEXEC);
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFL, O_NONBLOCK);
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we actually have all the pieces we need */
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((device_fd < 0) ||
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (property_set_fd < 0) ||
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (signal_recv_fd < 0)) {
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("init startup failure\n");
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 1;
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* execute all the boot actions to get us started */
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-boot", action_add_queue_tail);
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("boot", action_add_queue_tail);
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* run all property triggers based on current state of the properties */
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    queue_all_property_triggers();
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* enable property triggers */
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_triggers_enabled = 1;
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].fd = device_fd;
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].events = POLLIN;
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].fd = property_set_fd;
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].events = POLLIN;
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].fd = signal_recv_fd;
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].events = POLLIN;
8125ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd_count = 3;
8135ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
814a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross    if (get_keychord_fd() > 0) {
815a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross        ufds[3].fd = get_keychord_fd();
8165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = POLLIN;
8175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd_count++;
8185ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    } else {
8195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = 0;
8205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].revents = 0;
8215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
82435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    bootchart_count = bootchart_init();
82535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (bootchart_count < 0) {
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("bootcharting init failure\n");
82735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (bootchart_count > 0) {
82835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
82935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
83035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting ignored\n");
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for(;;) {
8355ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        int nr, i, timeout = -1;
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < fd_count; i++)
8385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ufds[i].revents = 0;
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        restart_processes();
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (process_needs_restart) {
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            timeout = (process_needs_restart - gettime()) * 1000;
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0)
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = 0;
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bootchart_count > 0) {
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = BOOTCHART_POLLING_MS;
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (bootchart_step() < 0 || --bootchart_count == 0) {
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_finish();
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_count = 0;
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
8595ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        nr = poll(ufds, fd_count, timeout);
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (nr <= 0)
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[2].revents == POLLIN) {
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* we got a SIGCHLD - reap and restart as needed */
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            read(signal_recv_fd, tmp, sizeof(tmp));
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (!wait_for_one_process(0))
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ;
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[0].revents == POLLIN)
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_device_fd(device_fd);
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[1].revents == POLLIN)
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_property_set_fd(property_set_fd);
8765ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (ufds[3].revents == POLLIN)
877a866695ebe3a396a0ec411c0f99e0921c74c0fd2Colin Cross            handle_keychord();
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
882