1dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
2dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
3dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
4dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * you may not use this file except in compliance with the License.
6dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * You may obtain a copy of the License at
7dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
8dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
10dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * See the License for the specific language governing permissions and
14dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * limitations under the License.
15dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
16dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
17dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define LOG_TAG "Zygote"
18dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
19dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/sockets.h>
20dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/zygote.h>
21dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <cutils/log.h>
22dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
23dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdio.h>
24dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <string.h>
25dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <errno.h>
26dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <time.h>
27dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdint.h>
28dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <stdlib.h>
29dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <unistd.h>
30dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <arpa/inet.h>
31dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/types.h>
32dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#include <sys/socket.h>
33dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
34dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ZYGOTE_SOCKET "zygote"
35dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
36dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ZYGOTE_RETRY_COUNT 1000
37dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#define ZYGOTE_RETRY_MILLIS 500
38dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
39dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void replace_nl(char *str);
40dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
41dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/*
42dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If sendStdio is non-zero, the current process's stdio file descriptors
43dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * will be sent and inherited by the spawned process.
44dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
45dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic int send_request(int fd, int sendStdio, int argc, const char **argv)
46dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
47dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#ifndef HAVE_ANDROID_OS
48dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // not supported on simulator targets
4901dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block    //ALOGE("zygote_* not supported on simulator targets");
50dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return -1;
51dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#else /* HAVE_ANDROID_OS */
52dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    uint32_t pid;
53dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
54dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct iovec ivs[2];
55dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct msghdr msg;
56dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char argc_buffer[12];
57dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *newline_string = "\n";
58dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    struct cmsghdr *cmsg;
59dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    char msgbuf[CMSG_SPACE(sizeof(int) * 3)];
60dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int *cmsg_payload;
61dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ssize_t ret;
62dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
63dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&msg, 0, sizeof(msg));
64dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memset(&ivs, 0, sizeof(ivs));
65dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
66dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // First line is arg count
67dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    snprintf(argc_buffer, sizeof(argc_buffer), "%d\n", argc);
68dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
69dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ivs[0].iov_base = argc_buffer;
70dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ivs[0].iov_len = strlen(argc_buffer);
71dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
72dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.msg_iov = ivs;
73dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.msg_iovlen = 1;
74dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
75dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (sendStdio != 0) {
76dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        // Pass the file descriptors with the first write
77dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.msg_control = msgbuf;
78dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.msg_controllen = sizeof msgbuf;
79dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
80dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg = CMSG_FIRSTHDR(&msg);
81dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
82dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg->cmsg_len = CMSG_LEN(3 * sizeof(int));
83dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg->cmsg_level = SOL_SOCKET;
84dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg->cmsg_type = SCM_RIGHTS;
85dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
86dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg_payload = (int *)CMSG_DATA(cmsg);
87dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg_payload[0] = STDIN_FILENO;
88dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg_payload[1] = STDOUT_FILENO;
89dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        cmsg_payload[2] = STDERR_FILENO;
90dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
91dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
92dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
93dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
94dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (ret < 0 && errno == EINTR);
95dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
96dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (ret < 0) {
97dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
98dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
99dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
100dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Only send the fd's once
101dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.msg_control = NULL;
102dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.msg_controllen = 0;
103dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
104dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // replace any newlines with spaces and send the args
105dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (i = 0; i < argc; i++) {
106dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        char *tofree = NULL;
107dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        const char *toprint;
108dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
109dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        toprint = argv[i];
110dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
111dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (strchr(toprint, '\n') != NULL) {
112dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            tofree = strdup(toprint);
113dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            toprint = tofree;
114dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            replace_nl(tofree);
115dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
116dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
117dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[0].iov_base = (char *)toprint;
118dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[0].iov_len = strlen(toprint);
119dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[1].iov_base = (char *)newline_string;
120dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[1].iov_len = 1;
121dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
122dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        msg.msg_iovlen = 2;
123dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
124dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
125dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = sendmsg(fd, &msg, MSG_NOSIGNAL);
126dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while (ret < 0 && errno == EINTR);
127dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
128dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (tofree != NULL) {
129dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            free(tofree);
130dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
131dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
132dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret < 0) {
133dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
134dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
135dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
136dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
137dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Read the pid, as a 4-byte network-order integer
138dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
139dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ivs[0].iov_base = &pid;
140dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    ivs[0].iov_len = sizeof(pid);
141dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    msg.msg_iovlen = 1;
142dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
143dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
144dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        do {
145dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ret = recvmsg(fd, &msg, MSG_NOSIGNAL | MSG_WAITALL);
146dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        } while (ret < 0 && errno == EINTR);
147dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
148dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (ret < 0) {
149dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            return -1;
150dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
151dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
152dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[0].iov_len -= ret;
153dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        ivs[0].iov_base += ret;
154dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (ivs[0].iov_len > 0);
155dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
156dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pid = ntohl(pid);
157dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
158dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return pid;
159dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project#endif /* HAVE_ANDROID_OS */
160dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
161dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
162dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint zygote_run_wait(int argc, const char **argv, void (*post_run_func)(int))
163dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
164dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd;
165dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pid;
166dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int err;
167dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char *newargv[argc + 1];
168dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
169dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    fd = socket_local_client(ZYGOTE_SOCKET,
170dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ANDROID_SOCKET_NAMESPACE_RESERVED, AF_LOCAL);
171dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
172dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
173dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
174dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
175dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
176dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // The command socket is passed to the peer as close-on-exec
177dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // and will close when the peer dies
178dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    newargv[0] = "--peer-wait";
179dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    memcpy(newargv + 1, argv, argc * sizeof(*argv));
180dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
181dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pid = send_request(fd, 1, argc + 1, newargv);
182dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
183dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (pid > 0 && post_run_func != NULL) {
184dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        post_run_func(pid);
185dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
186dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
187dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    // Wait for socket to close
188dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
189dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        int dummy;
190dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        err = read(fd, &dummy, sizeof(dummy));
191dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while ((err < 0 && errno == EINTR) || err != 0);
192dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
193dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
194dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        err = close(fd);
195dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (err < 0 && errno == EINTR);
196dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
197dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return 0;
198dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
199dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
200dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
201dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Spawns a new dalvik instance via the Zygote process. The non-zygote
202dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * arguments are passed to com.android.internal.os.RuntimeInit(). The
203dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * first non-option argument should be a class name in the system class path.
204dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
205dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The arg list  may start with zygote params such as --set-uid.
206dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
207dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * If sendStdio is non-zero, the current process's stdio file descriptors
208dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * will be sent and inherited by the spawned process.
209dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
210dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * The pid of the child process is returned, or -1 if an error was
211dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * encountered.
212dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project *
213dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * zygote_run_oneshot waits up to ZYGOTE_RETRY_COUNT *
214dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * ZYGOTE_RETRY_MILLIS for the zygote socket to be available.
215dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
216dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectint zygote_run_oneshot(int sendStdio, int argc, const char **argv)
217dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
218dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int fd = -1;
219dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int err;
220dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int i;
221dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int retries;
222dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    int pid;
223dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const char **newargv = argv;
224dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    const int newargc = argc;
225dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
226dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for (retries = 0; (fd < 0) && (retries < ZYGOTE_RETRY_COUNT); retries++) {
227dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (retries > 0) {
228dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            struct timespec ts;
229dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
230dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            memset(&ts, 0, sizeof(ts));
231dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            ts.tv_nsec = ZYGOTE_RETRY_MILLIS * 1000 * 1000;
232dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
233dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            do {
234dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                err = nanosleep (&ts, &ts);
235dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            } while (err < 0 && errno == EINTR);
236dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
237dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        fd = socket_local_client(ZYGOTE_SOCKET, AF_LOCAL,
238dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project                ANDROID_SOCKET_NAMESPACE_RESERVED);
239dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
240dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
241dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    if (fd < 0) {
242dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        return -1;
243dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
244dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
245dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    pid = send_request(fd, 0, newargc, newargv);
246dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
247dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    do {
248dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        err = close(fd);
249dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    } while (err < 0 && errno == EINTR);
250dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
251dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    return pid;
252dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
253dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
254dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project/**
255dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project * Replaces all occurrances of newline with space.
256dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project */
257dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Projectstatic void replace_nl(char *str)
258dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project{
259dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    for(; *str; str++) {
260dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        if (*str == '\n') {
261dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project            *str = ' ';
262dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project        }
263dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project    }
264dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project}
265dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
266dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
267dd7bc3319deb2b77c5d07a51b7d6cd7e11b5beb0The Android Open Source Project
268