summaryrefslogtreecommitdiff
path: root/init
diff options
context:
space:
mode:
Diffstat (limited to 'init')
-rw-r--r--init/init.c205
1 files changed, 190 insertions, 15 deletions
diff --git a/init/init.c b/init/init.c
index 6b01964d..450a38d7 100644
--- a/init/init.c
+++ b/init/init.c
@@ -25,23 +25,191 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
#include <device/device.h>
#include <stdio.h>
#include <assert.h>
+#include <hurd/paths.h>
+#include <sys/reboot.h>
+#include <sys/file.h>
+#include <unistd.h>
+#include <string.h>
#include "startup_reply.h"
+#include "startup_S.h"
+/* host_reboot flags for when we crash. */
+#define CRASH_FLAGS RB_AUTOBOOT
+
+#define BOOT(flags) ((flags & RB_HALT) ? "halt" : "reboot")
+
+/* This structure keeps track of each notified task. */
+struct ntfy_task
+ {
+ mach_port_t notify_port;
+ struct ntfy_task *next;
+ };
+
+/* This structure keeps track of each registered essential task. */
+struct ess_task
+ {
+ struct ess_task *next;
+ task_t task_port;
+ char *name;
+ };
+
+/* These are linked lists of all of the registered items. */
+struct ess_task *ess_tasks;
+struct ntfy_task *ntfy_tasks;
+
+int prompt_for_servers = 0;
+
+/* Our receive right */
mach_port_t startup;
+/* Ports to the kernel */
+mach_port_t host_priv, device_master;
+
+/* Stored information for returning proc and auth startup messages. */
+mach_port_t procreply, authreply;
+mach_msg_type_name_t procreplytype, authreplytype;
+
+/* Our ports to auth and proc. */
+mach_port_t authserver;
+mach_port_t procserver;
+
+/* The tasks of auth and proc and the bootstrap filesystem. */
+task_t authtask, prottask, fstask;
+
+char **global_argv;
+
+/* Read a string from stdin into BUF. */
+static int
+getstring (char *buf, size_t bufsize)
+{
+ if (fgets (buf, bufsize, stdin) != NULL && buf[0] != '\0')
+ {
+ size_t len = strlen (buf);
+ if (buf[len - 1] == '\n' || buf[len - 1] == '\r')
+ buf[len - 1] = '\0';
+ return 1;
+ }
+ return 0;
+}
+
+/* Reboot the microkernel. */
+void
+reboot_mach (int flags)
+{
+ printf ("init: %sing Mach (flags %#x)...\n", BOOT (flags), flags);
+ while (errno = host_reboot (host_priv, flags))
+ perror ("host_reboot");
+ for (;;);
+}
+
+void
+crash_mach (void)
+{
+ reboot_mach (CRASH_FLAGS);
+}
+
+void
+reboot_system (int flags)
+{
+ struct ntfy_task *n;
+
+ for (n = ntfy_tasks; n != NULL; n = n->next)
+ {
+ error_t err;
+ printf ("init: notifying %p\n", (void *) n->notify_port);
+ /* XXX need to time out on reply */
+ err = startup_dosync (n->notify_port);
+ if (err && err != MACH_SEND_INVALID_DEST)
+ printf ("init: %p complained: %s\n",
+ (void *) n->notify_port,
+ strerror (err));
+ }
+
+ reboot_mach (flags);
+}
+
+void
+crash (void)
+{
+ reboot_system (CRASH_FLAGS);
+}
+
+/* The RPC server demultiplexer. */
+static int
+request_server (mach_msg_header_t *inp,
+ mach_msg_header_t *outp)
+{
+ extern int notify_server (), startup_server ();
+
+ return (notify_server (inp, outp) ||
+ startup_server (inp, outp));
+}
+
+/* Run SERVER, giving it INIT_PORT_MAX initial ports from PORTS. */
+void
+run (char *server, mach_port_t *ports)
+{
+ error_t err;
+ char buf[BUFSIZ];
+ char *prog = server;
+
+ if (prompt_for_servers)
+ {
+ printf ("Server file name (default %s): ", server);
+ if (getstring (buf, sizeof (buf)))
+ prog = buf;
+ }
+
+ while (1)
+ {
+ file_t file;
+
+ file = path_lookup (prog, O_EXEC, 0);
+ if (file == MACH_PORT_NULL)
+ perror (prog);
+ else
+ {
+ err = file_exec (file, MACH_PORT_NULL, EXEC_NEWTASK,
+ NULL, 0, /* No args. */
+ NULL, 0, /* No env. */
+ NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No dtable. */
+ ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
+ NULL, 0, /* No info in init ints. */
+ NULL, 0, NULL, 0);
+ if (!err)
+ break;
+
+#ifdef notyet
+ hurd_perror (prog, err);
+#endif
+ }
+
+ printf ("File name for server %s (or nothing to reboot): ", server);
+ if (getstring (buf, sizeof (buf)))
+ prog = buf;
+ else
+ crash ();
+ }
+
+ printf ("started %s\n", prog);
+}
+
int
-main (int argc, char **argv)
+main (int argc, char **argv, char **envp)
{
int err;
mach_port_t bootport;
int i;
mach_port_t ports[INIT_PORT_MAX];
+ mach_port_t consdev;
+ global_argv = argv;
+
/* Fetch a port to the bootstrap filesystem, the host priv and
master device ports, and the console */
if (task_get_bootstrap_port (mach_task_self (), &bootport)
- || fsys_getpriv (bootport, &host_priv, &device_master)
+ || fsys_getpriv (bootport, &host_priv, &device_master, &fstask)
|| device_open (device_master, D_WRITE, "console", &consdev))
crash_mach ();
@@ -74,8 +242,8 @@ main (int argc, char **argv)
break;
}
- run (_HURD_PROC, ports);
- run (_HURD_AUTH, ports);
+ run ("/hurd/proc", ports, &proctask);
+ run ("/hurd/auth", ports, &authtask);
/* Wait for messages. When both auth and proc have started, we
run launch_system which does the rest of the boot. */
@@ -86,15 +254,21 @@ main (int argc, char **argv)
}
}
-error_t
+void
launch_system (void)
{
mach_port_t old;
+ mach_port_t authproc, fsproc;
- /* Reply to the proc and auth servers. */
- startup_procinit_reply (procreply, procreplytype, 0, authserver, host_priv,
- device_master);
- startup_authinit_reply (authreply, authreplytype, 0, authserver_proc);
+ /* Reply to the proc and auth servers. */
+ startup_procinit_reply (procreply, procreplytype, 0,
+ mach_task_self (), authserver,
+ host_priv, MACH_MSG_TYPE_COPY_SEND,
+ device_master, MACH_MSG_TYPE_MOVE_SEND);
+ device_master = 0;
+ proc_task2proc (procserver, authtask, &authproc);
+ startup_authinit_reply (authreply, authreplytype, 0, authproc,
+ MACH_MSG_TYPE_MOVE_SEND);
/* Give the library our auth and proc server ports. */
_hurd_port_init (&_hurd_ports[INIT_PORT_AUTH], authserver);
@@ -115,7 +289,9 @@ launch_system (void)
perror ("file_getcontrol (root)");
else
{
- if (errno = fsys_init (fsys, bootfs_proc, authserver))
+ proc_task2proc (procserver, fstask, &fsproc);
+ if (errno = fsys_init (fsys, fsproc, MACH_MSG_TYPE_MOVE_SEND,
+ authserver))
perror ("fsys_init");
mach_port_deallocate (mach_task_self (), fsys);
}
@@ -129,7 +305,8 @@ error_t
S_startup_procinit (startup_t server,
mach_port_t reply,
mach_msg_type_name_t reply_porttype,
- process_t proc, process_t fs_proc, process_t auth_proc,
+ process_t proc,
+ mach_port_t *startuptask,
auth_t *auth,
mach_port_t *priv, mach_port_t *dev)
{
@@ -139,9 +316,6 @@ S_startup_procinit (startup_t server,
procserver = proc;
- bootfs_proc = fs_proc;
- authserver_proc = auth_proc;
-
procreply = reply;
procreplytype = reply_porttype;
@@ -158,7 +332,8 @@ error_t
S_startup_authinit (startup_t server,
mach_port_t reply,
mach_msg_type_name_t reply_porttype,
- mach_port_t auth)
+ mach_port_t auth,
+ mach_port_t *proc)
{
if (authserver)
/* Only one auth server. */