init.c revision 5ae090ed949cea9d1e7ab1552b455a229f8f9757
14f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
24f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
34f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
44f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
54f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * you may not use this file except in compliance with the License.
64f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * You may obtain a copy of the License at
74f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
84f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
94f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project *
104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * See the License for the specific language governing permissions and
144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * limitations under the License.
154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdio.h>
184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdlib.h>
194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <string.h>
204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <unistd.h>
214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <fcntl.h>
224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <ctype.h>
234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <signal.h>
244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/wait.h>
254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/mount.h>
264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/stat.h>
274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/poll.h>
284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <time.h>
294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <errno.h>
304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <stdarg.h>
314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <mtd/mtd-user.h>
324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/types.h>
334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/socket.h>
344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/un.h>
354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/reboot.h>
364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <cutils/sockets.h>
384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <termios.h>
394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <linux/kd.h>
405ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project#include <linux/keychord.h>
414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include <sys/system_properties.h>
434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "devices.h"
454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "init.h"
464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#include "property_service.h"
4735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project#include "bootchart.h"
484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int property_triggers_enabled = 0;
504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int   bootchart_count;
534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char console[32];
564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char serialno[32];
574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootmode[32];
584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char baseband[32];
594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char carrier[32];
604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char bootloader[32];
614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char hardware[32];
624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic unsigned revision = 0;
634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char qemu[32];
645ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic struct input_keychord *keychords = 0;
655ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic int keychords_count = 0;
665ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectstatic int keychords_length = 0;
674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void drain_action_queue(void);
694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void notify_service_state(const char *name, const char *state)
714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char pname[PROP_NAME_MAX];
734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int len = strlen(name);
744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((len + 10) > PROP_NAME_MAX)
754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(pname, sizeof(pname), "init.svc.%s", name);
774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set(pname, state);
784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int have_console;
814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic char *console_name = "/dev/console";
824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t process_needs_restart;
834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic const char *ENV[32];
854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/* add_environment - add "key=value" to the current environment */
874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint add_environment(const char *key, const char *val)
884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < 31; n++) {
924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!ENV[n]) {
934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            size_t len = strlen(key) + strlen(val) + 2;
944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *entry = malloc(len);
954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            snprintf(entry, len, "%s=%s", key, val);
964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ENV[n] = entry;
974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return 0;
984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 1;
1024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void zap_stdio(void)
1054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/dev/null", O_RDWR);
1084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void open_console()
1154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
1174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((fd = open(console_name, O_RDWR)) < 0) {
1184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open("/dev/null", O_RDWR);
1194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 0);
1214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 1);
1224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    dup2(fd, 2);
1234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
1244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project/*
1274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * gettime() - returns the time in seconds of the system's monotonic clock or
1284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project * zero on error.
1294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project */
1304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic time_t gettime(void)
1314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct timespec ts;
1334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
1344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ret = clock_gettime(CLOCK_MONOTONIC, &ts);
1364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (ret < 0) {
1374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
1384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
1394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return ts.tv_sec;
1424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void publish_socket(const char *name, int fd)
1454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char key[64] = ANDROID_SOCKET_ENV_PREFIX;
1474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char val[64];
1484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
1504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            name,
1514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
1524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(val, sizeof(val), "%d", fd);
1534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    add_environment(key, val);
1544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we don't close-on-exec */
1564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fcntl(fd, F_SETFD, 0);
1574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
1584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_start(struct service *svc)
1604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
1614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct stat s;
1624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
1634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int needs_console;
1644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
1654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* starting a service removes it from the disabled
1674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state and immediately takes it out of the restarting
1684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * state if it was in there
1694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
1714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = 0;
1724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* running processes require no additional work -- if
1744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they're in the process of exiting, we've ensured
1754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that they will immediately restart on exit, unless
1764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * they are ONESHOT
1774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
1784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_RUNNING) {
1794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
1834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (needs_console && (!have_console)) {
1844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("service '%s' requires console\n", svc->name);
1854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (stat(svc->args[0], &s) != 0) {
1904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
1914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
1924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
1934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
1944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("starting '%s'\n", svc->name);
1964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid = fork();
1984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
1994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid == 0) {
2004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct socketinfo *si;
2014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        struct svcenvinfo *ei;
2024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[32];
2034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int fd, sz;
2044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        get_property_workspace(&fd, &sz);
2064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        sprintf(tmp, "%d,%d", dup(fd), sz);
2074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
2084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (ei = svc->envvars; ei; ei = ei->next)
2104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            add_environment(ei->name, ei->value);
2114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (si = svc->sockets; si; si = si->next) {
2134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            int s = create_socket(si->name,
2144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  !strcmp(si->type, "dgram") ?
2154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  SOCK_DGRAM : SOCK_STREAM,
2164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                                  si->perm, si->uid, si->gid);
2174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (s >= 0) {
2184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                publish_socket(si->name, s);
2194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
2204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (needs_console) {
2234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setsid();
2244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            open_console();
2254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
2264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            zap_stdio();
2274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if 0
2304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; svc->args[n]; n++) {
2314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("args[%d] = '%s'\n", n, svc->args[n]);
2324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        for (n = 0; ENV[n]; n++) {
2344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("env[%d] = '%s'\n", n, ENV[n]);
2354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
2374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        setpgid(0, getpid());
2394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2405ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* as requested, set our gid, supplemental gids, and uid */
2414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->gid) {
2424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgid(svc->gid);
2434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->nr_supp_gids) {
2454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setgroups(svc->nr_supp_gids, svc->supp_gids);
2464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->uid) {
2484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            setuid(svc->uid);
2494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
2504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        execve(svc->args[0], (char**) svc->args, (char**) ENV);
2524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        _exit(127);
2534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid < 0) {
2564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("failed to start '%s'\n", svc->name);
2574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->pid = 0;
2584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
2594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->time_started = gettime();
2624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = pid;
2634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RUNNING;
2644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "running");
2664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid service_stop(struct service *svc)
2694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* we are no longer running, nor should we
2714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * attempt to restart
2724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
2744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* if the service has not yet started, prevent
2764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * it from auto-starting with its class
2774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
2784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_DISABLED;
2794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->pid) {
2814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("service '%s' is being killed\n", svc->name);
2824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-svc->pid, SIGTERM);
2834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopping");
2844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
2854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
2864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid property_changed(const char *name, const char *value)
2904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
2914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (property_triggers_enabled) {
2924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        queue_property_triggers(name, value);
2934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
2944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
2954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
2964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
2974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
2984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
2994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int wait_for_one_process(int block)
3014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pid_t pid;
3034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int status;
3044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc;
3054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct socketinfo *si;
3064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t now;
3074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
3084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
3094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
3114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (pid <= 0) return -1;
3124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("waitpid returned pid %d, status = %08x\n", pid, status);
3134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc = service_find_by_pid(pid);
3154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!svc) {
3164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("untracked pid %d exited\n", pid);
3174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    NOTICE("process '%s', pid %d exited\n", svc->name, pid);
3214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!(svc->flags & SVC_ONESHOT)) {
3234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        kill(-pid, SIGKILL);
3244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        NOTICE("process '%s' killing any children in process group\n", svc->name);
3254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* remove any sockets we may have created */
3284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (si = svc->sockets; si; si = si->next) {
3294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char tmp[128];
3304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
3314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(tmp);
3324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->pid = 0;
3354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags &= (~SVC_RUNNING);
3364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* oneshot processes go into the disabled state on exit */
3384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_ONESHOT) {
3394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags |= SVC_DISABLED;
3404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* disabled processes do not get restarted automatically */
3434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_DISABLED) {
3444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        notify_service_state(svc->name, "stopped");
3454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 0;
3464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    now = gettime();
3494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc->flags & SVC_CRITICAL) {
3504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
3514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
3524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("critical process '%s' exited %d times in %d minutes; "
3534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      "rebooting into recovery mode\n", svc->name,
3544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                      CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
3554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                sync();
3564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
3574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                         LINUX_REBOOT_CMD_RESTART2, "recovery");
3584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                return 0;
3594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
3604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
3614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->time_crashed = now;
3624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            svc->nr_crashed = 1;
3634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
3644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Execute all onrestart commands for this service. */
3674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    list_for_each(node, &svc->onrestart.commands) {
3684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd = node_to_item(node, struct command, clist);
3694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmd->func(cmd->nargs, cmd->args);
3704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    svc->flags |= SVC_RESTARTING;
3724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    notify_service_state(svc->name, "restarting");
3734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
3744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_service_if_needed(struct service *svc)
3774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    time_t next_start_time = svc->time_started + 5;
3794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (next_start_time <= gettime()) {
3814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        svc->flags &= (~SVC_RESTARTING);
3824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_start(svc);
3834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
3844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((next_start_time < process_needs_restart) ||
3874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (process_needs_restart == 0)) {
3884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        process_needs_restart = next_start_time;
3894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
3904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void restart_processes()
3934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
3944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    process_needs_restart = 0;
3954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    service_for_each_flags(SVC_RESTARTING,
3964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                           restart_service_if_needed);
3974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
3984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
3994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int signal_fd = -1;
4004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void sigchld_handler(int s)
4024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    write(signal_fd, &s, 1);
4044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_start(const char *name)
4074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_start(svc);
4124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n", name);
4144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void msg_stop(const char *name)
4184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct service *svc = service_find_by_name(name);
4204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (svc) {
4224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        service_stop(svc);
4234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("no such service '%s'\n");
4254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid handle_control_message(const char *msg, const char *arg)
4294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(msg,"start")) {
4314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_start(arg);
4324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else if (!strcmp(msg,"stop")) {
4334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        msg_stop(arg);
4344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
4354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("unknown control msg '%s'\n", msg);
4364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#define MAX_MTD_PARTITIONS 16
4404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic struct {
4424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char name[16];
4434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int number;
4444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project} mtd_part_map[MAX_MTD_PARTITIONS];
4454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic int mtd_part_count = -1;
4474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void find_mtd_partitions(void)
4494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
4514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char buf[1024];
4524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *pmtdbufp;
4534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ssize_t pmtdsize;
4544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int r;
4554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/mtd", O_RDONLY);
4574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0)
4584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
4594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    buf[sizeof(buf) - 1] = '\0';
4614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdsize = read(fd, buf, sizeof(buf) - 1);
4624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    pmtdbufp = buf;
4634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (pmtdsize > 0) {
4644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int mtdnum, mtdsize, mtderasesize;
4654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char mtdname[16];
4664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdname[0] = '\0';
4674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtdnum = -1;
4684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
4694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                   &mtdnum, &mtdsize, &mtderasesize, mtdname);
4704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if ((r == 4) && (mtdname[0] == '"')) {
4714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            char *x = strchr(mtdname + 1, '"');
4724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (x) {
4734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                *x = 0;
4744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
4764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (mtd_part_count < MAX_MTD_PARTITIONS) {
4774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
4784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_map[mtd_part_count].number = mtdnum;
4794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                mtd_part_count++;
4804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            } else {
4814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ERROR("too many mtd partitions\n");
4824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
4834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        while (pmtdsize > 0 && *pmtdbufp != '\n') {
4854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
4864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
4874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (pmtdsize > 0) {
4894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdbufp++;
4904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            pmtdsize--;
4914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
4924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
4934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
4944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
4954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
4964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint mtd_name_to_number(const char *name)
4974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
4984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int n;
4994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mtd_part_count < 0) {
5004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        mtd_part_count = 0;
5014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        find_mtd_partitions();
5024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for (n = 0; n < mtd_part_count; n++) {
5044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name, mtd_part_map[n].name)) {
5054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return mtd_part_map[n].number;
5064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return -1;
5094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_nv(char *name, int in_qemu)
5124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *value = strchr(name, '=');
5144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (value == 0) return;
5164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    *value++ = 0;
5174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (*name == 0) return;
5184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!in_qemu)
5204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    {
5214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* on a real device, white-list the kernel options */
5224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (!strcmp(name,"qemu")) {
5234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(qemu, value, sizeof(qemu));
5244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.console")) {
5254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(console, value, sizeof(console));
5264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.mode")) {
5274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootmode, value, sizeof(bootmode));
5284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.serialno")) {
5294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(serialno, value, sizeof(serialno));
5304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.baseband")) {
5314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(baseband, value, sizeof(baseband));
5324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.carrier")) {
5334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(carrier, value, sizeof(carrier));
5344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.bootloader")) {
5354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(bootloader, value, sizeof(bootloader));
5364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else if (!strcmp(name,"androidboot.hardware")) {
5374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            strlcpy(hardware, value, sizeof(hardware));
5384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        } else {
5394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            qemu_cmdline(name, value);
5404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* in the emulator, export any kernel option with the
5434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * ro.kernel. prefix */
5444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char  buff[32];
5454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int   len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
5464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (len < (int)sizeof(buff)) {
5474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            property_set( buff, value );
5484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
5494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void import_kernel_cmdline(int in_qemu)
5534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char cmdline[1024];
5554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *ptr;
5564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
5574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cmdline", O_RDONLY);
5594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0) {
5604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        int n = read(fd, cmdline, 1023);
5614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n < 0) n = 0;
5624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* get rid of trailing newline, it happens */
5644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (n > 0 && cmdline[n-1] == '\n') n--;
5654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[n] = 0;
5674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        close(fd);
5684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    } else {
5694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        cmdline[0] = 0;
5704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ptr = cmdline;
5734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while (ptr && *ptr) {
5744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        char *x = strchr(ptr, ' ');
5754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x != 0) *x++ = 0;
5764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_nv(ptr, in_qemu);
5774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ptr = x;
5784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
5794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* don't expose the raw commandline to nonpriv processes */
5814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    chmod("/proc/cmdline", 0440);
5824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
5834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void get_hardware_name(void)
5854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
5864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char data[1024];
5874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd, n;
5884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *x, *hw, *rev;
5894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* Hardware string was provided on kernel command line */
5914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hardware[0])
5924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return;
5934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open("/proc/cpuinfo", O_RDONLY);
5954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd < 0) return;
5964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
5974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    n = read(fd, data, 1023);
5984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
5994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (n < 0) return;
6004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    data[n] = 0;
6024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    hw = strstr(data, "\nHardware");
6034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    rev = strstr(data, "\nRevision");
6044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (hw) {
6064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(hw, ": ");
6074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            x += 2;
6094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            n = 0;
6104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (*x && !isspace(*x)) {
6114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                hardware[n++] = tolower(*x);
6124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                x++;
6134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                if (n == 31) break;
6144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            hardware[n] = 0;
6164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (rev) {
6204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        x = strstr(rev, ": ");
6214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (x) {
6224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            revision = strtoul(x + 2, 0, 16);
6234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectstatic void drain_action_queue(void)
6284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct listnode *node;
6304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct command *cmd;
6314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct action *act;
6324f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int ret;
6334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    while ((act = action_remove_queue_head())) {
6354f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        INFO("processing action %p (%s)\n", act, act->name);
6364f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        list_for_each(node, &act->commands) {
6374f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            cmd = node_to_item(node, struct command, clist);
6384f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            ret = cmd->func(cmd->nargs, cmd->args);
6394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            INFO("command '%s' r=%d\n", cmd->args[0], ret);
6404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6434f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectvoid open_devnull_stdio(void)
6454f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
6464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
6474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    static const char *name = "/dev/__null__";
6484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
6494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fd = open(name, O_RDWR);
6504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        unlink(name);
6514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (fd >= 0) {
6524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 0);
6534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 1);
6544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            dup2(fd, 2);
6554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (fd > 2) {
6564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                close(fd);
6574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
6584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            return;
6594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
6604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
6614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    exit(1);
6634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
6644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
6655ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectvoid add_service_keycodes(struct service *svc)
6665ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
6675ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    struct input_keychord *keychord;
6685ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int i, size;
6695ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
6705ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (svc->keycodes) {
6715ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        /* add a new keychord to the list */
6725ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
6735ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords = realloc(keychords, keychords_length + size);
6745ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (!keychords) {
6755ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ERROR("could not allocate keychords\n");
6765ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychords_length = 0;
6775ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychords_count = 0;
6785ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            return;
6795ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        }
6805ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
6815ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord = (struct input_keychord *)((char *)keychords + keychords_length);
6825ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->version = KEYCHORD_VERSION;
6835ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->id = keychords_count + 1;
6845ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord->count = svc->nkeycodes;
6855ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        svc->keychord_id = keychord->id;
6865ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
6875ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < svc->nkeycodes; i++) {
6885ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            keychord->keycodes[i] = svc->keycodes[i];
6895ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        }
6905ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords_count++;
6915ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychords_length += size;
6925ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
6935ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
6945ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
6955ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectint open_keychord()
6965ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
6975ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd, ret;
6985ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
6995ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    service_for_each(add_service_keycodes);
7005ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7015ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    /* nothing to do if no services require keychords */
7025ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (!keychords)
7035ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        return -1;
7045ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7055ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/keychord", O_RDWR);
7065ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd < 0) {
7075ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("could not open /dev/keychord\n");
7085ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        return fd;
7095ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7105ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fcntl(fd, F_SETFD, FD_CLOEXEC);
7115ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7125ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    ret = write(fd, keychords, keychords_length);
7135ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (ret != keychords_length) {
7145ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
7155ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
7165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd = -1;
7175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7185ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7195ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    free(keychords);
7205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    keychords = 0;
7215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7225ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    return fd;
7235ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
7245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7255ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Projectvoid handle_keychord(int fd)
7265ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project{
7275ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    struct service *svc;
7285ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int ret;
7295ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    __u16 id;
7305ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7315ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    ret = read(fd, &id, sizeof(id));
7325ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (ret != sizeof(id)) {
7335ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("could not read keychord id\n");
7345ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        return;
7355ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7365ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    svc = service_find_by_keychord(id);
7385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (svc) {
7395ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        INFO("starting service %s from keychord\n", svc->name);
7405ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        service_start(svc);
7415ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    } else {
7425ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ERROR("service for keychord %d not found\n", id);
7435ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
7445ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project}
7455ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
7464f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Projectint main(int argc, char **argv)
7474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project{
7484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int device_fd = -1;
7494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int property_set_fd = -1;
7504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int signal_recv_fd = -1;
7515ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int keychord_fd = -1;
7525ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    int fd_count;
7534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int s[2];
7544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    int fd;
7554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct sigaction act;
7564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char tmp[PROP_VALUE_MAX];
7574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    struct pollfd ufds[4];
7584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    char *tmpdev;
7595ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    char* debuggable;
7604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_handler = sigchld_handler;
7624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_flags = SA_NOCLDSTOP;
7634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_mask = 0;
7644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    act.sa_restorer = NULL;
7654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    sigaction(SIGCHLD, &act, 0);
7664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* clear the umask */
7684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    umask(0);
7694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* Get the basic filesystem setup we need put
7714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * together in the initramdisk on / and then we'll
7724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * let the rc file figure out the rest.
7734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
7744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev", 0755);
7754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/proc", 0755);
7764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/sys", 0755);
7774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
7794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/pts", 0755);
7804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mkdir("/dev/socket", 0755);
7814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("devpts", "/dev/pts", "devpts", 0, NULL);
7824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("proc", "/proc", "proc", 0, NULL);
7834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    mount("sysfs", "/sys", "sysfs", 0, NULL);
7844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* We must have some place other than / to create the
7864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * device nodes for kmsg and null, otherwise we won't
7874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * be able to remount / read-only later on.
7884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * Now that tmpfs is mounted on /dev, we can actually
7894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * talk to the outside world.
7904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
7914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    open_devnull_stdio();
7924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    log_init();
7934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("reading config file\n");
7954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file("/init.rc");
7964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
7974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* pull the kernel commandline and ramdisk properties file in */
7984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    qemu_init();
7994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    import_kernel_cmdline(0);
8004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    get_hardware_name();
8024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
8034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    parse_config_file(tmp);
8044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-init", action_add_queue_tail);
8064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    INFO("device init\n");
8094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    device_fd = device_init();
8104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_init();
8125ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
8135ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    // only listen for keychords if ro.debuggable is true
8145ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    debuggable = property_get("ro.debuggable");
8155ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (debuggable && !strcmp(debuggable, "1")) {
8165ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        keychord_fd = open_keychord();
8175ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
8184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (console[0]) {
8204f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        snprintf(tmp, sizeof(tmp), "/dev/%s", console);
8214f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        console_name = strdup(tmp);
8224f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8234f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8244f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    fd = open(console_name, O_RDWR);
8254f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (fd >= 0)
8264f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        have_console = 1;
8274f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    close(fd);
8284f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8294f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if( load_565rle_image(INIT_IMAGE_FILE) ) {
8305ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd = open("/dev/tty0", O_WRONLY);
8315ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (fd >= 0) {
8325ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        const char *msg;
8334f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            msg = "\n"
8345ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8355ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8365ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8375ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8385ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8395ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"  // console is 40 cols x 30 lines
8405ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8415ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8425ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8435ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8445ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8455ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8465ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "\n"
8475ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        "             A N D R O I D ";
8485ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        write(fd, msg, strlen(msg));
8495ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        close(fd);
8505ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
8514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (qemu[0])
8544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        import_kernel_cmdline(1);
8554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (!strcmp(bootmode,"factory"))
8574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "1");
8584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else if (!strcmp(bootmode,"factory2"))
8594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "2");
8604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    else
8614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        property_set("ro.factorytest", "0");
8624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.serialno", serialno[0] ? serialno : "");
8644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
8654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.baseband", baseband[0] ? baseband : "unknown");
8664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.carrier", carrier[0] ? carrier : "unknown");
8674f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
8684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.hardware", hardware);
8704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
8714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set("ro.revision", tmp);
8724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* execute all the boot actions to get us started */
8744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("init", action_add_queue_tail);
8754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
8764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* read any property files on system or data and
8784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * fire up the property service.  This must happen
8794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * after the ro.foo properties are set above so
8804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         * that /data/local.prop cannot interfere with them.
8814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project         */
8824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_set_fd = start_property_service();
8834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8844f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* create a signalling mechanism for the sigchld handler */
8854f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
8864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_fd = s[0];
8874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        signal_recv_fd = s[1];
8884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFD, FD_CLOEXEC);
8894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[0], F_SETFL, O_NONBLOCK);
8904f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFD, FD_CLOEXEC);
8914f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        fcntl(s[1], F_SETFL, O_NONBLOCK);
8924f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
8934f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
8944f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* make sure we actually have all the pieces we need */
8954f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    if ((device_fd < 0) ||
8964f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (property_set_fd < 0) ||
8974f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        (signal_recv_fd < 0)) {
8984f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("init startup failure\n");
8994f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        return 1;
9004f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9014f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9024f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    /* execute all the boot actions to get us started */
9034f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("early-boot", action_add_queue_tail);
9044f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    action_for_each_trigger("boot", action_add_queue_tail);
9054f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
9064f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9074f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* run all property triggers based on current state of the properties */
9084f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    queue_all_property_triggers();
9094f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    drain_action_queue();
9104f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9114f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        /* enable property triggers */
9124f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    property_triggers_enabled = 1;
9134f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9144f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].fd = device_fd;
9154f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[0].events = POLLIN;
9164f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].fd = property_set_fd;
9174f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[1].events = POLLIN;
9184f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].fd = signal_recv_fd;
9194f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    ufds[2].events = POLLIN;
9205ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    fd_count = 3;
9215ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project
9225ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    if (keychord_fd > 0) {
9235ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].fd = keychord_fd;
9245ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = POLLIN;
9255ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        fd_count++;
9265ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    } else {
9275ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].events = 0;
9285ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        ufds[3].revents = 0;
9295ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project    }
9304f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9314f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
93235237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    bootchart_count = bootchart_init();
93335237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    if (bootchart_count < 0) {
9344f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        ERROR("bootcharting init failure\n");
93535237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else if (bootchart_count > 0) {
93635237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
93735237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project    } else {
93835237d135807af84bf9b0e5b8d7f8633e58db6f5The Android Open Source Project        NOTICE("bootcharting ignored\n");
9394f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9404f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
9414f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9424f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    for(;;) {
9435ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        int nr, i, timeout = -1;
9444f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9455ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        for (i = 0; i < fd_count; i++)
9465ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            ufds[i].revents = 0;
9474f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9484f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        drain_action_queue();
9494f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        restart_processes();
9504f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9514f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (process_needs_restart) {
9524f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            timeout = (process_needs_restart - gettime()) * 1000;
9534f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0)
9544f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = 0;
9554f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
9564f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9574f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#if BOOTCHART
9584f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (bootchart_count > 0) {
9594f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
9604f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                timeout = BOOTCHART_POLLING_MS;
9614f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            if (bootchart_step() < 0 || --bootchart_count == 0) {
9624f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_finish();
9634f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                bootchart_count = 0;
9644f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            }
9654f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
9664f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project#endif
9675ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        nr = poll(ufds, fd_count, timeout);
9684f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (nr <= 0)
9694f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
9704f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9714f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[2].revents == POLLIN) {
9724f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            /* we got a SIGCHLD - reap and restart as needed */
9734f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            read(signal_recv_fd, tmp, sizeof(tmp));
9744f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            while (!wait_for_one_process(0))
9754f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project                ;
9764f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            continue;
9774f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        }
9784f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9794f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[0].revents == POLLIN)
9804f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_device_fd(device_fd);
9814f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9824f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project        if (ufds[1].revents == POLLIN)
9834f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project            handle_property_set_fd(property_set_fd);
9845ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project        if (ufds[3].revents == POLLIN)
9855ae090ed949cea9d1e7ab1552b455a229f8f9757The Android Open Source Project            handle_keychord(keychord_fd);
9864f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    }
9874f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project
9884f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project    return 0;
9894f6e8d7a00cbeda1e70cc15be9c4af1018bdad5The Android Open Source Project}
990