fixed lots of not-thread-safe things

Most of the things I fixed here were using libc functions that are
fundamentally not thread-safe.
diff --git a/aos/linux_code/core.cc b/aos/linux_code/core.cc
index a9a58d1..5b580ef 100644
--- a/aos/linux_code/core.cc
+++ b/aos/linux_code/core.cc
@@ -1,3 +1,4 @@
+#include <sys/wait.h>
 #include <sys/select.h>
 #include <stdlib.h>
 #include <stdio.h>
@@ -7,6 +8,7 @@
 #include <string>
 
 #include "aos/linux_code/init.h"
+#include "aos/common/util/run_command.h"
 
 // Initializes shared memory. This is the only file that will create the shared
 // memory file if it doesn't already exist (and set everything up).
@@ -17,8 +19,10 @@
   aos::InitCreate();
 
   if (argc > 1) {
-    if (system((std::string("touch '") + argv[1] + "'").c_str()) != 0) {
-      fprintf(stderr, "`touch '%s'` failed\n", argv[1]);
+    const int result = ::aos::util::RunCommand(
+        (std::string("touch '") + argv[1] + "'").c_str());
+    if (result == -1 || !WIFEXITED(result) || WEXITSTATUS(result) != 0) {
+      fprintf(stderr, "`touch '%s'` failed; result = %x\n", argv[1], result);
       exit(EXIT_FAILURE);
     }
   }
diff --git a/aos/linux_code/ipc_lib/ipc_lib.gyp b/aos/linux_code/ipc_lib/ipc_lib.gyp
index 9b1e712..3c0c9fa 100644
--- a/aos/linux_code/ipc_lib/ipc_lib.gyp
+++ b/aos/linux_code/ipc_lib/ipc_lib.gyp
@@ -80,6 +80,8 @@
         '<(AOS)/common/common.gyp:mutex',
         'core_lib',
         '<(AOS)/common/common.gyp:die',
+        '<(AOS)/common/libc/libc.gyp:dirname',
+        '<(AOS)/common/libc/libc.gyp:aos_strsignal',
       ],
       'variables': {
         'is_special_test': 1,
diff --git a/aos/linux_code/ipc_lib/ipc_stress_test.cc b/aos/linux_code/ipc_lib/ipc_stress_test.cc
index c1dcb83..58d88b3 100644
--- a/aos/linux_code/ipc_lib/ipc_stress_test.cc
+++ b/aos/linux_code/ipc_lib/ipc_stress_test.cc
@@ -15,6 +15,8 @@
 #include "aos/common/mutex.h"
 #include "aos/linux_code/ipc_lib/core_lib.h"
 #include "aos/common/die.h"
+#include "aos/common/libc/dirname.h"
+#include "aos/common/libc/aos_strsignal.h"
 
 // This runs all of the IPC-related tests in a bunch of parallel processes for a
 // while and makes sure that they don't fail. It also captures the stdout and
@@ -175,7 +177,7 @@
     } else if (WIFSIGNALED(status)) {
       MutexLocker sync(&shared->output_mutex);
       fprintf(stderr, "Test %s terminated by signal %d: %s.\n", (*test)[0],
-              WTERMSIG(status), strsignal(WTERMSIG(status)));
+              WTERMSIG(status), aos_strsignal(WTERMSIG(status)));
         fputs(output.c_str(), stderr);
     } else {
       assert(WIFSTOPPED(status));
@@ -210,12 +212,10 @@
   Shared *shared = static_cast<Shared *>(shm_malloc(sizeof(Shared)));
   new (shared) Shared(time::Time::Now() + kTestTime);
 
-  char *temp = strdup(argv[0]);
   if (asprintf(const_cast<char **>(&shared->path),
-               "%s/../tests", dirname(temp)) == -1) {
+               "%s/../tests", ::aos::libc::Dirname(argv[0]).c_str()) == -1) {
     PDie("asprintf failed");
   }
-  free(temp);
 
   for (int i = 0; i < kTesters; ++i) {
     Run(shared);
diff --git a/aos/linux_code/linux_code.gyp b/aos/linux_code/linux_code.gyp
index cbae81b..74b788d 100644
--- a/aos/linux_code/linux_code.gyp
+++ b/aos/linux_code/linux_code.gyp
@@ -31,6 +31,7 @@
       ],
       'dependencies': [
         'init',
+        '<(AOS)/common/util/util.gyp:run_command',
       ],
     },
   ],
diff --git a/aos/linux_code/starter/starter.cc b/aos/linux_code/starter/starter.cc
index 800acd9..59aa88d 100644
--- a/aos/linux_code/starter/starter.cc
+++ b/aos/linux_code/starter/starter.cc
@@ -1,3 +1,8 @@
+// This has to come before anybody drags in <stdlib.h> or else we end up with
+// the wrong version of WIFEXITED etc (for one thing, they don't const-qualify
+// their casts) (sometimes at least).
+#include <sys/wait.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <sys/types.h>
@@ -10,7 +15,6 @@
 #include <stdint.h>
 #include <errno.h>
 #include <string.h>
-#include <sys/wait.h>
 #include <inttypes.h>
 
 #include <map>
@@ -32,6 +36,8 @@
 #include "aos/common/unique_malloc_ptr.h"
 #include "aos/common/time.h"
 #include "aos/common/once.h"
+#include "aos/common/libc/aos_strsignal.h"
+#include "aos/common/util/run_command.h"
 
 // This is the main piece of code that starts all of the rest of the code and
 // restarts it when the binaries are modified.
@@ -669,8 +675,7 @@
           // want it to stop, so it stopping isn't a WARNING.
           LOG((status == SIGTERM) ? DEBUG : WARNING,
               "child %d (%s) was killed by signal %d (%s)\n",
-              pid, child->name(), status,
-              strsignal(status));
+              pid, child->name(), status, aos_strsignal(status));
           break;
         case CLD_STOPPED:
           LOG(WARNING, "child %d (%s) was stopped by signal %d "
@@ -731,8 +736,13 @@
   std::string core_touch_file = "/tmp/starter.";
   core_touch_file += std::to_string(static_cast<intmax_t>(getpid()));
   core_touch_file += ".core_touch_file";
-  if (system(("touch '" + core_touch_file + "'").c_str()) != 0) {
+  const int result =
+      ::aos::util::RunCommand(("touch '" + core_touch_file + "'").c_str());
+  if (result == -1) {
     PLOG(FATAL, "running `touch '%s'` failed\n", core_touch_file.c_str());
+  } else if (!WIFEXITED(result) || WEXITSTATUS(result) != 0) {
+    LOG(FATAL, "`touch '%s'` gave result %x\n", core_touch_file.c_str(),
+        result);
   }
   FileWatch core_touch_file_watch(core_touch_file, Run, NULL);
   core = unique_ptr<Child>(
diff --git a/aos/linux_code/starter/starter.gyp b/aos/linux_code/starter/starter.gyp
index 0464d58..5d86ea4 100644
--- a/aos/linux_code/starter/starter.gyp
+++ b/aos/linux_code/starter/starter.gyp
@@ -25,6 +25,8 @@
         '<(AOS)/build/aos.gyp:logging',
         '<(AOS)/common/common.gyp:once',
         '<(AOS)/common/common.gyp:time',
+        '<(AOS)/common/libc/libc.gyp:aos_strsignal',
+        '<(AOS)/common/util/util.gyp:run_command',
       ],
       'copies': [
         {