logwrapper: split into liblogwrap and the executable itself

Abstracting the functionality of logwrapper into a library and making
use of it for the logwrapper executable.

Change-Id: I2bcf722413f3a8454c6f52137dec86c4477fb8b5
diff --git a/logwrapper/logwrapper.c b/logwrapper/logwrapper.c
index dd777c0..4f1bff9 100644
--- a/logwrapper/logwrapper.c
+++ b/logwrapper/logwrapper.c
@@ -14,17 +14,12 @@
  * limitations under the License.
  */
 
-#include <string.h>
-#include <sys/types.h>
-#include <sys/wait.h>
 #include <stdio.h>
 #include <stdlib.h>
-#include <unistd.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <libgen.h>
+#include <sys/wait.h>
 
-#include "private/android_filesystem_config.h"
+#include <logwrap/logwrap.h>
+
 #include "cutils/log.h"
 
 void fatal(const char *msg) {
@@ -45,90 +40,10 @@
         "    fault address is set to the status of wait()\n");
 }
 
-void parent(const char *tag, int seg_fault_on_exit, int parent_read) {
-    int status;
-    char buffer[4096];
-
-    int a = 0;  // start index of unprocessed data
-    int b = 0;  // end index of unprocessed data
-    int sz;
-
-    char *btag = basename(tag);
-    if (!btag) btag = (char*) tag;
-
-    while ((sz = read(parent_read, &buffer[b], sizeof(buffer) - 1 - b)) > 0) {
-
-        sz += b;
-        // Log one line at a time
-        for (b = 0; b < sz; b++) {
-            if (buffer[b] == '\r') {
-                buffer[b] = '\0';
-            } else if (buffer[b] == '\n') {
-                buffer[b] = '\0';
-                ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-                a = b + 1;
-            }
-        }
-
-        if (a == 0 && b == sizeof(buffer) - 1) {
-            // buffer is full, flush
-            buffer[b] = '\0';
-            ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-            b = 0;
-        } else if (a != b) {
-            // Keep left-overs
-            b -= a;
-            memmove(buffer, &buffer[a], b);
-            a = 0;
-        } else {
-            a = 0;
-            b = 0;
-        }
-
-    }
-    // Flush remaining data
-    if (a != b) {
-        buffer[b] = '\0';
-        ALOG(LOG_INFO, btag, "%s", &buffer[a]);
-    }
-    status = 0xAAAA;
-    if (wait(&status) != -1) {  // Wait for child
-        if (WIFEXITED(status) && WEXITSTATUS(status))
-            ALOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
-                    WEXITSTATUS(status));
-        else if (WIFSIGNALED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
-                    WTERMSIG(status));
-        else if (WIFSTOPPED(status))
-            ALOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
-                    WSTOPSIG(status));
-    } else
-        ALOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
-                strerror(errno), errno);
-    if (seg_fault_on_exit)
-        *(int *)status = 0;  // causes SIGSEGV with fault_address = status
-}
-
-void child(int argc, char* argv[]) {
-    // create null terminated argv_child array
-    char* argv_child[argc + 1];
-    memcpy(argv_child, argv, argc * sizeof(char *));
-    argv_child[argc] = NULL;
-
-    if (execvp(argv_child[0], argv_child)) {
-        ALOG(LOG_ERROR, "logwrapper",
-            "executing %s failed: %s\n", argv_child[0], strerror(errno));
-        exit(-1);
-    }
-}
-
 int main(int argc, char* argv[]) {
-    pid_t pid;
     int seg_fault_on_exit = 0;
-
-    int parent_ptty;
-    int child_ptty;
-    char *child_devname = NULL;
+    int status = 0xAAAA;
+    int rc;
 
     if (argc < 2) {
         usage();
@@ -144,43 +59,17 @@
         usage();
     }
 
-    /* Use ptty instead of socketpair so that STDOUT is not buffered */
-    parent_ptty = open("/dev/ptmx", O_RDWR);
-    if (parent_ptty < 0) {
-        fatal("Cannot create parent ptty\n");
+    rc = logwrap(argc, argv, &status);
+    if (!rc) {
+        if (WIFEXITED(status))
+            rc = WEXITSTATUS(status);
+        else
+            rc = -ECHILD;
     }
 
-    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
-            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
-        fatal("Problem with /dev/ptmx\n");
+    if (seg_fault_on_exit) {
+        *(int *)status = 0;  // causes SIGSEGV with fault_address = status
     }
 
-    pid = fork();
-    if (pid < 0) {
-        fatal("Failed to fork\n");
-    } else if (pid == 0) {
-        child_ptty = open(child_devname, O_RDWR);
-        if (child_ptty < 0) {
-            fatal("Problem with child ptty\n");
-        }
-
-        // redirect stdout and stderr
-        close(parent_ptty);
-        dup2(child_ptty, 1);
-        dup2(child_ptty, 2);
-        close(child_ptty);
-
-        child(argc - 1, &argv[1]);
-
-    } else {
-        // switch user and group to "log"
-        // this may fail if we are not root, 
-        // but in that case switching user/group is unnecessary 
-        setgid(AID_LOG);
-        setuid(AID_LOG);
-
-        parent(argv[1], seg_fault_on_exit, parent_ptty);
-    }
-
-    return 0;
+    return rc;
 }