commit-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[hurd] 01/02: New upstream snapshot


From: Samuel Thibault
Subject: [hurd] 01/02: New upstream snapshot
Date: Wed, 10 Dec 2014 15:17:02 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch master
in repository hurd.

commit f248a21a78d1ea3c025da928de4e950511f637f6
Author: Samuel Thibault <address@hidden>
Date:   Wed Dec 10 01:15:05 2014 +0000

    New upstream snapshot
---
 Makeconf                                           |    4 +-
 Makefile                                           |    4 +-
 auth/mig-decls.h                                   |    6 +
 auth/mig-mutate.h                                  |    1 +
 boot/boot.c                                        |  290 ++--
 boot/boot_script.h                                 |    4 -
 console-client/trans.c                             |   12 +-
 console/mutations.h                                |    3 +
 console/pager.c                                    |    1 +
 daemons/Makefile                                   |    4 +-
 daemons/rc.sh                                      |    3 -
 daemons/{runsystem.sh => runsystem.hurd}           |    0
 daemons/runsystem.sh                               |   80 +-
 devnode/devnode.c                                  |   21 -
 doc/hurd.texi                                      |    6 +-
 eth-filter/filter.c                                |   21 -
 eth-multiplexer/demuxer.c                          |   37 +-
 eth-multiplexer/device.h                           |  336 ----
 eth-multiplexer/device_impl.c                      |   26 -
 eth-multiplexer/ethernet.c                         |    7 +-
 exec/execmutations.h                               |    3 +
 exec/main.c                                        |   11 +-
 exec/mig-decls.h                                   |    6 +
 hurd/default_pager.defs                            |    1 +
 hurd/hurd_types.defs                               |  120 +-
 hurd/paths.h                                       |    3 +-
 hurd/process.defs                                  |    6 +-
 hurd/process_reply.defs                            |    2 +-
 hurd/process_request.defs                          |    7 +-
 hurd/term.defs                                     |    3 +
 include/Makefile                                   |    2 +-
 include/pids.h                                     |    7 +-
 init/Makefile                                      |   15 +-
 init/init.c                                        | 1614 ++------------------
 init/stubs.c                                       |  139 --
 libcons/mutations.h                                |    1 +
 libcons/priv.h                                     |    6 +
 libdiskfs/boot-start.c                             |   11 +-
 libdiskfs/dir-init.c                               |    3 +-
 libdiskfs/dir-lookup.c                             |   11 +-
 libdiskfs/disk-pager.c                             |    1 +
 libdiskfs/diskfs.h                                 |   29 +
 libdiskfs/fsmutations.h                            |    5 +
 libdiskfs/init-startup.c                           |   13 +-
 libdiskfs/opts-std-startup.c                       |    2 +-
 libfshelp/lock-acquire.c                           |   95 +-
 libmachdev/Makefile                                |    3 -
 libmachdev/ds_routines.c                           |   45 -
 libmachdev/net.c                                   |   36 +-
 libnetfs/dir-lookup.c                              |   13 +-
 libnetfs/mutations.h                               |    3 +
 libnetfs/priv.h                                    |   12 +
 libpager/demuxer.c                                 |   66 +-
 libpager/mig-decls.h                               |    6 +
 libpager/mig-mutate.h                              |    3 +
 libpager/pager-memcpy.c                            |    2 +
 libports/Makefile                                  |    2 +-
 random/mig-mutate.h => libports/extern-inline.c    |   13 +-
 libports/mig-decls.h                               |    6 +
 libports/mig-mutate.h                              |    4 +
 libports/ports.h                                   |   53 +
 libshouldbeinlibc/Makefile                         |    8 +-
 .../mig-mutate.h => libshouldbeinlibc/refcount.c   |   14 +-
 {include => libshouldbeinlibc}/refcount.h          |   40 +-
 libstore/memobj.c                                  |    1 +
 libtrivfs/mig-decls.h                              |   58 +
 libtrivfs/mig-mutate.h                             |    3 +
 mach-defpager/kalloc.c                             |   14 +-
 pfinet/ethernet.c                                  |   20 +-
 pfinet/main.c                                      |   24 +-
 pfinet/mig-decls.h                                 |   12 +
 pfinet/mig-mutate.h                                |    4 +
 pflocal/mig-decls.h                                |   12 +
 pflocal/mig-mutate.h                               |    3 +
 proc/main.c                                        |   53 +-
 proc/mgt.c                                         |   76 +-
 proc/mig-decls.h                                   |   17 +
 proc/mig-mutate.h                                  |    4 +
 proc/notify.c                                      |    6 +-
 proc/proc.h                                        |    8 +-
 proc/proc_exc.defs                                 |    1 +
 procfs/main.c                                      |   27 +-
 random/Makefile                                    |    1 -
 random/mig-decls.h                                 |   47 -
 random/random.c                                    |    5 +-
 {init => startup}/Makefile                         |   12 +-
 init/init.c => startup/startup.c                   |  180 ++-
 sutils/fstab.c                                     |  103 +-
 term/Makefile                                      |    1 +
 term/mig-decls.h                                   |    6 +
 term/mig-mutate.h                                  |    3 +
 term/ptyio.c                                       |    2 +-
 tmpfs/node.c                                       |    1 +
 trans/Makefile                                     |    9 +
 trans/fakeroot.c                                   |   31 +-
 trans/mtab.c                                       |   46 +-
 utils/rpctrace.c                                   |   31 +-
 utils/umount.c                                     |    4 +-
 98 files changed, 1390 insertions(+), 2746 deletions(-)

diff --git a/Makeconf b/Makeconf
index 32eec13..f0d3fe3 100644
--- a/Makeconf
+++ b/Makeconf
@@ -575,7 +575,9 @@ vpath %.defs $(top_srcdir)/hurd
 # These we want to find in the libc include directory...
 mach_defs_names = bootstrap exc mach mach4 \
        mach_host mach_port mach_timer_reply memory_object \
-       memory_object_default notify
+       memory_object_default notify \
+       gnumach \
+
 mach_debug_defs_names = mach_debug
 device_defs_names = dev_forward device device_reply device_request
 
diff --git a/Makefile b/Makefile
index 0b9eff2..3178740 100644
--- a/Makefile
+++ b/Makefile
@@ -31,7 +31,7 @@ lib-subdirs = libshouldbeinlibc libihash libiohelp libports 
libthreads \
              libnetfs libpipe libstore libhurdbugaddr libftpconn libcons
 
 # Hurd programs
-prog-subdirs = auth proc exec init term \
+prog-subdirs = auth proc exec term \
               ext2fs isofs tmpfs fatfs \
               storeio pflocal pfinet defpager mach-defpager \
               login daemons boot console \
@@ -40,6 +40,8 @@ prog-subdirs = auth proc exec init term \
               benchmarks fstests \
               random \
               procfs \
+              startup \
+              init \
 
 ifeq ($(HAVE_SUN_RPC),yes)
 prog-subdirs += nfs nfsd
diff --git a/auth/mig-decls.h b/auth/mig-decls.h
index 09c7c70..fa7b06d 100644
--- a/auth/mig-decls.h
+++ b/auth/mig-decls.h
@@ -32,6 +32,12 @@ auth_port_to_handle (mach_port_t auth)
   return ports_lookup_port (auth_bucket, auth, authhandle_portclass);
 }
 
+static inline struct authhandle * __attribute__ ((unused))
+auth_payload_to_handle (unsigned long payload)
+{
+  return ports_lookup_payload (auth_bucket, payload, authhandle_portclass);
+}
+
 static inline void __attribute__ ((unused))
 end_using_authhandle (struct authhandle *auth)
 {
diff --git a/auth/mig-mutate.h b/auth/mig-mutate.h
index ea40c70..5cc8914 100644
--- a/auth/mig-mutate.h
+++ b/auth/mig-mutate.h
@@ -20,5 +20,6 @@
 /* CPP definitions for MiG processing of auth.defs for auth server.  */
 
 #define AUTH_INTRAN authhandle_t auth_port_to_handle (auth_t)
+#define AUTH_INTRAN_PAYLOAD authhandle_t auth_payload_to_handle
 #define AUTH_DESTRUCTOR end_using_authhandle (authhandle_t)
 #define AUTH_IMPORTS import "mig-decls.h";
diff --git a/boot/boot.c b/boot/boot.c
index 03617f5..e2cb907 100644
--- a/boot/boot.c
+++ b/boot/boot.c
@@ -109,10 +109,10 @@ typedef struct stat host_stat_t;
 
 #endif /* UX */
 
-mach_port_t privileged_host_port, master_device_port, defpager;
+mach_port_t privileged_host_port, master_device_port;
 mach_port_t pseudo_master_device_port;
 mach_port_t receive_set;
-mach_port_t pseudo_console, pseudo_root;
+mach_port_t pseudo_console, pseudo_root, pseudo_time;
 auth_t authserver;
 
 struct store *root_store;
@@ -169,36 +169,55 @@ useropen (const char *name, int flags, int mode)
   return open (name, flags, mode);
 }
 
-int
-request_server (mach_msg_header_t *inp,
-               mach_msg_header_t *outp)
-{
-  extern int io_server (mach_msg_header_t *, mach_msg_header_t *);
-  extern int device_server (mach_msg_header_t *, mach_msg_header_t *);
-  extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
-  extern int term_server (mach_msg_header_t *, mach_msg_header_t *);
-/*  extern int tioctl_server (mach_msg_header_t *, mach_msg_header_t *); */
-  extern int bootstrap_server (mach_msg_header_t *, mach_msg_header_t *);
-  extern void bootstrap_compat ();
+/* XXX: glibc should provide mig_reply_setup but does not.  */
+/* Fill in default response.  */
+void
+mig_reply_setup (
+       const mach_msg_header_t *in,
+       mach_msg_header_t       *out)
+{
+      static const mach_msg_type_t RetCodeType = {
+               /* msgt_name = */               MACH_MSG_TYPE_INTEGER_32,
+               /* msgt_size = */               32,
+               /* msgt_number = */             1,
+               /* msgt_inline = */             TRUE,
+               /* msgt_longform = */           FALSE,
+               /* msgt_deallocate = */         FALSE,
+               /* msgt_unused = */             0
+       };
+
+#define        InP     (in)
+#define        OutP    ((mig_reply_header_t *) out)
+      OutP->Head.msgh_bits =
+       MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InP->msgh_bits), 0);
+      OutP->Head.msgh_size = sizeof *OutP;
+      OutP->Head.msgh_remote_port = InP->msgh_remote_port;
+      OutP->Head.msgh_local_port = MACH_PORT_NULL;
+      OutP->Head.msgh_seqno = 0;
+      OutP->Head.msgh_id = InP->msgh_id + 100;
+      OutP->RetCodeType = RetCodeType;
+      OutP->RetCode = MIG_BAD_ID;
+#undef InP
+#undef OutP
+}
 
-#if 0
-  if (inp->msgh_local_port == bootport && boot_like_cmudef)
+int
+boot_demuxer (mach_msg_header_t *inp,
+             mach_msg_header_t *outp)
+{
+  mig_routine_t routine;
+  mig_reply_setup (inp, outp);
+  if ((routine = io_server_routine (inp)) ||
+      (routine = device_server_routine (inp)) ||
+      (routine = notify_server_routine (inp)) ||
+      (routine = term_server_routine (inp))
+      /* (routine = tioctl_server_routine (inp)) */)
     {
-      if (inp->msgh_id == 999999)
-       {
-         bootstrap_compat (inp, outp);
-         return 1;
-       }
-      else
-       return bootstrap_server (inp, outp);
+      (*routine) (inp, outp);
+      return TRUE;
     }
   else
-#endif
-   return (io_server (inp, outp)
-          || device_server (inp, outp)
-          || notify_server (inp, outp)
-          || term_server (inp, outp)
-          /*       || tioctl_server (inp, outp) */);
+    return FALSE;
 }
 
 vm_address_t
@@ -295,47 +314,6 @@ void read_reply ();
 void * msg_thread (void *);
 
 /* Callbacks for boot_script.c; see boot_script.h.  */
-
-mach_port_t
-boot_script_read_file (const char *filename)
-{
-  static const char msg[] = ": cannot open\n";
-  int fd = useropen (filename, O_RDONLY, 0);
-  host_stat_t st;
-  error_t err;
-  mach_port_t memobj;
-  vm_address_t region;
-
-  write (2, filename, strlen (filename));
-  if (fd < 0)
-    {
-      write (2, msg, sizeof msg - 1);
-      host_exit (1);
-    }
-  else
-    write (2, msg + sizeof msg - 2, 1);
-
-  host_fstat (fd, &st);
-
-  err = default_pager_object_create (defpager, &memobj,
-                                    round_page (st.st_size));
-  if (err)
-    {
-      static const char msg[] = "cannot create default-pager object\n";
-      write (2, msg, sizeof msg - 1);
-      host_exit (1);
-    }
-
-  region = 0;
-  vm_map (mach_task_self (), &region, round_page (st.st_size),
-         0, 1, memobj, 0, 0, VM_PROT_ALL, VM_PROT_ALL, VM_INHERIT_NONE);
-  read (fd, (char *) region, st.st_size);
-  munmap ((caddr_t) region, round_page (st.st_size));
-
-  close (fd);
-  return memobj;
-}
-
 int
 boot_script_exec_cmd (void *hook,
                      mach_port_t task, char *path, int argc,
@@ -546,9 +524,6 @@ main (int argc, char **argv, char **envp)
 
   get_privileged_ports (&privileged_host_port, &master_device_port);
 
-  defpager = MACH_PORT_NULL;
-  vm_set_default_memory_manager (privileged_host_port, &defpager);
-
   strcat (bootstrap_args, "f");
 
   mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_PORT_SET,
@@ -592,6 +567,15 @@ main (int argc, char **argv, char **envp)
   if (foo != MACH_PORT_NULL)
     mach_port_deallocate (mach_task_self (), foo);
 
+  mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE,
+                     &pseudo_time);
+  mach_port_move_member (mach_task_self (), pseudo_time, receive_set);
+  mach_port_request_notification (mach_task_self (), pseudo_time,
+                                 MACH_NOTIFY_NO_SENDERS, 1, pseudo_time,
+                                 MACH_MSG_TYPE_MAKE_SEND_ONCE, &foo);
+  if (foo != MACH_PORT_NULL)
+    mach_port_deallocate (mach_task_self (), foo);
+
   if (kernel_command_line == 0)
     asprintf (&kernel_command_line, "%s %s root=%s",
              argv[0], bootstrap_args, bootdevice);
@@ -759,15 +743,13 @@ main (int argc, char **argv, char **envp)
       else /* We hosed */
        error (5, errno, "select");
     }
-
-/*  mach_msg_server (request_server, __vm_page_size * 2, receive_set); */
 }
 
 void *
 msg_thread (void *arg)
 {
   while (1)
-    mach_msg_server (request_server, 0, receive_set);
+    mach_msg_server (boot_demuxer, 0, receive_set);
 }
 
 
@@ -914,8 +896,6 @@ unlock_readlock ()
 /*
  *     Handle bootstrap requests.
  */
-/* These two functions from .../mk/bootstrap/default_pager.c. */
-
 kern_return_t
 do_bootstrap_privileged_ports(bootstrap, hostp, devicep)
        mach_port_t bootstrap;
@@ -925,68 +905,6 @@ do_bootstrap_privileged_ports(bootstrap, hostp, devicep)
        *devicep = pseudo_master_device_port;
        return KERN_SUCCESS;
 }
-
-void
-bootstrap_compat(in, out)
-       mach_msg_header_t *in, *out;
-{
-       mig_reply_header_t *reply = (mig_reply_header_t *) out;
-       mach_msg_return_t mr;
-
-       struct imsg {
-               mach_msg_header_t       hdr;
-               mach_msg_type_t         port_desc_1;
-               mach_port_t             port_1;
-               mach_msg_type_t         port_desc_2;
-               mach_port_t             port_2;
-       } imsg;
-
-       /*
-        * Send back the host and device ports.
-        */
-
-       imsg.hdr.msgh_bits = MACH_MSGH_BITS_COMPLEX |
-               MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(in->msgh_bits), 0);
-       /* msgh_size doesn't need to be initialized */
-       imsg.hdr.msgh_remote_port = in->msgh_remote_port;
-       imsg.hdr.msgh_local_port = MACH_PORT_NULL;
-       /* msgh_seqno doesn't need to be initialized */
-       imsg.hdr.msgh_id = in->msgh_id + 100;   /* this is a reply msg */
-
-       imsg.port_desc_1.msgt_name = MACH_MSG_TYPE_COPY_SEND;
-       imsg.port_desc_1.msgt_size = (sizeof(mach_port_t) * 8);
-       imsg.port_desc_1.msgt_number = 1;
-       imsg.port_desc_1.msgt_inline = TRUE;
-       imsg.port_desc_1.msgt_longform = FALSE;
-       imsg.port_desc_1.msgt_deallocate = FALSE;
-       imsg.port_desc_1.msgt_unused = 0;
-
-       imsg.port_1 = privileged_host_port;
-
-       imsg.port_desc_2 = imsg.port_desc_1;
-
-       imsg.port_desc_2.msgt_name = MACH_MSG_TYPE_MAKE_SEND;
-       imsg.port_2 = pseudo_master_device_port;
-
-       /*
-        * Send the reply message.
-        * (mach_msg_server can not do this, because the reply
-        * is not in standard format.)
-        */
-
-       mr = mach_msg(&imsg.hdr, MACH_SEND_MSG,
-                     sizeof imsg, 0, MACH_PORT_NULL,
-                     MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
-       if (mr != MACH_MSG_SUCCESS)
-               (void) mach_port_deallocate(mach_task_self (),
-                                           imsg.hdr.msgh_remote_port);
-
-       /*
-        * Tell mach_msg_server to do nothing.
-        */
-
-       reply->RetCode = MIG_NO_REPLY;
-}
 
 /* Implementation of device interface */
 
@@ -1016,6 +934,12 @@ ds_device_open (mach_port_t master_port,
       *devicetype = MACH_MSG_TYPE_MAKE_SEND;
       return 0;
     }
+  else if (!strcmp (name, "time"))
+    {
+      *device = pseudo_time;
+      *devicetype = MACH_MSG_TYPE_MAKE_SEND;
+      return 0;
+    }
   else if (strcmp (name, "pseudo-root") == 0)
     /* Magic root device.  */
     {
@@ -1240,40 +1164,6 @@ ds_device_read_inband (device_t device,
 }
 
 kern_return_t
-ds_xxx_device_set_status (device_t device,
-                         dev_flavor_t flavor,
-                         dev_status_t status,
-                         size_t statu_cnt)
-{
-  if (device != pseudo_console)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_get_status (device_t device,
-                         dev_flavor_t flavor,
-                         dev_status_t status,
-                         size_t *statuscnt)
-{
-  if (device != pseudo_console && device != pseudo_root)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_set_filter (device_t device,
-                         mach_port_t rec,
-                         int pri,
-                         filter_array_t filt,
-                         size_t len)
-{
-  if (device != pseudo_console && device != pseudo_root)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
 ds_device_map (device_t device,
               vm_prot_t prot,
               vm_offset_t offset,
@@ -1281,9 +1171,26 @@ ds_device_map (device_t device,
               memory_object_t *pager,
               int unmap)
 {
-  if (device != pseudo_console && device != pseudo_root)
+  if (device == pseudo_console || device == pseudo_root)
+    return D_INVALID_OPERATION;
+  else if (device == pseudo_time)
+    {
+      error_t err;
+      mach_port_t wr_memobj;
+      file_t node = file_name_lookup ("/dev/time", O_RDONLY, 0);
+
+      if (node == MACH_PORT_NULL)
+       return D_IO_ERROR;
+
+      err = io_map (node, pager, &wr_memobj);
+      if (!err && MACH_PORT_VALID (wr_memobj))
+       mach_port_deallocate (mach_task_self (), wr_memobj);
+
+      mach_port_deallocate (mach_task_self (), node);
+      return D_SUCCESS;
+    }
+  else
     return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
 }
 
 kern_return_t
@@ -1306,18 +1213,27 @@ ds_device_get_status (device_t device,
   if (device == pseudo_console)
     return D_INVALID_OPERATION;
   else if (device == pseudo_root)
-    if (flavor == DEV_GET_SIZE)
-      if (*statuslen < DEV_GET_SIZE_COUNT)
-       return D_INVALID_SIZE;
-      else
-       {
-         status[DEV_GET_SIZE_DEVICE_SIZE] = root_store->size;
-         status[DEV_GET_SIZE_RECORD_SIZE] = root_store->block_size;
-         *statuslen = DEV_GET_SIZE_COUNT;
-         return D_SUCCESS;
-       }
-    else
-      return D_INVALID_OPERATION;
+    switch (flavor)
+      {
+      case DEV_GET_SIZE:
+        if (*statuslen < DEV_GET_SIZE_COUNT)
+          return D_INVALID_SIZE;
+        status[DEV_GET_SIZE_DEVICE_SIZE] = root_store->size;
+        status[DEV_GET_SIZE_RECORD_SIZE] = root_store->block_size;
+        *statuslen = DEV_GET_SIZE_COUNT;
+        return D_SUCCESS;
+
+      case DEV_GET_RECORDS:
+        if (*statuslen < DEV_GET_RECORDS_COUNT)
+          return D_INVALID_SIZE;
+        status[DEV_GET_RECORDS_DEVICE_RECORDS] = root_store->blocks;
+        status[DEV_GET_RECORDS_RECORD_SIZE] = root_store->block_size;
+        *statuslen = DEV_GET_RECORDS_COUNT;
+        return D_SUCCESS;
+
+      default:
+        return D_INVALID_OPERATION;
+      }
   else
     return D_NO_SUCH_DEVICE;
 }
diff --git a/boot/boot_script.h b/boot/boot_script.h
index 6245869..da52e6f 100644
--- a/boot/boot_script.h
+++ b/boot/boot_script.h
@@ -69,10 +69,6 @@ int boot_script_exec_cmd (void *hook,
                          task_t task, char *path, int argc,
                          char **argv, char *strings, int stringlen);
 
-/* The user must define this function.  Load the contents of FILE
-   into a fresh anonymous memory object and return the memory object port.  */
-mach_port_t boot_script_read_file (const char *file);
-
 /* The user must define this functions to perform the corresponding
    Mach task manipulations.  */
 int boot_script_task_create (struct cmd *); /* task_create + task_suspend */
diff --git a/console-client/trans.c b/console-client/trans.c
index 67cd149..224229e 100644
--- a/console-client/trans.c
+++ b/console-client/trans.c
@@ -63,8 +63,16 @@ console_demuxer (mach_msg_header_t *inp,
   ret = netfs_demuxer (inp, outp);
   if (ret)
     return ret;
-  
-  user = ports_lookup_port (netfs_port_bucket, inop->msgh_local_port, 
netfs_protid_class);
+
+  if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) ==
+      MACH_MSG_TYPE_PROTECTED_PAYLOAD)
+    user = ports_lookup_payload (netfs_port_bucket,
+                                inop->msgh_protected_payload,
+                                netfs_protid_class);
+  else
+    user = ports_lookup_port (netfs_port_bucket,
+                             inop->msgh_local_port,
+                             netfs_protid_class);
   if (!user)
     return ret;
   
diff --git a/console/mutations.h b/console/mutations.h
index 4e1cc7e..87906cc 100644
--- a/console/mutations.h
+++ b/console/mutations.h
@@ -21,12 +21,15 @@
 /* Only CPP macro definitions should go in this file. */
 
 #define IO_INTRAN protid_t begin_using_protid_port (io_t)
+#define IO_INTRAN_PAYLOAD protid_t begin_using_protid_payload
 #define IO_DESTRUCTOR end_using_protid_port (protid_t)
 
 #define TIOCTL_IMPORTS import "libnetfs/priv.h";
 
 #define NOTIFY_INTRAN                                          \
   port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD                                  \
+  port_info_t begin_using_port_info_payload
 #define NOTIFY_DESTRUCTOR                                      \
   end_using_port_info (port_info_t)
 #define NOTIFY_IMPORTS                                         \
diff --git a/console/pager.c b/console/pager.c
index 3568211..5e13ba4 100644
--- a/console/pager.c
+++ b/console/pager.c
@@ -169,6 +169,7 @@ user_pager_create (struct user_pager *user_pager, unsigned 
int npages,
   mach_port_insert_right (mach_task_self (), user_pager->memobj,
                          user_pager->memobj, MACH_MSG_TYPE_MAKE_SEND);
 
+  *user = 0;
   err = vm_map (mach_task_self (),
                (vm_address_t *) user,
                (vm_size_t) npages * vm_page_size,
diff --git a/daemons/Makefile b/daemons/Makefile
index d16680e..db1acc7 100644
--- a/daemons/Makefile
+++ b/daemons/Makefile
@@ -22,7 +22,9 @@ makemode := utilities
 
 targets = rc getty mail.local console-run runttys runsystem
 special-targets = rc runsystem
-SRCS = rc.sh runsystem.sh getty.c lmail.c console-run.c runttys.c
+SRCS = rc.sh runsystem.sh getty.c lmail.c console-run.c runttys.c \
+       runsystem.hurd \
+
 installationdir = $(libexecdir)
 
 HURDLIBS = fshelp ports shouldbeinlibc
diff --git a/daemons/rc.sh b/daemons/rc.sh
index 5cf44fa..1240883 100644
--- a/daemons/rc.sh
+++ b/daemons/rc.sh
@@ -2,9 +2,6 @@
 
 PATH=/bin:/sbin
 
-# Start the default pager.  It will bail if there is already one running.
-/hurd/mach-defpager
-
 # Set up swap space.  This will complain if no default pager is functioning.
 swapon -a
 
diff --git a/daemons/runsystem.sh b/daemons/runsystem.hurd
similarity index 100%
copy from daemons/runsystem.sh
copy to daemons/runsystem.hurd
diff --git a/daemons/runsystem.sh b/daemons/runsystem.sh
index f4f2771..ae25a7d 100644
--- a/daemons/runsystem.sh
+++ b/daemons/runsystem.sh
@@ -1,9 +1,9 @@
 #!/bin/bash
 #
 # This program is run by /hurd/init at boot time after the essential
-# servers are up, and is responsible for running the "userland" parts of a
-# normal system.  This includes running the single-user shell as well as a
-# multi-user system.  This program is expected never to exit.
+# servers are up.  It does some initialization of its own and then
+# execs /hurd/init or any other roughly SysV init-compatible program
+# to bring up the "userland" parts of a normal system.
 #
 
 
@@ -22,11 +22,10 @@ fallback_shells='/bin/sh /bin/bash /bin/csh /bin/ash 
/bin/shd'
 # Shell used for normal single-user startup.
 SHELL=/bin/sh
 
-# Programs that do multi-user startup.
-RUNCOM=/libexec/rc
-RUNTTYS=/libexec/runttys
-# Signals that we should pass down to runttys.
-runttys_sigs='TERM INT HUP TSTP'
+# The init program to call.
+#
+# Can be overridden using init=something in the kernel command line.
+init=/hurd/init
 
 ###
 
@@ -44,7 +43,7 @@ trap 'reopen_console' SIGLOST
 # startup entirely.  We exec a single-user shell, so we will not come back
 # here.  The only way to get to multi-user from that shell will be
 # explicitly exec this script or something like that.
-function singleuser ()
+function singleuser()
 {
   test $# -eq 0 || echo "$0: $*"
   for try in ${fallback_shells}; do
@@ -54,6 +53,8 @@ function singleuser ()
   exit 127
 }
 
+# Print a newline.
+echo
 
 # See whether pflocal is set up already, and do so if not (install case)
 #
@@ -85,20 +86,23 @@ fi
 # The first argument is the kernel file name; skip that.
 shift
 flags=
+single=
 while [ $# -gt 0 ]; do
   arg="$1"
   shift
   case "$arg" in
   --*) ;;
+  init=*)
+    eval "${arg}"
+    ;;
   *=*) ;;
   -*)
     flags="${flags}${arg#-}"
     ;;
-  'single'|'emergency') # Linux compat
-    flags="${flags}s"
+  'single')
+    single="-s"
     ;;
-  'fastboot')
-    flags="${flags}f"
+  'fastboot'|'emergency')
     ;;
   esac
 done
