OSDN Git Service

netd: Initial skelaton for netd
authorSan Mehat <san@google.com>
Fri, 15 Jan 2010 16:02:39 +0000 (08:02 -0800)
committerSan Mehat <san@google.com>
Fri, 15 Jan 2010 16:02:39 +0000 (08:02 -0800)
Signed-off-by: San Mehat <san@google.com>
13 files changed:
Android.mk [new file with mode: 0644]
CommandListener.cpp [new file with mode: 0644]
CommandListener.h [new file with mode: 0644]
NetdCommand.cpp [new file with mode: 0644]
NetdCommand.h [new file with mode: 0644]
NetlinkHandler.cpp [new file with mode: 0644]
NetlinkHandler.h [new file with mode: 0644]
NetlinkManager.cpp [new file with mode: 0644]
NetlinkManager.h [new file with mode: 0644]
ResponseCode.h [new file with mode: 0644]
logwrapper.c [new file with mode: 0644]
main.cpp [new file with mode: 0644]
ndc.c [new file with mode: 0644]

diff --git a/Android.mk b/Android.mk
new file mode 100644 (file)
index 0000000..c78d102
--- /dev/null
@@ -0,0 +1,44 @@
+BUILD_NETD := false
+ifneq ($(TARGET_SIMULATOR),true)
+    BUILD_NETD := true
+endif
+
+ifeq ($(BUILD_NETD),true)
+
+LOCAL_PATH:= $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:=                                      \
+                  main.cpp                             \
+                 CommandListener.cpp                  \
+                  NetdCommand.cpp                      \
+                  NetlinkManager.cpp                   \
+                  NetlinkHandler.cpp                   \
+                  logwrapper.c                         
+
+LOCAL_MODULE:= netd
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS) -I../../frameworks/base/include/
+
+LOCAL_CFLAGS := 
+
+LOCAL_SHARED_LIBRARIES := libsysutils libcutils
+
+include $(BUILD_EXECUTABLE)
+
+include $(CLEAR_VARS)
+LOCAL_SRC_FILES:=          \
+                  ndc.c \
+
+LOCAL_MODULE:= ndc
+
+LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+
+LOCAL_CFLAGS := 
+
+LOCAL_SHARED_LIBRARIES := libcutils
+
+include $(BUILD_EXECUTABLE)
+
+endif # ifeq ($(BUILD_NETD,true)
diff --git a/CommandListener.cpp b/CommandListener.cpp
new file mode 100644 (file)
index 0000000..fa76f31
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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 <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <errno.h>
+
+#define LOG_TAG "CommandListener"
+#include <cutils/log.h>
+
+#include <sysutils/SocketClient.h>
+
+#include "CommandListener.h"
+#include "ResponseCode.h"
+
+CommandListener::CommandListener() :
+                 FrameworkListener("netd") {
+    registerCmd(new ListInterfacesCmd());
+    registerCmd(new IpFwdCmd());
+    registerCmd(new TetherCmd());
+    registerCmd(new NatCmd());
+}
+
+CommandListener::ListInterfacesCmd::ListInterfacesCmd() :
+                 NetdCommand("list_interfaces") {
+}
+
+int CommandListener::ListInterfacesCmd::runCommand(SocketClient *cli,
+                                                      int argc, char **argv) {
+    cli->sendMsg(ResponseCode::CommandOkay, "Interfaces listed.", false);
+    return 0;
+}
+
+CommandListener::IpFwdCmd::IpFwdCmd() :
+                 NetdCommand("ipfwd") {
+}
+
+int CommandListener::IpFwdCmd::runCommand(SocketClient *cli,
+                                                      int argc, char **argv) {
+
+    return 0;
+}
+
+CommandListener::TetherCmd::TetherCmd() :
+                 NetdCommand("tether") {
+}
+
+int CommandListener::TetherCmd::runCommand(SocketClient *cli,
+                                                      int argc, char **argv) {
+    if (argc < 2) {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
+        return 0;
+    }
+
+    if (!strcmp(argv[1], "start")) {
+    } else if (!strcmp(argv[1], "stop")) {
+    } else if (!strcmp(argv[1], "status")) {
+    } else if (!strcmp(argv[1], "interface")) {
+    } else if (!strcmp(argv[1], "dns")) {
+    } else {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown tether cmd", false);
+        return 0;
+    }
+
+    return 0;
+}
+
+CommandListener::NatCmd::NatCmd() :
+                 NetdCommand("nat") {
+}
+
+int CommandListener::NatCmd::runCommand(SocketClient *cli,
+                                                      int argc, char **argv) {
+
+    return 0;
+}
+
diff --git a/CommandListener.h b/CommandListener.h
new file mode 100644 (file)
index 0000000..c3fee39
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * 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.
+ */
+
+#ifndef _COMMANDLISTENER_H__
+#define _COMMANDLISTENER_H__
+
+#include <sysutils/FrameworkListener.h>
+#include "NetdCommand.h"
+
+class CommandListener : public FrameworkListener {
+public:
+    CommandListener();
+    virtual ~CommandListener() {}
+
+private:
+
+    class ListInterfacesCmd : public NetdCommand {
+    public:
+        ListInterfacesCmd();
+        virtual ~ListInterfacesCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+
+    class IpFwdCmd : public NetdCommand {
+    public:
+        IpFwdCmd();
+        virtual ~IpFwdCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+
+    class TetherCmd : public NetdCommand {
+    public:
+        TetherCmd();
+        virtual ~TetherCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+
+    class NatCmd : public NetdCommand {
+    public:
+        NatCmd();
+        virtual ~NatCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+};
+
+#endif
diff --git a/NetdCommand.cpp b/NetdCommand.cpp
new file mode 100644 (file)
index 0000000..3bd9322
--- /dev/null
@@ -0,0 +1,21 @@
+/*
+ * 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 "NetdCommand.h"
+
+NetdCommand::NetdCommand(const char *cmd) :
+              FrameworkCommand(cmd)  {
+}
diff --git a/NetdCommand.h b/NetdCommand.h
new file mode 100644 (file)
index 0000000..4f731bb
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+#ifndef _NETD_COMMAND_H
+#define _NETD_COMMAND_H
+
+#include <sysutils/FrameworkCommand.h>
+
+class NetdCommand : public FrameworkCommand {
+public:
+    NetdCommand(const char *cmd);
+    virtual ~NetdCommand() {}
+};
+
+#endif
diff --git a/NetlinkHandler.cpp b/NetlinkHandler.cpp
new file mode 100644 (file)
index 0000000..039e7da
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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 <stdlib.h>
+#include <errno.h>
+
+#define LOG_TAG "Netd"
+
+#include <cutils/log.h>
+
+#include <sysutils/NetlinkEvent.h>
+#include "NetlinkHandler.h"
+
+NetlinkHandler::NetlinkHandler(int listenerSocket) :
+                NetlinkListener(listenerSocket) {
+}
+
+NetlinkHandler::~NetlinkHandler() {
+}
+
+int NetlinkHandler::start() {
+    return this->startListener();
+}
+
+int NetlinkHandler::stop() {
+    return this->stopListener();
+}
+
+void NetlinkHandler::onEvent(NetlinkEvent *evt) {
+    const char *subsys = evt->getSubsystem();
+
+    if (!subsys) {
+        LOGW("No subsystem found in netlink event");
+        return;
+    }
+
+    if (!strcmp(subsys, "block")) {
+    } else if (!strcmp(subsys, "switch")) {
+    } else if (!strcmp(subsys, "battery")) {
+    } else if (!strcmp(subsys, "power_supply")) {
+    } else {
+        LOGE("Dropping %s netlink event", subsys);
+    }
+}
diff --git a/NetlinkHandler.h b/NetlinkHandler.h
new file mode 100644 (file)
index 0000000..00a31c8
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.
+ */
+
+#ifndef _NETLINKHANDLER_H
+#define _NETLINKHANDLER_H
+
+#include <sysutils/NetlinkListener.h>
+
+class NetlinkHandler: public NetlinkListener {
+
+public:
+    NetlinkHandler(int listenerSocket);
+    virtual ~NetlinkHandler();
+
+    int start(void);
+    int stop(void);
+
+protected:
+    virtual void onEvent(NetlinkEvent *evt);
+};
+#endif
diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp
new file mode 100644 (file)
index 0000000..e031dc5
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * 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 <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include <linux/netlink.h>
+
+#define LOG_TAG "Netd"
+
+#include <cutils/log.h>
+
+#include "NetlinkManager.h"
+#include "NetlinkHandler.h"
+
+NetlinkManager *NetlinkManager::sInstance = NULL;
+
+NetlinkManager *NetlinkManager::Instance() {
+    if (!sInstance)
+        sInstance = new NetlinkManager();
+    return sInstance;
+}
+
+NetlinkManager::NetlinkManager() {
+    mBroadcaster = NULL;
+}
+
+NetlinkManager::~NetlinkManager() {
+}
+
+int NetlinkManager::start() {
+    struct sockaddr_nl nladdr;
+    int sz = 64 * 1024;
+
+    memset(&nladdr, 0, sizeof(nladdr));
+    nladdr.nl_family = AF_NETLINK;
+    nladdr.nl_pid = getpid();
+    nladdr.nl_groups = 0xffffffff;
+
+    if ((mSock = socket(PF_NETLINK,
+                        SOCK_DGRAM,NETLINK_KOBJECT_UEVENT)) < 0) {
+        LOGE("Unable to create uevent socket: %s", strerror(errno));
+        return -1;
+    }
+
+    if (setsockopt(mSock, SOL_SOCKET, SO_RCVBUFFORCE, &sz, sizeof(sz)) < 0) {
+        LOGE("Unable to set uevent socket options: %s", strerror(errno));
+        return -1;
+    }
+
+    if (bind(mSock, (struct sockaddr *) &nladdr, sizeof(nladdr)) < 0) {
+        LOGE("Unable to bind uevent socket: %s", strerror(errno));
+        return -1;
+    }
+
+    mHandler = new NetlinkHandler(mSock);
+    if (mHandler->start()) {
+        LOGE("Unable to start NetlinkHandler: %s", strerror(errno));
+        return -1;
+    }
+    return 0;
+}
+
+int NetlinkManager::stop() {
+    if (mHandler->stop()) {
+        LOGE("Unable to stop NetlinkHandler: %s", strerror(errno));
+        return -1;
+    }
+    delete mHandler;
+    mHandler = NULL;
+
+    close(mSock);
+    mSock = -1;
+
+    return 0;
+}
diff --git a/NetlinkManager.h b/NetlinkManager.h
new file mode 100644 (file)
index 0000000..9c7ba11
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.
+ */
+
+#ifndef _NETLINKMANAGER_H
+#define _NETLINKMANAGER_H
+
+#include <sysutils/SocketListener.h>
+#include <sysutils/NetlinkListener.h>
+
+class NetlinkHandler;
+
+class NetlinkManager {
+private:
+    static NetlinkManager *sInstance;
+
+private:
+    SocketListener       *mBroadcaster;
+    NetlinkHandler       *mHandler;
+    int                  mSock;
+
+public:
+    virtual ~NetlinkManager();
+
+    int start();
+    int stop();
+
+    void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; }
+    SocketListener *getBroadcaster() { return mBroadcaster; }
+
+    static NetlinkManager *Instance();
+
+private:
+    NetlinkManager();
+};
+#endif
diff --git a/ResponseCode.h b/ResponseCode.h
new file mode 100644 (file)
index 0000000..bb27787
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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.
+ */
+
+#ifndef _RESPONSECODE_H
+#define _RESPONSECODE_H
+
+class ResponseCode {
+public:
+    // 100 series - Requestion action was initiated; expect another reply
+    // before proceeding with a new command.
+    static const int ActionInitiated  = 100;
+
+    static const int VolumeListResult = 110;
+    static const int AsecListResult   = 111;
+
+    // 200 series - Requested action has been successfully completed
+    static const int CommandOkay              = 200;
+    static const int ShareAvailabilityResult  = 210;
+    static const int AsecPathResult           = 211;
+
+    // 400 series - The command was accepted but the requested action
+    // did not take place.
+    static const int OperationFailed = 400;
+
+    // 500 series - The command was not accepted and the requested
+    // action did not take place.
+    static const int CommandSyntaxError = 500;
+    static const int CommandParameterError = 501;
+
+    // 600 series - Unsolicited broadcasts
+    static const int UnsolicitedInformational       = 600;
+    static const int VolumeStateChange              = 605;
+    static const int VolumeMountFailedBlank         = 610;
+    static const int VolumeMountFailedDamaged       = 611;
+    static const int VolumeMountFailedNoMedia       = 612;
+
+    static const int ShareAvailabilityChange        = 620;
+
+    static const int VolumeDiskInserted            = 630;
+    static const int VolumeDiskRemoved             = 631;
+    static const int VolumeBadRemoval              = 632;
+};
+#endif
diff --git a/logwrapper.c b/logwrapper.c
new file mode 100644 (file)
index 0000000..c96426f
--- /dev/null
@@ -0,0 +1,167 @@
+/*
+ * 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 <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 "private/android_filesystem_config.h"
+#include "cutils/log.h"
+
+int parent(const char *tag, 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;
+    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';
+
+                LOG(LOG_INFO, tag, "%s", &buffer[a]);
+                a = b + 1;
+            }
+        }
+
+        if (a == 0 && b == sizeof(buffer) - 1) {
+            // buffer is full, flush
+            buffer[b] = '\0';
+            LOG(LOG_INFO, tag, &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';
+        LOG(LOG_INFO, tag, &buffer[a]);
+    }
+    status = 0xAAAA;
+    if (wait(&status) != -1) {  // Wait for child
+        if (WIFEXITED(status)) {
+            LOG(LOG_INFO, "logwrapper", "%s terminated by exit(%d)", tag,
+                    WEXITSTATUS(status));
+            return WEXITSTATUS(status);
+        } else if (WIFSIGNALED(status))
+            LOG(LOG_INFO, "logwrapper", "%s terminated by signal %d", tag,
+                    WTERMSIG(status));
+        else if (WIFSTOPPED(status))
+            LOG(LOG_INFO, "logwrapper", "%s stopped by signal %d", tag,
+                    WSTOPSIG(status));
+    } else
+        LOG(LOG_INFO, "logwrapper", "%s wait() failed: %s (%d)", tag,
+                strerror(errno), errno);
+    return -EAGAIN;
+}
+
+void child(int argc, const char**argv) {
+    // create null terminated argv_child array
+    char* argv_child[argc + 1];
+    memcpy(argv_child, argv, argc * sizeof(char *));
+    argv_child[argc] = NULL;
+
+    // XXX: PROTECT FROM VIKING KILLER
+    if (execv(argv_child[0], argv_child)) {
+        LOG(LOG_ERROR, "logwrapper",
+            "executing %s failed: %s", argv_child[0], strerror(errno));
+        exit(-1);
+    }
+}
+
+int logwrap(int argc, const char* argv[], int background)
+{
+    pid_t pid;
+
+    int parent_ptty;
+    int child_ptty;
+    char *child_devname = NULL;
+
+    /* Use ptty instead of socketpair so that STDOUT is not buffered */
+    parent_ptty = open("/dev/ptmx", O_RDWR);
+    if (parent_ptty < 0) {
+       LOG(LOG_ERROR, "logwrapper", "Cannot create parent ptty");
+       return -errno;
+    }
+
+    if (grantpt(parent_ptty) || unlockpt(parent_ptty) ||
+            ((child_devname = (char*)ptsname(parent_ptty)) == 0)) {
+       LOG(LOG_ERROR, "logwrapper", "Problem with /dev/ptmx");
+       return -1;
+    }
+
+    pid = fork();
+    if (pid < 0) {
+       LOG(LOG_ERROR, "logwrapper", "Failed to fork");
+        return -errno;
+    } else if (pid == 0) {
+        child_ptty = open(child_devname, O_RDWR);
+        if (child_ptty < 0) {
+           LOG(LOG_ERROR, "logwrapper", "Problem with child ptty");
+            return -errno;
+        }
+
+        // redirect stdout and stderr
+        close(parent_ptty);
+        dup2(child_ptty, 1);
+        dup2(child_ptty, 2);
+        close(child_ptty);
+
+        if (background) {
+            int fd = open("/dev/cpuctl/bg_non_interactive/tasks", O_WRONLY);
+      
+            if (fd >=0 ) {
+                char text[64];
+
+                sprintf(text, "%d", getpid());
+                if (write(fd, text, strlen(text)) < 0) {
+                    LOG(LOG_WARN, "logwrapper",
+                        "Unable to background process (%s)", strerror(errno));
+                    close(fd);
+                }
+                close(fd);
+            } else {
+                LOG(LOG_WARN, "logwrapper",
+                    "Unable to background process (%s)", strerror(errno));
+            }
+        }
+
+        child(argc, argv);
+    } else {
+        return parent(argv[0], parent_ptty);
+    }
+
+    return 0;
+}
diff --git a/main.cpp b/main.cpp
new file mode 100644 (file)
index 0000000..98e1c3f
--- /dev/null
+++ b/main.cpp
@@ -0,0 +1,117 @@
+/*
+ * 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 <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <fcntl.h>
+#include <dirent.h>
+
+#define LOG_TAG "Netd"
+
+#include "cutils/log.h"
+
+#include "CommandListener.h"
+#include "NetlinkManager.h"
+
+static void coldboot(const char *path);
+
+int main() {
+
+    CommandListener *cl;
+    NetlinkManager *nm;
+
+    LOGI("Netd 1.0 starting");
+
+    if (!(nm = NetlinkManager::Instance())) {
+        LOGE("Unable to create NetlinkManager");
+        exit(1);
+    };
+
+
+    cl = new CommandListener();
+    nm->setBroadcaster((SocketListener *) cl);
+
+    if (nm->start()) {
+        LOGE("Unable to start NetlinkManager (%s)", strerror(errno));
+        exit(1);
+    }
+
+    /*
+     * Now that we're up, we can respond to commands
+     */
+    if (cl->startListener()) {
+        LOGE("Unable to start CommandListener (%s)", strerror(errno));
+        exit(1);
+    }
+
+    // Eventually we'll become the monitoring thread
+    while(1) {
+        sleep(1000);
+    }
+
+    LOGI("Netd exiting");
+    exit(0);
+}
+
+static void do_coldboot(DIR *d, int lvl)
+{
+    struct dirent *de;
+    int dfd, fd;
+
+    dfd = dirfd(d);
+
+    fd = openat(dfd, "uevent", O_WRONLY);
+    if(fd >= 0) {
+        write(fd, "add\n", 4);
+        close(fd);
+    }
+
+    while((de = readdir(d))) {
+        DIR *d2;
+
+        if (de->d_name[0] == '.')
+            continue;
+
+        if (de->d_type != DT_DIR && lvl > 0)
+            continue;
+
+        fd = openat(dfd, de->d_name, O_RDONLY | O_DIRECTORY);
+        if(fd < 0)
+            continue;
+
+        d2 = fdopendir(fd);
+        if(d2 == 0)
+            close(fd);
+        else {
+            do_coldboot(d2, lvl + 1);
+            closedir(d2);
+        }
+    }
+}
+
+static void coldboot(const char *path)
+{
+    DIR *d = opendir(path);
+    if(d) {
+        do_coldboot(d, 0);
+        closedir(d);
+    }
+}
diff --git a/ndc.c b/ndc.c
new file mode 100644 (file)
index 0000000..8c6f146
--- /dev/null
+++ b/ndc.c
@@ -0,0 +1,148 @@
+/*
+ * 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 <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#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("vold",
+                                     ANDROID_SOCKET_NAMESPACE_RESERVED,
+                                     SOCK_STREAM)) < 0) {
+        fprintf(stderr, "Error connecting (%s)\n", strerror(errno));
+        exit(4);
+    }
+
+    if (!strcmp(argv[1], "monitor"))
+        exit(do_monitor(sock, 0));
+    exit(do_cmd(sock, argc, argv));
+}
+
+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);
+
+    if (!stop_after_cmd)
+        printf("[Connected to Netd]\n");
+
+    while(1) {
+        fd_set read_fds;
+        struct timeval to;
+        int rc = 0;
+
+        to.tv_sec = 10;
+        to.tv_usec = 0;
+
+        FD_ZERO(&read_fds);
+        FD_SET(sock, &read_fds);
+
+        if ((rc = select(sock +1, &read_fds, NULL, NULL, &to)) < 0) {
+            fprintf(stderr, "Error in select (%s)\n", strerror(errno));
+            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) {
+                if (rc == 0)
+                    fprintf(stderr, "Lost connection to Vold - did it crash?\n");
+                else
+                    fprintf(stderr, "Error reading data (%s)\n", strerror(errno));
+                free(buffer);
+                if (rc == 0)
+                    return ECONNRESET;
+                return errno;
+            }
+            
+            int offset = 0;
+            int i = 0;
+
+            for (i = 0; i < rc; i++) {
+                if (buffer[i] == '\0') {
+                    int code;
+                    char tmp[4];
+
+                    strncpy(tmp, buffer + offset, 3);
+                    tmp[3] = '\0';
+                    code = atoi(tmp);
+
+                    printf("%s\n", buffer + offset);
+                    if (stop_after_cmd) {
+                        if (code >= 200 && code < 600)
+                            return 0;
+                    }
+                    offset = i + 1;
+                }
+            }
+        }
+    }
+    free(buffer);
+    return 0;
+}
+
+static void usage(char *progname) {
+    fprintf(stderr, "Usage: %s <monitor>|<cmd> [arg1] [arg2...]\n", progname);
+    exit(1);
+}
+