auto import from //depot/cupcake/@135843
diff --git a/libcutils/zygote.c b/libcutils/zygote.c
new file mode 100644
index 0000000..aa060c0
--- /dev/null
+++ b/libcutils/zygote.c
@@ -0,0 +1,267 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Zygote"
+
+#include <cutils/sockets.h>
+#include <cutils/zygote.h>
+#include <cutils/log.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <time.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#define ZYGOTE_SOCKET "zygote"
+
+#define ZYGOTE_RETRY_COUNT 1000
+#define ZYGOTE_RETRY_MILLIS 500
+
+static void replace_nl(char *str);
+
+/*
+ * If sendStdio is non-zero, the current process's stdio file descriptors
+ * will be sent and inherited by the spawned process.
+ */
+static int send_request(int fd, int sendStdio, int argc, const char **argv)
+{
+#ifndef HAVE_ANDROID_OS
+ // not supported on simulator targets
+ //LOGE("zygote_* not supported on simulator targets");
+ return -1;
+#else /* HAVE_ANDROID_OS */
+ uint32_t pid;
+ int i;
+ struct iovec ivs[2];
+ struct msghdr msg;
+ char argc_buffer[12];
+ const char *newline_string = "\n";
+ struct cmsghdr *cmsg;
+ char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
+ int *cmsg_payload;
+ ssize_t ret;
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&ivs, 0, sizeof(ivs));
+
+ // First line is arg count
+ snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
+
+ ivs[0].iov_base = argc_buffer;
+ ivs[0].iov_len = strlen(argc_buffer);
+
+ msg.msg_iov = ivs;
+ msg.msg_iovlen = 1;
+
+ if (sendStdio != 0) {
+ // Pass the file descriptors with the first write
+ msg.msg_control = msgbuf;
+ msg.msg_controllen = sizeof msgbuf;
+
+ cmsg = CMSG_FIRSTHDR(&msg);
+
+ cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+
+ cmsg_payload = (int *)CMSG_DATA(cmsg);
+ cmsg_payload[0] = STDIN_FILENO;
+ cmsg_payload[1] = STDOUT_FILENO;
+ cmsg_payload[2] = STDERR_FILENO;
+ }
+
+ do {
+ ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ // Only send the fd's once
+ msg.msg_control = NULL;
+ msg.msg_controllen = 0;
+
+ // replace any newlines with spaces and send the args
+ for (i = 0; i < argc; i++) {
+ char *tofree = NULL;
+ const char *toprint;
+
+ toprint = argv[i];
+
+ if (strchr(toprint, '\n') != NULL) {
+ tofree = strdup(toprint);
+ toprint = tofree;
+ replace_nl(tofree);
+ }
+
+ ivs[0].iov_base = (char *)toprint;
+ ivs[0].iov_len = strlen(toprint);
+ ivs[1].iov_base = (char *)newline_string;
+ ivs[1].iov_len = 1;
+
+ msg.msg_iovlen = 2;
+
+ do {
+ ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
+ } while (ret < 0 && errno == EINTR);
+
+ if (tofree != NULL) {
+ free(tofree);
+ }
+
+ if (ret < 0) {
+ return -1;
+ }
+ }
+
+ // Read the pid, as a 4-byte network-order integer
+
+ ivs[0].iov_base = &pid;
+ ivs[0].iov_len = sizeof(pid);
+ msg.msg_iovlen = 1;
+
+ do {
+ do {
+ ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
+ } while (ret < 0 && errno == EINTR);
+
+ if (ret < 0) {
+ return -1;
+ }
+
+ ivs[0].iov_len -= ret;
+ ivs[0].iov_base += ret;
+ } while (ivs[0].iov_len > 0);
+
+ pid = ntohl(pid);
+
+ return pid;
+#endif /* HAVE_ANDROID_OS */
+}
+
+int zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
+{
+ int fd;
+ int pid;
+ int err;
+ const char *newargv[argc + 1];
+
+ fd = socket_local_client(ZYGOTE_SOCKET,
+ ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ // The command socket is passed to the peer as close-on-exec
+ // and will close when the peer dies
+ newargv[0] = "--peer-wait";
+ memcpy(newargv + 1, argv, argc * sizeof(*argv));
+
+ pid = send_request(fd, 1, argc + 1, newargv);
+
+ if (pid > 0 && post_run_func != NULL) {
+ post_run_func(pid);
+ }
+
+ // Wait for socket to close
+ do {
+ int dummy;
+ err = read(fd, &dummy, sizeof(dummy));
+ } while ((err < 0 && errno == EINTR) || err != 0);
+
+ do {
+ err = close(fd);
+ } while (err < 0 && errno == EINTR);
+
+ return 0;
+}
+
+/**
+ * Spawns a new dalvik instance via the Zygote process. The non-zygote
+ * arguments are passed to com.android.internal.os.RuntimeInit(). The
+ * first non-option argument should be a class name in the system class path.
+ *
+ * The arg list may start with zygote params such as --set-uid.
+ *
+ * If sendStdio is non-zero, the current process's stdio file descriptors
+ * will be sent and inherited by the spawned process.
+ *
+ * The pid of the child process is returned, or -1 if an error was
+ * encountered.
+ *
+ * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT *
+ * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
+ */
+int zygote_run_oneshot(int sendStdio, int argc, const char **argv)
+{
+ int fd = -1;
+ int err;
+ int i;
+ int retries;
+ int pid;
+ const char **newargv = argv;
+ const int newargc = argc;
+
+ for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
+ if (retries > 0) {
+ struct timespec ts;
+
+ memset(&ts, 0, sizeof(ts));
+ ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
+
+ do {
+ err = nanosleep (&ts, &ts);
+ } while (err < 0 && errno == EINTR);
+ }
+ fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL,
+ ANDROID_SOCKET_NAMESPACE_RESERVED);
+ }
+
+ if (fd < 0) {
+ return -1;
+ }
+
+ pid = send_request(fd, 0, newargc, newargv);
+
+ do {
+ err = close(fd);
+ } while (err < 0 && errno == EINTR);
+
+ return pid;
+}
+
+/**
+ * Replaces all occurrances of newline with space.
+ */
+static void replace_nl(char *str)
+{
+ for(; *str; str++) {
+ if (*str == '\n') {
+ *str = ' ';
+ }
+ }
+}
+
+
+