summaryrefslogtreecommitdiffstats
path: root/init
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:29:04 -0800
commite54eebbf1a908d65ee8cf80bab62821c05666d70 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /init
parenta1e1c1b106423de09bc918502e7a51d4ffe5a4ae (diff)
downloadcore-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.gz
core-e54eebbf1a908d65ee8cf80bab62821c05666d70.tar.bz2
core-e54eebbf1a908d65ee8cf80bab62821c05666d70.zip
auto import from //depot/cupcake/@135843
Diffstat (limited to 'init')
-rw-r--r--init/Android.mk33
-rw-r--r--init/MODULE_LICENSE_APACHE20
-rw-r--r--init/NOTICE190
-rw-r--r--init/README.BOOTCHART52
-rw-r--r--init/bootchart.c378
-rw-r--r--init/bootchart.h36
-rw-r--r--init/builtins.c442
-rw-r--r--init/devices.c626
-rw-r--r--init/devices.h27
-rwxr-xr-xinit/grab-bootchart.sh22
-rw-r--r--init/init.c989
-rw-r--r--init/init.h174
-rw-r--r--init/keywords.h78
-rw-r--r--init/logo.c163
-rw-r--r--init/parser.c797
-rw-r--r--init/property_service.c502
-rw-r--r--init/property_service.h28
-rw-r--r--init/readme.txt293
-rw-r--r--init/util.c211
19 files changed, 0 insertions, 5041 deletions
diff --git a/init/Android.mk b/init/Android.mk
deleted file mode 100644
index d3766d455..000000000
--- a/init/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-# Copyright 2005 The Android Open Source Project
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES:= \
- builtins.c \
- init.c \
- devices.c \
- property_service.c \
- util.c \
- parser.c \
- logo.c
-
-ifeq ($(strip $(INIT_BOOTCHART)),true)
-LOCAL_SRC_FILES += bootchart.c
-LOCAL_CFLAGS += -DBOOTCHART=1
-endif
-
-LOCAL_MODULE:= init
-
-LOCAL_FORCE_STATIC_EXECUTABLE := true
-LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT)
-LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED)
-
-LOCAL_STATIC_LIBRARIES := libcutils libc
-
-#LOCAL_STATIC_LIBRARIES := libcutils libc libminui libpixelflinger_static
-#LOCAL_STATIC_LIBRARIES += libminzip libunz libamend libmtdutils libmincrypt
-#LOCAL_STATIC_LIBRARIES += libstdc++_static
-
-include $(BUILD_EXECUTABLE)
-
diff --git a/init/MODULE_LICENSE_APACHE2 b/init/MODULE_LICENSE_APACHE2
deleted file mode 100644
index e69de29bb..000000000
--- a/init/MODULE_LICENSE_APACHE2
+++ /dev/null
diff --git a/init/NOTICE b/init/NOTICE
deleted file mode 100644
index c5b1efa7a..000000000
--- a/init/NOTICE
+++ /dev/null
@@ -1,190 +0,0 @@
-
- Copyright (c) 2005-2008, The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
diff --git a/init/README.BOOTCHART b/init/README.BOOTCHART
deleted file mode 100644
index 70cf2c39b..000000000
--- a/init/README.BOOTCHART
+++ /dev/null
@@ -1,52 +0,0 @@
-This version of init contains code to perform "bootcharting", i.e. generating log
-files that can be later processed by the tools provided by www.bootchart.org.
-
-To activate it, you need to define build 'init' with the INIT_BOOTCHART environment
-variable defined to 'true', for example:
-
- touch system/init/init.c
- m INIT_BOOTCHART=true
-
-On the emulator, use the new -bootchart <timeout> option to boot with bootcharting
-activated for <timeout> seconds.
-
-Otherwise, flash your device, and start it. Then create a file on the /data partition
-with a command like the following:
-
- adb shell 'echo $TIMEOUT > /data/bootchart-start'
-
-Where the value of $TIMEOUT corresponds to the wanted bootcharted period in seconds;
-for example, to bootchart for 2 minutes, do:
-
- adb shell 'echo 120 > /data/bootchart-start'
-
-Reboot your device, bootcharting will begin and stop after the period you gave.
-You can also stop the bootcharting at any moment by doing the following:
-
- adb shell 'echo 1 > /data/bootchart-stop'
-
-Note that /data/bootchart-stop is deleted automatically by init at the end of the
-bootcharting. This is not the case of /data/bootchart-start, so don't forget to delete it
-when you're done collecting data:
-
- adb shell rm /data/bootchart-start
-
-The log files are placed in /data/bootchart/. you must run the script tools/grab-bootchart.sh
-which will use ADB to retrieve them and create a bootchart.tgz file that can be used with
-the bootchart parser/renderer, or even uploaded directly to the form located at:
-
- http://www.bootchart.org/download.html
-
-NOTE: the bootchart.org webform doesn't seem to work at the moment, you can generate an
- image on your machine by doing the following:
-
- 1/ download the sources from www.bootchart.org
- 2/ unpack them
- 3/ in the source directory, type 'ant' to build the bootchart program
- 4/ type 'java -jar bootchart.jar /path/to/bootchart.tgz
-
-technical note:
-
-this implementation of bootcharting does use the 'bootchartd' script provided by
-www.bootchart.org, but a C re-implementation that is directly compiled into our init
-program.
diff --git a/init/bootchart.c b/init/bootchart.c
deleted file mode 100644
index f72fcaaca..000000000
--- a/init/bootchart.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-/* this code is used to generate a boot sequence profile that can be used
- * with the 'bootchart' graphics generation tool. see www.bootchart.org
- * note that unlike the original bootchartd, this is not a Bash script but
- * some C code that is run right from the init script.
- */
-
-#include <stdio.h>
-#include <time.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include "bootchart.h"
-
-#define VERSION "0.8"
-#define SAMPLE_PERIOD 0.2
-#define LOG_ROOT "/data/bootchart"
-#define LOG_STAT LOG_ROOT"/proc_stat.log"
-#define LOG_PROCS LOG_ROOT"/proc_ps.log"
-#define LOG_DISK LOG_ROOT"/proc_diskstats.log"
-#define LOG_HEADER LOG_ROOT"/header"
-#define LOG_ACCT LOG_ROOT"/kernel_pacct"
-
-#define LOG_STARTFILE "/data/bootchart-start"
-#define LOG_STOPFILE "/data/bootchart-stop"
-
-static int
-unix_read(int fd, void* buff, int len)
-{
- int ret;
- do { ret = read(fd, buff, len); } while (ret < 0 && errno == EINTR);
- return ret;
-}
-
-static int
-unix_write(int fd, const void* buff, int len)
-{
- int ret;
- do { ret = write(fd, buff, len); } while (ret < 0 && errno == EINTR);
- return ret;
-}
-
-static int
-proc_read(const char* filename, char* buff, size_t buffsize)
-{
- int len = 0;
- int fd = open(filename, O_RDONLY);
- if (fd >= 0) {
- len = unix_read(fd, buff, buffsize-1);
- close(fd);
- }
- buff[len > 0 ? len : 0] = 0;
- return len;
-}
-
-#define FILE_BUFF_SIZE 65536
-
-typedef struct {
- int count;
- int fd;
- char data[FILE_BUFF_SIZE];
-} FileBuffRec, *FileBuff;
-
-static void
-file_buff_open( FileBuff buff, const char* path )
-{
- buff->count = 0;
- buff->fd = open(path, O_WRONLY|O_CREAT|O_TRUNC, 0755);
-}
-
-static void
-file_buff_write( FileBuff buff, const void* src, int len )
-{
- while (len > 0) {
- int avail = sizeof(buff->data) - buff->count;
- if (avail > len)
- avail = len;
-
- memcpy( buff->data + buff->count, src, avail );
- len -= avail;
- src = (char*)src + avail;
-
- buff->count += avail;
- if (buff->count == FILE_BUFF_SIZE) {
- unix_write( buff->fd, buff->data, buff->count );
- buff->count = 0;
- }
- }
-}
-
-static void
-file_buff_done( FileBuff buff )
-{
- if (buff->count > 0) {
- unix_write( buff->fd, buff->data, buff->count );
- buff->count = 0;
- }
-}
-
-static void
-log_header(void)
-{
- FILE* out;
- char cmdline[1024];
- char uname[128];
- char cpuinfo[128];
- char* cpu;
- char date[32];
- time_t now_t = time(NULL);
- struct tm now = *localtime(&now_t);
- strftime(date, sizeof(date), "%x %X", &now);
-
- out = fopen( LOG_HEADER, "w" );
- if (out == NULL)
- return;
-
- proc_read("/proc/cmdline", cmdline, sizeof(cmdline));
- proc_read("/proc/version", uname, sizeof(uname));
- proc_read("/proc/cpuinfo", cpuinfo, sizeof(cpuinfo));
-
- cpu = strchr( cpuinfo, ':' );
- if (cpu) {
- char* p = strchr(cpu, '\n');
- cpu += 2;
- if (p)
- *p = 0;
- }
-
- fprintf(out, "version = %s\n", VERSION);
- fprintf(out, "title = Boot chart for Android ( %s )\n", date);
- fprintf(out, "system.uname = %s\n", uname);
- fprintf(out, "system.release = 0.0\n");
- fprintf(out, "system.cpu = %s\n", cpu);
- fprintf(out, "system.kernel.options = %s\n", cmdline);
- fclose(out);
-}
-
-static void
-close_on_exec(int fd)
-{
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-}
-
-static void
-open_log_file(int* plogfd, const char* logfile)
-{
- int logfd = *plogfd;
-
- /* create log file if needed */
- if (logfd < 0)
- {
- logfd = open(logfile,O_WRONLY|O_CREAT|O_TRUNC,0755);
- if (logfd < 0) {
- *plogfd = -2;
- return;
- }
- close_on_exec(logfd);
- *plogfd = logfd;
- }
-}
-
-static void
-do_log_uptime(FileBuff log)
-{
- char buff[65];
- int fd, ret, len;
-
- fd = open("/proc/uptime",O_RDONLY);
- if (fd >= 0) {
- int ret;
- ret = unix_read(fd, buff, 64);
- close(fd);
- buff[64] = 0;
- if (ret >= 0) {
- long long jiffies = 100LL*strtod(buff,NULL);
- int len;
- snprintf(buff,sizeof(buff),"%lld\n",jiffies);
- len = strlen(buff);
- file_buff_write(log, buff, len);
- }
- }
-}
-
-static void
-do_log_ln(FileBuff log)
-{
- file_buff_write(log, "\n", 1);
-}
-
-
-static void
-do_log_file(FileBuff log, const char* procfile)
-{
- char buff[1024];
- int fd;
-
- do_log_uptime(log);
-
- /* append file content */
- fd = open(procfile,O_RDONLY);
- if (fd >= 0) {
- close_on_exec(fd);
- for (;;) {
- int ret;
- ret = unix_read(fd, buff, sizeof(buff));
- if (ret <= 0)
- break;
-
- file_buff_write(log, buff, ret);
- if (ret < (int)sizeof(buff))
- break;
- }
- close(fd);
- }
-
- do_log_ln(log);
-}
-
-static void
-do_log_procs(FileBuff log)
-{
- DIR* dir = opendir("/proc");
- struct dirent* entry;
-
- do_log_uptime(log);
-
- while ((entry = readdir(dir)) != NULL) {
- /* only match numeric values */
- char* end;
- int pid = strtol( entry->d_name, &end, 10);
- if (end != NULL && end > entry->d_name && *end == 0) {
- char filename[32];
- char buff[1024];
- char cmdline[1024];
- int len;
- int fd;
-
- /* read command line and extract program name */
- snprintf(filename,sizeof(filename),"/proc/%d/cmdline",pid);
- proc_read(filename, cmdline, sizeof(cmdline));
-
- /* read process stat line */
- snprintf(filename,sizeof(filename),"/proc/%d/stat",pid);
- fd = open(filename,O_RDONLY);
- if (fd >= 0) {
- len = unix_read(fd, buff, sizeof(buff)-1);
- close(fd);
- if (len > 0) {
- int len2 = strlen(cmdline);
- if (len2 > 0) {
- /* we want to substitute the process name with its real name */
- const char* p1;
- const char* p2;
- buff[len] = 0;
- p1 = strchr(buff, '(');
- p2 = strchr(p1, ')');
- file_buff_write(log, buff, p1+1-buff);
- file_buff_write(log, cmdline, strlen(cmdline));
- file_buff_write(log, p2, strlen(p2));
- } else {
- /* no substitution */
- file_buff_write(log,buff,len);
- }
- }
- }
- }
- }
- closedir(dir);
- do_log_ln(log);
-}
-
-static FileBuffRec log_stat[1];
-static FileBuffRec log_procs[1];
-static FileBuffRec log_disks[1];
-
-/* called to setup bootcharting */
-int bootchart_init( void )
-{
- int ret;
- char buff[4];
- int timeout = 0, count = 0;
-
- buff[0] = 0;
- proc_read( LOG_STARTFILE, buff, sizeof(buff) );
- if (buff[0] != 0) {
- timeout = atoi(buff);
- }
- else {
- /* when running with emulator, androidboot.bootchart=<timeout>
- * might be passed by as kernel parameters to specify the bootchart
- * timeout. this is useful when using -wipe-data since the /data
- * partition is fresh
- */
- char cmdline[1024];
- char* s;
-#define KERNEL_OPTION "androidboot.bootchart="
- proc_read( "/proc/cmdline", cmdline, sizeof(cmdline) );
- s = strstr(cmdline, KERNEL_OPTION);
- if (s) {
- s += sizeof(KERNEL_OPTION)-1;
- timeout = atoi(s);
- }
- }
- if (timeout == 0)
- return 0;
-
- if (timeout > BOOTCHART_MAX_TIME_SEC)
- timeout = BOOTCHART_MAX_TIME_SEC;
-
- count = (timeout*1000 + BOOTCHART_POLLING_MS-1)/BOOTCHART_POLLING_MS;
-
- do {ret=mkdir(LOG_ROOT,0755);}while (ret < 0 && errno == EINTR);
-
- file_buff_open(log_stat, LOG_STAT);
- file_buff_open(log_procs, LOG_PROCS);
- file_buff_open(log_disks, LOG_DISK);
-
- /* create kernel process accounting file */
- {
- int fd = open( LOG_ACCT, O_WRONLY|O_CREAT|O_TRUNC,0644);
- if (fd >= 0) {
- close(fd);
- acct( LOG_ACCT );
- }
- }
-
- log_header();
- return count;
-}
-
-/* called each time you want to perform a bootchart sampling op */
-int bootchart_step( void )
-{
- do_log_file(log_stat, "/proc/stat");
- do_log_file(log_disks, "/proc/diskstats");
- do_log_procs(log_procs);
-
- /* we stop when /data/bootchart-stop contains 1 */
- {
- char buff[2];
- if (proc_read(LOG_STOPFILE,buff,sizeof(buff)) > 0 && buff[0] == '1') {
- return -1;
- }
- }
-
- return 0;
-}
-
-void bootchart_finish( void )
-{
- unlink( LOG_STOPFILE );
- file_buff_done(log_stat);
- file_buff_done(log_disks);
- file_buff_done(log_procs);
- acct(NULL);
-}
diff --git a/init/bootchart.h b/init/bootchart.h
deleted file mode 100644
index 39d2d4f20..000000000
--- a/init/bootchart.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _BOOTCHART_H
-#define _BOOTCHART_H
-
-#ifndef BOOTCHART
-# define BOOTCHART 0
-#endif
-
-#if BOOTCHART
-
-extern int bootchart_init(void);
-extern int bootchart_step(void);
-extern void bootchart_finish(void);
-
-# define BOOTCHART_POLLING_MS 200 /* polling period in ms */
-# define BOOTCHART_DEFAULT_TIME_SEC (2*60) /* default polling time in seconds */
-# define BOOTCHART_MAX_TIME_SEC (10*60) /* max polling time in seconds */
-
-#endif /* BOOTCHART */
-
-#endif /* _BOOTCHART_H */
diff --git a/init/builtins.c b/init/builtins.c
deleted file mode 100644
index 95fb22304..000000000
--- a/init/builtins.c
+++ /dev/null
@@ -1,442 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <string.h>
-#include <stdio.h>
-#include <linux/kd.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <linux/if.h>
-#include <arpa/inet.h>
-#include <stdlib.h>
-#include <sys/mount.h>
-#include <sys/resource.h>
-
-#include "init.h"
-#include "keywords.h"
-#include "property_service.h"
-#include "devices.h"
-
-#include <private/android_filesystem_config.h>
-
-void add_environment(const char *name, const char *value);
-
-extern int init_module(void *, unsigned long, const char *);
-
-static int write_file(const char *path, const char *value)
-{
- int fd, ret, len;
-
- fd = open(path, O_WRONLY|O_CREAT, 0622);
-
- if (fd < 0)
- return -1;
-
- len = strlen(value);
-
- do {
- ret = write(fd, value, len);
- } while (ret < 0 && errno == EINTR);
-
- close(fd);
- if (ret < 0) {
- return -1;
- } else {
- return 0;
- }
-}
-
-static int insmod(const char *filename, char *options)
-{
- void *module;
- unsigned size;
- int ret;
-
- module = read_file(filename, &size);
- if (!module)
- return -1;
-
- ret = init_module(module, size, options);
-
- free(module);
-
- return ret;
-}
-
-static int setkey(struct kbentry *kbe)
-{
- int fd, ret;
-
- fd = open("/dev/tty0", O_RDWR | O_SYNC);
- if (fd < 0)
- return -1;
-
- ret = ioctl(fd, KDSKBENT, kbe);
-
- close(fd);
- return ret;
-}
-
-static int __ifupdown(const char *interface, int up)
-{
- struct ifreq ifr;
- int s, ret;
-
- strlcpy(ifr.ifr_name, interface, IFNAMSIZ);
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s < 0)
- return -1;
-
- ret = ioctl(s, SIOCGIFFLAGS, &ifr);
- if (ret < 0) {
- goto done;
- }
-
- if (up)
- ifr.ifr_flags |= IFF_UP;
- else
- ifr.ifr_flags &= ~IFF_UP;
-
- ret = ioctl(s, SIOCSIFFLAGS, &ifr);
-
-done:
- close(s);
- return ret;
-}
-
-static void service_start_if_not_disabled(struct service *svc)
-{
- if (!(svc->flags & SVC_DISABLED)) {
- service_start(svc);
- }
-}
-
-int do_class_start(int nargs, char **args)
-{
- /* Starting a class does not start services
- * which are explicitly disabled. They must
- * be started individually.
- */
- service_for_each_class(args[1], service_start_if_not_disabled);
- return 0;
-}
-
-int do_class_stop(int nargs, char **args)
-{
- service_for_each_class(args[1], service_stop);
- return 0;
-}
-
-int do_domainname(int nargs, char **args)
-{
- return write_file("/proc/sys/kernel/domainname", args[1]);
-}
-
-int do_exec(int nargs, char **args)
-{
- return -1;
-}
-
-int do_export(int nargs, char **args)
-{
- add_environment(args[1], args[2]);
- return 0;
-}
-
-int do_hostname(int nargs, char **args)
-{
- return write_file("/proc/sys/kernel/hostname", args[1]);
-}
-
-int do_ifup(int nargs, char **args)
-{
- return __ifupdown(args[1], 1);
-}
-
-
-static int do_insmod_inner(int nargs, char **args, int opt_len)
-{
- char options[opt_len + 1];
- int i;
-
- options[0] = '\0';
- if (nargs > 2) {
- strcpy(options, args[2]);
- for (i = 3; i < nargs; ++i) {
- strcat(options, " ");
- strcat(options, args[i]);
- }
- }
-
- return insmod(args[1], options);
-}
-
-int do_insmod(int nargs, char **args)
-{
- int i;
- int size = 0;
-
- if (nargs > 2) {
- for (i = 2; i < nargs; ++i)
- size += strlen(args[i]) + 1;
- }
-
- return do_insmod_inner(nargs, args, size);
-}
-
-int do_import(int nargs, char **args)
-{
- return -1;
-}
-
-int do_mkdir(int nargs, char **args)
-{
- mode_t mode = 0755;
-
- /* mkdir <path> [mode] [owner] [group] */
-
- if (nargs >= 3) {
- mode = strtoul(args[2], 0, 8);
- }
-
- if (mkdir(args[1], mode)) {
- return -errno;
- }
-
- if (nargs >= 4) {
- uid_t uid = decode_uid(args[3]);
- gid_t gid = -1;
-
- if (nargs == 5) {
- gid = decode_uid(args[4]);
- }
-
- if (chown(args[1], uid, gid)) {
- return -errno;
- }
- }
-
- return 0;
-}
-
-static struct {
- const char *name;
- unsigned flag;
-} mount_flags[] = {
- { "noatime", MS_NOATIME },
- { "nosuid", MS_NOSUID },
- { "nodev", MS_NODEV },
- { "nodiratime", MS_NODIRATIME },
- { "ro", MS_RDONLY },
- { "rw", 0 },
- { "remount", MS_REMOUNT },
- { "defaults", 0 },
- { 0, 0 },
-};
-
-/* mount <type> <device> <path> <flags ...> <options> */
-int do_mount(int nargs, char **args)
-{
- char tmp[64];
- char *source;
- char *options = NULL;
- unsigned flags = 0;
- int n, i;
-
- for (n = 4; n < nargs; n++) {
- for (i = 0; mount_flags[i].name; i++) {
- if (!strcmp(args[n], mount_flags[i].name)) {
- flags |= mount_flags[i].flag;
- break;
- }
- }
-
- /* if our last argument isn't a flag, wolf it up as an option string */
- if (n + 1 == nargs && !mount_flags[i].name)
- options = args[n];
- }
-
- source = args[2];
- if (!strncmp(source, "mtd@", 4)) {
- n = mtd_name_to_number(source + 4);
- if (n >= 0) {
- sprintf(tmp, "/dev/block/mtdblock%d", n);
- source = tmp;
- }
- }
- return mount(source, args[3], args[1], flags, options);
-}
-
-int do_setkey(int nargs, char **args)
-{
- struct kbentry kbe;
- kbe.kb_table = strtoul(args[1], 0, 0);
- kbe.kb_index = strtoul(args[2], 0, 0);
- kbe.kb_value = strtoul(args[3], 0, 0);
- return setkey(&kbe);
-}
-
-int do_setprop(int nargs, char **args)
-{
- property_set(args[1], args[2]);
- return 0;
-}
-
-int do_setrlimit(int nargs, char **args)
-{
- struct rlimit limit;
- int resource;
- resource = atoi(args[1]);
- limit.rlim_cur = atoi(args[2]);
- limit.rlim_max = atoi(args[3]);
- return setrlimit(resource, &limit);
-}
-
-int do_start(int nargs, char **args)
-{
- struct service *svc;
- svc = service_find_by_name(args[1]);
- if (svc) {
- service_start(svc);
- }
- return 0;
-}
-
-int do_stop(int nargs, char **args)
-{
- struct service *svc;
- svc = service_find_by_name(args[1]);
- if (svc) {
- service_stop(svc);
- }
- return 0;
-}
-
-int do_restart(int nargs, char **args)
-{
- struct service *svc;
- svc = service_find_by_name(args[1]);
- if (svc) {
- service_stop(svc);
- service_start(svc);
- }
- return 0;
-}
-
-int do_trigger(int nargs, char **args)
-{
- return 0;
-}
-
-int do_symlink(int nargs, char **args)
-{
- return symlink(args[1], args[2]);
-}
-
-int do_sysclktz(int nargs, char **args)
-{
- struct timezone tz;
-
- if (nargs != 2)
- return -1;
-
- memset(&tz, 0, sizeof(tz));
- tz.tz_minuteswest = atoi(args[1]);
- if (settimeofday(NULL, &tz))
- return -1;
- return 0;
-}
-
-int do_write(int nargs, char **args)
-{
- return write_file(args[1], args[2]);
-}
-
-int do_chown(int nargs, char **args) {
- /* GID is optional. */
- if (nargs == 3) {
- if (chown(args[2], decode_uid(args[1]), -1) < 0)
- return -errno;
- } else if (nargs == 4) {
- if (chown(args[3], decode_uid(args[1]), decode_uid(args[2])))
- return -errno;
- } else {
- return -1;
- }
- return 0;
-}
-
-static mode_t get_mode(const char *s) {
- mode_t mode = 0;
- while (*s) {
- if (*s >= '0' && *s <= '7') {
- mode = (mode<<3) | (*s-'0');
- } else {
- return -1;
- }
- s++;
- }
- return mode;
-}
-
-int do_chmod(int nargs, char **args) {
- mode_t mode = get_mode(args[1]);
- if (chmod(args[2], mode) < 0) {
- return -errno;
- }
- return 0;
-}
-
-int do_loglevel(int nargs, char **args) {
- if (nargs == 2) {
- log_set_level(atoi(args[1]));
- return 0;
- }
- return -1;
-}
-
-int do_device(int nargs, char **args) {
- int len;
- char tmp[64];
- char *source = args[1];
- int prefix = 0;
-
- if (nargs != 5)
- return -1;
- /* Check for wildcard '*' at the end which indicates a prefix. */
- len = strlen(args[1]) - 1;
- if (args[1][len] == '*') {
- args[1][len] = '\0';
- prefix = 1;
- }
- /* If path starts with mtd@ lookup the mount number. */
- if (!strncmp(source, "mtd@", 4)) {
- int n = mtd_name_to_number(source + 4);
- if (n >= 0) {
- snprintf(tmp, sizeof(tmp), "/dev/mtd/mtd%d", n);
- source = tmp;
- }
- }
- add_devperms_partners(source, get_mode(args[2]), decode_uid(args[3]),
- decode_uid(args[4]), prefix);
- return 0;
-}
diff --git a/init/devices.c b/init/devices.c
deleted file mode 100644
index b1ef6ab2a..000000000
--- a/init/devices.c
+++ /dev/null
@@ -1,626 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <fcntl.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <string.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <linux/netlink.h>
-#include <private/android_filesystem_config.h>
-#include <sys/time.h>
-#include <asm/page.h>
-
-#include "init.h"
-#include "devices.h"
-
-#define CMDLINE_PREFIX "/dev"
-#define SYSFS_PREFIX "/sys"
-#define FIRMWARE_DIR "/etc/firmware"
-#define MAX_QEMU_PERM 6
-
-struct uevent {
- const char *action;
- const char *path;
- const char *subsystem;
- const char *firmware;
- int major;
- int minor;
-};
-
-static int open_uevent_socket(void)
-{
- struct sockaddr_nl addr;
- int sz = 64*1024; // XXX larger? udev uses 16MB!
- int s;
-
- memset(&addr, 0, sizeof(addr));
- addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
- addr.nl_groups = 0xffffffff;
-
- s = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
- if(s < 0)
- return -1;
-
- setsockopt(s, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz));
-
- if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
- close(s);
- return -1;
- }
-
- return s;
-}
-
-struct perms_ {
- char *name;
- mode_t perm;
- unsigned int uid;
- unsigned int gid;
- unsigned short prefix;
-};
-static struct perms_ devperms[] = {
- { "/dev/null", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/zero", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/full", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/ptmx", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/tty", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/random", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/urandom", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/ashmem", 0666, AID_ROOT, AID_ROOT, 0 },
- { "/dev/binder", 0666, AID_ROOT, AID_ROOT, 0 },
-
- /* logger should be world writable (for logging) but not readable */
- { "/dev/log/", 0662, AID_ROOT, AID_LOG, 1 },
-
- /* these should not be world writable */
- { "/dev/android_adb", 0660, AID_ADB, AID_ADB, 0 },
- { "/dev/android_adb_enable", 0660, AID_ADB, AID_ADB, 0 },
- { "/dev/ttyMSM0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
- { "/dev/ttyHS0", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
- { "/dev/uinput", 0600, AID_BLUETOOTH, AID_BLUETOOTH, 0 },
- { "/dev/alarm", 0664, AID_SYSTEM, AID_RADIO, 0 },
- { "/dev/tty0", 0660, AID_ROOT, AID_SYSTEM, 0 },
- { "/dev/graphics/", 0660, AID_ROOT, AID_GRAPHICS, 1 },
- { "/dev/hw3d", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
- { "/dev/input/", 0660, AID_ROOT, AID_INPUT, 1 },
- { "/dev/eac", 0660, AID_ROOT, AID_AUDIO, 0 },
- { "/dev/cam", 0660, AID_ROOT, AID_CAMERA, 0 },
- { "/dev/pmem", 0660, AID_SYSTEM, AID_GRAPHICS, 0 },
- { "/dev/pmem_gpu", 0660, AID_SYSTEM, AID_GRAPHICS, 1 },
- { "/dev/pmem_adsp", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/pmem_camera", 0660, AID_SYSTEM, AID_CAMERA, 1 },
- { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 },
- { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 },
- { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 },
- { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 },
- { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 },
- { "/dev/msm_pcm_out", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_pcm_in", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_pcm_ctl", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_snd", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_mp3", 0660, AID_SYSTEM, AID_AUDIO, 1 },
- { "/dev/msm_audpre", 0660, AID_SYSTEM, AID_AUDIO, 0 },
- { "/dev/htc-acoustic", 0660, AID_SYSTEM, AID_AUDIO, 0 },
- { "/dev/smd0", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/qmi", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 },
- { "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 },
- { NULL, 0, 0, 0, 0 },
-};
-
-/* devperms_partners list and perm_node are for hardware specific /dev entries */
-struct perm_node {
- struct perms_ dp;
- struct listnode plist;
-};
-list_declare(devperms_partners);
-
-/*
- * Permission override when in emulator mode, must be parsed before
- * system properties is initalized.
- */
-static int qemu_perm_count;
-static struct perms_ qemu_perms[MAX_QEMU_PERM + 1];
-
-int add_devperms_partners(const char *name, mode_t perm, unsigned int uid,
- unsigned int gid, unsigned short prefix) {
- int size;
- struct perm_node *node = malloc(sizeof (struct perm_node));
- if (!node)
- return -ENOMEM;
-
- size = strlen(name) + 1;
- if ((node->dp.name = malloc(size)) == NULL)
- return -ENOMEM;
-
- memcpy(node->dp.name, name, size);
- node->dp.perm = perm;
- node->dp.uid = uid;
- node->dp.gid = gid;
- node->dp.prefix = prefix;
-
- list_add_tail(&devperms_partners, &node->plist);
- return 0;
-}
-
-void qemu_init(void) {
- qemu_perm_count = 0;
- memset(&qemu_perms, 0, sizeof(qemu_perms));
-}
-
-static int qemu_perm(const char* name, mode_t perm, unsigned int uid,
- unsigned int gid, unsigned short prefix)
-{
- char *buf;
- if (qemu_perm_count == MAX_QEMU_PERM)
- return -ENOSPC;
-
- buf = malloc(strlen(name) + 1);
- if (!buf)
- return -errno;
-
- strlcpy(buf, name, strlen(name) + 1);
- qemu_perms[qemu_perm_count].name = buf;
- qemu_perms[qemu_perm_count].perm = perm;
- qemu_perms[qemu_perm_count].uid = uid;
- qemu_perms[qemu_perm_count].gid = gid;
- qemu_perms[qemu_perm_count].prefix = prefix;
-
- qemu_perm_count++;
- return 0;
-}
-
-/* Permission overrides for emulator that are parsed from /proc/cmdline. */
-void qemu_cmdline(const char* name, const char *value)
-{
- char *buf;
- if (!strcmp(name, "android.ril")) {
- /* cmd line params currently assume /dev/ prefix */
- if (asprintf(&buf, CMDLINE_PREFIX"/%s", value) == -1) {
- return;
- }
- INFO("nani- buf:: %s\n", buf);
- qemu_perm(buf, 0660, AID_RADIO, AID_ROOT, 0);
- }
-}
-
-static int get_device_perm_inner(struct perms_ *perms, const char *path,
- unsigned *uid, unsigned *gid, mode_t *perm)
-{
- int i;
- for(i = 0; perms[i].name; i++) {
-
- if(perms[i].prefix) {
- if(strncmp(path, perms[i].name, strlen(perms[i].name)))
- continue;
- } else {
- if(strcmp(path, perms[i].name))
- continue;
- }
- *uid = perms[i].uid;
- *gid = perms[i].gid;
- *perm = perms[i].perm;
- return 0;
- }
- return -1;
-}
-
-/* First checks for emulator specific permissions specified in /proc/cmdline. */
-static mode_t get_device_perm(const char *path, unsigned *uid, unsigned *gid)
-{
- mode_t perm;
-
- if (get_device_perm_inner(qemu_perms, path, uid, gid, &perm) == 0) {
- return perm;
- } else if (get_device_perm_inner(devperms, path, uid, gid, &perm) == 0) {
- return perm;
- } else {
- struct listnode *node;
- struct perm_node *perm_node;
- struct perms_ *dp;
-
- /* Check partners list. */
- list_for_each(node, &devperms_partners) {
- perm_node = node_to_item(node, struct perm_node, plist);
- dp = &perm_node->dp;
-
- if (dp->prefix) {
- if (strncmp(path, dp->name, strlen(dp->name)))
- continue;
- } else {
- if (strcmp(path, dp->name))
- continue;
- }
- /* Found perm in partner list. */
- *uid = dp->uid;
- *gid = dp->gid;
- return dp->perm;
- }
- /* Default if nothing found. */
- *uid = 0;
- *gid = 0;
- return 0600;
- }
-}
-
-static void make_device(const char *path, int block, int major, int minor)
-{
- unsigned uid;
- unsigned gid;
- mode_t mode;
- dev_t dev;
-
- if(major > 255 || minor > 255)
- return;
-
- mode = get_device_perm(path, &uid, &gid) | (block ? S_IFBLK : S_IFCHR);
- dev = (major << 8) | minor;
- mknod(path, mode, dev);
- chown(path, uid, gid);
-}
-
-#ifdef LOG_UEVENTS
-
-static inline suseconds_t get_usecs(void)
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
- return tv.tv_sec * (suseconds_t) 1000000 + tv.tv_usec;
-}
-
-#define log_event_print(x...) INFO(x)
-
-#else
-
-#define log_event_print(fmt, args...) do { } while (0)
-#define get_usecs() 0
-
-#endif
-
-static void parse_event(const char *msg, struct uevent *uevent)
-{
- uevent->action = "";
- uevent->path = "";
- uevent->subsystem = "";
- uevent->firmware = "";
- uevent->major = -1;
- uevent->minor = -1;
-
- /* currently ignoring SEQNUM */
- while(*msg) {
- if(!strncmp(msg, "ACTION=", 7)) {
- msg += 7;
- uevent->action = msg;
- } else if(!strncmp(msg, "DEVPATH=", 8)) {
- msg += 8;
- uevent->path = msg;
- } else if(!strncmp(msg, "SUBSYSTEM=", 10)) {
- msg += 10;
- uevent->subsystem = msg;
- } else if(!strncmp(msg, "FIRMWARE=", 9)) {
- msg += 9;
- uevent->firmware = msg;
- } else if(!strncmp(msg, "MAJOR=", 6)) {
- msg += 6;
- uevent->major = atoi(msg);
- } else if(!strncmp(msg, "MINOR=", 6)) {
- msg += 6;
- uevent->minor = atoi(msg);
- }
-
- /* advance to after the next \0 */
- while(*msg++)
- ;
- }
-
- log_event_print("event { '%s', '%s', '%s', '%s', %d, %d }\n",
- uevent->action, uevent->path, uevent->subsystem,
- uevent->firmware, uevent->major, uevent->minor);
-}
-
-static void handle_device_event(struct uevent *uevent)
-{
- char devpath[96];
- char *base, *name;
- int block;
-
- /* if it's not a /dev device, nothing to do */
- if((uevent->major < 0) || (uevent->minor < 0))
- return;
-
- /* do we have a name? */
- name = strrchr(uevent->path, '/');
- if(!name)
- return;
- name++;
-
- /* too-long names would overrun our buffer */
- if(strlen(name) > 64)
- return;
-
- /* are we block or char? where should we live? */
- if(!strncmp(uevent->subsystem, "block", 5)) {
- block = 1;
- base = "/dev/block/";
- mkdir(base, 0755);
- } else {
- block = 0;
- /* this should probably be configurable somehow */
- if(!strncmp(uevent->subsystem, "graphics", 8)) {
- base = "/dev/graphics/";
- mkdir(base, 0755);
- } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) {
- base = "/dev/oncrpc/";
- mkdir(base, 0755);
- } else if (!strncmp(uevent->subsystem, "adsp", 4)) {
- base = "/dev/adsp/";
- mkdir(base, 0755);
- } else if(!strncmp(uevent->subsystem, "input", 5)) {
- base = "/dev/input/";
- mkdir(base, 0755);
- } else if(!strncmp(uevent->subsystem, "mtd", 3)) {
- base = "/dev/mtd/";
- mkdir(base, 0755);
- } else if(!strncmp(uevent->subsystem, "misc", 4) &&
- !strncmp(name, "log_", 4)) {
- base = "/dev/log/";
- mkdir(base, 0755);
- name += 4;
- } else
- base = "/dev/";
- }
-
- snprintf(devpath, sizeof(devpath), "%s%s", base, name);
-
- if(!strcmp(uevent->action, "add")) {
- make_device(devpath, block, uevent->major, uevent->minor);
- return;
- }
-
- if(!strcmp(uevent->action, "remove")) {
- unlink(devpath);
- return;
- }
-}
-
-static int load_firmware(int fw_fd, int loading_fd, int data_fd)
-{
- struct stat st;
- long len_to_copy;
- int ret = 0;
-
- if(fstat(fw_fd, &st) < 0)
- return -1;
- len_to_copy = st.st_size;
-
- write(loading_fd, "1", 1); /* start transfer */
-
- while (len_to_copy > 0) {
- char buf[PAGE_SIZE];
- ssize_t nr;
-
- nr = read(fw_fd, buf, sizeof(buf));
- if(!nr)
- break;
- if(nr < 0) {
- ret = -1;
- break;
- }
-
- len_to_copy -= nr;
- while (nr > 0) {
- ssize_t nw = 0;
-
- nw = write(data_fd, buf + nw, nr);
- if(nw <= 0) {
- ret = -1;
- goto out;
- }
- nr -= nw;
- }
- }
-
-out:
- if(!ret)
- write(loading_fd, "0", 1); /* successful end of transfer */
- else
- write(loading_fd, "-1", 2); /* abort transfer */
-
- return ret;
-}
-
-static void process_firmware_event(struct uevent *uevent)
-{
- char *root, *loading, *data, *file;
- int l, loading_fd, data_fd, fw_fd;
-
- log_event_print("firmware event { '%s', '%s' }\n",
- uevent->path, uevent->firmware);
-
- l = asprintf(&root, SYSFS_PREFIX"%s/", uevent->path);
- if (l == -1)
- return;
-
- l = asprintf(&loading, "%sloading", root);
- if (l == -1)
- goto root_free_out;
-
- l = asprintf(&data, "%sdata", root);
- if (l == -1)
- goto loading_free_out;
-
- l = asprintf(&file, FIRMWARE_DIR"/%s", uevent->firmware);
- if (l == -1)
- goto data_free_out;
-
- loading_fd = open(loading, O_WRONLY);
- if(loading_fd < 0)
- goto file_free_out;
-
- data_fd = open(data, O_WRONLY);
- if(data_fd < 0)
- goto loading_close_out;
-
- fw_fd = open(file, O_RDONLY);
- if(fw_fd < 0)
- goto data_close_out;
-
- if(!load_firmware(fw_fd, loading_fd, data_fd))
- log_event_print("firmware copy success { '%s', '%s' }\n", root, file);
- else
- log_event_print("firmware copy failure { '%s', '%s' }\n", root, file);
-
- close(fw_fd);
-data_close_out:
- close(data_fd);
-loading_close_out:
- close(loading_fd);
-file_free_out:
- free(file);
-data_free_out:
- free(data);
-loading_free_out:
- free(loading);
-root_free_out:
- free(root);
-}
-
-static void handle_firmware_event(struct uevent *uevent)
-{
- pid_t pid;
-
- if(strcmp(uevent->subsystem, "firmware"))
- return;
-
- if(strcmp(uevent->action, "add"))
- return;
-
- /* we fork, to avoid making large memory allocations in init proper */
- pid = fork();
- if (!pid) {
- process_firmware_event(uevent);
- exit(EXIT_SUCCESS);
- }
-}
-
-#define UEVENT_MSG_LEN 1024
-void handle_device_fd(int fd)
-{
- char msg[UEVENT_MSG_LEN+2];
- int n;
-
- while((n = recv(fd, msg, UEVENT_MSG_LEN, 0)) > 0) {
- struct uevent uevent;
-
- if(n == UEVENT_MSG_LEN) /* overflow -- discard */
- continue;
-
- msg[n] = '\0';
- msg[n+1] = '\0';
-
- parse_event(msg, &uevent);
-
- handle_device_event(&uevent);
- handle_firmware_event(&uevent);
- }
-}
-
-/* Coldboot walks parts of the /sys tree and pokes the uevent files
-** to cause the kernel to regenerate device add events that happened
-** before init's device manager was started
-**
-** We drain any pending events from the netlink socket every time
-** we poke another uevent file to make sure we don't overrun the
-** socket's buffer.
-*/
-
-static void do_coldboot(int event_fd, DIR *d)
-{
- struct dirent *de;
- int dfd, fd;
-
- dfd = dirfd(d);
-
- fd = openat(dfd, "uevent", O_WRONLY);
- if(fd >= 0) {
- write(fd, "add\n", 4);
- close(fd);
- handle_device_fd(event_fd);
- }
-
- while((de = readdir(d))) {
- DIR *d2;
-
- if(de->d_type != DT_DIR || de->d_name[0] == '.')
- continue;
-
- fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
- if(fd < 0)
- continue;
-
- d2 = fdopendir(fd);
- if(d2 == 0)
- close(fd);
- else {
- do_coldboot(event_fd, d2);
- closedir(d2);
- }
- }
-}
-
-static void coldboot(int event_fd, const char *path)
-{
- DIR *d = opendir(path);
- if(d) {
- do_coldboot(event_fd, d);
- closedir(d);
- }
-}
-
-int device_init(void)
-{
- suseconds_t t0, t1;
- int fd;
-
- fd = open_uevent_socket();
- if(fd < 0)
- return -1;
-
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- fcntl(fd, F_SETFL, O_NONBLOCK);
-
- t0 = get_usecs();
- coldboot(fd, "/sys/class");
- coldboot(fd, "/sys/block");
- coldboot(fd, "/sys/devices");
- t1 = get_usecs();
-
- log_event_print("coldboot %ld uS\n", ((long) (t1 - t0)));
-
- return fd;
-}
diff --git a/init/devices.h b/init/devices.h
deleted file mode 100644
index b484da45e..000000000
--- a/init/devices.h
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _INIT_DEVICES_H
-#define _INIT_DEVICES_H
-
-extern void handle_device_fd(int fd);
-extern int device_init(void);
-extern void qemu_init(void);
-extern void qemu_cmdline(const char* name, const char *value);
-extern int add_devperms_partners(const char *name, mode_t perm, unsigned int uid,
- unsigned int gid, unsigned short prefix);
-
-#endif /* _INIT_DEVICES_H */
diff --git a/init/grab-bootchart.sh b/init/grab-bootchart.sh
deleted file mode 100755
index 7fe890436..000000000
--- a/init/grab-bootchart.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/sh
-#
-# this script is used to retrieve the bootchart log generated
-# by init when compiled with INIT_BOOTCHART=true.
-#
-# for all details, see //device/system/init/README.BOOTCHART
-#
-TMPDIR=/tmp/android-bootchart
-rm -rf $TMPDIR
-mkdir -p $TMPDIR
-
-LOGROOT=/data/bootchart
-TARBALL=bootchart.tgz
-
-FILES="header proc_stat.log proc_ps.log proc_diskstats.log kernel_pacct"
-
-for f in $FILES; do
- adb pull $LOGROOT/$f $TMPDIR/$f 2>&1 > /dev/null
-done
-(cd $TMPDIR && tar -czf $TARBALL $FILES)
-cp -f $TMPDIR/$TARBALL ./$TARBALL
-echo "look at $TARBALL"
diff --git a/init/init.c b/init/init.c
deleted file mode 100644
index b8b4f4037..000000000
--- a/init/init.c
+++ /dev/null
@@ -1,989 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <sys/poll.h>
-#include <time.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <mtd/mtd-user.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/reboot.h>
-
-#include <cutils/sockets.h>
-#include <termios.h>
-#include <linux/kd.h>
-#include <linux/keychord.h>
-
-#include <sys/system_properties.h>
-
-#include "devices.h"
-#include "init.h"
-#include "property_service.h"
-#include "bootchart.h"
-
-static int property_triggers_enabled = 0;
-
-#if BOOTCHART
-static int bootchart_count;
-#endif
-
-static char console[32];
-static char serialno[32];
-static char bootmode[32];
-static char baseband[32];
-static char carrier[32];
-static char bootloader[32];
-static char hardware[32];
-static unsigned revision = 0;
-static char qemu[32];
-static struct input_keychord *keychords = 0;
-static int keychords_count = 0;
-static int keychords_length = 0;
-
-static void drain_action_queue(void);
-
-static void notify_service_state(const char *name, const char *state)
-{
- char pname[PROP_NAME_MAX];
- int len = strlen(name);
- if ((len + 10) > PROP_NAME_MAX)
- return;
- snprintf(pname, sizeof(pname), "init.svc.%s", name);
- property_set(pname, state);
-}
-
-static int have_console;
-static char *console_name = "/dev/console";
-static time_t process_needs_restart;
-
-static const char *ENV[32];
-
-/* add_environment - add "key=value" to the current environment */
-int add_environment(const char *key, const char *val)
-{
- int n;
-
- for (n = 0; n < 31; n++) {
- if (!ENV[n]) {
- size_t len = strlen(key) + strlen(val) + 2;
- char *entry = malloc(len);
- snprintf(entry, len, "%s=%s", key, val);
- ENV[n] = entry;
- return 0;
- }
- }
-
- return 1;
-}
-
-static void zap_stdio(void)
-{
- int fd;
- fd = open("/dev/null", O_RDWR);
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- close(fd);
-}
-
-static void open_console()
-{
- int fd;
- if ((fd = open(console_name, O_RDWR)) < 0) {
- fd = open("/dev/null", O_RDWR);
- }
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- close(fd);
-}
-
-/*
- * gettime() - returns the time in seconds of the system's monotonic clock or
- * zero on error.
- */
-static time_t gettime(void)
-{
- struct timespec ts;
- int ret;
-
- ret = clock_gettime(CLOCK_MONOTONIC, &ts);
- if (ret < 0) {
- ERROR("clock_gettime(CLOCK_MONOTONIC) failed: %s\n", strerror(errno));
- return 0;
- }
-
- return ts.tv_sec;
-}
-
-static void publish_socket(const char *name, int fd)
-{
- char key[64] = ANDROID_SOCKET_ENV_PREFIX;
- char val[64];
-
- strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
- name,
- sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
- snprintf(val, sizeof(val), "%d", fd);
- add_environment(key, val);
-
- /* make sure we don't close-on-exec */
- fcntl(fd, F_SETFD, 0);
-}
-
-void service_start(struct service *svc)
-{
- struct stat s;
- pid_t pid;
- int needs_console;
- int n;
-
- /* starting a service removes it from the disabled
- * state and immediately takes it out of the restarting
- * state if it was in there
- */
- svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING));
- svc->time_started = 0;
-
- /* running processes require no additional work -- if
- * they're in the process of exiting, we've ensured
- * that they will immediately restart on exit, unless
- * they are ONESHOT
- */
- if (svc->flags & SVC_RUNNING) {
- return;
- }
-
- needs_console = (svc->flags & SVC_CONSOLE) ? 1 : 0;
- if (needs_console && (!have_console)) {
- ERROR("service '%s' requires console\n", svc->name);
- svc->flags |= SVC_DISABLED;
- return;
- }
-
- if (stat(svc->args[0], &s) != 0) {
- ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name);
- svc->flags |= SVC_DISABLED;
- return;
- }
-
- NOTICE("starting '%s'\n", svc->name);
-
- pid = fork();
-
- if (pid == 0) {
- struct socketinfo *si;
- struct svcenvinfo *ei;
- char tmp[32];
- int fd, sz;
-
- get_property_workspace(&fd, &sz);
- sprintf(tmp, "%d,%d", dup(fd), sz);
- add_environment("ANDROID_PROPERTY_WORKSPACE", tmp);
-
- for (ei = svc->envvars; ei; ei = ei->next)
- add_environment(ei->name, ei->value);
-
- for (si = svc->sockets; si; si = si->next) {
- int s = create_socket(si->name,
- !strcmp(si->type, "dgram") ?
- SOCK_DGRAM : SOCK_STREAM,
- si->perm, si->uid, si->gid);
- if (s >= 0) {
- publish_socket(si->name, s);
- }
- }
-
- if (needs_console) {
- setsid();
- open_console();
- } else {
- zap_stdio();
- }
-
-#if 0
- for (n = 0; svc->args[n]; n++) {
- INFO("args[%d] = '%s'\n", n, svc->args[n]);
- }
- for (n = 0; ENV[n]; n++) {
- INFO("env[%d] = '%s'\n", n, ENV[n]);
- }
-#endif
-
- setpgid(0, getpid());
-
- /* as requested, set our gid, supplemental gids, and uid */
- if (svc->gid) {
- setgid(svc->gid);
- }
- if (svc->nr_supp_gids) {
- setgroups(svc->nr_supp_gids, svc->supp_gids);
- }
- if (svc->uid) {
- setuid(svc->uid);
- }
-
- execve(svc->args[0], (char**) svc->args, (char**) ENV);
- _exit(127);
- }
-
- if (pid < 0) {
- ERROR("failed to start '%s'\n", svc->name);
- svc->pid = 0;
- return;
- }
-
- svc->time_started = gettime();
- svc->pid = pid;
- svc->flags |= SVC_RUNNING;
-
- notify_service_state(svc->name, "running");
-}
-
-void service_stop(struct service *svc)
-{
- /* we are no longer running, nor should we
- * attempt to restart
- */
- svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING));
-
- /* if the service has not yet started, prevent
- * it from auto-starting with its class
- */
- svc->flags |= SVC_DISABLED;
-
- if (svc->pid) {
- NOTICE("service '%s' is being killed\n", svc->name);
- kill(-svc->pid, SIGTERM);
- notify_service_state(svc->name, "stopping");
- } else {
- notify_service_state(svc->name, "stopped");
- }
-}
-
-void property_changed(const char *name, const char *value)
-{
- if (property_triggers_enabled) {
- queue_property_triggers(name, value);
- drain_action_queue();
- }
-}
-
-#define CRITICAL_CRASH_THRESHOLD 4 /* if we crash >4 times ... */
-#define CRITICAL_CRASH_WINDOW (4*60) /* ... in 4 minutes, goto recovery*/
-
-static int wait_for_one_process(int block)
-{
- pid_t pid;
- int status;
- struct service *svc;
- struct socketinfo *si;
- time_t now;
- struct listnode *node;
- struct command *cmd;
-
- while ( (pid = waitpid(-1, &status, block ? 0 : WNOHANG)) == -1 && errno == EINTR );
- if (pid <= 0) return -1;
- INFO("waitpid returned pid %d, status = %08x\n", pid, status);
-
- svc = service_find_by_pid(pid);
- if (!svc) {
- ERROR("untracked pid %d exited\n", pid);
- return 0;
- }
-
- NOTICE("process '%s', pid %d exited\n", svc->name, pid);
-
- if (!(svc->flags & SVC_ONESHOT)) {
- kill(-pid, SIGKILL);
- NOTICE("process '%s' killing any children in process group\n", svc->name);
- }
-
- /* remove any sockets we may have created */
- for (si = svc->sockets; si; si = si->next) {
- char tmp[128];
- snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
- unlink(tmp);
- }
-
- svc->pid = 0;
- svc->flags &= (~SVC_RUNNING);
-
- /* oneshot processes go into the disabled state on exit */
- if (svc->flags & SVC_ONESHOT) {
- svc->flags |= SVC_DISABLED;
- }
-
- /* disabled processes do not get restarted automatically */
- if (svc->flags & SVC_DISABLED) {
- notify_service_state(svc->name, "stopped");
- return 0;
- }
-
- now = gettime();
- if (svc->flags & SVC_CRITICAL) {
- if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
- if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
- ERROR("critical process '%s' exited %d times in %d minutes; "
- "rebooting into recovery mode\n", svc->name,
- CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60);
- sync();
- __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2,
- LINUX_REBOOT_CMD_RESTART2, "recovery");
- return 0;
- }
- } else {
- svc->time_crashed = now;
- svc->nr_crashed = 1;
- }
- }
-
- /* Execute all onrestart commands for this service. */
- list_for_each(node, &svc->onrestart.commands) {
- cmd = node_to_item(node, struct command, clist);
- cmd->func(cmd->nargs, cmd->args);
- }
- svc->flags |= SVC_RESTARTING;
- notify_service_state(svc->name, "restarting");
- return 0;
-}
-
-static void restart_service_if_needed(struct service *svc)
-{
- time_t next_start_time = svc->time_started + 5;
-
- if (next_start_time <= gettime()) {
- svc->flags &= (~SVC_RESTARTING);
- service_start(svc);
- return;
- }
-
- if ((next_start_time < process_needs_restart) ||
- (process_needs_restart == 0)) {
- process_needs_restart = next_start_time;
- }
-}
-
-static void restart_processes()
-{
- process_needs_restart = 0;
- service_for_each_flags(SVC_RESTARTING,
- restart_service_if_needed);
-}
-
-static int signal_fd = -1;
-
-static void sigchld_handler(int s)
-{
- write(signal_fd, &s, 1);
-}
-
-static void msg_start(const char *name)
-{
- struct service *svc = service_find_by_name(name);
-
- if (svc) {
- service_start(svc);
- } else {
- ERROR("no such service '%s'\n", name);
- }
-}
-
-static void msg_stop(const char *name)
-{
- struct service *svc = service_find_by_name(name);
-
- if (svc) {
- service_stop(svc);
- } else {
- ERROR("no such service '%s'\n");
- }
-}
-
-void handle_control_message(const char *msg, const char *arg)
-{
- if (!strcmp(msg,"start")) {
- msg_start(arg);
- } else if (!strcmp(msg,"stop")) {
- msg_stop(arg);
- } else {
- ERROR("unknown control msg '%s'\n", msg);
- }
-}
-
-#define MAX_MTD_PARTITIONS 16
-
-static struct {
- char name[16];
- int number;
-} mtd_part_map[MAX_MTD_PARTITIONS];
-
-static int mtd_part_count = -1;
-
-static void find_mtd_partitions(void)
-{
- int fd;
- char buf[1024];
- char *pmtdbufp;
- ssize_t pmtdsize;
- int r;
-
- fd = open("/proc/mtd", O_RDONLY);
- if (fd < 0)
- return;
-
- buf[sizeof(buf) - 1] = '\0';
- pmtdsize = read(fd, buf, sizeof(buf) - 1);
- pmtdbufp = buf;
- while (pmtdsize > 0) {
- int mtdnum, mtdsize, mtderasesize;
- char mtdname[16];
- mtdname[0] = '\0';
- mtdnum = -1;
- r = sscanf(pmtdbufp, "mtd%d: %x %x %15s",
- &mtdnum, &mtdsize, &mtderasesize, mtdname);
- if ((r == 4) && (mtdname[0] == '"')) {
- char *x = strchr(mtdname + 1, '"');
- if (x) {
- *x = 0;
- }
- INFO("mtd partition %d, %s\n", mtdnum, mtdname + 1);
- if (mtd_part_count < MAX_MTD_PARTITIONS) {
- strcpy(mtd_part_map[mtd_part_count].name, mtdname + 1);
- mtd_part_map[mtd_part_count].number = mtdnum;
- mtd_part_count++;
- } else {
- ERROR("too many mtd partitions\n");
- }
- }
- while (pmtdsize > 0 && *pmtdbufp != '\n') {
- pmtdbufp++;
- pmtdsize--;
- }
- if (pmtdsize > 0) {
- pmtdbufp++;
- pmtdsize--;
- }
- }
- close(fd);
-}
-
-int mtd_name_to_number(const char *name)
-{
- int n;
- if (mtd_part_count < 0) {
- mtd_part_count = 0;
- find_mtd_partitions();
- }
- for (n = 0; n < mtd_part_count; n++) {
- if (!strcmp(name, mtd_part_map[n].name)) {
- return mtd_part_map[n].number;
- }
- }
- return -1;
-}
-
-static void import_kernel_nv(char *name, int in_qemu)
-{
- char *value = strchr(name, '=');
-
- if (value == 0) return;
- *value++ = 0;
- if (*name == 0) return;
-
- if (!in_qemu)
- {
- /* on a real device, white-list the kernel options */
- if (!strcmp(name,"qemu")) {
- strlcpy(qemu, value, sizeof(qemu));
- } else if (!strcmp(name,"androidboot.console")) {
- strlcpy(console, value, sizeof(console));
- } else if (!strcmp(name,"androidboot.mode")) {
- strlcpy(bootmode, value, sizeof(bootmode));
- } else if (!strcmp(name,"androidboot.serialno")) {
- strlcpy(serialno, value, sizeof(serialno));
- } else if (!strcmp(name,"androidboot.baseband")) {
- strlcpy(baseband, value, sizeof(baseband));
- } else if (!strcmp(name,"androidboot.carrier")) {
- strlcpy(carrier, value, sizeof(carrier));
- } else if (!strcmp(name,"androidboot.bootloader")) {
- strlcpy(bootloader, value, sizeof(bootloader));
- } else if (!strcmp(name,"androidboot.hardware")) {
- strlcpy(hardware, value, sizeof(hardware));
- } else {
- qemu_cmdline(name, value);
- }
- } else {
- /* in the emulator, export any kernel option with the
- * ro.kernel. prefix */
- char buff[32];
- int len = snprintf( buff, sizeof(buff), "ro.kernel.%s", name );
- if (len < (int)sizeof(buff)) {
- property_set( buff, value );
- }
- }
-}
-
-static void import_kernel_cmdline(int in_qemu)
-{
- char cmdline[1024];
- char *ptr;
- int fd;
-
- fd = open("/proc/cmdline", O_RDONLY);
- if (fd >= 0) {
- int n = read(fd, cmdline, 1023);
- if (n < 0) n = 0;
-
- /* get rid of trailing newline, it happens */
- if (n > 0 && cmdline[n-1] == '\n') n--;
-
- cmdline[n] = 0;
- close(fd);
- } else {
- cmdline[0] = 0;
- }
-
- ptr = cmdline;
- while (ptr && *ptr) {
- char *x = strchr(ptr, ' ');
- if (x != 0) *x++ = 0;
- import_kernel_nv(ptr, in_qemu);
- ptr = x;
- }
-
- /* don't expose the raw commandline to nonpriv processes */
- chmod("/proc/cmdline", 0440);
-}
-
-static void get_hardware_name(void)
-{
- char data[1024];
- int fd, n;
- char *x, *hw, *rev;
-
- /* Hardware string was provided on kernel command line */
- if (hardware[0])
- return;
-
- fd = open("/proc/cpuinfo", O_RDONLY);
- if (fd < 0) return;
-
- n = read(fd, data, 1023);
- close(fd);
- if (n < 0) return;
-
- data[n] = 0;
- hw = strstr(data, "\nHardware");
- rev = strstr(data, "\nRevision");
-
- if (hw) {
- x = strstr(hw, ": ");
- if (x) {
- x += 2;
- n = 0;
- while (*x && !isspace(*x)) {
- hardware[n++] = tolower(*x);
- x++;
- if (n == 31) break;
- }
- hardware[n] = 0;
- }
- }
-
- if (rev) {
- x = strstr(rev, ": ");
- if (x) {
- revision = strtoul(x + 2, 0, 16);
- }
- }
-}
-
-static void drain_action_queue(void)
-{
- struct listnode *node;
- struct command *cmd;
- struct action *act;
- int ret;
-
- while ((act = action_remove_queue_head())) {
- INFO("processing action %p (%s)\n", act, act->name);
- list_for_each(node, &act->commands) {
- cmd = node_to_item(node, struct command, clist);
- ret = cmd->func(cmd->nargs, cmd->args);
- INFO("command '%s' r=%d\n", cmd->args[0], ret);
- }
- }
-}
-
-void open_devnull_stdio(void)
-{
- int fd;
- static const char *name = "/dev/__null__";
- if (mknod(name, S_IFCHR | 0600, (1 << 8) | 3) == 0) {
- fd = open(name, O_RDWR);
- unlink(name);
- if (fd >= 0) {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
- if (fd > 2) {
- close(fd);
- }
- return;
- }
- }
-
- exit(1);
-}
-
-void add_service_keycodes(struct service *svc)
-{
- struct input_keychord *keychord;
- int i, size;
-
- if (svc->keycodes) {
- /* add a new keychord to the list */
- size = sizeof(*keychord) + svc->nkeycodes * sizeof(keychord->keycodes[0]);
- keychords = realloc(keychords, keychords_length + size);
- if (!keychords) {
- ERROR("could not allocate keychords\n");
- keychords_length = 0;
- keychords_count = 0;
- return;
- }
-
- keychord = (struct input_keychord *)((char *)keychords + keychords_length);
- keychord->version = KEYCHORD_VERSION;
- keychord->id = keychords_count + 1;
- keychord->count = svc->nkeycodes;
- svc->keychord_id = keychord->id;
-
- for (i = 0; i < svc->nkeycodes; i++) {
- keychord->keycodes[i] = svc->keycodes[i];
- }
- keychords_count++;
- keychords_length += size;
- }
-}
-
-int open_keychord()
-{
- int fd, ret;
-
- service_for_each(add_service_keycodes);
-
- /* nothing to do if no services require keychords */
- if (!keychords)
- return -1;
-
- fd = open("/dev/keychord", O_RDWR);
- if (fd < 0) {
- ERROR("could not open /dev/keychord\n");
- return fd;
- }
- fcntl(fd, F_SETFD, FD_CLOEXEC);
-
- ret = write(fd, keychords, keychords_length);
- if (ret != keychords_length) {
- ERROR("could not configure /dev/keychord %d (%d)\n", ret, errno);
- close(fd);
- fd = -1;
- }
-
- free(keychords);
- keychords = 0;
-
- return fd;
-}
-
-void handle_keychord(int fd)
-{
- struct service *svc;
- int ret;
- __u16 id;
-
- ret = read(fd, &id, sizeof(id));
- if (ret != sizeof(id)) {
- ERROR("could not read keychord id\n");
- return;
- }
-
- svc = service_find_by_keychord(id);
- if (svc) {
- INFO("starting service %s from keychord\n", svc->name);
- service_start(svc);
- } else {
- ERROR("service for keychord %d not found\n", id);
- }
-}
-
-int main(int argc, char **argv)
-{
- int device_fd = -1;
- int property_set_fd = -1;
- int signal_recv_fd = -1;
- int keychord_fd = -1;
- int fd_count;
- int s[2];
- int fd;
- struct sigaction act;
- char tmp[PROP_VALUE_MAX];
- struct pollfd ufds[4];
- char *tmpdev;
- char* debuggable;
-
- act.sa_handler = sigchld_handler;
- act.sa_flags = SA_NOCLDSTOP;
- act.sa_mask = 0;
- act.sa_restorer = NULL;
- sigaction(SIGCHLD, &act, 0);
-
- /* clear the umask */
- umask(0);
-
- /* Get the basic filesystem setup we need put
- * together in the initramdisk on / and then we'll
- * let the rc file figure out the rest.
- */
- mkdir("/dev", 0755);
- mkdir("/proc", 0755);
- mkdir("/sys", 0755);
-
- mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755");
- mkdir("/dev/pts", 0755);
- mkdir("/dev/socket", 0755);
- mount("devpts", "/dev/pts", "devpts", 0, NULL);
- mount("proc", "/proc", "proc", 0, NULL);
- mount("sysfs", "/sys", "sysfs", 0, NULL);
-
- /* We must have some place other than / to create the
- * device nodes for kmsg and null, otherwise we won't
- * be able to remount / read-only later on.
- * Now that tmpfs is mounted on /dev, we can actually
- * talk to the outside world.
- */
- open_devnull_stdio();
- log_init();
-
- INFO("reading config file\n");
- parse_config_file("/init.rc");
-
- /* pull the kernel commandline and ramdisk properties file in */
- qemu_init();
- import_kernel_cmdline(0);
-
- get_hardware_name();
- snprintf(tmp, sizeof(tmp), "/init.%s.rc", hardware);
- parse_config_file(tmp);
-
- action_for_each_trigger("early-init", action_add_queue_tail);
- drain_action_queue();
-
- INFO("device init\n");
- device_fd = device_init();
-
- property_init();
-
- // only listen for keychords if ro.debuggable is true
- debuggable = property_get("ro.debuggable");
- if (debuggable && !strcmp(debuggable, "1")) {
- keychord_fd = open_keychord();
- }
-
- if (console[0]) {
- snprintf(tmp, sizeof(tmp), "/dev/%s", console);
- console_name = strdup(tmp);
- }
-
- fd = open(console_name, O_RDWR);
- if (fd >= 0)
- have_console = 1;
- close(fd);
-
- if( load_565rle_image(INIT_IMAGE_FILE) ) {
- fd = open("/dev/tty0", O_WRONLY);
- if (fd >= 0) {
- const char *msg;
- msg = "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n" // console is 40 cols x 30 lines
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- "\n"
- " A N D R O I D ";
- write(fd, msg, strlen(msg));
- close(fd);
- }
- }
-
- if (qemu[0])
- import_kernel_cmdline(1);
-
- if (!strcmp(bootmode,"factory"))
- property_set("ro.factorytest", "1");
- else if (!strcmp(bootmode,"factory2"))
- property_set("ro.factorytest", "2");
- else
- property_set("ro.factorytest", "0");
-
- property_set("ro.serialno", serialno[0] ? serialno : "");
- property_set("ro.bootmode", bootmode[0] ? bootmode : "unknown");
- property_set("ro.baseband", baseband[0] ? baseband : "unknown");
- property_set("ro.carrier", carrier[0] ? carrier : "unknown");
- property_set("ro.bootloader", bootloader[0] ? bootloader : "unknown");
-
- property_set("ro.hardware", hardware);
- snprintf(tmp, PROP_VALUE_MAX, "%d", revision);
- property_set("ro.revision", tmp);
-
- /* execute all the boot actions to get us started */
- action_for_each_trigger("init", action_add_queue_tail);
- drain_action_queue();
-
- /* read any property files on system or data and
- * fire up the property service. This must happen
- * after the ro.foo properties are set above so
- * that /data/local.prop cannot interfere with them.
- */
- property_set_fd = start_property_service();
-
- /* create a signalling mechanism for the sigchld handler */
- if (socketpair(AF_UNIX, SOCK_STREAM, 0, s) == 0) {
- signal_fd = s[0];
- signal_recv_fd = s[1];
- fcntl(s[0], F_SETFD, FD_CLOEXEC);
- fcntl(s[0], F_SETFL, O_NONBLOCK);
- fcntl(s[1], F_SETFD, FD_CLOEXEC);
- fcntl(s[1], F_SETFL, O_NONBLOCK);
- }
-
- /* make sure we actually have all the pieces we need */
- if ((device_fd < 0) ||
- (property_set_fd < 0) ||
- (signal_recv_fd < 0)) {
- ERROR("init startup failure\n");
- return 1;
- }
-
- /* execute all the boot actions to get us started */
- action_for_each_trigger("early-boot", action_add_queue_tail);
- action_for_each_trigger("boot", action_add_queue_tail);
- drain_action_queue();
-
- /* run all property triggers based on current state of the properties */
- queue_all_property_triggers();
- drain_action_queue();
-
- /* enable property triggers */
- property_triggers_enabled = 1;
-
- ufds[0].fd = device_fd;
- ufds[0].events = POLLIN;
- ufds[1].fd = property_set_fd;
- ufds[1].events = POLLIN;
- ufds[2].fd = signal_recv_fd;
- ufds[2].events = POLLIN;
- fd_count = 3;
-
- if (keychord_fd > 0) {
- ufds[3].fd = keychord_fd;
- ufds[3].events = POLLIN;
- fd_count++;
- } else {
- ufds[3].events = 0;
- ufds[3].revents = 0;
- }
-
-#if BOOTCHART
- bootchart_count = bootchart_init();
- if (bootchart_count < 0) {
- ERROR("bootcharting init failure\n");
- } else if (bootchart_count > 0) {
- NOTICE("bootcharting started (period=%d ms)\n", bootchart_count*BOOTCHART_POLLING_MS);
- } else {
- NOTICE("bootcharting ignored\n");
- }
-#endif
-
- for(;;) {
- int nr, i, timeout = -1;
-
- for (i = 0; i < fd_count; i++)
- ufds[i].revents = 0;
-
- drain_action_queue();
- restart_processes();
-
- if (process_needs_restart) {
- timeout = (process_needs_restart - gettime()) * 1000;
- if (timeout < 0)
- timeout = 0;
- }
-
-#if BOOTCHART
- if (bootchart_count > 0) {
- if (timeout < 0 || timeout > BOOTCHART_POLLING_MS)
- timeout = BOOTCHART_POLLING_MS;
- if (bootchart_step() < 0 || --bootchart_count == 0) {
- bootchart_finish();
- bootchart_count = 0;
- }
- }
-#endif
- nr = poll(ufds, fd_count, timeout);
- if (nr <= 0)
- continue;
-
- if (ufds[2].revents == POLLIN) {
- /* we got a SIGCHLD - reap and restart as needed */
- read(signal_recv_fd, tmp, sizeof(tmp));
- while (!wait_for_one_process(0))
- ;
- continue;
- }
-
- if (ufds[0].revents == POLLIN)
- handle_device_fd(device_fd);
-
- if (ufds[1].revents == POLLIN)
- handle_property_set_fd(property_set_fd);
- if (ufds[3].revents == POLLIN)
- handle_keychord(keychord_fd);
- }
-
- return 0;
-}
diff --git a/init/init.h b/init/init.h
deleted file mode 100644
index b68686930..000000000
--- a/init/init.h
+++ /dev/null
@@ -1,174 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _INIT_INIT_H
-#define _INIT_INIT_H
-
-int mtd_name_to_number(const char *name);
-
-void handle_control_message(const char *msg, const char *arg);
-
-int create_socket(const char *name, int type, mode_t perm,
- uid_t uid, gid_t gid);
-
-void *read_file(const char *fn, unsigned *_sz);
-
-void log_init(void);
-void log_set_level(int level);
-void log_close(void);
-void log_write(int level, const char *fmt, ...);
-
-#define ERROR(x...) log_write(3, "<3>init: " x)
-#define NOTICE(x...) log_write(5, "<5>init: " x)
-#define INFO(x...) log_write(6, "<6>init: " x)
-
-#define LOG_DEFAULT_LEVEL 3 /* messages <= this level are logged */
-#define LOG_UEVENTS 0 /* log uevent messages if 1. verbose */
-
-unsigned int decode_uid(const char *s);
-
-struct listnode
-{
- struct listnode *next;
- struct listnode *prev;
-};
-
-#define node_to_item(node, container, member) \
- (container *) (((char*) (node)) - offsetof(container, member))
-
-#define list_declare(name) \
- struct listnode name = { \
- .next = &name, \
- .prev = &name, \
- }
-
-#define list_for_each(node, list) \
- for (node = (list)->next; node != (list); node = node->next)
-
-void list_init(struct listnode *list);
-void list_add_tail(struct listnode *list, struct listnode *item);
-void list_remove(struct listnode *item);
-
-#define list_empty(list) ((list) == (list)->next)
-#define list_head(list) ((list)->next)
-#define list_tail(list) ((list)->prev)
-
-struct command
-{
- /* list of commands in an action */
- struct listnode clist;
-
- int (*func)(int nargs, char **args);
- int nargs;
- char *args[1];
-};
-
-struct action {
- /* node in list of all actions */
- struct listnode alist;
- /* node in the queue of pending actions */
- struct listnode qlist;
- /* node in list of actions for a trigger */
- struct listnode tlist;
-
- unsigned hash;
- const char *name;
-
- struct listnode commands;
- struct command *current;
-};
-
-struct socketinfo {
- struct socketinfo *next;
- const char *name;
- const char *type;
- uid_t uid;
- gid_t gid;
- int perm;
-};
-
-struct svcenvinfo {
- struct svcenvinfo *next;
- const char *name;
- const char *value;
-};
-
-#define SVC_DISABLED 0x01 /* do not autostart with class */
-#define SVC_ONESHOT 0x02 /* do not restart on exit */
-#define SVC_RUNNING 0x04 /* currently active */
-#define SVC_RESTARTING 0x08 /* waiting to restart */
-#define SVC_CONSOLE 0x10 /* requires console */
-#define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */
-
-#define NR_SVC_SUPP_GIDS 6 /* six supplementary groups */
-
-struct service {
- /* list of all services */
- struct listnode slist;
-
- const char *name;
- const char *classname;
-
- unsigned flags;
- pid_t pid;
- time_t time_started; /* time of last start */
- time_t time_crashed; /* first crash within inspection window */
- int nr_crashed; /* number of times crashed within window */
-
- uid_t uid;
- gid_t gid;
- gid_t supp_gids[NR_SVC_SUPP_GIDS];
- size_t nr_supp_gids;
-
- struct socketinfo *sockets;
- struct svcenvinfo *envvars;
-
- int nargs;
- char *args[1];
- struct action onrestart; /* Actions to execute on restart. */
-
- /* keycodes for triggering this service via /dev/keychord */
- int *keycodes;
- int nkeycodes;
- int keychord_id;
-};
-
-int parse_config_file(const char *fn);
-
-struct service *service_find_by_name(const char *name);
-struct service *service_find_by_pid(pid_t pid);
-struct service *service_find_by_keychord(int keychord_id);
-void service_for_each(void (*func)(struct service *svc));
-void service_for_each_class(const char *classname,
- void (*func)(struct service *svc));
-void service_for_each_flags(unsigned matchflags,
- void (*func)(struct service *svc));
-void service_stop(struct service *svc);
-void service_start(struct service *svc);
-void property_changed(const char *name, const char *value);
-
-struct action *action_remove_queue_head(void);
-void action_add_queue_tail(struct action *act);
-void action_for_each_trigger(const char *trigger,
- void (*func)(struct action *act));
-void queue_property_triggers(const char *name, const char *value);
-void queue_all_property_triggers();
-
-#define INIT_IMAGE_FILE "/initlogo.rle"
-
-int load_565rle_image( char *file_name );
-
-#endif /* _INIT_INIT_H */
diff --git a/init/keywords.h b/init/keywords.h
deleted file mode 100644
index 6f47379c6..000000000
--- a/init/keywords.h
+++ /dev/null
@@ -1,78 +0,0 @@
-
-#ifndef KEYWORD
-int do_class_start(int nargs, char **args);
-int do_class_stop(int nargs, char **args);
-int do_domainname(int nargs, char **args);
-int do_exec(int nargs, char **args);
-int do_export(int nargs, char **args);
-int do_hostname(int nargs, char **args);
-int do_ifup(int nargs, char **args);
-int do_insmod(int nargs, char **args);
-int do_import(int nargs, char **args);
-int do_mkdir(int nargs, char **args);
-int do_mount(int nargs, char **args);
-int do_restart(int nargs, char **args);
-int do_setkey(int nargs, char **args);
-int do_setprop(int nargs, char **args);
-int do_setrlimit(int nargs, char **args);
-int do_start(int nargs, char **args);
-int do_stop(int nargs, char **args);
-int do_trigger(int nargs, char **args);
-int do_symlink(int nargs, char **args);
-int do_sysclktz(int nargs, char **args);
-int do_write(int nargs, char **args);
-int do_chown(int nargs, char **args);
-int do_chmod(int nargs, char **args);
-int do_loglevel(int nargs, char **args);
-int do_device(int nargs, char **args);
-#define __MAKE_KEYWORD_ENUM__
-#define KEYWORD(symbol, flags, nargs, func) K_##symbol,
-enum {
- K_UNKNOWN,
-#endif
- KEYWORD(capability, OPTION, 0, 0)
- KEYWORD(class, OPTION, 0, 0)
- KEYWORD(class_start, COMMAND, 1, do_class_start)
- KEYWORD(class_stop, COMMAND, 1, do_class_stop)
- KEYWORD(console, OPTION, 0, 0)
- KEYWORD(critical, OPTION, 0, 0)
- KEYWORD(disabled, OPTION, 0, 0)
- KEYWORD(domainname, COMMAND, 1, do_domainname)
- KEYWORD(exec, COMMAND, 1, do_exec)
- KEYWORD(export, COMMAND, 2, do_export)
- KEYWORD(group, OPTION, 0, 0)
- KEYWORD(hostname, COMMAND, 1, do_hostname)
- KEYWORD(ifup, COMMAND, 1, do_ifup)
- KEYWORD(insmod, COMMAND, 1, do_insmod)
- KEYWORD(import, COMMAND, 1, do_import)
- KEYWORD(keycodes, OPTION, 0, 0)
- KEYWORD(mkdir, COMMAND, 1, do_mkdir)
- KEYWORD(mount, COMMAND, 3, do_mount)
- KEYWORD(on, SECTION, 0, 0)
- KEYWORD(oneshot, OPTION, 0, 0)
- KEYWORD(onrestart, OPTION, 0, 0)
- KEYWORD(restart, COMMAND, 1, do_restart)
- KEYWORD(service, SECTION, 0, 0)
- KEYWORD(setenv, OPTION, 2, 0)
- KEYWORD(setkey, COMMAND, 0, do_setkey)
- KEYWORD(setprop, COMMAND, 2, do_setprop)
- KEYWORD(setrlimit, COMMAND, 3, do_setrlimit)
- KEYWORD(socket, OPTION, 0, 0)
- KEYWORD(start, COMMAND, 1, do_start)
- KEYWORD(stop, COMMAND, 1, do_stop)
- KEYWORD(trigger, COMMAND, 1, do_trigger)
- KEYWORD(symlink, COMMAND, 1, do_symlink)
- KEYWORD(sysclktz, COMMAND, 1, do_sysclktz)
- KEYWORD(user, OPTION, 0, 0)
- KEYWORD(write, COMMAND, 2, do_write)
- KEYWORD(chown, COMMAND, 2, do_chown)
- KEYWORD(chmod, COMMAND, 2, do_chmod)
- KEYWORD(loglevel, COMMAND, 1, do_loglevel)
- KEYWORD(device, COMMAND, 4, do_device)
-#ifdef __MAKE_KEYWORD_ENUM__
- KEYWORD_COUNT,
-};
-#undef __MAKE_KEYWORD_ENUM__
-#undef KEYWORD
-#endif
-
diff --git a/init/logo.c b/init/logo.c
deleted file mode 100644
index 6a740bfd6..000000000
--- a/init/logo.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <linux/fb.h>
-#include <linux/kd.h>
-
-#include "init.h"
-
-#ifdef ANDROID
-#include <cutils/memory.h>
-#else
-void android_memset16(void *_ptr, unsigned short val, unsigned count)
-{
- unsigned short *ptr = _ptr;
- count >>= 1;
- while(count--)
- *ptr++ = val;
-}
-#endif
-
-struct FB {
- unsigned short *bits;
- unsigned size;
- int fd;
- struct fb_fix_screeninfo fi;
- struct fb_var_screeninfo vi;
-};
-
-#define fb_width(fb) ((fb)->vi.xres)
-#define fb_height(fb) ((fb)->vi.yres)
-#define fb_size(fb) ((fb)->vi.xres * (fb)->vi.yres * 2)
-
-static int fb_open(struct FB *fb)
-{
- fb->fd = open("/dev/graphics/fb0", O_RDWR);
- if (fb->fd < 0)
- return -1;
-
- if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0)
- goto fail;
- if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0)
- goto fail;
-
- fb->bits = mmap(0, fb_size(fb), PROT_READ | PROT_WRITE,
- MAP_SHARED, fb->fd, 0);
- if (fb->bits == MAP_FAILED)
- goto fail;
-
- return 0;
-
-fail:
- close(fb->fd);
- return -1;
-}
-
-static void fb_close(struct FB *fb)
-{
- munmap(fb->bits, fb_size(fb));
- close(fb->fd);
-}
-
-/* there's got to be a more portable way to do this ... */
-static void fb_update(struct FB *fb)
-{
- fb->vi.yoffset = 1;
- ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);
- fb->vi.yoffset = 0;
- ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);
-}
-
-static int vt_set_mode(int graphics)
-{
- int fd, r;
- fd = open("/dev/tty0", O_RDWR | O_SYNC);
- if (fd < 0)
- return -1;
- r = ioctl(fd, KDSETMODE, (void*) (graphics ? KD_GRAPHICS : KD_TEXT));
- close(fd);
- return r;
-}
-
-/* 565RLE image format: [count(2 bytes), rle(2 bytes)] */
-
-int load_565rle_image(char *fn)
-{
- struct FB fb;
- struct stat s;
- unsigned short *data, *bits, *ptr;
- unsigned count, max;
- int fd;
-
- if (vt_set_mode(1))
- return -1;
-
- fd = open(fn, O_RDONLY);
- if (fd < 0) {
- ERROR("cannot open '%s'\n", fn);
- goto fail_restore_text;
- }
-
- if (fstat(fd, &s) < 0) {
- goto fail_close_file;
- }
-
- data = mmap(0, s.st_size, PROT_READ, MAP_SHARED, fd, 0);
- if (data == MAP_FAILED)
- goto fail_close_file;
-
- if (fb_open(&fb))
- goto fail_unmap_data;
-
- max = fb_width(&fb) * fb_height(&fb);
- ptr = data;
- count = s.st_size;
- bits = fb.bits;
- while (count > 3) {
- unsigned n = ptr[0];
- if (n > max)
- break;
- android_memset16(bits, ptr[1], n << 1);
- bits += n;
- max -= n;
- ptr += 2;
- count -= 4;
- }
-
- munmap(data, s.st_size);
- fb_update(&fb);
- fb_close(&fb);
- close(fd);
- unlink(fn);
- return 0;
-
-fail_unmap_data:
- munmap(data, s.st_size);
-fail_close_file:
- close(fd);
-fail_restore_text:
- vt_set_mode(0);
- return -1;
-}
-
diff --git a/init/parser.c b/init/parser.c
deleted file mode 100644
index 6a22d242d..000000000
--- a/init/parser.c
+++ /dev/null
@@ -1,797 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stddef.h>
-#include <ctype.h>
-
-#include "init.h"
-#include "property_service.h"
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
-static list_declare(service_list);
-static list_declare(action_list);
-static list_declare(action_queue);
-
-#define RAW(x...) log_write(6, x)
-
-void DUMP(void)
-{
-#if 0
- struct service *svc;
- struct action *act;
- struct command *cmd;
- struct listnode *node;
- struct listnode *node2;
- struct socketinfo *si;
- int n;
-
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- RAW("service %s\n", svc->name);
- RAW(" class '%s'\n", svc->classname);
- RAW(" exec");
- for (n = 0; n < svc->nargs; n++) {
- RAW(" '%s'", svc->args[n]);
- }
- RAW("\n");
- for (si = svc->sockets; si; si = si->next) {
- RAW(" socket %s %s 0%o\n", si->name, si->type, si->perm);
- }
- }
-
- list_for_each(node, &action_list) {
- act = node_to_item(node, struct action, alist);
- RAW("on %s\n", act->name);
- list_for_each(node2, &act->commands) {
- cmd = node_to_item(node2, struct command, clist);
- RAW(" %p", cmd->func);
- for (n = 0; n < cmd->nargs; n++) {
- RAW(" %s", cmd->args[n]);
- }
- RAW("\n");
- }
- RAW("\n");
- }
-#endif
-}
-
-#define MAXARGS 64
-
-#define T_EOF 0
-#define T_TEXT 1
-#define T_NEWLINE 2
-
-struct parse_state
-{
- char *ptr;
- char *text;
- int line;
- int nexttoken;
- void *context;
- void (*parse_line)(struct parse_state *state, int nargs, char **args);
- const char *filename;
-};
-
-static void *parse_service(struct parse_state *state, int nargs, char **args);
-static void parse_line_service(struct parse_state *state, int nargs, char **args);
-
-static void *parse_action(struct parse_state *state, int nargs, char **args);
-static void parse_line_action(struct parse_state *state, int nargs, char **args);
-
-void parse_error(struct parse_state *state, const char *fmt, ...)
-{
- va_list ap;
- char buf[128];
- int off;
-
- snprintf(buf, 128, "%s: %d: ", state->filename, state->line);
- buf[127] = 0;
- off = strlen(buf);
-
- va_start(ap, fmt);
- vsnprintf(buf + off, 128 - off, fmt, ap);
- va_end(ap);
- buf[127] = 0;
- ERROR("%s", buf);
-}
-
-#define SECTION 0x01
-#define COMMAND 0x02
-#define OPTION 0x04
-
-#include "keywords.h"
-
-#define KEYWORD(symbol, flags, nargs, func) \
- [ K_##symbol ] = { #symbol, func, nargs + 1, flags, },
-
-struct {
- const char *name;
- int (*func)(int nargs, char **args);
- unsigned char nargs;
- unsigned char flags;
-} keyword_info[KEYWORD_COUNT] = {
- [ K_UNKNOWN ] = { "unknown", 0, 0, 0 },
-#include "keywords.h"
-};
-#undef KEYWORD
-
-#define kw_is(kw, type) (keyword_info[kw].flags & (type))
-#define kw_name(kw) (keyword_info[kw].name)
-#define kw_func(kw) (keyword_info[kw].func)
-#define kw_nargs(kw) (keyword_info[kw].nargs)
-
-int lookup_keyword(const char *s)
-{
- switch (*s++) {
- case 'c':
- if (!strcmp(s, "apability")) return K_capability;
- if (!strcmp(s, "lass")) return K_class;
- if (!strcmp(s, "lass_start")) return K_class_start;
- if (!strcmp(s, "lass_stop")) return K_class_stop;
- if (!strcmp(s, "onsole")) return K_console;
- if (!strcmp(s, "hown")) return K_chown;
- if (!strcmp(s, "hmod")) return K_chmod;
- if (!strcmp(s, "ritical")) return K_critical;
- break;
- case 'd':
- if (!strcmp(s, "isabled")) return K_disabled;
- if (!strcmp(s, "omainname")) return K_domainname;
- if (!strcmp(s, "evice")) return K_device;
- break;
- case 'e':
- if (!strcmp(s, "xec")) return K_exec;
- if (!strcmp(s, "xport")) return K_export;
- break;
- case 'g':
- if (!strcmp(s, "roup")) return K_group;
- break;
- case 'h':
- if (!strcmp(s, "ostname")) return K_hostname;
- break;
- case 'i':
- if (!strcmp(s, "fup")) return K_ifup;
- if (!strcmp(s, "nsmod")) return K_insmod;
- if (!strcmp(s, "mport")) return K_import;
- break;
- case 'k':
- if (!strcmp(s, "eycodes")) return K_keycodes;
- break;
- case 'l':
- if (!strcmp(s, "oglevel")) return K_loglevel;
- break;
- case 'm':
- if (!strcmp(s, "kdir")) return K_mkdir;
- if (!strcmp(s, "ount")) return K_mount;
- break;
- case 'o':
- if (!strcmp(s, "n")) return K_on;
- if (!strcmp(s, "neshot")) return K_oneshot;
- if (!strcmp(s, "nrestart")) return K_onrestart;
- break;
- case 'r':
- if (!strcmp(s, "estart")) return K_restart;
- break;
- case 's':
- if (!strcmp(s, "ervice")) return K_service;
- if (!strcmp(s, "etenv")) return K_setenv;
- if (!strcmp(s, "etkey")) return K_setkey;
- if (!strcmp(s, "etprop")) return K_setprop;
- if (!strcmp(s, "etrlimit")) return K_setrlimit;
- if (!strcmp(s, "ocket")) return K_socket;
- if (!strcmp(s, "tart")) return K_start;
- if (!strcmp(s, "top")) return K_stop;
- if (!strcmp(s, "ymlink")) return K_symlink;
- if (!strcmp(s, "ysclktz")) return K_sysclktz;
- break;
- case 't':
- if (!strcmp(s, "rigger")) return K_trigger;
- break;
- case 'u':
- if (!strcmp(s, "ser")) return K_user;
- break;
- case 'w':
- if (!strcmp(s, "rite")) return K_write;
- break;
- }
- return K_UNKNOWN;
-}
-
-void parse_line_no_op(struct parse_state *state, int nargs, char **args)
-{
-}
-
-int next_token(struct parse_state *state)
-{
- char *x = state->ptr;
- char *s;
-
- if (state->nexttoken) {
- int t = state->nexttoken;
- state->nexttoken = 0;
- return t;
- }
-
- for (;;) {
- switch (*x) {
- case 0:
- state->ptr = x;
- return T_EOF;
- case '\n':
- state->line++;
- x++;
- state->ptr = x;
- return T_NEWLINE;
- case ' ':
- case '\t':
- case '\r':
- x++;
- continue;
- case '#':
- while (*x && (*x != '\n')) x++;
- state->line++;
- state->ptr = x;
- return T_NEWLINE;
- default:
- goto text;
- }
- }
-
-textdone:
- state->ptr = x;
- *s = 0;
- return T_TEXT;
-text:
- state->text = s = x;
-textresume:
- for (;;) {
- switch (*x) {
- case 0:
- goto textdone;
- case ' ':
- case '\t':
- case '\r':
- x++;
- goto textdone;
- case '\n':
- state->nexttoken = T_NEWLINE;
- x++;
- goto textdone;
- case '"':
- x++;
- for (;;) {
- switch (*x) {
- case 0:
- /* unterminated quoted thing */
- state->ptr = x;
- return T_EOF;
- case '"':
- x++;
- goto textresume;
- default:
- *s++ = *x++;
- }
- }
- break;
- case '\\':
- x++;
- switch (*x) {
- case 0:
- goto textdone;
- case 'n':
- *s++ = '\n';
- break;
- case 'r':
- *s++ = '\r';
- break;
- case 't':
- *s++ = '\t';
- break;
- case '\\':
- *s++ = '\\';
- break;
- case '\r':
- /* \ <cr> <lf> -> line continuation */
- if (x[1] != '\n') {
- x++;
- continue;
- }
- case '\n':
- /* \ <lf> -> line continuation */
- state->line++;
- x++;
- /* eat any extra whitespace */
- while((*x == ' ') || (*x == '\t')) x++;
- continue;
- default:
- /* unknown escape -- just copy */
- *s++ = *x++;
- }
- continue;
- default:
- *s++ = *x++;
- }
- }
- return T_EOF;
-}
-
-void parse_line(int nargs, char **args)
-{
- int n;
- int id = lookup_keyword(args[0]);
- printf("%s(%d)", args[0], id);
- for (n = 1; n < nargs; n++) {
- printf(" '%s'", args[n]);
- }
- printf("\n");
-}
-
-void parse_new_section(struct parse_state *state, int kw,
- int nargs, char **args)
-{
- printf("[ %s %s ]\n", args[0],
- nargs > 1 ? args[1] : "");
- switch(kw) {
- case K_service:
- state->context = parse_service(state, nargs, args);
- if (state->context) {
- state->parse_line = parse_line_service;
- return;
- }
- break;
- case K_on:
- state->context = parse_action(state, nargs, args);
- if (state->context) {
- state->parse_line = parse_line_action;
- return;
- }
- break;
- }
- state->parse_line = parse_line_no_op;
-}
-
-static void parse_config(const char *fn, char *s)
-{
- struct parse_state state;
- char *args[MAXARGS];
- int nargs;
-
- nargs = 0;
- state.filename = fn;
- state.line = 1;
- state.ptr = s;
- state.nexttoken = 0;
- state.parse_line = parse_line_no_op;
- for (;;) {
- switch (next_token(&state)) {
- case T_EOF:
- state.parse_line(&state, 0, 0);
- return;
- case T_NEWLINE:
- if (nargs) {
- int kw = lookup_keyword(args[0]);
- if (kw_is(kw, SECTION)) {
- state.parse_line(&state, 0, 0);
- parse_new_section(&state, kw, nargs, args);
- } else {
- state.parse_line(&state, nargs, args);
- }
- nargs = 0;
- }
- break;
- case T_TEXT:
- if (nargs < MAXARGS) {
- args[nargs++] = state.text;
- }
- break;
- }
- }
-}
-
-int parse_config_file(const char *fn)
-{
- char *data;
- data = read_file(fn, 0);
- if (!data) return -1;
-
- parse_config(fn, data);
- DUMP();
- return 0;
-}
-
-static int valid_name(const char *name)
-{
- if (strlen(name) > 16) {
- return 0;
- }
- while (*name) {
- if (!isalnum(*name) && (*name != '_') && (*name != '-')) {
- return 0;
- }
- name++;
- }
- return 1;
-}
-
-struct service *service_find_by_name(const char *name)
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- if (!strcmp(svc->name, name)) {
- return svc;
- }
- }
- return 0;
-}
-
-struct service *service_find_by_pid(pid_t pid)
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- if (svc->pid == pid) {
- return svc;
- }
- }
- return 0;
-}
-
-struct service *service_find_by_keychord(int keychord_id)
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- if (svc->keychord_id == keychord_id) {
- return svc;
- }
- }
- return 0;
-}
-
-void service_for_each(void (*func)(struct service *svc))
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- func(svc);
- }
-}
-
-void service_for_each_class(const char *classname,
- void (*func)(struct service *svc))
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- if (!strcmp(svc->classname, classname)) {
- func(svc);
- }
- }
-}
-
-void service_for_each_flags(unsigned matchflags,
- void (*func)(struct service *svc))
-{
- struct listnode *node;
- struct service *svc;
- list_for_each(node, &service_list) {
- svc = node_to_item(node, struct service, slist);
- if (svc->flags & matchflags) {
- func(svc);
- }
- }
-}
-
-void action_for_each_trigger(const char *trigger,
- void (*func)(struct action *act))
-{
- struct listnode *node;
- struct action *act;
- list_for_each(node, &action_list) {
- act = node_to_item(node, struct action, alist);
- if (!strcmp(act->name, trigger)) {
- func(act);
- }
- }
-}
-
-void queue_property_triggers(const char *name, const char *value)
-{
- struct listnode *node;
- struct action *act;
- list_for_each(node, &action_list) {
- act = node_to_item(node, struct action, alist);
- if (!strncmp(act->name, "property:", strlen("property:"))) {
- const char *test = act->name + strlen("property:");
- int name_length = strlen(name);
-
- if (!strncmp(name, test, name_length) &&
- test[name_length] == '=' &&
- !strcmp(test + name_length + 1, value)) {
- action_add_queue_tail(act);
- }
- }
- }
-}
-
-void queue_all_property_triggers()
-{
- struct listnode *node;
- struct action *act;
- list_for_each(node, &action_list) {
- act = node_to_item(node, struct action, alist);
- if (!strncmp(act->name, "property:", strlen("property:"))) {
- /* parse property name and value
- syntax is property:<name>=<value> */
- const char* name = act->name + strlen("property:");
- const char* equals = strchr(name, '=');
- if (equals) {
- char* prop_name[PROP_NAME_MAX + 1];
- const char* value;
- int length = equals - name;
- if (length > PROP_NAME_MAX) {
- ERROR("property name too long in trigger %s", act->name);
- } else {
- memcpy(prop_name, name, length);
- prop_name[length] = 0;
-
- /* does the property exist, and match the trigger value? */
- value = property_get((const char *)&prop_name[0]);
- if (value && !strcmp(equals + 1, value)) {
- action_add_queue_tail(act);
- }
- }
- }
- }
- }
-}
-
-void action_add_queue_tail(struct action *act)
-{
- list_add_tail(&action_queue, &act->qlist);
-}
-
-struct action *action_remove_queue_head(void)
-{
- if (list_empty(&action_queue)) {
- return 0;
- } else {
- struct listnode *node = list_head(&action_queue);
- struct action *act = node_to_item(node, struct action, qlist);
- list_remove(node);
- return act;
- }
-}
-
-static void *parse_service(struct parse_state *state, int nargs, char **args)
-{
- struct service *svc;
- if (nargs < 3) {
- parse_error(state, "services must have a name and a program\n");
- return 0;
- }
- if (!valid_name(args[1])) {
- parse_error(state, "invalid service name '%s'\n", args[1]);
- return 0;
- }
-
- svc = service_find_by_name(args[1]);
- if (svc) {
- parse_error(state, "ignored duplicate definition of service '%s'\n", args[1]);
- return 0;
- }
-
- nargs -= 2;
- svc = calloc(1, sizeof(*svc) + sizeof(char*) * nargs);
- if (!svc) {
- parse_error(state, "out of memory\n");
- return 0;
- }
- svc->name = args[1];
- svc->classname = "default";
- memcpy(svc->args, args + 2, sizeof(char*) * nargs);
- svc->args[nargs] = 0;
- svc->nargs = nargs;
- svc->onrestart.name = "onrestart";
- list_init(&svc->onrestart.commands);
- list_add_tail(&service_list, &svc->slist);
- return svc;
-}
-
-static void parse_line_service(struct parse_state *state, int nargs, char **args)
-{
- struct service *svc = state->context;
- struct command *cmd;
- int i, kw, kw_nargs;
-
- if (nargs == 0) {
- return;
- }
-
- kw = lookup_keyword(args[0]);
- switch (kw) {
- case K_capability:
- break;
- case K_class:
- if (nargs != 2) {
- parse_error(state, "class option requires a classname\n");
- } else {
- svc->classname = args[1];
- }
- break;
- case K_console:
- svc->flags |= SVC_CONSOLE;
- break;
- case K_disabled:
- svc->flags |= SVC_DISABLED;
- break;
- case K_group:
- if (nargs < 2) {
- parse_error(state, "group option requires a group id\n");
- } else if (nargs > NR_SVC_SUPP_GIDS + 2) {
- parse_error(state, "group option accepts at most %d supp. groups\n",
- NR_SVC_SUPP_GIDS);
- } else {
- int n;
- svc->gid = decode_uid(args[1]);
- for (n = 2; n < nargs; n++) {
- svc->supp_gids[n-2] = decode_uid(args[n]);
- }
- svc->nr_supp_gids = n - 2;
- }
- break;
- case K_keycodes:
- if (nargs < 2) {
- parse_error(state, "keycodes option requires atleast one keycode\n");
- } else {
- svc->keycodes = malloc((nargs - 1) * sizeof(svc->keycodes[0]));
- if (!svc->keycodes) {
- parse_error(state, "could not allocate keycodes\n");
- } else {
- svc->nkeycodes = nargs - 1;
- for (i = 1; i < nargs; i++) {
- svc->keycodes[i - 1] = atoi(args[i]);
- }
- }
- }
- break;
- case K_oneshot:
- svc->flags |= SVC_ONESHOT;
- break;
- case K_onrestart:
- nargs--;
- args++;
- kw = lookup_keyword(args[0]);
- if (!kw_is(kw, COMMAND)) {
- parse_error(state, "invalid command '%s'\n", args[0]);
- break;
- }
- kw_nargs = kw_nargs(kw);
- if (nargs < kw_nargs) {
- parse_error(state, "%s requires %d %s\n", args[0], kw_nargs - 1,
- kw_nargs > 2 ? "arguments" : "argument");
- break;
- }
-
- cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
- cmd->func = kw_func(kw);
- cmd->nargs = nargs;
- memcpy(cmd->args, args, sizeof(char*) * nargs);
- list_add_tail(&svc->onrestart.commands, &cmd->clist);
- break;
- case K_critical:
- svc->flags |= SVC_CRITICAL;
- break;
- case K_setenv: { /* name value */
- struct svcenvinfo *ei;
- if (nargs < 2) {
- parse_error(state, "setenv option requires name and value arguments\n");
- break;
- }
- ei = calloc(1, sizeof(*ei));
- if (!ei) {
- parse_error(state, "out of memory\n");
- break;
- }
- ei->name = args[1];
- ei->value = args[2];
- ei->next = svc->envvars;
- svc->envvars = ei;
- break;
- }
- case K_socket: {/* name type perm [ uid gid ] */
- struct socketinfo *si;
- if (nargs < 4) {
- parse_error(state, "socket option requires name, type, perm arguments\n");
- break;
- }
- if (strcmp(args[2],"dgram") && strcmp(args[2],"stream")) {
- parse_error(state, "socket type must be 'dgram' or 'stream'\n");
- break;
- }
- si = calloc(1, sizeof(*si));
- if (!si) {
- parse_error(state, "out of memory\n");
- break;
- }
- si->name = args[1];
- si->type = args[2];
- si->perm = strtoul(args[3], 0, 8);
- if (nargs > 4)
- si->uid = decode_uid(args[4]);
- if (nargs > 5)
- si->gid = decode_uid(args[5]);
- si->next = svc->sockets;
- svc->sockets = si;
- break;
- }
- case K_user:
- if (nargs != 2) {
- parse_error(state, "user option requires a user id\n");
- } else {
- svc->uid = decode_uid(args[1]);
- }
- break;
- default:
- parse_error(state, "invalid option '%s'\n", args[0]);
- }
-}
-
-static void *parse_action(struct parse_state *state, int nargs, char **args)
-{
- struct action *act;
- if (nargs < 2) {
- parse_error(state, "actions must have a trigger\n");
- return 0;
- }
- if (nargs > 2) {
- parse_error(state, "actions may not have extra parameters\n");
- return 0;
- }
- act = calloc(1, sizeof(*act));
- act->name = args[1];
- list_init(&act->commands);
- list_add_tail(&action_list, &act->alist);
- /* XXX add to hash */
- return act;
-}
-
-static void parse_line_action(struct parse_state* state, int nargs, char **args)
-{
- struct command *cmd;
- struct action *act = state->context;
- int (*func)(int nargs, char **args);
- int kw, n;
-
- if (nargs == 0) {
- return;
- }
-
- kw = lookup_keyword(args[0]);
- if (!kw_is(kw, COMMAND)) {
- parse_error(state, "invalid command '%s'\n", args[0]);
- return;
- }
-
- n = kw_nargs(kw);
- if (nargs < n) {
- parse_error(state, "%s requires %d %s\n", args[0], n - 1,
- n > 2 ? "arguments" : "argument");
- return;
- }
- cmd = malloc(sizeof(*cmd) + sizeof(char*) * nargs);
- cmd->func = kw_func(kw);
- cmd->nargs = nargs;
- memcpy(cmd->args, args, sizeof(char*) * nargs);
- list_add_tail(&act->commands, &cmd->clist);
-}
diff --git a/init/property_service.c b/init/property_service.c
deleted file mode 100644
index 7a6416b5e..000000000
--- a/init/property_service.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <stdarg.h>
-#include <dirent.h>
-#include <limits.h>
-#include <errno.h>
-
-#include <cutils/misc.h>
-#include <cutils/sockets.h>
-#include <cutils/ashmem.h>
-
-#define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
-#include <sys/_system_properties.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/select.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-#include <sys/mman.h>
-#include <sys/atomics.h>
-#include <private/android_filesystem_config.h>
-
-#include "property_service.h"
-#include "init.h"
-
-#define PERSISTENT_PROPERTY_DIR "/data/property"
-
-static int persistent_properties_loaded = 0;
-
-/* White list of permissions for setting property services. */
-struct {
- const char *prefix;
- unsigned int uid;
-} property_perms[] = {
- { "net.rmnet0.", AID_RADIO },
- { "net.gprs.", AID_RADIO },
- { "ril.", AID_RADIO },
- { "gsm.", AID_RADIO },
- { "net.dns", AID_RADIO },
- { "net.", AID_SYSTEM },
- { "dev.", AID_SYSTEM },
- { "runtime.", AID_SYSTEM },
- { "hw.", AID_SYSTEM },
- { "sys.", AID_SYSTEM },
- { "service.", AID_SYSTEM },
- { "wlan.", AID_SYSTEM },
- { "dhcp.", AID_SYSTEM },
- { "dhcp.", AID_DHCP },
- { "debug.", AID_SHELL },
- { "log.", AID_SHELL },
- { "persist.sys.", AID_SYSTEM },
- { "persist.service.", AID_SYSTEM },
- { NULL, 0 }
-};
-
-/*
- * White list of UID that are allowed to start/stop services.
- * Currently there are no user apps that require.
- */
-struct {
- const char *service;
- unsigned int uid;
-} control_perms[] = {
- {NULL, 0 }
-};
-
-typedef struct {
- void *data;
- size_t size;
- int fd;
-} workspace;
-
-static int init_workspace(workspace *w, size_t size)
-{
- void *data;
- int fd;
-
- fd = ashmem_create_region("system_properties", size);
- if(fd < 0)
- return -1;
-
- data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if(data == MAP_FAILED)
- goto out;
-
- /* allow the wolves we share with to do nothing but read */
- ashmem_set_prot_region(fd, PROT_READ);
-
- w->data = data;
- w->size = size;
- w->fd = fd;
-
- return 0;
-
-out:
- close(fd);
- return -1;
-}
-
-/* (8 header words + 247 toc words) = 1020 bytes */
-/* 1024 bytes header and toc + 247 prop_infos @ 128 bytes = 32640 bytes */
-
-#define PA_COUNT_MAX 247
-#define PA_INFO_START 1024
-#define PA_SIZE 32768
-
-static workspace pa_workspace;
-static prop_info *pa_info_array;
-
-extern prop_area *__system_property_area__;
-
-static int init_property_area(void)
-{
- prop_area *pa;
-
- if(pa_info_array)
- return -1;
-
- if(init_workspace(&pa_workspace, PA_SIZE))
- return -1;
-
- fcntl(pa_workspace.fd, F_SETFD, FD_CLOEXEC);
-
- pa_info_array = (void*) (((char*) pa_workspace.data) + PA_INFO_START);
-
- pa = pa_workspace.data;
- memset(pa, 0, PA_SIZE);
- pa->magic = PROP_AREA_MAGIC;
- pa->version = PROP_AREA_VERSION;
-
- /* plug into the lib property services */
- __system_property_area__ = pa;
-
- return 0;
-}
-
-static void update_prop_info(prop_info *pi, const char *value, unsigned len)
-{
- pi->serial = pi->serial | 1;
- memcpy(pi->value, value, len + 1);
- pi->serial = (len << 24) | ((pi->serial + 1) & 0xffffff);
- __futex_wake(&pi->serial, INT32_MAX);
-}
-
-static int property_write(prop_info *pi, const char *value)
-{
- int valuelen = strlen(value);
- if(valuelen >= PROP_VALUE_MAX) return -1;
- update_prop_info(pi, value, valuelen);
- return 0;
-}
-
-
-/*
- * Checks permissions for starting/stoping system services.
- * AID_SYSTEM and AID_ROOT are always allowed.
- *
- * Returns 1 if uid allowed, 0 otherwise.
- */
-static int check_control_perms(const char *name, int uid) {
- int i;
- if (uid == AID_SYSTEM || uid == AID_ROOT)
- return 1;
-
- /* Search the ACL */
- for (i = 0; control_perms[i].service; i++) {
- if (strcmp(control_perms[i].service, name) == 0) {
- if (control_perms[i].uid == uid)
- return 1;
- }
- }
- return 0;
-}
-
-/*
- * Checks permissions for setting system properties.
- * Returns 1 if uid allowed, 0 otherwise.
- */
-static int check_perms(const char *name, unsigned int uid)
-{
- int i;
- if (uid == 0)
- return 1;
-
- if(!strncmp(name, "ro.", 3))
- name +=3;
-
- for (i = 0; property_perms[i].prefix; i++) {
- int tmp;
- if (strncmp(property_perms[i].prefix, name,
- strlen(property_perms[i].prefix)) == 0) {
- if (property_perms[i].uid == uid) {
- return 1;
- }
- }
- }
-
- return 0;
-}
-
-const char* property_get(const char *name)
-{
- prop_info *pi;
-
- if(strlen(name) >= PROP_NAME_MAX) return 0;
-
- pi = (prop_info*) __system_property_find(name);
-
- if(pi != 0) {
- return pi->value;
- } else {
- return 0;
- }
-}
-
-static void write_peristent_property(const char *name, const char *value)
-{
- const char *tempPath = PERSISTENT_PROPERTY_DIR "/.temp";
- char path[PATH_MAX];
- int fd, length;
-
- snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, name);
-
- fd = open(tempPath, O_WRONLY|O_CREAT|O_TRUNC, 0600);
- if (fd < 0) {
- ERROR("Unable to write persistent property to temp file %s errno: %d\n", tempPath, errno);
- return;
- }
- write(fd, value, strlen(value));
- close(fd);
-
- if (rename(tempPath, path)) {
- unlink(tempPath);
- ERROR("Unable to rename persistent property file %s to %s\n", tempPath, path);
- }
-}
-
-int property_set(const char *name, const char *value)
-{
- prop_area *pa;
- prop_info *pi;
-
- int namelen = strlen(name);
- int valuelen = strlen(value);
-
- if(namelen >= PROP_NAME_MAX) return -1;
- if(valuelen >= PROP_VALUE_MAX) return -1;
- if(namelen < 1) return -1;
-
- pi = (prop_info*) __system_property_find(name);
-
- if(pi != 0) {
- /* ro.* properties may NEVER be modified once set */
- if(!strncmp(name, "ro.", 3)) return -1;
-
- pa = __system_property_area__;
- update_prop_info(pi, value, valuelen);
- pa->serial++;
- __futex_wake(&pa->serial, INT32_MAX);
- } else {
- pa = __system_property_area__;
- if(pa->count == PA_COUNT_MAX) return -1;
-
- pi = pa_info_array + pa->count;
- pi->serial = (valuelen << 24);
- memcpy(pi->name, name, namelen + 1);
- memcpy(pi->value, value, valuelen + 1);
-
- pa->toc[pa->count] =
- (namelen << 24) | (((unsigned) pi) - ((unsigned) pa));
-
- pa->count++;
- pa->serial++;
- __futex_wake(&pa->serial, INT32_MAX);
- }
- /* If name starts with "net." treat as a DNS property. */
- if (strncmp("net.", name, sizeof("net.") - 1) == 0) {
- if (strcmp("net.change", name) == 0) {
- return 0;
- }
- /*
- * The 'net.change' property is a special property used track when any
- * 'net.*' property name is updated. It is _ONLY_ updated here. Its value
- * contains the last updated 'net.*' property.
- */
- property_set("net.change", name);
- } else if (persistent_properties_loaded &&
- strncmp("persist.", name, sizeof("persist.") - 1) == 0) {
- /*
- * Don't write properties to disk until after we have read all default properties
- * to prevent them from being overwritten by default values.
- */
- write_peristent_property(name, value);
- }
- property_changed(name, value);
- return 0;
-}
-
-static int property_list(void (*propfn)(const char *key, const char *value, void *cookie),
- void *cookie)
-{
- char name[PROP_NAME_MAX];
- char value[PROP_VALUE_MAX];
- const prop_info *pi;
- unsigned n;
-
- for(n = 0; (pi = __system_property_find_nth(n)); n++) {
- __system_property_read(pi, name, value);
- propfn(name, value, cookie);
- }
- return 0;
-}
-
-void handle_property_set_fd(int fd)
-{
- prop_msg msg;
- int s;
- int r;
- int res;
- struct ucred cr;
- struct sockaddr_un addr;
- socklen_t addr_size = sizeof(addr);
- socklen_t cr_size = sizeof(cr);
-
- if ((s = accept(fd, (struct sockaddr *) &addr, &addr_size)) < 0) {
- return;
- }
-
- /* Check socket options here */
- if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cr, &cr_size) < 0) {
- close(s);
- ERROR("Unable to recieve socket options\n");
- return;
- }
-
- r = recv(s, &msg, sizeof(msg), 0);
- close(s);
- if(r != sizeof(prop_msg)) {
- ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n",
- r, sizeof(prop_msg));
- return;
- }
-
- switch(msg.cmd) {
- case PROP_MSG_SETPROP:
- msg.name[PROP_NAME_MAX-1] = 0;
- msg.value[PROP_VALUE_MAX-1] = 0;
-
- if(memcmp(msg.name,"ctl.",4) == 0) {
- if (check_control_perms(msg.value, cr.uid)) {
- handle_control_message((char*) msg.name + 4, (char*) msg.value);
- } else {
- ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n",
- msg.name + 4, msg.value, cr.uid, cr.pid);
- }
- } else {
- if (check_perms(msg.name, cr.uid)) {
- property_set((char*) msg.name, (char*) msg.value);
- } else {
- ERROR("sys_prop: permission denied uid:%d name:%s\n",
- cr.uid, msg.name);
- }
- }
- break;
-
- default:
- break;
- }
-}
-
-void get_property_workspace(int *fd, int *sz)
-{
- *fd = pa_workspace.fd;
- *sz = pa_workspace.size;
-}
-
-static void load_properties(char *data)
-{
- char *key, *value, *eol, *sol, *tmp;
-
- sol = data;
- while((eol = strchr(sol, '\n'))) {
- key = sol;
- *eol++ = 0;
- sol = eol;
-
- value = strchr(key, '=');
- if(value == 0) continue;
- *value++ = 0;
-
- while(isspace(*key)) key++;
- if(*key == '#') continue;
- tmp = value - 2;
- while((tmp > key) && isspace(*tmp)) *tmp-- = 0;
-
- while(isspace(*value)) value++;
- tmp = eol - 2;
- while((tmp > value) && isspace(*tmp)) *tmp-- = 0;
-
- property_set(key, value);
- }
-}
-
-static void load_properties_from_file(const char *fn)
-{
- char *data;
- unsigned sz;
-
- data = read_file(fn, &sz);
-
- if(data != 0) {
- load_properties(data);
- free(data);
- }
-}
-
-static void load_persistent_properties()
-{
- DIR* dir = opendir(PERSISTENT_PROPERTY_DIR);
- struct dirent* entry;
- char path[PATH_MAX];
- char value[PROP_VALUE_MAX];
- int fd, length;
-
- if (dir) {
- while ((entry = readdir(dir)) != NULL) {
- if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..") ||
- strncmp("persist.", entry->d_name, sizeof("persist.") - 1))
- continue;
-#if HAVE_DIRENT_D_TYPE
- if (entry->d_type != DT_REG)
- continue;
-#endif
- /* open the file and read the property value */
- snprintf(path, sizeof(path), "%s/%s", PERSISTENT_PROPERTY_DIR, entry->d_name);
- fd = open(path, O_RDONLY);
- if (fd >= 0) {
- length = read(fd, value, sizeof(value) - 1);
- if (length >= 0) {
- value[length] = 0;
- property_set(entry->d_name, value);
- } else {
- ERROR("Unable to read persistent property file %s errno: %d\n", path, errno);
- }
- close(fd);
- } else {
- ERROR("Unable to open persistent property file %s errno: %d\n", path, errno);
- }
- }
- closedir(dir);
- } else {
- ERROR("Unable to open persistent property directory %s errno: %d\n", PERSISTENT_PROPERTY_DIR, errno);
- }
-
- persistent_properties_loaded = 1;
-}
-
-void property_init(void)
-{
- init_property_area();
- load_properties_from_file(PROP_PATH_RAMDISK_DEFAULT);
-}
-
-int start_property_service(void)
-{
- int fd;
-
- load_properties_from_file(PROP_PATH_SYSTEM_BUILD);
- load_properties_from_file(PROP_PATH_SYSTEM_DEFAULT);
- load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE);
- /* Read persistent properties after all default values have been loaded. */
- load_persistent_properties();
-
- fd = create_socket(PROP_SERVICE_NAME, SOCK_STREAM, 0666, 0, 0);
- if(fd < 0) return -1;
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- fcntl(fd, F_SETFL, O_NONBLOCK);
-
- listen(fd, 8);
- return fd;
-}
diff --git a/init/property_service.h b/init/property_service.h
deleted file mode 100644
index d12f1f38b..000000000
--- a/init/property_service.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _INIT_PROPERTY_H
-#define _INIT_PROPERTY_H
-
-extern void handle_property_fd(int fd);
-extern void handle_property_set_fd(int fd);
-extern void property_init(void);
-extern int start_property_service(void);
-void get_property_workspace(int *fd, int *sz);
-extern const char* property_get(const char *name);
-extern int property_set(const char *name, const char *value);
-
-#endif /* _INIT_PROPERTY_H */
diff --git a/init/readme.txt b/init/readme.txt
deleted file mode 100644
index 665090bad..000000000
--- a/init/readme.txt
+++ /dev/null
@@ -1,293 +0,0 @@
-
-Android Init Language
----------------------
-
-The Android Init Language consists of four broad classes of statements,
-which are Actions, Commands, Services, and Options.
-
-All of these are line-oriented, consisting of tokens separated by
-whitespace. The c-style backslash escapes may be used to insert
-whitespace into a token. Double quotes may also be used to prevent
-whitespace from breaking text into multiple tokens. The backslash,
-when it is the last character on a line, may be used for line-folding.
-
-Lines which start with a # (leading whitespace allowed) are comments.
-
-Actions and Services implicitly declare a new section. All commands
-or options belong to the section most recently declared. Commands
-or options before the first section are ignored.
-
-Actions and Services have unique names. If a second Action or Service
-is declared with the same name as an existing one, it is ignored as
-an error. (??? should we override instead)
-
-
-Actions
--------
-Actions are named sequences of commands. Actions have a trigger which
-is used to determine when the action should occur. When an event
-occurs which matches an action's trigger, that action is added to
-the tail of a to-be-executed queue (unless it is already on the
-queue).
-
-Each action in the queue is dequeued in sequence and each command in
-that action is executed in sequence. Init handles other activities
-(device creation/destruction, property setting, process restarting)
-"between" the execution of the commands in activities.
-
-Actions take the form of:
-
-on <trigger>
- <command>
- <command>
- <command>
-
-
-Services
---------
-Services are programs which init launches and (optionally) restarts
-when they exit. Services take the form of:
-
-service <name> <pathname> [ <argument> ]*
- <option>
- <option>
- ...
-
-
-Options
--------
-Options are modifiers to services. They affect how and when init
-runs the service.
-
-critical
- This is a device-critical service. If it exits more than four times in
- four minutes, the device will reboot into recovery mode.
-
-disabled
- This service will not automatically start with its class.
- It must be explicitly started by name.
-
-setenv <name> <value>
- Set the environment variable <name> to <value> in the launched process.
-
-socket <name> <type> <perm> [ <user> [ <group> ] ]
- Create a unix domain socket named /dev/socket/<name> and pass
- its fd to the launched process. <type> must be "dgram" or "stream".
- User and group default to 0.
-
-user <username>
- Change to username before exec'ing this service.
- Currently defaults to root. (??? probably should default to nobody)
- Currently, if your process requires linux capabilities then you cannot use
- this command. You must instead request the capabilities in-process while
- still root, and then drop to your desired uid.
-
-group <groupname> [ <groupname> ]*
- Change to groupname before exec'ing this service. Additional
- groupnames beyond the (required) first one are used to set the
- supplemental groups of the process (via setgroups()).
- Currently defaults to root. (??? probably should default to nobody)
-
-oneshot
- Do not restart the service when it exits.
-
-class <name>
- Specify a class name for the service. All services in a
- named class may be started or stopped together. A service
- is in the class "default" if one is not specified via the
- class option.
-
-onrestart
- Execute a Command (see below) when service restarts.
-
-Triggers
---------
- Triggers are strings which can be used to match certain kinds
- of events and used to cause an action to occur.
-
-boot
- This is the first trigger that will occur when init starts
- (after /init.conf is loaded)
-
-<name>=<value>
- Triggers of this form occur when the property <name> is set
- to the specific value <value>.
-
-device-added-<path>
-device-removed-<path>
- Triggers of these forms occur when a device node is added
- or removed.
-
-service-exited-<name>
- Triggers of this form occur when the specified service exits.
-
-
-Commands
---------
-
-exec <path> [ <argument> ]*
- Fork and execute a program (<path>). This will block until
- the program completes execution. It is best to avoid exec
- as unlike the builtin commands, it runs the risk of getting
- init "stuck". (??? maybe there should be a timeout?)
-
-export <name> <value>
- Set the environment variable <name> equal to <value> in the
- global environment (which will be inherited by all processes
- started after this command is executed)
-
-ifup <interface>
- Bring the network interface <interface> online.
-
-import <filename>
- Parse an init config file, extending the current configuration.
-
-hostname <name>
- Set the host name.
-
-chmod <octal-mode> <path>
- Change file access permissions.
-
-chown <owner> <group> <path>
- Change file owner and group.
-
-class_start <serviceclass>
- Start all services of the specified class if they are
- not already running.
-
-class_stop <serviceclass>
- Stop all services of the specified class if they are
- currently running.
-
-domainname <name>
- Set the domain name.
-
-insmod <path>
- Install the module at <path>
-
-mkdir <path> [mode] [owner] [group]
- Create a directory at <path>, optionally with the given mode, owner, and
- group. If not provided, the directory is created with permissions 755 and
- owned by the root user and root group.
-
-mount <type> <device> <dir> [ <mountoption> ]*
- Attempt to mount the named device at the directory <dir>
- <device> may be of the form mtd@name to specify a mtd block
- device by name.
- <mountoption>s include "ro", "rw", "remount", "noatime", ...
-
-setkey
- TBD
-
-setprop <name> <value>
- Set system property <name> to <value>.
-
-setrlimit <resource> <cur> <max>
- Set the rlimit for a resource.
-
-start <service>
- Start a service running if it is not already running.
-
-stop <service>
- Stop a service from running if it is currently running.
-
-symlink <target> <path>
- Create a symbolic link at <path> with the value <target>
-
-sysclktz <mins_west_of_gmt>
- Set the system clock base (0 if system clock ticks in GMT)
-
-trigger <event>
- Trigger an event. Used to queue an action from another
- action.
-
-write <path> <string> [ <string> ]*
- Open the file at <path> and write one or more strings
- to it with write(2)
-
-
-Properties
-----------
-Init updates some system properties to provide some insight into
-what it's doing:
-
-init.action
- Equal to the name of the action currently being executed or "" if none
-
-init.command
- Equal to the command being executed or "" if none.
-
-init.svc.<name>
- State of a named service ("stopped", "running", "restarting")
-
-
-Example init.conf
------------------
-
-# not complete -- just providing some examples of usage
-#
-on boot
- export PATH /sbin:/system/sbin:/system/bin
- export LD_LIBRARY_PATH /system/lib
-
- mkdir /dev
- mkdir /proc
- mkdir /sys
-
- mount tmpfs tmpfs /dev
- mkdir /dev/pts
- mkdir /dev/socket
- mount devpts devpts /dev/pts
- mount proc proc /proc
- mount sysfs sysfs /sys
-
- write /proc/cpu/alignment 4
-
- ifup lo
-
- hostname localhost
- domainname localhost
-
- mount yaffs2 mtd@system /system
- mount yaffs2 mtd@userdata /data
-
- import /system/etc/init.conf
-
- class_start default
-
-service adbd /sbin/adbd
- user adb
- group adb
-
-service usbd /system/bin/usbd -r
- user usbd
- group usbd
- socket usbd 666
-
-service zygote /system/bin/app_process -Xzygote /system/bin --zygote
- socket zygote 666
-
-service runtime /system/bin/runtime
- user system
- group system
-
-on device-added-/dev/compass
- start akmd
-
-on device-removed-/dev/compass
- stop akmd
-
-service akmd /sbin/akmd
- disabled
- user akmd
- group akmd
-
-Debugging notes
----------------
-By default, programs executed by init will drop stdout and stderr into
-/dev/null. To help with debugging, you can execute your program via the
-Andoird program logwrapper. This will redirect stdout/stderr into the
-Android logging system (accessed via logcat).
-
-For example
-service akmd /system/bin/logwrapper /sbin/akmd
diff --git a/init/util.c b/init/util.c
deleted file mode 100644
index 0b7667dae..000000000
--- a/init/util.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <stdarg.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <ctype.h>
-#include <errno.h>
-
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-
-/* for ANDROID_SOCKET_* */
-#include <cutils/sockets.h>
-
-#include <private/android_filesystem_config.h>
-
-#include "init.h"
-
-static int log_fd = -1;
-/* Inital log level before init.rc is parsed and this this is reset. */
-static int log_level = LOG_DEFAULT_LEVEL;
-
-
-void log_set_level(int level) {
- log_level = level;
-}
-
-void log_init(void)
-{
- static const char *name = "/dev/__kmsg__";
- if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) {
- log_fd = open(name, O_WRONLY);
- fcntl(log_fd, F_SETFD, FD_CLOEXEC);
- unlink(name);
- }
-}
-
-#define LOG_BUF_MAX 512
-
-void log_write(int level, const char *fmt, ...)
-{
- char buf[LOG_BUF_MAX];
- va_list ap;
-
- if (level > log_level) return;
- if (log_fd < 0) return;
-
- va_start(ap, fmt);
- vsnprintf(buf, LOG_BUF_MAX, fmt, ap);
- buf[LOG_BUF_MAX - 1] = 0;
- va_end(ap);
- write(log_fd, buf, strlen(buf));
-}
-
-/*
- * android_name_to_id - returns the integer uid/gid associated with the given
- * name, or -1U on error.
- */
-static unsigned int android_name_to_id(const char *name)
-{
- struct android_id_info *info = android_ids;
- unsigned int n;
-
- for (n = 0; n < android_id_count; n++) {
- if (!strcmp(info[n].name, name))
- return info[n].aid;
- }
-
- return -1U;
-}
-
-/*
- * decode_uid - decodes and returns the given string, which can be either the
- * numeric or name representation, into the integer uid or gid. Returns -1U on
- * error.
- */
-unsigned int decode_uid(const char *s)
-{
- unsigned int v;
-
- if (!s || *s == '\0')
- return -1U;
- if (isalpha(s[0]))
- return android_name_to_id(s);
-
- errno = 0;
- v = (unsigned int) strtoul(s, 0, 0);
- if (errno)
- return -1U;
- return v;
-}
-
-/*
- * create_socket - creates a Unix domain socket in ANDROID_SOCKET_DIR
- * ("/dev/socket") as dictated in init.rc. This socket is inherited by the
- * daemon. We communicate the file descriptor's value via the environment
- * variable ANDROID_SOCKET_ENV_PREFIX<name> ("ANDROID_SOCKET_foo").
- */
-int create_socket(const char *name, int type, mode_t perm, uid_t uid, gid_t gid)
-{
- struct sockaddr_un addr;
- int fd, ret;
-
- fd = socket(PF_UNIX, type, 0);
- if (fd < 0) {
- ERROR("Failed to open socket '%s': %s\n", name, strerror(errno));
- return -1;
- }
-
- memset(&addr, 0 , sizeof(addr));
- addr.sun_family = AF_UNIX;
- snprintf(addr.sun_path, sizeof(addr.sun_path), ANDROID_SOCKET_DIR"/%s",
- name);
-
- ret = unlink(addr.sun_path);
- if (ret != 0 && errno != ENOENT) {
- ERROR("Failed to unlink old socket '%s': %s\n", name, strerror(errno));
- goto out_close;
- }
-
- ret = bind(fd, (struct sockaddr *) &addr, sizeof (addr));
- if (ret) {
- ERROR("Failed to bind socket '%s': %s\n", name, strerror(errno));
- goto out_unlink;
- }
-
- chown(addr.sun_path, uid, gid);
- chmod(addr.sun_path, perm);
-
- INFO("Created socket '%s' with mode '%o', user '%d', group '%d'\n",
- addr.sun_path, perm, uid, gid);
-
- return fd;
-
-out_unlink:
- unlink(addr.sun_path);
-out_close:
- close(fd);
- return -1;
-}
-
-/* reads a file, making sure it is terminated with \n \0 */
-void *read_file(const char *fn, unsigned *_sz)
-{
- char *data;
- int sz;
- int fd;
-
- data = 0;
- fd = open(fn, O_RDONLY);
- if(fd < 0) return 0;
-
- sz = lseek(fd, 0, SEEK_END);
- if(sz < 0) goto oops;
-
- if(lseek(fd, 0, SEEK_SET) != 0) goto oops;
-
- data = (char*) malloc(sz + 2);
- if(data == 0) goto oops;
-
- if(read(fd, data, sz) != sz) goto oops;
- close(fd);
- data[sz] = '\n';
- data[sz+1] = 0;
- if(_sz) *_sz = sz;
- return data;
-
-oops:
- close(fd);
- if(data != 0) free(data);
- return 0;
-}
-
-void list_init(struct listnode *node)
-{
- node->next = node;
- node->prev = node;
-}
-
-void list_add_tail(struct listnode *head, struct listnode *item)
-{
- item->next = head;
- item->prev = head->prev;
- head->prev->next = item;
- head->prev = item;
-}
-
-void list_remove(struct listnode *item)
-{
- item->next->prev = item->prev;
- item->prev->next = item->next;
-}
-