1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * you may not use this file except in compliance with the License.
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * You may obtain a copy of the License at
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * See the License for the specific language governing permissions and
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * limitations under the License.
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Thread that reads from stdout/stderr and converts them to log messages.
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (Sort of a hack.)
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include "Dalvik.h"
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <stdlib.h>
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <unistd.h>
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <fcntl.h>
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#include <errno.h>
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFilenoStdout   1
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kFilenoStderr   2
29f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#define kMaxLine    512
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Hold some data.
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
35d862faa2ceae186da5518607505eb942d634ced9Carl Shapirostruct BufferedData {
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char    buf[kMaxLine+1];
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int     count;
38d862faa2ceae186da5518607505eb942d634ced9Carl Shapiro};
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// fwd
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* stdioConverterThreadStart(void* arg);
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool readAndLog(int fd, BufferedData* data, const char* tag);
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Crank up the stdout/stderr converter thread.
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Returns immediately.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
501e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirobool dvmStdioConverterStartup()
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.haltStdioConverter = false;
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmInitMutex(&gDvm.stdioConverterLock);
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_cond_init(&gDvm.stdioConverterCond, NULL);
56f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
570c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    if (pipe(gDvm.stdoutPipe) != 0) {
58e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("pipe failed: %s", strerror(errno));
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
610c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    if (pipe(gDvm.stderrPipe) != 0) {
62e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("pipe failed: %s", strerror(errno));
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
660c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    if (dup2(gDvm.stdoutPipe[1], kFilenoStdout) != kFilenoStdout) {
67e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("dup2(1) failed: %s", strerror(errno));
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
700c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    close(gDvm.stdoutPipe[1]);
710c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    gDvm.stdoutPipe[1] = -1;
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#ifdef HAVE_ANDROID_OS
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* don't redirect stderr on sim -- logs get written there! */
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* (don't need this on the sim anyway) */
750c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    if (dup2(gDvm.stderrPipe[1], kFilenoStderr) != kFilenoStderr) {
76e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("dup2(2) failed: %d %s", errno, strerror(errno));
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
790c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    close(gDvm.stderrPipe[1]);
800c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    gDvm.stderrPipe[1] = -1;
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project#endif
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Create the thread.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.stdioConverterLock);
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (!dvmCreateInternalThread(&gDvm.stdioConverterHandle,
900c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro                                 "Stdio Converter",
910c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro                                 stdioConverterThreadStart,
920c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro                                 NULL)) {
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (!gDvm.stdioConverterReady) {
97b31b30131bbf58280a515c40027aa958b81b5cd6Carl Shapiro        dvmWaitCond(&gDvm.stdioConverterCond, &gDvm.stdioConverterLock);
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.stdioConverterLock);
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Shut down the stdio converter thread if it was started.
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Since we know the thread is just sitting around waiting for something
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * to arrive on stdout, print something.
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
1101e1433e78f560a01744e870c19c162ab88df9dc1Carl Shapirovoid dvmStdioConverterShutdown()
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.haltStdioConverter = true;
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (gDvm.stdioConverterHandle == 0)    // not started, or still starting
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return;
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* print something to wake it up */
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    printf("Shutting down\n");
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    fflush(stdout);
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block    ALOGD("Joining stdio converter...");
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    pthread_join(gDvm.stdioConverterHandle, NULL);
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
123f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Select on stdout/stderr pipes, waiting for activity.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
127f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * DO NOT use printf from here.
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic void* stdioConverterThreadStart(void* arg)
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int cc;
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* tell the main thread that we're ready */
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmLockMutex(&gDvm.stdioConverterLock);
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    gDvm.stdioConverterReady = true;
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    cc = pthread_cond_signal(&gDvm.stdioConverterCond);
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(cc == 0);
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmUnlockMutex(&gDvm.stdioConverterLock);
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* we never do anything that affects the rest of the VM */
141f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(NULL, THREAD_VMWAIT);
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Allocate read buffers.
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
1460c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    BufferedData* stdoutData = new BufferedData;
1470c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    BufferedData* stderrData = new BufferedData;
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    stdoutData->count = stderrData->count = 0;
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Read until shutdown time.
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    while (!gDvm.haltStdioConverter) {
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fd_set readfds;
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int maxFd, fdCount;
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        FD_ZERO(&readfds);
1580c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro        FD_SET(gDvm.stdoutPipe[0], &readfds);
1590c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro        FD_SET(gDvm.stderrPipe[0], &readfds);
1600c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro        maxFd = MAX(gDvm.stdoutPipe[0], gDvm.stderrPipe[0]);
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        fdCount = select(maxFd+1, &readfds, NULL, NULL, NULL);
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (fdCount < 0) {
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (errno != EINTR) {
166c1a4ab9c313d8a3d12007f2dbef7b5a6fa4ac2efSteve Block                ALOGE("select on stdout/stderr failed");
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
169062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("Got EINTR, ignoring");
170f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else if (fdCount == 0) {
171062bf509a77fce9dfcb7e7b2e401cf2a124d83d5Steve Block            ALOGD("WEIRD: select returned zero");
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bool err = false;
1740c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro            if (FD_ISSET(gDvm.stdoutPipe[0], &readfds)) {
1750c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro                err |= !readAndLog(gDvm.stdoutPipe[0], stdoutData,
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "stdout");
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
1780c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro            if (FD_ISSET(gDvm.stderrPipe[0], &readfds)) {
1790c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro                err |= !readAndLog(gDvm.stderrPipe[0], stderrData,
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    "stderr");
181f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
182f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* probably EOF; give up */
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (err) {
185e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block                ALOGW("stdio converter got read error; shutting it down");
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                break;
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1910c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    close(gDvm.stdoutPipe[0]);
1920c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    close(gDvm.stderrPipe[0]);
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
1940c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    delete stdoutData;
1950c32ebc544b8dd1528dc007090abda0be5f31174Carl Shapiro    delete stderrData;
196f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /* change back for shutdown sequence */
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    dvmChangeStatus(NULL, THREAD_RUNNING);
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return NULL;
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * Data is pending on "fd".  Read as much as will fit in "data", then
204f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * write out any full lines and compact "data".
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectstatic bool readAndLog(int fd, BufferedData* data, const char* tag)
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project{
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    ssize_t actual;
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    size_t want;
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    assert(data->count < kMaxLine);
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    want = kMaxLine - data->count;
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    actual = read(fd, data->buf + data->count, want);
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (actual <= 0) {
216e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block        ALOGW("read %s: (%d,%d) failed (%d): %s",
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            tag, fd, want, (int)actual, strerror(errno));
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return false;
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    } else {
2204308417beec548c2b2c06ecec4f7f4a965b09fb2Steve Block        //ALOGI("read %s: %d at %d", tag, actual, data->count);
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    data->count += actual;
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Got more data, look for an EOL.  We expect LF or CRLF, but will
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * try to handle a standalone CR.
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    char* cp = data->buf;
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    const char* start = data->buf;
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    int i = data->count;
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    for (i = data->count; i > 0; i--, cp++) {
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (*cp == '\n' || (*cp == '\r' && i != 0 && *(cp+1) != '\n')) {
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            *cp = '\0';
234e8e1ddccd616e8226b7cc1e4e9fdb327429249e8Steve Block            //ALOGW("GOT %d at %d '%s'", cp - start, start - data->buf, start);
2351663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block            ALOG(LOG_INFO, tag, "%s", start);
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            start = cp+1;
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * See if we overflowed.  If so, cut it off.
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start == data->buf && data->count == kMaxLine) {
244f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        data->buf[kMaxLine] = '\0';
2451663a6c12fdf4732d7ea0a0406af6085b3c408e4Steve Block        ALOG(LOG_INFO, tag, "%s!", start);
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        start = cp + kMaxLine;
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /*
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Update "data" if we consumed some output.  If there's anything left
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in the buffer, it's because we didn't see an EOL and need to keep
252f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * reading until we see one.
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    if (start != data->buf) {
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (start >= data->buf + data->count) {
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* consumed all available */
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data->count = 0;
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } else {
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            /* some left over */
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int remaining = data->count - (start - data->buf);
261f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            memmove(data->buf, start, remaining);
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            data->count = remaining;
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    return true;
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
268