@@ -106,50 +110,18 @@ done
 # Check boot flags.
 case "$flags" in
 *s*)
-  rc=false                     # force single-user
-  ;;
-*f*)
-  rc="${RUNCOM}"               # fastboot
-  ;;
-*)
-  rc="${RUNCOM} autoboot"      # multi-user default
+  single="-s"                  # force single-user
   ;;
 esac
 
-# Large infinite loop.  If this script ever exits, init considers that
-# a serious bogosity and punts to a fallback single-user shell.
-# We handle here the normal transitions between single-user and multi-user.
-while : ; do
-
-  # Run the rc script.  As long as it exits nonzero, punt to single-user.
-  # After the single-user shell exits, we will start over attempting to
-  # run rc; but later invocations strip the `autoboot' argument.
-  until $rc; do
-    rc=${RUNCOM}
-
-    # Run single-user shell and repeat as long as it dies with a signal.
-    until ${SHELL} || test $? -lt 128; do
-      :
-    done
-  done
-
-  # Now we are officially ready for normal multi-user operation.
-
-  # Trap certain signals and send them on to runttys.  For this to work, we
-  # must run it asynchronously and wait for it with the `wait' built-in.
-  runttys_pid=0
-  for sig in $runttys_sigs; do
-    trap "kill -$sig \${runttys_pid}" $sig
-  done
+# Start the default pager.  It will bail if there is already one running.
+/hurd/mach-defpager
 
-  # This program reads /etc/ttys and starts the programs it says to.
-  ${RUNTTYS} &
-  runttys_pid=$!
+# This is necessary to make stat / return the correct device ids.
+# Work around a race condition (probably in the root translator).
+for i in `seq 1 100000` ; do : ; done # XXX
 
-  # Wait for runttys to die, meanwhile handling trapped signals.
-  wait
+fsysopts / --update --readonly
 
-  # Go back to the top of the infinite loop, as if booting single-user.
-  rc=false
-
-done
+# Finally, start the actual init.
+exec ${init} ${single} -a
diff --git a/devnode/devnode.c b/devnode/devnode.c
index 789bf51..f9f0359 100644
--- a/devnode/devnode.c
+++ b/devnode/devnode.c
@@ -138,27 +138,6 @@ do_mach_notify_dead_name (struct port_info *pi,
 }
 
 /* Implementation of device interface */
