diff options
author | Michael I. Bushnell <mib@gnu.org> | 1994-09-20 20:22:33 +0000 |
---|---|---|
committer | Michael I. Bushnell <mib@gnu.org> | 1994-09-20 20:22:33 +0000 |
commit | 5dfb41de08fec4f5668d106c8e2e7fc53890684d (patch) | |
tree | d9936fcdbd54a175453e1db97d28cf0ceba8be81 | |
parent | 47768c79e262d915a9b3209244831fde50499e6d (diff) |
Formerly init.c.~48~
-rw-r--r-- | init/init.c | 915 |
1 files changed, 0 insertions, 915 deletions
diff --git a/init/init.c b/init/init.c index f78c2d0b..e69de29b 100644 --- a/init/init.c +++ b/init/init.c @@ -1,915 +0,0 @@ -/* Init that only bootstraps the hurd and runs sh. - Copyright (C) 1993, 1994 Free Software Foundation - -This file is part of the GNU Hurd. - -The GNU Hurd is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -The GNU Hurd is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You should have received a copy of the GNU General Public License -along with the GNU Hurd; see the file COPYING. If not, write to -the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ - -/* Written by Michael I. Bushnell and Roland McGrath. */ - -#include <hurd.h> -#include <hurd/fs.h> -#include <hurd/fsys.h> -#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 <mach/notify.h> -#include <stdlib.h> -#include <hurd/msg.h> -#include <hurd/term.h> - -#include "startup_reply_U.h" -#include "startup_S.h" -#include "notify_S.h" - -/* Define this if we should really reboot mach instead of - just simulating it. */ -#undef STANDALONE - -/* 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; - -/* Our receive right */ -mach_port_t startup; - -/* Ports to the kernel */ -mach_port_t host_priv, device_master; - -/* Args to bootstrap, expressed as flags */ -int bootstrap_args; - -/* 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; - -/* Our bootstrap port, on which we call fsys_getpriv and fsys_init. */ -mach_port_t bootport; - -/* The tasks of auth and proc and the bootstrap filesystem. */ -task_t authtask, proctask, fstask; - -char *init_version = "0.0 pre-alpha"; - -mach_port_t default_ports[INIT_PORT_MAX]; -mach_port_t default_dtable[3]; - -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) -{ -#ifdef STANDALONE - printf ("init: %sing Mach (flags %#x)...\n", BOOT (flags), flags); - fflush (stdout); - while (errno = host_reboot (host_priv, flags)) - perror ("host_reboot"); - for (;;); -#else - printf ("init: Would %s Mach with flags %#x\n", BOOT (flags), flags); - fflush (stdout); - exit (1); -#endif -} - -/* Reboot the microkernel, specifying that this is a crash. */ -void -crash_mach (void) -{ - reboot_mach (CRASH_FLAGS); -} - -/* Reboot the Hurd. */ -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); - fflush (stdout); - /* 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)); - fflush (stdout); - } - } - -#ifdef STANDALONE - reboot_mach (flags); -#else - { - pid_t *pp; - u_int npids = 0; - error_t err; - int ind; - - err = proc_getallpids (procserver, &pp, &npids); - if (err == MACH_SEND_INVALID_DEST) - { - procbad: - /* The procserver must have died. Give up. */ - printf ("Init: can't simulate crash; proc has died\n"); - fflush (stdout); - reboot_mach (flags); - } - for (ind = 0; ind < npids; ind++) - { - task_t task; - err = proc_pid2task (procserver, pp[ind], &task); - if (err == MACH_SEND_INVALID_DEST) - goto procbad; - - else if (err) - { - printf ("init: getting task for pid %d: %s\n", - pp[ind], strerror (err)); - fflush (stdout); - continue; - } - - /* Postpone self so we can finish; postpone proc - so that we can finish. */ - if (task != mach_task_self () && task != proctask) - { - struct procinfo *pi = 0; - u_int pisize = 0; - err = proc_getprocinfo (procserver, pp[ind], (int **)&pi, &pisize); - if (err == MACH_SEND_INVALID_DEST) - goto procbad; - if (err) - { - printf ("init: getting procinfo for pid %d: %s\n", - pp[ind], strerror (err)); - fflush (stdout); - continue; - } - if (!(pi->state & PI_NOPARENT)) - { - printf ("init: killing pid %d\n", pp[ind]); - fflush (stdout); - task_terminate (task); - } - } - } - printf ("Killing proc server\n"); - fflush (stdout); - task_terminate (proctask); - printf ("Init exiting\n"); - fflush (stdout); - exit (1); - } -#endif -} - -/* Reboot the Hurd, specifying that this is a crash. */ -void -crash_system (void) -{ - reboot_system (CRASH_FLAGS); -} - -/* Run SERVER, giving it INIT_PORT_MAX initial ports from PORTS. - Set TASK to be the task port of the new image. */ -void -run (char *server, mach_port_t *ports, task_t *task) -{ - char buf[BUFSIZ]; - char *prog = server; - - if (bootstrap_args & RB_INITNAME) - { - printf ("Server file name (default %s): ", server); - if (getstring (buf, sizeof (buf))) - prog = buf; - } - - while (1) - { - file_t file; - - file = file_name_lookup (prog, O_EXEC, 0); - if (file == MACH_PORT_NULL) - perror (prog); - else - { - char *progname; - task_create (mach_task_self (), 0, task); - if (bootstrap_args & RB_KDB) - { - printf ("Pausing for %s\n", prog); - getchar (); - } - progname = strrchr (prog, '/'); - if (progname) - ++progname; - else - progname = prog; - errno = file_exec (file, *task, 0, - progname, strlen (progname) + 1, /* Args. */ - "", 1, /* No env. */ - default_dtable, MACH_MSG_TYPE_COPY_SEND, 3, - ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX, - NULL, 0, /* No info in init ints. */ - NULL, 0, NULL, 0); - if (!errno) - break; - - perror (prog); - } - - printf ("File name for server %s (or nothing to reboot): ", server); - if (getstring (buf, sizeof (buf))) - prog = buf; - else - crash_system (); - } - -#if 0 - printf ("started %s\n", prog); - fflush (stdout); -#endif -} - -/* Run FILENAME as root with ARGS as its argv (length ARGLEN). - Return the task that we started. If CTTY is set, then make - that the controlling terminal of the new process and put it in - its own login collection. */ -task_t -run_for_real (char *filename, char *args, int arglen, mach_port_t ctty) -{ - file_t file; - error_t err; - task_t task; - char *progname; - -#if 0 - char buf[512]; - do - { - printf ("File name [%s]: ", filename); - if (getstring (buf, sizeof (buf)) && *buf) - filename = buf; - file = file_name_lookup (filename, O_EXEC, 0); - if (!file) - perror (filename); - } - while (!file); -#else - file = file_name_lookup (filename, O_EXEC, 0); - if (!file) - { - perror (filename); - return MACH_PORT_NULL; - } -#endif - - task_create (mach_task_self (), 0, &task); - proc_child (procserver, task); - proc_task2proc (procserver, task, &default_ports[INIT_PORT_PROC]); - proc_setsid (default_ports[INIT_PORT_PROC]); - if (ctty != MACH_PORT_NULL) - { - int pid; - term_getctty (ctty, &default_ports[INIT_PORT_CTTYID]); - proc_task2pid (procserver, task, &pid); - io_mod_owner (ctty, -pid); - proc_make_login_coll (default_ports[INIT_PORT_PROC]); - } - if (bootstrap_args & RB_KDB) - { - printf ("Pausing for %s\n", filename); - getchar (); - } - progname = strrchr (filename, '/'); - if (progname) - ++progname; - else - progname = filename; - err = file_exec (file, task, 0, - args, arglen, - NULL, 0, /* No env. */ - default_dtable, MACH_MSG_TYPE_COPY_SEND, 3, - default_ports, MACH_MSG_TYPE_COPY_SEND, - INIT_PORT_MAX, - NULL, 0, /* No info in init ints. */ - NULL, 0, NULL, 0); - mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]); - if (ctty != MACH_PORT_NULL) - { - mach_port_deallocate (mach_task_self (), - default_ports[INIT_PORT_CTTYID]); - default_ports[INIT_PORT_CTTYID] = MACH_PORT_NULL; - } - mach_port_deallocate (mach_task_self (), file); - return err ? MACH_PORT_NULL : task; -} - -static int -demuxer (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)); -} - -int -main (int argc, char **argv, char **envp) -{ - volatile int err; - int i; - mach_port_t consdev; - extern char _edata, _etext, __data_start; - - global_argv = argv; - - /* Parse the arguments */ - bootstrap_args = 0; - if (argc >= 2) - { - if (index (argv[1], 'q')) - bootstrap_args |= RB_ASKNAME; - if (index (argv[1], 's')) - bootstrap_args |= RB_SINGLE; - if (index (argv[1], 'd')) - bootstrap_args |= RB_KDB; - if (index (argv[1], 'n')) - bootstrap_args |= RB_INITNAME; - } - - /* 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, &fstask) - || device_open (device_master, D_WRITE, "console", &consdev)) - crash_mach (); - - err = vm_wire (host_priv, mach_task_self (), - (vm_address_t) 0x10000, /* XXX */ - (vm_size_t) (&_etext - 0x10000), - VM_PROT_READ|VM_PROT_EXECUTE); - err = vm_wire (host_priv, mach_task_self (), - (vm_address_t) &__data_start, - (vm_size_t) (&_edata - &__data_start), - VM_PROT_READ|VM_PROT_WRITE); - - /* Clear our bootstrap port so our children don't inherit it. */ - task_set_bootstrap_port (mach_task_self (), MACH_PORT_NULL); - - stderr = stdout = mach_open_devstream (consdev, "w"); - stdin = mach_open_devstream (consdev, "r"); - if (stdout == NULL || stdin == NULL) - crash_mach (); - setbuf (stdout, NULL); - - /* At this point we can use assert to check for errors. */ - err = mach_port_allocate (mach_task_self (), - MACH_PORT_RIGHT_RECEIVE, &startup); - assert (!err); - err = mach_port_insert_right (mach_task_self (), startup, startup, - MACH_MSG_TYPE_MAKE_SEND); - assert (!err); - - /* Set up the set of ports we will pass to the programs we exec. */ - for (i = 0; i < INIT_PORT_MAX; i++) - switch (i) - { - case INIT_PORT_CRDIR: - default_ports[i] = getcrdir (); - break; - case INIT_PORT_CWDIR: - default_ports[i] = getcwdir (); - break; - default: - default_ports[i] = MACH_PORT_NULL; - break; - } - - default_dtable[0] = getdport (0); - default_dtable[1] = getdport (1); - default_dtable[2] = getdport (2); - - default_ports[INIT_PORT_BOOTSTRAP] = startup; - run ("/hurd/proc", default_ports, &proctask); - printf (" proc"); - fflush (stdout); - run ("/hurd/auth", default_ports, &authtask); - printf (" auth"); - fflush (stdout); - default_ports[INIT_PORT_BOOTSTRAP] = MACH_PORT_NULL; - - /* Wait for messages. When both auth and proc have started, we - run launch_system which does the rest of the boot. */ - while (1) - { - err = mach_msg_server (demuxer, 0, startup); - assert (!err); - } -} - -void -launch_core_servers (void) -{ - mach_port_t old; - mach_port_t authproc, fsproc; - - /* 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_COPY_SEND); -#ifdef STANDALONE - mach_port_deallocate (mach_task_self (), device_master); - device_master = 0; -#endif - - /* Declare that the filesystem and auth are our children. */ - proc_child (procserver, fstask); - proc_child (procserver, authtask); - - 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_set (&_hurd_ports[INIT_PORT_AUTH], authserver); - _hurd_port_set (&_hurd_ports[INIT_PORT_PROC], procserver); - - /* Do NOT run _hurd_proc_init! That will start signals, which we do not - want. We listen to our own message port. Tell the proc server where - our args and environment are. */ - proc_set_arg_locations (procserver, - (vm_address_t) global_argv, (vm_address_t) environ); - - default_ports[INIT_PORT_AUTH] = authserver; - - proc_register_version (procserver, host_priv, "init", HURD_RELEASE, - init_version); - - /* Get the bootstrap filesystem's proc server port. - We must do this before calling proc_setmsgport below. */ - proc_task2proc (procserver, fstask, &fsproc); - -#if 0 - printf ("Init has completed.\n"); - fflush (stdout); -#endif - printf (".\n"); - fflush (stdout); - - /* Tell the proc server our msgport. Be sure to do this after we are all - done making requests of proc. Once we have done this RPC, proc - assumes it can send us requests, so we cannot block on proc again - before accepting more RPC requests! However, we must do this before - calling fsys_init, because fsys_init blocks on exec_init, and - exec_init to block waiting on our message port. */ - proc_setmsgport (procserver, startup, &old); - if (old) - mach_port_deallocate (mach_task_self (), old); - - /* Give the bootstrap FS its proc and auth ports. */ - if (errno = fsys_init (bootport, fsproc, MACH_MSG_TYPE_MOVE_SEND, - authserver)) - perror ("fsys_init"); -} - -/* Set up the initial value of the standard exec data. */ -void -init_stdarrays () -{ - auth_t nullauth; - mach_port_t pt; - mach_port_t ref; - mach_port_t *std_port_array; - int *std_int_array; - - std_port_array = alloca (sizeof (mach_port_t) * INIT_PORT_MAX); - std_int_array = alloca (sizeof (int) * INIT_INT_MAX); - - bzero (std_port_array, sizeof (mach_port_t) * INIT_PORT_MAX); - bzero (std_int_array, sizeof (int) * INIT_INT_MAX); - - __USEPORT (AUTH, auth_makeauth (port, 0, MACH_MSG_TYPE_COPY_SEND, 0, - 0, 0, 0, 0, 0, 0, 0, 0, &nullauth)); - - pt = getcwdir (); - ref = mach_reply_port (); - io_reauthenticate (pt, ref, MACH_MSG_TYPE_MAKE_SEND); - auth_user_authenticate (nullauth, pt, ref, MACH_MSG_TYPE_MAKE_SEND, - &std_port_array[INIT_PORT_CWDIR]); - mach_port_destroy (mach_task_self (), ref); - mach_port_deallocate (mach_task_self (), pt); - - pt = getcrdir (); - ref = mach_reply_port (); - io_reauthenticate (pt, ref, MACH_MSG_TYPE_MAKE_SEND); - auth_user_authenticate (nullauth, pt, ref, MACH_MSG_TYPE_MAKE_SEND, - &std_port_array[INIT_PORT_CRDIR]); - mach_port_destroy (mach_task_self (), ref); - mach_port_deallocate (mach_task_self (), pt); - - std_port_array[INIT_PORT_AUTH] = nullauth; - - std_int_array[INIT_UMASK] = CMASK; - - __USEPORT (PROC, proc_setexecdata (port, std_port_array, - MACH_MSG_TYPE_MOVE_SEND, INIT_PORT_MAX, - std_int_array, INIT_INT_MAX)); -} - - -/* Start the single-user environment. This can only be done - when the core servers have fully started. We know that - startup_essential_task is the last thing they do before being - ready to handle requests, so we start this once all the necessary - servers have identified themselves that way. */ -void -launch_single_user () -{ - char shell[] = "/bin/sh"; - char terminal[] = "/hurd/term\0console\0/tmp/console"; - mach_port_t term, foo; - char *termname; - task_t termtask; - int fd; - int foobiebletch[TASK_BASIC_INFO_COUNT]; - int foobiebletchcount = TASK_BASIC_INFO_COUNT; - struct stat st; - - init_stdarrays (); - - printf ("Single-user environment:"); - fflush (stdout); - - /* Open the console. If we get something which is a terminal, then - we conclude that the filesystem has a proper translator for it, - and we're done. Otherwise, start /hurd/term on something inside - /tmp and use that. */ - term = file_name_lookup ("/dev/console", O_READ, 0); - termname = "/dev/console"; - if (term != MACH_PORT_NULL) - io_stat (term, &st); - - if (term == MACH_PORT_NULL || st.st_fstype != FSTYPE_TERM) - { - /* Start the terminal server ourselves. */ - - termtask = run_for_real (terminal, terminal, - sizeof (terminal), MACH_PORT_NULL); - printf (" term"); - fflush (stdout); - - /* Must match arg to terminal above. */ - termname = "/tmp/console"; - - tryagain: - - term = file_name_lookup (termname, O_READ, 0); - if (term != MACH_PORT_NULL) - io_stat (term, &st); - if (term == MACH_PORT_NULL || st.st_fstype != FSTYPE_TERM) - { - /* It hasn't been set yet; sleep a bit and try again. - - However, if TERMTASK has died, then it has a bug. We'll - just let our fd's pass through unchanged. This probably - won't work, but it will enable some sort of debugging, - maybe. */ - errno = task_info (termtask, TASK_BASIC_INFO, foobiebletch, - &foobiebletchcount); - if (errno != MACH_SEND_INVALID_DEST - && errno != KERN_INVALID_ARGUMENT) - { - sleep (1); - goto tryagain; - } - printf ("\nWarning: no normal console terminal.\n"); - fflush (stdout); - term = MACH_PORT_NULL; - } - mach_port_deallocate (mach_task_self (), termtask); - } - - /* At this point either TERM is the console or it's null. If it's - null, then don't do anything, and our fd's will be copied. - Otherwise, open fd's 0, 1, and 2. */ - if (term != MACH_PORT_NULL) - { - fd = open (termname, O_READ); - assert (fd != -1); - dup2 (fd, 0); - close (fd); - - fd = open (termname, O_WRITE); - assert (fd != -1); - dup2 (fd, 1); - dup2 (fd, 2); - close (fd); - - fclose (stdin); - stdin = fdopen (0, "r"); - - /* Don't reopen our output channel for reliability's sake. */ - - /* Set ports in init_dtable for programs we start. */ - mach_port_deallocate (mach_task_self (), default_dtable[0]); - mach_port_deallocate (mach_task_self (), default_dtable[1]); - mach_port_deallocate (mach_task_self (), default_dtable[2]); - default_dtable[0] = getdport (0); - default_dtable[1] = getdport (1); - default_dtable[2] = getdport (2); - } - - /* The shell needs a real controlling terminal, so set that up here. */ - foo = run_for_real (shell, shell, sizeof (shell), term); - mach_port_deallocate (mach_task_self (), term); - if (foo != MACH_PORT_NULL) - mach_port_deallocate (mach_task_self (), foo); - printf (" shell.\n"); - fflush (stdout); -} - - -kern_return_t -S_startup_procinit (startup_t server, - mach_port_t reply, - mach_msg_type_name_t reply_porttype, - process_t proc, - mach_port_t *startuptask, - auth_t *auth, - mach_port_t *priv, - mach_msg_type_name_t *hostprivtype, - mach_port_t *dev, - mach_msg_type_name_t *devtype) -{ - if (procserver) - /* Only one proc server. */ - return EPERM; - - procserver = proc; - - procreply = reply; - procreplytype = reply_porttype; - - /* Save the reply port until we get startup_authinit. */ - if (authserver) - launch_core_servers (); - - return MIG_NO_REPLY; -} - -/* Called by the auth server when it starts up. */ - -kern_return_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 *proc, - mach_msg_type_name_t *proctype) -{ - if (authserver) - /* Only one auth server. */ - return EPERM; - - authserver = auth; - - /* Save the reply port until we get startup_procinit. */ - authreply = reply; - authreplytype = reply_porttype; - - if (procserver) - launch_core_servers (); - - return MIG_NO_REPLY; -} - -kern_return_t -S_startup_essential_task (mach_port_t server, - mach_port_t reply, - mach_msg_type_name_t replytype, - task_t task, - mach_port_t excpt, - char *name, - mach_port_t credential) -{ - struct ess_task *et; - mach_port_t prev; - static int authinit, procinit, execinit, initdone; - - if (credential != host_priv) - return EPERM; - /* Record this task as essential. */ - et = malloc (sizeof (struct ess_task)); - if (et == NULL) - return ENOMEM; - et->task_port = task; - et->name = strdup (name); - if (et->name == NULL) - { - free (et); - return ENOMEM; - } - et->next = ess_tasks; - ess_tasks = et; - - /* Dead-name notification on the task port will tell us when it dies. */ - mach_port_request_notification (mach_task_self (), task, - MACH_NOTIFY_DEAD_NAME, 1, startup, - MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev); - if (prev) - mach_port_deallocate (mach_task_self (), prev); - -#if 0 - /* Taking over the exception port will give us a better chance - if the task tries to get wedged on a fault. */ - task_set_special_port (task, TASK_EXCEPTION_PORT, startup); -#endif - - mach_port_deallocate (mach_task_self (), credential); - - if (!initdone) - { - if (!strcmp (name, "auth")) - authinit = 1; - else if (!strcmp (name, "exec")) - execinit = 1; - else if (!strcmp (name, "proc")) - procinit = 1; - - if (authinit && execinit && procinit) - { - /* Reply to this RPC, after that everything - is ready for real startup to begin. */ - startup_essential_task_reply (reply, replytype, 0); - - launch_single_user (); - initdone = 1; - return MIG_NO_REPLY; - } - } - - return 0; -} - -kern_return_t -S_startup_request_notification (mach_port_t server, - mach_port_t notify) -{ - struct ntfy_task *nt; - mach_port_t prev; - - mach_port_request_notification (mach_task_self (), notify, - MACH_NOTIFY_DEAD_NAME, 1, startup, - MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev); - if (prev) - mach_port_deallocate (mach_task_self (), prev); - - nt = malloc (sizeof (struct ntfy_task)); - nt->notify_port = notify; - nt->next = ntfy_tasks; - ntfy_tasks = nt; - return 0; -} - -kern_return_t -do_mach_notify_dead_name (mach_port_t notify, - mach_port_t name) -{ - struct ntfy_task *nt, *pnt; - struct ess_task *et; - - for (et = ess_tasks; et != NULL; et = et->next) - if (et->task_port == name) - /* An essential task has died. */ - { - printf ("Init crashing system; essential task %s died\n", - et->name); - fflush (stdout); - crash_system (); - } - - for (nt = ntfy_tasks, pnt = NULL; nt != NULL; pnt = nt, nt = nt->next) - if (nt->notify_port == name) - { - /* Someone who wanted to be notified is gone. */ - mach_port_deallocate (mach_task_self (), name); - if (pnt != NULL) - pnt->next = nt->next; - else - ntfy_tasks = nt->next; - free (nt); - return 0; - } - return 0; -} - -kern_return_t -S_startup_reboot (mach_port_t server, - mach_port_t refpt, - int code) -{ - if (refpt != host_priv) - return EPERM; - - reboot_system (code); - for (;;); -} - -kern_return_t -do_mach_notify_port_destroyed (mach_port_t notify, - mach_port_t rights) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_send_once (mach_port_t notify) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_no_senders (mach_port_t port, mach_port_mscount_t mscount) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_port_deleted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} - -kern_return_t -do_mach_notify_msg_accepted (mach_port_t notify, - mach_port_t name) -{ - return EOPNOTSUPP; -} |