#include "compat.h" #include #include #include #include #include #include int wctomb(char *s, wchar_t wc) { return wcrtomb(s,wc,NULL); } int mbtowc(wchar_t *pwc, const char *s, size_t n) { return mbrtowc(pwc, s, n, NULL); } struct stream { const char *name; int fd[2]; FILE *src; }; static void* log_thread(void *arg) { struct stream *stream = arg; char buf[4000], *off = buf, *nl; // Can't be too big or android stops logging for (ssize_t r = 0;;off += r, r = 0) { if (off - buf < sizeof(buf) - 1) { errno = 0; r = read(stream->fd[0], off, (sizeof(buf) - 1) - (off - buf)); if (r <= 0) { if (errno == EINTR) continue; else break; } off[r] = 0; } if ((nl = strrchr(off, '\n'))) { *nl = 0; ++nl; __android_log_write(ANDROID_LOG_INFO, stream->name, buf); r = (off + r) - nl; memcpy((off = buf), nl, r); } else if (off - buf >= sizeof(buf)) { __android_log_write(ANDROID_LOG_INFO, stream->name, buf); r = 0; off = buf; } } close(stream->fd[0]); close(stream->fd[1]); return NULL; } __attribute__((constructor)) static void log_init(void) { static struct stream stream[] = { { .name = "stdout" }, { .name = "stderr" } }; stream[0].src = stdout; stream[1].src = stderr; for (size_t i = 0; i < sizeof(stream) / sizeof(stream[0]); ++i) { setvbuf(stream[i].src, NULL, _IOLBF, BUFSIZ); pipe(stream[i].fd); dup2(stream[i].fd[1], fileno(stream[i].src)); pthread_t thread; pthread_create(&thread, 0, log_thread, &stream[i]); pthread_detach(thread); } chdir(getenv("COMPAT_CHDIR")); }