-kern_return_t 
-ds_xxx_device_set_status (device_t device, dev_flavor_t flavor,
-                         dev_status_t status, size_t statu_cnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_get_status (device_t device, dev_flavor_t flavor,
-                         dev_status_t status, size_t *statuscnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_set_filter (device_t device, mach_port_t rec,
-                         int pri, filter_array_t filt, size_t len)
-{
-  return D_INVALID_OPERATION;
-}
-
 kern_return_t
 ds_device_open (mach_port_t master_port, mach_port_t reply_port,
                mach_msg_type_name_t reply_portPoly,
diff --git a/doc/hurd.texi b/doc/hurd.texi
index 8fa6da7..7e7b5ee 100644
--- a/doc/hurd.texi
+++ b/doc/hurd.texi
@@ -563,10 +563,10 @@ bootstrapped by starting the GNU Mach microkernel and two 
programs:
 the root filesystem and the exec server.
 
 The @option{--multiboot-command-line} option tells the file system server that
-it is a root filesystem, which triggers it to run @command{/hurd/init} as PID
-1.  @command{/hurd/init} starts the @command{/hurd/proc} and
+it is a root filesystem, which triggers it to run @command{/hurd/startup} as 
PID
+2.  @command{/hurd/startup} starts the @command{/hurd/proc} and
 @command{/hurd/auth} servers.  After the servers are launched
address@hidden/hurd/init} starts the @command{/libexec/runsystem.sh} script to
address@hidden/hurd/startup} starts the @command{/libexec/runsystem.sh} script 
to
 finish booting.
 
 After the Hurd has been booted, other sets of core Hurd servers can be
diff --git a/eth-filter/filter.c b/eth-filter/filter.c
index 482b080..13dd03b 100644
--- a/eth-filter/filter.c
+++ b/eth-filter/filter.c
@@ -294,27 +294,6 @@ do_mach_notify_dead_name (struct port_info *pi,
 }
 
 /* Implementation of device interface */
-kern_return_t 
-ds_xxx_device_set_status (struct proxy_user *device, dev_flavor_t flavor,
-                         dev_status_t status, size_t statu_cnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_get_status (struct proxy_user *device, dev_flavor_t flavor,
-                         dev_status_t status, size_t *statuscnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_set_filter (struct proxy_user *device, mach_port_t rec,
-                         int pri, filter_array_t filt, size_t len)
-{
-  return D_INVALID_OPERATION;
-}
-
 kern_return_t
 ds_device_open (mach_port_t master_port, mach_port_t reply_port,
                mach_msg_type_name_t reply_portPoly,
diff --git a/eth-multiplexer/demuxer.c b/eth-multiplexer/demuxer.c
index 1f671b2..68bf968 100644
--- a/eth-multiplexer/demuxer.c
+++ b/eth-multiplexer/demuxer.c
@@ -1,5 +1,5 @@
 /* 
-   Copyright (C) 1996 Free Software Foundation, Inc.
+   Copyright (C) 1996, 2013 Free Software Foundation, Inc.
    Written by Michael I. Bushnell, p/BSG.
 
    This file is part of the GNU Hurd.
@@ -20,22 +20,31 @@
 
 #include <hurd/netfs.h>
 
+#include "libnetfs/io_S.h"
+#include "libnetfs/fs_S.h"
+#include "libports/notify_S.h"
+#include "libnetfs/fsys_S.h"
+#include "libports/interrupt_S.h"
+#include "libnetfs/ifsock_S.h"
+#include "device_S.h"
+
 int
 netfs_demuxer (mach_msg_header_t *inp,
               mach_msg_header_t *outp)
 {
-  int netfs_fs_server (mach_msg_header_t *, mach_msg_header_t *);
-  int netfs_io_server (mach_msg_header_t *, mach_msg_header_t *);
-  int netfs_fsys_server (mach_msg_header_t *, mach_msg_header_t *);
-  int netfs_ifsock_server (mach_msg_header_t *, mach_msg_header_t *);
-  int device_server (mach_msg_header_t *, mach_msg_header_t *);
-
-  return (netfs_io_server (inp, outp)
-          || netfs_fs_server (inp, outp)
-          || ports_notify_server (inp, outp)
-          || netfs_fsys_server (inp, outp)
-          || ports_interrupt_server (inp, outp)
-          || netfs_ifsock_server (inp, outp)
-         || device_server (inp, outp));
+  mig_routine_t routine;
+  if ((routine = netfs_io_server_routine (inp)) ||
+      (routine = netfs_fs_server_routine (inp)) ||
+      (routine = ports_notify_server_routine (inp)) ||
+      (routine = netfs_fsys_server_routine (inp)) ||
+      (routine = ports_interrupt_server_routine (inp)) ||
+      (routine = netfs_ifsock_server_routine (inp)) ||
+      (routine = device_server_routine (inp)))
+    {
+      (*routine) (inp, outp);
+      return TRUE;
+    }
+  else
+    return FALSE;
 }
 
diff --git a/eth-multiplexer/device.h b/eth-multiplexer/device.h
deleted file mode 100644
index db0798d..0000000
--- a/eth-multiplexer/device.h
+++ /dev/null
@@ -1,336 +0,0 @@
-#ifndef        _device_user_
-#define        _device_user_
-
-/* Module device */
-
-#include <mach/kern_return.h>
-#include <mach/port.h>
-#include <mach/message.h>
-
-#include <mach/std_types.h>
-#include <mach/mach_types.h>
-#include <device/device_types.h>
-#include <device/net_status.h>
-
-/* Routine device_open */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_open
-#if    defined(LINTLIBRARY)
-    (master_port, mode, name, device)
-       mach_port_t master_port;
-       dev_mode_t mode;
-       dev_name_t name;
-       mach_port_t *device;
-{ return device_open(master_port, mode, name, device); }
-#else
-(
-       mach_port_t master_port,
-       dev_mode_t mode,
-       dev_name_t name,
-       mach_port_t *device
-);
-#endif
-
-/* Routine device_close */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_close
-#if    defined(LINTLIBRARY)
-    (device)
-       mach_port_t device;
-{ return device_close(device); }
-#else
-(
-       mach_port_t device
-);
-#endif
-
-/* Routine device_write */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_write
-#if    defined(LINTLIBRARY)
-    (device, mode, recnum, data, dataCnt, bytes_written)
-       mach_port_t device;
-       dev_mode_t mode;
-       recnum_t recnum;
-       io_buf_ptr_t data;
-       mach_msg_type_number_t dataCnt;
-       int *bytes_written;
-{ return device_write(device, mode, recnum, data, dataCnt, bytes_written); }
-#else
-(
-       mach_port_t device,
-       dev_mode_t mode,
-       recnum_t recnum,
-       io_buf_ptr_t data,
-       mach_msg_type_number_t dataCnt,
-       int *bytes_written
-);
-#endif
-
-/* Routine device_write_inband */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_write_inband
-#if    defined(LINTLIBRARY)
-    (device, mode, recnum, data, dataCnt, bytes_written)
-       mach_port_t device;
-       dev_mode_t mode;
-       recnum_t recnum;
-       io_buf_ptr_inband_t data;
-       mach_msg_type_number_t dataCnt;
-       int *bytes_written;
-{ return device_write_inband(device, mode, recnum, data, dataCnt, 
bytes_written); }
-#else
-(
-       mach_port_t device,
-       dev_mode_t mode,
-       recnum_t recnum,
-       io_buf_ptr_inband_t data,
-       mach_msg_type_number_t dataCnt,
-       int *bytes_written
-);
-#endif
-
-/* Routine device_read */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_read
-#if    defined(LINTLIBRARY)
-    (device, mode, recnum, bytes_wanted, data, dataCnt)
-       mach_port_t device;
-       dev_mode_t mode;
-       recnum_t recnum;
-       int bytes_wanted;
-       io_buf_ptr_t *data;
-       mach_msg_type_number_t *dataCnt;
-{ return device_read(device, mode, recnum, bytes_wanted, data, dataCnt); }
-#else
-(
-       mach_port_t device,
-       dev_mode_t mode,
-       recnum_t recnum,
-       int bytes_wanted,
-       io_buf_ptr_t *data,
-       mach_msg_type_number_t *dataCnt
-);
-#endif
-
-/* Routine device_read_inband */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_read_inband
-#if    defined(LINTLIBRARY)
-    (device, mode, recnum, bytes_wanted, data, dataCnt)
-       mach_port_t device;
-       dev_mode_t mode;
-       recnum_t recnum;
-       int bytes_wanted;
-       io_buf_ptr_inband_t data;
-       mach_msg_type_number_t *dataCnt;
-{ return device_read_inband(device, mode, recnum, bytes_wanted, data, 
dataCnt); }
-#else
-(
-       mach_port_t device,
-       dev_mode_t mode,
-       recnum_t recnum,
-       int bytes_wanted,
-       io_buf_ptr_inband_t data,
-       mach_msg_type_number_t *dataCnt
-);
-#endif
-
-/* Routine xxx_device_set_status */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t xxx_device_set_status
-#if    defined(LINTLIBRARY)
-    (device, flavor, status, statusCnt)
-       mach_port_t device;
-       dev_flavor_t flavor;
-       dev_status_t status;
-       mach_msg_type_number_t statusCnt;
-{ return xxx_device_set_status(device, flavor, status, statusCnt); }
-#else
-(
-       mach_port_t device,
-       dev_flavor_t flavor,
-       dev_status_t status,
-       mach_msg_type_number_t statusCnt
-);
-#endif
-
-/* Routine xxx_device_get_status */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t xxx_device_get_status
-#if    defined(LINTLIBRARY)
-    (device, flavor, status, statusCnt)
-       mach_port_t device;
-       dev_flavor_t flavor;
-       dev_status_t status;
-       mach_msg_type_number_t *statusCnt;
-{ return xxx_device_get_status(device, flavor, status, statusCnt); }
-#else
-(
-       mach_port_t device,
-       dev_flavor_t flavor,
-       dev_status_t status,
-       mach_msg_type_number_t *statusCnt
-);
-#endif
-
-/* Routine xxx_device_set_filter */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t xxx_device_set_filter
-#if    defined(LINTLIBRARY)
-    (device, receive_port, receive_portPoly, priority, filter, filterCnt)
-       mach_port_t device;
-       mach_port_t receive_port;
-       mach_msg_type_name_t receive_portPoly;
-       int priority;
-       filter_array_t filter;
-       mach_msg_type_number_t filterCnt;
-{ return xxx_device_set_filter(device, receive_port, receive_portPoly, 
priority, filter, filterCnt); }
-#else
-(
-       mach_port_t device,
-       mach_port_t receive_port,
-       mach_msg_type_name_t receive_portPoly,
-       int priority,
-       filter_array_t filter,
-       mach_msg_type_number_t filterCnt
-);
-#endif
-
-/* Routine device_map */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_map
-#if    defined(LINTLIBRARY)
-    (device, prot, offset, size, pager, unmap)
-       mach_port_t device;
-       vm_prot_t prot;
-       vm_offset_t offset;
-       vm_size_t size;
-       mach_port_t *pager;
-       int unmap;
-{ return device_map(device, prot, offset, size, pager, unmap); }
-#else
-(
-       mach_port_t device,
-       vm_prot_t prot,
-       vm_offset_t offset,
-       vm_size_t size,
-       mach_port_t *pager,
-       int unmap
-);
-#endif
-
-/* Routine device_set_status */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_set_status
-#if    defined(LINTLIBRARY)
-    (device, flavor, status, statusCnt)
-       mach_port_t device;
-       dev_flavor_t flavor;
-       dev_status_t status;
-       mach_msg_type_number_t statusCnt;
-{ return device_set_status(device, flavor, status, statusCnt); }
-#else
-(
-       mach_port_t device,
-       dev_flavor_t flavor,
-       dev_status_t status,
-       mach_msg_type_number_t statusCnt
-);
-#endif
-
-/* Routine device_get_status */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_get_status
-#if    defined(LINTLIBRARY)
-    (device, flavor, status, statusCnt)
-       mach_port_t device;
-       dev_flavor_t flavor;
-       dev_status_t status;
-       mach_msg_type_number_t *statusCnt;
-{ return device_get_status(device, flavor, status, statusCnt); }
-#else
-(
-       mach_port_t device,
-       dev_flavor_t flavor,
-       dev_status_t status,
-       mach_msg_type_number_t *statusCnt
-);
-#endif
-
-/* Routine device_set_filter */
-#ifdef mig_external
-mig_external
-#else
-extern
-#endif
-kern_return_t device_set_filter
-#if    defined(LINTLIBRARY)
-    (device, receive_port, receive_portPoly, priority, filter, filterCnt)
-       mach_port_t device;
-       mach_port_t receive_port;
-       mach_msg_type_name_t receive_portPoly;
-       int priority;
-       filter_array_t filter;
-       mach_msg_type_number_t filterCnt;
-{ return device_set_filter(device, receive_port, receive_portPoly, priority, 
filter, filterCnt); }
-#else
-(
-       mach_port_t device,
-       mach_port_t receive_port,
-       mach_msg_type_name_t receive_portPoly,
-       int priority,
-       filter_array_t filter,
-       mach_msg_type_number_t filterCnt
-);
-#endif
-
-#endif /* not defined(_device_user_) */
diff --git a/eth-multiplexer/device_impl.c b/eth-multiplexer/device_impl.c
index 35a4da4..7d82b8d 100644
--- a/eth-multiplexer/device_impl.c
+++ b/eth-multiplexer/device_impl.c
@@ -39,32 +39,6 @@ extern struct port_class *other_portclass;
 extern struct port_info *notify_pi;
 
 /* Implementation of device interface */
-kern_return_t
-ds_xxx_device_set_status (struct vether_device *vdev, dev_flavor_t flavor,
-                         dev_status_t status, size_t statu_cnt)
-{
-  if (vdev == NULL)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_get_status (struct vether_device *vdev, dev_flavor_t flavor,
-                         dev_status_t status, size_t *statuscnt)
-{
-  if (vdev == NULL)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_set_filter (struct vether_device *vdev, mach_port_t rec,
-                         int pri, filter_array_t filt, size_t len)
-{
-  if (vdev == NULL)
-    return D_NO_SUCH_DEVICE;
-  return D_INVALID_OPERATION;
-}
 
 /*
  * This function is currently running in the multithread environment,
diff --git a/eth-multiplexer/ethernet.c b/eth-multiplexer/ethernet.c
index 32c5589..886f5df 100644
--- a/eth-multiplexer/ethernet.c
+++ b/eth-multiplexer/ethernet.c
@@ -76,12 +76,12 @@ int set_promisc (char *dev_name, mach_port_t ether_port, 
int is_promisc)
 #ifndef NET_FLAGS
 #define NET_FLAGS (('n'<<16) + 4)
 #endif
-  short flags;
+  int flags;
   int ret;
   size_t count;
 
   debug ("set_promisc is called, is_promisc: %d\n", is_promisc);
-  count = sizeof (flags);
+  count = 1;
   ret = device_get_status (ether_port, NET_FLAGS, (dev_status_t) &flags, 
                            &count);
   if (ret) 
@@ -93,8 +93,7 @@ int set_promisc (char *dev_name, mach_port_t ether_port, int 
is_promisc)
     flags |= IFF_PROMISC;
   else
     flags &= ~IFF_PROMISC;
-  ret = device_set_status(ether_port, NET_FLAGS, (dev_status_t) &flags,
-                          sizeof (flags));
+  ret = device_set_status(ether_port, NET_FLAGS, (dev_status_t) &flags, 1);
   if (ret) 
     {
       error (0, ret, "device_set_status");
diff --git a/exec/execmutations.h b/exec/execmutations.h
index 2acca7a..0b5b8bb 100644
--- a/exec/execmutations.h
+++ b/exec/execmutations.h
@@ -1,6 +1,7 @@
 /* CPP definitions for MiG processing of exec.defs for exec server.  */
 
 #define FILE_INTRAN trivfs_protid_t trivfs_begin_using_protid (file_t)
+#define FILE_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload
 #define FILE_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
 
 #define EXEC_IMPORTS                                   \
@@ -9,6 +10,8 @@
 
 #define EXEC_STARTUP_INTRAN                             \
   bootinfo_t begin_using_bootinfo_port (exec_startup_t)
+#define EXEC_STARTUP_INTRAN_PAYLOAD                     \
+  bootinfo_t begin_using_bootinfo_payload
 #define EXEC_STARTUP_DESTRUCTOR                         \
   end_using_bootinfo (bootinfo_t)
 #define EXEC_STARTUP_IMPORTS                            \
diff --git a/exec/main.c b/exec/main.c
index 784000b..c86c000 100644
--- a/exec/main.c
+++ b/exec/main.c
@@ -331,8 +331,15 @@ S_exec_init (struct trivfs_protid *protid,
 
   proc_register_version (procserver, host_priv, "exec", "", HURD_VERSION);
 
-  err = proc_getmsgport (procserver, HURD_PID_STARTUP, &startup);
-  assert_perror (err);
+  startup = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+  if (startup == MACH_PORT_NULL)
+    {
+      error (0, errno, "%s", _SERVERS_STARTUP);
+
+      /* Fall back to abusing the message port lookup.  */
+      err = proc_getmsgport (procserver, HURD_PID_STARTUP, &startup);
+      assert_perror (err);
+    }
   mach_port_deallocate (mach_task_self (), procserver);
 
   /* Call startup_essential task last; init assumes we are ready to
diff --git a/exec/mig-decls.h b/exec/mig-decls.h
index 0437414..cf3e17d 100644
--- a/exec/mig-decls.h
+++ b/exec/mig-decls.h
@@ -30,6 +30,12 @@ begin_using_bootinfo_port (mach_port_t port)
     return ports_lookup_port (port_bucket, port, execboot_portclass);
 }
 
+static inline struct bootinfo * __attribute__ ((unused))
+begin_using_bootinfo_payload (unsigned long payload)
+{
+    return ports_lookup_payload (port_bucket, payload, execboot_portclass);
+}
+
 static inline void __attribute__ ((unused))
 end_using_bootinfo (struct bootinfo *b)
 {
diff --git a/hurd/default_pager.defs b/hurd/default_pager.defs
index 1a4290d..a97bff2 100644
--- a/hurd/default_pager.defs
+++ b/hurd/default_pager.defs
@@ -29,6 +29,7 @@
 
 subsystem default_pager 2275;
 
+#include <hurd/hurd_types.defs>        /* For `MACH_PAYLOAD_TO_PORT'.  */
 #include <mach/std_types.defs>
 #include <mach/mach_types.defs>
 #include <mach/default_pager_types.defs>
diff --git a/hurd/hurd_types.defs b/hurd/hurd_types.defs
index 129a68c..57af6dc 100644
--- a/hurd/hurd_types.defs
+++ b/hurd/hurd_types.defs
@@ -18,13 +18,67 @@ along with the GNU Hurd; see the file COPYING.  If not, 
write to
 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
+/* The Hurd uses protected payloads to quickly look up the object
+   receiving a message.  Looking up objects is optimized at the cost
+   of having to translate payloads back to port names if the server
+   function expect a port name rather than an object.
+
+   Support for this is implemented in libports.  Almost all of Hurd's
+   servers use libports.  For servers using libports, the optimized
+   lookup is completely transparent.
+
+   Servers not using libports are not using protected payloads
+   automatically.  Define HURD_DEFAULT_PAYLOAD_TO_PORT to 1 (1 like
+   the identity function) for programs not using libports to avoid
+   injecting the default payload-to-port translation function which is
+   in libports.  If you want to use protected payloads without
+   libports, you can use HURD_DEFAULT_PAYLOAD_TO_PORT to inject a
+   custom translation function.  */
+
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+#if HURD_DEFAULT_PAYLOAD_TO_PORT
+/* Any non-numeric value will fail this test.  If 1 (or any number) is
+   given, do not inject the default translator function.  */
+#undef HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
+#else
+   import <hurd/ports.h>;
+#define HURD_DEFAULT_PAYLOAD_TO_PORT ports_payload_get_name
+#endif
+
+/* Override the mach_port_t.  Use the default payload to port
+   translation function to convert payloads back to port names for
+   this type.  */
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+#define MACH_PAYLOAD_TO_PORT   HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
+
 #include <mach/std_types.defs>
 #include <mach/mach_types.defs>
 #include <device/device_types.defs>
+
+/* The Hurd types.  You can inject translation functions for type X
+   using the X_INTRAN, X_INTRAN_PAYLOAD, X_OUTTRAN, and X_DESTRUCTOR.
+
+   If you define X_INTRAN and your server is using libports, you also
+   have to define X_INTRAN_PAYLOAD.
+
+   If you do not use libports, and do not want to use the protected
+   payload mechanism, but you do want to use X_INTRAN, you must
+   provide a X_INTRAN_PAYLOAD that either ignores the message by
+   returning NULL, or indicates an error condition in some appropriate
+   way.  If you do want to use the protected payload mechanism, make
+   sure you also define an appropriate HURD_DEFAULT_PAYLOAD_TO_PORT
+   translation function.  */
 
 type file_t = mach_port_copy_send_t
 #ifdef FILE_INTRAN
 intran: FILE_INTRAN
+intranpayload: FILE_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: file_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef FILE_OUTTRAN
 outtran: FILE_OUTTRAN
@@ -37,6 +91,11 @@ destructor: FILE_DESTRUCTOR
 type fsys_t = mach_port_copy_send_t
 #ifdef FSYS_INTRAN
 intran: FSYS_INTRAN
+intranpayload: FSYS_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: fsys_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef FSYS_OUTTRAN
 outtran: FSYS_OUTTRAN
@@ -50,6 +109,11 @@ destructor: FSYS_DESTRUCTOR
 type io_t = mach_port_copy_send_t
 #ifdef IO_INTRAN
 intran: IO_INTRAN
+intranpayload: IO_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: io_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef IO_OUTTRAN
 outtran: IO_OUTTRAN
@@ -62,6 +126,11 @@ destructor: IO_DESTRUCTOR
 type process_t = mach_port_copy_send_t
 #ifdef PROCESS_INTRAN
 intran: PROCESS_INTRAN
+intranpayload: PROCESS_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: process_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef PROCESS_OUTTRAN
 outtran: PROCESS_OUTTRAN
@@ -74,6 +143,11 @@ destructor: PROCESS_DESTRUCTOR
 type auth_t = mach_port_copy_send_t
 #ifdef AUTH_INTRAN
 intran: AUTH_INTRAN
+intranpayload: AUTH_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: auth_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef AUTH_OUTTRAN
 outtran: AUTH_OUTTRAN
@@ -86,6 +160,11 @@ destructor: AUTH_DESTRUCTOR
 type socket_t = mach_port_copy_send_t
 #ifdef SOCKET_INTRAN
 intran: SOCKET_INTRAN
+intranpayload: SOCKET_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: socket_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef SOCKET_OUTTRAN
 outtran: SOCKET_OUTTRAN
@@ -99,6 +178,11 @@ destructor: SOCKET_DESTRUCTOR
 type pf_t = mach_port_copy_send_t
 #ifdef PF_INTRAN
 intran: PF_INTRAN
+intranpayload: PF_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: pf_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef PF_OUTTRAN
 outtran: PF_OUTTRAN
@@ -111,6 +195,11 @@ destructor: PF_DESTRUCTOR
 type addr_port_t = mach_port_copy_send_t
 #ifdef ADDRPORT_INTRAN
 intran: ADDRPORT_INTRAN
+intranpayload: ADDRPORT_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: addr_port_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef ADDRPORT_OUTTRAN
 outtran: ADDRPORT_OUTTRAN
@@ -123,6 +212,11 @@ destructor: ADDRPORT_DESTRUCTOR
 type term_t = mach_port_copy_send_t
 #ifdef TERM_INTRAN
 intran: TERM_INTRAN
+intranpayload: TERM_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: term_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef TERM_OUTTRAN
 outtran: TERM_OUTTRAN
@@ -135,6 +229,11 @@ destructor: TERM_DESTRUCTOR
 type startup_t = mach_port_copy_send_t
 #ifdef STARTUP_INTRAN
 intran: STARTUP_INTRAN
+intranpayload: STARTUP_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: startup_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef STARTUP_OUTTRAN
 outtran: STARTUP_OUTTRAN
@@ -147,6 +246,11 @@ destructor: STARTUP_DESTRUCTOR
 type fs_notify_t = mach_port_copy_send_t
 #ifdef FS_NOTIFY_INTRAN
 intran: FS_NOTIFY_INTRAN
+intranpayload: FS_NOTIFY_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: fs_notify_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef FS_NOTIFY_OUTTRAN
 outtran: FS_NOTIFY_OUTTRAN
@@ -159,6 +263,11 @@ destructor: FS_NOTIFY_DESTRUCTOR
 type exec_startup_t = mach_port_copy_send_t
 #ifdef EXEC_STARTUP_INTRAN
 intran: EXEC_STARTUP_INTRAN
+intranpayload: EXEC_STARTUP_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: exec_startup_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef EXEC_STARTUP_OUTTRAN
 outtran: EXEC_STARTUP_OUTTRAN
@@ -171,6 +280,11 @@ destructor: EXEC_STARTUP_DESTRUCTOR
 type interrupt_t = mach_port_copy_send_t
 #ifdef INTERRUPT_INTRAN
 intran: INTERRUPT_INTRAN
+intranpayload: INTERRUPT_INTRAN_PAYLOAD
+#else
+#ifdef HURD_DEFAULT_PAYLOAD_TO_PORT
+intranpayload: exec_startup_t HURD_DEFAULT_PAYLOAD_TO_PORT
+#endif
 #endif
 #ifdef INTERRUPT_OUTTRAN
 outtran: INTERRUPT_OUTTRAN
@@ -184,7 +298,11 @@ destructor: INTERRUPT_DESTRUCTOR
 type proccoll_t = mach_port_copy_send_t;
 
 type sreply_port_t = MACH_MSG_TYPE_MAKE_SEND_ONCE | polymorphic
-       ctype: mach_port_t;
+       ctype: mach_port_t
+#ifdef MACH_PAYLOAD_TO_PORT
+intranpayload: mach_port_t MACH_PAYLOAD_TO_PORT
+#endif /* MACH_PAYLOAD_TO_PORT */
+;
 
 /* These macros are used in some .defs files so that every routine has a
    server reply port argument #ifdef REPLY_PORTS.  */
diff --git a/hurd/paths.h b/hurd/paths.h
index 92875b2..a13ba9b 100644
--- a/hurd/paths.h
+++ b/hurd/paths.h
@@ -26,6 +26,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 
02139, USA.  */
 #define        _SERVERS                "/servers/"
 #define        _SERVERS_CRASH          _SERVERS "crash"
 #define        _SERVERS_EXEC           _SERVERS "exec"
+#define _SERVERS_STARTUP       _SERVERS "startup"
 #define _SERVERS_PROC          _SERVERS "proc"
 #define _SERVERS_PASSWORD      _SERVERS "password"
 #define _SERVERS_DEFPAGER      _SERVERS "default-pager"
@@ -39,7 +40,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 
02139, USA.  */
    the canonical pathname being /hurd/foo.  */
 
 #define        _HURD           "/hurd/"
-#define        _HURD_INIT      _HURD "init"
+#define        _HURD_STARTUP   _HURD "startup"
 #define _HURD_PROC     _HURD "proc"
 #define _HURD_AUTH     _HURD "auth"
 
diff --git a/hurd/process.defs b/hurd/process.defs
index bf90556..498faba 100644
--- a/hurd/process.defs
+++ b/hurd/process.defs
@@ -373,7 +373,11 @@ routine proc_getnports (
 
 /*** Routines related to early server bootstrapping ***/
 
-skip;  /* Reserved for proc_set_init_task */
+/* Set the task of process HURD_PID_INIT. Only the startup process
+   HURD_PID_STARTUP may use this interface.  */
+routine proc_set_init_task (
+       process: process_t;
+       task: task_t);
 
 /* Inform the process server that the process is important.  */
 routine proc_mark_important (
diff --git a/hurd/process_reply.defs b/hurd/process_reply.defs
index ed46d55..80454a6 100644
--- a/hurd/process_reply.defs
+++ b/hurd/process_reply.defs
@@ -177,7 +177,7 @@ simpleroutine proc_getnports_reply (
 
 /*** Routines related to early server bootstrapping ***/
 
-skip;  /* Reserved for proc_set_init_task */
+skip; /* proc_set_init_task */
 skip; /* proc_mark_important */
 
 simpleroutine proc_is_important_reply (
diff --git a/hurd/process_request.defs b/hurd/process_request.defs
index 38e7146..7565f03 100644
--- a/hurd/process_request.defs
+++ b/hurd/process_request.defs
@@ -374,7 +374,12 @@ simpleroutine proc_getnports_request (
 
 /*** Routines related to early server bootstrapping ***/
 
-skip;  /* Reserved for proc_set_init_task */
+/* Set the task of process HURD_PID_INIT. Only the startup process
+   HURD_PID_STARTUP may use this interface.  */
+simpleroutine proc_set_init_task_request (
+       process: process_t;
+       ureplyport reply: reply_port_t;
+       task: task_t);
 
 /* Inform the process server that the process is important.  */
 simpleroutine proc_mark_important_request (
diff --git a/hurd/term.defs b/hurd/term.defs
index 45d825d..29b94ef 100644
--- a/hurd/term.defs
+++ b/hurd/term.defs
@@ -33,6 +33,9 @@ type ctty_t = mach_port_copy_send_t
 #ifdef CTTY_INTRAN
 intran: CTTY_INTRAN
 #endif
+#ifdef CTTY_INTRAN_PAYLOAD
+intranpayload: CTTY_INTRAN_PAYLOAD
+#endif
 #ifdef CTTY_OUTTRAN
 outtran: CTTY_OUTTRAN
 #endif
diff --git a/include/Makefile b/include/Makefile
index 4de165d..b8773fe 100644
--- a/include/Makefile
+++ b/include/Makefile
@@ -22,7 +22,7 @@
 dir := include
 makemode := misc
 
-installhdrs := sys/procfs.h refcount.h
+installhdrs := sys/procfs.h
 
 include ../Makeconf
 
diff --git a/include/pids.h b/include/pids.h
index 22415f4..dff7635 100644
--- a/include/pids.h
+++ b/include/pids.h
@@ -22,8 +22,9 @@
 #ifndef _HURD_PROCESSES_H
 #define _HURD_PROCESSES_H
 
-#define HURD_PID_STARTUP       1
-#define HURD_PID_KERNEL                2
-#define HURD_PID_PROC          3
+#define HURD_PID_INIT          1
+#define HURD_PID_STARTUP       2
+#define HURD_PID_KERNEL                3
+#define HURD_PID_PROC          4
 
 #endif  /* _HURD_PROCESSES_H */
diff --git a/init/Makefile b/init/Makefile
index ffb82ff..07b8026 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -1,5 +1,5 @@
 #
-#   Copyright (C) 1994,95,96,99,2001 Free Software Foundation, Inc.
+#   Copyright (C) 2013 Free Software Foundation, Inc.
 #
 #   This program is free software; you can redistribute it and/or
 #   modify it under the terms of the GNU General Public License as
@@ -12,20 +12,13 @@
 #   General Public License for more details.
 #
 #   You should have received a copy of the GNU General Public License
-#   along with this program; if not, write to the Free Software
-#   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+#   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 dir := init
 makemode := server
 
-SRCS = init.c stubs.c
-OBJS = $(SRCS:.c=.o) \
-       startupServer.o notifyServer.o startup_replyUser.o msgServer.o \
-       startup_notifyUser.o
+SRCS = init.c
+OBJS = $(SRCS:.c=.o)
 target = init
-HURDLIBS = shouldbeinlibc
 
 include ../Makeconf
-
-mung_msg_S.h: msg_S.h
-       sed 's/msg_server/mung_msg_server/' < $< > $@
diff --git a/init/init.c b/init/init.c
index b7b40bd..b3d3301 100644
--- a/init/init.c
+++ b/init/init.c
@@ -1,7 +1,6 @@
-/* Start and maintain hurd core servers and system run state
+/* A minimalist init for the Hurd
 
-   Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
-     2005, 2008, 2013 Free Software Foundation, Inc.
+   Copyright (C) 2013,14 Free Software Foundation, Inc.
    This file is part of the GNU Hurd.
 
    The GNU Hurd is free software; you can redistribute it and/or modify
@@ -15,1579 +14,142 @@
    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.  */
+   along with the Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Written by Michael I. Bushnell and Roland McGrath.  */
-
-/* This is probably more include files than I've ever seen before for
-   one file. */
+#include <argp.h>
+#include <error.h>
 #include <hurd.h>
-#include <hurd/fs.h>
-#include <hurd/fsys.h>
-#include <device/device.h>
+#include <signal.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 <hurd/fshelp.h>
-#include <paths.h>
-#include <sys/mman.h>
-#include <hurd/msg_server.h>
-#include <wire.h>
+#include <sys/types.h>
 #include <sys/wait.h>
-#include <error.h>
-#include <hurd/msg_reply.h>
-#include <argz.h>
-#include <maptime.h>
+#include <unistd.h>
 #include <version.h>
-#include <argp.h>
-#include <pids.h>
-
-#include "startup_notify_U.h"
-#include "startup_reply_U.h"
-#include "startup_S.h"
-#include "notify_S.h"
-#include "mung_msg_S.h"
-
-/* host_reboot flags for when we crash.  */
-static int crash_flags = RB_AUTOBOOT;
-
-#define BOOT(flags)    ((flags & RB_HALT) ? "halt" : "reboot")
-
 
 const char *argp_program_version = STANDARD_HURD_VERSION (init);
-
+static pid_t child_pid;
+static int single;
+
 static struct argp_option
 options[] =
 {
-  {"single-user", 's', 0, 0, "Startup system in single-user mode"},
-  {"query",       'q', 0, 0, "Ask for the names of servers to start"},
-  {"init-name",   'n', 0, 0 },
-  {"crash-debug",  'H', 0, 0, "On system crash, go to kernel debugger"},
-  {"debug",       'd', 0, 0 },
-  {"fake-boot",   'f', 0, 0, "This hurd hasn't been booted on the raw 
machine"},
-  {0,             'x', 0, OPTION_HIDDEN},
+  /* XXX: Currently, -s does nothing.  */
+  {"single-user", 's', NULL, 0, "Startup system in single-user mode", 0},
+  {NULL, 'a', NULL, 0, "Ignored for compatibility with sysvinit", 0},
   {0}
 };
 
-static char doc[] = "Start and maintain hurd core servers and system run 
state";
-
-static int booted;             /* Set when the core servers are up.  */
-
-/* This structure keeps track of each notified task.  */
-struct ntfy_task
-  {
-    mach_port_t notify_port;
-    struct ntfy_task *next;
-    char *name;
-  };
-
-/* 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.  */
-static struct ess_task *ess_tasks;
-static struct ntfy_task *ntfy_tasks;
-
-
-/* Our receive right */
-static mach_port_t startup;
-
-/* Ports to the kernel */
-static mach_port_t host_priv, device_master;
-
-/* Args to bootstrap, expressed as flags */
-static int bootstrap_args = 0;
-
-/* Stored information for returning proc and auth startup messages. */
-static mach_port_t procreply, authreply;
-static mach_msg_type_name_t procreplytype, authreplytype;
-
-/* Our ports to auth and proc. */
-static mach_port_t authserver;
-static mach_port_t procserver;
-
-/* Our bootstrap port, on which we call fsys_getpriv and fsys_init. */
-static mach_port_t bootport;
-
-/* Set iff we are a `fake' bootstrap. */
-static int fakeboot;
-
-/* The tasks of auth and proc and the bootstrap filesystem. */
-static task_t authtask, proctask, fstask;
-
-static mach_port_t default_ports[INIT_PORT_MAX];
-static mach_port_t default_dtable[3];
-static int default_ints[INIT_INT_MAX];
-
-static char **global_argv;
-static char *startup_envz;
-static size_t startup_envz_len;
-
-void launch_system (void);
-void process_signal (int signo);
-
-/** Utility functions **/
-
-/* 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;
-}
-
-
-/** System shutdown **/
-
-/* Reboot the microkernel.  */
-void
-reboot_mach (int flags)
-{
-  if (fakeboot)
-    {
-      printf ("%s: Would %s Mach with flags %#x\n",
-             program_invocation_short_name, BOOT (flags), flags);
-      fflush (stdout);
-      exit (1);
-    }
-  else
-    {
-      error_t err;
-      printf ("%s: %sing Mach (flags %#x)...\n",
-             program_invocation_short_name, BOOT (flags), flags);
-      fflush (stdout);
-      sleep (5);
-      while ((err = host_reboot (host_priv, flags)))
-       error (0, err, "reboot");
-      for (;;);
-    }
-}
-
-/* Reboot the microkernel, specifying that this is a crash. */
-void
-crash_mach (void)
-{
-  reboot_mach (crash_flags);
-}
-
-/* Notify all tasks that have requested shutdown notifications */
-void
-notify_shutdown (const char *msg)
-{
-  struct ntfy_task *n;
-
-  for (n = ntfy_tasks; n != NULL; n = n->next)
-    {
-      error_t err;
-      printf ("%s: notifying %s of %s...",
-             program_invocation_short_name, n->name, msg);
-      fflush (stdout);
-      err = startup_dosync (n->notify_port, 60000); /* 1 minute to reply */
-      if (err == MACH_SEND_INVALID_DEST)
-       puts ("(no longer present)");
-      else if (err)
-       puts (strerror (err));
-      else
-       puts ("done");
-      fflush (stdout);
-    }
-}
-
-/* Reboot the Hurd. */
-void
-reboot_system (int flags)
-{
-  notify_shutdown ("shutdown");
-
-  if (fakeboot)
-    {
-      pid_t *pp;
-      size_t 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. */
-         error (0, 0, "Can't simulate crash; proc has died");
-         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)
-           {
-             error (0, err, "Getting task for pid %d", pp[ind]);
-             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;
-             size_t pisize = 0;
-             char *noise;
-             size_t noise_len = 0;
-             int flags;
-             err = proc_getprocinfo (procserver, pp[ind], &flags,
-                                     (int **)&pi, &pisize,
-                                     &noise, &noise_len);
-             if (err == MACH_SEND_INVALID_DEST)
-               goto procbad;
-             if (err)
-               {
-                 error (0, err, "Getting procinfo for pid %d", pp[ind]);
-                 continue;
-               }
-             if (!(pi->state & PI_NOPARENT))
-               {
-                 printf ("%s: Killing pid %d\n",
-                         program_invocation_short_name, pp[ind]);
-                 fflush (stdout);
-                 task_terminate (task);
-               }
-             if (noise_len > 0)
-               munmap (noise, noise_len);
-           }
-       }
-      printf ("%s: Killing proc server\n", program_invocation_short_name);
-      fflush (stdout);
-      task_terminate (proctask);
-      printf ("%s: Exiting", program_invocation_short_name);
-      fflush (stdout);
-    }
-  reboot_mach (flags);
-}
-
-/* Reboot the Hurd, specifying that this is a crash. */
-void
-crash_system (void)
-{
-  reboot_system (crash_flags);
-}
-
-
+static char doc[] = "A minimalist init for the Hurd";
 
-/* Request a dead-name notification sent to our port.  */
-static void
-request_dead_name (mach_port_t name)
-{
-  mach_port_t prev;
-  mach_port_request_notification (mach_task_self (), name,
-                                 MACH_NOTIFY_DEAD_NAME, 1, startup,
-                                 MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev);
-  if (prev != MACH_PORT_NULL)
-    mach_port_deallocate (mach_task_self (), prev);
-}
-
-/* Record an essential task in the list.  */
 static error_t
-record_essential_task (const char *name, task_t task)
-{
-  struct ess_task *et;
-  /* 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.  */
-  request_dead_name (task);
-
-#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
-
-  return 0;
-}
-
-
-/** Starting programs **/
-
-/* Run SERVER, giving it INIT_PORT_MAX initial ports from PORTS.
-   Set TASK to be the task port of the new image. */
-void
-run (const char *server, mach_port_t *ports, task_t *task)
-{
-  char buf[BUFSIZ];
-  const 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;
-      error_t err;
-
-      file = file_name_lookup (prog, O_EXEC, 0);
-      if (file == MACH_PORT_NULL)
-       error (0, errno, "%s", prog);
-      else
-       {
-         task_create (mach_task_self (),
-#ifdef KERN_INVALID_LEDGER
-                      NULL, 0, /* OSF Mach */
-#endif
-                      0, task);
-         if (bootstrap_args & RB_KDB)
-           {
-             printf ("Pausing for %s\n", prog);
-             getchar ();
-           }
-         err = file_exec (file, *task, 0,
-                          (char *)prog, strlen (prog) + 1, /* Args.  */
-                          startup_envz, startup_envz_len,
-                          default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
-                          ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
-                          default_ints, INIT_INT_MAX,
-                          NULL, 0, NULL, 0);
-         if (!err)
-           break;
-
-         error (0, err, "%s", 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
-
-  /* Dead-name notification on the task port will tell us when it dies,
-     so we can crash if we don't make it to a fully bootstrapped Hurd.  */
-  request_dead_name (*task);
-}
-
-/* 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.  If SETSID is set, put it in a new session.  Return
-   0 if the task was not created successfully. */
-pid_t
-run_for_real (char *filename, char *args, int arglen, mach_port_t ctty,
-             int setsid)
-{
-  file_t file;
-  error_t err;
-  task_t task;
-  char *progname;
-  int pid;
-
-#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 == MACH_PORT_NULL)
-       error (0, errno, "%s", filename);
-    }
-  while (file == MACH_PORT_NULL);
-#else
-  file = file_name_lookup (filename, O_EXEC, 0);
-  if (file == MACH_PORT_NULL)
-    {
-      error (0, errno, "%s", filename);
-      return 0;
-    }
-#endif
-
-  task_create (mach_task_self (),
-#ifdef KERN_INVALID_LEDGER
-              NULL, 0, /* OSF Mach */
-#endif
-              0, &task);
-  proc_child (procserver, task);
-  proc_task2pid (procserver, task, &pid);
-  proc_task2proc (procserver, task, &default_ports[INIT_PORT_PROC]);
-  proc_mark_exec (default_ports[INIT_PORT_PROC]);
-  if (setsid)
-    proc_setsid (default_ports[INIT_PORT_PROC]);
-  if (ctty != MACH_PORT_NULL)
-    {
-      term_getctty (ctty, &default_ports[INIT_PORT_CTTYID]);
-      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,
-                  startup_envz, startup_envz_len,
-                  default_dtable, MACH_MSG_TYPE_COPY_SEND, 3,
-                  default_ports, MACH_MSG_TYPE_COPY_SEND,
-                  INIT_PORT_MAX,
-                  default_ints, INIT_INT_MAX,
-                  NULL, 0, NULL, 0);
-  mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
-  mach_port_deallocate (mach_task_self (), task);
-  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);
-  if (err)
-    {
-      error (0, err, "Cannot execute %s", filename);
-      return 0;
-    }
-  return pid;
-}
-
-
-/** Main program and setup **/
-
-static int
-demuxer (mach_msg_header_t *inp,
-        mach_msg_header_t *outp)
-{
-  extern int notify_server (), startup_server (), msg_server ();
-
-  return (notify_server (inp, outp) ||
-         msg_server (inp, outp) ||
-         startup_server (inp, outp));
-}
-
-static int
 parse_opt (int key, char *arg, struct argp_state *state)
 {
   switch (key)
     {
-    case 'q': bootstrap_args |= RB_ASKNAME; break;
-    case 's': bootstrap_args |= RB_SINGLE; break;
-    case 'd': bootstrap_args |= RB_KDB; break;
-    case 'n': bootstrap_args |= RB_INITNAME; break;
-    case 'f': fakeboot = 1; break;
-    case 'H': crash_flags = RB_DEBUGGER; break;
-    case 'x': /* NOP */ break;
-    default: return ARGP_ERR_UNKNOWN;
-    }
-  return 0;
-}
-
-int
-main (int argc, char **argv, char **envp)
-{
-  volatile int err;
-  int i;
-  int flags;
-  mach_port_t consdev;
-  struct argp argp = { options, parse_opt, 0, doc };
-
-  /* Parse the arguments.  We don't want the vector reordered, we
-     should pass on to our child the exact arguments we got and just
-     ignore any arguments that aren't flags for us.  ARGP_NO_ERRS
-     suppresses --help and --version, so we only use that option if we
-     are booting.  */
-  flags = ARGP_IN_ORDER;
-  if (getpid () == 0)
-    flags |= ARGP_NO_ERRS;
-  argp_parse (&argp, argc, argv, flags, 0, 0);
-
-  if (getpid () > 0)
-    error (2, 0, "can only be run by bootstrap filesystem");
-
-  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, &fstask)
-      || device_open (device_master, D_WRITE, "console", &consdev))
-    crash_mach ();
-
-  wire_task_self ();
-
-  /* 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);
-
-  err = argz_create (envp, &startup_envz, &startup_envz_len);
-  assert_perror (err);
-
-  /* At this point we can use assert to check for errors.  */
-  err = mach_port_allocate (mach_task_self (),
-                           MACH_PORT_RIGHT_RECEIVE, &startup);
-  assert_perror (err);
-  err = mach_port_insert_right (mach_task_self (), startup, startup,
-                               MACH_MSG_TYPE_MAKE_SEND);
-  assert_perror (err);
-
-  /* Crash if the boot filesystem task dies.  */
-  request_dead_name (fstask);
-
-  /* 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);
-
-  /* All programs we start should ignore job control stop signals.
-     That way Posix.1 B.2.2.2 is satisfied where it says that programs
-     not run under job control shells are protected.  */
-  default_ints[INIT_SIGIGN] = (sigmask (SIGTSTP)
-                              | sigmask (SIGTTIN)
-                              | sigmask (SIGTTOU));
-
-  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_perror (err);
-    }
-}
-
-void
-launch_core_servers (void)
-{
-  mach_port_t old;
-  mach_port_t authproc, fsproc, procproc;
-  error_t err;
-
-  /* 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);
-  if (!fakeboot)
-    {
-      mach_port_deallocate (mach_task_self (), device_master);
-      device_master = 0;
-    }
-
-  /* Mark us as important.  */
-  proc_mark_important (procserver);
-  proc_mark_exec (procserver);
-
-  /* Declare that the filesystem and auth are our children. */
-  proc_child (procserver, fstask);
-  proc_child (procserver, authtask);
-
-  proc_task2proc (procserver, authtask, &authproc);
-  proc_mark_important (authproc);
-  proc_mark_exec (authproc);
-  startup_authinit_reply (authreply, authreplytype, 0, authproc,
-                         MACH_MSG_TYPE_COPY_SEND);
-  mach_port_deallocate (mach_task_self (), authproc);
-
-  /* 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;
-
-  /* Declare that the proc server is our child.  */
-  proc_child (procserver, proctask);
-  err = proc_task2proc (procserver, proctask, &procproc);
-  if (!err)
-    {
-      proc_mark_important (procproc);
-      proc_mark_exec (procproc);
-      mach_port_deallocate (mach_task_self (), procproc);
-    }
-
-  proc_register_version (procserver, host_priv, "init", "", HURD_VERSION);
-
-  /* Get the bootstrap filesystem's proc server port.
-     We must do this before calling proc_setmsgport below.  */
-  proc_task2proc (procserver, fstask, &fsproc);
-  proc_mark_important (fsproc);
-  proc_mark_exec (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 will block waiting on our message port.  */
-  proc_setmsgport (procserver, startup, &old);
-  if (old != MACH_PORT_NULL)
-    mach_port_deallocate (mach_task_self (), old);
-
-  /* Give the bootstrap FS its proc and auth ports.  */
-  err = fsys_init (bootport, fsproc, MACH_MSG_TYPE_COPY_SEND, authserver);
-  mach_port_deallocate (mach_task_self (), fsproc);
-  if (err)
-    error (0, err, "fsys_init"); /* Not necessarily fatal.  */
-}
-
-/* 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;
-  int i;
-
-  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));
-
-  /* MAKE_SEND is safe in these transactions because we destroy REF
-     ourselves each time. */
-  pt = getcwdir ();
-  ref = mach_reply_port ();
-  io_reauthenticate (pt, ref, MACH_MSG_TYPE_MAKE_SEND);
-  auth_user_authenticate (nullauth, 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, 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_COPY_SEND, INIT_PORT_MAX,
-                                    std_int_array, INIT_INT_MAX));
-  for (i = 0; i < INIT_PORT_MAX; i++)
-    mach_port_deallocate (mach_task_self (), std_port_array[i]);
-}
-
-/* Frobnicate the kernel task and the proc server's idea of it (PID 2),
-   so the kernel command line can be read as for a normal Hurd process.  */
-
-void
-frob_kernel_process (void)
-{
-  error_t err;
-  int argc, i;
-  char *argz, *entry;
-  size_t argzlen;
-  size_t windowsz;
-  vm_address_t mine, his;
-  task_t task;
-  process_t proc, kbs;
-
-  err = proc_pid2task (procserver, HURD_PID_KERNEL, &task);
-  if (err)
-    {
-      error (0, err, "cannot get kernel task port");
-      return;
-    }
-  err = proc_task2proc (procserver, task, &proc);
-  if (err)
-    {
-      error (0, err, "cannot get kernel task's proc server port");
-      mach_port_deallocate (mach_task_self (), task);
-      return;
-    }
-
-  /* Mark the kernel task as an essential task so that we or the proc server
-     never want to task_terminate it.  */
-  proc_mark_important (proc);
-
-  err = record_essential_task ("kernel", task);
-  assert_perror (err);
-
-  err = task_get_bootstrap_port (task, &kbs);
-  assert_perror (err);
-  if (kbs == MACH_PORT_NULL)
-    {
-      /* The kernel task has no bootstrap port set, so we are presumably
-        the first Hurd to boot.  Install the kernel task's proc port from
-        this Hurd's proc server as the task bootstrap port.  Additional
-        Hurds will see this.  */
+    case 's':
+      single = 1;
+      break;
 
-      err = task_set_bootstrap_port (task, proc);
-      if (err)
-       error (0, err, "cannot set kernel task's bootstrap port");
+    case 'a':
+      /* Ignored.  */
+      break;
 
-      if (fakeboot)
-       error (0, 0, "warning: --fake-boot specified but I see no other Hurd");
+    default:
+      return ARGP_ERR_UNKNOWN;
     }
-  else
-    {
-      /* The kernel task has a bootstrap port set.  Perhaps it is its proc
-        server port from another Hurd.  If so, propagate the kernel
-        argument locations from that Hurd rather than diddling with the
-        kernel task ourselves.  */
-
-      vm_address_t kargv, kenvp;
-      err = proc_get_arg_locations (kbs, &kargv, &kenvp);
-      mach_port_deallocate (mach_task_self (), kbs);
-      if (err)
-       error (0, err, "kernel task bootstrap port (ignoring)");
-      else
-       {
-         err = proc_set_arg_locations (proc, kargv, kenvp);
-         if (err)
-           error (0, err, "cannot propagate original kernel command line");
-         else
-           {
-             mach_port_deallocate (mach_task_self (), proc);
-             mach_port_deallocate (mach_task_self (), task);
-             if (! fakeboot)
-               error (0, 0, "warning: "
-                      "I see another Hurd, but --fake-boot was not given");
-             return;
-           }
-       }
-    }
-
-  /* Our arguments make up the multiboot command line used to boot the
-     kernel.  We'll write into the kernel task a page containing a
-     canonical argv array and argz of those words.  */
-
-  err = argz_create (&global_argv[1], &argz, &argzlen);
-  assert_perror (err);
-  argc = argz_count (argz, argzlen);
-
-  windowsz = round_page (((argc + 1) * sizeof (char *)) + argzlen);
 
-  mine = (vm_address_t) mmap (0, windowsz, PROT_READ|PROT_WRITE,
-                             MAP_ANON, 0, 0);
-  assert (mine != -1);
-  err = vm_allocate (task, &his, windowsz, 1);
-  if (err)
-    {
-      error (0, err, "cannot allocate %Zu bytes in kernel task", windowsz);
-      free (argz);
-      mach_port_deallocate (mach_task_self (), proc);
-      mach_port_deallocate (mach_task_self (), task);
-      munmap ((caddr_t) mine, windowsz);
-      return;
-    }
-
-  for (i = 0, entry = argz; entry != NULL;
-       ++i, entry = argz_next (argz, argzlen, entry))
-    ((char **) mine)[i] = ((char *) &((char **) his)[argc + 1]
-                          + (entry - argz));
-  ((char **) mine)[argc] = NULL;
-  memcpy (&((char **) mine)[argc + 1], argz, argzlen);
-
-  free (argz);
-
-  /* We have the data all set up in our copy, now just write it over.  */
-  err = vm_write (task, his, mine, windowsz);
-  mach_port_deallocate (mach_task_self (), task);
-  munmap ((caddr_t) mine, windowsz);
-  if (err)
-    {
-      error (0, err, "cannot write command line into kernel task");
-      return;
-    }
-
-  /* The argument vector is set up in the kernel task at address HIS.
-     Finally, we can inform the proc server where to find it.  */
-  err = proc_set_arg_locations (proc, his, his + (argc * sizeof (char *)));
-  mach_port_deallocate (mach_task_self (), proc);
-  if (err)
-    error (0, err, "proc_set_arg_locations for kernel task");
+  return 0;
 }
 
-/** Running userland.  **/
-
-/* In the "split-init" setup, we just run a single program (usually
-   /libexec/runsystem) that is not expected to ever exit (or stop).
-   If it does exit (or can't be started), we go to an emergency single-user
-   shell as a fallback.  */
-
-
-static pid_t child_pid;                /* PID of the child we run */
-static task_t child_task;              /* and its (original) task port */
-
-error_t send_signal (mach_port_t msgport, int signal, mach_port_t refport,
-                    mach_msg_timeout_t);
-
-static void launch_something (const char *why);
-
-
-/* SIGNO has arrived and has been validated.  Do whatever work it
-   implies. */
 void
-process_signal (int signo)
+sigchld_handler(int signal)
 {
-  if (signo == SIGCHLD)
-    {
-      /* A child died.  Find its status.  */
-      int status;
-      pid_t pid;
-
-      while (1)
-       {
-         pid = waitpid (WAIT_ANY, &status, WNOHANG | WUNTRACED);
-         if (pid <= 0)
-           break;              /* No more children.  */
-
-         /* Since we are init, orphaned processes get reparented to us and
-            alas, all our adopted children eventually die.  Woe is us.  We
-            just need to reap the zombies to relieve the proc server of
-            its burden, and then we can forget about the little varmints.  */
-
-         if (pid == child_pid)
-           {
-             /* The big magilla bit the dust.  */
-
-             char *desc = 0;
-
-             mach_port_deallocate (mach_task_self (), child_task);
-             child_task = MACH_PORT_NULL;
-             child_pid = -1;
-
-             if (WIFSIGNALED (status))
-               asprintf (&desc, "terminated abnormally (%s)",
-                         strsignal (WTERMSIG (status)));
-             else if (WIFSTOPPED (status))
-               asprintf (&desc, "stopped abnormally (%s)",
-                         strsignal (WTERMSIG (status)));
-             else if (WEXITSTATUS (status) == 0)
-               desc = strdup ("finished");
-             else
-               asprintf (&desc, "exited with status %d",
-                         WEXITSTATUS (status));
-
-             {
-               char buf[40];
-               snprintf (buf, sizeof buf, "%d", status);
-               setenv ("STATUS", buf, 1);
-             }
+  /* A child died.  Find its status.  */
+  int status;
+  pid_t pid;
 
-             launch_something (desc);
-              free (desc);
-           }
-       }
-    }
-  else
+  while (1)
     {
-      /* Pass the signal on to the child.  */
-      task_t task;
-      error_t err;
+      pid = waitpid (WAIT_ANY, &status, WNOHANG | WUNTRACED);
+      if (pid <= 0)
+       break;          /* No more children.  */
 
-      err = proc_pid2task (procserver, child_pid, &task);
-      if (err)
-       {
-         error (0, err, "proc_pid2task on %d", child_pid);
-         task = child_task;
-       }
-      else
-       {
-         mach_port_deallocate (mach_task_self (), child_task);
-         child_task = task;
-       }
+      /* Since we are init, orphaned processes get reparented to us and
+        alas, all our adopted children eventually die.  Woe is us.  We
+        just need to reap the zombies to relieve the proc server of
+        its burden, and then we can forget about the little varmints.  */
 
-      if (signo == SIGKILL)
-       {
-         err = task_terminate (task);
-         if (err != MACH_SEND_INVALID_DEST)
-           error (0, err, "task_terminate");
-       }
-      else
+      if (pid == child_pid)
        {
-         mach_port_t msgport;
-         err = proc_getmsgport (procserver, child_pid, &msgport);
-         if (err)
-           error (0, err, "proc_getmsgport");
+         /* The big magilla bit the dust.  */
+         child_pid = -1;
+
+         char *desc = NULL;
+         if (WIFSIGNALED (status))
+           asprintf (&desc, "terminated abnormally (%s)",
+                     strsignal (WTERMSIG (status)));
+         else if (WIFSTOPPED (status))
+           asprintf (&desc, "stopped abnormally (%s)",
+                     strsignal (WTERMSIG (status)));
+         else if (WEXITSTATUS (status) == 0)
+           desc = strdup ("finished");
          else
-           {
-             err = send_signal (msgport, signo, task,
-                                500); /* Block only half a second.  */
-             mach_port_deallocate (mach_task_self (), msgport);
-             if (err)
-               {
-                 error (0, err, "cannot send %s to child %d",
-                        strsignal (signo), child_pid);
-                 err = task_terminate (task);
-                 if (err != MACH_SEND_INVALID_DEST)
-                   error (0, err, "task_terminate");
-               }
-           }
-       }
-    }
-}
+           asprintf (&desc, "exited with status %d",
+                     WEXITSTATUS (status));
 
-/* Start the child program PROG.  It is run via /libexec/console-run
-   with the given additional arguments.  */
-static int
-start_child (const char *prog, char **progargs)
-{
-  file_t file;
-  error_t err;
-  char *args;
-  size_t arglen;
-
-  if (progargs == 0)
-    {
-      const char *argv[] = { "/libexec/console-run", prog, 0 };
-      err = argz_create ((char **) argv, &args, &arglen);
-    }
-  else
-    {
-      int argc = 0;
-      while (progargs[argc] != 0)
-       ++argc;
-      {
-       const char *argv[2 + argc + 1];
-       argv[0] = "/libexec/console-run";
-       argv[1] = prog;
-       argv[2 + argc] = 0;
-       while (argc-- > 0)
-         argv[2 + argc] = progargs[argc];
-       err = argz_create ((char **) argv, &args, &arglen);
-      }
-    }
-  assert_perror (err);
-
-  file = file_name_lookup (args, O_EXEC, 0);
-  if (file == MACH_PORT_NULL)
-    {
-      error (0, errno, "%s", args);
-      free (args);
-      return -1;
-    }
-
-  task_create (mach_task_self (),
-#ifdef KERN_INVALID_LEDGER
-              NULL, 0, /* OSF Mach */
-#endif
-              0, &child_task);
-  proc_child (procserver, child_task);
-  proc_task2pid (procserver, child_task, &child_pid);
-  proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
-
-  if (bootstrap_args & RB_KDB)
-    {
-      printf ("Pausing for %s\n", args);
-      getchar ();
-    }
+         error (0, 0, "child %s", desc);
+         free (desc);
 
-  err = file_exec (file, child_task, 0,
-                  args, arglen,
-                  startup_envz, startup_envz_len,
-                  NULL, MACH_MSG_TYPE_COPY_SEND, 0, /* No fds.  */
-                  default_ports, MACH_MSG_TYPE_COPY_SEND, INIT_PORT_MAX,
-                  default_ints, INIT_INT_MAX,
-                  NULL, 0, NULL, 0);
-  proc_mark_important (default_ports[INIT_PORT_PROC]);
-  mach_port_deallocate (mach_task_self (), default_ports[INIT_PORT_PROC]);
-  mach_port_deallocate (mach_task_self (), file);
-  if (err)
-    {
-      error (0, err, "Cannot execute %s", args);
-      free (args);
-      return -1;
-    }
-  free (args);
-  return 0;
-}
-
-static void
-launch_something (const char *why)
-{
-  file_t something;
-  static unsigned int try;
-  static const char *const tries[] =
-  {
-    "/libexec/runsystem",
-    _PATH_BSHELL,
-    "/bin/shd",                        /* XXX */
-  };
-
-  if (why)
-    error (0, 0, "%s %s", tries[try - 1], why);
-
-  something = file_name_lookup (tries[try], O_EXEC, 0);
-  if (something != MACH_PORT_NULL)
-    {
-      mach_port_deallocate (mach_task_self (), something);
-      if (try == 0 && start_child (tries[try++], &global_argv[1]) == 0)
-        return;
-    }
-  else
-    try++;
-
-  while (try < sizeof tries / sizeof tries[0])
-    {
-      something = file_name_lookup (tries[try], O_EXEC, 0);
-      if (something != MACH_PORT_NULL)
-       {
-         mach_port_deallocate (mach_task_self (), something);
-         if (start_child (tries[try++], NULL) == 0)
-           return;
+         /* XXX: launch emergency shell.  */
+         error (23, 0, "panic!!");
        }
     }
-
-  crash_system ();
-}
-
-void
-launch_system (void)
-{
-  launch_something (0);
 }
 
-/** RPC servers **/
-
-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)
+int
+main (int argc, char **argv)
 {
-  static int authinit, procinit, execinit;
-  int fail;
-
-  /* Always deallocate the extra reference this message carries.  */
-  if (MACH_PORT_VALID (credential))
-    mach_port_deallocate (mach_task_self (), credential);
-
-  if (credential != host_priv)
-    return EPERM;
-
-  fail = record_essential_task (name, task);
-  if (fail)
-    return fail;
-
-  if (!booted)
+  struct argp argp =
     {
-      if (!strcmp (name, "auth"))
-       authinit = 1;
-      else if (!strcmp (name, "exec"))
-        {
-          execinit = 1;
-          mach_port_t execproc;
-          proc_task2proc (procserver, task, &execproc);
-          proc_mark_important (execproc);
-        }
-      else if (!strcmp (name, "proc"))
-       procinit = 1;
+      .options = options,
+      .parser = parse_opt,
+      .doc = doc,
+    };
+  argp_parse (&argp, argc, argv, 0, 0, 0);
 
-      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);
+  if (getpid () != 1)
+    error (1, 0, "can only be run as PID 1");
 
-         init_stdarrays ();
-         frob_kernel_process ();
+  struct sigaction sa;
+  sa.sa_handler = SIG_IGN;
+  sa.sa_flags = 0;
+  sigemptyset (&sa.sa_mask);
 
-         launch_system ();
+  sigaction (SIGHUP, &sa, NULL);
+  sigaction (SIGINT, &sa, NULL);
+  sigaction (SIGQUIT, &sa, NULL);
+  sigaction (SIGTERM, &sa, NULL);
+  sigaction (SIGUSR1, &sa, NULL);
+  sigaction (SIGUSR2, &sa, NULL);
+  sigaction (SIGTSTP, &sa, NULL);
 
-         booted = 1;
+  sa.sa_handler = sigchld_handler;
+  sa.sa_flags |= SA_RESTART;
+  sigaction (SIGCHLD, &sa, NULL);
 
-         return MIG_NO_REPLY;
-       }
-    }
+  char *args[] = { "/etc/hurd/runsystem.hurd", NULL };
 
-  return 0;
-}
-
-kern_return_t
-S_startup_request_notification (mach_port_t server,
-                               mach_port_t notify,
-                               char *name)
-{
-  struct ntfy_task *nt;
-
-  request_dead_name (notify);
-
-  /* Note that the ntfy_tasks list is kept in inverse order of the
-     calls; this is important.  We need later notification requests
-     to get executed first.  */
-  nt = malloc (sizeof (struct ntfy_task));
-  nt->notify_port = notify;
-  nt->next = ntfy_tasks;
-  ntfy_tasks = nt;
-  nt->name = malloc (strlen (name) + 1);
-  strcpy (nt->name, name);
-  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;
-
-  assert (notify == startup);
-
-  /* Deallocate the extra reference the notification carries. */
-  mach_port_deallocate (mach_task_self (), name);
-
-  for (et = ess_tasks; et != NULL; et = et->next)
-    if (et->task_port == name)
-      /* An essential task has died.  */
-      {
-       error (0, 0, "Crashing system; essential task %s died", et->name);
-       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;
-      }
-
-  if (! booted)
+  switch (child_pid = fork ())
     {
-      /* The system has not come up yet, so essential tasks are not yet
-        registered.  But the essential servers involved in the bootstrap
-        handshake might crash before completing it, so we have requested
-        dead-name notification on those tasks.  */
-      static const struct { task_t *taskp; const char *name; } boots[] =
-        {
-         {&fstask, "bootstrap filesystem"},
-         {&authtask, "auth"},
-         {&proctask, "proc"},
-       };
-      size_t i;
-      for (i = 0; i < sizeof boots / sizeof boots[0]; ++i)
-       if (name == *boots[i].taskp)
-         {
-           error (0, 0, "Crashing system; %s server died during bootstrap",
-                  boots[i].name);
-           crash_mach ();
-         }
-      error (0, 0, "BUG!  Unexpected dead-name notification (name %#zx)",
-            name);
-      crash_mach ();
+    case -1:
+      error (1, errno, "failed to fork");
+    case 0:
+      execv (args[0], args);
+      error (2, errno, "failed to execv child");
     }
 
-  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 (;;);
-}
-
-/* Stubs for unused notification RPCs.  */
-
-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;
-}
-
-/* msg server */
-
-kern_return_t
-S_msg_sig_post_untraced (mach_port_t msgport,
-                        mach_port_t reply, mach_msg_type_name_t reply_type,
-                        int signo, natural_t sigcode, mach_port_t refport)
-{
-  if (refport != mach_task_self ())
-    return EPERM;
-  mach_port_deallocate (mach_task_self (), refport);
-
-  /* Reply immediately */
-  msg_sig_post_untraced_reply (reply, reply_type, 0);
-
-  process_signal (signo);
-  return MIG_NO_REPLY;
-}
-
-kern_return_t
-S_msg_sig_post (mach_port_t msgport,
-               mach_port_t reply, mach_msg_type_name_t reply_type,
-               int signo, natural_t sigcode, mach_port_t refport)
-{
-  if (refport != mach_task_self ())
-    return EPERM;
-  mach_port_deallocate (mach_task_self (), refport);
-
-  /* Reply immediately */
-  msg_sig_post_reply (reply, reply_type, 0);
-
-  process_signal (signo);
-  return MIG_NO_REPLY;
-}
-
-
-/* For the rest of the msg functions, just call the C library's
-   internal server stubs usually run in the signal thread.  */
-
-kern_return_t
-S_msg_proc_newids (mach_port_t process,
-       mach_port_t task,
-       pid_t ppid,
-       pid_t pgrp,
-       int orphaned)
-{ return _S_msg_proc_newids (process, task, ppid, pgrp, orphaned); }
-
-
-kern_return_t
-S_msg_add_auth (mach_port_t process,
-       auth_t auth)
-{ return _S_msg_add_auth (process, auth); }
-
-
-kern_return_t
-S_msg_del_auth (mach_port_t process,
-       mach_port_t task,
-       intarray_t uids,
-       mach_msg_type_number_t uidsCnt,
-       intarray_t gids,
-       mach_msg_type_number_t gidsCnt)
-{ return _S_msg_del_auth (process, task, uids, uidsCnt, gids, gidsCnt); }
-
-
-kern_return_t
-S_msg_get_init_port (mach_port_t process,
-       mach_port_t refport,
-       int which,
-       mach_port_t *port,
-       mach_msg_type_name_t *portPoly)
-{ return _S_msg_get_init_port (process, refport, which, port, portPoly); }
-
-
-kern_return_t
-S_msg_set_init_port (mach_port_t process,
-       mach_port_t refport,
-       int which,
-       mach_port_t port)
-{ return _S_msg_set_init_port (process, refport, which, port); }
-
-
-kern_return_t
-S_msg_get_init_ports (mach_port_t process,
-       mach_port_t refport,
-       portarray_t *ports,
-       mach_msg_type_name_t *portsPoly,
-       mach_msg_type_number_t *portsCnt)
-{ return _S_msg_get_init_ports (process, refport, ports, portsPoly, portsCnt); 
}
-
-
-kern_return_t
-S_msg_set_init_ports (mach_port_t process,
-       mach_port_t refport,
-       portarray_t ports,
-       mach_msg_type_number_t portsCnt)
-{ return _S_msg_set_init_ports (process, refport, ports, portsCnt); }
-
-
-kern_return_t
-S_msg_get_init_int (mach_port_t process,
-       mach_port_t refport,
-       int which,
-       int *value)
-{ return _S_msg_get_init_int (process, refport, which, value); }
-
-
-kern_return_t
-S_msg_set_init_int (mach_port_t process,
-       mach_port_t refport,
-       int which,
-       int value)
-{ return _S_msg_set_init_int (process, refport, which, value); }
-
-
-kern_return_t
-S_msg_get_init_ints (mach_port_t process,
-       mach_port_t refport,
-       intarray_t *values,
-       mach_msg_type_number_t *valuesCnt)
-{ return _S_msg_get_init_ints (process, refport, values, valuesCnt); }
-
-
-kern_return_t
-S_msg_set_init_ints (mach_port_t process,
-       mach_port_t refport,
-       intarray_t values,
-       mach_msg_type_number_t valuesCnt)
-{ return _S_msg_set_init_ints (process, refport, values, valuesCnt); }
-
-
-kern_return_t
-S_msg_get_dtable (mach_port_t process,
-       mach_port_t refport,
-       portarray_t *dtable,
-       mach_msg_type_name_t *dtablePoly,
-       mach_msg_type_number_t *dtableCnt)
-{ return _S_msg_get_dtable (process, refport, dtable, dtablePoly, dtableCnt); }
-
-
-kern_return_t
-S_msg_set_dtable (mach_port_t process,
-       mach_port_t refport,
-       portarray_t dtable,
-       mach_msg_type_number_t dtableCnt)
-{ return _S_msg_set_dtable (process, refport, dtable, dtableCnt); }
-
-
-kern_return_t
-S_msg_get_fd (mach_port_t process,
-       mach_port_t refport,
-       int fd,
-       mach_port_t *port,
-       mach_msg_type_name_t *portPoly)
-{ return _S_msg_get_fd (process, refport, fd, port, portPoly); }
-
-
-kern_return_t
-S_msg_set_fd (mach_port_t process,
-       mach_port_t refport,
-       int fd,
-       mach_port_t port)
-{ return _S_msg_set_fd (process, refport, fd, port); }
-
-
-kern_return_t
-S_msg_get_environment (mach_port_t process,
-       data_t *value,
-       mach_msg_type_number_t *valueCnt)
-{ return _S_msg_get_environment (process, value, valueCnt); }
-
-
-kern_return_t
-S_msg_set_environment (mach_port_t process,
-       mach_port_t refport,
-       data_t value,
-       mach_msg_type_number_t valueCnt)
-{ return _S_msg_set_environment (process, refport, value, valueCnt); }
-
-
-kern_return_t
-S_msg_get_env_variable (mach_port_t process,
-       string_t variable,
-       data_t *value,
-       mach_msg_type_number_t *valueCnt)
-{ return _S_msg_get_env_variable (process, variable, value, valueCnt); }
-
-
-kern_return_t
-S_msg_set_env_variable (mach_port_t process,
-       mach_port_t refport,
-       string_t variable,
-       string_t value,
-       boolean_t replace)
-{ return _S_msg_set_env_variable (process, refport, variable, value, replace); 
}
-
-error_t
-S_msg_describe_ports (mach_port_t process,
-                     mach_port_t refport,
-                     mach_port_array_t names,
-                     mach_msg_type_number_t namesCnt,
-                     data_t *descriptions,
-                     mach_msg_type_number_t *descriptionsCnt)
-{
-  return _S_msg_describe_ports (process, refport, names, namesCnt,
-                               descriptions, descriptionsCnt);
-}
-
-error_t
-S_msg_report_wait (mach_port_t process, thread_t thread,
-                  string_t desc, mach_msg_id_t *rpc)
-{
-  *desc = 0;
-  *rpc = 0;
+  select (0, NULL, NULL, NULL, NULL);
+  /* Not reached.  */
   return 0;
 }
diff --git a/init/stubs.c b/init/stubs.c
deleted file mode 100644
index 5292ab6..0000000
--- a/init/stubs.c
+++ /dev/null
@@ -1,139 +0,0 @@
-/* By-hand stubs for some RPC calls
-   Copyright (C) 1994,96,99,2000 Free Software Foundation, Inc.
-
-   This program 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.
-
-   This program 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 this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-#include <stdlib.h>
-#include <hurd/hurd_types.h>
-#include <mach.h>
-#include <string.h>
-#include <assert.h>
-
-/* From hurd/msg.defs: */
-#define RPCID_SIG_POST 23000
-
-
-/* Send signal SIGNO to MSGPORT with REFPORT as reference.  Don't
-   block in any fashion.  */
-error_t
-send_signal (mach_port_t msgport,
-            int signal,
-            mach_port_t refport,
-            mach_msg_timeout_t timeout)
-{
-  error_t err;
-
-  /* This message buffer might be modified by mach_msg in some error cases,
-     so we cannot safely reuse a static buffer.  */
-  struct
-    {
-      mach_msg_header_t head;
-      mach_msg_type_t signaltype;
-      int signal;
-      mach_msg_type_t sigcode_type;
-      natural_t sigcode;
-      mach_msg_type_t refporttype;
-      mach_port_t refport;
-    }
-  message =
-  {
-    {
-      /* Message header: */
-      (MACH_MSGH_BITS_COMPLEX
-       | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
-                        MACH_MSG_TYPE_MAKE_SEND_ONCE)), /* msgh_bits */
-      sizeof message,          /* msgh_size */
-      msgport,                 /* msgh_remote_port */
-      MACH_PORT_NULL,          /* msgh_local_port */
-      0,                       /* msgh_seqno */
-      RPCID_SIG_POST,          /* msgh_id */
-    },
-    {
-      /* Type descriptor for signo */
-      MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
-      32,                      /* msgt_size */
-      1,                       /* msgt_number */
-      1,                       /* msgt_inline */
-      0,                       /* msgt_longform */
-      0,                       /* msgt_deallocate */
-      0,                       /* msgt_unused */
-    },
-    /* Signal number */
-    signal,
-    /* Type descriptor for sigcode */
-    {
-      MACH_MSG_TYPE_INTEGER_32, /* msgt_name */
-      32,                      /* msgt_size */
-      1,                       /* msgt_number */
-      1,                       /* msgt_inline */
-      0,                       /* msgt_longform */
-      0,                       /* msgt_deallocate */
-      0,                       /* msgt_unused */
-    },
-    /* Sigcode */
-    0,
-    {
-      /* Type descriptor for refport */
-      MACH_MSG_TYPE_COPY_SEND, /* msgt_name */
-      32,                      /* msgt_size */
-      1,                       /* msgt_number */
-      1,                       /* msgt_inline */
-      0,                       /* msgt_longform */
-      0,                       /* msgt_deallocate */
-      0,                       /* msgt_unused */
-    },
-    /* Reference port */
-    refport
-  };
-
-  err = mach_msg (&message.head,
-                 MACH_SEND_MSG|MACH_SEND_TIMEOUT, sizeof message, 0,
-                 MACH_PORT_NULL, timeout, MACH_PORT_NULL);
-
-  switch (err)
-    {
-    case MACH_SEND_TIMED_OUT:
-      /* The send could not complete in time.  In this error case, the
-        kernel has modified the message buffer in a pseudo-receive
-        operation.  That means our COPY_SEND refs might now be MOVE_SEND
-        refs, in which case each has gained user ref accordingly.  To
-        avoid leaking those refs, we must clean up the buffer.  We don't
-        use mach_msg_destroy because it assumes the local/remote ports in
-        the header have been reversed as from a real receive, while a
-        pseudo-receive leaves them as they were.  */
-      if (MACH_MSGH_BITS_REMOTE (message.head.msgh_bits)
-         == MACH_MSG_TYPE_MOVE_SEND)
-       mach_port_deallocate (mach_task_self (),
-                             message.head.msgh_remote_port);
-      if (message.refporttype.msgt_name == MACH_MSG_TYPE_MOVE_SEND)
-       mach_port_deallocate (mach_task_self (), message.refport);
-      break;
-
-      /* These are the other codes that mean a pseudo-receive modified
-        the message buffer and we might need to clean up the send rights.
-        None of them should be possible in our usage.  */
-    case MACH_SEND_INTERRUPTED:
-    case MACH_SEND_INVALID_NOTIFY:
-    case MACH_SEND_NO_NOTIFY:
-    case MACH_SEND_NOTIFY_IN_PROGRESS:
-      assert_perror (err);
-      break;
-
-    default:                   /* Other errors are safe to ignore.  */
-      break;
-    }
-
-  return err;
-}
diff --git a/libcons/mutations.h b/libcons/mutations.h
index c895447..4751340 100644
--- a/libcons/mutations.h
+++ b/libcons/mutations.h
@@ -21,6 +21,7 @@
 /* Only CPP macro definitions should go in this file. */
 
 #define FS_NOTIFY_INTRAN cons_notify_t begin_using_notify_port (fs_notify_t)
+#define FS_NOTIFY_INTRAN_PAYLOAD cons_notify_t begin_using_notify_payload
 #define FS_NOTIFY_DESTRUCTOR end_using_notify_port (cons_notify_t)
 
 #define FS_NOTIFY_IMPORTS import "priv.h";
diff --git a/libcons/priv.h b/libcons/priv.h
index 38971ff..6cdf3db 100644
--- a/libcons/priv.h
+++ b/libcons/priv.h
@@ -80,6 +80,12 @@ begin_using_notify_port (fs_notify_t port)
   return ports_lookup_port (cons_port_bucket, port, cons_port_class);
 }
 
+static inline cons_notify_t
+begin_using_notify_payload (unsigned long payload)
+{
+  return ports_lookup_payload (cons_port_bucket, payload, cons_port_class);
+}
+
 /* Called by MiG after server routines have been run; this balances
    begin_using_notify_port, and is arranged for the fs_notify
    interfaces by mutations.h. */
diff --git a/libdiskfs/boot-start.c b/libdiskfs/boot-start.c
index a590975..cfe2303 100644
--- a/libdiskfs/boot-start.c
+++ b/libdiskfs/boot-start.c
@@ -33,7 +33,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 
02139, USA.  */
 #include <string.h>
 #include <argz.h>
 #include <error.h>
-#include <pids.h>
 #include "exec_S.h"
 #include "exec_startup_S.h"
 #include "fsys_S.h"
@@ -46,7 +45,7 @@ static task_t parent_task = MACH_PORT_NULL;
 static pthread_mutex_t execstartlock;
 static pthread_cond_t execstarted;
 
-const char *diskfs_boot_init_program = _HURD_INIT;
+const char *diskfs_boot_init_program = _HURD_STARTUP;
 
 static void start_execserver ();
 
@@ -602,9 +601,12 @@ diskfs_S_fsys_init (struct diskfs_control *pt,
 
   proc_register_version (procserver, host, diskfs_server_name, "",
                         diskfs_server_version);
+  mach_port_deallocate (mach_task_self (), procserver);
 
-  err = proc_getmsgport (procserver, HURD_PID_STARTUP, &startup);
-  if (!err)
+  startup = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+  if (startup == MACH_PORT_NULL)
+    error (0, errno, "%s", _SERVERS_STARTUP);
+  else
     {
       startup_essential_task (startup, mach_task_self (), MACH_PORT_NULL,
                              diskfs_server_name, host);
@@ -612,7 +614,6 @@ diskfs_S_fsys_init (struct diskfs_control *pt,
     }
 
   mach_port_deallocate (mach_task_self (), host);
-  mach_port_deallocate (mach_task_self (), procserver);
 
   _diskfs_init_completed ();
 
diff --git a/libdiskfs/dir-init.c b/libdiskfs/dir-init.c
index 4efded0..8301ca1 100644
--- a/libdiskfs/dir-init.c
+++ b/libdiskfs/dir-init.c
@@ -33,7 +33,8 @@ diskfs_init_dir (struct node *dp, struct node *pdp, struct 
protid *cred)
   static uid_t zero = 0;
   static struct idvec vec = {&zero, 1, 1};
   static struct iouser user = {&vec, &vec, 0};
-  struct protid lookupcred = {{0, 0, 0, 0}, &user, cred->po, 0, 0};
+  struct protid lookupcred = {{ .refcounts = { .references = {1, 0}}},
+                             &user, cred->po, 0, 0};
 
   /* New links */
   if (pdp->dn_stat.st_nlink == diskfs_link_max - 1)
diff --git a/libdiskfs/dir-lookup.c b/libdiskfs/dir-lookup.c
index 3950bf9..e228745 100644
--- a/libdiskfs/dir-lookup.c
+++ b/libdiskfs/dir-lookup.c
@@ -314,6 +314,7 @@ diskfs_S_dir_lookup (struct protid *dircred,
              if (register_translator)
                {
                  char *translator_path = strdupa (relpath);
+                 char *complete_path;
                  if (nextname != NULL)
                    {
                      /* This was not the last path component.
@@ -326,9 +327,17 @@ diskfs_S_dir_lookup (struct protid *dircred,
                      translator_path[end - path_start] = '\0';
                    }
 
+                 if (dircred->po->path == NULL)
+                     /* dircred is the root directory.  */
+                     complete_path = translator_path;
+                 else
+                     asprintf (&complete_path, "%s/%s", dircred->po->path, 
translator_path);
+
                  error = fshelp_set_active_translator (&newpi->pi,
-                                                       translator_path,
+                                                       complete_path,
                                                        np->transbox.active);
+                 if (complete_path != translator_path)
+                   free(complete_path);
                  if (error)
                    goto out;
                }
diff --git a/libdiskfs/disk-pager.c b/libdiskfs/disk-pager.c
index 4083ef2..008aa2d 100644
--- a/libdiskfs/disk-pager.c
+++ b/libdiskfs/disk-pager.c
@@ -60,6 +60,7 @@ diskfs_start_disk_pager (struct user_pager_info *upi,
                          MACH_MSG_TYPE_MAKE_SEND);
 
   /* Now map the disk image.  */
+  *image = 0;
   err = vm_map (mach_task_self (), (vm_address_t *)image, size,
                0, 1, disk_pager_port, 0, 0,
                VM_PROT_READ | (diskfs_readonly ? 0 : VM_PROT_WRITE),
diff --git a/libdiskfs/diskfs.h b/libdiskfs/diskfs.h
index e59ba99..2818225 100644
--- a/libdiskfs/diskfs.h
+++ b/libdiskfs/diskfs.h
@@ -833,8 +833,14 @@ error_t diskfs_start_protid (struct peropen *po, struct 
protid **cred);
 void diskfs_finish_protid (struct protid *cred, struct iouser *user);
 
 extern struct protid * diskfs_begin_using_protid_port (file_t port);
+extern struct protid *
+diskfs_begin_using_protid_payload (unsigned long payload);
 extern struct diskfs_control * diskfs_begin_using_control_port (fsys_t port);
+extern struct diskfs_control *
+diskfs_begin_using_control_port_payload (unsigned long payload);
 extern struct bootinfo *diskfs_begin_using_bootinfo_port (exec_startup_t port);
+struct bootinfo *
+diskfs_begin_using_bootinfo_payload (unsigned long payload);
 
 extern void diskfs_end_using_protid_port (struct protid *cred);
 extern void diskfs_end_using_control_port (struct diskfs_control *cred);
@@ -851,6 +857,14 @@ diskfs_begin_using_protid_port (file_t port)
   return ports_lookup_port (diskfs_port_bucket, port, diskfs_protid_class);
 }
 
+DISKFS_EXTERN_INLINE struct protid *
+diskfs_begin_using_protid_payload (unsigned long payload)
+{
+  return ports_lookup_payload (diskfs_port_bucket,
+                              payload,
+                              diskfs_protid_class);
+}
+
 /* And for the fsys interface. */
 DISKFS_EXTERN_INLINE struct diskfs_control *
 diskfs_begin_using_control_port (fsys_t port)
@@ -858,6 +872,14 @@ diskfs_begin_using_control_port (fsys_t port)
   return ports_lookup_port (diskfs_port_bucket, port, NULL);
 }
 
+DISKFS_EXTERN_INLINE struct diskfs_control *
+diskfs_begin_using_control_port_payload (unsigned long payload)
+{
+  return ports_lookup_payload (diskfs_port_bucket,
+                              payload,
+                              NULL);
+}
+
 /* And for the exec_startup interface. */
 DISKFS_EXTERN_INLINE struct bootinfo *
 diskfs_begin_using_bootinfo_port (exec_startup_t port)
@@ -865,6 +887,13 @@ diskfs_begin_using_bootinfo_port (exec_startup_t port)
   return ports_lookup_port (diskfs_port_bucket, port, diskfs_execboot_class);
 }
 
+DISKFS_EXTERN_INLINE struct bootinfo *
+diskfs_begin_using_bootinfo_payload (unsigned long payload)
+{
+  return ports_lookup_payload (diskfs_port_bucket,
+                              payload,
+                              diskfs_execboot_class);
+}
 
 /* Called by MiG after server routines have been run; this
    balances begin_using_protid_port, and is arranged for the io
diff --git a/libdiskfs/fsmutations.h b/libdiskfs/fsmutations.h
index 3f9362b..c2167c6 100644
--- a/libdiskfs/fsmutations.h
+++ b/libdiskfs/fsmutations.h
@@ -18,12 +18,15 @@
 /* Only CPP macro definitions should go in this file. */
 
 #define FILE_INTRAN protid_t diskfs_begin_using_protid_port (file_t)
+#define FILE_INTRAN_PAYLOAD protid_t diskfs_begin_using_protid_payload
 #define FILE_DESTRUCTOR diskfs_end_using_protid_port (protid_t)
 
 #define IO_INTRAN protid_t diskfs_begin_using_protid_port (io_t)
+#define IO_INTRAN_PAYLOAD protid_t diskfs_begin_using_protid_payload
 #define IO_DESTRUCTOR diskfs_end_using_protid_port (protid_t)
 
 #define FSYS_INTRAN control_t diskfs_begin_using_control_port (fsys_t)
+#define FSYS_INTRAN_PAYLOAD control_t diskfs_begin_using_control_port_payload
 #define FSYS_DESTRUCTOR diskfs_end_using_control_port (control_t)
 
 #define FILE_IMPORTS import "libdiskfs/priv.h";
@@ -33,6 +36,8 @@
 
 #define EXEC_STARTUP_INTRAN                             \
   bootinfo_t diskfs_begin_using_bootinfo_port (exec_startup_t)
+#define EXEC_STARTUP_INTRAN_PAYLOAD                     \
+  bootinfo_t diskfs_begin_using_bootinfo_payload
 #define EXEC_STARTUP_DESTRUCTOR                         \
   diskfs_end_using_bootinfo (bootinfo_t)
 #define EXEC_STARTUP_IMPORTS                            \
diff --git a/libdiskfs/init-startup.c b/libdiskfs/init-startup.c
index d10c964..3a588e1 100644
--- a/libdiskfs/init-startup.c
+++ b/libdiskfs/init-startup.c
@@ -25,8 +25,8 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 
02139, USA.  */
 #include <fcntl.h>
 #include <error.h>
 #include <hurd/fsys.h>
+#include <hurd/paths.h>
 #include <hurd/startup.h>
-#include <pids.h>
 
 #include "startup_S.h"
 
@@ -195,15 +195,18 @@ _diskfs_init_completed ()
 
   /* Mark us as important.  */
   err = proc_mark_important (proc);
+  mach_port_deallocate (mach_task_self (), proc);
   /* This might fail due to permissions or because the old proc server
      is still running, ignore any such errors.  */
   if (err && err != EPERM && err != EMIG_BAD_ID)
     goto errout;
 
-  err = proc_getmsgport (proc, HURD_PID_STARTUP, &init);
-  mach_port_deallocate (mach_task_self (), proc);
-  if (err)
-    goto errout;
+  init = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+  if (init == MACH_PORT_NULL)
+    {
+      err = errno;
+      goto errout;
+    }
 
   notify = ports_get_send_right (pi);
   ports_port_deref (pi);
diff --git a/libdiskfs/opts-std-startup.c b/libdiskfs/opts-std-startup.c
index 6fe2875..ed25a18 100644
--- a/libdiskfs/opts-std-startup.c
+++ b/libdiskfs/opts-std-startup.c
@@ -59,7 +59,7 @@ startup_options[] =
    "Required for bootstrap filesystem, the multiboot kernel command line"},
   {"bootflags", 0, 0, OPTION_ALIAS|OPTION_HIDDEN},
   {"boot-init-program",  OPT_BOOT_INIT_PROGRAM,  "FILE", 0,
-   "For bootstrap filesystem, init program to run (default " _HURD_INIT ")"},
+   "For bootstrap filesystem, init program to run (default " _HURD_STARTUP 
")"},
   {"boot-debug-pause",  OPT_BOOT_PAUSE,                 0, 0,
    "Pause for keystroke before starting bootstrap programs"},
   {"boot-command",      OPT_BOOT_COMMAND,       0, 0,
diff --git a/libfshelp/lock-acquire.c b/libfshelp/lock-acquire.c
index 574bc5c..06c93d8 100644
--- a/libfshelp/lock-acquire.c
+++ b/libfshelp/lock-acquire.c
@@ -23,17 +23,30 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 
02139, USA.  */
 
 #define EWOULDBLOCK EAGAIN /* XXX */
 
+/* Remove this when glibc has it.  */
+#ifndef __LOCK_ATOMIC
+#define __LOCK_ATOMIC 16
+#endif
+
 error_t
 fshelp_acquire_lock (struct lock_box *box, int *user, pthread_mutex_t *mut,
                     int flags)
 {
+  int atomic = 0;
+
   if (!(flags & (LOCK_UN | LOCK_EX | LOCK_SH)))
     return 0;
   
   if ((flags & LOCK_UN)
       && (flags & (LOCK_SH | LOCK_EX)))
     return EINVAL;
-  
+
+  if (flags & __LOCK_ATOMIC)
+    {
+      atomic = 1;
+      flags &= ~__LOCK_ATOMIC;
+    }
+
   if (flags & LOCK_EX)
     flags &= ~LOCK_SH;
   
@@ -44,8 +57,10 @@ fshelp_acquire_lock (struct lock_box *box, int *user, 
pthread_mutex_t *mut,
       if (*user & LOCK_UN)
        return 0;
 
-      assert (*user == box->type);
-      assert (*user == LOCK_SH || *user == LOCK_EX);
+      assert (*user == box->type ||
+             (*user == LOCK_SH && box->type == (LOCK_SH | LOCK_EX)));
+      assert (*user == LOCK_SH || *user == LOCK_EX ||
+             *user == (LOCK_SH | LOCK_EX));
 
       if (*user == LOCK_SH)
        {
@@ -60,12 +75,39 @@ fshelp_acquire_lock (struct lock_box *box, int *user, 
pthread_mutex_t *mut,
          box->waiting = 0;
          pthread_cond_broadcast (&box->wait);
        }
+      if (box->type == (LOCK_SH | LOCK_EX) && box->shcount == 1 && 
box->waiting)
+       {
+         box->waiting = 0;
+         pthread_cond_broadcast (&box->wait);
+       }
       *user = LOCK_UN;
     }
   else
     {
+      if (atomic && *user == (flags & (LOCK_SH | LOCK_EX)))
+       /* Already have it the right way. */
+       return 0;
+
+      if (atomic && *user == LOCK_EX && flags & LOCK_SH)
+       {
+         /* Easy atomic change. */
+         *user = LOCK_SH;
+         box->type = LOCK_SH;
+         box->shcount = 1;
+         if (box->waiting)
+           {
+             box->waiting = 0;
+             pthread_cond_broadcast (&box->wait);
+           }
+         return 0;
+       }
+
+      /* We can not have two people upgrading their lock, this is a deadlock! 
*/
+      if (*user == LOCK_SH && atomic && box->type == (LOCK_SH | LOCK_EX))
+       return EDEADLK;
+
       /* If we have an exclusive lock, release it. */
-      if (*user == LOCK_EX)
+      if (*user == LOCK_EX && !atomic)
        {
          *user = LOCK_UN;
          box->type = LOCK_UN;
@@ -75,19 +117,9 @@ fshelp_acquire_lock (struct lock_box *box, int *user, 
pthread_mutex_t *mut,
              pthread_cond_broadcast (&box->wait);
            }
        }
-      
-      /* If there is an exclusive lock, wait for it to end. */
-      while (box->type == LOCK_EX)
-       {
-         if (flags & LOCK_NB)
-           return EWOULDBLOCK;
-         box->waiting = 1;
-         if (pthread_hurd_cond_wait_np (&box->wait, mut))
-           return EINTR;
-       }
 
       /* If we have a shared lock, release it. */
-      if (*user == LOCK_SH)
+      if (*user == LOCK_SH && !atomic)
        {
          *user = LOCK_UN;
          if (!--box->shcount)
@@ -99,12 +131,29 @@ fshelp_acquire_lock (struct lock_box *box, int *user, 
pthread_mutex_t *mut,
                  pthread_cond_broadcast (&box->wait);
                }
            }
+         if (box->type == (LOCK_SH | LOCK_EX) && box->shcount == 1 &&
+             box->waiting)
+           {
+             box->waiting = 0;
+             pthread_cond_broadcast (&box->wait);
+           }
        }
-      
+
+      /* If there is another exclusive lock or a pending upgrade, wait for it 
to
+        end. */
+      while (box->type & LOCK_EX)
+       {
+         if (flags & LOCK_NB)
+           return EWOULDBLOCK;
+         box->waiting = 1;
+         if (pthread_hurd_cond_wait_np (&box->wait, mut))
+           return EINTR;
+       }
+
       assert ((flags & LOCK_SH) || (flags & LOCK_EX));
       if (flags & LOCK_SH)
        {
-         assert (box->type != LOCK_EX);
+         assert (!(box->type & LOCK_EX));
          *user = LOCK_SH;
          box->type = LOCK_SH;
          box->shcount++;
@@ -112,17 +161,27 @@ fshelp_acquire_lock (struct lock_box *box, int *user, 
pthread_mutex_t *mut,
       else if (flags & LOCK_EX)
        {
          /* Wait for any shared (and exclusive) locks to finish. */
-         while (box->type != LOCK_UN)
+         while ((*user == LOCK_SH && box->shcount > 1) ||
+                (*user == LOCK_UN && box->type != LOCK_UN))
            {
              if (flags & LOCK_NB)
                return EWOULDBLOCK;
              else
                {
+                 /* Tell others that we are upgrading.  */
+                 if (*user == LOCK_SH && atomic)
+                   box->type = LOCK_SH | LOCK_EX;
+
                  box->waiting = 1;
                  if (pthread_hurd_cond_wait_np (&box->wait, mut))
                    return EINTR;
                }
            }
+         if (*user == LOCK_SH)
+           {
+             assert (box->shcount == 1);
+             box->shcount = 0;
+           }
          box->type = LOCK_EX;
          *user = LOCK_EX;
        }
diff --git a/libmachdev/Makefile b/libmachdev/Makefile
index a47bf32..345c004 100644
--- a/libmachdev/Makefile
+++ b/libmachdev/Makefile
@@ -31,6 +31,3 @@ OBJS = $(SRCS:.c=.o) $(MIGSTUBS)
 MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
 
 include ../Makeconf
-
-$(libname).so.$(hurd-version):
-       echo "INPUT ( $(libname).a )" > $@
diff --git a/libmachdev/ds_routines.c b/libmachdev/ds_routines.c
index 6bd5a12..e9fbe94 100644
--- a/libmachdev/ds_routines.c
+++ b/libmachdev/ds_routines.c
@@ -87,52 +87,7 @@ boolean_t is_master_device (mach_port_t port);
  * What follows is the interface for the native Mach devices.
  */
 
-static inline mach_port_t
-mach_convert_device_to_port (mach_device_t device)
-{
-  if (device == NULL)
-    return MACH_PORT_NULL;
-
-  // TODO I have to somehow dereference it when it is called at the first time.
-  return ports_get_right (device);
-}
-
 /* Implementation of device interface */
-kern_return_t 
-ds_xxx_device_set_status (struct mach_device *device, dev_flavor_t flavor,
-                         dev_status_t status, size_t statu_cnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_get_status (struct mach_device *device, dev_flavor_t flavor,
-                         dev_status_t status, size_t *statuscnt)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_xxx_device_set_filter (struct mach_device *device, mach_port_t rec,
-                         int pri, filter_array_t filt, size_t len)
-{
-  return D_INVALID_OPERATION;
-}
-
-io_return_t
-ds_device_intr_register (mach_port_t master_port, int irq,
-                        int flags, int id, mach_port_t receive_port)
-{
-  return D_INVALID_OPERATION;
-}
-
-kern_return_t
-ds_device_intr_enable (mach_port_t master_port,
-                      int line, char status)
-{
-  return D_INVALID_OPERATION;
-}
-
 io_return_t
 ds_device_open (mach_port_t open_port, mach_port_t reply_port,
                mach_msg_type_name_t reply_port_type, dev_mode_t mode,
diff --git a/libmachdev/net.c b/libmachdev/net.c
index e04b558..220121a 100644
--- a/libmachdev/net.c
+++ b/libmachdev/net.c
@@ -104,8 +104,6 @@ static struct net_data *nd_head;
 
 extern struct device_emulation_ops linux_net_emulation_ops;
 
-static int print_packet_size = 1;
-
 static mach_msg_type_t header_type = 
 {
   MACH_MSG_TYPE_BYTE,
@@ -225,32 +223,25 @@ static void
 netif_rx_handle (char *data, int len, struct net_device *dev)
 {
   int pack_size;
-  net_rcv_msg_t net_msg;
+  struct net_rcv_msg net_msg;
   struct ether_header *eh;
   struct packet_header *ph;
   struct net_data *nd;
 
-  if (print_packet_size)
-    printf ("netif_rx: length %d\n", len);
-
   nd = search_nd(dev);
   assert (nd);
 
-  /* Allocate a kernel message buffer.  */
-  net_msg = malloc (sizeof (*net_msg));
-  if (!net_msg)
-    return;
-
   pack_size = len - sizeof (struct ethhdr);
   /* remember message sizes must be rounded up */
-  net_msg->msg_hdr.msgh_size =
+  net_msg.msg_hdr.msgh_size =
     (((mach_msg_size_t) (sizeof (struct net_rcv_msg)
-                        - sizeof net_msg->sent
+                        - sizeof net_msg.sent
+                        + sizeof (struct packet_header)
                         - NET_RCV_MAX + pack_size)) + 3) & ~3;
 
   /* Copy packet into message buffer.  */
-  eh = (struct ether_header *) (net_msg->header);
-  ph = (struct packet_header *) (net_msg->packet);
+  eh = (struct ether_header *) (net_msg.header);
+  ph = (struct packet_header *) (net_msg.packet);
   memcpy (eh, data, sizeof (struct ether_header));
   /* packet is prefixed with a struct packet_header,
      see include/device/net_status.h.  */
@@ -258,13 +249,12 @@ netif_rx_handle (char *data, int len, struct net_device 
*dev)
   ph->type = eh->h_proto;
   ph->length = pack_size + sizeof (struct packet_header);
 
-  net_msg->sent = FALSE; /* Mark packet as received.  */
+  net_msg.sent = FALSE; /* Mark packet as received.  */
 
-  net_msg->header_type = header_type;
-  net_msg->packet_type = packet_type;
-  net_msg->net_rcv_msg_packet_count = ph->length;
-  deliver_msg (net_msg, &nd->ifnet.port_list);
-  free (net_msg);
+  net_msg.header_type = header_type;
+  net_msg.packet_type = packet_type;
+  net_msg.net_rcv_msg_packet_count = ph->length;
+  deliver_msg (&net_msg, &nd->ifnet.port_list);
 }
 
 /* Mach device interface routines.  */
@@ -513,10 +503,10 @@ device_get_status (void *d, dev_flavor_t flavor, 
dev_status_t status,
 
   if (flavor == NET_FLAGS)
     {
-      if (*count != sizeof(short))
+      if (*count != 1)
        return D_INVALID_SIZE;
 
-      *(short *) status = netdev_flags (net->dev);
+      *(int *) status = netdev_flags (net->dev);
       return D_SUCCESS;
     }
 
diff --git a/libnetfs/dir-lookup.c b/libnetfs/dir-lookup.c
index 99a8746..77cbbbd 100644
--- a/libnetfs/dir-lookup.c
+++ b/libnetfs/dir-lookup.c
@@ -260,7 +260,7 @@ netfs_S_dir_lookup (struct protid *diruser,
                }
            }
 
-         boolean_t register_translator;
+         boolean_t register_translator = 0;
          if (! error)
            {
              dirport = ports_get_send_right (newpi);
@@ -297,6 +297,7 @@ netfs_S_dir_lookup (struct protid *diruser,
              if (register_translator)
                {
                  char *translator_path = strdupa (relpath);
+                 char *complete_path;
                  if (nextname != NULL)
                    {
                      /* This was not the last path component.
@@ -309,9 +310,17 @@ netfs_S_dir_lookup (struct protid *diruser,
                      translator_path[end - filename_start] = '\0';
                    }
 
+                 if (diruser->po->path == NULL)
+                     /* diruser is the root directory.  */
+                     complete_path = translator_path;
+                 else
+                     asprintf (&complete_path, "%s/%s", diruser->po->path, 
translator_path);
+
                  error = fshelp_set_active_translator (&newpi->pi,
-                                                       translator_path,
+                                                       complete_path,
                                                        np->transbox.active);
+                 if (complete_path != translator_path)
+                   free(complete_path);
                  if (error)
                    {
                      ports_port_deref (newpi);
diff --git a/libnetfs/mutations.h b/libnetfs/mutations.h
index e60a220..088d8a0 100644
--- a/libnetfs/mutations.h
+++ b/libnetfs/mutations.h
@@ -23,12 +23,15 @@
 #define IO_SELECT_REPLY_PORT
 
 #define FILE_INTRAN protid_t begin_using_protid_port (file_t)
+#define FILE_INTRAN_PAYLOAD protid_t begin_using_protid_payload
 #define FILE_DESTRUCTOR end_using_protid_port (protid_t)
 
 #define IO_INTRAN protid_t begin_using_protid_port (io_t)
+#define IO_INTRAN_PAYLOAD protid_t begin_using_protid_payload
 #define IO_DESTRUCTOR end_using_protid_port (protid_t)
 
 #define FSYS_INTRAN control_t begin_using_control_port (fsys_t)
+#define FSYS_INTRAN_PAYLOAD control_t begin_using_control_payload
 #define FSYS_DESTRUCTOR end_using_control_port (control_t)
 
 #define FILE_IMPORTS import "libnetfs/netfs.h"; import "libnetfs/priv.h";
diff --git a/libnetfs/priv.h b/libnetfs/priv.h
index ba31080..3c5bcd4 100644
--- a/libnetfs/priv.h
+++ b/libnetfs/priv.h
@@ -31,6 +31,12 @@ begin_using_protid_port (file_t port)
   return ports_lookup_port (netfs_port_bucket, port, netfs_protid_class);
 }
 
+static inline struct protid * __attribute__ ((unused))
+begin_using_protid_payload (unsigned long payload)
+{
+  return ports_lookup_payload (netfs_port_bucket, payload, netfs_protid_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_protid_port (struct protid *cred)
 {
@@ -44,6 +50,12 @@ begin_using_control_port (fsys_t port)
   return ports_lookup_port (netfs_port_bucket, port, netfs_control_class);
 }
 
+static inline struct netfs_control * __attribute__ ((unused))
+begin_using_control_payload (unsigned long payload)
+{
+  return ports_lookup_payload (netfs_port_bucket, payload, 
netfs_control_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_control_port (struct netfs_control *cred)
 {
diff --git a/libpager/demuxer.c b/libpager/demuxer.c
index efdf285..a06c4bf 100644
--- a/libpager/demuxer.c
+++ b/libpager/demuxer.c
@@ -47,10 +47,16 @@ struct request
 {
   struct item item;
   mig_routine_t routine;
-  mach_msg_header_t *inp;
-  mach_msg_header_t *outp;
 };
 
+/* A struct request object is immediately followed by the received
+   message.  */
+static inline mach_msg_header_t *
+request_inp (const struct request *r)
+{
+  return (mach_msg_header_t *) ((char *) r + sizeof *r);
+}
+
 /* A worker.  */
 struct worker
 {
@@ -81,10 +87,6 @@ pager_demuxer (struct requests *requests,
 {
   error_t err = MIG_NO_REPLY;
 
-  /* The maximum size of the reply is 2048 bytes.  See the MIG source
-     for details.  */
-  const mach_msg_size_t max_size = 2048;
-
   mig_routine_t routine;
   if (! ((routine = _pager_seqnos_memory_object_server_routine (inp)) ||
         (routine = _pager_seqnos_notify_server_routine (inp))))
@@ -94,7 +96,7 @@ pager_demuxer (struct requests *requests,
   mach_msg_size_t padded_size = (inp->msgh_size + MASK) & ~MASK;
 #undef MASK
 
-  struct request *r = malloc (sizeof *r + padded_size + max_size);
+  struct request *r = malloc (sizeof *r + padded_size);
   if (r == NULL)
     {
       err = ENOMEM;
@@ -102,11 +104,7 @@ pager_demuxer (struct requests *requests,
     }
 
   r->routine = routine;
-  r->inp = (mach_msg_header_t *) ((char *) r + sizeof *r);
-  memcpy (r->inp, inp, inp->msgh_size);
-
-  r->outp = (mach_msg_header_t *) ((char *) r + sizeof *r + padded_size);
-  memcpy (r->outp, outp, sizeof *outp);
+  memcpy (request_inp (r), inp, inp->msgh_size);
 
   pthread_mutex_lock (&requests->lock);
 
@@ -126,6 +124,37 @@ pager_demuxer (struct requests *requests,
   return TRUE;
 }
 
+/* XXX: The libc should provide this function.  */
+static void
+mig_reply_setup (
+       const mach_msg_header_t *in,
+       mach_msg_header_t       *out)
+{
+      static const mach_msg_type_t RetCodeType = {
+               /* msgt_name = */               MACH_MSG_TYPE_INTEGER_32,
+               /* msgt_size = */               32,
+               /* msgt_number = */             1,
+               /* msgt_inline = */             TRUE,
+               /* msgt_longform = */           FALSE,
+               /* msgt_deallocate = */         FALSE,
+               /* msgt_unused = */             0
+       };
+
+#define        InP     (in)
+#define        OutP    ((mig_reply_header_t *) out)
+      OutP->Head.msgh_bits =
+       MACH_MSGH_BITS(MACH_MSGH_BITS_REMOTE(InP->msgh_bits), 0);
+      OutP->Head.msgh_size = sizeof *OutP;
+      OutP->Head.msgh_remote_port = InP->msgh_remote_port;
+      OutP->Head.msgh_local_port = MACH_PORT_NULL;
+      OutP->Head.msgh_seqno = 0;
+      OutP->Head.msgh_id = InP->msgh_id + 100;
+      OutP->RetCodeType = RetCodeType;
+      OutP->RetCode = MIG_BAD_ID;
+#undef InP
+#undef OutP
+}
+
 /* Consumes requests from the queue.  */
 static void *
 worker_func (void *arg)
@@ -133,6 +162,7 @@ worker_func (void *arg)
   struct worker *self = (struct worker *) arg;
   struct requests *requests = self->requests;
   struct request *r = NULL;
+  mig_reply_header_t reply_msg;
 
   while (1)
     {
@@ -165,7 +195,7 @@ worker_func (void *arg)
 
       for (i = 0; i < WORKER_COUNT; i++)
        if (requests->workers[i].tag
-           == (unsigned long) r->inp->msgh_local_port)
+           == (unsigned long) request_inp (r)->msgh_local_port)
          {
            /* Some other thread is working on that object.  Delegate
               the request to that worker.  */
@@ -174,18 +204,20 @@ worker_func (void *arg)
          }
 
       /* Claim responsibility for this object by setting our tag.  */
-      self->tag = (unsigned long) r->inp->msgh_local_port;
+      self->tag = (unsigned long) request_inp (r)->msgh_local_port;
 
     got_one:
       pthread_mutex_unlock (&requests->lock);
 
+      mig_reply_setup (request_inp (r), (mach_msg_header_t *) &reply_msg);
+
       /* Call the server routine.  */
-      (*r->routine) (r->inp, r->outp);
+      (*r->routine) (request_inp (r), (mach_msg_header_t *) &reply_msg);
 
       /* What follows is basically the second part of
         mach_msg_server_timeout.  */
-      mig_reply_header_t *request = (mig_reply_header_t *) r->inp;
-      mig_reply_header_t *reply = (mig_reply_header_t *) r->outp;
+      mig_reply_header_t *request = (mig_reply_header_t *) request_inp (r);
+      mig_reply_header_t *reply = &reply_msg;
 
       switch (reply->RetCode)
        {
diff --git a/libpager/mig-decls.h b/libpager/mig-decls.h
index 0c7b402..7e6b64f 100644
--- a/libpager/mig-decls.h
+++ b/libpager/mig-decls.h
@@ -32,6 +32,12 @@ begin_using_pager (mach_port_t port)
   return ports_lookup_port (0, port, _pager_class);
 }
 
+static inline struct pager * __attribute__ ((unused))
+begin_using_pager_payload (unsigned long payload)
+{
+  return ports_lookup_payload (0, payload, _pager_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_pager (struct pager *p)
 {
diff --git a/libpager/mig-mutate.h b/libpager/mig-mutate.h
index 9e9065f..c4f30ce 100644
--- a/libpager/mig-mutate.h
+++ b/libpager/mig-mutate.h
@@ -18,11 +18,14 @@
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #define MEMORY_OBJECT_INTRAN pager_t begin_using_pager (memory_object_t)
+#define MEMORY_OBJECT_INTRAN_PAYLOAD pager_t begin_using_pager_payload
 #define MEMORY_OBJECT_DESTRUCTOR end_using_pager (pager_t)
 #define MEMORY_OBJECT_IMPORTS import "mig-decls.h";
 
 #define NOTIFY_INTRAN                                          \
   port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD                                  \
+  port_info_t begin_using_port_info_payload
 #define NOTIFY_DESTRUCTOR                                      \
   end_using_port_info (port_info_t)
 #define NOTIFY_IMPORTS                                         \
diff --git a/libpager/pager-memcpy.c b/libpager/pager-memcpy.c
index f2be558..7bdc248 100644
--- a/libpager/pager-memcpy.c
+++ b/libpager/pager-memcpy.c
@@ -64,6 +64,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj,
          assert (window_size >= VMCOPY_BETTER_THAN_MEMCPY);
          assert ((window_size & (vm_page_size - 1)) == 0);
          
+         window = 0;
          err = vm_map (mach_task_self (), &window, window_size, 0, 1,
                        memobj, offset, 0, prot, prot, VM_INHERIT_NONE);
          if (err)
@@ -110,6 +111,7 @@ pager_memcpy (struct pager *pager, memory_object_t memobj,
                  window_size = round_page (pageoff + to_copy);
                }
 
+             window = 0;
              err = vm_map (mach_task_self (), &window, window_size, 0, 1,
                            memobj, offset - pageoff, 0,
                            prot, prot, VM_INHERIT_NONE);
diff --git a/libports/Makefile b/libports/Makefile
index 30da1c1..f49cb9f 100644
--- a/libports/Makefile
+++ b/libports/Makefile
@@ -36,7 +36,7 @@ SRCS = create-bucket.c create-class.c \
  interrupt-operation.c interrupt-on-notify.c interrupt-notified-rpcs.c \
  dead-name.c create-port.c import-port.c default-uninhibitable-rpcs.c \
  claim-right.c transfer-right.c create-port-noinstall.c create-internal.c \
- interrupted.c
+ interrupted.c extern-inline.c
 
 installhdrs = ports.h
 
diff --git a/random/mig-mutate.h b/libports/extern-inline.c
similarity index 75%
copy from random/mig-mutate.h
copy to libports/extern-inline.c
index dab89e5..fbc9e53 100644
--- a/random/mig-mutate.h
+++ b/libports/extern-inline.c
@@ -1,6 +1,7 @@
-/*
+/* Run time callable functions for extern inlines.
    Copyright (C) 2014 Free Software Foundation, Inc.
-   Written by Justus Winter.
+
+   Written by Justus Winter <address@hidden>
 
    This file is part of the GNU Hurd.
 
@@ -17,9 +18,5 @@
    You should have received a copy of the GNU General Public License
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#define STARTUP_INTRAN                                         \
-  port_info_t begin_using_startup_port (mach_port_t)
-#define STARTUP_DESTRUCTOR                                     \
-  end_using_startup (port_info_t)
-#define STARTUP_IMPORTS                                                \
-  import "mig-decls.h";
+#define PORTS_DEFINE_EI
+#include "ports.h"
diff --git a/libports/mig-decls.h b/libports/mig-decls.h
index f8c4f15..c88ff26 100644
--- a/libports/mig-decls.h
+++ b/libports/mig-decls.h
@@ -30,6 +30,12 @@ begin_using_port_info_port (mach_port_t port)
   return ports_lookup_port (0, port, 0);
 }
 
+static inline struct port_info * __attribute__ ((unused))
+begin_using_port_info_payload (unsigned long payload)
+{
+  return ports_lookup_payload (0, payload, 0);
+}
+
 static inline void __attribute__ ((unused))
 end_using_port_info (struct port_info *p)
 {
diff --git a/libports/mig-mutate.h b/libports/mig-mutate.h
index 4c011b6..1c96fea 100644
--- a/libports/mig-mutate.h
+++ b/libports/mig-mutate.h
@@ -19,6 +19,8 @@
 
 #define NOTIFY_INTRAN                                          \
   port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD                                  \
+  port_info_t begin_using_port_info_payload
 #define NOTIFY_DESTRUCTOR                                      \
   end_using_port_info (port_info_t)
 #define NOTIFY_IMPORTS                                         \
@@ -26,6 +28,8 @@
 
 #define INTERRUPT_INTRAN                                       \
   port_info_t begin_using_port_info_port (mach_port_t)
+#define INTERRUPT_INTRAN_PAYLOAD                               \
+  port_info_t begin_using_port_info_payload
 #define INTERRUPT_DESTRUCTOR                                   \
   end_using_port_info (port_info_t)
 #define INTERRUPT_IMPORTS                                      \
diff --git a/libports/ports.h b/libports/ports.h
index 652edb8..a625b47 100644
--- a/libports/ports.h
+++ b/libports/ports.h
@@ -29,6 +29,12 @@
 #include <pthread.h>
 #include <refcount.h>
 
+#ifdef PORTS_DEFINE_EI
+#define PORTS_EI
+#else
+#define PORTS_EI __extern_inline
+#endif
+
 /* These are global values for common flags used in the various structures.
    Not all of these are meaningful in all flag fields.  */
 #define PORTS_INHIBITED                0x0100 /* block RPC's */
@@ -234,6 +240,53 @@ mach_port_t ports_get_send_right (void *port);
 void *ports_lookup_port (struct port_bucket *bucket,
                         mach_port_t port, struct port_class *class);
 
+/* Like ports_lookup_port, but uses PAYLOAD to look up the object.  If
+   this function is used, PAYLOAD must be a pointer to the port
+   structure.  */
+extern void *ports_lookup_payload (struct port_bucket *bucket,
+                                  unsigned long payload,
+                                  struct port_class *class);
+
+/* This returns the ports name.  This function can be used as
+   intranpayload function turning payloads back into port names.  If
+   this function is used, PAYLOAD must be a pointer to the port
+   structure.  */
+extern mach_port_t ports_payload_get_name (unsigned int payload);
+
+#if defined(__USE_EXTERN_INLINES) || defined(PORTS_DEFINE_EI)
+
+PORTS_EI void *
+ports_lookup_payload (struct port_bucket *bucket,
+                     unsigned long payload,
+                     struct port_class *class)
+{
+  struct port_info *pi = (struct port_info *) payload;
+
+  if (pi && bucket && pi->bucket != bucket)
+    pi = NULL;
+
+  if (pi && class && pi->class != class)
+    pi = NULL;
+
+  if (pi)
+    refcounts_unsafe_ref (&pi->refcounts, NULL);
+
+  return pi;
+}
+
+PORTS_EI mach_port_t
+ports_payload_get_name (unsigned int payload)
+{
+  struct port_info *pi = (struct port_info *) payload;
+
+  if (pi)
+    return pi->port_right;
+
+  return MACH_PORT_NULL;
+}
+
+#endif /* Use extern inlines.  */
+
 /* Allocate another reference to PORT. */
 void ports_port_ref (void *port);
 
diff --git a/libshouldbeinlibc/Makefile b/libshouldbeinlibc/Makefile
index 14a7939..633d60e 100644
--- a/libshouldbeinlibc/Makefile
+++ b/libshouldbeinlibc/Makefile
@@ -27,9 +27,13 @@ SRCS = termsize.c timefmt.c exec-reauth.c maptime-funcs.c \
        idvec-impgids.c idvec-verify.c idvec-rep.c \
        ugids.c ugids-argp.c ugids-rep.c ugids-verify.c ugids-subtract.c \
        ugids-auth.c ugids-xinl.c ugids-merge.c ugids-imply.c ugids-posix.c \
-       ugids-verify-auth.c nullauth.c
+       ugids-verify-auth.c nullauth.c \
+       refcount.c \
+
 installhdrs = idvec.h timefmt.h maptime.h \
-             wire.h portinfo.h portxlate.h cacheq.h ugids.h nullauth.h
+             wire.h portinfo.h portxlate.h cacheq.h ugids.h nullauth.h \
+             refcount.h \
+
 installhdrsubdir = .
 
 OBJS = $(SRCS:.c=.o)
diff --git a/random/mig-mutate.h b/libshouldbeinlibc/refcount.c
similarity index 75%
rename from random/mig-mutate.h
rename to libshouldbeinlibc/refcount.c
index dab89e5..17e01c5 100644
--- a/random/mig-mutate.h
+++ b/libshouldbeinlibc/refcount.c
@@ -1,6 +1,8 @@
-/*
+/* Lock-less reference counting primitives
+
    Copyright (C) 2014 Free Software Foundation, Inc.
-   Written by Justus Winter.
+
+   Written by Justus Winter <address@hidden>
 
    This file is part of the GNU Hurd.
 
@@ -17,9 +19,5 @@
    You should have received a copy of the GNU General Public License
    along with the GNU Hurd.  If not, see <http://www.gnu.org/licenses/>.  */
 
-#define STARTUP_INTRAN                                         \
-  port_info_t begin_using_startup_port (mach_port_t)
-#define STARTUP_DESTRUCTOR                                     \
-  end_using_startup (port_info_t)
-#define STARTUP_IMPORTS                                                \
-  import "mig-decls.h";
+#define REFCOUNT_DEFINE_EI
+#include "refcount.h"
diff --git a/include/refcount.h b/libshouldbeinlibc/refcount.h
similarity index 96%
rename from include/refcount.h
rename to libshouldbeinlibc/refcount.h
index ebde42d..e8b0f5b 100644
--- a/include/refcount.h
+++ b/libshouldbeinlibc/refcount.h
@@ -22,6 +22,12 @@
 #ifndef _HURD_REFCOUNT_H_
 #define _HURD_REFCOUNT_H_
 
+#ifdef REFCOUNT_DEFINE_EI
+#define REFCOUNT_EI
+#else
+#define REFCOUNT_EI __extern_inline
+#endif
+
 #include <assert.h>
 #include <limits.h>
 #include <stdint.h>
@@ -32,7 +38,7 @@
 typedef unsigned int refcount_t;
 
 /* Initialize REF with REFERENCES.  REFERENCES must not be zero.  */
-static inline void
+REFCOUNT_EI void
 refcount_init (refcount_t *ref, unsigned int references)
 {
   assert (references > 0 || !"references must not be zero!");
@@ -46,7 +52,7 @@ refcount_init (refcount_t *ref, unsigned int references)
    This is the unsafe version of refcount_ref.  refcount_ref also
    checks for use-after-free errors.  When in doubt, use that one
    instead.  */
-static inline unsigned int
+REFCOUNT_EI unsigned int
 refcount_unsafe_ref (refcount_t *ref)
 {
   unsigned int r;
@@ -58,7 +64,7 @@ refcount_unsafe_ref (refcount_t *ref)
 /* Increment REF.  Return the result of the operation.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
-static inline unsigned int
+REFCOUNT_EI unsigned int
 refcount_ref (refcount_t *ref)
 {
   unsigned int r;
@@ -70,7 +76,7 @@ refcount_ref (refcount_t *ref)
 /* Decrement REF.  Return the result of the operation.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
-static inline unsigned int
+REFCOUNT_EI unsigned int
 refcount_deref (refcount_t *ref)
 {
   unsigned int r;
@@ -81,7 +87,7 @@ refcount_deref (refcount_t *ref)
 
 /* Return REF.  This function uses atomic operations.  It is not
    required to serialize calls to this function.  */
-static inline unsigned int
+REFCOUNT_EI unsigned int
 refcount_references (refcount_t *ref)
 {
   return __atomic_load_n (ref, __ATOMIC_RELAXED);
@@ -120,7 +126,7 @@ union _references {
 
 /* Initialize REF with HARD and WEAK references.  HARD and WEAK must
    not both be zero.  */
-static inline void
+REFCOUNT_EI void
 refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t weak)
 {
   assert ((hard != 0 || weak != 0) || !"references must not both be zero!");
@@ -135,7 +141,7 @@ refcounts_init (refcounts_t *ref, uint32_t hard, uint32_t 
weak)
    This is the unsafe version of refcounts_ref.  refcounts_ref also
    checks for use-after-free errors.  When in doubt, use that one
    instead.  */
-static inline void
+REFCOUNT_EI void
 refcounts_unsafe_ref (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .hard = 1 } };
@@ -150,7 +156,7 @@ refcounts_unsafe_ref (refcounts_t *ref, struct references 
*result)
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
    function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_ref (refcounts_t *ref, struct references *result)
 {
   struct references r;
@@ -165,7 +171,7 @@ refcounts_ref (refcounts_t *ref, struct references *result)
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
    function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_deref (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .hard = 1 } };
@@ -180,7 +186,7 @@ refcounts_deref (refcounts_t *ref, struct references 
*result)
    NULL, the result of the operation is written there.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_promote (refcounts_t *ref, struct references *result)
 {
   /* To promote a weak reference, we need to atomically subtract 1
@@ -211,7 +217,7 @@ refcounts_promote (refcounts_t *ref, struct references 
*result)
    NULL, the result of the operation is written there.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_demote (refcounts_t *ref, struct references *result)
 {
   /* To demote a hard reference, we need to atomically subtract 1 from
@@ -243,7 +249,7 @@ refcounts_demote (refcounts_t *ref, struct references 
*result)
    This is the unsafe version of refcounts_ref_weak.
    refcounts_ref_weak also checks for use-after-free errors.  When in
    doubt, use that one instead.  */
-static inline void
+REFCOUNT_EI void
 refcounts_unsafe_ref_weak (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .weak = 1 } };
@@ -258,7 +264,7 @@ refcounts_unsafe_ref_weak (refcounts_t *ref, struct 
references *result)
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
    function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_ref_weak (refcounts_t *ref, struct references *result)
 {
   struct references r;
@@ -273,7 +279,7 @@ refcounts_ref_weak (refcounts_t *ref, struct references 
*result)
    the result of the operation is written there.  This function uses
    atomic operations.  It is not required to serialize calls to this
    function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_deref_weak (refcounts_t *ref, struct references *result)
 {
   const union _references op = { .references = { .weak = 1 } };
@@ -287,7 +293,7 @@ refcounts_deref_weak (refcounts_t *ref, struct references 
*result)
 /* Store the current reference counts of REF in RESULT.  This function
    uses atomic operations.  It is not required to serialize calls to
    this function.  */
-static inline void
+REFCOUNT_EI void
 refcounts_references (refcounts_t *ref, struct references *result)
 {
   union _references r;
@@ -298,7 +304,7 @@ refcounts_references (refcounts_t *ref, struct references 
*result)
 /* Return the hard reference count of REF.  This function uses atomic
    operations.  It is not required to serialize calls to this
    function.  */
-static inline uint32_t
+REFCOUNT_EI uint32_t
 refcounts_hard_references (refcounts_t *ref)
 {
   struct references result;
@@ -309,7 +315,7 @@ refcounts_hard_references (refcounts_t *ref)
 /* Return the weak reference count of REF.  This function uses atomic
    operations.  It is not required to serialize calls to this
    function.  */
-static inline uint32_t
+REFCOUNT_EI uint32_t
 refcounts_weak_references (refcounts_t *ref)
 {
   struct references result;
diff --git a/libstore/memobj.c b/libstore/memobj.c
index 0d5c816..cc6c7ca 100644
--- a/libstore/memobj.c
+++ b/libstore/memobj.c
@@ -133,6 +133,7 @@ memobj_read (struct store *store,
   if (((size_t) addr & (vm_page_size - 1)) == 0)
     {
       *len = amount;
+      *buf = 0;
       return vm_map (mach_task_self (), (vm_address_t *) buf, amount,
                     0, 1, store->port, addr << store->log2_block_size, 0,
                     VM_PROT_READ, VM_PROT_ALL, VM_INHERIT_NONE);
diff --git a/libtrivfs/mig-decls.h b/libtrivfs/mig-decls.h
index 2baaee8..13a9eb7 100644
--- a/libtrivfs/mig-decls.h
+++ b/libtrivfs/mig-decls.h
@@ -61,6 +61,35 @@ trivfs_begin_using_protid (mach_port_t port)
     return ports_lookup_port (0, port, trivfs_dynamic_protid_port_classes[0]);
 }
 
+static inline struct trivfs_protid * __attribute__ ((unused))
+trivfs_begin_using_protid_payload (unsigned long payload)
+{
+  if (trivfs_protid_nportclasses + trivfs_num_dynamic_protid_port_classes > 1)
+    {
+      struct port_info *pi = ports_lookup_payload (NULL, payload, NULL);
+      int i;
+
+      if (pi)
+       {
+         for (i = 0; i < trivfs_protid_nportclasses; i++)
+           if (pi->class == trivfs_protid_portclasses[i])
+             return (struct trivfs_protid *) pi;
+         for (i = 0; i < trivfs_num_dynamic_protid_port_classes; i++)
+           if (pi->class == trivfs_dynamic_protid_port_classes[i])
+             return (struct trivfs_protid *) pi;
+         ports_port_deref (pi);
+       }
+
+      return NULL;
+    }
+  else if (trivfs_protid_nportclasses == 1)
+    return ports_lookup_payload (NULL, payload,
+                                trivfs_protid_portclasses[0]);
+  else
+    return ports_lookup_payload (NULL, payload,
+                                trivfs_dynamic_protid_port_classes[0]);
+}
+
 static inline void __attribute__ ((unused))
 trivfs_end_using_protid (struct trivfs_protid *cred)
 {
@@ -95,6 +124,35 @@ trivfs_begin_using_control (mach_port_t port)
     return ports_lookup_port (0, port, trivfs_dynamic_control_port_classes[0]);
 }
 
+static inline struct trivfs_control * __attribute__ ((unused))
+trivfs_begin_using_control_payload (unsigned long payload)
+{
+  if (trivfs_cntl_nportclasses + trivfs_num_dynamic_control_port_classes > 1)
+    {
+      struct port_info *pi = ports_lookup_payload (NULL, payload, NULL);
+      int i;
+
+      if (pi)
+       {
+         for (i = 0; i < trivfs_cntl_nportclasses; i++)
+           if (pi->class == trivfs_cntl_portclasses[i])
+             return (struct trivfs_control *) pi;
+         for (i = 0; i < trivfs_num_dynamic_control_port_classes; i++)
+           if (pi->class == trivfs_dynamic_control_port_classes[i])
+             return (struct trivfs_control *) pi;
+         ports_port_deref (pi);
+       }
+
+      return NULL;
+    }
+  else if (trivfs_cntl_nportclasses == 1)
+    return ports_lookup_payload (NULL, payload,
+                                trivfs_cntl_portclasses[0]);
+  else
+    return ports_lookup_payload (NULL, payload,
+                                trivfs_dynamic_control_port_classes[0]);
+}
+
 static inline void __attribute__ ((unused))
 trivfs_end_using_control (struct trivfs_control *cred)
 {
diff --git a/libtrivfs/mig-mutate.h b/libtrivfs/mig-mutate.h
index cc15d38..dcbebf6 100644
--- a/libtrivfs/mig-mutate.h
+++ b/libtrivfs/mig-mutate.h
@@ -20,13 +20,16 @@
 #define REPLY_PORTS
 
 #define FILE_INTRAN trivfs_protid_t trivfs_begin_using_protid (file_t)
+#define FILE_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload
 #define FILE_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
 #define FILE_IMPORTS import "libtrivfs/mig-decls.h";
 
 #define IO_INTRAN trivfs_protid_t trivfs_begin_using_protid (io_t)
+#define IO_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload
 #define IO_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
 #define IO_IMPORTS import "libtrivfs/mig-decls.h";
 
 #define FSYS_INTRAN trivfs_control_t trivfs_begin_using_control (fsys_t)
+#define FSYS_INTRAN_PAYLOAD trivfs_control_t trivfs_begin_using_control_payload
 #define FSYS_DESTRUCTOR trivfs_end_using_control (trivfs_control_t)
 #define FSYS_IMPORTS import "libtrivfs/mig-decls.h";
diff --git a/mach-defpager/kalloc.c b/mach-defpager/kalloc.c
index 2f8f002..ef844ac 100644
--- a/mach-defpager/kalloc.c
+++ b/mach-defpager/kalloc.c
@@ -58,7 +58,7 @@ void (*__MALLOC_HOOK_VOLATILE __malloc_initialize_hook) 
(void) = init_hook;
  *     next highest power of 2.
  */
 vm_size_t      kalloc_max;             /* max before we use vm_allocate */
-#define                MINSIZE 4               /* minimum allocation size */
+#define                MINSIZE sizeof(vm_offset_t)             /* minimum 
allocation size */
 
 struct free_list {
        pthread_spinlock_t      lock;
@@ -99,8 +99,8 @@ void kalloc_init(void)
         * 16Kbytes, whichever is less.
         */
 
-       if (vm_page_size > 16*1024)
-               kalloc_max = 16*1024;
+       if (vm_page_size > (MINSIZE << (KLIST_MAX-1)))
+               kalloc_max = (MINSIZE << (KLIST_MAX-1));
        else
                kalloc_max = vm_page_size;
 
@@ -197,7 +197,7 @@ void *kalloc(vm_size_t size)
        /* compute the size of the block that we will actually allocate */
 
        allocsize = size;
-       if (size < kalloc_max) {
+       if (size <= kalloc_max) {
            allocsize = MINSIZE;
            fl = kfree_list;
            while (allocsize < size) {
@@ -211,7 +211,7 @@ void *kalloc(vm_size_t size)
         * and allocate.
         */
 
-       if (allocsize < kalloc_max) {
+       if (allocsize <= kalloc_max) {
            pthread_spin_lock(&fl->lock);
            if ((addr = fl->head) != 0) {
                fl->head = *(vm_offset_t *)addr;
@@ -241,7 +241,7 @@ kfree(      void *data,
        struct free_list *fl;
 
        freesize = size;
-       if (size < kalloc_max) {
+       if (size <= kalloc_max) {
            freesize = MINSIZE;
            fl = kfree_list;
            while (freesize < size) {
@@ -250,7 +250,7 @@ kfree(      void *data,
            }
        }
 
-       if (freesize < kalloc_max) {
+       if (freesize <= kalloc_max) {
            pthread_spin_lock(&fl->lock);
            *(vm_offset_t *)data = fl->head;
            fl->head = (vm_offset_t) data;
diff --git a/pfinet/ethernet.c b/pfinet/ethernet.c
index 053fd1b..1678243 100644
--- a/pfinet/ethernet.c
+++ b/pfinet/ethernet.c
@@ -116,12 +116,30 @@ ethernet_demuxer (mach_msg_header_t *inp,
   int datalen;
   struct ether_device *edev;
   struct device *dev = 0;
+  mach_port_t local_port;
 
   if (inp->msgh_id != NET_RCV_MSG_ID)
     return 0;
 
+  if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) ==
+      MACH_MSG_TYPE_PROTECTED_PAYLOAD)
+    {
+      struct port_info *pi = ports_lookup_payload (NULL,
+                                                  inp->msgh_protected_payload,
+                                                  NULL);
+      if (pi)
+       {
+         local_port = pi->port_right;
+         ports_port_deref (pi);
+       }
+      else
+       local_port = MACH_PORT_NULL;
+    }
+  else
+    local_port = inp->msgh_local_port;
+
   for (edev = ether_dev; edev; edev = edev->next)
-    if (inp->msgh_local_port == edev->readptname)
+    if (local_port == edev->readptname)
       dev = &edev->dev;
 
   if (! dev)
diff --git a/pfinet/main.c b/pfinet/main.c
index d52d9a3..8716fdb 100644
--- a/pfinet/main.c
+++ b/pfinet/main.c
@@ -24,11 +24,11 @@
 #include <arpa/inet.h>
 #include <error.h>
 #include <argp.h>
+#include <hurd/paths.h>
 #include <hurd/startup.h>
 #include <string.h>
 #include <fcntl.h>
 #include <version.h>
-#include <pids.h>
 
 /* Include Hurd's errno.h file, but don't include glue-include/linux/errno.h,
    since it #undef's the errno macro. */
@@ -86,8 +86,16 @@ pfinet_demuxer (mach_msg_header_t *inp,
 
   /* We have several classes in one bucket, which need to be demuxed
      differently.  */
-  pi = ports_lookup_port(pfinet_bucket, inp->msgh_local_port, 
socketport_class);
-  
+  if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) ==
+      MACH_MSG_TYPE_PROTECTED_PAYLOAD)
+    pi = ports_lookup_payload (pfinet_bucket,
+                              inp->msgh_protected_payload,
+                              socketport_class);
+  else
+    pi = ports_lookup_port (pfinet_bucket,
+                           inp->msgh_local_port,
+                           socketport_class);
+
   if (pi)
     {
       ports_port_deref (pi);
@@ -154,7 +162,6 @@ arrange_shutdown_notification ()
 {
   error_t err;
   mach_port_t initport, notify;
-  process_t procserver;
   struct port_info *pi;
 
   shutdown_notify_class = ports_create_class (0, 0);
@@ -169,13 +176,8 @@ arrange_shutdown_notification ()
   if (err)
     return;
 
-  procserver = getproc ();
-  if (!procserver)
-    return;
-
-  err = proc_getmsgport (procserver, HURD_PID_STARTUP, &initport);
-  mach_port_deallocate (mach_task_self (), procserver);
-  if (err)
+  initport = file_name_lookup (_SERVERS_STARTUP, 0, 0);
+  if (initport == MACH_PORT_NULL)
     return;
 
   notify = ports_get_send_right (pi);
diff --git a/pfinet/mig-decls.h b/pfinet/mig-decls.h
index ec8fb23..67bcbfc 100644
--- a/pfinet/mig-decls.h
+++ b/pfinet/mig-decls.h
@@ -32,6 +32,12 @@ begin_using_socket_port (mach_port_t port)
   return ports_lookup_port (pfinet_bucket, port, socketport_class);
 }
 
+static inline struct sock_user * __attribute__ ((unused))
+begin_using_socket_payload (unsigned long payload)
+{
+  return ports_lookup_payload (pfinet_bucket, payload, socketport_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_socket_port (struct sock_user *user)
 {
@@ -45,6 +51,12 @@ begin_using_sockaddr_port (mach_port_t port)
   return ports_lookup_port (pfinet_bucket, port, addrport_class);
 }
 
+static inline struct sock_addr * __attribute__ ((unused))
+begin_using_sockaddr_payload (unsigned long payload)
+{
+  return ports_lookup_payload (pfinet_bucket, payload, addrport_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_sockaddr_port (struct sock_addr *addr)
 {
diff --git a/pfinet/mig-mutate.h b/pfinet/mig-mutate.h
index 0a1eeb8..2bc385b 100644
--- a/pfinet/mig-mutate.h
+++ b/pfinet/mig-mutate.h
@@ -23,18 +23,22 @@
 #define IO_SELECT_REPLY_PORT
 
 #define IO_INTRAN sock_user_t begin_using_socket_port (io_t)
+#define IO_INTRAN_PAYLOAD sock_user_t begin_using_socket_payload
 #define IO_DESTRUCTOR end_using_socket_port (sock_user_t)
 #define IO_IMPORTS import "mig-decls.h";
 #define IIOCTL_IMPORTS import "mig-decls.h";
 
 #define SOCKET_INTRAN sock_user_t begin_using_socket_port (socket_t)
+#define SOCKET_INTRAN_PAYLOAD sock_user_t begin_using_socket_payload
 #define SOCKET_DESTRUCTOR end_using_socket_port (sock_user_t)
 #define SOCKET_IMPORTS                         \
   import "mig-decls.h";                                \
   import "../libtrivfs/mig-decls.h";           \
 
 #define ADDRPORT_INTRAN sock_addr_t begin_using_sockaddr_port (addr_port_t)
+#define ADDRPORT_INTRAN_PAYLOAD sock_addr_t begin_using_sockaddr_payload
 #define ADDRPORT_DESTRUCTOR end_using_sockaddr_port (sock_addr_t)
 
 #define PF_INTRAN trivfs_protid_t trivfs_begin_using_protid (pf_t)
+#define PF_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload
 #define PF_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
diff --git a/pflocal/mig-decls.h b/pflocal/mig-decls.h
index 983de9d..b1da797 100644
--- a/pflocal/mig-decls.h
+++ b/pflocal/mig-decls.h
@@ -36,6 +36,12 @@ begin_using_sock_user_port(mach_port_t port)
   return (sock_user_t)ports_lookup_port (0, port, sock_user_port_class);
 }
 
+static inline sock_user_t __attribute__ ((unused))
+begin_using_sock_user_payload (unsigned long payload)
+{
+  return ports_lookup_payload (NULL, payload, sock_user_port_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_sock_user_port (sock_user_t sock_user)
 {
@@ -49,6 +55,12 @@ begin_using_addr_port(mach_port_t port)
   return (addr_t)ports_lookup_port (0, port, addr_port_class);
 }
 
+static inline addr_t __attribute__ ((unused))
+begin_using_addr_payload (unsigned long payload)
+{
+  return ports_lookup_port (NULL, payload, addr_port_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_addr_port (addr_t addr)
 {
diff --git a/pflocal/mig-mutate.h b/pflocal/mig-mutate.h
index b149473..238c806 100644
--- a/pflocal/mig-mutate.h
+++ b/pflocal/mig-mutate.h
@@ -21,13 +21,16 @@
 #define IO_SELECT_REPLY_PORT
 
 #define IO_INTRAN sock_user_t begin_using_sock_user_port (io_t)
+#define IO_INTRAN_PAYLOAD sock_user_t begin_using_sock_user_payload
 #define IO_DESTRUCTOR end_using_sock_user_port (sock_user_t)
 
 #define IO_IMPORTS import "mig-decls.h";
 
 #define SOCKET_INTRAN sock_user_t begin_using_sock_user_port (socket_t)
+#define SOCKET_INTRAN_PAYLOAD sock_user_t begin_using_sock_user_payload
 #define SOCKET_DESTRUCTOR end_using_sock_user_port (sock_user_t)
 #define ADDRPORT_INTRAN addr_t begin_using_addr_port (addr_port_t)
+#define ADDRPORT_INTRAN_PAYLOAD addr_t begin_using_addr_payload
 #define ADDRPORT_DESTRUCTOR end_using_addr_port (addr_t)
 
 #define SOCKET_IMPORTS import "mig-decls.h";
diff --git a/proc/main.c b/proc/main.c
index 73742ed..3419d44 100644
--- a/proc/main.c
+++ b/proc/main.c
@@ -1,5 +1,5 @@
 /* Initialization of the proc server
-   Copyright (C) 1993,94,95,96,97,99,2000,01 Free Software Foundation, Inc.
+   Copyright (C) 1993,94,95,96,97,99,2000,01,13 Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
@@ -60,12 +60,40 @@ message_demuxer (mach_msg_header_t *inp,
 
 pthread_mutex_t global_lock = PTHREAD_MUTEX_INITIALIZER;
 
+error_t
+increase_priority (void)
+{
+  mach_port_t pset = MACH_PORT_NULL, psetcntl = MACH_PORT_NULL;
+  error_t err;
+
+  err = thread_get_assignment (mach_thread_self (), &pset);
+  if (err)
+    goto out;
+
+  err = host_processor_set_priv (_hurd_host_priv, pset, &psetcntl);
+  if (err)
+    goto out;
+
+  err = thread_max_priority (mach_thread_self (), psetcntl, 0);
+  if (err)
+    goto out;
+
+  err = task_priority (mach_task_self (), 2, 1);
+
+ out:
+  if (MACH_PORT_VALID (pset))
+    mach_port_deallocate (mach_task_self (), pset);
+  if (MACH_PORT_VALID (psetcntl))
+    mach_port_deallocate (mach_task_self (), psetcntl);
+
+  return err;
+}
+
 int
 main (int argc, char **argv, char **envp)
 {
   mach_port_t boot;
   error_t err;
-  mach_port_t pset, psetcntl;
   void *genport;
   process_t startup_port;
   struct argp argp = { 0, 0, 0, "Hurd process server" };
@@ -88,7 +116,12 @@ main (int argc, char **argv, char **envp)
   generic_port = ports_get_right (genport);
 
   /* Create the initial proc object for init (PID 1).  */
-  startup_proc = create_startup_proc ();
+  init_proc = create_init_proc ();
+
+  /* Create the startup proc object for /hurd/init (PID 2).  */
+  startup_proc = allocate_proc (MACH_PORT_NULL);
+  startup_proc->p_deadmsg = 1;
+  complete_proc (startup_proc, HURD_PID_STARTUP);
 
   /* Create our own proc object.  */
   self_proc = allocate_proc (mach_task_self ());
@@ -115,17 +148,9 @@ main (int argc, char **argv, char **envp)
 
   /* Give ourselves good scheduling performance, because we are so
      important. */
-  err = thread_get_assignment (mach_thread_self (), &pset);
-  assert_perror (err);
-  err = host_processor_set_priv (_hurd_host_priv, pset, &psetcntl);
-  assert_perror (err);
-  thread_max_priority (mach_thread_self (), psetcntl, 0);
-  assert_perror (err);
-  err = task_priority (mach_task_self (), 2, 1);
-  assert_perror (err);
-
-  mach_port_deallocate (mach_task_self (), pset);
-  mach_port_deallocate (mach_task_self (), psetcntl);
+  err = increase_priority ();
+  if (err)
+    error (0, err, "Increasing priority failed");
 
   {
     /* Get our stderr set up to print on the console, in case we have
diff --git a/proc/mgt.c b/proc/mgt.c
index b8aa0fc..02d69db 100644
--- a/proc/mgt.c
+++ b/proc/mgt.c
@@ -1,5 +1,6 @@
 /* Process management
-   Copyright (C) 1992,93,94,95,96,99,2000,01,02 Free Software Foundation, Inc.
+   Copyright (C) 1992,93,94,95,96,99,2000,01,02,13
+     Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
@@ -184,7 +185,7 @@ S_proc_child (struct proc *parentp,
   /* Process hierarchy.  Remove from our current location
      and place us under our new parent.  Sanity check to make sure
      parent is currently init. */
-  assert (childp->p_parent == startup_proc);
+  assert (childp->p_parent == init_proc);
   if (childp->p_sib)
     childp->p_sib->p_prevsib = childp->p_prevsib;
   *childp->p_prevsib = childp->p_sib;
@@ -586,7 +587,7 @@ allocate_proc (task_t task)
 /* Allocate and initialize the proc structure for init (PID 1),
    the original parent of all other procs.  */
 struct proc *
-create_startup_proc (void)
+create_init_proc (void)
 {
   static const uid_t zero;
   struct proc *p;
@@ -595,7 +596,7 @@ create_startup_proc (void)
   p = allocate_proc (MACH_PORT_NULL);
   assert (p);
 
-  p->p_pid = HURD_PID_STARTUP;
+  p->p_pid = HURD_PID_INIT;
 
   p->p_parent = p;
   p->p_sib = 0;
@@ -643,7 +644,7 @@ proc_death_notify (struct proc *p)
 }
 
 /* Complete a new process that has been allocated but not entirely initialized.
-   This gets called for every process except startup_proc (PID 1).  */
+   This gets called for every process except init_proc (PID 1).  */
 void
 complete_proc (struct proc *p, pid_t pid)
 {
@@ -662,30 +663,47 @@ complete_proc (struct proc *p, pid_t pid)
 
   p->p_pid = pid;
 
-  ids_ref (&nullids);
-  p->p_id = &nullids;
+  if (pid == HURD_PID_STARTUP)
+    {
+      /* Equip HURD_PID_STARTUP with the same credentials as
+         HURD_PID_INIT.  */
+      static const uid_t zero;
+      p->p_id = make_ids (&zero, 1);
+      assert (p->p_id);
+    }
+  else
+    {
+      ids_ref (&nullids);
+      p->p_id = &nullids;
+    }
 
   p->p_login = nulllogin;
   p->p_login->l_refcnt++;
 
   /* Our parent is init for now.  */
-  p->p_parent = startup_proc;
+  p->p_parent = init_proc;
 
-  p->p_sib = startup_proc->p_ochild;
-  p->p_prevsib = &startup_proc->p_ochild;
+  p->p_sib = init_proc->p_ochild;
+  p->p_prevsib = &init_proc->p_ochild;
   if (p->p_sib)
     p->p_sib->p_prevsib = &p->p_sib;
-  startup_proc->p_ochild = p;
+  init_proc->p_ochild = p;
   p->p_loginleader = 0;
   p->p_ochild = 0;
   p->p_parentset = 0;
 
   p->p_noowner = 1;
 
-  p->p_pgrp = startup_proc->p_pgrp;
+  p->p_pgrp = init_proc->p_pgrp;
 
-  proc_death_notify (p);
-  add_proc_to_hash (p);
+  /* At this point, we do not know the task of the startup process,
+     defer registering death notifications and adding it to the hash
+     tables.  */
+  if (pid != HURD_PID_STARTUP)
+    {
+      proc_death_notify (p);
+      add_proc_to_hash (p);
+    }
   join_pgrp (p);
 }
 
@@ -747,7 +765,7 @@ process_has_exited (struct proc *p)
            nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
                                    1, tp->p_pgrp->pg_pgid,
                                    !tp->p_pgrp->pg_orphcnt);
-         tp->p_parent = startup_proc;
+         tp->p_parent = init_proc;
          if (tp->p_dead)
            isdead = 1;
        }
@@ -755,17 +773,17 @@ process_has_exited (struct proc *p)
        nowait_msg_proc_newids (tp->p_msgport, tp->p_task,
                                1, tp->p_pgrp->pg_pgid,
                                !tp->p_pgrp->pg_orphcnt);
-      tp->p_parent = startup_proc;
+      tp->p_parent = init_proc;
 
       /* And now append the lists. */
-      tp->p_sib = startup_proc->p_ochild;
+      tp->p_sib = init_proc->p_ochild;
       if (tp->p_sib)
        tp->p_sib->p_prevsib = &tp->p_sib;
-      startup_proc->p_ochild = p->p_ochild;
-      p->p_ochild->p_prevsib = &startup_proc->p_ochild;
+      init_proc->p_ochild = p->p_ochild;
+      p->p_ochild->p_prevsib = &init_proc->p_ochild;
 
       if (isdead)
-       alert_parent (startup_proc);
+       alert_parent (init_proc);
     }
 
   /* If an operation is in progress for this process, cause it
@@ -883,6 +901,24 @@ genpid ()
   return nextpid++;
 }
 
+/* Implement proc_set_init_task as described in <hurd/process.defs>.  */
+error_t
+S_proc_set_init_task(struct proc *callerp,
+                    task_t task)
+{
+  if (! callerp)
+    return EOPNOTSUPP;
+
+  if (callerp != startup_proc)
+    return EPERM;
+
+  init_proc->p_task = task;
+  proc_death_notify (init_proc);
+  add_proc_to_hash (init_proc);
+
+  return 0;
+}
+
 /* Implement proc_mark_important as described in <hurd/process.defs>. */
 kern_return_t
 S_proc_mark_important (struct proc *p)
diff --git a/proc/mig-decls.h b/proc/mig-decls.h
index 7d36a87..eb33ef3 100644
--- a/proc/mig-decls.h
+++ b/proc/mig-decls.h
@@ -35,6 +35,17 @@ begin_using_proc_port (mach_port_t port)
   return (!p || p->p_dead) ? NULL : p;
 }
 
+static inline struct proc * __attribute__ ((unused))
+begin_using_proc_payload (unsigned long payload)
+{
+  struct proc *p;
+  p = ports_lookup_payload (proc_bucket, payload, proc_class);
+  if (p && p->p_dead)
+    ports_port_deref (p);
+  return (!p || p->p_dead) ? 0 : p;
+}
+
+
 static inline void __attribute__ ((unused))
 end_using_proc (struct proc *p)
 {
@@ -50,6 +61,12 @@ begin_using_exc_port (mach_port_t port)
   return ports_lookup_port (NULL, port, exc_class);
 }
 
+static inline exc_t __attribute__ ((unused))
+begin_using_exc_payload (unsigned long payload)
+{
+  return ports_lookup_payload (NULL, payload, exc_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_exc (exc_t exc)
 {
diff --git a/proc/mig-mutate.h b/proc/mig-mutate.h
index ce9f88e..62dc2a5 100644
--- a/proc/mig-mutate.h
+++ b/proc/mig-mutate.h
@@ -20,6 +20,8 @@
 
 #define PROCESS_INTRAN                                         \
   pstruct_t begin_using_proc_port (process_t)
+#define PROCESS_INTRAN_PAYLOAD                                 \
+  pstruct_t begin_using_proc_payload
 #define PROCESS_DESTRUCTOR                                     \
   end_using_proc (pstruct_t)
 #define PROCESS_IMPORTS                                                \
@@ -27,6 +29,8 @@
 
 #define NOTIFY_INTRAN                                          \
   port_info_t begin_using_port_info_port (mach_port_t)
+#define NOTIFY_INTRAN_PAYLOAD                                  \
+  port_info_t begin_using_port_info_payload
 #define NOTIFY_DESTRUCTOR                                      \
   end_using_port_info (port_info_t)
 #define NOTIFY_IMPORTS                                         \
diff --git a/proc/notify.c b/proc/notify.c
index b6731ae..c5734b0 100644
--- a/proc/notify.c
+++ b/proc/notify.c
@@ -41,6 +41,9 @@ do_mach_notify_dead_name (struct port_info *pi,
 {
   struct proc *p;
 
+  if (!pi)
+    return EOPNOTSUPP;
+
   if (pi->port_right == generic_port)
     {
       check_dead_execdata_notify (deadport);
@@ -50,8 +53,7 @@ do_mach_notify_dead_name (struct port_info *pi,
 
   p = (struct proc *) pi;
 
-  if (!p
-      || p->p_pi.bucket != proc_bucket
+  if (p->p_pi.bucket != proc_bucket
       || p->p_pi.class != proc_class)
     return EOPNOTSUPP;
 
diff --git a/proc/proc.h b/proc/proc.h
index a2e3c53..6196697 100644
--- a/proc/proc.h
+++ b/proc/proc.h
@@ -1,5 +1,6 @@
 /* Process server definitions
-   Copyright (C) 1992,93,94,95,96,99,2000,01 Free Software Foundation, Inc.
+   Copyright (C) 1992,93,94,95,96,99,2000,01,13
+     Free Software Foundation, Inc.
 
 This file is part of the GNU Hurd.
 
@@ -134,7 +135,8 @@ struct exc
 
 mach_port_t authserver;
 struct proc *self_proc;                /* process HURD_PID_PROC (us) */
-struct proc *startup_proc;     /* process 1 (init) */
+struct proc *init_proc;                /* process 1 (sysvinit) */
+struct proc *startup_proc;     /* process 2 (hurd/init) */
 
 struct port_bucket *proc_bucket;
 struct port_class *proc_class;
@@ -183,7 +185,7 @@ void exc_clean (void *);
 struct proc *add_tasks (task_t);
 int pidfree (pid_t);
 
-struct proc *create_startup_proc (void);
+struct proc *create_init_proc (void);
 struct proc *allocate_proc (task_t);
 void proc_death_notify (struct proc *);
 void complete_proc (struct proc *, pid_t);
diff --git a/proc/proc_exc.defs b/proc/proc_exc.defs
index c910824..9dc3626 100644
--- a/proc/proc_exc.defs
+++ b/proc/proc_exc.defs
@@ -38,6 +38,7 @@ import "mig-decls.h";
 type exception_t = mach_port_copy_send_t
        cusertype: mach_port_t
        intran: exc_t begin_using_exc_port (exception_t)
+       intranpayload: exc_t begin_using_exc_payload
        destructor: end_using_exc (exc_t);
 
 routine proc_exception_raise (
diff --git a/procfs/main.c b/procfs/main.c
index 54e9682..320f55b 100644
--- a/procfs/main.c
+++ b/procfs/main.c
@@ -25,6 +25,7 @@
 #include <argz.h>
 #include <hurd/netfs.h>
 #include <ps.h>
+#include <pids.h>
 #include "procfs.h"
 #include "proclist.h"
 #include "rootdir.h"
@@ -42,7 +43,7 @@ uid_t opt_anon_owner;
 #define OPT_CLK_TCK    sysconf(_SC_CLK_TCK)
 #define OPT_STAT_MODE  0400
 #define OPT_FAKE_SELF  -1
-#define OPT_KERNEL_PID 2
+#define OPT_KERNEL_PID HURD_PID_KERNEL
 #define OPT_ANON_OWNER 0
 
 #define NODEV_KEY  -1 /* <= 0, so no short option. */
@@ -137,15 +138,17 @@ argp_parser (int key, char *arg, struct argp_state *state)
 }
 
 struct argp_option common_options[] = {
+#define STR(X) XSTR (X)
+#define XSTR(X)        #X
   { "clk-tck", 'h', "HZ", 0,
       "Unit used for the values expressed in system clock ticks "
-      "(default: sysconf(_SC_CLK_TCK))" },
+      "(default: " STR (OPT_CLK_TCK) ")" },
   { "stat-mode", 's', "MODE", 0,
       "The [pid]/stat file publishes information which on Hurd is only "
       "available to the process owner.  "
       "You can use this option to override its mode to be more permissive "
       "for compatibility purposes.  "
-      "(default: 0400)" },
+      "(default: " STR (OPT_STAT_MODE) ")" },
   { "fake-self", 'S', "PID", OPTION_ARG_OPTIONAL,
       "Provide a fake \"self\" symlink to the given PID, for compatibility "
       "purposes.  If PID is omitted, \"self\" will point to init.  "
@@ -153,7 +156,7 @@ struct argp_option common_options[] = {
   { "kernel-process", 'k', "PID", 0,
       "Process identifier for the kernel, used to retreive its command "
       "line, as well as the global up and idle times. "
-      "(default: 2)" },
+      "(default: " STR (OPT_KERNEL_PID) ")" },
   { "compatible", 'c', NULL, 0,
       "Try to be compatible with the Linux procps utilities.  "
       "Currently equivalent to -h 100 -s 0444 -S 1." },
@@ -161,7 +164,7 @@ struct argp_option common_options[] = {
       "Make USER the owner of files related to processes without one.  "
       "Be aware that USER will be granted access to the environment and "
       "other sensitive information about the processes in question.  "
-      "(default: use uid 0)" },
+      "(default: use uid " STR (OPT_ANON_OWNER) ")" },
   { "nodev", NODEV_KEY, NULL, 0,
       "Ignored for compatibility with Linux' procfs." },
   { "noexec", NOEXEC_KEY, NULL, 0,
@@ -169,6 +172,8 @@ struct argp_option common_options[] = {
   { "nosuid", NOSUID_KEY, NULL, 0,
       "Ignored for compatibility with Linux' procfs." },
   {}
+#undef XSTR
+#undef STR
 };
 
 struct argp argp = {
@@ -259,6 +264,18 @@ netfs_append_args (char **argz, size_t *argz_len)
 
   return err;
 }
+
+/* The user may define this function.  The function must set source to
+   the source of CRED. The function may return an EOPNOTSUPP to
+   indicate that the concept of a source device is not applicable. The
+   default function always returns EOPNOTSUPP. */
+error_t netfs_get_source (struct protid *cred, char *source, size_t source_len)
+{
+  if (! cred)
+    return EOPNOTSUPP;
+  snprintf (source, source_len, "proc");
+  return 0;
+}
 
 error_t
 root_make_node (struct ps_context *pc, struct node **np)
diff --git a/random/Makefile b/random/Makefile
index 6291da0..0949b63 100644
--- a/random/Makefile
+++ b/random/Makefile
@@ -26,6 +26,5 @@ OBJS = $(SRCS:.c=.o) startup_notifyServer.o
 LCLHDRS = gnupg-random.h gnupg-rmd.h gnupg-bithelp.h random.h
 HURDLIBS = trivfs ports fshelp ihash shouldbeinlibc
 OTHERLIBS = -lpthread
-MIGSFLAGS = -DSEQNOS -imacros $(srcdir)/mig-mutate.h
 
 include ../Makeconf
diff --git a/random/mig-decls.h b/random/mig-decls.h
deleted file mode 100644
index 87b7eb2..0000000
--- a/random/mig-decls.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
-   Copyright (C) 2014 Free Software Foundation, Inc.
-   Written by Justus Winter.
-
-   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.  If not, see <http://www.gnu.org/licenses/>.  */
-
-#ifndef __RANDOM_MIG_DECLS_H__
-#define __RANDOM_MIG_DECLS_H__
-
-#include <hurd/ports.h>
-
-typedef struct port_info *port_info_t;
-
-extern struct trivfs_control *fsys;
-extern struct port_class *shutdown_notify_class;
-
-/* Called by server stub functions.  */
-
-static inline struct port_info * __attribute__ ((unused))
-begin_using_startup_port (mach_port_t port)
-{
-  return ports_lookup_port (fsys->pi.bucket,
-                            handle,
-                            shutdown_notify_class);
-}
-
-static inline void __attribute__ ((unused))
-end_using_startup (struct port_info *p)
-{
-  if (p)
-    ports_port_deref (p);
-}
-
-#endif /* __RANDOM_MIG_DECLS_H__ */
diff --git a/random/random.c b/random/random.c
index 6eea363..15be383 100644
--- a/random/random.c
+++ b/random/random.c
@@ -537,8 +537,11 @@ struct port_class *shutdown_notify_class;
 /* The system is going down; destroy all the extant port rights.  That
    will cause net channels and such to close promptly.  */
 error_t
-S_startup_dosync (struct port_info *inpi)
+S_startup_dosync (mach_port_t handle)
 {
+  struct port_info *inpi = ports_lookup_port (fsys->pi.bucket, handle,
+                                             shutdown_notify_class);
+
   if (!inpi)
     return EOPNOTSUPP;
 
diff --git a/init/Makefile b/startup/Makefile
similarity index 81%
copy from init/Makefile
copy to startup/Makefile
index ffb82ff..ee2ecdd5 100644
--- a/init/Makefile
+++ b/startup/Makefile
@@ -15,16 +15,20 @@
 #   along with this program; if not, write to the Free Software
 #   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
-dir := init
+dir := startup
 makemode := server
 
-SRCS = init.c stubs.c
+SRCS = startup.c
 OBJS = $(SRCS:.c=.o) \
        startupServer.o notifyServer.o startup_replyUser.o msgServer.o \
-       startup_notifyUser.o
-target = init
+       startup_notifyUser.o fsysServer.o
+target = startup
 HURDLIBS = shouldbeinlibc
 
+# startup does not use libports.  Disable the default payload to port
+# conversion.
+MIGSFLAGS="-DHURD_DEFAULT_PAYLOAD_TO_PORT=1"
+
 include ../Makeconf
 
 mung_msg_S.h: msg_S.h
diff --git a/init/init.c b/startup/startup.c
similarity index 93%
copy from init/init.c
copy to startup/startup.c
index b7b40bd..e177075 100644
--- a/init/init.c
+++ b/startup/startup.c
@@ -63,7 +63,7 @@ static int crash_flags = RB_AUTOBOOT;
 #define BOOT(flags)    ((flags & RB_HALT) ? "halt" : "reboot")
 
 
-const char *argp_program_version = STANDARD_HURD_VERSION (init);
+const char *argp_program_version = STANDARD_HURD_VERSION (startup);
 
 static struct argp_option
 options[] =
@@ -217,7 +217,7 @@ notify_shutdown (const char *msg)
 void
 reboot_system (int flags)
 {
-  notify_shutdown ("shutdown");
+  notify_shutdown (BOOT (flags));
 
   if (fakeboot)
     {
@@ -501,10 +501,14 @@ static int
 demuxer (mach_msg_header_t *inp,
         mach_msg_header_t *outp)
 {
-  extern int notify_server (), startup_server (), msg_server ();
+  extern int notify_server (mach_msg_header_t *, mach_msg_header_t *);
+  extern int startup_server (mach_msg_header_t *, mach_msg_header_t *);
+  extern int msg_server (mach_msg_header_t *, mach_msg_header_t *);
+  extern int fsys_server (mach_msg_header_t *, mach_msg_header_t *);
 
   return (notify_server (inp, outp) ||
          msg_server (inp, outp) ||
+         fsys_server (inp, outp) ||
          startup_server (inp, outp));
 }
 
@@ -553,7 +557,7 @@ main (int argc, char **argv, char **envp)
      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))
+      || device_open (device_master, D_READ|D_WRITE, "console", &consdev))
     crash_mach ();
 
   wire_task_self ();
@@ -581,6 +585,18 @@ main (int argc, char **argv, char **envp)
   /* Crash if the boot filesystem task dies.  */
   request_dead_name (fstask);
 
+  file_t node = file_name_lookup (_SERVERS_STARTUP, O_NOTRANS, 0);
+  if (node == MACH_PORT_NULL)
+    error (0, errno, "%s", _SERVERS_STARTUP);
+  else
+    {
+      file_set_translator (node,
+                          0, FS_TRANS_SET, 0,
+                          NULL, 0,
+                          startup, MACH_MSG_TYPE_COPY_SEND);
+      mach_port_deallocate (mach_task_self (), node);
+    }
+
   /* Set up the set of ports we will pass to the programs we exec.  */
   for (i = 0; i < INIT_PORT_MAX; i++)
     switch (i)
@@ -904,9 +920,6 @@ frob_kernel_process (void)
 static pid_t child_pid;                /* PID of the child we run */
 static task_t child_task;              /* and its (original) task port */
 
-error_t send_signal (mach_port_t msgport, int signal, mach_port_t refport,
-                    mach_msg_timeout_t);
-
 static void launch_something (const char *why);
 
 
@@ -965,52 +978,6 @@ process_signal (int signo)
            }
        }
     }
-  else
-    {
-      /* Pass the signal on to the child.  */
-      task_t task;
-      error_t err;
-
-      err = proc_pid2task (procserver, child_pid, &task);
-      if (err)
-       {
-         error (0, err, "proc_pid2task on %d", child_pid);
-         task = child_task;
-       }
-      else
-       {
-         mach_port_deallocate (mach_task_self (), child_task);
-         child_task = task;
-       }
-
-      if (signo == SIGKILL)
-       {
-         err = task_terminate (task);
-         if (err != MACH_SEND_INVALID_DEST)
-           error (0, err, "task_terminate");
-       }
-      else
-       {
-         mach_port_t msgport;
-         err = proc_getmsgport (procserver, child_pid, &msgport);
-         if (err)
-           error (0, err, "proc_getmsgport");
-         else
-           {
-             err = send_signal (msgport, signo, task,
-                                500); /* Block only half a second.  */
-             mach_port_deallocate (mach_task_self (), msgport);
-             if (err)
-               {
-                 error (0, err, "cannot send %s to child %d",
-                        strsignal (signo), child_pid);
-                 err = task_terminate (task);
-                 if (err != MACH_SEND_INVALID_DEST)
-                   error (0, err, "task_terminate");
-               }
-           }
-       }
-    }
 }
 
 /* Start the child program PROG.  It is run via /libexec/console-run
@@ -1058,7 +1025,7 @@ start_child (const char *prog, char **progargs)
               NULL, 0, /* OSF Mach */
 #endif
               0, &child_task);
-  proc_child (procserver, child_task);
+  proc_set_init_task (procserver, child_task);
   proc_task2pid (procserver, child_task, &child_pid);
   proc_task2proc (procserver, child_task, &default_ports[INIT_PORT_PROC]);
 
@@ -1591,3 +1558,108 @@ S_msg_report_wait (mach_port_t process, thread_t thread,
   *rpc = 0;
   return 0;
 }
+
+/* fsys */
+error_t
+S_fsys_getroot (mach_port_t fsys_t,
+               mach_port_t dotdotnode,
+               uid_t *uids, size_t nuids,
+               uid_t *gids, size_t ngids,
+               int flags,
+               retry_type *do_retry,
+               char *retry_name,
+               mach_port_t *ret,
+               mach_msg_type_name_t *rettype)
+{
+  int is_root = 0;
+  size_t i;
+
+  for (i = 0; i < nuids; i++)
+    if (uids[i] == 0)
+      {
+        is_root = 1;
+        break;
+      }
+
+  if (! is_root)
+    return EPERM;
+
+  *do_retry = FS_RETRY_NORMAL;
+  *retry_name = '\0';
+  *ret = startup;
+  *rettype = MACH_MSG_TYPE_COPY_SEND;
+  return 0;
+}
+
+error_t
+S_fsys_goaway (mach_port_t control, int flags)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_startup (mach_port_t bootstrap, int flags, mach_port_t control,
+               mach_port_t *real, mach_msg_type_name_t *realtype)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_syncfs (mach_port_t control,
+              int wait,
+              int recurse)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_set_options (mach_port_t control,
+                   char *data, mach_msg_type_number_t len,
+                   int do_children)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_get_options (mach_port_t control,
+                   char **data, mach_msg_type_number_t *len)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getfile (mach_port_t control,
+               uid_t *uids, size_t nuids,
+               uid_t *gids, size_t ngids,
+               char *handle, size_t handllen,
+               mach_port_t *pt,
+               mach_msg_type_name_t *pttype)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_getpriv (mach_port_t control,
+               mach_port_t *host_priv, mach_msg_type_name_t *host_priv_type,
+               mach_port_t *dev_master, mach_msg_type_name_t *dev_master_type,
+               task_t *fs_task, mach_msg_type_name_t *fs_task_type)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_init (mach_port_t control,
+          mach_port_t reply,
+          mach_msg_type_name_t replytype,
+          mach_port_t proc,
+          auth_t auth)
+{
+  return EOPNOTSUPP;
+}
+
+error_t
+S_fsys_forward (mach_port_t server, mach_port_t requestor,
+               char *argz, size_t argz_len)
+{
+  return EOPNOTSUPP;
+}
diff --git a/sutils/fstab.c b/sutils/fstab.c
index ed59151..e13f15b 100644
--- a/sutils/fstab.c
+++ b/sutils/fstab.c
@@ -240,16 +240,32 @@ fstypes_find_program (struct fstypes *types, const char 
*program,
 
 /* Copy MNTENT into FS, copying component strings as well.  */
 error_t
-fs_set_mntent (struct fs *fs, const struct mntent *mntent)
+fs_set_mntent (struct fs *fs, const struct mntent *provided_mntent)
 {
   char *end;
   size_t needed = 0;
+  struct mntent mntent = *provided_mntent;
+  char *real_fsname = NULL;
+  char *real_dir = NULL;
 
   if (fs->storage)
     free (fs->storage);
 
+  if (mntent.mnt_fsname)
+    {
+      real_fsname = realpath (mntent.mnt_fsname, NULL);
+      if (real_fsname)
+       mntent.mnt_fsname = real_fsname;
+    }
+  if (mntent.mnt_dir)
+    {
+      real_dir = realpath (mntent.mnt_dir, NULL);
+      if (real_dir)
+       mntent.mnt_dir = real_dir;
+    }
+
   /* Allocate space for all string mntent fields in FS.  */
-#define COUNT(field) if (mntent->field) needed += strlen (mntent->field) + 1;
+#define COUNT(field) if (mntent.field) needed += strlen (mntent.field) + 1;
   COUNT (mnt_fsname);
   COUNT (mnt_dir);
   COUNT (mnt_type);
@@ -258,10 +274,14 @@ fs_set_mntent (struct fs *fs, const struct mntent *mntent)
 
   fs->storage = malloc (needed);
   if (! fs->storage)
-    return ENOMEM;
+    {
+      free (real_fsname);
+      free (real_dir);
+      return ENOMEM;
+    }
 
-  if (!fs->mntent.mnt_dir || !mntent->mnt_dir
-      || strcmp (fs->mntent.mnt_dir, mntent->mnt_dir) != 0)
+  if (!fs->mntent.mnt_dir || !mntent.mnt_dir
+      || strcmp (fs->mntent.mnt_dir, mntent.mnt_dir) != 0)
     {
       fs->mounted = fs->readonly = -1;
       if (fs->fsys != MACH_PORT_NULL)
@@ -270,15 +290,15 @@ fs_set_mntent (struct fs *fs, const struct mntent *mntent)
     }
 
   /* Copy MNTENT into FS; string-valued fields will be fixed up next.  */
-  fs->mntent = *mntent;
+  fs->mntent = mntent;
 
   /* Copy each mntent field from MNTENT into FS's version.  */
   end = fs->storage;
 #define STORE(field) \
-  if (mntent->field)                           \
+  if (mntent.field)                            \
     {                                          \
       fs->mntent.field = end;                  \
-      end = stpcpy (end, mntent->field) + 1;   \
+      end = stpcpy (end, mntent.field) + 1;    \
     }                                          \
   else                                         \
     fs->mntent.field = 0;
@@ -289,10 +309,13 @@ fs_set_mntent (struct fs *fs, const struct mntent *mntent)
 #undef STORE
 
   if (fs->type
-      && (!mntent->mnt_type
-         || strcasecmp (fs->type->name, mntent->mnt_type) != 0))
+      && (!mntent.mnt_type
+         || strcasecmp (fs->type->name, mntent.mnt_type) != 0))
     fs->type = 0;              /* Type is different.  */
 
+  free (real_fsname);
+  free (real_dir);
+
   return 0;
 }
 
@@ -470,11 +493,21 @@ fstab_find_device (const struct fstab *fstab, const char 
*name)
   if (strcmp (name, "none") == 0)
     return NULL;
 
+  char *real_name = realpath (name, NULL);
+  const char *lookup_name;
+
+  if (real_name)
+    lookup_name = real_name;
+  else
+    lookup_name = name;
+
   struct fs *fs;
   for (fs = fstab->entries; fs; fs = fs->next)
-    if (strcmp (fs->mntent.mnt_fsname, name) == 0)
-      return fs;
-  return 0;
+    if (strcmp (fs->mntent.mnt_fsname, lookup_name) == 0)
+      break;
+
+  free (real_name);
+  return fs;
 }
 
 /* Returns the FS entry in FSTAB with the mount point NAME (there can only
@@ -482,8 +515,6 @@ fstab_find_device (const struct fstab *fstab, const char 
*name)
 inline struct fs *
 fstab_find_mount (const struct fstab *fstab, const char *name)
 {
-  struct fs *fs;
-
   /* Don't count "none" or "-" as matching any other mount point.
      It is canonical to use "none" for swap partitions, and multiple
      such do not in fact conflict with each other.  Likewise, the
@@ -494,10 +525,21 @@ fstab_find_mount (const struct fstab *fstab, const char 
*name)
       || !strcmp (name, "ignore"))
     return 0;
 
+  char *real_name = realpath (name, NULL);
+  const char *lookup_name;
+
+  if (real_name)
+    lookup_name = real_name;
+  else
+    lookup_name = name;
+
+  struct fs *fs;
   for (fs = fstab->entries; fs; fs = fs->next)
-    if (strcmp (fs->mntent.mnt_dir, name) == 0)
-      return fs;
-  return 0;
+    if (strcmp (fs->mntent.mnt_dir, lookup_name) == 0)
+      break;
+
+  free (real_name);
+  return fs;
 }
 
 /* Returns the FS entry in FSTAB with the device or mount point NAME (there
@@ -505,29 +547,7 @@ fstab_find_mount (const struct fstab *fstab, const char 
*name)
 inline struct fs *
 fstab_find (const struct fstab *fstab, const char *name)
 {
-  struct fs *ret;
-  char *real_name;
-
-  ret = fstab_find_device (fstab, name);
-  if (ret)
-    return ret;
-
-  ret = fstab_find_mount (fstab, name);
-  if (ret)
-    return ret;
-
-  real_name = realpath (name, NULL);
-
-  ret = fstab_find_device (fstab, real_name);
-  if (ret) {
-    free (real_name);
-    return ret;
-  }
-
-  ret = fstab_find_mount (fstab, real_name);
-  free (real_name);
-
-  return ret;
+  return fstab_find_device (fstab, name) ?: fstab_find_mount (fstab, name);
 }
 
 /* Cons FS onto the beginning of FSTAB's entry list.  */
@@ -690,6 +710,7 @@ fstab_read (struct fstab *fstab, const char *name)
     {
       while (!err && !feof (stream))
        {
+         errno = 0;
          struct mntent *mntent = getmntent (stream);
 
          if (! mntent)
diff --git a/term/Makefile b/term/Makefile
index 5006c0d..1419d2a 100644
--- a/term/Makefile
+++ b/term/Makefile
@@ -33,5 +33,6 @@ include ../Makeconf
 
 device_replyServer-CPPFLAGS = -DTypeCheck=0 -Wno-unused # XXX
 
+device_reply-MIGSFLAGS = -DMACH_PAYLOAD_TO_PORT=ports_payload_get_name
 tioctl-MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
 term-MIGSFLAGS = -imacros $(srcdir)/mig-mutate.h
diff --git a/term/mig-decls.h b/term/mig-decls.h
index c91b133..09b45c6 100644
--- a/term/mig-decls.h
+++ b/term/mig-decls.h
@@ -32,6 +32,12 @@ begin_using_ctty_port (mach_port_t port)
   return ports_lookup_port (term_bucket, port, cttyid_class);
 }
 
+static inline struct port_info * __attribute__ ((unused))
+begin_using_ctty_payload (unsigned long payload)
+{
+  return ports_lookup_payload (term_bucket, payload, cttyid_class);
+}
+
 static inline void __attribute__ ((unused))
 end_using_ctty (struct port_info *p)
 {
diff --git a/term/mig-mutate.h b/term/mig-mutate.h
index 1545719..af8877e 100644
--- a/term/mig-mutate.h
+++ b/term/mig-mutate.h
@@ -20,10 +20,13 @@
 /* Only CPP macro definitions should go in this file. */
 
 #define IO_INTRAN trivfs_protid_t trivfs_begin_using_protid (io_t)
+#define IO_INTRAN_PAYLOAD trivfs_protid_t trivfs_begin_using_protid_payload
 #define IO_DESTRUCTOR trivfs_end_using_protid (trivfs_protid_t)
 
 #define CTTY_INTRAN                                    \
   port_info_t begin_using_ctty_port (mach_port_t)
+#define CTTY_INTRAN_PAYLOAD                            \
+  port_info_t begin_using_ctty_payload
 #define CTTY_DESTRUCTOR                                        \
   end_using_ctty (port_info_t)
 
diff --git a/term/ptyio.c b/term/ptyio.c
index 211e70a..6b01585 100644
--- a/term/ptyio.c
+++ b/term/ptyio.c
@@ -331,7 +331,7 @@ pty_io_read (struct trivfs_protid *cred,
        }
     }
 
-  if (!(termflags & TTY_OPEN))
+  if (!(termflags & TTY_OPEN) && !qsize (outputq))
     {
       pthread_mutex_unlock (&global_lock);
       return EIO;
diff --git a/tmpfs/node.c b/tmpfs/node.c
index acc029a..8835e3f 100644
--- a/tmpfs/node.c
+++ b/tmpfs/node.c
@@ -508,6 +508,7 @@ diskfs_get_filemap (struct node *np, vm_prot_t prot)
       
       /* XXX we need to keep a reference to the object, or GNU Mach
         will terminate it when we release the map. */
+      np->dn->u.reg.memref = 0;
       vm_map (mach_task_self (), &np->dn->u.reg.memref, 4096, 0, 1,
              np->dn->u.reg.memobj, 0, 0, VM_PROT_NONE, VM_PROT_NONE,
              VM_INHERIT_NONE);
diff --git a/trans/Makefile b/trans/Makefile
index 71e6424..ce1eae7 100644
--- a/trans/Makefile
+++ b/trans/Makefile
@@ -34,14 +34,23 @@ LDLIBS += -lpthread
 password-LDLIBS = -lcrypt
 password-MIGSFLAGS=\
     "-DIO_INTRAN=trivfs_protid_t trivfs_begin_using_protid (io_t)" \
+    "-DIO_INTRAN_PAYLOAD=trivfs_protid_t trivfs_begin_using_protid_payload" \
     "-DIO_DESTRUCTOR=trivfs_end_using_protid (trivfs_protid_t)" \
     "-DPASSWORD_IMPORTS=import \"../libtrivfs/mig-decls.h\";"
 
 ifsock-MIGSFLAGS=\
     "-DFILE_INTRAN=trivfs_protid_t trivfs_begin_using_protid (io_t)" \
+    "-DFILE_INTRAN_PAYLOAD=trivfs_protid_t trivfs_begin_using_protid_payload" \
     "-DFILE_DESTRUCTOR=trivfs_end_using_protid (trivfs_protid_t)" \
     "-DIFSOCK_IMPORTS=import \"../libtrivfs/mig-decls.h\";"
 
+# device_replyServer is used by the streamio translator.
+device_reply-MIGSFLAGS="-DMACH_PAYLOAD_TO_PORT=ports_payload_get_name"
+
+# fsysServer is only used by the symlink translator which does not use
+# libports.  Disable the default payload to port conversion.
+fsys-MIGSFLAGS = "-DHURD_DEFAULT_PAYLOAD_TO_PORT=1"
+
 include ../Makeconf
 
 vpath elfcore.c $(top_srcdir)/exec
diff --git a/trans/fakeroot.c b/trans/fakeroot.c
index df2de64..a223bc4 100644
--- a/trans/fakeroot.c
+++ b/trans/fakeroot.c
@@ -103,6 +103,7 @@ new_node (file_t file, mach_port_t idport, int locked, int 
openmodes,
          return err;
        }
     }
+  nn->faked = FAKE_DEFAULT;
 
   if (!locked)
     pthread_mutex_lock (&idport_ihash_lock);
@@ -679,13 +680,22 @@ netfs_attempt_mkfile (struct iouser *user, struct node 
*dir,
                      mode_t mode, struct node **np)
 {
   file_t newfile;
+  mode_t real_mode = real_from_fake_mode (mode);
   error_t err = dir_mkfile (netfs_node_netnode (dir)->file, O_RDWR|O_EXEC,
-                           real_from_fake_mode (mode), &newfile);
+                           real_mode, &newfile);
   pthread_mutex_unlock (&dir->lock);
   if (err == 0)
     err = new_node (newfile, MACH_PORT_NULL, 0, O_RDWR|O_EXEC, np);
   if (err == 0)
-    pthread_mutex_unlock (&(*np)->lock);
+    {
+      pthread_mutex_unlock (&(*np)->lock);
+      set_default_attributes (*np);
+      if (real_mode != mode)
+       {
+         set_faked_attribute (*np, FAKE_MODE);
+         (*np)->nn_stat.st_mode = mode;
+       }
+    }
   return err;
 }
 
@@ -964,9 +974,16 @@ netfs_demuxer (mach_msg_header_t *inp,
     {
       /* We didn't recognize the message ID, so pass the message through
         unchanged to the underlying file.  */
-      struct protid *cred = ports_lookup_port (netfs_port_bucket,
-                                              inp->msgh_local_port,
-                                              netfs_protid_class);
+      struct protid *cred;
+      if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) ==
+         MACH_MSG_TYPE_PROTECTED_PAYLOAD)
+       cred = ports_lookup_payload (netfs_port_bucket,
+                                    inp->msgh_protected_payload,
+                                    netfs_protid_class);
+      else
+       cred = ports_lookup_port (netfs_port_bucket,
+                                 inp->msgh_local_port,
+                                 netfs_protid_class);
       if (cred == 0)
        /* This must be an unknown message on our fsys control port.  */
        return 0;
@@ -974,7 +991,9 @@ netfs_demuxer (mach_msg_header_t *inp,
        {
          error_t err;
          assert (MACH_MSGH_BITS_LOCAL (inp->msgh_bits)
-                 == MACH_MSG_TYPE_MOVE_SEND);
+                 == MACH_MSG_TYPE_MOVE_SEND
+                 || MACH_MSGH_BITS_LOCAL (inp->msgh_bits)
+                 == MACH_MSG_TYPE_PROTECTED_PAYLOAD);
          inp->msgh_bits = (inp->msgh_bits & MACH_MSGH_BITS_COMPLEX)
            | MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
                              MACH_MSGH_BITS_REMOTE (inp->msgh_bits));
diff --git a/trans/mtab.c b/trans/mtab.c
index 5207c1e..a9928b3 100644
--- a/trans/mtab.c
+++ b/trans/mtab.c
@@ -24,6 +24,7 @@
 #include <error.h>
 #include <fcntl.h>
 #include <hurd.h>
+#include <hurd/ihash.h>
 #include <hurd/trivfs.h>
 #include <inttypes.h>
 #include <mntent.h>
@@ -55,6 +56,7 @@ struct mtab
   char *contents;
   size_t contents_len;
   off_t offs;
+  struct hurd_ihash ports_seen;
 };
 
 const char *argp_program_version = STANDARD_HURD_VERSION (mtab);
@@ -244,7 +246,11 @@ main (int argc, char *argv[])
   else
     {
       /* One-shot mode.         */
-      struct mtab mtab = { .lock = PTHREAD_MUTEX_INITIALIZER };
+      struct mtab mtab =
+        {
+          .lock = PTHREAD_MUTEX_INITIALIZER,
+          .ports_seen = HURD_IHASH_INITIALIZER (HURD_IHASH_NO_LOCP),
+        };
       err = mtab_populate (&mtab, target_path, insecure);
       if (err)
        error (5, err, "%s", target_path);
@@ -301,6 +307,33 @@ is_filesystem_translator (file_t node)
     }
 }
 
+/* Records NODE's idport in ports_seen, returns true if we have
+   already seen this node or there was an error getting the id
+   port.  */
+boolean_t
+mtab_mark_as_seen (struct mtab *mtab, mach_port_t node)
+{
+  error_t err;
+  mach_port_t idport, fsidport;
+  ino_t fileno;
+
+  err = io_identity (node, &idport, &fsidport, &fileno);
+  if (err)
+    return TRUE;
+
+  mach_port_deallocate (mach_task_self (), fsidport);
+
+  if (hurd_ihash_find (&mtab->ports_seen, idport))
+    {
+      /* Already seen.  Get rid of the extra reference.  */
+      mach_port_deallocate (mach_task_self (), idport);
+      return TRUE;
+    }
+
+  hurd_ihash_add (&mtab->ports_seen, idport, idport);
+  return FALSE;
+}
+
 /* Populates the given MTAB object with the information for PATH.  If
    INSECURE is given, also follow translators bound to nodes not owned
    by root or the current user.  */
@@ -363,6 +396,13 @@ mtab_populate (struct mtab *mtab, const char *path, int 
insecure)
       goto errout;
     }
 
+  /* Avoid running in circles.  */
+  if (mtab_mark_as_seen (mtab, node))
+    {
+      err = 0;
+      goto errout;
+    }
+
   /* Query its options.         */
   err = file_get_fs_options (node, &argz, &argz_len);
   if (err)
@@ -602,6 +642,7 @@ open_hook (struct trivfs_peropen *peropen)
   mtab->offs = 0;
   mtab->contents = NULL;
   mtab->contents_len = 0;
+  hurd_ihash_init (&mtab->ports_seen, HURD_IHASH_NO_LOCP);
 
   /* The mtab object is initialized, but not yet populated.  We delay
      that until that data is really needed.  This avoids the following
@@ -635,6 +676,9 @@ close_hook (struct trivfs_peropen *peropen)
   struct mtab *op = peropen->hook;
   pthread_mutex_destroy (&op->lock);
   free (op->contents);
+  HURD_IHASH_ITERATE (&op->ports_seen, p)
+    mach_port_deallocate (mach_task_self (), (mach_port_t) p);
+  hurd_ihash_destroy (&op->ports_seen);
   free (op);
 }
 
diff --git a/utils/rpctrace.c b/utils/rpctrace.c
index b11fea4..62d3c87 100644
--- a/utils/rpctrace.c
+++ b/utils/rpctrace.c
@@ -1195,6 +1195,16 @@ wrap_new_task (mach_msg_header_t *inp, struct req_info 
*req)
   ports_port_deref (task_wrapper1);
 }
 
+/* Returns true if the given message is a Mach notification.  */
+static inline int
+is_notification (const mach_msg_header_t *InHeadP)
+{
+  int msgh_id = InHeadP->msgh_id - 64;
+  if ((msgh_id > 8) || (msgh_id < 0))
+    return 0;
+  return 1;
+}
+
 int
 trace_and_forward (mach_msg_header_t *inp, mach_msg_header_t *outp)
 {
@@ -1219,7 +1229,24 @@ trace_and_forward (mach_msg_header_t *inp, 
mach_msg_header_t *outp)
   /* Look up our record for the receiving port.  There is no need to check
      the class, because our port bucket only ever contains one class of
      ports (traced_class).  */
-  info = ports_lookup_port (traced_bucket, inp->msgh_local_port, 0);
+
+  if (MACH_MSGH_BITS_LOCAL (inp->msgh_bits) == MACH_MSG_TYPE_PROTECTED_PAYLOAD)
+    {
+      info = ports_lookup_payload (traced_bucket, inp->msgh_protected_payload,
+                                  NULL);
+      if (info)
+       {
+         /* Undo the protected payload optimization.  */
+         inp->msgh_bits = MACH_MSGH_BITS (
+           MACH_MSGH_BITS_REMOTE (inp->msgh_bits),
+           is_notification (inp)? MACH_MSG_TYPE_MOVE_SEND_ONCE: info->type)
+           | MACH_MSGH_BITS_OTHER (inp->msgh_bits);
+         inp->msgh_local_port = ports_payload_get_name (info);
+       }
+    }
+  else
+    info = ports_lookup_port (traced_bucket, inp->msgh_local_port, NULL);
+
   assert (info);
 
   /* A notification message from the kernel appears to have been sent
@@ -1606,7 +1633,7 @@ print_data (mach_msg_type_name_t type,
         the first character that has not yet been printed.  */
       const char *p, *q;
       p = q = (const char *) data;
-      while (*q && q - (const char *) data < (int) (nelt * eltsize))
+      while (q && *q && q - (const char *) data < (int) (nelt * eltsize))
        {
          if (isgraph (*q) || *q == ' ')
            {
diff --git a/utils/umount.c b/utils/umount.c
index cf6be22..4005029 100644
--- a/utils/umount.c
+++ b/utils/umount.c
@@ -292,8 +292,6 @@ main (int argc, char **argv)
            fs = fstab_find_device (fstab, t);
            if (! fs)
              {
-               error (0, 0, "could not find entry for: %s", t);
-
                /* As last resort, just assume it is the mountpoint.  */
                struct mntent m =
                  {
@@ -307,7 +305,7 @@ main (int argc, char **argv)
 
                err = fstab_add_mntent (fstab, &m, &fs);
                if (err)
-                 error (2, err, "%s", t);
+                 error (2, err, "could not find entry for: %s", t);
              }
          }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]