Add basic job support to make.
Change-Id: I0e5640fe2e717dfdd56300e2aecb171aa6803157
diff --git a/job.c b/job.c
index 8124897..d9dec2c 100644
--- a/job.c
+++ b/job.c
@@ -76,6 +76,13 @@
# define VMS_POSIX_EXIT_MASK (C_FACILITY_NO | 0xA000)
#endif
+#elif defined (__Fuchsia__)
+#include <launchpad/launchpad.h>
+#include <launchpad/vmo.h>
+#include <magenta/syscalls.h>
+
+const char *default_shell = "/boot/bin/sh";
+int batch_mode_shell = 0;
#else
const char *default_shell = "/bin/sh";
@@ -587,6 +594,10 @@
pid_t pid;
int exit_code, exit_sig, coredump;
struct child *lastc, *c;
+#ifdef __Fuchsia__
+ int mx_status = ERR_TIMED_OUT;
+ mx_signals_t pending_signals = 0;
+#endif
int child_failed;
int any_remote, any_local;
int dontcare;
@@ -670,6 +681,44 @@
/* A Posix failure can be exactly translated */
if ((c->cstatus & VMS_POSIX_EXIT_MASK) == VMS_POSIX_EXIT_MASK)
status = (c->cstatus >> 3 & 255) << 8;
+#elif defined(__Fuchsia__)
+ status = 0;
+ pid = 0;
+
+ do
+ {
+ for (c = children; c != 0; c = c->next)
+ {
+ mx_status = mx_handle_wait_one
+ (c->pid, MX_TASK_TERMINATED, 0,
+ &pending_signals);
+
+ /* If we get any other status, something has gone
+ wildly off the rails. Unfortunately, the API for
+ this function doesn't allow us to, for example,
+ report that the child handle is invalid. */
+ assert (mx_status == NO_ERROR
+ || mx_status == ERR_TIMED_OUT);
+
+ /* mx_status will always be ERR_TIMED_OUT when
+ we do a non-blocking wait, so we have to look
+ at pending_signals to discover an exited
+ child. */
+ if (pending_signals)
+ {
+ mx_info_process_t proc_info;
+
+ mx_status = mx_object_get_info
+ (c->pid, MX_INFO_PROCESS, &proc_info,
+ sizeof (proc_info), NULL, NULL);
+ if (mx_status == NO_ERROR)
+ status = proc_info.return_code;
+
+ pid = c->pid;
+ break;
+ }
+ }
+ } while (block && !pending_signals);
#else
#ifdef WAIT_NOHANG
if (!block)
@@ -1395,8 +1444,11 @@
if (child->pid < 0)
{
/* Fork failed! */
+ /* Fuchsia prints an error on failure in child_execute_job. */
+#ifndef __Fuchsia__
unblock_sigs ();
perror_with_name ("fork", "");
+#endif
goto error;
}
#endif /* !VMS */
@@ -2113,6 +2165,100 @@
return pid;
}
+#elif defined (__Fuchsia__)
+/* Fuchsia:
+ Create a child process executing the command in ARGV.
+ ENVP is the environment of the new program. Returns the PID or -1. */
+int
+child_execute_job (struct output *out, int good_stdin, char **argv, char **envp)
+{
+ launchpad_t *lp = NULL;
+ mx_handle_t child_job = MX_HANDLE_INVALID;
+ mx_handle_t this_job = launchpad_get_mxio_job ();
+ mx_status_t status;
+ int argc;
+ mx_handle_t result = -1;
+
+ /* Copy privileges. */
+ if (this_job != MX_HANDLE_INVALID)
+ mx_handle_duplicate (this_job, MX_RIGHT_SAME_RIGHTS, &child_job);
+
+ status = launchpad_create (child_job, argv[0], &lp);
+ if (status != NO_ERROR)
+ goto done_noalloc;
+
+ status = launchpad_elf_load (lp, launchpad_vmo_from_file (argv[0]));
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_load_vdso (lp, MX_HANDLE_INVALID);
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_add_vdso_vmo (lp);
+ if (status != NO_ERROR)
+ goto done;
+
+ /* We have to tell launchpad how many arguments. */
+ for (argc = 0; argv[argc]; argc++)
+ ;
+
+ status = launchpad_arguments (lp, argc, (const char * const *) argv);
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_environ (lp, (const char * const *) envp);
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_clone_mxio_root (lp);
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_clone_mxio_cwd (lp);
+ if (status != NO_ERROR)
+ goto done;
+
+ /* Copy descriptors, but don't make stdin available to the child. */
+ if (out && out->syncout)
+ {
+ if (out->out >= 0)
+ status = launchpad_clone_fd (lp, out->out, FD_STDOUT);
+ else
+ status = launchpad_clone_fd (lp, FD_STDOUT, FD_STDOUT);
+
+ if (status != NO_ERROR)
+ goto done;
+
+ if (out->err >= 0)
+ status = launchpad_clone_fd (lp, out->err, FD_STDERR);
+ else
+ status = launchpad_clone_fd (lp, FD_STDERR, FD_STDERR);
+ }
+ else
+ {
+ status = launchpad_clone_fd (lp, FD_STDOUT, FD_STDOUT);
+ if (status != NO_ERROR)
+ goto done;
+
+ status = launchpad_clone_fd (lp, FD_STDERR, FD_STDERR);
+ }
+
+ if (status == NO_ERROR)
+ result = launchpad_start (lp);
+
+done:
+ launchpad_destroy (lp);
+
+done_noalloc:
+ if (status != NO_ERROR)
+ O (error, NILF, _("launchpad: failure to launch"));
+
+ if (result > 0)
+ return (int) result;
+ else
+ return -1;
+}
#elif !defined (_AMIGA) && !defined (__MSDOS__) && !defined (VMS)
/* POSIX: