[xargs] basic process launch working on Fuchsia

It's not honoring $PATH yet (we should add a feature to
launchpad for that), but it does successfully do the
xargs thing.

Change-Id: I050e363155661c4db979c192871f579046398812
diff --git a/BUILD.gn b/BUILD.gn
index 63beae9..2a9b0ea 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -126,7 +126,7 @@
       "libutf",
     ]
 
-     configs += [
+    configs += [
       ":sbase_config",
     ]
   }
@@ -224,6 +224,24 @@
 sbase_util("wc") {}
 sbase_util("which") {}
 sbase_util("whoami") {}
-sbase_util("xargs") {}
 sbase_util("xinstall") {}
 sbase_util("yes") {}
+
+executable("xargs") {
+  sources = [
+    "xargs.c",
+  ]
+
+  deps = [
+    "libutil",
+    "libutf",
+  ]
+
+  libs = [
+    "launchpad",
+  ]
+
+  configs += [
+    ":sbase_config",
+  ]
+}
diff --git a/rules.mk b/rules.mk
index 2811733..f1a2db1 100644
--- a/rules.mk
+++ b/rules.mk
@@ -104,10 +104,10 @@
     wc \
     which \
     whoami \
-    xargs \
     xinstall \
     yes \
 
+THIRD_PARTY_SBASE_LIBS := ulib/mxio ulib/c
 
 THIRD_PARTY_SBASE_CFLAGS := \
     -Wno-sign-compare \
@@ -123,9 +123,13 @@
 $(eval MODULE_TYPE := userapp)\
 $(eval MODULE_SRCS += $(THIRD_PARTY_SBASE_DIR)/$(1).c)\
 $(eval MODULE_STATIC_LIBS := uapp/sbase/libutil uapp/sbase/libutf)\
-$(eval MODULE_LIBS := ulib/mxio ulib/c)\
+$(eval MODULE_LIBS := $(THIRD_PARTY_SBASE_LIBS))\
 $(eval MODULE_CFLAGS := $(THIRD_PARTY_SBASE_CFLAGS))\
 $(eval include make/module.mk)
 endef
 
 $(foreach pgm,$(SBASE_PROGRAMS),$(call make-sbase-program,$(pgm)))
+
+THIRD_PARTY_SBASE_LIBS := ulib/launchpad ulib/magenta ulib/mxio ulib/c
+
+$(call make-sbase-program,xargs)
diff --git a/xargs.c b/xargs.c
index 0d5dd53..b5433c0 100644
--- a/xargs.c
+++ b/xargs.c
@@ -137,6 +137,36 @@
 	return (eofstr && !strcmp(argb, eofstr)) ? NULL : argb;
 }
 
+#ifdef __Fuchsia__
+#include <launchpad/launchpad.h>
+#include <magenta/syscalls.h>
+
+static void
+launch_and_wait(const char* fn, char* const argv[])
+{
+	char **p;
+	size_t argc = 0;
+	for (p = cmd; *p; p++)
+		argc++;
+
+	launchpad_t* lp;
+	launchpad_create(0, fn, &lp);
+	int nofile = (launchpad_load_from_file(lp, fn) != NO_ERROR);
+	launchpad_set_args(lp, argc, (void*) argv);
+	launchpad_clone(lp, LP_CLONE_ALL);
+
+	mx_handle_t proc;
+	mx_status_t status = launchpad_go(lp, &proc, NULL);
+
+	if (status == NO_ERROR) {
+		mx_object_wait_one(proc, MX_PROCESS_TERMINATED, MX_TIME_INFINITE, NULL);
+	} else {
+		errno = nofile ? ENOENT : EIO;
+		weprintf("execvp %s:", *cmd);
+		_exit(126 + nofile);
+	}
+}
+#else
 static void
 waitchld(void)
 {
@@ -155,11 +185,11 @@
 	if (WIFSIGNALED(status))
 		exit(125);
 }
+#endif
 
 static void
 spawn(void)
 {
-	int savederrno;
 	int first = 1;
 	char **p;
 
@@ -173,16 +203,20 @@
 		fputc('\n', stderr);
 	}
 
+#ifdef __Fuchsia__
+	launch_and_wait(*cmd, cmd);
+#else
 	switch (fork()) {
 	case -1:
 		eprintf("fork:");
 	case 0:
 		execvp(*cmd, cmd);
-		savederrno = errno;
+		int savederrno = errno;
 		weprintf("execvp %s:", *cmd);
 		_exit(126 + (savederrno == ENOENT));
 	}
 	waitchld();
+#endif
 }
 
 static void