libsysutils: New C++ system convenience library

        This library contains re-usable classes for common
    system level daemons. Initial consumers of this library
    are 'nexus' and 'vold2'

Signed-off-by: San Mehat <san@google.com>
diff --git a/libsysutils/src/SocketListener.cpp b/libsysutils/src/SocketListener.cpp
new file mode 100644
index 0000000..f92e30d
--- /dev/null
+++ b/libsysutils/src/SocketListener.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#define LOG_TAG "SocketListener"
+#include <cutils/log.h>
+
+#include <cutils/sockets.h>
+
+#include <sysutils/SocketListener.h>
+
+SocketListener::SocketListener(const char *socketName, bool acceptClients) {
+    mAcceptClients = acceptClients;
+    mCsock = -1;
+    mSocketName = socketName;
+    mSock = -1;
+}
+
+SocketListener::SocketListener(int socketFd, bool acceptClients) {
+    mAcceptClients = acceptClients;
+    mCsock = -1;
+    mSocketName = NULL;
+    mSock = socketFd;
+}
+
+int SocketListener::run() {
+
+    if (!mSocketName && mSock == -1) {
+        errno = EINVAL;
+        return -1;
+    } else if (mSocketName) {
+        if ((mSock = android_get_control_socket(mSocketName)) < 0) {
+            LOGE("Obtaining file descriptor socket '%s' failed: %s",
+                 mSocketName, strerror(errno));
+            return -1;
+        }
+    }
+
+    if (mAcceptClients) {
+        if (listen(mSock, 4) < 0) {
+            LOGE("Unable to listen on socket (%s)", strerror(errno));
+            return -1;
+        }
+    }
+
+    while(1) {
+        fd_set read_fds;
+        struct timeval to;
+        int max = 0;
+        int rc = 0;
+
+        to.tv_sec = 60 * 60;
+        to.tv_usec = 0;
+
+        FD_ZERO(&read_fds);
+
+        if ((mAcceptClients == false) ||
+            (mAcceptClients == true && mCsock == -1)) {
+            FD_SET(mSock, &read_fds);
+            max = mSock;
+        } else if (mCsock != -1) {
+            FD_SET(mCsock, &read_fds);
+            max = mCsock;
+        }
+
+        if ((rc = select(max + 1, &read_fds, NULL, NULL, &to)) < 0) {
+            LOGE("select failed (%s)", strerror(errno));
+            return -errno;
+        } else if (!rc)
+            continue;
+        else if (FD_ISSET(mSock, &read_fds)) {
+            /*
+             * If we're accepting client connections then 
+             * accept and gobble the event. Otherwise
+             * pass it on to the handlers.
+             */
+            if (mAcceptClients) {
+                struct sockaddr addr;
+                socklen_t alen = sizeof(addr);
+
+                if ((mCsock = accept(mSock, &addr, &alen)) < 0) {
+                    LOGE("accept failed (%s)", strerror(errno));
+                    return -errno;
+                }
+                LOGD("SocketListener client connection accepted");
+            } else if (!onDataAvailable(mSock)) {
+                LOGW("SocketListener closing listening socket (Will shut down)");
+                close(mSock);
+                return -ESHUTDOWN;
+            }
+        } else if ((FD_ISSET(mCsock, &read_fds)) &&
+                   !onDataAvailable(mCsock)) {
+                /*
+                 * Once mCsock == -1, we'll start
+                 * accepting connections on mSock again.
+                 */
+                LOGD("SocketListener closing client socket");
+                close(mCsock);
+                mCsock = -1;
+            }
+    }
+    return 0;
+}
+
+bool SocketListener::onDataAvailable(int socket) {
+    return false;
+}