init.c revision 4e221f0077373b37ca70e862eface2987557295b
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#include <linux/kd.h>
415ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project#include <linux/keychord.h>
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/system_properties.h>
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "devices.h"
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "init.h"
474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "property_service.h"
4835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project#include "bootchart.h"
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int property_triggers_enabled = 0;
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int   bootchart_count;
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char console[32];
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char serialno[32];
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootmode[32];
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char baseband[32];
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char carrier[32];
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootloader[32];
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char hardware[32];
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic unsigned revision = 0;
644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char qemu[32];
655ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic struct input_keychord *keychords = 0;
665ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic int keychords_count = 0;
675ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic int keychords_length = 0;
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void notify_service_state(const char *name, const char *state)
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char pname[PROP_NAME_MAX];
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int len = strlen(name);
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((len + 10) > PROP_NAME_MAX)
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(pname, sizeof(pname), "init.svc.%s", name);
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set(pname, state);
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int have_console;
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char *console_name = "/dev/console";
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t process_needs_restart;
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic const char *ENV[32];
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* add_environment - add "key=value" to the current environment */
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint add_environment(const char *key, const char *val)
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < 31; n++) {
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!ENV[n]) {
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            size_t len = strlen(key) + strlen(val) + 2;
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *entry = malloc(len);
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            snprintf(entry, len, "%s=%s", key, val);
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ENV[n] = entry;
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return 0;
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 1;
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void zap_stdio(void)
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/dev/null", O_RDWR);
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void open_console()
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((fd = open(console_name, O_RDWR)) < 0) {
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open("/dev/null", O_RDWR);
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * gettime() - returns the time in seconds of the system's monotonic clock or
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * zero on error.
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t gettime(void)
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct timespec ts;
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (ret < 0) {
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ts.tv_sec;
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void publish_socket(const char *name, int fd)
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char val[64];
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            name,
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(val, sizeof(val), "%d", fd);
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    add_environment(key, val);
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we don't close-on-exec */
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fcntl(fd, F_SETFD, 0);
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
158f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehatvoid service_start(struct service *svc, const char *dynamic_args)
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct stat s;
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int needs_console;
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* starting a service removes it from the disabled
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state and immediately takes it out of the restarting
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state if it was in there
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = 0;
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* running processes require no additional work -- if
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they're in the process of exiting, we've ensured
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that they will immediately restart on exit, unless
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they are ONESHOT
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_RUNNING) {
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (needs_console && (!have_console)) {
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("service '%s' requires console\n", svc->name);
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (stat(svc->args[0], &s) != 0) {
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
194f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) {
195d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat        ERROR("service '%s' must be one-shot to use dynamic args, disabling\n",
196d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat               svc->args[0]);
197f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc->flags |= SVC_DISABLED;
198f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        return;
199f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
200f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("starting '%s'\n", svc->name);
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid = fork();
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid == 0) {
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct socketinfo *si;
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct svcenvinfo *ei;
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[32];
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int fd, sz;
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        get_property_workspace(&fd, &sz);
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        sprintf(tmp, "%d,%d", dup(fd), sz);
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (ei = svc->envvars; ei; ei = ei->next)
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            add_environment(ei->name, ei->value);
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = create_socket(si->name,
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  !strcmp(si->type, "dgram") ?
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  SOCK_DGRAM : SOCK_STREAM,
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  si->perm, si->uid, si->gid);
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (s >= 0) {
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                publish_socket(si->name, s);
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2284e221f0077373b37ca70e862eface2987557295bSan Mehat        if (svc->ioprio_class != IoSchedClass_NONE) {
2294e221f0077373b37ca70e862eface2987557295bSan Mehat            if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) {
2304e221f0077373b37ca70e862eface2987557295bSan Mehat                ERROR("Failed to set pid %d ioprio = %d,%d: %s\n",
2314e221f0077373b37ca70e862eface2987557295bSan Mehat                      getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno));
2324e221f0077373b37ca70e862eface2987557295bSan Mehat            }
2334e221f0077373b37ca70e862eface2987557295bSan Mehat        }
2344e221f0077373b37ca70e862eface2987557295bSan Mehat
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (needs_console) {
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setsid();
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            open_console();
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            zap_stdio();
2404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; svc->args[n]; n++) {
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("args[%d] = '%s'\n", n, svc->args[n]);
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; ENV[n]; n++) {
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("env[%d] = '%s'\n", n, ENV[n]);
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        setpgid(0, getpid());
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2535ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* as requested, set our gid, supplemental gids, and uid */
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->gid) {
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgid(svc->gid);
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->nr_supp_gids) {
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgroups(svc->nr_supp_gids, svc->supp_gids);
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->uid) {
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setuid(svc->uid);
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2648ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        if (!dynamic_args) {
2658ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) {
2668ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat                ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno));
2678ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat            }
2688ad15685e6d3d2251ceac4ac7135397cf6140e1aSan Mehat        } else {
269f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *arg_ptrs[SVC_MAXARGS+1];
270d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            int arg_idx = svc->nargs;
271f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            char *tmp = strdup(dynamic_args);
272d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *next = tmp;
273d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            char *bword;
274f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
275f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            /* Copy the static arguments */
276d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *)));
277f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
278d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat            while((bword = strsep(&next, " "))) {
279d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                arg_ptrs[arg_idx++] = bword;
280d4cdd13f6f56f3fe8d8511b609e823925fdd83f9San Mehat                if (arg_idx == SVC_MAXARGS)
281f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat                    break;
282f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            }
283f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            arg_ptrs[arg_idx] = '\0';
284f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat            execve(svc->args[0], (char**) arg_ptrs, (char**) ENV);
285165de92bf1bca1648b4df3047a8f274e0aff4ca9Ivan Djelic        }
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        _exit(127);
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid < 0) {
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("failed to start '%s'\n", svc->name);
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->pid = 0;
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = gettime();
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = pid;
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RUNNING;
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "running");
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_stop(struct service *svc)
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* we are no longer running, nor should we
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * attempt to restart
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* if the service has not yet started, prevent
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * it from auto-starting with its class
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_DISABLED;
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->pid) {
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("service '%s' is being killed\n", svc->name);
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-svc->pid, SIGTERM);
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopping");
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid property_changed(const char *name, const char *value)
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (property_triggers_enabled) {
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        queue_property_triggers(name, value);
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int wait_for_one_process(int block)
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int status;
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc;
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct socketinfo *si;
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t now;
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid <= 0) return -1;
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("waitpid returned pid %d, status = %08x\n", pid, status);
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc = service_find_by_pid(pid);
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!svc) {
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("untracked pid %d exited\n", pid);
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("process '%s', pid %d exited\n", svc->name, pid);
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!(svc->flags & SVC_ONESHOT)) {
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-pid, SIGKILL);
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("process '%s' killing any children in process group\n", svc->name);
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* remove any sockets we may have created */
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (si = svc->sockets; si; si = si->next) {
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[128];
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(tmp);
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = 0;
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~SVC_RUNNING);
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* oneshot processes go into the disabled state on exit */
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_ONESHOT) {
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* disabled processes do not get restarted automatically */
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_DISABLED) {
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    now = gettime();
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_CRITICAL) {
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("critical process '%s' exited %d times in %d minutes; "
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      "rebooting into recovery mode\n", svc->name,
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                sync();
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         LINUX_REBOOT_CMD_RESTART2, "recovery");
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return 0;
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->time_crashed = now;
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->nr_crashed = 1;
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
400dc816d5dcd87a3578e47eade55db80b99b802c62Ben Gruver    svc->flags |= SVC_RESTARTING;
401dc816d5dcd87a3578e47eade55db80b99b802c62Ben Gruver
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Execute all onrestart commands for this service. */
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    list_for_each(node, &svc->onrestart.commands) {
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd = node_to_item(node, struct command, clist);
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd->func(cmd->nargs, cmd->args);
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "restarting");
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_service_if_needed(struct service *svc)
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t next_start_time = svc->time_started + 5;
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (next_start_time <= gettime()) {
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags &= (~SVC_RESTARTING);
417f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, NULL);
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((next_start_time < process_needs_restart) ||
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (process_needs_restart == 0)) {
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        process_needs_restart = next_start_time;
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_processes()
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    process_needs_restart = 0;
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    service_for_each_flags(SVC_RESTARTING,
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           restart_service_if_needed);
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int signal_fd = -1;
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void sigchld_handler(int s)
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    write(signal_fd, &s, 1);
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_start(const char *name)
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
443f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    struct service *svc;
444f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *tmp = NULL;
445f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    char *args = NULL;
446f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
447f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (!strchr(name, ':'))
448f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(name);
449f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    else {
450f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        tmp = strdup(name);
451f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args = strchr(tmp, ':');
452f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        *args = '\0';
453f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        args++;
454f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat
455f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        svc = service_find_by_name(tmp);
456f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    }
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
459f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        service_start(svc, args);
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n", name);
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
463f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat    if (tmp)
464f24e252903ca0f71c7fbfb135cf17e83e0c2ea90San Mehat        free(tmp);
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_stop(const char *name)
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_stop(svc);
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
474770354d7e6cd471daed426fcf04bf7246e7cb18bDima Zavin        ERROR("no such service '%s'\n", name);
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid handle_control_message(const char *msg, const char *arg)
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(msg,"start")) {
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_start(arg);
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (!strcmp(msg,"stop")) {
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_stop(arg);
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("unknown control msg '%s'\n", msg);
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define MAX_MTD_PARTITIONS 16
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic struct {
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char name[16];
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int number;
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} mtd_part_map[MAX_MTD_PARTITIONS];
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int mtd_part_count = -1;
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void find_mtd_partitions(void)
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char buf[1024];
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *pmtdbufp;
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ssize_t pmtdsize;
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int r;
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/mtd", O_RDONLY);
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0)
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    buf[sizeof(buf) - 1] = '\0';
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdsize = read(fd, buf, sizeof(buf) - 1);
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdbufp = buf;
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (pmtdsize > 0) {
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int mtdnum, mtdsize, mtderasesize;
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char mtdname[16];
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdname[0] = '\0';
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdnum = -1;
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((r == 4) && (mtdname[0] == '"')) {
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *x = strchr(mtdname + 1, '"');
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (x) {
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                *x = 0;
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mtd_part_count < MAX_MTD_PARTITIONS) {
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_map[mtd_part_count].number = mtdnum;
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_count++;
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("too many mtd partitions\n");
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        while (pmtdsize > 0 && *pmtdbufp != '\n') {
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pmtdsize > 0) {
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint mtd_name_to_number(const char *name)
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mtd_part_count < 0) {
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtd_part_count = 0;
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        find_mtd_partitions();
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < mtd_part_count; n++) {
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name, mtd_part_map[n].name)) {
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return mtd_part_map[n].number;
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return -1;
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_nv(char *name, int in_qemu)
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *value = strchr(name, '=');
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (value == 0) return;
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *value++ = 0;
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (*name == 0) return;
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!in_qemu)
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* on a real device, white-list the kernel options */
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name,"qemu")) {
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(qemu, value, sizeof(qemu));
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.console")) {
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(console, value, sizeof(console));
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.mode")) {
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootmode, value, sizeof(bootmode));
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.serialno")) {
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(serialno, value, sizeof(serialno));
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.baseband")) {
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(baseband, value, sizeof(baseband));
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.carrier")) {
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(carrier, value, sizeof(carrier));
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.bootloader")) {
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootloader, value, sizeof(bootloader));
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.hardware")) {
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(hardware, value, sizeof(hardware));
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            qemu_cmdline(name, value);
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* in the emulator, export any kernel option with the
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * ro.kernel. prefix */
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char  buff[32];
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (len < (int)sizeof(buff)) {
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            property_set( buff, value );
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_cmdline(int in_qemu)
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char cmdline[1024];
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ptr;
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cmdline", O_RDONLY);
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0) {
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int n = read(fd, cmdline, 1023);
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n < 0) n = 0;
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* get rid of trailing newline, it happens */
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n > 0 && cmdline[n-1] == '\n') n--;
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[n] = 0;
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        close(fd);
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[0] = 0;
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptr = cmdline;
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (ptr && *ptr) {
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *x = strchr(ptr, ' ');
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x != 0) *x++ = 0;
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_nv(ptr, in_qemu);
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ptr = x;
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* don't expose the raw commandline to nonpriv processes */
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    chmod("/proc/cmdline", 0440);
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void get_hardware_name(void)
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char data[1024];
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd, n;
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *x, *hw, *rev;
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Hardware string was provided on kernel command line */
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hardware[0])
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cpuinfo", O_RDONLY);
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0) return;
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    n = read(fd, data, 1023);
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (n < 0) return;
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    data[n] = 0;
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    hw = strstr(data, "\nHardware");
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    rev = strstr(data, "\nRevision");
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hw) {
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(hw, ": ");
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            x += 2;
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            n = 0;
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (*x && !isspace(*x)) {
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                hardware[n++] = tolower(*x);
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                x++;
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (n == 31) break;
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            hardware[n] = 0;
6664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (rev) {
6704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(rev, ": ");
6714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            revision = strtoul(x + 2, 0, 16);
6734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
67711e1c42df69b15c938aa1b7570e4370e6ab15a86Jay Freeman (saurik)void drain_action_queue(void)
6784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
6804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
6814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct action *act;
6824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
6834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ((act = action_remove_queue_head())) {
6854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        INFO("processing action %p (%s)\n", act, act->name);
6864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        list_for_each(node, &act->commands) {
6874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cmd = node_to_item(node, struct command, clist);
6884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ret = cmd->func(cmd->nargs, cmd->args);
6894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("command '%s' r=%d\n", cmd->args[0], ret);
6904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid open_devnull_stdio(void)
6954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static const char *name = "/dev/__null__";
6984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
6994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open(name, O_RDWR);
7004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(name);
7014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (fd >= 0) {
7024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 0);
7034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 1);
7044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 2);
7054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (fd > 2) {
7064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                close(fd);
7074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
7084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
7094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
7104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
7114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    exit(1);
7134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
7144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7155ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectvoid add_service_keycodes(struct service *svc)
7165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
7175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    struct input_keychord *keychord;
7185ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int i, size;
7195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (svc->keycodes) {
7215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        /* add a new keychord to the list */
7225ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
7235ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords = realloc(keychords, keychords_length + size);
7245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (!keychords) {
7255ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ERROR("could not allocate keychords\n");
7265ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychords_length = 0;
7275ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychords_count = 0;
7285ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            return;
7295ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        }
7305ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7315ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord = (struct input_keychord *)((char *)keychords + keychords_length);
7325ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->version = KEYCHORD_VERSION;
7335ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->id = keychords_count + 1;
7345ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->count = svc->nkeycodes;
7355ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        svc->keychord_id = keychord->id;
7365ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < svc->nkeycodes; i++) {
7385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychord->keycodes[i] = svc->keycodes[i];
7395ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        }
7405ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords_count++;
7415ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords_length += size;
7425ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7435ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
7445ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7455ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectint open_keychord()
7465ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
7475ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd, ret;
7485ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7495ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    service_for_each(add_service_keycodes);
7505ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7515ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* nothing to do if no services require keychords */
7525ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (!keychords)
7535ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        return -1;
7545ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7555ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/keychord", O_RDWR);
7565ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd < 0) {
7575ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("could not open /dev/keychord\n");
7585ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        return fd;
7595ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7605ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fcntl(fd, F_SETFD, FD_CLOEXEC);
7615ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7625ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    ret = write(fd, keychords, keychords_length);
7635ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (ret != keychords_length) {
7645ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
7655ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
7665ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd = -1;
7675ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7685ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7695ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    free(keychords);
7705ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    keychords = 0;
7715ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7725ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    return fd;
7735ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
7745ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7755ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectvoid handle_keychord(int fd)
7765ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
7775ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    struct service *svc;
7787a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    char* debuggable;
7797a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    char* adb_enabled;
7805ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int ret;
7815ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    __u16 id;
7825ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7837a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    // only handle keychords if ro.debuggable is set or adb is enabled.
7847a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    // the logic here is that bugreports should be enabled in userdebug or eng builds
7857a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    // and on user builds for users that are developers.
7867a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    debuggable = property_get("ro.debuggable");
7877a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    adb_enabled = property_get("init.svc.adbd");
7887a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    if ((debuggable && !strcmp(debuggable, "1")) ||
7897a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        (adb_enabled && !strcmp(adb_enabled, "running"))) {
7907a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        ret = read(fd, &id, sizeof(id));
7917a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        if (ret != sizeof(id)) {
7927a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood            ERROR("could not read keychord id\n");
7937a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood            return;
7947a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        }
7955ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7967a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        svc = service_find_by_keychord(id);
7977a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        if (svc) {
7987a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood            INFO("starting service %s from keychord\n", svc->name);
7997a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood            service_start(svc, NULL);
8007a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        } else {
8017a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood            ERROR("service for keychord %d not found\n", id);
8027a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood        }
8035ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
8045ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
8055ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint main(int argc, char **argv)
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int device_fd = -1;
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int property_set_fd = -1;
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int signal_recv_fd = -1;
8115ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int keychord_fd = -1;
8125ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd_count;
8134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int s[2];
8144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
8154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct sigaction act;
8164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char tmp[PROP_VALUE_MAX];
8174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct pollfd ufds[4];
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *tmpdev;
8195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    char* debuggable;
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_handler = sigchld_handler;
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_flags = SA_NOCLDSTOP;
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_mask = 0;
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_restorer = NULL;
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    sigaction(SIGCHLD, &act, 0);
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* clear the umask */
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    umask(0);
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* Get the basic filesystem setup we need put
8314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * together in the initramdisk on / and then we'll
8324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * let the rc file figure out the rest.
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
8344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev", 0755);
8354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/proc", 0755);
8364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/sys", 0755);
8374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
8394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/pts", 0755);
8404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/socket", 0755);
8414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("devpts", "/dev/pts", "devpts", 0, NULL);
8424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("proc", "/proc", "proc", 0, NULL);
8434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("sysfs", "/sys", "sysfs", 0, NULL);
8444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* We must have some place other than / to create the
8464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * device nodes for kmsg and null, otherwise we won't
8474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * be able to remount / read-only later on.
8484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * Now that tmpfs is mounted on /dev, we can actually
8494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * talk to the outside world.
8504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    open_devnull_stdio();
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    log_init();
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("reading config file\n");
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file("/init.rc");
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* pull the kernel commandline and ramdisk properties file in */
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    qemu_init();
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    import_kernel_cmdline(0);
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    get_hardware_name();
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file(tmp);
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-init", action_add_queue_tail);
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("device init\n");
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    device_fd = device_init();
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_init();
8725ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
8735ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    // only listen for keychords if ro.debuggable is true
8747a36210cdb39bde3a7d73095d5891678685e431fMike Lockwood    keychord_fd = open_keychord();
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (console[0]) {
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        console_name = strdup(tmp);
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open(console_name, O_RDWR);
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0)
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        have_console = 1;
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
8854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if( load_565rle_image(INIT_IMAGE_FILE) ) {
8875ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/tty0", O_WRONLY);
8885ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd >= 0) {
8895ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        const char *msg;
8904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            msg = "\n"
8915ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8925ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8935ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8945ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8955ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8965ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"  // console is 40 cols x 30 lines
8975ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8985ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8995ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
9005ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
9015ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
9025ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
9035ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
9045ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "             A N D R O I D ";
9055ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        write(fd, msg, strlen(msg));
9065ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
9075ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
9084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (qemu[0])
9114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_cmdline(1);
9124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(bootmode,"factory"))
9144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "1");
9154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (!strcmp(bootmode,"factory2"))
9164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "2");
9174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else
9184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "0");
9194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.serialno", serialno[0] ? serialno : "");
9214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
9224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
9234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
9244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
9254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.hardware", hardware);
9274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
9284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.revision", tmp);
9294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* execute all the boot actions to get us started */
9314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("init", action_add_queue_tail);
9324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
9334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* read any property files on system or data and
9354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * fire up the property service.  This must happen
9364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * after the ro.foo properties are set above so
9374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that /data/local.prop cannot interfere with them.
9384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
9394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set_fd = start_property_service();
9404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* create a signalling mechanism for the sigchld handler */
9424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
9434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_fd = s[0];
9444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_recv_fd = s[1];
9454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFD, FD_CLOEXEC);
9464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFL, O_NONBLOCK);
9474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFD, FD_CLOEXEC);
9484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFL, O_NONBLOCK);
9494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we actually have all the pieces we need */
9524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((device_fd < 0) ||
9534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (property_set_fd < 0) ||
9544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (signal_recv_fd < 0)) {
9554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("init startup failure\n");
9564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 1;
9574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* execute all the boot actions to get us started */
9604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-boot", action_add_queue_tail);
9614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("boot", action_add_queue_tail);
9624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
9634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* run all property triggers based on current state of the properties */
9654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    queue_all_property_triggers();
9664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
9674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* enable property triggers */
9694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_triggers_enabled = 1;
9704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].fd = device_fd;
9724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].events = POLLIN;
9734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].fd = property_set_fd;
9744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].events = POLLIN;
9754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].fd = signal_recv_fd;
9764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].events = POLLIN;
9775ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd_count = 3;
9785ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
9795ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (keychord_fd > 0) {
9805ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].fd = keychord_fd;
9815ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = POLLIN;
9825ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd_count++;
9835ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    } else {
9845ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = 0;
9855ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].revents = 0;
9865ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
9874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
98935237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    bootchart_count = bootchart_init();
99035237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (bootchart_count < 0) {
9914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("bootcharting init failure\n");
99235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (bootchart_count > 0) {
99335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
99435237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
99535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting ignored\n");
9964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
9984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for(;;) {
10005ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        int nr, i, timeout = -1;
10014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10025ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < fd_count; i++)
10035ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ufds[i].revents = 0;
10044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
10064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        restart_processes();
10074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (process_needs_restart) {
10094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            timeout = (process_needs_restart - gettime()) * 1000;
10104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0)
10114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = 0;
10124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
10154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bootchart_count > 0) {
10164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
10174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = BOOTCHART_POLLING_MS;
10184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (bootchart_step() < 0 || --bootchart_count == 0) {
10194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_finish();
10204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_count = 0;
10214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
10224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
10245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        nr = poll(ufds, fd_count, timeout);
10254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (nr <= 0)
10264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
10274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[2].revents == POLLIN) {
10294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* we got a SIGCHLD - reap and restart as needed */
10304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            read(signal_recv_fd, tmp, sizeof(tmp));
10314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (!wait_for_one_process(0))
10324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ;
10334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
10344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
10354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[0].revents == POLLIN)
10374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_device_fd(device_fd);
10384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[1].revents == POLLIN)
10404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_property_set_fd(property_set_fd);
10415ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (ufds[3].revents == POLLIN)
10425ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            handle_keychord(keychord_fd);
10434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
10444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
10454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
10464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1047