am 2d0a6ca2: Merge change 4227 into donut

Merge commit '2d0a6ca27c6f75eb0ec881fe4ad0b4f478d941c0'

* commit '2d0a6ca27c6f75eb0ec881fe4ad0b4f478d941c0':
  nexctl: Refactor so Nexus can be tested from scripts easily.
  libsysutils: Move to a null terminated string protocol using space as a field separator.
diff --git a/include/sysutils/FrameworkCommand.h b/include/sysutils/FrameworkCommand.h
index 5b50247..6c1fca6 100644
--- a/include/sysutils/FrameworkCommand.h
+++ b/include/sysutils/FrameworkCommand.h
@@ -29,7 +29,7 @@
     FrameworkCommand(const char *cmd);
     virtual ~FrameworkCommand() { }
 
-    virtual int runCommand(SocketClient *c, char *data) = 0;
+    virtual int runCommand(SocketClient *c, int argc, char **argv) = 0;
 
     const char *getCommand() { return mCommand; }
 };
diff --git a/include/sysutils/FrameworkListener.h b/include/sysutils/FrameworkListener.h
index 8a83c33..4e3d396 100644
--- a/include/sysutils/FrameworkListener.h
+++ b/include/sysutils/FrameworkListener.h
@@ -22,6 +22,8 @@
 class SocketClient;
 
 class FrameworkListener : public SocketListener {
+public:
+    static const int CMD_ARGS_MAX = 8;
 private:
     FrameworkCommandCollection *mCommands;
 
@@ -34,6 +36,6 @@
     virtual bool onDataAvailable(SocketClient *c);
 
 private:
-    void dispatchCommand(SocketClient *c, char *cmd);
+    void dispatchCommand(SocketClient *c, char *data);
 };
 #endif
diff --git a/libsysutils/src/FrameworkCommand.cpp b/libsysutils/src/FrameworkCommand.cpp
index 94e7426..c52eac7 100644
--- a/libsysutils/src/FrameworkCommand.cpp
+++ b/libsysutils/src/FrameworkCommand.cpp
@@ -25,7 +25,7 @@
     mCommand = cmd;
 }
 
