Implement exec.

Change-Id: I20329bc9b378479d745b498d6a00eca0872cd5ab
diff --git a/init/signal_handler.cpp b/init/signal_handler.cpp
index c0898fb..c428b96 100644
--- a/init/signal_handler.cpp
+++ b/init/signal_handler.cpp
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
-#include <stdio.h>
 #include <errno.h>
-#include <signal.h>
-#include <unistd.h>
 #include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <unistd.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -27,34 +27,28 @@
 #include <cutils/list.h>
 
 #include "init.h"
-#include "util.h"
 #include "log.h"
+#include "util.h"
 
 static int signal_fd = -1;
 static int signal_recv_fd = -1;
 
-static void sigchld_handler(int s)
-{
+static void sigchld_handler(int s) {
     write(signal_fd, &s, 1);
 }
 
 #define CRITICAL_CRASH_THRESHOLD    4       /* if we crash >4 times ... */
-#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery*/
+#define CRITICAL_CRASH_WINDOW       (4*60)  /* ... in 4 minutes, goto recovery */
 
-static int wait_for_one_process(int block)
-{
+static int wait_for_one_process() {
     int status;
-    struct service *svc;
-    struct socketinfo *si;
-    time_t now;
-    struct listnode *node;
-    struct command *cmd;
-
-    pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, block ? 0 : WNOHANG));
-    if (pid <= 0) return -1;
+    pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
+    if (pid <= 0) {
+        return -1;
+    }
     INFO("waitpid returned pid %d, status = %08x\n", pid, status);
 
-    svc = service_find_by_pid(pid);
+    service* svc = service_find_by_pid(pid);
     if (!svc) {
         if (WIFEXITED(status)) {
             ERROR("untracked pid %d exited with status %d\n", pid, WEXITSTATUS(status));
@@ -68,36 +62,47 @@
         return 0;
     }
 
+    // TODO: all the code from here down should be a member function on service.
+
     NOTICE("process '%s', pid %d exited\n", svc->name, pid);
 
     if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {
-        kill(-pid, SIGKILL);
         NOTICE("process '%s' killing any children in process group\n", svc->name);
+        kill(-pid, SIGKILL);
     }
 
-    /* remove any sockets we may have created */
-    for (si = svc->sockets; si; si = si->next) {
+    // Remove any sockets we may have created.
+    for (socketinfo* si = svc->sockets; si; si = si->next) {
         char tmp[128];
         snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
         unlink(tmp);
     }
 
+    if (svc->flags & SVC_EXEC) {
+        INFO("SVC_EXEC pid %d finished...\n", svc->pid);
+        waiting_for_exec = false;
+        list_remove(&svc->slist);
+        free(svc->name);
+        free(svc);
+        return 0;
+    }
+
     svc->pid = 0;
     svc->flags &= (~SVC_RUNNING);
 
-        /* oneshot processes go into the disabled state on exit,
-         * except when manually restarted. */
+    // Oneshot processes go into the disabled state on exit,
+    // except when manually restarted.
     if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
         svc->flags |= SVC_DISABLED;
     }
 
-        /* disabled and reset processes do not get restarted automatically */
-    if (svc->flags & (SVC_DISABLED | SVC_RESET) )  {
-        notify_service_state(svc->name, "stopped");
+    // Disabled and reset processes do not get restarted automatically.
+    if (svc->flags & (SVC_DISABLED | SVC_RESET))  {
+        svc->NotifyStateChange("stopped");
         return 0;
     }
 
-    now = gettime();
+    time_t now = gettime();
     if ((svc->flags & SVC_CRITICAL) && !(svc->flags & SVC_RESTART)) {
         if (svc->time_crashed + CRITICAL_CRASH_WINDOW >= now) {
             if (++svc->nr_crashed > CRITICAL_CRASH_THRESHOLD) {
@@ -116,36 +121,33 @@
     svc->flags &= (~SVC_RESTART);
     svc->flags |= SVC_RESTARTING;
 
-    /* Execute all onrestart commands for this service. */
+    // Execute all onrestart commands for this service.
+    struct listnode* node;
     list_for_each(node, &svc->onrestart.commands) {
-        cmd = node_to_item(node, struct command, clist);
+        command* cmd = node_to_item(node, struct command, clist);
         cmd->func(cmd->nargs, cmd->args);
     }
-    notify_service_state(svc->name, "restarting");
+    svc->NotifyStateChange("restarting");
     return 0;
 }
 
-void handle_signal(void)
-{
+void handle_signal() {
+    // We got a SIGCHLD - reap and restart as needed.
     char tmp[32];
-
-    /* we got a SIGCHLD - reap and restart as needed */
     read(signal_recv_fd, tmp, sizeof(tmp));
-    while (!wait_for_one_process(0))
-        ;
+    while (!wait_for_one_process()) {
+    }
 }
 
-void signal_init(void)
-{
-    int s[2];
-
+void signal_init() {
     struct sigaction act;
     memset(&act, 0, sizeof(act));
     act.sa_handler = sigchld_handler;
     act.sa_flags = SA_NOCLDSTOP;
     sigaction(SIGCHLD, &act, 0);
 
-    /* create a signalling mechanism for the sigchld handler */
+    // Create a signalling mechanism for the sigchld handler.
+    int s[2];
     if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == 0) {
         signal_fd = s[0];
         signal_recv_fd = s[1];
@@ -154,7 +156,6 @@
     handle_signal();
 }
 
-int get_signal_fd()
-{
+int get_signal_fd() {
     return signal_recv_fd;
 }