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 = ' ';
+        }
+    }
+}
+
+
+