-int FrameworkCommand::runCommand(SocketClient *c, char *data) {
+int FrameworkCommand::runCommand(SocketClient *c, int argc, char **argv) {
     LOGW("Command %s has no run handler!", getCommand());
     errno = ENOSYS;
     return -1;
diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp
index e8ae847..e9ca897 100644
--- a/libsysutils/src/FrameworkListener.cpp
+++ b/libsysutils/src/FrameworkListener.cpp
@@ -36,17 +36,14 @@
     if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) {
         LOGE("read() failed (%s)", strerror(errno));
         return errno;
-    } else if (!len) {
-        LOGW("Lost connection to client");
+    } else if (!len)
         return false;
-    }
 
     int offset = 0;
     int i;
 
     for (i = 0; i < len; i++) {
-        if (buffer[i] == '\n') {
-            buffer[i] = '\0';
+        if (buffer[i] == '\0') {
             dispatchCommand(c, buffer + offset);
             offset = i + 1;
         }
@@ -58,13 +55,20 @@
     mCommands->push_back(cmd);
 }
 
-void FrameworkListener::dispatchCommand(SocketClient *cli, char *cmd) {
-    char *next = cmd;
-    char *cm;
-    char *arg;
+void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) {
+    int argc;
+    char *argv[FrameworkListener::CMD_ARGS_MAX];
 
-    if (!(cm = strsep(&next, ":"))) {
-        cli->sendMsg(500, "Malformatted message", false);
+    if (!index(data, '"')) {
+        char *next = data;
+        char *field;
+        int i;
+
+        for (i = 0; (i < FrameworkListener::CMD_ARGS_MAX) &&
+                    (argv[i] = strsep(&next, " ")); i++);
+        argc = i+1;
+    } else {
+        LOGD("blehhh not supported");
         return;
     }
 
@@ -73,8 +77,8 @@
     for (i = mCommands->begin(); i != mCommands->end(); ++i) {
         FrameworkCommand *c = *i;
 
-        if (!strcmp(cm, c->getCommand())) {
-            if (c->runCommand(cli, next)) {
+        if (!strcmp(argv[0], c->getCommand())) {
+            if (c->runCommand(cli, argc, argv)) {
                 LOGW("Handler '%s' error (%s)", c->getCommand(), strerror(errno));
             }
             return;
diff --git a/libsysutils/src/SocketClient.cpp b/libsysutils/src/SocketClient.cpp
index f0e846f..857ed4d 100644
--- a/libsysutils/src/SocketClient.cpp
+++ b/libsysutils/src/SocketClient.cpp
@@ -33,19 +33,10 @@
         return -1;
     }
 
-    char *tmp;
-    const char *bp = msg;
-
-    if (msg[strlen(msg)] != '\n') {
-        tmp = (char *) alloca(strlen(msg) + 1);
-        strcpy(tmp, msg);
-        strcat(tmp, "\n");
-        bp = tmp;
-    }
-
+    // Send the message including null character
     int rc = 0;
-    const char *p = bp;
-    int brtw = strlen(bp);
+    const char *p = msg;
+    int brtw = strlen(msg) + 1;
 
     pthread_mutex_lock(&mWriteMutex);
     while(brtw) {
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
index 1f80121..1a937c2 100644
--- a/libsysutils/src/SocketListener.cpp
+++ b/libsysutils/src/SocketListener.cpp
@@ -157,7 +157,6 @@
                 if (FD_ISSET(fd, &read_fds)) {
                     pthread_mutex_unlock(&mClientsLock);
                     if (!onDataAvailable(*it)) {
-                        LOGD("SocketListener closing client socket");
                         close(fd);
                         pthread_mutex_lock(&mClientsLock);
                         delete *it;
diff --git a/nexus/nexctl.c b/nexus/nexctl.c
index cfebbf0..8e1d90c 100644
--- a/nexus/nexctl.c
+++ b/nexus/nexctl.c
@@ -29,25 +29,59 @@
 #include <sys/un.h>
 
 #include <cutils/sockets.h>
-
 #include <private/android_filesystem_config.h>
 
+static void usage(char *progname);
+static int do_monitor(int sock, int stop_after_cmd);
+static int do_cmd(int sock, int argc, char **argv);
+
 int main(int argc, char **argv) {
     int sock;
 
+    if (argc < 2)
+        usage(argv[0]);
+
     if ((sock = socket_local_client("nexus",
                                      ANDROID_SOCKET_NAMESPACE_RESERVED,
                                      SOCK_STREAM)) < 0) {
         fprintf(stderr, "Error connecting (%s)\n", strerror(errno));
-        exit(1);
+        exit(4);
     }
 
-    printf("Connected to nexus\n");
+    if (!strcmp(argv[1], "monitor"))
+        exit(do_monitor(sock, 0));
+    exit(do_cmd(sock, argc, argv));
+}
 
-    char line[255];
+static int do_cmd(int sock, int argc, char **argv) {
+    char final_cmd[255] = { '\0' };
+    int i;
+
+    for (i = 1; i < argc; i++) {
+        char *cmp;
+
+        if (!index(argv[i], ' '))
+            asprintf(&cmp, "%s%s", argv[i], (i == (argc -1)) ? "" : " ");
+        else
+            asprintf(&cmp, "\"%s\"%s", argv[i], (i == (argc -1)) ? "" : " ");
+
+        strcat(final_cmd, cmp);
+        free(cmp);
+    }
+
+    if (write(sock, final_cmd, strlen(final_cmd) + 1) < 0) {
+        perror("write");
+        return errno;
+    }
+
+    return do_monitor(sock, 1);
+}
+
+static int do_monitor(int sock, int stop_after_cmd) {
     char *buffer = malloc(4096);
-    int cursor = 0;
-    int col = 0;
+
+    if (!stop_after_cmd)
+        printf("[Connected to Nexus]\n");
 
     while(1) {
         fd_set read_fds;
@@ -59,66 +93,56 @@
 
         FD_ZERO(&read_fds);
         FD_SET(sock, &read_fds);
-        FD_SET(0, &read_fds);
 
-        if (col == 0) {
-            fprintf(stdout, "-> ");
-            fflush(stdout);
-            col = 3;
-        }
-    
         if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
             fprintf(stderr, "Error in select (%s)\n", strerror(errno));
-            exit(2);
+            free(buffer);
+            return errno;
         } else if (!rc) {
             continue;
+            fprintf(stderr, "[TIMEOUT]\n");
+            return ETIMEDOUT;
         } else if (FD_ISSET(sock, &read_fds)) {
             memset(buffer, 0, 4096);
             if ((rc = read(sock, buffer, 4096)) <= 0) {
-                 fprintf(stderr, "Error reading response (%s)\n", strerror(errno));
-                 exit(2);
+                if (rc == 0)
+                    fprintf(stderr, "Lost connection to Nexus - did it crash?\n");
+                else
+                    fprintf(stderr, "Error reading data (%s)\n", strerror(errno));
+                free(buffer);
+                if (rc == 0)
+                    return ECONNRESET;
+                return errno;
             }
-            int i;
-            for (i = 0; i < col; i++) {
-                fprintf(stdout, "%c", 8);
-            }
+            
+            int offset = 0;
+            int i = 0;
 
-            printf("%s", buffer);
-            printf("-> ");
-            for (i = 0; i < cursor; i++) {
-                fprintf(stdout, "%c", line[i]);
-            }
-            fflush(stdout);
-        } else if (FD_ISSET(0, &read_fds)) {
-            char c;
+            for (i = 0; i < rc; i++) {
+                if (buffer[i] == '\0') {
+                    int code;
+                    char tmp[4];
 
-            if ((rc = read(0, &c, 1)) < 0) {
-                fprintf(stderr, "Error reading from terminal (%s)\n", strerror(errno));
-                exit(2);
-            } else if (!rc) {
-                fprintf(stderr, "0 length read from terminal\n");
-                exit(2);
-            }
+                    strncpy(tmp, buffer + offset, 3);
+                    tmp[3] = '\0';
+                    code = atoi(tmp);
 
-            fprintf(stdout, "%c", c);
-            fflush(stdout);
-
-            line[cursor] = c;
-
-            if (c == '\n') {
-                if ((rc = write(sock, line, strlen(line))) < 0) {
-                    fprintf(stderr, "Error writing to nexus (%s)\n", strerror(errno));
-                    exit(2);
+                    printf("%s\n", buffer + offset);
+                    if (stop_after_cmd) {
+                        if (code >= 200 && code < 600)
+                            return 0;
+                    }
+                    offset = i + 1;
                 }
-                memset(line, 0, sizeof(line));
-                cursor = 0;
-                col = 0;
-            } else {
-                cursor++;
-                col++;
             }
         }
     }
-
-    exit(0);
+    free(buffer);
+    return 0;
 }
+
+static void usage(char *progname) {
+    fprintf(stderr, "Usage: %s <monitor>|<cmd> [arg1] [arg2...]\n", progname);
+    exit(1);
+}
+