summaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd')
-rw-r--r--sysdeps/mach/hurd/.cvsignore4
-rw-r--r--sysdeps/mach/hurd/Dist3
-rw-r--r--sysdeps/mach/hurd/Implies2
-rw-r--r--sysdeps/mach/hurd/Makefile132
-rw-r--r--sysdeps/mach/hurd/Subdirs1
-rw-r--r--sysdeps/mach/hurd/_exit.c54
-rw-r--r--sysdeps/mach/hurd/accept.c71
-rw-r--r--sysdeps/mach/hurd/access.c138
-rw-r--r--sysdeps/mach/hurd/adjtime.c53
-rw-r--r--sysdeps/mach/hurd/alpha/exc2signal.c76
-rw-r--r--sysdeps/mach/hurd/alpha/longjmp-ctx.c38
-rw-r--r--sysdeps/mach/hurd/alpha/longjmp-ts.c41
-rw-r--r--sysdeps/mach/hurd/alpha/sigcontext.h65
-rw-r--r--sysdeps/mach/hurd/alpha/sigreturn.c212
-rw-r--r--sysdeps/mach/hurd/alpha/trampoline.c286
-rw-r--r--sysdeps/mach/hurd/bind.c102
-rw-r--r--sysdeps/mach/hurd/brk.c130
-rw-r--r--sysdeps/mach/hurd/chdir.c45
-rw-r--r--sysdeps/mach/hurd/chflags.c38
-rw-r--r--sysdeps/mach/hurd/chmod.c40
-rw-r--r--sysdeps/mach/hurd/chown.c41
-rw-r--r--sysdeps/mach/hurd/chroot.c45
-rw-r--r--sysdeps/mach/hurd/close.c36
-rw-r--r--sysdeps/mach/hurd/closedir.c52
-rwxr-xr-xsysdeps/mach/hurd/configure21
-rw-r--r--sysdeps/mach/hurd/configure.in19
-rw-r--r--sysdeps/mach/hurd/connect.c75
-rw-r--r--sysdeps/mach/hurd/defs.c85
-rw-r--r--sysdeps/mach/hurd/dirstream.h40
-rw-r--r--sysdeps/mach/hurd/dup2.c114
-rw-r--r--sysdeps/mach/hurd/err_hurd.sub11
-rw-r--r--sysdeps/mach/hurd/errlist.awk77
-rw-r--r--sysdeps/mach/hurd/errlist.c93
-rw-r--r--sysdeps/mach/hurd/errnos.awk157
-rw-r--r--sysdeps/mach/hurd/errnos.h266
-rw-r--r--sysdeps/mach/hurd/execve.c45
-rw-r--r--sysdeps/mach/hurd/fchdir.c45
-rw-r--r--sysdeps/mach/hurd/fchflags.c36
-rw-r--r--sysdeps/mach/hurd/fchmod.c38
-rw-r--r--sysdeps/mach/hurd/fchown.c39
-rw-r--r--sysdeps/mach/hurd/fcntl.c159
-rw-r--r--sysdeps/mach/hurd/fcntlbits.h178
-rw-r--r--sysdeps/mach/hurd/fdopen.c69
-rw-r--r--sysdeps/mach/hurd/fexecve.c34
-rw-r--r--sysdeps/mach/hurd/flock.c39
-rw-r--r--sysdeps/mach/hurd/fork.c574
-rw-r--r--sysdeps/mach/hurd/fstat.c38
-rw-r--r--sysdeps/mach/hurd/fsync.c33
-rw-r--r--sysdeps/mach/hurd/ftruncate.c34
-rw-r--r--sysdeps/mach/hurd/getcwd.c250
-rw-r--r--sysdeps/mach/hurd/getdents.c62
-rw-r--r--sysdeps/mach/hurd/getdtsz.c39
-rw-r--r--sysdeps/mach/hurd/getegid.c58
-rw-r--r--sysdeps/mach/hurd/geteuid.c58
-rw-r--r--sysdeps/mach/hurd/getgid.c55
-rw-r--r--sysdeps/mach/hurd/getgroups.c68
-rw-r--r--sysdeps/mach/hurd/gethostid.c33
-rw-r--r--sysdeps/mach/hurd/gethostname.c48
-rw-r--r--sysdeps/mach/hurd/getitimer.c104
-rw-r--r--sysdeps/mach/hurd/getlogin.c40
-rw-r--r--sysdeps/mach/hurd/getpeername.c59
-rw-r--r--sysdeps/mach/hurd/getpgid.c44
-rw-r--r--sysdeps/mach/hurd/getpid.c32
-rw-r--r--sysdeps/mach/hurd/getppid.c34
-rw-r--r--sysdeps/mach/hurd/getpriority.c73
-rw-r--r--sysdeps/mach/hurd/getrlimit.c46
-rw-r--r--sysdeps/mach/hurd/getsockname.c58
-rw-r--r--sysdeps/mach/hurd/getsockopt.c53
-rw-r--r--sysdeps/mach/hurd/getuid.c55
-rw-r--r--sysdeps/mach/hurd/hppa/sigcontext.h86
-rw-r--r--sysdeps/mach/hurd/hppa/trampoline.c258
-rw-r--r--sysdeps/mach/hurd/i386/exc2signal.c165
-rw-r--r--sysdeps/mach/hurd/i386/init-fault.c41
-rw-r--r--sysdeps/mach/hurd/i386/longjmp-ctx.c35
-rw-r--r--sysdeps/mach/hurd/i386/longjmp-ts.c39
-rw-r--r--sysdeps/mach/hurd/i386/sigcontext.h106
-rw-r--r--sysdeps/mach/hurd/i386/sigreturn.c126
-rw-r--r--sysdeps/mach/hurd/i386/trampoline.c271
-rw-r--r--sysdeps/mach/hurd/ioctl.c242
-rw-r--r--sysdeps/mach/hurd/ioctls.h323
-rw-r--r--sysdeps/mach/hurd/isatty.c39
-rw-r--r--sysdeps/mach/hurd/kill.c106
-rw-r--r--sysdeps/mach/hurd/libc-ldscript5
-rw-r--r--sysdeps/mach/hurd/link.c60
-rw-r--r--sysdeps/mach/hurd/listen.c36
-rw-r--r--sysdeps/mach/hurd/local_lim.h40
-rw-r--r--sysdeps/mach/hurd/lseek.c35
-rw-r--r--sysdeps/mach/hurd/lstat.c40
-rw-r--r--sysdeps/mach/hurd/mig-reply.c86
-rw-r--r--sysdeps/mach/hurd/mips/exc2signal.c98
-rw-r--r--sysdeps/mach/hurd/mips/init-fault.c41
-rw-r--r--sysdeps/mach/hurd/mips/longjmp-ctx.c41
-rw-r--r--sysdeps/mach/hurd/mips/longjmp-ts.c45
-rw-r--r--sysdeps/mach/hurd/mips/sigcontext.h71
-rw-r--r--sysdeps/mach/hurd/mips/sigreturn.c169
-rw-r--r--sysdeps/mach/hurd/mips/trampoline.c260
-rw-r--r--sysdeps/mach/hurd/mkdir.c41
-rw-r--r--sysdeps/mach/hurd/mknod.c114
-rw-r--r--sysdeps/mach/hurd/mmap.c105
-rw-r--r--sysdeps/mach/hurd/open.c51
-rw-r--r--sysdeps/mach/hurd/opendir.c60
-rw-r--r--sysdeps/mach/hurd/pipe.c99
-rw-r--r--sysdeps/mach/hurd/ptrace.c392
-rw-r--r--sysdeps/mach/hurd/read.c34
-rw-r--r--sysdeps/mach/hurd/readdir.c90
-rw-r--r--sysdeps/mach/hurd/readlink.c76
-rw-r--r--sysdeps/mach/hurd/reboot.c51
-rw-r--r--sysdeps/mach/hurd/recv.c60
-rw-r--r--sysdeps/mach/hurd/recvfrom.c85
-rw-r--r--sysdeps/mach/hurd/rename.c47
-rw-r--r--sysdeps/mach/hurd/rewinddir.c31
-rw-r--r--sysdeps/mach/hurd/rmdir.c41
-rw-r--r--sysdeps/mach/hurd/sbrk.c42
-rw-r--r--sysdeps/mach/hurd/seekdir.c35
-rw-r--r--sysdeps/mach/hurd/select.c275
-rw-r--r--sysdeps/mach/hurd/send.c40
-rw-r--r--sysdeps/mach/hurd/sendto.c60
-rw-r--r--sysdeps/mach/hurd/setegid.c67
-rw-r--r--sysdeps/mach/hurd/seteuid.c67
-rw-r--r--sysdeps/mach/hurd/setgid.c76
-rw-r--r--sysdeps/mach/hurd/setgroups.c63
-rw-r--r--sysdeps/mach/hurd/sethostid.c31
-rw-r--r--sysdeps/mach/hurd/sethostname.c34
-rw-r--r--sysdeps/mach/hurd/setitimer.c332
-rw-r--r--sysdeps/mach/hurd/setlogin.c32
-rw-r--r--sysdeps/mach/hurd/setpgid.c57
-rw-r--r--sysdeps/mach/hurd/setpriority.c85
-rw-r--r--sysdeps/mach/hurd/setregid.c71
-rw-r--r--sysdeps/mach/hurd/setreuid.c71
-rw-r--r--sysdeps/mach/hurd/setrlimit.c58
-rw-r--r--sysdeps/mach/hurd/setsid.c59
-rw-r--r--sysdeps/mach/hurd/setsockopt.c40
-rw-r--r--sysdeps/mach/hurd/settimeofday.c56
-rw-r--r--sysdeps/mach/hurd/setuid.c76
-rw-r--r--sysdeps/mach/hurd/shutdown.c40
-rw-r--r--sysdeps/mach/hurd/sigaction.c84
-rw-r--r--sysdeps/mach/hurd/sigaltstack.c62
-rw-r--r--sysdeps/mach/hurd/sigpending.c46
-rw-r--r--sysdeps/mach/hurd/sigprocmask.c87
-rw-r--r--sysdeps/mach/hurd/sigstack.c46
-rw-r--r--sysdeps/mach/hurd/sigsuspend.c81
-rw-r--r--sysdeps/mach/hurd/socket.c57
-rw-r--r--sysdeps/mach/hurd/socketpair.c93
-rw-r--r--sysdeps/mach/hurd/start.c316
-rw-r--r--sysdeps/mach/hurd/stat.c40
-rw-r--r--sysdeps/mach/hurd/statbuf.h119
-rw-r--r--sysdeps/mach/hurd/stdio_init.c63
-rw-r--r--sysdeps/mach/hurd/symlink.c68
-rw-r--r--sysdeps/mach/hurd/sync.c33
-rw-r--r--sysdeps/mach/hurd/sys/param.h135
-rw-r--r--sysdeps/mach/hurd/sysd-stdio.c237
-rw-r--r--sysdeps/mach/hurd/telldir.c31
-rw-r--r--sysdeps/mach/hurd/truncate.c42
-rw-r--r--sysdeps/mach/hurd/ttyname.c38
-rw-r--r--sysdeps/mach/hurd/umask.c34
-rw-r--r--sysdeps/mach/hurd/uname.c31
-rw-r--r--sysdeps/mach/hurd/unlink.c46
-rw-r--r--sysdeps/mach/hurd/utimes.c43
-rw-r--r--sysdeps/mach/hurd/wait4.c40
-rw-r--r--sysdeps/mach/hurd/write.c35
160 files changed, 13208 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/.cvsignore b/sysdeps/mach/hurd/.cvsignore
new file mode 100644
index 0000000000..1f69fd919a
--- /dev/null
+++ b/sysdeps/mach/hurd/.cvsignore
@@ -0,0 +1,4 @@
+*.gz *.Z *.tar *.tgz
+=*
+TODO COPYING* AUTHORS copyr-* copying.*
+glibc-*
diff --git a/sysdeps/mach/hurd/Dist b/sysdeps/mach/hurd/Dist
new file mode 100644
index 0000000000..89a6b56f32
--- /dev/null
+++ b/sysdeps/mach/hurd/Dist
@@ -0,0 +1,3 @@
+errnos.awk errlist.awk err_hurd.sub
+libc-ldscript
+
diff --git a/sysdeps/mach/hurd/Implies b/sysdeps/mach/hurd/Implies
new file mode 100644
index 0000000000..b6e4d864d5
--- /dev/null
+++ b/sysdeps/mach/hurd/Implies
@@ -0,0 +1,2 @@
+# The Hurd provides a rough superset of the functionality of 4.4 BSD.
+unix/bsd/bsd4.4
diff --git a/sysdeps/mach/hurd/Makefile b/sysdeps/mach/hurd/Makefile
new file mode 100644
index 0000000000..70b6ec5d49
--- /dev/null
+++ b/sysdeps/mach/hurd/Makefile
@@ -0,0 +1,132 @@
+# Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# The GNU C Library 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# Get mach-srcdir defined.
+old-in-Makerules := $(in-Makerules)
+in-Makerules :=
+include $(..)sysdeps/mach/Makefile
+in-Makerules := $(old-in-Makerules)
+
+
+ifndef hurd-srcdir-computed
+hurd-srcdir-computed := yes
+
+# If we were configured with `--with-hurd=DIR', then config.make sets
+# hurd-srcdir to DIR. Otherwise guess we are in a big source tree.
+ifndef hurd-srcdir
+hurd-srcdir = ../hurd
+endif
+
+# hurd-srcdir is now set to the logical directory name. This name might be
+# relative to $(objdir), might be relative to the source directory $(..), or
+# might be absolute. We choose among these possibilities by looking for a
+# canonical file in each of those places (in that order).
+f := hurd/hurd_types.defs # Random file that identifies the Hurd source dir.
+f := $(strip $f)
+hurd-srcdir := $(firstword $(patsubst %/$f,%,$(wildcard $(addsuffix /$f,\
+ $(objpfx)$(hurd-srcdir) $(..)$(hurd-srcdir)))) $(hurd-srcdir))
+
+endif # ! hurd-srcdir-computed
+
+ifdef in-Makerules
+
+# For the time being, elide directories where nothing at all works.
+subdirs := $(filter-out sunrpc manual,$(subdirs)) # XXX
+
+# Look for header files in hurd/ under the top-level library source directory.
+includes += -I$(..)hurd
+
+# When compiling, use the Hurd header files directly from the sources.
+includes += -I$(hurd-srcdir)
+
+# When compiling, find cthreads.h in the Hurd cthreads source.
+# This directory has some other (private) header file with
+# conflicting names, so we put it last.
+last-includes += -I$(hurd-srcdir)/libthreads
+
+# Find the Hurd header files in the Hurd source.
+vpath hurd/%.h $(hurd-srcdir)
+
+# Do not use any assembly code from sysdeps/unix (and subdirectories).
+# This bypasses all the system call stubs and uses any existing posix or
+# generic C files instead.
+inhibit-sysdep-asm += unix*
+
+# Don't try to generate anything from the installed Unix system and its
+# libraries. That is only of use when building for a Unix system, so as to
+# be compatible with some existing binaries for that system.
+inhibit-glue = yes
+
+
+ifeq (,$(filter mach hurd,$(subdir)))
+# Subdirectories other than hurd/ might use the generated Hurd headers.
+# So make sure we get a chance to run in hurd/ to make them before all else.
+# (But we don't want to do this in mach/, because hurd/ needs some things
+# there, and we know mach/ doesn't need anything from hurd/.)
+
+ifdef objpfx
+hurd-objpfx = $(objpfx)
+else
+hurd-objpfx = $(..)hurd/
+endif
+
+# These are all the generated headers that <hurd.h> includes.
+before-compile += $(patsubst %,$(hurd-objpfx)hurd/%.h,io fs process)
+$(patsubst %,$(hurd-objpfx)hurd/%.%,io fs process):
+ $(MAKE) -C $(..)hurd generated no_deps=t
+endif
+
+# Generate errnos.h and sys_errlist.c from the section of the manual that
+# lists all the errno codes.
+
+errno.texinfo = $(..)manual/errno.texi
+
+hurd = $(..)sysdeps/mach/hurd
+
+$(hurd)/errnos.h: $(objpfx)stamp-errnos ;
+$(objpfx)stamp-errnos: $(hurd)/errnos.awk $(errno.texinfo) \
+ $(mach-srcdir)/mach/message.h \
+ $(mach-srcdir)/mach/kern_return.h \
+ $(mach-srcdir)/mach/mig_errors.h \
+ $(mach-srcdir)/device/device_types.h
+ gawk -f $^ > $(hurd)/errnos.h-tmp
+# Make it unwritable so noone will edit it by mistake.
+ -chmod a-w $(hurd)/errnos.h-tmp
+ ./$(..)move-if-change $(hurd)/errnos.h-tmp $(hurd)/errnos.h
+ test -d CVS && cvs commit -m'Regenerated from $^' $@
+ touch $@
+
+$(hurd)/errlist.c: $(hurd)/errlist.awk $(errno.texinfo)
+ gawk -f $^ > $@-tmp
+# Make it unwritable so noone will edit it by mistake.
+ -chmod a-w $@-tmp
+ mv -f $@-tmp $@
+ test -d CVS && cvs commit -m'Regenerated from $^' $@
+
+# We install the real libc.a as libcrt.a and as libc.a we install a linker
+# script which does -( -lcrt -lmachuser -lhurduser -).
+
+libc-name = crt
+
+ifeq (,$(subdir))
+install-others += $(libdir)/libc.a
+$(libdir)/libc.a: $(hurd)/libc-ldscript; $(do-install)
+endif
+
+
+endif # in-Makerules
diff --git a/sysdeps/mach/hurd/Subdirs b/sysdeps/mach/hurd/Subdirs
new file mode 100644
index 0000000000..16b8348437
--- /dev/null
+++ b/sysdeps/mach/hurd/Subdirs
@@ -0,0 +1 @@
+hurd
diff --git a/sysdeps/mach/hurd/_exit.c b/sysdeps/mach/hurd/_exit.c
new file mode 100644
index 0000000000..fd56791ee8
--- /dev/null
+++ b/sysdeps/mach/hurd/_exit.c
@@ -0,0 +1,54 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <sysdep.h>
+#include <sys/wait.h>
+
+void
+_hurd_exit (int status)
+{
+ /* Give the proc server our exit status. */
+ __USEPORT (PROC, __proc_mark_exit (port, status));
+
+ /* Commit suicide. */
+ __task_terminate (__mach_task_self ());
+
+ /* Perhaps the cached mach_task_self was bogus. */
+ __task_terminate ((__mach_task_self) ());
+
+ /* This sucker really doesn't want to die. */
+ while (1)
+ {
+#ifdef LOSE
+ LOSE;
+#else
+ volatile const int zero = 0, one = 1;
+ volatile int lossage = one / zero;
+#endif
+ }
+}
+
+void
+DEFUN(_exit, (status), int status)
+{
+ _hurd_exit (W_EXITCODE (status, 0));
+}
diff --git a/sysdeps/mach/hurd/accept.c b/sysdeps/mach/hurd/accept.c
new file mode 100644
index 0000000000..48402b1227
--- /dev/null
+++ b/sysdeps/mach/hurd/accept.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <sys/socket.h>
+#include <hurd/socket.h>
+#include <fcntl.h>
+#include <string.h>
+
+/* Await a connection on socket FD.
+ When a connection arrives, open a new socket to communicate with it,
+ set *ADDR (which is *ADDR_LEN bytes long) to the address of the connecting
+ peer and *ADDR_LEN to the address's actual length, and return the
+ new socket's descriptor, or -1 for errors. */
+int
+DEFUN(accept, (fd, addr, addr_len),
+ int fd AND struct sockaddr *addr AND size_t *addr_len)
+{
+ error_t err;
+ socket_t new;
+ addr_port_t aport;
+ char *buf = (char *) addr;
+ mach_msg_type_number_t buflen = *addr_len;
+ int type;
+
+ if (err = HURD_DPORT_USE (fd, __socket_accept (port, &new, &aport)))
+ return __hurd_dfail (fd, err);
+
+ if (addr != NULL)
+ err = __socket_whatis_address (aport, &type, &buf, &buflen);
+ __mach_port_deallocate (__mach_task_self (), aport);
+
+ if (err)
+ {
+ __mach_port_deallocate (__mach_task_self (), new);
+ return __hurd_dfail (fd, err);
+ }
+
+ if (addr != NULL)
+ {
+ if (buf != (char *) addr)
+ {
+ if (*addr_len < buflen)
+ *addr_len = buflen;
+ memcpy (addr, buf, *addr_len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ addr->sa_family = type;
+ }
+
+ return _hurd_intern_fd (new, O_IGNORE_CTTY, 1);
+}
diff --git a/sysdeps/mach/hurd/access.c b/sysdeps/mach/hurd/access.c
new file mode 100644
index 0000000000..90938060e0
--- /dev/null
+++ b/sysdeps/mach/hurd/access.c
@@ -0,0 +1,138 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <hurd/id.h>
+#include <fcntl.h>
+
+/* Test for access to FILE by our real user and group IDs. */
+int
+DEFUN(__access, (file, type), CONST char *file AND int type)
+{
+ error_t err;
+ file_t crdir, cwdir, rcrdir, rcwdir, io;
+ struct hurd_userlink crdir_ulink, cwdir_ulink;
+ int flags, allowed;
+ mach_port_t ref;
+
+ HURD_CRITICAL_BEGIN;
+
+ __mutex_lock (&_hurd_id.lock);
+ /* Get _hurd_id up to date. */
+ if (err = _hurd_check_ids ())
+ goto lose;
+
+ if (_hurd_id.rid_auth == MACH_PORT_NULL)
+ {
+ /* Set up _hurd_id.rid_auth. This is a special auth server port
+ which uses the real uid and gid (the first aux uid and gid) as
+ the only effective uid and gid. */
+
+ if (_hurd_id.aux.nuids < 1 || _hurd_id.aux.ngids < 1)
+ {
+ /* We do not have a real UID and GID. Lose, lose, lose! */
+ err = EGRATUITOUS;
+ goto lose;
+ }
+
+ /* Create a new auth port using our real UID and GID (the first
+ auxiliary UID and GID) as the only effective IDs. */
+ if (err = __USEPORT (AUTH,
+ __auth_makeauth (port,
+ NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ _hurd_id.aux.uids, 1,
+ _hurd_id.aux.gids, 1,
+ _hurd_id.aux.uids,
+ _hurd_id.aux.nuids,
+ _hurd_id.aux.gids,
+ _hurd_id.aux.ngids,
+ &_hurd_id.rid_auth)))
+ goto lose;
+ }
+
+ /* Get a port to our root directory, authenticated with the real IDs. */
+ crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
+ ref = __mach_reply_port ();
+ err = __io_reauthenticate (crdir, ref, MACH_MSG_TYPE_MAKE_SEND);
+ if (!err)
+ err = __auth_user_authenticate (_hurd_id.rid_auth,
+ crdir,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ &rcrdir);
+ _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
+ __mach_port_destroy (__mach_task_self (), ref);
+
+ if (!err)
+ {
+ /* Get a port to our current working directory, authenticated with
+ the real IDs. */
+ cwdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink);
+ ref = __mach_reply_port ();
+ err = __io_reauthenticate (cwdir, ref, MACH_MSG_TYPE_MAKE_SEND);
+ if (!err)
+ err = __auth_user_authenticate (_hurd_id.rid_auth,
+ cwdir,
+ ref, MACH_MSG_TYPE_MAKE_SEND,
+ &rcwdir);
+ _hurd_port_free (&_hurd_ports[INIT_PORT_CWDIR], &cwdir_ulink, cwdir);
+ __mach_port_destroy (__mach_task_self (), ref);
+ }
+
+ /* We are done with _hurd_id.rid_auth now. */
+ lose:
+ __mutex_unlock (&_hurd_id.lock);
+
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Now do a path lookup on FILE, using the crdir and cwdir
+ reauthenticated with _hurd_id.rid_auth. */
+
+ err = __hurd_file_name_lookup (rcrdir, rcwdir, file, 0, 0, &io);
+ __mach_port_deallocate (__mach_task_self (), rcrdir);
+ __mach_port_deallocate (__mach_task_self (), rcwdir);
+ if (err)
+ return __hurd_fail (err);
+
+ /* Find out what types of access we are allowed to this file. */
+ err = __file_check_access (io, &allowed);
+ __mach_port_deallocate (__mach_task_self (), io);
+ if (err)
+ return __hurd_fail (err);
+
+ flags = 0;
+ if (type & R_OK)
+ flags |= O_READ;
+ if (type & W_OK)
+ flags |= O_WRITE;
+ if (type & X_OK)
+ flags |= O_EXEC;
+
+ if (flags & ~allowed)
+ /* We are not allowed all the requested types of access. */
+ return __hurd_fail (EACCES);
+
+ return 0;
+}
+
+weak_alias (__access, access)
diff --git a/sysdeps/mach/hurd/adjtime.c b/sysdeps/mach/hurd/adjtime.c
new file mode 100644
index 0000000000..d88f404ce4
--- /dev/null
+++ b/sysdeps/mach/hurd/adjtime.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <hurd.h>
+
+/* Adjust the current time of day by the amount in DELTA.
+ If OLDDELTA is not NULL, it is filled in with the amount
+ of time adjustment remaining to be done from the last `__adjtime' call.
+ This call is restricted to the super-user. */
+int
+DEFUN(__adjtime, (delta, olddelta),
+ CONST struct timeval *delta AND
+ struct timeval *olddelta)
+{
+ error_t err;
+ mach_port_t hostpriv, devmaster;
+
+ if (err = __USEPORT (PROC, __proc_getprivports (port,
+ &hostpriv, &devmaster)))
+ return __hurd_fail (err);
+ __mach_port_deallocate (__mach_task_self (), devmaster);
+
+ err = __host_adjust_time (hostpriv,
+ /* `time_value_t' and `struct timeval' are in
+ fact identical with the names changed. */
+ *(time_value_t *) delta,
+ (time_value_t *) olddelta);
+ __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__adjtime, adjtime)
diff --git a/sysdeps/mach/hurd/alpha/exc2signal.c b/sysdeps/mach/hurd/alpha/exc2signal.c
new file mode 100644
index 0000000000..edac0aaa67
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/exc2signal.c
@@ -0,0 +1,76 @@
+/* Translate Mach exception codes into signal numbers. Alpha version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <mach/exception.h>
+
+/* Translate the Mach exception codes, as received in an `exception_raise' RPC,
+ into a signal number and signal subcode. */
+
+void
+_hurd_exception2signal (int exception, int code, int subcode,
+ int *signo, long int *sigcode, int *error)
+{
+ *error = 0;
+
+ switch (exception)
+ {
+ default:
+ *signo = SIGIOT;
+ *sigcode = exception;
+ break;
+
+ case EXC_BAD_ACCESS:
+ if (code == KERN_PROTECTION_FAILURE)
+ *signo = SIGSEGV;
+ else
+ *signo = SIGBUS;
+ *sigcode = subcode;
+ *error = code;
+ break;
+
+ case EXC_BAD_INSTRUCTION:
+ *signo = SIGILL;
+ *sigcode = code;
+ break;
+
+ case EXC_ARITHMETIC:
+ *signo = SIGFPE;
+ *sigcode = code;
+ break;
+ break;
+
+ case EXC_EMULATION:
+ /* 3.0 doesn't give this one, why, I don't know. */
+ *signo = SIGEMT;
+ *sigcode = code;
+ break;
+
+ case EXC_SOFTWARE:
+ *signo = SIGEMT;
+ *sigcode = code;
+ break;
+
+ case EXC_BREAKPOINT:
+ *signo = SIGTRAP;
+ *sigcode = code;
+ break;
+ }
+}
diff --git a/sysdeps/mach/hurd/alpha/longjmp-ctx.c b/sysdeps/mach/hurd/alpha/longjmp-ctx.c
new file mode 100644
index 0000000000..dfc16fdfe4
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/longjmp-ctx.c
@@ -0,0 +1,38 @@
+/* Perform a `longjmp' on a `struct sigcontext'. Alpha version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <setjmp.h>
+#include <hurd/signal.h>
+#include <string.h>
+
+void
+_hurd_longjmp_sigcontext (struct sigcontext *scp, jmp_buf env, int retval)
+{
+ memset (scp, 0, sizeof (*scp));
+ scp->sc_regs[9] = env[0].__9;
+ scp->sc_regs[11] = env[0].__11;
+ scp->sc_regs[12] = env[0].__12;
+ scp->sc_regs[13] = env[0].__13;
+ scp->sc_regs[14] = env[0].__14;
+ scp->sc_regs[15] = (long int) env[0].__fp;
+ scp->sc_regs[30] = (long int) env[0].__sp;
+ scp->sc_pc = (long int) env[0].__pc;
+
+ memcpy (&scp->sc_fpregs[2], &env[0].__f2, sizeof (double));
+}
diff --git a/sysdeps/mach/hurd/alpha/longjmp-ts.c b/sysdeps/mach/hurd/alpha/longjmp-ts.c
new file mode 100644
index 0000000000..ad6f80cdb0
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/longjmp-ts.c
@@ -0,0 +1,41 @@
+/* Perform a `longjmp' on a Mach thread_state. Alpha version.
+Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include <setjmp.h>
+#include <mach/thread_status.h>
+
+
+/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */
+
+void
+_hurd_longjmp_thread_state (void *state, jmp_buf env, int val)
+{
+ struct alpha_thread_state *ts = state;
+
+ ts->r9 = env[0].__jmpbuf[0].__9;
+ ts->r11 = env[0].__jmpbuf[0].__11;
+ ts->r12 = env[0].__jmpbuf[0].__12;
+ ts->r13 = env[0].__jmpbuf[0].__13;
+ ts->r14 = env[0].__jmpbuf[0].__14;
+ ts->r15 = (long int) env[0].__jmpbuf[0].__fp;
+ ts->r30 = (long int) env[0].__jmpbuf[0].__sp;
+ ts->pc = (long int) env[0].__jmpbuf[0].__pc;
+ ts->r0 = val ?: 1;
+}
diff --git a/sysdeps/mach/hurd/alpha/sigcontext.h b/sysdeps/mach/hurd/alpha/sigcontext.h
new file mode 100644
index 0000000000..32e0c94f98
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/sigcontext.h
@@ -0,0 +1,65 @@
+/* Machine-dependent signal context structure for GNU Hurd. Alpha version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Signal handlers are actually called:
+ void handler (int sig, int code, struct sigcontext *scp); */
+
+/* State of this thread when the signal was taken. */
+struct sigcontext
+ {
+ /* These first members are machine-independent. */
+
+ long int sc_onstack; /* Nonzero if running on sigstack. */
+ __sigset_t sc_mask; /* Blocked signals to restore. */
+
+ /* MiG reply port this thread is using. */
+ unsigned long int sc_reply_port;
+
+ /* Port this thread is doing an interruptible RPC on. */
+ unsigned long int sc_intr_port;
+
+ /* Error code associated with this signal (interpreted as `error_t'). */
+ int sc_error;
+
+ /* All following members are machine-dependent. The rest of this
+ structure is written to be laid out identically to:
+ {
+ struct alpha_thread_state basic;
+ struct alpha_exc_state exc;
+ struct alpha_float_state fpu;
+ }
+ trampoline.c knows this, so it must be changed if this changes. */
+
+#define sc_alpha_thread_state sc_regs /* Beginning of correspondence. */
+ long int sc_regs[31]; /* General registers $0..$30. */
+ long int sc_pc; /* Program counter. */
+
+ /* struct alpha_exc_state */
+#define sc_alpha_exc_state sc_badvaddr
+ unsigned long int sc_badvaddr;
+ unsigned int sc_cause; /* Machine-level trap code. */
+#define SC_CAUSE_SET_SSTEP 1
+ int sc_used_fpa; /* Nonzero if FPU was used. */
+
+ /* struct alpha_float_state
+ This is only filled in if sc_used_fpa is nonzero. */
+#define sc_alpha_float_state sc_fpregs
+ double sc_fpregs[31]; /* Floating point registers $f0..$f30. */
+ long int sc_fpcsr; /* Floating point control/status register. */
+ };
diff --git a/sysdeps/mach/hurd/alpha/sigreturn.c b/sysdeps/mach/hurd/alpha/sigreturn.c
new file mode 100644
index 0000000000..e5dc383a3a
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/sigreturn.c
@@ -0,0 +1,212 @@
+/* Return from signal handler in GNU C library for Hurd. Alpha version.
+Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/threadvar.h>
+#include <hurd/msg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mach/machine/alpha_instruction.h>
+
+int
+__sigreturn (struct sigcontext *scp)
+{
+ struct hurd_sigstate *ss;
+ mach_port_t *reply_port;
+
+ if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss = _hurd_self_sigstate ();
+ __spin_lock (&ss->lock);
+
+ /* Restore the set of blocked signals, and the intr_port slot. */
+ ss->blocked = scp->sc_mask;
+ ss->intr_port = scp->sc_intr_port;
+
+ /* Check for pending signals that were blocked by the old set. */
+ if (ss->pending & ~ss->blocked)
+ {
+ /* There are pending signals that just became unblocked. Wake up the
+ signal thread to deliver them. But first, squirrel away SCP where
+ the signal thread will notice it if it runs another handler, and
+ arrange to have us called over again in the new reality. */
+ ss->context = scp;
+ /* Clear the intr_port slot, since we are not in fact doing
+ an interruptible RPC right now. If SS->intr_port is not null,
+ the SCP context is doing an interruptible RPC, but the signal
+ thread will examine us while we are blocked in the sig_post RPC. */
+ ss->intr_port = MACH_PORT_NULL;
+ __spin_unlock (&ss->lock);
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+ /* If a pending signal was handled, sig_post never returned. */
+ __spin_lock (&ss->lock);
+ }
+
+ if (scp->sc_onstack)
+ {
+ ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
+ /* XXX cannot unlock until off sigstack */
+ abort ();
+ }
+ else
+ __spin_unlock (&ss->lock);
+
+ /* Destroy the MiG reply port used by the signal handler, and restore the
+ reply port in use by the thread when interrupted. */
+ reply_port =
+ (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ if (*reply_port)
+ __mach_port_destroy (__mach_task_self (), *reply_port);
+ *reply_port = scp->sc_reply_port;
+
+ if (scp->sc_used_fpa)
+ {
+ /* Restore FPU state. */
+
+ /* Restore the floating-point control/status register.
+ We must do this first because the compiler will need
+ a temporary FP register for the load. */
+ asm volatile ("mt_fpcr %0" : : "f" (scp->sc_fpcsr));
+
+ /* Restore floating-point registers. */
+#define restore_fpr(n) \
+ asm volatile ("ldt $f" #n ",%0" : : "m" (scp->sc_fpregs[n]))
+ restore_fpr (0);
+ restore_fpr (1);
+ restore_fpr (2);
+ restore_fpr (3);
+ restore_fpr (4);
+ restore_fpr (5);
+ restore_fpr (6);
+ restore_fpr (7);
+ restore_fpr (8);
+ restore_fpr (9);
+ restore_fpr (10);
+ restore_fpr (11);
+ restore_fpr (12);
+ restore_fpr (13);
+ restore_fpr (14);
+ restore_fpr (15);
+ restore_fpr (16);
+ restore_fpr (17);
+ restore_fpr (18);
+ restore_fpr (19);
+ restore_fpr (20);
+ restore_fpr (21);
+ restore_fpr (22);
+ restore_fpr (23);
+ restore_fpr (24);
+ restore_fpr (25);
+ restore_fpr (26);
+ restore_fpr (27);
+ restore_fpr (28);
+ restore_fpr (29);
+ restore_fpr (30);
+ }
+
+ /* Load all the registers from the sigcontext. */
+#define restore_gpr(n) \
+ asm volatile ("ldq $" #n ",%0" : : "m" (scpreg->sc_regs[n]))
+
+ {
+ /* The `rei' PAL pseudo-instruction restores registers $2..$7, the PC
+ and processor status. So we can use these few registers for our
+ working variables. Unfortunately, it finds its data on the stack
+ and merely pops the SP ($30) over the words of state restored,
+ allowing no other option for the new SP value. So we must push the
+ registers and PSW it will to restore, onto the user's stack and let
+ it pop them from there. */
+ register const struct sigcontext *const scpreg asm ("$2") = scp;
+ register integer_t *usp asm ("$3") = (integer_t *) scpreg->sc_regs[30];
+ register integer_t usp_align asm ("$4");
+
+ /* Push an 8-word "trap frame" onto the user stack for `rei':
+ registers $2..$7, the PC, and the PSW. */
+
+ register struct rei_frame
+ {
+ integer_t regs[5], pc, ps;
+ } *rei_frame asm ("$5");
+
+ usp -= 8;
+ /* `rei' demands that the stack be aligned to a 64 byte (8 word)
+ boundary; bits 61..56 of the PSW are OR'd back into the SP value
+ after popping the 8-word trap frame, so we store (sp % 64)
+ there and this restores the original user SP. */
+ usp_align = (integer_t) usp & 63L;
+ rei_frame = (void *) ((integer_t) usp & ~63L);
+
+ /* Copy the registers and PC from the sigcontext. */
+ memcpy (rei_frame->regs, &scpreg->sc_regs[2], sizeof rei_frame->regs);
+ rei_frame->pc = scpreg->sc_pc;
+
+ /* Compute the new PS value to be restored. `rei' adds the value at
+ bits 61..56 to the SP to compensate for the alignment above that
+ cleared the low 6 bits; bits 5..3 are the new mode/privilege level
+ (must be >= current mode; 3 == user mode); bits 2..0 are "software",
+ unused by the processor or kernel (XXX should trampoline save these?
+ How?); in user mode, `rei' demands that all other bits be zero. */
+ rei_frame->ps = (usp_align << 56) | (3 << 3); /* XXX low 3 bits??? */
+
+ /* Restore the other general registers: everything except $2..$7, which
+ are in the `rei' trap frame we set up above, and $30, which is the
+ SP which is popped by `rei'. */
+ restore_gpr (1);
+ restore_gpr (8);
+ restore_gpr (9);
+ restore_gpr (10);
+ restore_gpr (11);
+ restore_gpr (12);
+ restore_gpr (13);
+ restore_gpr (14);
+ restore_gpr (15);
+ restore_gpr (16);
+ restore_gpr (17);
+ restore_gpr (18);
+ restore_gpr (19);
+ restore_gpr (20);
+ restore_gpr (21);
+ restore_gpr (22);
+ restore_gpr (23);
+ restore_gpr (24);
+ restore_gpr (25);
+ restore_gpr (26);
+ restore_gpr (27);
+ restore_gpr (28);
+ restore_gpr (29);
+
+ /* Switch the stack pointer to the trap frame set up on
+ the user stack and do the magical `rei' PAL call. */
+ asm volatile ("mov %0, $30\n"
+ "call_pal %1"
+ : : "r" (rei_frame), "i" (op_rei));
+ /* Firewall. */
+ asm volatile ("call_pal %0" : : "i" (op_halt));
+ }
+
+ /* NOTREACHED */
+ return -1;
+}
+
+weak_alias (__sigreturn, sigreturn)
diff --git a/sysdeps/mach/hurd/alpha/trampoline.c b/sysdeps/mach/hurd/alpha/trampoline.c
new file mode 100644
index 0000000000..85f4964e14
--- /dev/null
+++ b/sysdeps/mach/hurd/alpha/trampoline.c
@@ -0,0 +1,286 @@
+/* Set thread_state for sighandler, and sigcontext to recover. Alpha version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include "thread_state.h"
+#include <mach/machine/alpha_instruction.h>
+#include "hurdfault.h"
+#include <assert.h>
+
+struct mach_msg_trap_args
+ {
+ /* This is the order of arguments to mach_msg_trap. */
+ mach_msg_header_t *msg;
+ mach_msg_option_t option;
+ mach_msg_size_t send_size;
+ mach_msg_size_t rcv_size;
+ mach_port_t rcv_name;
+ mach_msg_timeout_t timeout;
+ mach_port_t notify;
+ };
+
+
+struct sigcontext *
+_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ int signo, long int sigcode,
+ int rpc_wait,
+ struct machine_thread_all_state *state)
+{
+ __label__ trampoline, rpc_wait_trampoline;
+ void *sigsp;
+ struct sigcontext *scp;
+
+ if (ss->context)
+ {
+ /* We have a previous sigcontext that sigreturn was about
+ to restore when another signal arrived. We will just base
+ our setup on that. */
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
+ _hurdsig_fault_sigcode < (long int) (ss->context + 1));
+ else
+ {
+ memcpy (&state->basic, &ss->context->sc_alpha_thread_state,
+ sizeof (state->basic));
+ memcpy (&state->exc, &ss->context->sc_alpha_exc_state,
+ sizeof (state->exc));
+ state->set = (1 << ALPHA_THREAD_STATE) | (1 << ALPHA_EXC_STATE);
+ if (state->exc.used_fpa)
+ {
+ memcpy (&state->fpu, &ss->context->sc_alpha_float_state,
+ sizeof (state->fpu));
+ state->set |= (1 << ALPHA_FLOAT_STATE);
+ }
+ assert (! rpc_wait);
+ /* The intr_port slot was cleared before sigreturn sent us the
+ sig_post that made us notice this pending signal, so
+ _hurd_internal_post_signal wouldn't do interrupt_operation.
+ After we return, our caller will set SCP->sc_intr_port (in the
+ new context) from SS->intr_port and clear SS->intr_port. Now
+ that we are restoring this old context recorded by sigreturn,
+ we want to restore its intr_port too; so store it in
+ SS->intr_port now, so it will end up in SCP->sc_intr_port
+ later. */
+ ss->intr_port = ss->context->sc_intr_port;
+ }
+ /* If the sigreturn context was bogus, just ignore it. */
+ ss->context = NULL;
+ }
+ else if (! machine_get_basic_state (ss->thread, state))
+ return NULL;
+
+ if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ !(ss->sigaltstack.ss_flags & (SA_DISABLE|SA_ONSTACK)))
+ {
+ sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
+ ss->sigaltstack.ss_flags |= SA_ONSTACK;
+ /* XXX need to set up base of new stack for
+ per-thread variables, cthreads. */
+ }
+ else
+ sigsp = (char *) state->basic.SP;
+
+ /* Set up the sigcontext structure on the stack. This is all the stack
+ needs, since the args are passed in registers (below). */
+ sigsp -= sizeof (*scp);
+ scp = sigsp;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode >= (long int) scp &&
+ _hurdsig_fault_sigcode < (long int) (scp + 1));
+ /* We got a fault trying to write the stack frame.
+ We cannot set up the signal handler.
+ Returning NULL tells our caller, who will nuke us with a SIGILL. */
+ return NULL;
+ }
+ else
+ {
+ /* Set up the sigcontext from the current state of the thread. */
+
+ scp->sc_onstack = ss->sigaltstack.ss_flags & SA_ONSTACK ? 1 : 0;
+
+ /* struct sigcontext is laid out so that starting at sc_regs
+ mimics a struct alpha_thread_state. */
+ memcpy (&scp->sc_alpha_thread_state,
+ &state->basic, sizeof (state->basic));
+
+ /* struct sigcontext is laid out so that starting at sc_badvaddr
+ mimics a struct mips_exc_state. */
+ if (! machine_get_state (ss->thread, state, ALPHA_EXC_STATE,
+ &state->exc, &scp->sc_alpha_exc_state,
+ sizeof (state->exc)))
+ return NULL;
+
+ if (state->exc.used_fpa &&
+ /* struct sigcontext is laid out so that starting at sc_fpregs
+ mimics a struct alpha_float_state. This state
+ is only meaningful if the coprocessor was used. */
+ ! machine_get_state (ss->thread, state, ALPHA_FLOAT_STATE,
+ &state->fpu,
+ &scp->sc_alpha_float_state,
+ sizeof (state->fpu)))
+ return NULL;
+ }
+
+ /* Modify the thread state to call the trampoline code on the new stack. */
+ if (rpc_wait)
+ {
+ /* The signalee thread was blocked in a mach_msg_trap system call,
+ still waiting for a reply. We will have it run the special
+ trampoline code which retries the message receive before running
+ the signal handler.
+
+ To do this we change the OPTION argument in its registers to
+ enable only message reception, since the request message has
+ already been sent. */
+
+ /* The system call arguments are stored in consecutive registers
+ starting with a0 ($16). */
+ struct mach_msg_trap_args *args = (void *) &state->basic.r16;
+
+ assert (args->option & MACH_RCV_MSG);
+ /* Disable the message-send, since it has already completed. The
+ calls we retry need only wait to receive the reply message. */
+ args->option &= ~MACH_SEND_MSG;
+
+ state->basic.pc = (long int) &&rpc_wait_trampoline;
+ /* After doing the message receive, the trampoline code will need to
+ update the v0 ($0) value to be restored by sigreturn. To simplify
+ the assembly code, we pass the address of its slot in SCP to the
+ trampoline code in at ($28). */
+ state->basic.r28 = (long int) &scp->sc_regs[0];
+ /* We must preserve the mach_msg_trap args in a0..a5 and t0
+ ($16..$21, $1). Pass the handler args to the trampoline code in
+ t8..t10 ($22.$24). */
+ state->basic.r22 = signo;
+ state->basic.r23 = sigcode;
+ state->basic.r24 = (long int) scp;
+ }
+ else
+ {
+ state->basic.pc = (long int) &&trampoline;
+ state->basic.r16 = signo;
+ state->basic.r17 = sigcode;
+ state->basic.r18 = (long int) scp;
+ }
+
+ state->basic.r30 = (long int) sigsp; /* $30 is the stack pointer. */
+
+ /* We pass the handler function to the trampoline code in ra ($26). */
+ state->basic.r26 = (long int) handler;
+ /* In the callee-saved register t12/pv ($27), we store the
+ address of __sigreturn itself, for the trampoline code to use. */
+ state->basic.r27 = (long int) &__sigreturn;
+ /* In the callee-saved register t11/ai ($25), we save the SCP value to pass
+ to __sigreturn after the handler returns. */
+ state->basic.r25 = (long int) scp;
+
+ return scp;
+
+ /* The trampoline code follows. This is not actually executed as part of
+ this function, it is just convenient to write it that way. */
+
+ rpc_wait_trampoline:
+ /* This is the entry point when we have an RPC reply message to receive
+ before running the handler. The MACH_MSG_SEND bit has already been
+ cleared in the OPTION argument in our registers. For our convenience,
+ at ($28) points to the sc_regs[0] member of the sigcontext (saved v0
+ ($0)). */
+ asm volatile
+ (/* Retry the interrupted mach_msg system call. */
+ "lda $0, -25($31)\n" /* mach_msg_trap */
+ "call_pal %0\n" /* Magic system call instruction. */
+ /* When the sigcontext was saved, v0 was MACH_RCV_INTERRUPTED. But
+ now the message receive has completed and the original caller of
+ the RPC (i.e. the code running when the signal arrived) needs to
+ see the final return value of the message receive in v0. So
+ store the new v0 value into the sc_regs[0] member of the sigcontext
+ (whose address is in at to make this code simpler). */
+ "stq $0, 0($28)\n"
+ /* Since the argument registers needed to have the mach_msg_trap
+ arguments, we've stored the arguments to the handler function
+ in registers t8..t10 ($22..$24). */
+ "mov $22, $16\n"
+ "mov $23, $17\n"
+ "mov $24, $18\n"
+ : : "i" (op_chmk));
+
+ trampoline:
+ /* Entry point for running the handler normally. The arguments to the
+ handler function are already in the standard registers:
+
+ a0 SIGNO
+ a1 SIGCODE
+ a2 SCP
+
+ t12 also contains SCP; this value is callee-saved (and so should not get
+ clobbered by running the handler). We use this saved value to pass to
+ __sigreturn, so the handler can clobber the argument registers if it
+ likes. */
+ /* Call the handler function, saving return address in ra ($26). */
+ asm volatile ("jsr $26, ($26)");
+ /* Reset gp ($29) from the return address (here) in ra ($26). */
+ asm volatile ("ldgp $29, 0($26)");
+ asm volatile ("mov $25, $16"); /* Move saved SCP to argument register. */
+ /* Call __sigreturn (SCP); this cannot return. */
+ asm volatile ("jmp $31, ($27)");
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+/* STATE describes a thread that had intr_port set (meaning it was inside
+ HURD_EINTR_RPC), after it has been thread_abort'd. If it looks to have
+ just completed a mach_msg_trap system call that returned
+ MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right
+ being waited on. */
+int
+_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
+ mach_port_t *port)
+{
+ if (state->basic.r0 == MACH_RCV_INTERRUPTED)
+ {
+ const unsigned int *pc = (void *) state->basic.pc;
+ struct mach_msg_trap_args *args = (void *) &state->basic.r16;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode == (long int) (pc - 1) ||
+ _hurdsig_fault_sigcode == (long int) &args->rcv_name);
+ /* We got a fault trying to read the PC or stack. */
+ return 0;
+ }
+ else
+ {
+ if (pc[-1] == ((alpha_instruction) { pal_format:
+ { opcode: op_pal,
+ function: op_chmk } }).bits)
+ {
+ /* We did just return from a mach_msg_trap system call
+ doing a message receive that was interrupted.
+ Examine the parameters to find the receive right. */
+ *port = args->rcv_name;
+ return 1;
+ }
+ }
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/bind.c b/sysdeps/mach/hurd/bind.c
new file mode 100644
index 0000000000..e9e54ec8dc
--- /dev/null
+++ b/sysdeps/mach/hurd/bind.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <hurd/ifsock.h>
+#include <sys/un.h>
+#include <string.h>
+
+/* Give the socket FD the local address ADDR (which is LEN bytes long). */
+int
+DEFUN(bind, (fd, addr, len),
+ int fd AND struct sockaddr *addr AND size_t len)
+{
+ addr_port_t aport;
+ error_t err;
+
+ if (addr->sa_family == AF_LOCAL)
+ {
+ /* For the local domain, we must create a node in the filesystem
+ using the ifsock translator and then fetch the address from it. */
+ struct sockaddr_un *unaddr = (struct sockaddr_un *) addr;
+ file_t dir, node;
+ char name[len - offsetof (struct sockaddr_un, sun_path)], *n;
+ strncpy (name, unaddr->sun_path, sizeof name);
+ dir = __file_name_split (name, &n);
+ if (dir == MACH_PORT_NULL)
+ return -1;
+
+ /* Create a new, unlinked node in the target directory. */
+ err = __dir_mkfile (dir, O_CREAT, 0666 & ~_hurd_umask, &node);
+
+ if (! err)
+ {
+ file_t ifsock;
+ /* Set the node's translator to make it a local-domain socket. */
+ err = __file_set_translator (node,
+ FS_TRANS_EXCL | FS_TRANS_SET,
+ FS_TRANS_EXCL | FS_TRANS_SET, 0,
+ _HURD_IFSOCK, sizeof _HURD_IFSOCK,
+ MACH_PORT_NULL,
+ MACH_MSG_TYPE_COPY_SEND);
+ if (! err)
+ /* Get a port to the ifsock translator. */
+ err = __hurd_invoke_translator (node, 0, &ifsock);
+ if (! err)
+ /* Get the address port. */
+ err = __ifsock_getsockaddr (ifsock, &aport);
+ __mach_port_deallocate (__mach_task_self (), ifsock);
+ if (! err)
+ /* Link the node, now a socket, into the target directory. */
+ err = __dir_link (node, dir, name);
+ __mach_port_deallocate (__mach_task_self (), node);
+ }
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ if (err)
+ return __hurd_fail (err);
+ }
+ else
+ err = EIEIO;
+
+ err = HURD_DPORT_USE (fd,
+ ({
+ if (err)
+ err = __socket_create_address (port,
+ addr->sa_family,
+ (char *) addr, len,
+ &aport, 1);
+ if (! err)
+ {
+ err = __socket_bind (port, aport);
+ __mach_port_deallocate (__mach_task_self (),
+ aport);
+ }
+ err;
+ }));
+
+ return err ? __hurd_dfail (fd, err) : 0;
+}
diff --git a/sysdeps/mach/hurd/brk.c b/sysdeps/mach/hurd/brk.c
new file mode 100644
index 0000000000..a96286b2d9
--- /dev/null
+++ b/sysdeps/mach/hurd/brk.c
@@ -0,0 +1,130 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/resource.h>
+#include <cthreads.h> /* For `struct mutex'. */
+
+
+/* Initial maximum size of the data segment (32MB, which is arbitrary). */
+#define DATA_SIZE (32 * 1024 * 1024)
+
+
+/* Up to the page including this address is allocated from the kernel.
+ This address is the data resource limit. */
+vm_address_t _hurd_data_end;
+
+/* Up to this address is actually available to the user.
+ Pages beyond the one containing this address allow no access. */
+vm_address_t _hurd_brk;
+
+struct mutex _hurd_brk_lock;
+
+extern int __data_start, _end;
+
+
+/* Set the end of the process's data space to INADDR.
+ Return 0 if successful, -1 if not. */
+int
+DEFUN(__brk, (inaddr), PTR inaddr)
+{
+ int ret;
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_brk_lock);
+ ret = _hurd_set_brk ((vm_address_t) inaddr);
+ __mutex_unlock (&_hurd_brk_lock);
+ HURD_CRITICAL_END;
+ return ret;
+}
+weak_alias (__brk, brk)
+
+
+int
+_hurd_set_brk (vm_address_t addr)
+{
+ error_t err;
+ vm_address_t pagend = round_page (addr);
+ vm_address_t pagebrk = round_page (_hurd_brk);
+ long int rlimit;
+
+ if (pagend <= pagebrk)
+ {
+ if (pagend < pagebrk)
+ /* Make that memory inaccessible. */
+ __vm_protect (__mach_task_self (), pagend, pagebrk - pagend,
+ 0, VM_PROT_NONE);
+ _hurd_brk = addr;
+ return 0;
+ }
+
+ __mutex_lock (&_hurd_rlimit_lock);
+ rlimit = _hurd_rlimits[RLIMIT_DATA].rlim_cur;
+ __mutex_unlock (&_hurd_rlimit_lock);
+
+ if (addr - (vm_address_t) &__data_start > rlimit)
+ {
+ /* Need to increase the resource limit. */
+ errno = ENOMEM;
+ return -1;
+ }
+
+ /* Make the memory accessible. */
+ if (err = __vm_protect (__mach_task_self (), pagebrk, pagend - pagebrk,
+ 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE))
+ {
+ errno = err;
+ return -1;
+ }
+
+ _hurd_brk = addr;
+ return 0;
+}
+
+static void
+init_brk (void)
+{
+ vm_address_t pagend;
+
+ __mutex_init (&_hurd_brk_lock);
+
+ /* If _hurd_brk is already set, don't change it. The assumption is that
+ it was set in a previous run before something like Emacs's unexec was
+ called and dumped all the data up to the break at that point. */
+ if (_hurd_brk == 0)
+ _hurd_brk = (vm_address_t) &_end;
+
+ pagend = round_page (_hurd_brk);
+
+ _hurd_data_end = (vm_address_t) &__data_start + DATA_SIZE;
+
+ if (pagend < _hurd_data_end)
+ {
+ /* We use vm_map to allocate and change permissions atomically. */
+ if (__vm_map (__mach_task_self (), &pagend, _hurd_data_end - pagend,
+ 0, 0, MACH_PORT_NULL, 0, 0,
+ 0, VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE,
+ VM_INHERIT_COPY))
+ /* Couldn't allocate the memory. The break will be very short. */
+ _hurd_data_end = pagend;
+ }
+
+ (void) &init_brk; /* Avoid ``defined but not used'' warning. */
+}
+text_set_element (_hurd_preinit_hook, init_brk);
diff --git a/sysdeps/mach/hurd/chdir.c b/sysdeps/mach/hurd/chdir.c
new file mode 100644
index 0000000000..912ca08683
--- /dev/null
+++ b/sysdeps/mach/hurd/chdir.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <fcntl.h>
+#include <hurd/port.h>
+
+/* Change the current directory to FILE_NAME. */
+int
+DEFUN(__chdir, (file_name), CONST char *file_name)
+{
+ file_t file, dir;
+ error_t err;
+
+ file = __file_name_lookup (file_name, O_EXEC, 0);
+ if (file == MACH_PORT_NULL)
+ return -1;
+ err = __USEPORT (CRDIR, __hurd_file_name_lookup (port, file, "",
+ O_EXEC, 0, &dir));
+ __mach_port_deallocate (__mach_task_self (), file);
+ if (err)
+ return __hurd_fail (err);
+
+ _hurd_port_set (&_hurd_ports[INIT_PORT_CWDIR], dir);
+ return 0;
+}
+
+weak_alias (__chdir, chdir)
diff --git a/sysdeps/mach/hurd/chflags.c b/sysdeps/mach/hurd/chflags.c
new file mode 100644
index 0000000000..157940d19b
--- /dev/null
+++ b/sysdeps/mach/hurd/chflags.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+
+/* Change the flags of FILE to FLAGS. */
+int
+DEFUN(chflags, (file, flags), CONST char *file AND int flags)
+{
+ error_t err;
+ file_t port = __file_name_lookup (file, 0, 0);
+ if (port == MACH_PORT_NULL)
+ return -1;
+ err = __file_chflags (port, flags);
+ __mach_port_deallocate (__mach_task_self (), port);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/chmod.c b/sysdeps/mach/hurd/chmod.c
new file mode 100644
index 0000000000..00a81ef0cf
--- /dev/null
+++ b/sysdeps/mach/hurd/chmod.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+
+/* Change the protections of FILE to MODE. */
+int
+DEFUN(__chmod, (file, mode), CONST char *file AND mode_t mode)
+{
+ error_t err;
+ file_t port = __file_name_lookup (file, 0, 0);
+ if (port == MACH_PORT_NULL)
+ return -1;
+ err = __file_chmod (port, mode);
+ __mach_port_deallocate (__mach_task_self (), port);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__chmod, chmod)
diff --git a/sysdeps/mach/hurd/chown.c b/sysdeps/mach/hurd/chown.c
new file mode 100644
index 0000000000..a1ed9d5e14
--- /dev/null
+++ b/sysdeps/mach/hurd/chown.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Change the owner and group of FILE. */
+int
+DEFUN(__chown, (file, owner, group),
+ CONST char *file AND uid_t owner AND gid_t group)
+{
+ error_t err;
+ file_t port = __file_name_lookup (file, 0, 0);
+ if (port == MACH_PORT_NULL)
+ return -1;
+ err = __file_chown (port, owner, group);
+ __mach_port_deallocate (__mach_task_self (), port);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__chown, chown)
diff --git a/sysdeps/mach/hurd/chroot.c b/sysdeps/mach/hurd/chroot.c
new file mode 100644
index 0000000000..415a068004
--- /dev/null
+++ b/sysdeps/mach/hurd/chroot.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <fcntl.h>
+#include <hurd/port.h>
+
+/* Change the current root to FILE_NAME. */
+int
+DEFUN(chroot, (file_name), CONST char *file_name)
+{
+ file_t file, dir;
+ error_t err;
+
+ file = __file_name_lookup (file_name, O_EXEC, 0);
+ if (file == MACH_PORT_NULL)
+ return -1;
+ err = __USEPORT (CRDIR, __hurd_file_name_lookup (port, file, "",
+ O_EXEC, 0, &dir));
+ __mach_port_deallocate (__mach_task_self (), file);
+ if (err)
+ return __hurd_fail (err);
+
+ _hurd_port_set (&_hurd_ports[INIT_PORT_CRDIR], dir);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/close.c b/sysdeps/mach/hurd/close.c
new file mode 100644
index 0000000000..259687e1fb
--- /dev/null
+++ b/sysdeps/mach/hurd/close.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Close the file descriptor FD. */
+int
+DEFUN(__close, (fd), int fd)
+{
+ error_t err;
+
+ err = HURD_FD_USE (fd, _hurd_fd_close (descriptor));
+
+ return err ? __hurd_fail (err) : 0;
+}
+
+weak_alias (__close, close)
diff --git a/sysdeps/mach/hurd/closedir.c b/sysdeps/mach/hurd/closedir.c
new file mode 100644
index 0000000000..9d20621747
--- /dev/null
+++ b/sysdeps/mach/hurd/closedir.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Close the directory stream DIRP.
+ Return 0 if successful, -1 if not. */
+int
+DEFUN(closedir, (dirp), DIR *dirp)
+{
+ error_t err;
+
+ if (dirp == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((err = __vm_deallocate (__mach_task_self (),
+ (vm_address_t) dirp->__data, dirp->__allocation))
+ || (err = __mach_port_deallocate (__mach_task_self (), dirp->__port)))
+ {
+ errno = err;
+ return -1;
+ }
+
+ free (dirp);
+
+ return 0;
+}
+
diff --git a/sysdeps/mach/hurd/configure b/sysdeps/mach/hurd/configure
new file mode 100755
index 0000000000..a396cd0024
--- /dev/null
+++ b/sysdeps/mach/hurd/configure
@@ -0,0 +1,21 @@
+
+# If configure is passed `--with-hurd=DIR', set `hurd-srcdir' to DIR in
+# config.make.
+
+ac_help="$ac_help
+ --with-hurd=DIRECTORY find Hurd source code in DIRECTORY [../hurd]"
+# Check whether --with-hurd or --without-hurd was given.
+withval="$with_hurd"
+if test -n "$withval"; then
+ case z"$with_hurd" in
+z | zno | zyes) ;; # Not specified, or specified with no value.
+z*) config_vars="$config_vars
+hurd-srcdir = $with_hurd" ;;
+esac
+
+fi
+
+
+# Don't bother trying to generate any glue code to be compatible with the
+# existing system library, because we are the only system library.
+inhibit_glue=yes
diff --git a/sysdeps/mach/hurd/configure.in b/sysdeps/mach/hurd/configure.in
new file mode 100644
index 0000000000..39e1002d6e
--- /dev/null
+++ b/sysdeps/mach/hurd/configure.in
@@ -0,0 +1,19 @@
+sinclude(./aclocal.m4)dnl Autoconf lossage.
+GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+
+# If configure is passed `--with-hurd=DIR', set `hurd-srcdir' to DIR in
+# config.make.
+
+AC_ARG_WITH(hurd, dnl
+[ --with-hurd=DIRECTORY find Hurd source code in DIRECTORY [../hurd]],
+ [dnl
+case z"$with_hurd" in
+z | zno | zyes) ;; # Not specified, or specified with no value.
+z*) config_vars="$config_vars
+hurd-srcdir = $with_hurd" ;;
+esac
+])
+
+# Don't bother trying to generate any glue code to be compatible with the
+# existing system library, because we are the only system library.
+inhibit_glue=yes
diff --git a/sysdeps/mach/hurd/connect.c b/sysdeps/mach/hurd/connect.c
new file mode 100644
index 0000000000..e015a14c50
--- /dev/null
+++ b/sysdeps/mach/hurd/connect.c
@@ -0,0 +1,75 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <sys/socket.h>
+#include <hurd/socket.h>
+#include <sys/un.h>
+#include <hurd/ifsock.h>
+
+/* Open a connection on socket FD to peer at ADDR (which LEN bytes long).
+ For connectionless socket types, just set the default address to send to
+ and the only address from which to accept transmissions.
+ Return 0 on success, -1 for errors. */
+int
+DEFUN(connect, (fd, addr, len),
+ int fd AND struct sockaddr *addr AND size_t len)
+{
+ error_t err;
+ addr_port_t aport;
+
+ if (addr->sa_family == AF_LOCAL)
+ {
+ /* For the local domain, we must look up the name as a file and talk
+ to it with the ifsock protocol. */
+ struct sockaddr_un *unaddr = (struct sockaddr_un *) addr;
+ file_t file = __file_name_lookup (unaddr->sun_path, 0, 0);
+ if (file == MACH_PORT_NULL)
+ return -1;
+ err = __ifsock_getsockaddr (file, &aport);
+ __mach_port_deallocate (__mach_task_self (), file);
+ if (err == MIG_BAD_ID || err == EOPNOTSUPP)
+ /* The file did not grok the ifsock protocol. */
+ err = ENOTSOCK;
+ if (err)
+ return __hurd_fail (err);
+ }
+ else
+ err = EIEIO;
+
+ err = HURD_DPORT_USE (fd,
+ ({
+ if (err)
+ err = __socket_create_address (port,
+ addr->sa_family,
+ (char *) addr, len,
+ &aport, 0);
+ if (! err)
+ {
+ err = __socket_connect (port, aport);
+ __mach_port_deallocate (__mach_task_self (),
+ aport);
+ }
+ err;
+ }));
+
+ return err ? __hurd_dfail (fd, err) : 0;
+}
diff --git a/sysdeps/mach/hurd/defs.c b/sysdeps/mach/hurd/defs.c
new file mode 100644
index 0000000000..b2cfe7c4ff
--- /dev/null
+++ b/sysdeps/mach/hurd/defs.c
@@ -0,0 +1,85 @@
+/* Definitions of global stdio data structures.
+
+Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <hurd/fd.h>
+#include <unistd.h>
+
+FILE *stdin, *stdout, *stderr;
+
+/* Pointer to the first stream in the list. */
+FILE *__stdio_head = NULL;
+
+static void
+init_stdio (void)
+{
+ inline void init (FILE **streamptr, int fd)
+ {
+ /* We want to use the existing FILE object if one has been allocated.
+ (This will only be the case if our image came from something like
+ Emacs's unexec, where we were called in the first run.) */
+ FILE *s = *streamptr ?: __newstream ();
+ struct hurd_fd *d = _hurd_fd_get (fd);
+ if (d == NULL)
+ {
+ /* There is no file descriptor allocated. We want the standard
+ streams to always refer to their standard file descriptors, even
+ if those descriptors are not set up until later. So allocate
+ the descriptor structure with no ports and store it in the
+ stream. Operations will fail until ports are installed in the
+ file descriptor. */
+ if (d = _hurd_alloc_fd (NULL, fd))
+ __spin_unlock (&d->port.lock);
+ }
+ if (s)
+ s->__cookie = d;
+ *streamptr = s;
+ }
+#define S(NAME, FD, MODE) \
+ init (&NAME, FD); if (NAME) NAME->__mode.__##MODE = 1;
+
+ S (stdin, STDIN_FILENO, read);
+ S (stdout, STDOUT_FILENO, write);
+ S (stderr, STDERR_FILENO, write);
+
+#undef S
+
+ if (stderr)
+ stderr->__userbuf = 1; /* stderr is always unbuffered. */
+
+ (void) &init_stdio; /* Avoid "defined but not used" warning. */
+}
+text_set_element (_hurd_fd_subinit, init_stdio);
+
+/* This function MUST be in this file!
+ This is because we want _cleanup to go into the __libc_atexit set
+ when any stdio code is used (and to use any stdio code, one must reference
+ something defined in this file), and since only local symbols can be made
+ set elements, having the set element stab entry here and _cleanup elsewhere
+ loses; and having them both elsewhere loses because there is no reference
+ to cause _cleanup to be linked in. */
+
+void
+DEFUN_VOID(_cleanup)
+{
+ (void) fclose ((FILE *) NULL);
+}
+text_set_element (__libc_atexit, _cleanup);
diff --git a/sysdeps/mach/hurd/dirstream.h b/sysdeps/mach/hurd/dirstream.h
new file mode 100644
index 0000000000..0bcec36f0f
--- /dev/null
+++ b/sysdeps/mach/hurd/dirstream.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _DIRSTREAM_H
+
+#define _DIRSTREAM_H 1
+
+/* Directory stream type.
+
+ The Hurd directory format is the same as `struct dirent', so `readdir'
+ returns a pointer into the buffer we read directory data into. */
+
+typedef struct
+ {
+ /* XXX we need a namespace-clean name for mach_port_t! */
+ unsigned int __port; /* Port to the directory. */
+ char *__data; /* Directory block. */
+ int __entry_data; /* Entry number `__data' corresponds to. */
+ char *__ptr; /* Current pointer into the block. */
+ int __entry_ptr; /* Entry number `__ptr' corresponds to. */
+ unsigned long int __allocation; /* Space allocated for the block. */
+ unsigned long int __size; /* Total valid data in the block. */
+ } DIR;
+
+#endif /* dirstream.h */
diff --git a/sysdeps/mach/hurd/dup2.c b/sysdeps/mach/hurd/dup2.c
new file mode 100644
index 0000000000..f4ec623b05
--- /dev/null
+++ b/sysdeps/mach/hurd/dup2.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+
+/* Duplicate FD to FD2, closing the old FD2 and making FD2 be
+ open on the same file as FD is. Return FD2 or -1. */
+int
+DEFUN(__dup2, (fd, fd2), int fd AND int fd2)
+{
+ struct hurd_fd *d;
+
+ /* Extract the ports and flags from FD. */
+ d = _hurd_fd_get (fd);
+ if (d == NULL)
+ {
+ errno = EBADF;
+ return -1;
+ }
+
+ HURD_CRITICAL_BEGIN;
+
+ __spin_lock (&d->port.lock);
+ if (d->port.port == MACH_PORT_NULL)
+ {
+ __spin_unlock (&d->port.lock);
+ errno = EBADF;
+ fd2 = -1;
+ }
+ else if (fd2 == fd)
+ /* FD is valid and FD2 is already the same; just return it. */
+ __spin_unlock (&d->port.lock);
+ else
+ {
+ struct hurd_userlink ulink, ctty_ulink;
+ int flags = d->flags;
+ io_t ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
+ io_t port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */
+
+ __mutex_lock (&_hurd_dtable_lock);
+ if (fd2 < 0 || fd2 >= _hurd_dtablesize)
+ {
+ errno = EBADF;
+ fd2 = -1;
+ }
+ else
+ {
+ /* Get a hold of the destination descriptor. */
+ struct hurd_fd *d2 = _hurd_dtable[fd2];
+ if (d2 == NULL)
+ {
+ /* Must allocate a new one. We don't initialize the port cells
+ with this call so that if it fails (out of memory), we will
+ not have already added user references for the ports, which we
+ would then have to deallocate. */
+ d2 = _hurd_dtable[fd2] = _hurd_new_fd (MACH_PORT_NULL,
+ MACH_PORT_NULL);
+ }
+ if (d2 == NULL)
+ {
+ fd2 = -1;
+ if (errno == EINVAL)
+ errno = EBADF; /* POSIX.1-1990 6.2.1.2 ll 54-55. */
+ }
+ else
+ {
+ /* Give the ports each a user ref for the new descriptor. */
+ __mach_port_mod_refs (__mach_task_self (), port,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (ctty != MACH_PORT_NULL)
+ __mach_port_mod_refs (__mach_task_self (), ctty,
+ MACH_PORT_RIGHT_SEND, 1);
+
+ /* Install the ports and flags in the new descriptor slot. */
+ __spin_lock (&d2->port.lock);
+ d2->flags = flags & ~FD_CLOEXEC; /* Dup clears FD_CLOEXEC. */
+ _hurd_port_set (&d2->ctty, ctty);
+ _hurd_port_locked_set (&d2->port, port); /* Unlocks D2. */
+ }
+ }
+ __mutex_unlock (&_hurd_dtable_lock);
+
+ _hurd_port_free (&d->port, &ulink, port);
+ if (ctty != MACH_PORT_NULL)
+ _hurd_port_free (&d->ctty, &ctty_ulink, port);
+ }
+
+ HURD_CRITICAL_END;
+
+ return fd2;
+}
+
+weak_alias (__dup2, dup2)
diff --git a/sysdeps/mach/hurd/err_hurd.sub b/sysdeps/mach/hurd/err_hurd.sub
new file mode 100644
index 0000000000..b077d24786
--- /dev/null
+++ b/sysdeps/mach/hurd/err_hurd.sub
@@ -0,0 +1,11 @@
+/* This file defines the Mach error system for Hurd server errors. */
+
+#include <stdio.h>
+#include <errno.h>
+
+/* Omit `const' because we are included with `static'
+ defined to `static const'. */
+static struct error_subsystem err_hurd_sub[] =
+ {
+ { "(os/hurd)", _HURD_ERRNOS, (const char *const *) _sys_errlist },
+ };
diff --git a/sysdeps/mach/hurd/errlist.awk b/sysdeps/mach/hurd/errlist.awk
new file mode 100644
index 0000000000..a06ec88af7
--- /dev/null
+++ b/sysdeps/mach/hurd/errlist.awk
@@ -0,0 +1,77 @@
+# Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# The GNU C Library 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# errno.texinfo contains lines like:
+# @comment errno.h
+# @comment POSIX.1: Function not implemented
+# @deftypevr Macro int ENOSYS
+# @comment errno 78
+
+BEGIN {
+ print "/* This file is generated from errno.texi by errlist.awk. */"
+ print "";
+ print "#ifndef HAVE_GNU_LD"
+ print "#define _sys_nerr sys_nerr"
+ print "#define _sys_errlist sys_errlist"
+ print "#endif"
+ print ""
+ print "const char *_sys_errlist[] =";
+ print " {";
+ maxerrno = 0;
+ print " \"Success\","
+ }
+$1 == "@comment" && $2 == "errno.h" { errnoh=1; next }
+errnoh == 1 && $1 == "@comment" \
+ {
+ ++errnoh;
+ etext = $3;
+ for (i = 4; i <= NF; ++i)
+ etext = etext " " $i;
+ next;
+ }
+errnoh == 2 && $1 == "@deftypevr" && $2 == "Macro" && $3 == "int" \
+ {
+ e = $4; errnoh++; next;
+ }
+errnoh == 3 && $1 == "@comment" && $2 == "errno" \
+ {
+ errno = $3 + 0;
+ msgs[errno] = etext;
+ names[errno] = e;
+ if (errno > maxerrno) maxerrno = errno;
+ next;
+ }
+{ errnoh=0 }
+END {
+ for (i = 1; i <= maxerrno; ++i)
+ {
+ if (names[i] == "")
+ print " \"Reserved error " i "\",";
+ else
+ printf "%-40s/* %d = %s */\n", " \"" msgs[i] "\",", i, names[i];
+ }
+ print " };";
+ print "";
+ print "#include <errno.h>";
+ printf "#if _HURD_ERRNOS != %d\n", maxerrno+1;
+ print "#error errlist/errnos generation bug";
+ print "#endif"
+ printf "const int _sys_nerr = %d;\n", maxerrno+1;
+ print "weak_alias (_sys_errlist, sys_errlist)"
+ print "weak_alias (_sys_nerr, sys_nerr)"
+ }
diff --git a/sysdeps/mach/hurd/errlist.c b/sysdeps/mach/hurd/errlist.c
new file mode 100644
index 0000000000..b72cd7379a
--- /dev/null
+++ b/sysdeps/mach/hurd/errlist.c
@@ -0,0 +1,93 @@
+/* This file is generated from errno.texi by errlist.awk. */
+
+#ifndef HAVE_GNU_LD
+#define _sys_nerr sys_nerr
+#define _sys_errlist sys_errlist
+#endif
+
+const char *_sys_errlist[] =
+ {
+ "Success",
+ "Operation not permitted", /* 1 = EPERM */
+ "No such file or directory", /* 2 = ENOENT */
+ "No such process", /* 3 = ESRCH */
+ "Interrupted system call", /* 4 = EINTR */
+ "Input/output error", /* 5 = EIO */
+ "Device not configured", /* 6 = ENXIO */
+ "Argument list too long", /* 7 = E2BIG */
+ "Exec format error", /* 8 = ENOEXEC */
+ "Bad file descriptor", /* 9 = EBADF */
+ "No child processes", /* 10 = ECHILD */
+ "Resource deadlock avoided", /* 11 = EDEADLK */
+ "Cannot allocate memory", /* 12 = ENOMEM */
+ "Permission denied", /* 13 = EACCES */
+ "Bad address", /* 14 = EFAULT */
+ "Block device required", /* 15 = ENOTBLK */
+ "Device busy", /* 16 = EBUSY */
+ "File exists", /* 17 = EEXIST */
+ "Invalid cross-device link", /* 18 = EXDEV */
+ "Operation not supported by device",/* 19 = ENODEV */
+ "Not a directory", /* 20 = ENOTDIR */
+ "Is a directory", /* 21 = EISDIR */
+ "Invalid argument", /* 22 = EINVAL */
+ "Too many open files", /* 23 = EMFILE */
+ "Too many open files in system", /* 24 = ENFILE */
+ "Inappropriate ioctl for device", /* 25 = ENOTTY */
+ "Text file busy", /* 26 = ETXTBSY */
+ "File too large", /* 27 = EFBIG */
+ "No space left on device", /* 28 = ENOSPC */
+ "Illegal seek", /* 29 = ESPIPE */
+ "Read-only file system", /* 30 = EROFS */
+ "Too many links", /* 31 = EMLINK */
+ "Broken pipe", /* 32 = EPIPE */
+ "Numerical argument out of domain", /* 33 = EDOM */
+ "Numerical result out of range", /* 34 = ERANGE */
+ "Operation would block", /* 35 = EWOULDBLOCK */
+ "Operation now in progress", /* 36 = EINPROGRESS */
+ "Operation already in progress", /* 37 = EALREADY */
+ "Socket operation on non-socket", /* 38 = ENOTSOCK */
+ "Destination address required", /* 39 = EDESTADDRREQ */
+ "Message too long", /* 40 = EMSGSIZE */
+ "Protocol wrong type for socket", /* 41 = EPROTOTYPE */
+ "Protocol not available", /* 42 = ENOPROTOOPT */
+ "Protocol not supported", /* 43 = EPROTONOSUPPORT */
+ "Socket type not supported", /* 44 = ESOCKTNOSUPPORT */
+ "Operation not supported", /* 45 = EOPNOTSUPP */
+ "Protocol family not supported", /* 46 = EPFNOSUPPORT */
+ "Address family not supported by protocol family",/* 47 = EAFNOSUPPORT */
+ "Address already in use", /* 48 = EADDRINUSE */
+ "Can't assign requested address", /* 49 = EADDRNOTAVAIL */
+ "Network is down", /* 50 = ENETDOWN */
+ "Network is unreachable", /* 51 = ENETUNREACH */
+ "Network dropped connection on reset",/* 52 = ENETRESET */
+ "Software caused connection abort", /* 53 = ECONNABORTED */
+ "Connection reset by peer", /* 54 = ECONNRESET */
+ "No buffer space available", /* 55 = ENOBUFS */
+ "Socket is already connected", /* 56 = EISCONN */
+ "Socket is not connected", /* 57 = ENOTCONN */
+ "Can't send after socket shutdown", /* 58 = ESHUTDOWN */
+ "Connection timed out", /* 59 = ETIMEDOUT */
+ "Connection refused", /* 60 = ECONNREFUSED */
+ "Too many levels of symbolic links",/* 61 = ELOOP */
+ "File name too long", /* 62 = ENAMETOOLONG */
+ "Host is down", /* 63 = EHOSTDOWN */
+ "No route to host", /* 64 = EHOSTUNREACH */
+ "Directory not empty", /* 65 = ENOTEMPTY */
+ "Too many users", /* 66 = EUSERS */
+ "Disc quota exceeded", /* 67 = EDQUOT */
+ "Stale NFS file handle", /* 68 = ESTALE */
+ "Too many levels of remote in path",/* 69 = EREMOTE */
+ "No locks available", /* 70 = ENOLCK */
+ "Function not implemented", /* 71 = ENOSYS */
+ "Inappropriate operation for background process",/* 72 = EBACKGROUND */
+ "?", /* 73 = ED */
+ "You really blew it this time", /* 74 = EGREGIOUS */
+ "Computer bought the farm", /* 75 = EIEIO */
+ "Gratuitous error", /* 76 = EGRATUITOUS */
+ };
+
+#include <errno.h>
+#if _HURD_ERRNOS != 77
+#error errlist/errnos generation bug
+#endif
+const int _sys_nerr = 77;
diff --git a/sysdeps/mach/hurd/errnos.awk b/sysdeps/mach/hurd/errnos.awk
new file mode 100644
index 0000000000..a6b251f211
--- /dev/null
+++ b/sysdeps/mach/hurd/errnos.awk
@@ -0,0 +1,157 @@
+# Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public License
+# as published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+
+# The GNU C Library 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
+# Library General Public License for more details.
+
+# You should have received a copy of the GNU Library General Public
+# License along with the GNU C Library; see the file COPYING.LIB. If
+# not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+# Cambridge, MA 02139, USA.
+
+# errno.texinfo contains lines like:
+# @comment errno.h
+# @comment POSIX.1: Function not implemented
+# @deftypevr Macro int ENOSYS
+
+BEGIN {
+ printf "/* This file generated by";
+ for (i = 0; i < ARGC; ++i)
+ printf " %s", ARGV[i];
+ printf ". */\n";
+ print "";
+ print "/* The Hurd uses Mach error system 0x10, currently only subsystem 0. */";
+ print "#ifndef _HURD_ERRNO";
+ print "#define _HURD_ERRNO(n)\t((0x10 << 26) | ((n) & 0x3fff))";
+ print "#endif";
+ print "";
+ print "#ifdef _ERRNO_H\n";
+ print "enum __error_t_codes\n{";
+ errnoh = 0;
+ maxerrno = 0;
+ in_mach_errors = 0;
+ in_math = 0;
+ edom = erange = "";
+ print "#undef EDOM\n#undef ERANGE";
+ }
+
+$1 == "@comment" && $2 == "errno.h" { errnoh=1; next }
+$1 == "@comment" && errnoh == 1 \
+ {
+ ++errnoh;
+ etext = "";
+ for (i = 3; i <= NF; ++i)
+ etext = etext " " $i;
+ next;
+ }
+
+errnoh == 2 && $1 == "@deftypevr" && $2 == "Macro" && $3 == "int" \
+ { ++errnoh; e = $4; next; }
+
+errnoh == 3 && $1 == "@comment" && $2 == "errno" {
+ errno = $3 + 0;
+ if (errno > maxerrno) maxerrno = errno;
+ if (e == "EWOULDBLOCK")
+ {
+ print "#define EWOULDBLOCK EAGAIN /* Operation would block */";
+ next;
+ }
+ x = sprintf ("%-40s/*%s */", sprintf ("%-24s%s", "#define\t" e,
+ "_HURD_ERRNO (" errno ")"),
+ etext);
+ if (e == "EDOM")
+ edom = x;
+ else if (e == "ERANGE")
+ erange = x;
+ printf "\t%-16s= _HURD_ERRNO (%d),\n", e, errno;
+ print x;
+ next;
+ }
+{ errnoh=0 }
+
+NF == 3 && $1 == "#define" && $2 == "MACH_SEND_IN_PROGRESS" \
+ {
+ in_mach_errors = 1;
+ print "\n\t/* Errors from <mach/message.h>. */";
+ }
+NF == 3 && $1 == "#define" && $2 == "KERN_SUCCESS" \
+ {
+ in_mach_errors = 1;
+ print "\n\t/* Errors from <mach/kern_return.h>. */";
+ next;
+ }
+
+in_mach_errors && $2 == "MACH_IPC_COMPAT" \
+ {
+ in_mach_errors = 0;
+ }
+
+in_mach_errors == 1 && NF == 3 && $1 == "#define" \
+ {
+ printf "\t%-32s= %s,\n", "E" $2, $3;
+ }
+
+$1 == "#define" && $2 == "_MACH_MIG_ERRORS_H_" \
+ {
+ in_mig_errors = 1;
+ print "\n\t/* Errors from <mach/mig_errors.h>. */";
+ next;
+ }
+in_mig_errors && $1 == "#endif" && $3 == "_MACH_MIG_ERRORS_H_" \
+ {
+ in_mig_errors = 0;
+ }
+
+(in_mig_errors && $1 == "#define" && $3 <= -300) || \
+(in_device_errors && $1 == "#define") \
+ {
+ printf "%-32s", sprintf ("\t%-24s= %s,", "E" $2, $3);
+ for (i = 4; i <= NF; ++i)
+ printf " %s", $i;
+ printf "\n";
+ }
+
+$1 == "#define" && $2 == "D_SUCCESS" \
+ {
+ in_device_errors = 1;
+ print "\n\t/* Errors from <device/device_types.h>. */";
+ next;
+ }
+in_device_errors && $1 == "#endif" \
+ {
+ in_device_errors = 0;
+ }
+
+
+END \
+ {
+ print "";
+ print "};";
+ print "";
+ printf "#define\t_HURD_ERRNOS\t%d\n", maxerrno+1;
+ print "";
+ print "\
+/* User-visible type of error codes. It is ok to use `int' or\n\
+ `kern_return_t' for these, but with `error_t' the debugger prints\n\
+ symbolic values. */";
+ print "#ifdef __USE_GNU";
+ print "typedef enum __error_t_codes error_t;"
+ print "#endif";
+ print "";
+ print "/* errno is a per-thread variable. */";
+ print "#include <hurd/threadvar.h>";
+ print "#define errno (*__hurd_errno_location ())";
+ print "";
+ print "#endif /* <errno.h> included. */";
+ print "";
+ print "#if !defined (_ERRNO_H) && defined (__need_Emath)";
+ print edom; print erange;
+ print "#endif /* <errno.h> not included and need math error codes. */";
+ }
diff --git a/sysdeps/mach/hurd/errnos.h b/sysdeps/mach/hurd/errnos.h
new file mode 100644
index 0000000000..911af3c5c8
--- /dev/null
+++ b/sysdeps/mach/hurd/errnos.h
@@ -0,0 +1,266 @@
+/* This file generated by gawk manual/errno.texi ../mach/mach/message.h ../mach/mach/kern_return.h ../mach/mach/mig_errors.h ../mach/device/device_types.h. */
+
+/* The Hurd uses Mach error system 0x10, currently only subsystem 0. */
+#ifndef _HURD_ERRNO
+#define _HURD_ERRNO(n) ((0x10 << 26) | ((n) & 0x3fff))
+#endif
+
+#ifdef _ERRNO_H
+
+enum __error_t_codes
+{
+#undef EDOM
+#undef ERANGE
+ EPERM = _HURD_ERRNO (1),
+#define EPERM _HURD_ERRNO (1) /* Operation not permitted */
+ ENOENT = _HURD_ERRNO (2),
+#define ENOENT _HURD_ERRNO (2) /* No such file or directory */
+ ESRCH = _HURD_ERRNO (3),
+#define ESRCH _HURD_ERRNO (3) /* No such process */
+ EINTR = _HURD_ERRNO (4),
+#define EINTR _HURD_ERRNO (4) /* Interrupted system call */
+ EIO = _HURD_ERRNO (5),
+#define EIO _HURD_ERRNO (5) /* Input/output error */
+ ENXIO = _HURD_ERRNO (6),
+#define ENXIO _HURD_ERRNO (6) /* Device not configured */
+ E2BIG = _HURD_ERRNO (7),
+#define E2BIG _HURD_ERRNO (7) /* Argument list too long */
+ ENOEXEC = _HURD_ERRNO (8),
+#define ENOEXEC _HURD_ERRNO (8) /* Exec format error */
+ EBADF = _HURD_ERRNO (9),
+#define EBADF _HURD_ERRNO (9) /* Bad file descriptor */
+ ECHILD = _HURD_ERRNO (10),
+#define ECHILD _HURD_ERRNO (10)/* No child processes */
+ EDEADLK = _HURD_ERRNO (11),
+#define EDEADLK _HURD_ERRNO (11)/* Resource deadlock avoided */
+ ENOMEM = _HURD_ERRNO (12),
+#define ENOMEM _HURD_ERRNO (12)/* Cannot allocate memory */
+ EACCES = _HURD_ERRNO (13),
+#define EACCES _HURD_ERRNO (13)/* Permission denied */
+ EFAULT = _HURD_ERRNO (14),
+#define EFAULT _HURD_ERRNO (14)/* Bad address */
+ ENOTBLK = _HURD_ERRNO (15),
+#define ENOTBLK _HURD_ERRNO (15)/* Block device required */
+ EBUSY = _HURD_ERRNO (16),
+#define EBUSY _HURD_ERRNO (16)/* Device busy */
+ EEXIST = _HURD_ERRNO (17),
+#define EEXIST _HURD_ERRNO (17)/* File exists */
+ EXDEV = _HURD_ERRNO (18),
+#define EXDEV _HURD_ERRNO (18)/* Invalid cross-device link */
+ ENODEV = _HURD_ERRNO (19),
+#define ENODEV _HURD_ERRNO (19)/* Operation not supported by device */
+ ENOTDIR = _HURD_ERRNO (20),
+#define ENOTDIR _HURD_ERRNO (20)/* Not a directory */
+ EISDIR = _HURD_ERRNO (21),
+#define EISDIR _HURD_ERRNO (21)/* Is a directory */
+ EINVAL = _HURD_ERRNO (22),
+#define EINVAL _HURD_ERRNO (22)/* Invalid argument */
+ EMFILE = _HURD_ERRNO (23),
+#define EMFILE _HURD_ERRNO (23)/* Too many open files */
+ ENFILE = _HURD_ERRNO (24),
+#define ENFILE _HURD_ERRNO (24)/* Too many open files in system */
+ ENOTTY = _HURD_ERRNO (25),
+#define ENOTTY _HURD_ERRNO (25)/* Inappropriate ioctl for device */
+ ETXTBSY = _HURD_ERRNO (26),
+#define ETXTBSY _HURD_ERRNO (26)/* Text file busy */
+ EFBIG = _HURD_ERRNO (27),
+#define EFBIG _HURD_ERRNO (27)/* File too large */
+ ENOSPC = _HURD_ERRNO (28),
+#define ENOSPC _HURD_ERRNO (28)/* No space left on device */
+ ESPIPE = _HURD_ERRNO (29),
+#define ESPIPE _HURD_ERRNO (29)/* Illegal seek */
+ EROFS = _HURD_ERRNO (30),
+#define EROFS _HURD_ERRNO (30)/* Read-only file system */
+ EMLINK = _HURD_ERRNO (31),
+#define EMLINK _HURD_ERRNO (31)/* Too many links */
+ EPIPE = _HURD_ERRNO (32),
+#define EPIPE _HURD_ERRNO (32)/* Broken pipe */
+ EDOM = _HURD_ERRNO (33),
+#define EDOM _HURD_ERRNO (33)/* Numerical argument out of domain */
+ ERANGE = _HURD_ERRNO (34),
+#define ERANGE _HURD_ERRNO (34)/* Numerical result out of range */
+ EAGAIN = _HURD_ERRNO (35),
+#define EAGAIN _HURD_ERRNO (35)/* Resource temporarily unavailable */
+#define EWOULDBLOCK EAGAIN /* Operation would block */
+ EINPROGRESS = _HURD_ERRNO (36),
+#define EINPROGRESS _HURD_ERRNO (36)/* Operation now in progress */
+ EALREADY = _HURD_ERRNO (37),
+#define EALREADY _HURD_ERRNO (37)/* Operation already in progress */
+ ENOTSOCK = _HURD_ERRNO (38),
+#define ENOTSOCK _HURD_ERRNO (38)/* Socket operation on non-socket */
+ EDESTADDRREQ = _HURD_ERRNO (39),
+#define EDESTADDRREQ _HURD_ERRNO (39)/* Destination address required */
+ EMSGSIZE = _HURD_ERRNO (40),
+#define EMSGSIZE _HURD_ERRNO (40)/* Message too long */
+ EPROTOTYPE = _HURD_ERRNO (41),
+#define EPROTOTYPE _HURD_ERRNO (41)/* Protocol wrong type for socket */
+ ENOPROTOOPT = _HURD_ERRNO (42),
+#define ENOPROTOOPT _HURD_ERRNO (42)/* Protocol not available */
+ EPROTONOSUPPORT = _HURD_ERRNO (43),
+#define EPROTONOSUPPORT _HURD_ERRNO (43)/* Protocol not supported */
+ ESOCKTNOSUPPORT = _HURD_ERRNO (44),
+#define ESOCKTNOSUPPORT _HURD_ERRNO (44)/* Socket type not supported */
+ EOPNOTSUPP = _HURD_ERRNO (45),
+#define EOPNOTSUPP _HURD_ERRNO (45)/* Operation not supported */
+ EPFNOSUPPORT = _HURD_ERRNO (46),
+#define EPFNOSUPPORT _HURD_ERRNO (46)/* Protocol family not supported */
+ EAFNOSUPPORT = _HURD_ERRNO (47),
+#define EAFNOSUPPORT _HURD_ERRNO (47)/* Address family not supported by protocol family */
+ EADDRINUSE = _HURD_ERRNO (48),
+#define EADDRINUSE _HURD_ERRNO (48)/* Address already in use */
+ EADDRNOTAVAIL = _HURD_ERRNO (49),
+#define EADDRNOTAVAIL _HURD_ERRNO (49)/* Can't assign requested address */
+ ENETDOWN = _HURD_ERRNO (50),
+#define ENETDOWN _HURD_ERRNO (50)/* Network is down */
+ ENETUNREACH = _HURD_ERRNO (51),
+#define ENETUNREACH _HURD_ERRNO (51)/* Network is unreachable */
+ ENETRESET = _HURD_ERRNO (52),
+#define ENETRESET _HURD_ERRNO (52)/* Network dropped connection on reset */
+ ECONNABORTED = _HURD_ERRNO (53),
+#define ECONNABORTED _HURD_ERRNO (53)/* Software caused connection abort */
+ ECONNRESET = _HURD_ERRNO (54),
+#define ECONNRESET _HURD_ERRNO (54)/* Connection reset by peer */
+ ENOBUFS = _HURD_ERRNO (55),
+#define ENOBUFS _HURD_ERRNO (55)/* No buffer space available */
+ EISCONN = _HURD_ERRNO (56),
+#define EISCONN _HURD_ERRNO (56)/* Socket is already connected */
+ ENOTCONN = _HURD_ERRNO (57),
+#define ENOTCONN _HURD_ERRNO (57)/* Socket is not connected */
+ ESHUTDOWN = _HURD_ERRNO (58),
+#define ESHUTDOWN _HURD_ERRNO (58)/* Can't send after socket shutdown */
+ ETIMEDOUT = _HURD_ERRNO (59),
+#define ETIMEDOUT _HURD_ERRNO (59)/* Connection timed out */
+ ECONNREFUSED = _HURD_ERRNO (60),
+#define ECONNREFUSED _HURD_ERRNO (60)/* Connection refused */
+ ELOOP = _HURD_ERRNO (61),
+#define ELOOP _HURD_ERRNO (61)/* Too many levels of symbolic links */
+ ENAMETOOLONG = _HURD_ERRNO (62),
+#define ENAMETOOLONG _HURD_ERRNO (62)/* File name too long */
+ EHOSTDOWN = _HURD_ERRNO (63),
+#define EHOSTDOWN _HURD_ERRNO (63)/* Host is down */
+ EHOSTUNREACH = _HURD_ERRNO (64),
+#define EHOSTUNREACH _HURD_ERRNO (64)/* No route to host */
+ ENOTEMPTY = _HURD_ERRNO (65),
+#define ENOTEMPTY _HURD_ERRNO (65)/* Directory not empty */
+ EUSERS = _HURD_ERRNO (66),
+#define EUSERS _HURD_ERRNO (66)/* Too many users */
+ EDQUOT = _HURD_ERRNO (67),
+#define EDQUOT _HURD_ERRNO (67)/* Disc quota exceeded */
+ ESTALE = _HURD_ERRNO (68),
+#define ESTALE _HURD_ERRNO (68)/* Stale NFS file handle */
+ EREMOTE = _HURD_ERRNO (69),
+#define EREMOTE _HURD_ERRNO (69)/* Too many levels of remote in path */
+ ENOLCK = _HURD_ERRNO (70),
+#define ENOLCK _HURD_ERRNO (70)/* No locks available */
+ ENOSYS = _HURD_ERRNO (71),
+#define ENOSYS _HURD_ERRNO (71)/* Function not implemented */
+ EBACKGROUND = _HURD_ERRNO (72),
+#define EBACKGROUND _HURD_ERRNO (72)/* Inappropriate operation for background process */
+ ED = _HURD_ERRNO (73),
+#define ED _HURD_ERRNO (73)/* ? */
+ EGREGIOUS = _HURD_ERRNO (74),
+#define EGREGIOUS _HURD_ERRNO (74)/* You really blew it this time */
+ EIEIO = _HURD_ERRNO (75),
+#define EIEIO _HURD_ERRNO (75)/* Computer bought the farm */
+ EGRATUITOUS = _HURD_ERRNO (76),
+#define EGRATUITOUS _HURD_ERRNO (76)/* Gratuitous error */
+
+ /* Errors from <mach/message.h>. */
+ EMACH_SEND_IN_PROGRESS = 0x10000001,
+ EMACH_SEND_INVALID_DATA = 0x10000002,
+ EMACH_SEND_INVALID_DEST = 0x10000003,
+ EMACH_SEND_TIMED_OUT = 0x10000004,
+ EMACH_SEND_WILL_NOTIFY = 0x10000005,
+ EMACH_SEND_NOTIFY_IN_PROGRESS = 0x10000006,
+ EMACH_SEND_INTERRUPTED = 0x10000007,
+ EMACH_SEND_MSG_TOO_SMALL = 0x10000008,
+ EMACH_SEND_INVALID_REPLY = 0x10000009,
+ EMACH_SEND_INVALID_RIGHT = 0x1000000a,
+ EMACH_SEND_INVALID_NOTIFY = 0x1000000b,
+ EMACH_SEND_INVALID_MEMORY = 0x1000000c,
+ EMACH_SEND_NO_BUFFER = 0x1000000d,
+ EMACH_SEND_NO_NOTIFY = 0x1000000e,
+ EMACH_SEND_INVALID_TYPE = 0x1000000f,
+ EMACH_SEND_INVALID_HEADER = 0x10000010,
+ EMACH_RCV_IN_PROGRESS = 0x10004001,
+ EMACH_RCV_INVALID_NAME = 0x10004002,
+ EMACH_RCV_TIMED_OUT = 0x10004003,
+ EMACH_RCV_TOO_LARGE = 0x10004004,
+ EMACH_RCV_INTERRUPTED = 0x10004005,
+ EMACH_RCV_PORT_CHANGED = 0x10004006,
+ EMACH_RCV_INVALID_NOTIFY = 0x10004007,
+ EMACH_RCV_INVALID_DATA = 0x10004008,
+ EMACH_RCV_PORT_DIED = 0x10004009,
+ EMACH_RCV_IN_SET = 0x1000400a,
+ EMACH_RCV_HEADER_ERROR = 0x1000400b,
+ EMACH_RCV_BODY_ERROR = 0x1000400c,
+
+ /* Errors from <mach/kern_return.h>. */
+ EKERN_INVALID_ADDRESS = 1,
+ EKERN_PROTECTION_FAILURE = 2,
+ EKERN_NO_SPACE = 3,
+ EKERN_INVALID_ARGUMENT = 4,
+ EKERN_FAILURE = 5,
+ EKERN_RESOURCE_SHORTAGE = 6,
+ EKERN_NOT_RECEIVER = 7,
+ EKERN_NO_ACCESS = 8,
+ EKERN_MEMORY_FAILURE = 9,
+ EKERN_MEMORY_ERROR = 10,
+ EKERN_NOT_IN_SET = 12,
+ EKERN_NAME_EXISTS = 13,
+ EKERN_ABORTED = 14,
+ EKERN_INVALID_NAME = 15,
+ EKERN_INVALID_TASK = 16,
+ EKERN_INVALID_RIGHT = 17,
+ EKERN_INVALID_VALUE = 18,
+ EKERN_UREFS_OVERFLOW = 19,
+ EKERN_INVALID_CAPABILITY = 20,
+ EKERN_RIGHT_EXISTS = 21,
+ EKERN_INVALID_HOST = 22,
+ EKERN_MEMORY_PRESENT = 23,
+
+ /* Errors from <mach/mig_errors.h>. */
+ EMIG_TYPE_ERROR = -300, /* client type check failure */
+ EMIG_REPLY_MISMATCH = -301, /* wrong reply message ID */
+ EMIG_REMOTE_ERROR = -302, /* server detected error */
+ EMIG_BAD_ID = -303, /* bad request message ID */
+ EMIG_BAD_ARGUMENTS = -304, /* server type check failure */
+ EMIG_NO_REPLY = -305, /* no reply should be sent */
+ EMIG_EXCEPTION = -306, /* server raised exception */
+ EMIG_ARRAY_TOO_LARGE = -307, /* array not large enough */
+ EMIG_SERVER_DIED = -308, /* server died */
+ EMIG_DESTROY_REQUEST = -309, /* destroy request with no reply */
+
+ /* Errors from <device/device_types.h>. */
+ ED_IO_ERROR = 2500, /* hardware IO error */
+ ED_WOULD_BLOCK = 2501, /* would block, but D_NOWAIT set */
+ ED_NO_SUCH_DEVICE = 2502, /* no such device */
+ ED_ALREADY_OPEN = 2503, /* exclusive-use device already open */
+ ED_DEVICE_DOWN = 2504, /* device has been shut down */
+ ED_INVALID_OPERATION = 2505, /* bad operation for device */
+ ED_INVALID_RECNUM = 2506, /* invalid record (block) number */
+ ED_INVALID_SIZE = 2507, /* invalid IO size */
+ ED_NO_MEMORY = 2508, /* memory allocation failure */
+ ED_READ_ONLY = 2509, /* device cannot be written to */
+
+};
+
+#define _HURD_ERRNOS 77
+
+/* User-visible type of error codes. It is ok to use `int' or
+ `kern_return_t' for these, but with `error_t' the debugger prints
+ symbolic values. */
+#ifdef __USE_GNU
+typedef enum __error_t_codes error_t;
+#endif
+
+/* errno is a per-thread variable. */
+#include <hurd/threadvar.h>
+#define errno (*__hurd_errno_location ())
+
+#endif /* <errno.h> included. */
+
+#if !defined (_ERRNO_H) && defined (__need_Emath)
+#define EDOM _HURD_ERRNO (33)/* Numerical argument out of domain */
+#define ERANGE _HURD_ERRNO (34)/* Numerical result out of range */
+#endif /* <errno.h> not included and need math error codes. */
diff --git a/sysdeps/mach/hurd/execve.c b/sysdeps/mach/hurd/execve.c
new file mode 100644
index 0000000000..5a45f5f42e
--- /dev/null
+++ b/sysdeps/mach/hurd/execve.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <fcntl.h>
+
+/* Replace the current process, executing FILE_NAME with arguments ARGV and
+ environment ENVP. ARGV and ENVP are terminated by NULL pointers. */
+int
+DEFUN(__execve, (file_name, argv, envp),
+ CONST char *file_name AND char *CONST argv[] AND char *CONST envp[])
+{
+ error_t err;
+ file_t file = __file_name_lookup (file_name, O_EXEC, 0);
+
+ if (file == MACH_PORT_NULL)
+ return -1;
+
+ /* Hopefully this will not return. */
+ err = _hurd_exec (__mach_task_self (), file, argv, envp);
+
+ /* Oh well. Might as well be tidy. */
+ __mach_port_deallocate (__mach_task_self (), file);
+
+ return __hurd_fail (err);
+}
+
+weak_alias (__execve, execve)
diff --git a/sysdeps/mach/hurd/fchdir.c b/sysdeps/mach/hurd/fchdir.c
new file mode 100644
index 0000000000..088bba9d16
--- /dev/null
+++ b/sysdeps/mach/hurd/fchdir.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <hurd/fd.h>
+
+/* Change the current directory to FD. */
+int
+DEFUN(fchdir, (fd), int fd)
+{
+ error_t err;
+ file_t cwdir;
+
+ err = __USEPORT (CRDIR,
+ ({ file_t crdir = port;
+ HURD_DPORT_USE (fd,
+ __hurd_file_name_lookup (crdir, port, "",
+ 0, 0, &cwdir));
+ }));
+
+ if (err)
+ return __hurd_fail (err);
+
+ _hurd_port_set (&_hurd_ports[INIT_PORT_CWDIR], cwdir);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/fchflags.c b/sysdeps/mach/hurd/fchflags.c
new file mode 100644
index 0000000000..aa1e32696d
--- /dev/null
+++ b/sysdeps/mach/hurd/fchflags.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the flags of the file FD refers to to FLAGS. */
+int
+DEFUN(fchflags, (fd, flags), int fd AND int flags)
+{
+ error_t err;
+
+ if (err = HURD_DPORT_USE (fd, __file_chflags (port, flags)))
+ return __hurd_dfail (fd, err);
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/fchmod.c b/sysdeps/mach/hurd/fchmod.c
new file mode 100644
index 0000000000..3dc84ff11a
--- /dev/null
+++ b/sysdeps/mach/hurd/fchmod.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the protections of the file FD refers to to MODE. */
+int
+DEFUN(__fchmod, (fd, mode), int fd AND mode_t mode)
+{
+ error_t err;
+
+ if (err = HURD_DPORT_USE (fd, __file_chmod (port, mode)))
+ return __hurd_dfail (fd, err);
+
+ return 0;
+}
+
+weak_alias (__fchmod, fchmod)
diff --git a/sysdeps/mach/hurd/fchown.c b/sysdeps/mach/hurd/fchown.c
new file mode 100644
index 0000000000..c2f873c78d
--- /dev/null
+++ b/sysdeps/mach/hurd/fchown.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Change the owner and group of the file referred to by FD. */
+int
+DEFUN(__fchown, (fd, owner, group),
+ int fd AND uid_t owner AND gid_t group)
+{
+ error_t err;
+
+ if (err = HURD_DPORT_USE (fd, __file_chown (port, owner, group)))
+ return __hurd_dfail (fd, err);
+
+ return 0;
+}
+
+weak_alias (__fchown, fchown)
diff --git a/sysdeps/mach/hurd/fcntl.c b/sysdeps/mach/hurd/fcntl.c
new file mode 100644
index 0000000000..4b7207f7ee
--- /dev/null
+++ b/sysdeps/mach/hurd/fcntl.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <stdarg.h>
+
+
+/* Perform file control operations on FD. */
+int
+DEFUN(__fcntl, (fd, cmd), int fd AND int cmd DOTS)
+{
+ va_list ap;
+ struct hurd_fd *d;
+ int result;
+
+ d = _hurd_fd_get (fd);
+
+ if (d == NULL)
+ return __hurd_fail (EBADF);
+
+ va_start (ap, cmd);
+
+ switch (cmd)
+ {
+ error_t err;
+
+ default: /* Bad command. */
+ errno = EINVAL;
+ result = -1;
+ break;
+
+ /* First the descriptor-based commands, which do no RPCs. */
+
+ case F_DUPFD: /* Duplicate the file descriptor. */
+ {
+ struct hurd_fd *new;
+ io_t port, ctty;
+ struct hurd_userlink ulink, ctty_ulink;
+ int flags;
+
+ HURD_CRITICAL_BEGIN;
+
+ /* Extract the ports and flags from the file descriptor. */
+ __spin_lock (&d->port.lock);
+ flags = d->flags;
+ ctty = _hurd_port_get (&d->ctty, &ctty_ulink);
+ port = _hurd_port_locked_get (&d->port, &ulink); /* Unlocks D. */
+
+ /* Get a new file descriptor. The third argument to __fcntl is the
+ minimum file descriptor number for it. */
+ new = _hurd_alloc_fd (&result, va_arg (ap, int));
+ if (new == NULL)
+ /* _hurd_alloc_fd has set errno. */
+ result = -1;
+ else
+ {
+ /* Give the ports each a user ref for the new descriptor. */
+ __mach_port_mod_refs (__mach_task_self (), port,
+ MACH_PORT_RIGHT_SEND, 1);
+ if (ctty != MACH_PORT_NULL)
+ __mach_port_mod_refs (__mach_task_self (), ctty,
+ MACH_PORT_RIGHT_SEND, 1);
+
+ /* Install the ports and flags in the new descriptor. */
+ if (ctty != MACH_PORT_NULL)
+ _hurd_port_set (&new->ctty, ctty);
+ /* Duplication clears the FD_CLOEXEC flag. */
+ new->flags = flags & ~FD_CLOEXEC;
+ _hurd_port_locked_set (&new->port, port); /* Unlocks NEW. */
+ }
+
+ HURD_CRITICAL_END;
+
+ _hurd_port_free (&d->port, &ulink, port);
+ if (ctty != MACH_PORT_NULL)
+ _hurd_port_free (&d->ctty, &ctty_ulink, port);
+
+ break;
+ }
+
+ /* Set RESULT by evaluating EXPR with the descriptor locked.
+ Check for an empty descriptor and return EBADF. */
+#define LOCKED(expr) \
+ HURD_CRITICAL_BEGIN; \
+ __spin_lock (&d->port.lock); \
+ if (d->port.port == MACH_PORT_NULL) \
+ result = __hurd_fail (EBADF); \
+ else \
+ result = (expr); \
+ __spin_unlock (&d->port.lock); \
+ HURD_CRITICAL_END;
+
+ case F_GETFD: /* Get descriptor flags. */
+ LOCKED (d->flags);
+ break;
+
+ case F_SETFD: /* Set descriptor flags. */
+ LOCKED ((d->flags = va_arg (ap, int), 0));
+ break;
+
+
+ /* Now the real io operations, done by RPCs to io servers. */
+
+ case F_GETLK:
+ case F_SETLK:
+ case F_SETLKW:
+ {
+ struct flock *fl = va_arg (ap, struct flock *);
+ errno = fl?ENOSYS:EINVAL; /* XXX mib needs to implement io rpcs. */
+ result = -1;
+ break;
+ }
+
+ case F_GETFL: /* Get per-open flags. */
+ if (err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &result)))
+ result = __hurd_dfail (fd, err);
+ break;
+
+ case F_SETFL: /* Set per-open flags. */
+ err = HURD_FD_PORT_USE (d, __io_set_all_openmodes (port,
+ va_arg (ap, int)));
+ result = err ? __hurd_dfail (fd, err) : 0;
+
+ case F_GETOWN: /* Get owner. */
+ if (err = HURD_FD_PORT_USE (d, __io_get_owner (port, &result)))
+ result = __hurd_dfail (fd, err);
+ break;
+
+ case F_SETOWN: /* Set owner. */
+ err = HURD_FD_PORT_USE (d, __io_mod_owner (port, va_arg (ap, pid_t)));
+ result = err ? __hurd_dfail (fd, err) : 0;
+ break;
+ }
+
+ va_end (ap);
+
+ return result;
+}
+
+weak_alias (__fcntl, fcntl)
diff --git a/sysdeps/mach/hurd/fcntlbits.h b/sysdeps/mach/hurd/fcntlbits.h
new file mode 100644
index 0000000000..8a5e4cd52a
--- /dev/null
+++ b/sysdeps/mach/hurd/fcntlbits.h
@@ -0,0 +1,178 @@
+/* O_*, F_*, FD_* bit values for GNU.
+Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _FCNTLBITS_H
+
+#define _FCNTLBITS_H 1
+
+
+/* File access modes. These are understood by io servers; they can be
+ passed in `dir_lookup', and are returned by `io_get_openmodes'.
+ Consequently they can be passed to `open', `hurd_file_name_lookup', and
+ `file_name_lookup'; and are returned by `fcntl' with the F_GETFL
+ command. */
+
+/* In GNU, read and write are bits (unlike BSD). */
+#ifdef __USE_GNU
+#define O_READ O_RDONLY /* Open for reading. */
+#define O_WRITE O_WRONLY /* Open for writing. */
+#define O_EXEC 0x0004 /* Open for execution. */
+#endif
+/* POSIX.1 standard names. */
+#define O_RDONLY 0x0001 /* Open read-only. */
+#define O_WRONLY 0x0002 /* Open write-only. */
+#define O_RDWR (O_RDONLY|O_WRONLY) /* Open for reading and writing. */
+#define O_ACCMODE O_RDWR /* Mask for file access modes. */
+
+
+
+/* File name translation flags. These are understood by io servers;
+ they can be passed in `dir_lookup', and consequently to `open',
+ `hurd_file_name_lookup', and `file_name_lookup'. */
+
+#define O_CREAT 0x0010 /* Create file if it doesn't exist. */
+#define O_EXCL 0x0020 /* Fail if file already exists. */
+#ifdef __USE_GNU
+#define O_NOLINK 0x0040 /* No name mappings on final component. */
+#define O_NOTRANS 0x0080 /* No translator on final component. */
+#endif
+
+
+/* I/O operating modes. These are understood by io servers; they can be
+ passed in `dir_lookup' and set or fetched with `io_*_openmodes'.
+ Consequently they can be passed to `open', `hurd_file_name_lookup',
+ `file_name_lookup', and `fcntl' with the F_SETFL command; and are
+ returned by `fcntl' with the F_GETFL command. */
+
+#define O_APPEND 0x0100 /* Writes always append to the file. */
+#ifdef __USE_BSD
+#define O_ASYNC 0x0200 /* Send SIGIO to owner when data is ready. */
+#define O_FSYNC 0x0400 /* Synchronous writes. */
+#define O_SYNC O_FSYNC
+#endif
+#ifdef __USE_GNU
+#define O_NOATIME 0x0800 /* Don't set access time on read (owner). */
+#endif
+
+
+/* The name O_NONBLOCK is unfortunately overloaded; it is both a file name
+ translation flag and an I/O operating mode. O_NDELAY is the deprecated
+ BSD name for the same flag, overloaded in the same way.
+
+ When used in `dir_lookup' (and consequently `open', `hurd_file_name_lookup',
+ or `file_name_lookup'), O_NONBLOCK says the open should return immediately
+ instead of blocking for any significant length of time (e.g., to wait
+ for carrier detect on a serial line). It is also saved as an I/O
+ operating mode, and after open has the following meaning.
+
+ When used in `io_*_openmodes' (and consequently `fcntl' with the F_SETFL
+ command), the O_NONBLOCK flag means to do nonblocking i/o: any i/o
+ operation that would block for any significant length of time will instead
+ fail with EAGAIN. */
+
+#define O_NONBLOCK 0x0008 /* Non-blocking open or non-blocking I/O. */
+#ifdef __USE_BSD
+#define O_NDELAY O_NONBLOCK /* Deprecated. */
+#endif
+
+
+#ifdef __USE_GNU
+/* Mask of bits which are understood by io servers. */
+#define O_HURD 0xffff /* XXX name? want this? */
+#endif
+
+
+/* Open-time action flags. These are understood by `hurd_file_name_lookup'
+ and consequently by `open' and `file_name_lookup'. They are not preserved
+ once the file has been opened. */
+
+#define O_TRUNC 0x00010000 /* Truncate file to zero length. */
+#ifdef __USE_MISC
+#define O_SHLOCK 0x00020000 /* Open with shared file lock. */
+#define O_EXLOCK 0x00040000 /* Open with exclusive file lock. */
+#endif
+
+
+/* Controlling terminal flags. These are understood only by `open',
+ and are not preserved once the file has been opened. */
+
+#ifdef __USE_GNU
+#define O_IGNORE_CTTY 0x00080000 /* Don't do any ctty magic at all. */
+#endif
+/* `open' never assigns a controlling terminal in GNU. */
+#define O_NOCTTY 0 /* Don't assign a controlling terminal. */
+
+
+#ifdef __USE_BSD
+/* Bits in the file status flags returned by F_GETFL. */
+#define FREAD O_RDONLY
+#define FWRITE O_WRONLY
+
+/* Traditional BSD names the O_* bits. */
+#define FASYNC O_ASYNC
+#define FCREAT O_CREAT
+#define FEXCL O_EXCL
+#define FTRUNC O_TRUNC
+#define FNOCTTY O_NOCTTY
+#define FFSYNC O_FSYNC
+#define FSYNC O_SYNC
+#define FAPPEND O_APPEND
+#define FNONBLOCK O_NONBLOCK
+#define FNDELAY O_NDELAY
+#endif
+
+
+/* Values for the second argument to `fcntl'. */
+#define F_DUPFD 0 /* Duplicate file descriptor. */
+#define F_GETFD 1 /* Get file descriptor flags. */
+#define F_SETFD 2 /* Set file descriptor flags. */
+#define F_GETFL 3 /* Get file status flags. */
+#define F_SETFL 4 /* Set file status flags. */
+#ifdef __USE_BSD
+#define F_GETOWN 5 /* Get owner (receiver of SIGIO). */
+#define F_SETOWN 6 /* Set owner (receiver of SIGIO). */
+#endif
+#define F_GETLK 7 /* Get record locking info. */
+#define F_SETLK 8 /* Set record locking info (non-blocking). */
+#define F_SETLKW 9 /* Set record locking info (blocking). */
+
+/* File descriptor flags used with F_GETFD and F_SETFD. */
+#define FD_CLOEXEC 1 /* Close on exec. */
+
+
+#include <gnu/types.h>
+
+/* The structure describing an advisory lock. This is the type of the third
+ argument to `fcntl' for the F_GETLK, F_SETLK, and F_SETLKW requests. */
+struct flock
+ {
+ int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
+ int l_whence; /* Where `l_start' is relative to (like `lseek'). */
+ __off_t l_start; /* Offset where the lock begins. */
+ __off_t l_len; /* Size of the locked area; zero means until EOF. */
+ __pid_t l_pid; /* Process holding the lock. */
+ };
+
+/* Values for the `l_type' field of a `struct flock'. */
+#define F_RDLCK 1 /* Read lock. */
+#define F_WRLCK 2 /* Write lock. */
+#define F_UNLCK 3 /* Remove lock. */
+
+
+#endif /* fcntlbits.h */
diff --git a/sysdeps/mach/hurd/fdopen.c b/sysdeps/mach/hurd/fdopen.c
new file mode 100644
index 0000000000..3fdd742a59
--- /dev/null
+++ b/sysdeps/mach/hurd/fdopen.c
@@ -0,0 +1,69 @@
+/* Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <hurd/fd.h>
+#include <fcntl.h>
+#include <hurd/io.h>
+
+/* Defined in fopen.c. */
+extern int EXFUN(__getmode, (CONST char *mode, __io_mode *mptr));
+
+/* Open a new stream on a given system file descriptor. */
+FILE *
+DEFUN(fdopen, (fd, mode), int fd AND CONST char *mode)
+{
+ FILE *stream;
+ __io_mode m;
+ struct hurd_fd *d;
+ error_t err;
+ int openmodes;
+
+ if (!__getmode (mode, &m))
+ return NULL;
+
+ HURD_CRITICAL_BEGIN;
+ d = _hurd_fd_get (fd);
+ if (d == NULL)
+ err = EBADF;
+ else
+ err = HURD_FD_PORT_USE (d, __io_get_openmodes (port, &openmodes));
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_dfail (fd, err), NULL;
+
+ /* Check the access mode. */
+ if ((m.__read && !(openmodes & O_READ)) ||
+ (m.__write && !(openmodes & O_WRITE)))
+ {
+ errno = EBADF;
+ return NULL;
+ }
+
+ stream = __newstream ();
+ if (stream == NULL)
+ return NULL;
+
+ stream->__cookie = d;
+ stream->__mode = m;
+
+ return stream;
+}
diff --git a/sysdeps/mach/hurd/fexecve.c b/sysdeps/mach/hurd/fexecve.c
new file mode 100644
index 0000000000..e4f2cda1a2
--- /dev/null
+++ b/sysdeps/mach/hurd/fexecve.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <errno.h>
+
+/* Execute the file FD refers to, overlaying the running program image. */
+
+int
+fexecve (int fd, char *const argv[], char *const envp[])
+{
+ error_t err = HURD_DPORT_USE (fd, _hurd_exec (__mach_task_self (), port,
+ argv, envp));
+ if (! err)
+ err = EGRATUITOUS;
+ return __hurd_fail (err);
+}
diff --git a/sysdeps/mach/hurd/flock.c b/sysdeps/mach/hurd/flock.c
new file mode 100644
index 0000000000..6154fd2292
--- /dev/null
+++ b/sysdeps/mach/hurd/flock.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/file.h>
+#include <hurd/fd.h>
+#include <hurd/fs.h>
+
+/* Apply or remove an advisory lock, according to OPERATION,
+ on the file FD refers to. */
+int
+DEFUN(__flock, (fd, operation),
+ int fd AND int operation)
+{
+ error_t err;
+
+ if (err = HURD_DPORT_USE (fd, __file_lock (port, operation)))
+ return __hurd_dfail (fd, err);
+
+ return 0;
+}
+
+weak_alias (__flock, flock)
diff --git a/sysdeps/mach/hurd/fork.c b/sysdeps/mach/hurd/fork.c
new file mode 100644
index 0000000000..b9170f155e
--- /dev/null
+++ b/sysdeps/mach/hurd/fork.c
@@ -0,0 +1,574 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <setjmp.h>
+#include "thread_state.h"
+#include <sysdep.h> /* For stack growth direction. */
+#include "set-hooks.h"
+#include <assert.h>
+#include "hurdmalloc.h" /* XXX */
+
+extern void _hurd_longjmp_thread_state (struct machine_thread_state *,
+ jmp_buf env, int value);
+
+
+/* Things that want to be locked while forking. */
+struct
+ {
+ size_t n;
+ struct mutex *locks[0];
+ } _hurd_fork_locks;
+
+
+/* Things that want to be called before we fork, to prepare the parent for
+ task_create, when the new child task will inherit our address space. */
+DEFINE_HOOK (_hurd_fork_prepare_hook, (void));
+
+/* Things that want to be called when we are forking, with the above all
+ locked. They are passed the task port of the child. The child process
+ is all set up except for doing proc_child, and has no threads yet. */
+DEFINE_HOOK (_hurd_fork_setup_hook, (void));
+
+/* Things to be run in the child fork. */
+DEFINE_HOOK (_hurd_fork_child_hook, (void));
+
+/* Things to be run in the parent fork. */
+DEFINE_HOOK (_hurd_fork_parent_hook, (void));
+
+
+/* Clone the calling process, creating an exact copy.
+ Return -1 for errors, 0 to the new process,
+ and the process ID of the new process to the old process. */
+pid_t
+__fork (void)
+{
+ jmp_buf env;
+ pid_t pid;
+ size_t i;
+ error_t err;
+ thread_t thread_self = __mach_thread_self ();
+ struct hurd_sigstate *volatile ss;
+ sigset_t pending;
+
+ void unlockss (void)
+ {
+ __spin_lock (&ss->lock);
+ ss->critical_section = 0;
+ pending = ss->pending & ~ss->blocked;
+ __spin_unlock (&ss->lock);
+ /* XXX Copying mutex into child and calling mutex_unlock lossy. */
+ __mutex_unlock (&_hurd_siglock);
+ ss = NULL; /* Make sure we crash if we use it again. */
+ }
+
+ ss = _hurd_self_sigstate ();
+ __spin_lock (&ss->lock);
+ ss->critical_section = 1;
+ __spin_unlock (&ss->lock);
+ __mutex_lock (&_hurd_siglock);
+
+ if (! setjmp (env))
+ {
+ process_t newproc;
+ task_t newtask;
+ thread_t thread, sigthread;
+ mach_port_urefs_t thread_refs, sigthread_refs;
+ struct machine_thread_state state;
+ mach_msg_type_number_t statecount;
+ mach_port_t *portnames = NULL;
+ mach_msg_type_number_t nportnames = 0;
+ mach_port_type_t *porttypes = NULL;
+ mach_msg_type_number_t nporttypes = 0;
+ thread_t *threads = NULL;
+ mach_msg_type_number_t nthreads = 0;
+ int ports_locked = 0;
+
+ /* Run things that prepare for forking before we create the task. */
+ RUN_HOOK (_hurd_fork_prepare_hook, ());
+
+ /* Lock things that want to be locked before we fork. */
+ for (i = 0; i < _hurd_fork_locks.n; ++i)
+ __mutex_lock (_hurd_fork_locks.locks[i]);
+
+ newtask = MACH_PORT_NULL;
+ thread = sigthread = MACH_PORT_NULL;
+ newproc = MACH_PORT_NULL;
+
+ /* Lock all the port cells for the standard ports while we copy the
+ address space. We want to insert all the send rights into the
+ child with the same names. */
+ for (i = 0; i < _hurd_nports; ++i)
+ __spin_lock (&_hurd_ports[i].lock);
+ ports_locked = 1;
+
+ /* Create the child task. It will inherit a copy of our memory. */
+ if (err = __task_create (__mach_task_self (), 1, &newtask))
+ goto lose;
+
+ /* Fetch the names of all ports used in this task. */
+ if (err = __mach_port_names (__mach_task_self (),
+ &portnames, &nportnames,
+ &porttypes, &nporttypes))
+ goto lose;
+ if (nportnames != nporttypes)
+ {
+ err = EGRATUITOUS;
+ goto lose;
+ }
+
+ /* Get send rights for all the threads in this task.
+ We want to avoid giving these rights to the child. */
+ if (err = __task_threads (__mach_task_self (), &threads, &nthreads))
+ goto lose;
+
+ /* Get the child process's proc server port. We will insert it into
+ the child with the same name as we use for our own proc server
+ port; and we will need it to set the child's message port. */
+ if (err = __proc_task2proc (_hurd_ports[INIT_PORT_PROC].port,
+ newtask, &newproc))
+ goto lose;
+
+ /* Insert all our port rights into the child task. */
+ thread_refs = sigthread_refs = 0;
+ for (i = 0; i < nportnames; ++i)
+ {
+ if (porttypes[i] & MACH_PORT_TYPE_RECEIVE)
+ {
+ /* This is a receive right. We want to give the child task
+ its own new receive right under the same name. */
+ err = __mach_port_allocate_name (newtask,
+ MACH_PORT_RIGHT_RECEIVE,
+ portnames[i]);
+ if (err == KERN_NAME_EXISTS)
+ {
+ /* It already has a right under this name (?!). Well,
+ there is this bizarre old Mach IPC feature (in #ifdef
+ MACH_IPC_COMPAT in the ukernel) which results in new
+ tasks getting a new receive right for task special
+ port number 2. What else might be going on I'm not
+ sure. So let's check. */
+#if !MACH_IPC_COMPAT
+#define TASK_NOTIFY_PORT 2
+#endif
+ assert (({ mach_port_t thisport, notify_port;
+ mach_msg_type_name_t poly;
+ (__task_get_special_port (newtask,
+ TASK_NOTIFY_PORT,
+ &notify_port) == 0 &&
+ __mach_port_extract_right
+ (newtask,
+ portnames[i],
+ MACH_MSG_TYPE_MAKE_SEND,
+ &thisport, &poly) == 0 &&
+ (thisport == notify_port) &&
+ __mach_port_deallocate (__mach_task_self (),
+ thisport) == 0 &&
+ __mach_port_deallocate (__mach_task_self (),
+ notify_port) == 0);
+ }));
+ }
+ else if (err)
+ goto lose;
+ if (porttypes[i] & MACH_PORT_TYPE_SEND)
+ {
+ /* Give the child as many send rights for its receive
+ right as we have for ours. */
+ mach_port_urefs_t refs;
+ mach_port_t port;
+ mach_msg_type_name_t poly;
+ if (err = __mach_port_get_refs (__mach_task_self (),
+ portnames[i],
+ MACH_PORT_RIGHT_SEND,
+ &refs))
+ goto lose;
+ if (err = __mach_port_extract_right (newtask,
+ portnames[i],
+ MACH_MSG_TYPE_MAKE_SEND,
+ &port, &poly))
+ goto lose;
+ if (portnames[i] == _hurd_msgport)
+ {
+ /* We just created a receive right for the child's
+ message port and are about to insert send rights
+ for it. Now, while we happen to have a send right
+ for it, give it to the proc server. */
+ mach_port_t old;
+ if (err = __proc_setmsgport (newproc, port, &old))
+ goto lose;
+ if (old != MACH_PORT_NULL)
+ /* XXX what to do here? */
+ __mach_port_deallocate (__mach_task_self (), old);
+ }
+ if (err = __mach_port_insert_right (newtask,
+ portnames[i],
+ port,
+ MACH_MSG_TYPE_MOVE_SEND))
+ goto lose;
+ if (refs > 1 &&
+ (err = __mach_port_mod_refs (newtask,
+ portnames[i],
+ MACH_PORT_RIGHT_SEND,
+ refs - 1)))
+ goto lose;
+ }
+ if (porttypes[i] & MACH_PORT_TYPE_SEND_ONCE)
+ {
+ /* Give the child a send-once right for its receive right,
+ since we have one for ours. */
+ mach_port_t port;
+ mach_msg_type_name_t poly;
+ if (err = __mach_port_extract_right
+ (newtask,
+ portnames[i],
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ &port, &poly))
+ goto lose;
+ if (err = __mach_port_insert_right
+ (newtask,
+ portnames[i], port,
+ MACH_MSG_TYPE_MOVE_SEND_ONCE))
+ goto lose;
+ }
+ }
+ else if (porttypes[i] & MACH_PORT_TYPE_SEND)
+ {
+ /* This is a send right or a dead name.
+ Give the child as many references for it as we have. */
+ mach_port_urefs_t refs, *record_refs = NULL;
+ mach_port_t insert;
+ if (portnames[i] == newtask)
+ /* Skip the name we use for the child's task port. */
+ continue;
+ if (portnames[i] == __mach_task_self ())
+ /* For the name we use for our own task port,
+ insert the child's task port instead. */
+ insert = newtask;
+ else if (portnames[i] == _hurd_ports[INIT_PORT_PROC].port)
+ {
+ /* Get the proc server port for the new task. */
+ if (err = __proc_task2proc (portnames[i], newtask, &insert))
+ goto lose;
+ }
+ else if (portnames[i] == thread_self)
+ {
+ /* For the name we use for our own thread port, we will
+ insert the thread port for the child main user thread
+ after we create it. */
+ insert = MACH_PORT_NULL;
+ record_refs = &thread_refs;
+ /* Allocate a dead name right for this name as a
+ placeholder, so the kernel will not chose this name
+ for any other new port (it might use it for one of the
+ rights created when a thread is created). */
+ if (err = __mach_port_allocate_name
+ (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
+ goto lose;
+ }
+ else if (portnames[i] == _hurd_msgport_thread)
+ /* For the name we use for our signal thread's thread port,
+ we will insert the thread port for the child's signal
+ thread after we create it. */
+ {
+ insert = MACH_PORT_NULL;
+ record_refs = &sigthread_refs;
+ /* Allocate a dead name right as a placeholder. */
+ if (err = __mach_port_allocate_name
+ (newtask, MACH_PORT_RIGHT_DEAD_NAME, portnames[i]))
+ goto lose;
+ }
+ else
+ {
+ /* Skip the name we use for any of our own thread ports. */
+ mach_msg_type_number_t j;
+ for (j = 0; j < nthreads; ++j)
+ if (portnames[i] == threads[j])
+ break;
+ if (j < nthreads)
+ continue;
+
+ insert = portnames[i];
+ }
+ /* Find out how many user references we have for
+ the send right with this name. */
+ if (err = __mach_port_get_refs (__mach_task_self (),
+ portnames[i],
+ MACH_PORT_RIGHT_SEND,
+ record_refs ?: &refs))
+ goto lose;
+ if (insert == MACH_PORT_NULL)
+ continue;
+ /* Insert the chosen send right into the child. */
+ err = __mach_port_insert_right (newtask,
+ portnames[i],
+ insert,
+ MACH_MSG_TYPE_COPY_SEND);
+ if (err == KERN_NAME_EXISTS)
+ {
+ /* It already has a send right under this name (?!).
+ Well, it starts out with a send right for its task
+ port, and inherits the bootstrap and exception ports
+ from us. */
+ mach_port_t childport;
+ mach_msg_type_name_t poly;
+ assert (__mach_port_extract_right (newtask, portnames[i],
+ MACH_MSG_TYPE_COPY_SEND,
+ &childport, &poly) == 0 &&
+ childport == insert &&
+ __mach_port_deallocate (__mach_task_self (),
+ childport) == 0);
+ }
+ else if (err)
+ goto lose;
+ /* Give the child as many user references as we have. */
+ if (refs > 1 &&
+ (err = __mach_port_mod_refs (newtask,
+ portnames[i],
+ MACH_PORT_RIGHT_SEND,
+ refs - 1)))
+ goto lose;
+ }
+ }
+
+ /* Unlock the standard port cells. The child must unlock its own
+ copies too. */
+ for (i = 0; i < _hurd_nports; ++i)
+ __spin_unlock (&_hurd_ports[i].lock);
+ ports_locked = 0;
+
+ /* Unlock the signal state. The child must unlock its own copy too. */
+ unlockss ();
+
+ /* Create the child main user thread and signal thread. */
+ if ((err = __thread_create (newtask, &thread)) ||
+ (err = __thread_create (newtask, &sigthread)))
+ goto lose;
+
+ /* Insert send rights for those threads. We previously allocated
+ dead name rights with the names we want to give the thread ports
+ in the child as placeholders. Now deallocate them so we can use
+ the names. */
+ if ((err = __mach_port_deallocate (newtask, thread_self)) ||
+ (err = __mach_port_insert_right (newtask, thread_self,
+ thread, MACH_MSG_TYPE_COPY_SEND)))
+ goto lose;
+ /* We have one extra user reference created at the beginning of this
+ function, accounted for by mach_port_names (and which will thus be
+ accounted for in the child below). This extra right gets consumed
+ in the child by the store into _hurd_sigthread in the child fork. */
+ if (thread_refs > 1 &&
+ (err = __mach_port_mod_refs (newtask, thread_self,
+ MACH_PORT_RIGHT_SEND,
+ thread_refs - 1)))
+ goto lose;
+ if ((_hurd_msgport_thread != MACH_PORT_NULL) /* Let user have none. */
+ && ((err = __mach_port_deallocate (newtask, _hurd_msgport_thread)) ||
+ (err = __mach_port_insert_right (newtask, _hurd_msgport_thread,
+ sigthread,
+ MACH_MSG_TYPE_COPY_SEND))))
+ goto lose;
+ if (sigthread_refs > 1 &&
+ (err = __mach_port_mod_refs (newtask, _hurd_msgport_thread,
+ MACH_PORT_RIGHT_SEND,
+ sigthread_refs - 1)))
+ goto lose;
+
+ /* This seems like a convenient juncture to copy the proc server's
+ idea of what addresses our argv and envp are found at from the
+ parent into the child. Since we happen to know that the child
+ shares our memory image, it is we who should do this copying. */
+ {
+ vm_address_t argv, envp;
+ err = (__USEPORT (PROC, __proc_get_arg_locations (port, &argv, &envp))
+ ?: __proc_set_arg_locations (newproc, argv, envp));
+ if (err)
+ goto lose;
+ }
+
+ /* Set the child signal thread up to run the msgport server function
+ using the same signal thread stack copied from our address space.
+ We fetch the state before longjmp'ing it so that miscellaneous
+ registers not affected by longjmp (such as i386 segment registers)
+ are in their normal default state. */
+ statecount = MACHINE_THREAD_STATE_COUNT;
+ if (err = __thread_get_state (_hurd_msgport_thread,
+ MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &state, &statecount))
+ goto lose;
+#if STACK_GROWTH_UP
+ state.SP = __hurd_sigthread_stack_base;
+#else
+ state.SP = __hurd_sigthread_stack_end;
+#endif
+ MACHINE_THREAD_STATE_SET_PC (&state,
+ (unsigned long int) _hurd_msgport_receive);
+ if (err = __thread_set_state (sigthread, MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &state, statecount))
+ goto lose;
+ /* We do not thread_resume SIGTHREAD here because the child
+ fork needs to do more setup before it can take signals. */
+
+ /* Set the child user thread up to return 1 from the setjmp above. */
+ _hurd_longjmp_thread_state (&state, env, 1);
+ if (err = __thread_set_state (thread, MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &state, statecount))
+ goto lose;
+
+ /* Get the PID of the child from the proc server. We must do this
+ before calling proc_child below, because at that point any
+ authorized POSIX.1 process may kill the child task with SIGKILL. */
+ if (err = __USEPORT (PROC, __proc_task2pid (port, newtask, &pid)))
+ goto lose;
+
+ /* Register the child with the proc server. It is important that
+ this be that last thing we do before starting the child thread
+ running. Once proc_child has been done for the task, it appears
+ as a POSIX.1 process. Any errors we get must be detected before
+ this point, and the child must have a message port so it responds
+ to POSIX.1 signals. */
+ if (err = __USEPORT (PROC, __proc_child (port, newtask)))
+ goto lose;
+
+ /* This must be the absolutely last thing we do; we can't assume that
+ the child will remain alive for even a moment once we do this. We
+ ignore errors because we have committed to the fork and are not
+ allowed to return them after the process becomes visible to
+ POSIX.1 (which happened right above when we called proc_child). */
+ (void) __thread_resume (thread);
+
+ lose:
+ if (ports_locked)
+ for (i = 0; i < _hurd_nports; ++i)
+ __spin_unlock (&_hurd_ports[i].lock);
+
+ if (newtask != MACH_PORT_NULL)
+ {
+ if (err)
+ __task_terminate (newtask);
+ __mach_port_deallocate (__mach_task_self (), newtask);
+ }
+ if (thread != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), thread);
+ if (sigthread != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), sigthread);
+ if (newproc != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), newproc);
+ if (thread_self != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), thread_self);
+
+ if (portnames)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) portnames,
+ nportnames * sizeof (*portnames));
+ if (porttypes)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) porttypes,
+ nporttypes * sizeof (*porttypes));
+ if (threads)
+ {
+ for (i = 0; i < nthreads; ++i)
+ __mach_port_deallocate (__mach_task_self (), threads[i]);
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) threads,
+ nthreads * sizeof (*threads));
+ }
+
+ /* Run things that want to run in the parent to restore it to
+ normality. Usually prepare hooks and parent hooks are
+ symmetrical: the prepare hook arrests state in some way for the
+ fork, and the parent hook restores the state for the parent to
+ continue executing normally. */
+ RUN_HOOK (_hurd_fork_parent_hook, ());
+ }
+ else
+ {
+ struct hurd_sigstate *oldstates;
+
+ /* We are the child task. Unlock the standard port cells, which were
+ locked in the parent when we copied its memory. The parent has
+ inserted send rights with the names that were in the cells then. */
+ for (i = 0; i < _hurd_nports; ++i)
+ __spin_unlock (&_hurd_ports[i].lock);
+
+ /* We are the only thread in this new task, so we will
+ take the task-global signals. */
+ _hurd_sigthread = thread_self;
+
+ /* Unchain the sigstate structures for threads that existed in the
+ parent task but don't exist in this task (the child process).
+ Delay freeing them until later because some of the further setup
+ and unlocking might be required for free to work. */
+ oldstates = _hurd_sigstates;
+ if (oldstates == ss)
+ oldstates = ss->next;
+ else
+ {
+ while (_hurd_sigstates->next != ss)
+ _hurd_sigstates = _hurd_sigstates->next;
+ _hurd_sigstates->next = ss->next;
+ }
+ ss->next = NULL;
+ _hurd_sigstates = ss;
+
+ /* Unlock our copies of the signal state locks. */
+ unlockss ();
+
+ /* Fetch our new process IDs from the proc server. No need to
+ refetch our pgrp; it is always inherited from the parent (so
+ _hurd_pgrp is already correct), and the proc server will send us a
+ proc_newids notification when it changes. */
+ err = __USEPORT (PROC, __proc_getpids (port, &_hurd_pid, &_hurd_ppid,
+ &_hurd_orphaned));
+
+ /* Run things that want to run in the child task to set up. */
+ RUN_HOOK (_hurd_fork_child_hook, ());
+
+ /* Set up proc server-assisted fault recovery for the signal thread. */
+ _hurdsig_fault_init ();
+
+ /* Start the signal thread listening on the message port. */
+ if (!err)
+ err = __thread_resume (_hurd_msgport_thread);
+
+ /* Free the old sigstate structures. */
+ while (oldstates != NULL)
+ {
+ struct hurd_sigstate *next = oldstates->next;
+ free (oldstates);
+ oldstates = next;
+ }
+ /* XXX what to do if we have any errors here? */
+
+ pid = 0;
+ }
+
+ /* Unlock things we locked before creating the child task.
+ They are locked in both the parent and child tasks. */
+ for (i = 0; i < _hurd_fork_locks.n; ++i)
+ __mutex_unlock (_hurd_fork_locks.locks[i]);
+
+ if (pending)
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+
+ return err ? __hurd_fail (err) : pid;
+}
+
+weak_alias (__fork, fork)
diff --git a/sysdeps/mach/hurd/fstat.c b/sysdeps/mach/hurd/fstat.c
new file mode 100644
index 0000000000..5341e3e4a4
--- /dev/null
+++ b/sysdeps/mach/hurd/fstat.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Get information about the file descriptor FD in BUF. */
+int
+DEFUN(__fstat, (fd, buf), int fd AND struct stat *buf)
+{
+ error_t err;
+
+ if (err = HURD_DPORT_USE (fd, __io_stat (port, buf)))
+ return __hurd_dfail (fd, err);
+
+ return 0;
+}
+
+weak_alias (__fstat, fstat)
diff --git a/sysdeps/mach/hurd/fsync.c b/sysdeps/mach/hurd/fsync.c
new file mode 100644
index 0000000000..adfe9800d3
--- /dev/null
+++ b/sysdeps/mach/hurd/fsync.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Make all changes done to FD actually appear on disk. */
+int
+DEFUN(fsync, (fd), int fd)
+{
+ error_t err = HURD_DPORT_USE (fd, __file_sync (port, 1));
+ if (err)
+ return __hurd_dfail (fd, err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/ftruncate.c b/sysdeps/mach/hurd/ftruncate.c
new file mode 100644
index 0000000000..23a5e796cc
--- /dev/null
+++ b/sysdeps/mach/hurd/ftruncate.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Truncate the file FD refers to to LENGTH bytes. */
+int
+DEFUN(ftruncate, (fd, length),
+ int fd AND off_t length)
+{
+ error_t err;
+ if (err = HURD_DPORT_USE (fd, __file_truncate (port, length)))
+ return __hurd_dfail (fd, err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/getcwd.c b/sysdeps/mach/hurd/getcwd.c
new file mode 100644
index 0000000000..c0d9bcd567
--- /dev/null
+++ b/sysdeps/mach/hurd/getcwd.c
@@ -0,0 +1,250 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+
+
+/* Get the pathname of the current working directory, and put it in SIZE
+ bytes of BUF. Returns NULL if the directory couldn't be determined or
+ SIZE was too small. If successful, returns BUF. In GNU, if BUF is
+ NULL, an array is allocated with `malloc'; the array is SIZE bytes long,
+ unless SIZE <= 0, in which case it is as big as necessary. */
+
+char *
+getcwd (char *buf, size_t size)
+{
+ error_t err;
+ dev_t rootdev, thisdev;
+ ino_t rootino, thisino;
+ char *file_name;
+ register char *file_namep;
+ struct stat st;
+ file_t parent;
+ char *dirbuf = NULL;
+ unsigned int dirbufsize = 0;
+ file_t crdir;
+ struct hurd_userlink crdir_ulink;
+
+ inline void cleanup (void)
+ {
+ _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
+ __mach_port_deallocate (__mach_task_self (), parent);
+
+ if (dirbuf != NULL)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) dirbuf, dirbufsize);
+ }
+
+
+ if (size == 0)
+ {
+ if (buf != NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ size = FILENAME_MAX * 4 + 1; /* Good starting guess. */
+ }
+
+ if (buf != NULL)
+ file_name = buf;
+ else
+ {
+ file_name = malloc (size);
+ if (file_name == NULL)
+ return NULL;
+ }
+
+ file_namep = file_name + size;
+ *--file_namep = '\0';
+
+ /* Get a port to our root directory and stat it. */
+
+ crdir = _hurd_port_get (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink);
+ if (err = __io_stat (crdir, &st))
+ {
+ _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
+ return __hurd_fail (err), NULL;
+ }
+ rootdev = st.st_dev;
+ rootino = st.st_ino;
+
+ /* Get a port to our current working directory and stat it. */
+
+ if (err = __USEPORT (CWDIR, __mach_port_mod_refs (__mach_task_self (),
+ (parent = port),
+ MACH_PORT_RIGHT_SEND,
+ 1)))
+ {
+ _hurd_port_free (&_hurd_ports[INIT_PORT_CRDIR], &crdir_ulink, crdir);
+ return __hurd_fail (err), NULL;
+ }
+ if (err = __io_stat (parent, &st))
+ {
+ cleanup ();
+ return __hurd_fail (err), NULL;
+ }
+
+ thisdev = st.st_dev;
+ thisino = st.st_ino;
+
+ while (!(thisdev == rootdev && thisino == rootino))
+ {
+ /* PARENT is a port to the directory we are currently on;
+ THISDEV and THISINO are its device and node numbers.
+ Look in its parent (..) for a file with the same numbers. */
+
+ struct dirent *d;
+ dev_t dotdev;
+ ino_t dotino;
+ int mount_point;
+ file_t newp;
+ char *dirdata;
+ unsigned int dirdatasize;
+ int direntry, nentries;
+
+ /* Look at the parent directory. */
+ if (err = __hurd_file_name_lookup (crdir, parent, "..", O_READ, 0, &newp))
+ goto lose;
+ __mach_port_deallocate (__mach_task_self (), parent);
+ parent = newp;
+
+ /* Figure out if this directory is a mount point. */
+ if (err = __io_stat (parent, &st))
+ goto lose;
+ dotdev = st.st_dev;
+ dotino = st.st_ino;
+ mount_point = dotdev != thisdev;
+
+ /* Search for the last directory. */
+ direntry = 0;
+ dirdata = dirbuf;
+ dirdatasize = dirbufsize;
+ while (!(err = __dir_readdir (parent, &dirdata, &dirdatasize,
+ direntry, -1, 0, &nentries)) &&
+ nentries != 0)
+ {
+ /* We have a block of directory entries. */
+
+ unsigned int offset;
+
+ direntry += nentries;
+
+ if (dirdata != dirbuf)
+ {
+ /* The data was passed out of line, so our old buffer is no
+ longer useful. Deallocate the old buffer and reset our
+ information for the new buffer. */
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) dirbuf, dirbufsize);
+ dirbuf = dirdata;
+ dirbufsize = round_page (dirdatasize);
+ }
+
+ /* Iterate over the returned directory entries, looking for one
+ whose file number is THISINO. */
+
+ offset = 0;
+ while (offset < dirdatasize)
+ {
+ d = (struct dirent *) &dirdata[offset];
+ offset += d->d_reclen;
+
+ /* Ignore `.' and `..'. */
+ if (d->d_name[0] == '.' &&
+ (d->d_namlen == 1 ||
+ (d->d_namlen == 2 && d->d_name[1] == '.')))
+ continue;
+
+ if (mount_point || d->d_ino == thisino)
+ {
+ file_t try;
+ if (err = __hurd_file_name_lookup (crdir, parent, d->d_name,
+ O_NOLINK, 0, &try))
+ goto lose;
+ err = __io_stat (try, &st);
+ __mach_port_deallocate (__mach_task_self (), try);
+ if (err)
+ goto lose;
+ if (st.st_dev == thisdev && st.st_ino == thisino)
+ break;
+ }
+ }
+ }
+
+ if (err)
+ goto lose;
+ else
+ {
+ /* Prepend the directory name just discovered. */
+
+ if (file_namep - file_name < d->d_namlen + 1)
+ {
+ if (buf != NULL)
+ {
+ errno = ERANGE;
+ return NULL;
+ }
+ else
+ {
+ size *= 2;
+ buf = realloc (file_name, size);
+ if (buf == NULL)
+ {
+ free (file_name);
+ return NULL;
+ }
+ file_namep = &buf[file_namep - file_name];
+ file_name = buf;
+ }
+ }
+ file_namep -= d->d_namlen;
+ (void) memcpy (file_namep, d->d_name, d->d_namlen);
+ *--file_namep = '/';
+ }
+
+ /* The next iteration will find the name of the directory we
+ just searched through. */
+ thisdev = dotdev;
+ thisino = dotino;
+ }
+
+ if (file_namep == &file_name[size - 1])
+ /* We found nothing and got all the way to the root.
+ So the root is our current directory. */
+ *--file_namep = '/';
+
+ memmove (file_name, file_namep, file_name + size - file_namep);
+ cleanup ();
+ return file_name;
+
+ lose:
+ cleanup ();
+ return NULL;
+}
diff --git a/sysdeps/mach/hurd/getdents.c b/sysdeps/mach/hurd/getdents.c
new file mode 100644
index 0000000000..4de2eb351d
--- /dev/null
+++ b/sysdeps/mach/hurd/getdents.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Ince
+
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <string.h>
+
+ssize_t
+DEFUN(__getdirentries, (fd, buf, nbytes, basep),
+ int fd AND PTR buf AND size_t nbytes AND off_t *basep)
+{
+ error_t err;
+ int entriesread;
+ char *data = buf;
+ mach_msg_type_number_t bytesread = nbytes;
+
+ /* Fault before taking any locks. */
+ *(volatile off_t *) basep = *basep;
+
+ err = HURD_DPORT_USE (fd, __dir_readdir (port, &data, &bytesread,
+ *basep, -1, nbytes, &entriesread));
+ if (err)
+ return __hurd_dfail (fd, err);
+
+ if (data != buf)
+ {
+ size_t copy = bytesread;
+ if (copy > nbytes)
+ /* The server has a violated the dir_readdir protocol. */
+ copy = nbytes;
+ memcpy (buf, data, copy);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) data, bytesread);
+ bytesread = copy;
+ }
+
+ *basep += entriesread;
+
+ return bytesread;
+}
+
+weak_alias (__getdirentries, getdirentries)
+
diff --git a/sysdeps/mach/hurd/getdtsz.c b/sysdeps/mach/hurd/getdtsz.c
new file mode 100644
index 0000000000..e506963ac3
--- /dev/null
+++ b/sysdeps/mach/hurd/getdtsz.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Return the maximum number of file descriptors the current process
+ could possibly have (until it raises the resource limit). */
+int
+DEFUN_VOID(__getdtablesize)
+{
+ int size;
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_dtable_lock);
+ size = _hurd_dtablesize;
+ __mutex_unlock (&_hurd_dtable_lock);
+ HURD_CRITICAL_END;
+ return size;
+}
+
+weak_alias (__getdtablesize, getdtablesize)
diff --git a/sysdeps/mach/hurd/getegid.c b/sysdeps/mach/hurd/getegid.c
new file mode 100644
index 0000000000..88f6ea00e2
--- /dev/null
+++ b/sysdeps/mach/hurd/getegid.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+
+/* Get the effective group ID of the calling process. */
+gid_t
+DEFUN_VOID(__getegid)
+{
+ error_t err;
+ gid_t egid;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+
+ if (err = _hurd_check_ids ())
+ {
+ errno = err;
+ egid = -1;
+ }
+ else if (_hurd_id.gen.ngids >= 1)
+ egid = _hurd_id.gen.gids[0];
+ else if (_hurd_id.aux.ngids >= 1)
+ /* We have no effective gids. Return the real gid. */
+ egid = _hurd_id.aux.gids[0];
+ else
+ {
+ /* We do not even have a real gid. */
+ errno = EGRATUITOUS;
+ egid = -1;
+ }
+
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ return egid;
+}
+
+weak_alias (__getegid, getegid)
diff --git a/sysdeps/mach/hurd/geteuid.c b/sysdeps/mach/hurd/geteuid.c
new file mode 100644
index 0000000000..416cd31f82
--- /dev/null
+++ b/sysdeps/mach/hurd/geteuid.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+
+/* Get the effective user ID of the calling process. */
+uid_t
+DEFUN_VOID(__geteuid)
+{
+ error_t err;
+ uid_t euid;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+
+ if (err = _hurd_check_ids ())
+ {
+ errno = err;
+ euid = -1;
+ }
+ else if (_hurd_id.gen.nuids >= 1)
+ euid = _hurd_id.gen.uids[0];
+ else if (_hurd_id.aux.nuids >= 1)
+ /* We have no effective uids. Return the real uid. */
+ euid = _hurd_id.aux.uids[0];
+ else
+ {
+ /* We do not even have a real uid. */
+ errno = EGRATUITOUS;
+ euid = -1;
+ }
+
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ return euid;
+}
+
+weak_alias (__geteuid, geteuid)
diff --git a/sysdeps/mach/hurd/getgid.c b/sysdeps/mach/hurd/getgid.c
new file mode 100644
index 0000000000..0d1b27f8e6
--- /dev/null
+++ b/sysdeps/mach/hurd/getgid.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+
+/* Get the real group ID of the calling process. */
+gid_t
+DEFUN_VOID(__getgid)
+{
+ error_t err;
+ gid_t gid;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+
+ if (err = _hurd_check_ids ())
+ {
+ errno = err;
+ gid = -1;
+ }
+ else if (_hurd_id.aux.ngids >= 1)
+ gid = _hurd_id.aux.gids[0];
+ else
+ {
+ /* We do not even have a real gid. */
+ errno = EGRATUITOUS;
+ gid = -1;
+ }
+
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ return gid;
+}
+
+weak_alias (__getgid, getgid)
diff --git a/sysdeps/mach/hurd/getgroups.c b/sysdeps/mach/hurd/getgroups.c
new file mode 100644
index 0000000000..d985d29317
--- /dev/null
+++ b/sysdeps/mach/hurd/getgroups.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+#include <string.h>
+
+int
+__getgroups (int n, gid_t *gidset)
+{
+ error_t err;
+ int ngids;
+ void *crit;
+
+ crit = _hurd_critical_section_lock ();
+ __mutex_lock (&_hurd_id.lock);
+
+ if (err = _hurd_check_ids ())
+ {
+ __mutex_unlock (&_hurd_id.lock);
+ _hurd_critical_section_unlock (crit);
+ return __hurd_fail (err);
+ }
+
+ ngids = _hurd_id.gen.ngids;
+
+ if (n != 0)
+ {
+ /* Copy the gids onto stack storage and then release the idlock. */
+ gid_t gids[ngids];
+ memcpy (gids, _hurd_id.gen.gids, sizeof (gids));
+ __mutex_unlock (&_hurd_id.lock);
+ _hurd_critical_section_unlock (crit);
+
+ /* Now that the lock is released, we can safely copy the
+ group set into the user's array, which might fault. */
+ if (ngids > n)
+ ngids = n;
+ memcpy (gidset, gids, ngids * sizeof (gid_t));
+ }
+ else
+ {
+ __mutex_unlock (&_hurd_id.lock);
+ _hurd_critical_section_unlock (crit);
+ }
+
+ return ngids;
+}
+
+weak_alias (__getgroups, getgroups)
diff --git a/sysdeps/mach/hurd/gethostid.c b/sysdeps/mach/hurd/gethostid.c
new file mode 100644
index 0000000000..5a3309266e
--- /dev/null
+++ b/sysdeps/mach/hurd/gethostid.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Return the current machine's Internet number. */
+long int
+DEFUN_VOID(gethostid)
+{
+ int hostid;
+ error_t err;
+ if (err = __USEPORT (PROC, __proc_gethostid (port, &hostid)))
+ return __hurd_fail (err);
+ return hostid;
+}
diff --git a/sysdeps/mach/hurd/gethostname.c b/sysdeps/mach/hurd/gethostname.c
new file mode 100644
index 0000000000..94a0537d91
--- /dev/null
+++ b/sysdeps/mach/hurd/gethostname.c
@@ -0,0 +1,48 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <string.h>
+
+/* Put the name of the current host in no more than LEN bytes of NAME.
+ The result is null-terminated if LEN is large enough for the full
+ name and the terminator. */
+int
+DEFUN(__gethostname, (name, len),
+ char *name AND size_t len)
+{
+ error_t err;
+ char *buf = name;
+ mach_msg_type_number_t buflen = len;
+ if (err = __USEPORT (PROC, __proc_gethostname (port, &buf, &buflen)))
+ return __hurd_fail (err);
+ if (buf != name)
+ {
+ memcpy (name, buf, len < buflen ? len : buflen);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+ if (buflen > len)
+ return __hurd_fail (ENAMETOOLONG);
+ return 0;
+}
+
+weak_alias (__gethostname, gethostname)
diff --git a/sysdeps/mach/hurd/getitimer.c b/sysdeps/mach/hurd/getitimer.c
new file mode 100644
index 0000000000..15c46cae68
--- /dev/null
+++ b/sysdeps/mach/hurd/getitimer.c
@@ -0,0 +1,104 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <hurd.h>
+
+/* XXX Temporary cheezoid implementation; see __setitmr.c. */
+
+/* These are defined in __setitmr.c. */
+extern spin_lock_t _hurd_itimer_lock;
+extern struct itimerval _hurd_itimerval;
+extern struct timeval _hurd_itimer_started;
+
+static inline void
+subtract_timeval (struct timeval *from, const struct timeval *subtract)
+{
+ from->tv_usec -= subtract->tv_usec;
+ from->tv_sec -= subtract->tv_sec;
+ while (from->tv_usec < 0)
+ {
+ --from->tv_sec;
+ from->tv_usec += 1000000;
+ }
+}
+
+/* Set *VALUE to the current setting of timer WHICH.
+ Return 0 on success, -1 on errors. */
+int
+DEFUN(__getitimer, (which, value),
+ enum __itimer_which which AND struct itimerval *value)
+{
+ struct itimerval val;
+ struct timeval elapsed;
+
+ switch (which)
+ {
+ default:
+ return __hurd_fail (EINVAL);
+
+ case ITIMER_VIRTUAL:
+ case ITIMER_PROF:
+ return __hurd_fail (ENOSYS);
+
+ case ITIMER_REAL:
+ break;
+ }
+
+ /* Get the time now. */
+ if (__gettimeofday (&elapsed, NULL) < 0)
+ return -1;
+
+ /* Extract the current timer setting; and the time it was set, so we can
+ calculate the time elapsed so far. */
+ HURD_CRITICAL_BEGIN;
+ __spin_lock (&_hurd_itimer_lock);
+ val = _hurd_itimerval;
+ subtract_timeval (&elapsed, &_hurd_itimer_started);
+ __spin_unlock (&_hurd_itimer_lock);
+ HURD_CRITICAL_END;
+
+ if ((val.it_value.tv_sec | val.it_value.tv_usec) != 0)
+ {
+ /* There is a pending alarm set. VAL indicates the interval it was
+ set for, relative to the time recorded in _hurd_itimer_started.
+ Now compensate for the time elapsed since to get the user's
+ conception of the current value of the timer (as if the value
+ stored decreased every microsecond). */
+ if (timercmp (&val.it_value, &elapsed, <))
+ {
+ /* Hmm. The timer should have just gone off, but has not been
+ reset. This is a possible timing glitch. The alarm will signal
+ soon, so fabricate a value for how soon. */
+ val.it_value.tv_sec = 0;
+ val.it_value.tv_usec = 10; /* Random. */
+ }
+ else
+ /* Subtract the time elapsed since the timer was set
+ from the current timer value the user sees. */
+ subtract_timeval (&val.it_value, &elapsed);
+ }
+
+ *value = val;
+ return 0;
+}
+
+weak_alias (__getitimer, getitimer)
diff --git a/sysdeps/mach/hurd/getlogin.c b/sysdeps/mach/hurd/getlogin.c
new file mode 100644
index 0000000000..523db3f2d7
--- /dev/null
+++ b/sysdeps/mach/hurd/getlogin.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Return the login name of the user, or NULL if it can't be determined.
+ The returned pointer, if not NULL, is good only until the next call. */
+char *
+DEFUN_VOID(getlogin)
+{
+ static char login[1024]; /* XXX */
+ error_t err;
+
+ if (err = __USEPORT (PROC, __proc_getlogin (port, login)))
+ {
+ errno = err;
+ return NULL;
+ }
+
+ return login;
+}
diff --git a/sysdeps/mach/hurd/getpeername.c b/sysdeps/mach/hurd/getpeername.c
new file mode 100644
index 0000000000..a9ea32c2ae
--- /dev/null
+++ b/sysdeps/mach/hurd/getpeername.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <string.h>
+
+/* Put the address of the peer connected to socket FD into *ADDR
+ (which is *LEN bytes long), and its actual length into *LEN. */
+int
+DEFUN(getpeername, (fd, addr, len),
+ int fd AND struct sockaddr *addr AND size_t *len)
+{
+ error_t err;
+ char *buf = (char *) addr;
+ mach_msg_type_number_t buflen = *len;
+ int type;
+ addr_port_t aport;
+
+ if (err = HURD_DPORT_USE (fd, __socket_peername (port, &aport)))
+ return __hurd_dfail (fd, err);
+
+ err = __socket_whatis_address (aport, &type, &buf, &buflen);
+ __mach_port_deallocate (__mach_task_self (), aport);
+
+ if (err)
+ return __hurd_dfail (fd, err);
+
+ if (buf != (char *) addr)
+ {
+ if (*len < buflen)
+ *len = buflen;
+ memcpy (addr, buf, *len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ addr->sa_family = type;
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/getpgid.c b/sysdeps/mach/hurd/getpgid.c
new file mode 100644
index 0000000000..b9a3634fed
--- /dev/null
+++ b/sysdeps/mach/hurd/getpgid.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+
+/* Get the process group ID of process PID. */
+int
+DEFUN(__getpgid, (pid), pid_t pid)
+{
+ error_t err;
+ pid_t pgrp;
+
+ if (pid == 0)
+ {
+ /* Assume atomic word fetch and store, so don't lock _hurd_pid_lock. */
+ pgrp = _hurd_pgrp;
+ err = 0;
+ }
+ else
+ err = __USEPORT (PROC, __proc_getpgrp (port, pid, &pgrp));
+
+ return err ? __hurd_fail (err) : pgrp;
+}
+
+weak_alias (__getpgid, getpgid)
diff --git a/sysdeps/mach/hurd/getpid.c b/sysdeps/mach/hurd/getpid.c
new file mode 100644
index 0000000000..bbff6a3ca0
--- /dev/null
+++ b/sysdeps/mach/hurd/getpid.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Get the process ID of the calling process. */
+pid_t
+DEFUN_VOID(__getpid)
+{
+ /* Assumes atomic word fetch and store, so doesn't lock _hurd_pid_lock. */
+ return _hurd_pid;
+}
+
+weak_alias (__getpid, getpid)
diff --git a/sysdeps/mach/hurd/getppid.c b/sysdeps/mach/hurd/getppid.c
new file mode 100644
index 0000000000..6a5ac1dd1b
--- /dev/null
+++ b/sysdeps/mach/hurd/getppid.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991, 1993, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+
+
+/* Get the parent process ID of the calling process. */
+pid_t
+DEFUN_VOID(__getppid)
+{
+ /* Assumes atomic word fetch and store, so doesn't lock _hurd_pid_lock. */
+ return _hurd_ppid;
+}
+
+weak_alias (__getppid, getppid)
diff --git a/sysdeps/mach/hurd/getpriority.c b/sysdeps/mach/hurd/getpriority.c
new file mode 100644
index 0000000000..5b24ce23f8
--- /dev/null
+++ b/sysdeps/mach/hurd/getpriority.c
@@ -0,0 +1,73 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <limits.h>
+#include <hurd.h>
+#include <hurd/resource.h>
+
+/* Return the highest priority of any process specified by WHICH and WHO
+ (see <sys/resource.h>); if WHO is zero, the current process, process group,
+ or user (as specified by WHO) is used. A lower priority number means higher
+ priority. Priorities range from PRIO_MIN to PRIO_MAX. */
+int
+getpriority (enum __priority_which which, int who)
+{
+ error_t err, onerr;
+ int maxpri = INT_MIN;
+ struct procinfo *pip; /* Just for sizeof. */
+ int pibuf[sizeof *pip + 2 * sizeof (pip->threadinfos[0])], *pi = pibuf;
+ unsigned int pisize = sizeof pibuf / sizeof pibuf[0];
+
+ error_t getonepriority (pid_t pid, struct procinfo *pip)
+ {
+ if (pip)
+ onerr = 0;
+ else
+ {
+ int *oldpi = pi;
+ unsigned int oldpisize = pisize;
+ onerr = __USEPORT (PROC, __proc_getprocinfo (port,
+ pid,
+ &pi, &pisize));
+ if (pi != oldpi && oldpi != pibuf)
+ /* Old buffer from last call was not reused; free it. */
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) oldpi, oldpisize * sizeof pi[0]);
+ pip = (struct procinfo *) pi;
+ }
+ if (!onerr && pip->taskinfo.base_priority > maxpri)
+ maxpri = pip->taskinfo.base_priority;
+ return 0;
+ }
+
+ onerr = 0;
+ err = _hurd_priority_which_map (which, who, getonepriority);
+
+ if (pi != pibuf)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) pi, pisize * sizeof pi[0]);
+
+ if (!err && maxpri == INT_MIN)
+ /* No error, but no pids found. */
+ err = onerr ?: ESRCH;
+
+ if (err)
+ return __hurd_fail (err);
+
+ return MACH_PRIORITY_TO_NICE (maxpri);
+}
diff --git a/sysdeps/mach/hurd/getrlimit.c b/sysdeps/mach/hurd/getrlimit.c
new file mode 100644
index 0000000000..a05d32277d
--- /dev/null
+++ b/sysdeps/mach/hurd/getrlimit.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/resource.h>
+
+/* Put the soft and hard limits for RESOURCE in *RLIMITS.
+ Returns 0 if successful, -1 if not (and sets errno). */
+int
+DEFUN(getrlimit, (resource, rlimits),
+ enum __rlimit_resource resource AND struct rlimit *rlimits)
+{
+ struct rlimit lim;
+
+ if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __mutex_lock (&_hurd_rlimit_lock);
+ lim = _hurd_rlimits[resource];
+ __mutex_unlock (&_hurd_rlimit_lock);
+
+ *rlimits = lim;
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/getsockname.c b/sysdeps/mach/hurd/getsockname.c
new file mode 100644
index 0000000000..5a9182b4fc
--- /dev/null
+++ b/sysdeps/mach/hurd/getsockname.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <string.h>
+
+/* Put the local address of FD into *ADDR and its length in *LEN. */
+int
+DEFUN(getsockname, (fd, addr, len),
+ int fd AND struct sockaddr *addr AND size_t *len)
+{
+ error_t err;
+ char *buf = (char *) addr;
+ mach_msg_type_number_t buflen = *len;
+ int type;
+ addr_port_t aport;
+
+ if (err = HURD_DPORT_USE (fd, __socket_name (port, &aport)))
+ return __hurd_dfail (fd, err);
+
+ err = __socket_whatis_address (aport, &type, &buf, &buflen);
+ __mach_port_deallocate (__mach_task_self (), aport);
+
+ if (err)
+ return __hurd_dfail (fd, err);
+
+ if (buf != (char *) addr)
+ {
+ if (*len < buflen)
+ *len = buflen;
+ memcpy (addr, buf, *len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ addr->sa_family = type;
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/getsockopt.c b/sysdeps/mach/hurd/getsockopt.c
new file mode 100644
index 0000000000..a9c91ea0f1
--- /dev/null
+++ b/sysdeps/mach/hurd/getsockopt.c
@@ -0,0 +1,53 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <string.h>
+
+/* Put the current value for socket FD's option OPTNAME at protocol level LEVEL
+ into OPTVAL (which is *OPTLEN bytes long), and set *OPTLEN to the value's
+ actual length. Returns 0 on success, -1 for errors. */
+int
+DEFUN(getsockopt, (fd, level, optname, optval, optlen),
+ int fd AND int level AND int optname AND
+ PTR optval AND size_t *optlen)
+{
+ error_t err;
+ char *buf = optval;
+ mach_msg_type_number_t buflen = *optlen;
+
+ if (err = HURD_DPORT_USE (fd, __socket_getopt (port,
+ level, optname,
+ &buf, &buflen)))
+ return __hurd_dfail (fd, err);
+
+ if (buf != optval)
+ {
+ if (*optlen < buflen)
+ *optlen = buflen;
+ memcpy (optval, buf, *optlen);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/getuid.c b/sysdeps/mach/hurd/getuid.c
new file mode 100644
index 0000000000..9381c6e8ec
--- /dev/null
+++ b/sysdeps/mach/hurd/getuid.c
@@ -0,0 +1,55 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+
+/* Get the real user ID of the calling process. */
+uid_t
+DEFUN_VOID(__getuid)
+{
+ error_t err;
+ uid_t uid;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+
+ if (err = _hurd_check_ids ())
+ {
+ errno = err;
+ uid = -1;
+ }
+ else if (_hurd_id.aux.nuids >= 1)
+ uid = _hurd_id.aux.uids[0];
+ else
+ {
+ /* We do not even have a real uid. */
+ errno = EGRATUITOUS;
+ uid = -1;
+ }
+
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ return uid;
+}
+
+weak_alias (__getuid, getuid)
diff --git a/sysdeps/mach/hurd/hppa/sigcontext.h b/sysdeps/mach/hurd/hppa/sigcontext.h
new file mode 100644
index 0000000000..b616469f21
--- /dev/null
+++ b/sysdeps/mach/hurd/hppa/sigcontext.h
@@ -0,0 +1,86 @@
+/* Machine-dependent signal context structure for GNU Hurd. HPPA version.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Signal handlers are actually called:
+ void handler (int sig, int code, struct sigcontext *scp); */
+
+/* State of this thread when the signal was taken. */
+struct sigcontext
+ {
+ /* These first members are machine-independent. */
+
+ int sc_onstack; /* Nonzero if running on sigstack. */
+ __sigset_t sc_mask; /* Blocked signals to restore. */
+
+ /* MiG reply port this thread is using. */
+ unsigned int sc_reply_port;
+
+ /* Port this thread is doing an interruptible RPC on. */
+ unsigned int sc_intr_port;
+
+ /* Error code associated with this signal (interpreted as `error_t'). */
+ int sc_error;
+
+ /* All following members are machine-dependent. The rest of this
+ structure is written to be laid out identically to a `struct
+ parisc_thread_state'. trampoline.c knows this, so it must be
+ changed if this changes. */
+
+#define sc_parisc_thread_state sc_flags /* Beginning of correspondence. */
+ /* "General" registers $1..$31. */
+ unsigned int sc_regs[31];
+
+ /* Control registers. */
+ unsigned int sc_cr11; /* sar */
+ /* These four registers make up the PC. */
+ unsigned int iioq_head;
+ unsigned int iisq_head;
+ unsigned int iioq_tail;
+ unsigned int iisq_tail;
+ unsigned int sc_cr15;
+ unsigned int sc_cr19;
+ unsigned int sc_cr20;
+ unsigned int sc_cr21;
+ unsigned int sc_cr22; /* ipsw */
+ unsigned int sc_bsd_goto; /* unused */
+ unsigned int sc_sr4;
+ unsigned int sc_sr0;
+ unsigned int sc_sr1;
+ unsigned int sc_sr2;
+ unsigned int sc_sr3;
+ unsigned int sc_sr5;
+ unsigned int sc_sr6;
+ unsigned int sc_sr7;
+ unsigned int sc_cr0;
+ unsigned int sc_cr8;
+ unsigned int sc_cr9;
+ unsigned int sc_cr10; /* unused */
+ unsigned int sc_cr12;
+ unsigned int sc_cr13;
+ unsigned int sc_cr24; /* unused */
+ unsigned int sc_cr25; /* unused */
+ unsigned int sc_cr26; /* unused */
+ unsigned sc_mpsfu_high; /* unused */
+ unsigned sc_mpsfu_low; /* unused */
+ unsigned sc_mpsfu_ovflo; /* unused */
+ int sc_pad;
+
+ /* Floating point registers $f0..$f31. */
+ double sc_fpregs[32];
+ };
diff --git a/sysdeps/mach/hurd/hppa/trampoline.c b/sysdeps/mach/hurd/hppa/trampoline.c
new file mode 100644
index 0000000000..09ab71e88d
--- /dev/null
+++ b/sysdeps/mach/hurd/hppa/trampoline.c
@@ -0,0 +1,258 @@
+/* Set thread_state for sighandler, and sigcontext to recover. HPPA version.
+Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include "thread_state.h"
+#include <assert.h>
+#include <errno.h>
+#include "hurdfault.h"
+
+
+struct mach_msg_trap_regargs
+ {
+ /* These first four arguments are in registers 26..23. */
+ mach_msg_size_t rcv_size; /* arg3 */
+ mach_msg_size_t send_size; /* arg2 */
+ mach_msg_option_t option; /* arg1 */
+ mach_msg_header_t *msg; /* arg0 */
+ };
+
+struct sigcontext *
+_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ int signo, long int sigcode,
+ volatile int rpc_wait,
+ struct machine_thread_all_state *state)
+{
+ __label__ trampoline, rpc_wait_trampoline;
+ void *volatile sigsp;
+ struct sigcontext *scp;
+
+ if (ss->context)
+ {
+ /* We have a previous sigcontext that sigreturn was about
+ to restore when another signal arrived. We will just base
+ our setup on that. */
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
+ _hurdsig_fault_sigcode < (long int) (ss->context + 1));
+ else
+ {
+ memcpy (&state->basic, &ss->context->sc_parisc_thread_state,
+ sizeof (state->basic));
+ state->set = (1 << PARISC_THREAD_STATE);
+ assert (! rpc_wait);
+ /* The intr_port slot was cleared before sigreturn sent us the
+ sig_post that made us notice this pending signal, so
+ _hurd_internal_post_signal wouldn't do interrupt_operation.
+ After we return, our caller will set SCP->sc_intr_port (in the
+ new context) from SS->intr_port and clear SS->intr_port. Now
+ that we are restoring this old context recorded by sigreturn,
+ we want to restore its intr_port too; so store it in
+ SS->intr_port now, so it will end up in SCP->sc_intr_port
+ later. */
+ ss->intr_port = ss->context->sc_intr_port;
+ }
+ /* If the sigreturn context was bogus, just ignore it. */
+ ss->context = NULL;
+ }
+ else if (! machine_get_basic_state (ss->thread, state))
+ return NULL;
+
+ if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ !(ss->sigaltstack.ss_flags & (SA_DISABLE|SA_ONSTACK)))
+ {
+ sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
+ ss->sigaltstack.ss_flags |= SA_ONSTACK;
+ /* XXX need to set up base of new stack for
+ per-thread variables, cthreads. */
+ }
+ else
+ sigsp = (char *) state->basic.uesp;
+
+ /* Push the signal context on the stack. */
+ sigsp -= sizeof (*scp);
+ scp = sigsp;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode >= (long int) scp &&
+ _hurdsig_fault_sigcode <= (long int) (scp + 1));
+ /* We got a fault trying to write the stack frame.
+ We cannot set up the signal handler.
+ Returning NULL tells our caller, who will nuke us with a SIGILL. */
+ return NULL;
+ }
+ else
+ {
+ int ok;
+
+ /* Set up the sigcontext from the current state of the thread. */
+
+ scp->sc_onstack = ss->sigaltstack.ss_flags & SA_ONSTACK ? 1 : 0;
+
+ /* struct sigcontext is laid out so that starting at sc_regs mimics a
+ struct parisc_thread_state. */
+ memcpy (&scp->sc_parisc_thread_state,
+ &state->basic, sizeof (state->basic));
+
+ _hurdsig_end_catch_fault ();
+
+ if (! ok)
+ return NULL;
+ }
+
+ /* Modify the thread state to call the trampoline code on the new stack. */
+ if (rpc_wait)
+ {
+ /* The signalee thread was blocked in a mach_msg_trap system call,
+ still waiting for a reply. We will have it run the special
+ trampoline code which retries the message receive before running
+ the signal handler.
+
+ To do this we change the OPTION argument on its stack to enable only
+ message reception, since the request message has already been
+ sent. */
+
+ struct mach_msg_trap_regargs *args = (void *) &state->basic.r23;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode >= (long int) args &&
+ _hurdsig_fault_sigcode < (long int) (args + 1));
+ /* Faulted accessing ARGS. Bomb. */
+ return NULL;
+ }
+
+ assert (args->option & MACH_RCV_MSG);
+ /* Disable the message-send, since it has already completed. The
+ calls we retry need only wait to receive the reply message. */
+ args->option &= ~MACH_SEND_MSG;
+
+ _hurdsig_end_catch_fault ();
+
+ MACHINE_THREAD_STATE_SET_PC (&state->basic, &&rpc_wait_trampoline);
+ /* The reply-receiving trampoline code runs initially on the original
+ user stack. We pass it the signal stack pointer in %r5. */
+ state->basic.r5 = (int) sigsp;
+ /* After doing the message receive, the trampoline code will need to
+ update the %r28 value to be restored by sigreturn. To simplify
+ the assembly code, we pass the address of its slot in SCP to the
+ trampoline code in %r4. */
+ state->basic.r4 = (unsigned int) &scp->sc_regs[27];
+ /* Set up the arguments for the handler function in callee-saved
+ registers that we will move to the argument registers after
+ mach_msg_trap returns. */
+ state->basic.r6 = signo;
+ state->basic.r7 = sigcode;
+ state->basic.r8 = (unsigned int) scp;
+ }
+ else
+ {
+ MACHINE_THREAD_STATE_SET_PC (&state->basic, &&trampoline);
+ state->basic.r20 = (unsigned int) sigsp;
+ /* Set up the arguments for the handler function. */
+ state->basic.r26 = signo;
+ state->basic.r25 = sigcode;
+ state->basic.r24 = (unsigned int) scp;
+ }
+
+ /* We pass the handler function to the trampoline code in %r9. */
+ state->basic.r9 = (unsigned int) handler;
+ /* For convenience, we pass the address of __sigreturn in %r10. */
+ state->basic.r10 = (unsigned int) &__sigreturn;
+ /* The extra copy of SCP for the __sigreturn arg goes in %r8. */
+ state->basic.r10 = (unsigned int) scp;
+
+ return scp;
+
+ /* The trampoline code follows. This is not actually executed as part of
+ this function, it is just convenient to write it that way. */
+
+ rpc_wait_trampoline:
+ /* This is the entry point when we have an RPC reply message to receive
+ before running the handler. The MACH_MSG_SEND bit has already been
+ cleared in the OPTION argument on our stack. The interrupted user
+ stack pointer has not been changed, so the system call can find its
+ arguments; the signal stack pointer is in %ebx. For our convenience,
+ %ecx points to the sc_eax member of the sigcontext. */
+ asm volatile
+ (/* Retry the interrupted mach_msg system call. */
+ "ldil L%0xC0000000,%r1\nble 4(%sr7,%r1)\n"
+ "ldi -25, %r22\n" /* mach_msg_trap */
+ /* When the sigcontext was saved, %r28 was MACH_RCV_INTERRUPTED. But
+ now the message receive has completed and the original caller of
+ the RPC (i.e. the code running when the signal arrived) needs to
+ see the final return value of the message receive in %r28. So
+ store the new %r28 value into the sc_regs[27] member of the sigcontext
+ (whose address is in %r4 to make this code simpler). */
+ "stw (%r4), %r28\n"
+ /* Switch to the signal stack. */
+ "copy %r5, %r30\n"
+ /* Copy the handler arguments to the argument registers. */
+ "copy %r6, %r26\n"
+ "copy %r7, %r25\n"
+ "copy %r8, %r24\n"
+ );
+
+ trampoline:
+ /* Entry point for running the handler normally. The arguments to the
+ handler function are already in the argument registers. */
+ asm volatile
+ ("bv (%r9); nop" /* Call the handler function. */
+ "bv (%r10)\n" /* Call __sigreturn (SCP); never returns. */
+ "copy %r8, %r26" /* Set up arg in delay slot. */
+ : : "i" (&__sigreturn));
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+/* STATE describes a thread that had intr_port set (meaning it was inside
+ HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have
+ just completed a mach_msg_trap system call that returned
+ MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right
+ being waited on. */
+int
+_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
+ mach_port_t *port)
+{
+ const unsigned int *volatile pc
+ = MACHINE_THREAD_STATE_PC (&state->basic);
+ const mach_port_t *rcv_name
+ = (void *) state->r30 -32-20; /* VA_ARG4 from <mach/machine/asm.h>. */
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode == (long int) pc ||
+ _hurdsig_fault_sigcode == (long int) rcv_name);
+ else
+ {
+ int rcving = (state->basic.r28 == MACH_RCV_INTERRUPTED &&
+ pc == ???unfinished???);
+ if (rcving)
+ /* We did just return from a mach_msg_trap system call
+ doing a message receive that was interrupted.
+ Examine the parameters to find the receive right. */
+ *port = *rcv_name;
+ _hurdsig_end_catch_fault ();
+ if (rcving)
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/i386/exc2signal.c b/sysdeps/mach/hurd/i386/exc2signal.c
new file mode 100644
index 0000000000..19f845a49e
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/exc2signal.c
@@ -0,0 +1,165 @@
+/* Translate Mach exception codes into signal numbers. i386 version.
+Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <mach/exception.h>
+
+/* Translate the Mach exception codes, as received in an `exception_raise' RPC,
+ into a signal number and signal subcode. */
+
+void
+_hurd_exception2signal (int exception, int code, int subcode,
+ int *signo, long int *sigcode, int *error)
+{
+ *error = 0;
+
+ switch (exception)
+ {
+ default:
+ *signo = SIGIOT;
+ *sigcode = exception;
+ break;
+
+ case EXC_BAD_ACCESS:
+ if (code == KERN_PROTECTION_FAILURE)
+ *signo = SIGSEGV;
+ else
+ *signo = SIGBUS;
+ *sigcode = subcode;
+ *error = code;
+ break;
+
+ case EXC_BAD_INSTRUCTION:
+ *signo = SIGILL;
+ if (code == EXC_I386_INVOP)
+ *sigcode = ILL_INVOPR_FAULT;
+ else if (code == EXC_I386_STKFLT)
+ *sigcode = ILL_STACK_FAULT;
+ else
+ *sigcode = 0;
+ break;
+
+ case EXC_ARITHMETIC:
+ switch (code)
+ {
+ case EXC_I386_DIV: /* integer divide by zero */
+ *signo = SIGFPE;
+ *sigcode = FPE_INTDIV_FAULT;
+ break;
+
+ case EXC_I386_INTO: /* integer overflow */
+ *signo = SIGFPE;
+ *sigcode = FPE_INTOVF_TRAP;
+ break;
+
+ /* These aren't anywhere documented or used in Mach 3.0. */
+ case EXC_I386_NOEXT:
+ case EXC_I386_EXTOVR:
+ default:
+ *signo = SIGFPE;
+ *sigcode = 0;
+ break;
+
+ case EXC_I386_EXTERR:
+ /* Subcode is the fp_status word saved by the hardware.
+ Give an error code corresponding to the first bit set. */
+ if (subcode & FPS_IE)
+ {
+ *signo = SIGILL;
+ *sigcode = ILL_FPEOPR_FAULT;
+ }
+ else if (subcode & FPS_DE)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_FLTDNR_FAULT;
+ }
+ else if (subcode & FPS_ZE)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_FLTDIV_FAULT;
+ }
+ else if (subcode & FPS_OE)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_FLTOVF_FAULT;
+ }
+ else if (subcode & FPS_UE)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_FLTUND_FAULT;
+ }
+ else if (subcode & FPS_PE)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_FLTINX_FAULT;
+ }
+ else
+ {
+ *signo = SIGFPE;
+ *sigcode = 0;
+ }
+ break;
+
+ /* These two can only be arithmetic exceptions if we
+ are in V86 mode, which sounds like emulation to me.
+ (See Mach 3.0 i386/trap.c.) */
+ case EXC_I386_EMERR:
+ *signo = SIGFPE;
+ *sigcode = FPE_EMERR_FAULT;
+ break;
+ case EXC_I386_BOUND:
+ *signo = SIGFPE;
+ *sigcode = FPE_EMBND_FAULT;
+ break;
+ }
+ break;
+
+ case EXC_EMULATION:
+ /* 3.0 doesn't give this one, why, I don't know. */
+ *signo = SIGEMT;
+ *sigcode = 0;
+ break;
+
+ case EXC_SOFTWARE:
+ /* The only time we get this in Mach 3.0
+ is for an out of bounds trap. */
+ if (code == EXC_I386_BOUND)
+ {
+ *signo = SIGFPE;
+ *sigcode = FPE_SUBRNG_FAULT;
+ }
+ else
+ {
+ *signo = SIGEMT;
+ *sigcode = 0;
+ }
+ break;
+
+ case EXC_BREAKPOINT:
+ *signo = SIGTRAP;
+ if (code == EXC_I386_SGL)
+ *sigcode = DBG_SINGLE_TRAP;
+ else if (code == EXC_I386_BPT)
+ *sigcode = DBG_BRKPNT_FAULT;
+ else
+ *sigcode = 0;
+ break;
+ }
+}
diff --git a/sysdeps/mach/hurd/i386/init-fault.c b/sysdeps/mach/hurd/i386/init-fault.c
new file mode 100644
index 0000000000..ff22814308
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/init-fault.c
@@ -0,0 +1,41 @@
+/* Set up a thread_state for proc_handle_exceptions. i386 version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include <mach/thread_status.h>
+#include <string.h>
+#include <setjmp.h>
+
+extern jmp_buf _hurd_sigthread_fault_env;
+
+static char fault_stack[32];
+static volatile void
+faulted (void)
+{
+ __longjmp (_hurd_sigthread_fault_env, 1);
+}
+
+void
+_hurd_initialize_fault_recovery_state (void *state)
+{
+ struct i386_thread_state *ts = state;
+ memset (ts, 0, sizeof (*ts));
+ ts->uesp = (int) &fault_stack[sizeof (fault_stack)];
+ ts->eip = (int) &faulted;
+}
diff --git a/sysdeps/mach/hurd/i386/longjmp-ctx.c b/sysdeps/mach/hurd/i386/longjmp-ctx.c
new file mode 100644
index 0000000000..acfbee602e
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/longjmp-ctx.c
@@ -0,0 +1,35 @@
+/* Perform a `longjmp' on a `struct sigcontext'. i386 version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <setjmp.h>
+#include <hurd/signal.h>
+#include <string.h>
+
+void
+_hurd_longjmp_sigcontext (struct sigcontext *scp, jmp_buf env, int retval)
+{
+ memset (scp, 0, sizeof (*scp));
+ scp->sc_ebx = env[0].__bx;
+ scp->sc_esi = env[0].__si;
+ scp->sc_edi = env[0].__di;
+ scp->sc_ebp = (int) env[0].__bp;
+ scp->sc_uesp = (int) env[0].__sp;
+ scp->sc_eip = (int) env[0].__pc;
+ scp->sc_eax = retval == 0 ? 1 : retval;
+}
diff --git a/sysdeps/mach/hurd/i386/longjmp-ts.c b/sysdeps/mach/hurd/i386/longjmp-ts.c
new file mode 100644
index 0000000000..7da9be2a26
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/longjmp-ts.c
@@ -0,0 +1,39 @@
+/* Perform a `longjmp' on a Mach thread_state. i386 version.
+Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include <setjmp.h>
+#include <mach/thread_status.h>
+
+
+/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */
+
+void
+_hurd_longjmp_thread_state (void *state, jmp_buf env, int val)
+{
+ struct i386_thread_state *ts = state;
+
+ ts->ebx = env[0].__jmpbuf[0].__bx;
+ ts->esi = env[0].__jmpbuf[0].__si;
+ ts->edi = env[0].__jmpbuf[0].__di;
+ ts->ebp = (int) env[0].__jmpbuf[0].__bp;
+ ts->uesp = (int) env[0].__jmpbuf[0].__sp;
+ ts->eip = (int) env[0].__jmpbuf[0].__pc;
+ ts->eax = val ?: 1;
+}
diff --git a/sysdeps/mach/hurd/i386/sigcontext.h b/sysdeps/mach/hurd/i386/sigcontext.h
new file mode 100644
index 0000000000..b742326bdb
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/sigcontext.h
@@ -0,0 +1,106 @@
+/* Machine-dependent signal context structure for GNU Hurd. i386 version.
+Copyright (C) 1991, 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Signal handlers are actually called:
+ void handler (int sig, int code, struct sigcontext *scp); */
+
+#include <mach/machine/fp_reg.h>
+
+/* State of this thread when the signal was taken. */
+struct sigcontext
+ {
+ /* These first members are machine-independent. */
+
+ int sc_onstack; /* Nonzero if running on sigstack. */
+ __sigset_t sc_mask; /* Blocked signals to restore. */
+
+ /* MiG reply port this thread is using. */
+ unsigned int sc_reply_port;
+
+ /* Port this thread is doing an interruptible RPC on. */
+ unsigned int sc_intr_port;
+
+ /* Error code associated with this signal (interpreted as `error_t'). */
+ int sc_error;
+
+ /* All following members are machine-dependent. The rest of this
+ structure is written to be laid out identically to:
+ {
+ struct i386_thread_state basic;
+ struct i386_float_state fpu;
+ }
+ trampoline.c knows this, so it must be changed if this changes. */
+
+#define sc_i386_thread_state sc_gs /* Beginning of correspondence. */
+ /* Segment registers. */
+ int sc_gs;
+ int sc_fs;
+ int sc_es;
+ int sc_ds;
+
+ /* "General" registers. These members are in the order that the i386
+ `pusha' and `popa' instructions use (`popa' ignores %esp). */
+ int sc_edi;
+ int sc_esi;
+ int sc_ebp;
+ int sc_esp; /* Not used; sc_uesp is used instead. */
+ int sc_ebx;
+ int sc_edx;
+ int sc_ecx;
+ int sc_eax;
+
+ int sc_eip; /* Instruction pointer. */
+ int sc_cs; /* Code segment register. */
+
+ int sc_efl; /* Processor flags. */
+
+ int sc_uesp; /* This stack pointer is used. */
+ int sc_ss; /* Stack segment register. */
+
+ /* Following mimics struct i386_float_state. Structures and symbolic
+ values can be found in <mach/i386/fp_reg.h>. */
+#define sc_i386_float_state sc_fpkind
+ int sc_fpkind; /* FP_NO, FP_387, etc. */
+ int sc_fpused; /* If zero, ignore rest of float state. */
+ struct i386_fp_save sc_fpsave;
+ struct i386_fp_regs sc_fpregs;
+ int sc_fpexcsr; /* FPSR including exception bits. */
+ };
+
+
+/* Codes for SIGFPE. */
+#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
+#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */
+#define FPE_FLTOVF_FAULT 0x3 /* floating overflow */
+#define FPE_FLTDIV_FAULT 0x4 /* floating divide by zero */
+#define FPE_FLTUND_FAULT 0x5 /* floating underflow */
+#define FPE_SUBRNG_FAULT 0x7 /* BOUNDS instruction failed */
+#define FPE_FLTDNR_FAULT 0x8 /* denormalized operand */
+#define FPE_FLTINX_FAULT 0x9 /* floating loss of precision */
+#define FPE_EMERR_FAULT 0xa /* mysterious emulation error 33 */
+#define FPE_EMBND_FAULT 0xb /* emulation BOUNDS instruction failed */
+
+/* Codes for SIGILL. */
+#define ILL_INVOPR_FAULT 0x1 /* invalid operation */
+#define ILL_STACK_FAULT 0x2 /* fault on microkernel stack access */
+#define ILL_FPEOPR_FAULT 0x3 /* invalid floating operation */
+
+/* Codes for SIGTRAP. */
+#define DBG_SINGLE_TRAP 0x1 /* single step */
+#define DBG_BRKPNT_FAULT 0x2 /* breakpoint instruction */
diff --git a/sysdeps/mach/hurd/i386/sigreturn.c b/sysdeps/mach/hurd/i386/sigreturn.c
new file mode 100644
index 0000000000..df8960669f
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/sigreturn.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+register int *sp asm ("%esp");
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/threadvar.h>
+#include <hurd/msg.h>
+#include <stdlib.h>
+
+int
+__sigreturn (struct sigcontext *scp)
+{
+ struct hurd_sigstate *ss;
+ mach_port_t *reply_port;
+
+ if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss = _hurd_self_sigstate ();
+ __spin_lock (&ss->lock);
+
+ /* Restore the set of blocked signals, and the intr_port slot. */
+ ss->blocked = scp->sc_mask;
+ ss->intr_port = scp->sc_intr_port;
+
+ /* Check for pending signals that were blocked by the old set. */
+ if (ss->pending & ~ss->blocked)
+ {
+ /* There are pending signals that just became unblocked. Wake up the
+ signal thread to deliver them. But first, squirrel away SCP where
+ the signal thread will notice it if it runs another handler, and
+ arrange to have us called over again in the new reality. */
+ ss->context = scp;
+ /* Clear the intr_port slot, since we are not in fact doing
+ an interruptible RPC right now. If SS->intr_port is not null,
+ the SCP context is doing an interruptible RPC, but the signal
+ thread will examine us while we are blocked in the sig_post RPC. */
+ ss->intr_port = MACH_PORT_NULL;
+ __spin_unlock (&ss->lock);
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+ /* If a pending signal was handled, sig_post never returned. */
+ __spin_lock (&ss->lock);
+ }
+
+ if (scp->sc_onstack)
+ {
+ ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
+ /* XXX cannot unlock until off sigstack */
+ abort ();
+ }
+ else
+ __spin_unlock (&ss->lock);
+
+ /* Destroy the MiG reply port used by the signal handler, and restore the
+ reply port in use by the thread when interrupted. */
+ reply_port =
+ (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ if (*reply_port)
+ __mach_port_destroy (__mach_task_self (), *reply_port);
+ *reply_port = scp->sc_reply_port;
+
+ if (scp->sc_fpused)
+ {
+ /* XXX should restore FPU state here XXX roland needs 387 manual */
+ /* abort (); */
+ }
+
+ {
+ /* There are convenient instructions to pop state off the stack, so we
+ copy the registers onto the user's stack, switch there, pop and
+ return. */
+
+ int *usp = (int *) scp->sc_uesp;
+
+ *--usp = scp->sc_eip;
+ *--usp = scp->sc_efl;
+ memcpy (usp -= 12, &scp->sc_i386_thread_state, 12 * sizeof (int));
+
+ sp = usp;
+
+#define A(line) asm volatile (#line)
+ /* The members in the sigcontext are arranged in this order
+ so we can pop them easily. */
+
+ /* Pop the segment registers (except %cs and %ss, done last). */
+ A (popl %gs);
+ A (popl %fs);
+ A (popl %es);
+ A (popl %ds);
+ /* Pop the general registers. */
+ A (popa);
+ /* Pop the processor flags. */
+ A (popf);
+ /* Return to the saved PC. */
+ A (ret);
+
+ /* Firewall. */
+ A (hlt);
+#undef A
+ }
+
+ /* NOTREACHED */
+ return -1;
+}
+
+weak_alias (__sigreturn, sigreturn)
diff --git a/sysdeps/mach/hurd/i386/trampoline.c b/sysdeps/mach/hurd/i386/trampoline.c
new file mode 100644
index 0000000000..eabf940b44
--- /dev/null
+++ b/sysdeps/mach/hurd/i386/trampoline.c
@@ -0,0 +1,271 @@
+/* Set thread_state for sighandler, and sigcontext to recover. i386 version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include "thread_state.h"
+#include <assert.h>
+#include <errno.h>
+#include "hurdfault.h"
+
+
+struct mach_msg_trap_args
+ {
+ void *retaddr; /* Address mach_msg_trap will return to. */
+ /* This is the order of arguments to mach_msg_trap. */
+ mach_msg_header_t *msg;
+ mach_msg_option_t option;
+ mach_msg_size_t send_size;
+ mach_msg_size_t rcv_size;
+ mach_port_t rcv_name;
+ mach_msg_timeout_t timeout;
+ mach_port_t notify;
+ };
+
+struct sigcontext *
+_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ int signo, long int sigcode,
+ volatile int rpc_wait,
+ struct machine_thread_all_state *state)
+{
+ __label__ trampoline, rpc_wait_trampoline;
+ void *volatile sigsp;
+ struct sigcontext *scp;
+ struct
+ {
+ int signo;
+ long int sigcode;
+ struct sigcontext *scp; /* Points to ctx, below. */
+ struct sigcontext *return_scp; /* Same; arg to sigreturn. */
+ struct sigcontext ctx;
+ } *stackframe;
+
+ if (ss->context)
+ {
+ /* We have a previous sigcontext that sigreturn was about
+ to restore when another signal arrived. We will just base
+ our setup on that. */
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode >= (long int) ss->context &&
+ _hurdsig_fault_sigcode < (long int) (ss->context + 1));
+ else
+ {
+ memcpy (&state->basic, &ss->context->sc_i386_thread_state,
+ sizeof (state->basic));
+ memcpy (&state->fpu, &ss->context->sc_i386_float_state,
+ sizeof (state->fpu));
+ state->set = (1 << i386_THREAD_STATE) | (1 << i386_FLOAT_STATE);
+ assert (! rpc_wait);
+ /* The intr_port slot was cleared before sigreturn sent us the
+ sig_post that made us notice this pending signal, so
+ _hurd_internal_post_signal wouldn't do interrupt_operation.
+ After we return, our caller will set SCP->sc_intr_port (in the
+ new context) from SS->intr_port and clear SS->intr_port. Now
+ that we are restoring this old context recorded by sigreturn,
+ we want to restore its intr_port too; so store it in
+ SS->intr_port now, so it will end up in SCP->sc_intr_port
+ later. */
+ ss->intr_port = ss->context->sc_intr_port;
+ }
+ /* If the sigreturn context was bogus, just ignore it. */
+ ss->context = NULL;
+ }
+ else if (! machine_get_basic_state (ss->thread, state))
+ return NULL;
+
+ if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ !(ss->sigaltstack.ss_flags & (SA_DISABLE|SA_ONSTACK)))
+ {
+ sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
+ ss->sigaltstack.ss_flags |= SA_ONSTACK;
+ /* XXX need to set up base of new stack for
+ per-thread variables, cthreads. */
+ }
+ else
+ sigsp = (char *) state->basic.uesp;
+
+ /* Push the arguments to call `trampoline' on the stack. */
+ sigsp -= sizeof (*stackframe);
+ stackframe = sigsp;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode >= (long int) stackframe &&
+ _hurdsig_fault_sigcode <= (long int) (stackframe + 1));
+ /* We got a fault trying to write the stack frame.
+ We cannot set up the signal handler.
+ Returning NULL tells our caller, who will nuke us with a SIGILL. */
+ return NULL;
+ }
+ else
+ {
+ int ok;
+
+ /* Set up the arguments for the signal handler. */
+ stackframe->signo = signo;
+ stackframe->sigcode = sigcode;
+ stackframe->scp = stackframe->return_scp = scp = &stackframe->ctx;
+
+ /* Set up the sigcontext from the current state of the thread. */
+
+ scp->sc_onstack = ss->sigaltstack.ss_flags & SA_ONSTACK ? 1 : 0;
+
+ /* struct sigcontext is laid out so that starting at sc_gs mimics a
+ struct i386_thread_state. */
+ memcpy (&scp->sc_i386_thread_state,
+ &state->basic, sizeof (state->basic));
+
+ /* struct sigcontext is laid out so that starting at sc_fpkind mimics
+ a struct i386_float_state. */
+ ok = machine_get_state (ss->thread, state, i386_FLOAT_STATE,
+ &state->fpu, &scp->sc_i386_float_state,
+ sizeof (state->fpu));
+
+ _hurdsig_end_catch_fault ();
+
+ if (! ok)
+ return NULL;
+ }
+
+ /* Modify the thread state to call the trampoline code on the new stack. */
+ if (rpc_wait)
+ {
+ /* The signalee thread was blocked in a mach_msg_trap system call,
+ still waiting for a reply. We will have it run the special
+ trampoline code which retries the message receive before running
+ the signal handler.
+
+ To do this we change the OPTION argument on its stack to enable only
+ message reception, since the request message has already been
+ sent. */
+
+ struct mach_msg_trap_args *args = (void *) state->basic.uesp;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ {
+ assert (_hurdsig_fault_sigcode >= (long int) args &&
+ _hurdsig_fault_sigcode < (long int) (args + 1));
+ /* Faulted accessing ARGS. Bomb. */
+ return NULL;
+ }
+
+ assert (args->option & MACH_RCV_MSG);
+ /* Disable the message-send, since it has already completed. The
+ calls we retry need only wait to receive the reply message. */
+ args->option &= ~MACH_SEND_MSG;
+
+ _hurdsig_end_catch_fault ();
+
+ state->basic.eip = (int) &&rpc_wait_trampoline;
+ /* The reply-receiving trampoline code runs initially on the original
+ user stack. We pass it the signal stack pointer in %ebx. */
+ state->basic.ebx = (int) sigsp;
+ /* After doing the message receive, the trampoline code will need to
+ update the %eax value to be restored by sigreturn. To simplify
+ the assembly code, we pass the address of its slot in SCP to the
+ trampoline code in %ecx. */
+ state->basic.ecx = (int) &scp->sc_eax;
+ }
+ else
+ {
+ state->basic.eip = (int) &&trampoline;
+ state->basic.uesp = (int) sigsp;
+ }
+ /* We pass the handler function to the trampoline code in %edx. */
+ state->basic.edx = (int) handler;
+
+ return scp;
+
+ /* The trampoline code follows. This is not actually executed as part of
+ this function, it is just convenient to write it that way. */
+
+ rpc_wait_trampoline:
+ /* This is the entry point when we have an RPC reply message to receive
+ before running the handler. The MACH_MSG_SEND bit has already been
+ cleared in the OPTION argument on our stack. The interrupted user
+ stack pointer has not been changed, so the system call can find its
+ arguments; the signal stack pointer is in %ebx. For our convenience,
+ %ecx points to the sc_eax member of the sigcontext. */
+ asm volatile
+ (/* Retry the interrupted mach_msg system call. */
+ "movl $-25, %eax\n" /* mach_msg_trap */
+ "lcall $7, $0\n"
+ /* When the sigcontext was saved, %eax was MACH_RCV_INTERRUPTED. But
+ now the message receive has completed and the original caller of
+ the RPC (i.e. the code running when the signal arrived) needs to
+ see the final return value of the message receive in %eax. So
+ store the new %eax value into the sc_eax member of the sigcontext
+ (whose address is in %ecx to make this code simpler). */
+ "movl %eax, (%ecx)\n"
+ /* Switch to the signal stack. */
+ "movl %ebx, %esp\n");
+
+ trampoline:
+ /* Entry point for running the handler normally. The arguments to the
+ handler function are already on the top of the stack:
+
+ 0(%esp) SIGNO
+ 4(%esp) SIGCODE
+ 8(%esp) SCP
+ */
+ asm volatile
+ ("call %*%%edx\n" /* Call the handler function. */
+ "addl $12, %%esp\n" /* Pop its args. */
+ "call %P0\n" /* Call __sigreturn (SCP); never returns. */
+ "hlt" /* Just in case. */
+ : : "i" (&__sigreturn));
+
+ /* NOTREACHED */
+ return NULL;
+}
+
+/* STATE describes a thread that had intr_port set (meaning it was inside
+ HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have
+ just completed a mach_msg_trap system call that returned
+ MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right
+ being waited on. */
+int
+_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
+ mach_port_t *port)
+{
+ static const unsigned char syscall[] = { 0x9a, 0, 0, 0, 0, 7, 0 };
+ const unsigned char *volatile pc
+ = (void *) state->basic.eip - sizeof syscall;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode >= (long int) pc &&
+ _hurdsig_fault_sigcode < (long int) pc + sizeof syscall);
+ else
+ {
+ int rcving = (state->basic.eax == MACH_RCV_INTERRUPTED &&
+ !memcmp (pc, &syscall, sizeof syscall));
+ _hurdsig_end_catch_fault ();
+ if (rcving)
+ {
+ /* We did just return from a mach_msg_trap system call
+ doing a message receive that was interrupted.
+ Examine the parameters to find the receive right. */
+ struct mach_msg_trap_args *args = (void *) state->basic.uesp;
+
+ *port = args->rcv_name;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/ioctl.c b/sysdeps/mach/hurd/ioctl.c
new file mode 100644
index 0000000000..4aad0bb377
--- /dev/null
+++ b/sysdeps/mach/hurd/ioctl.c
@@ -0,0 +1,242 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/signal.h>
+#include <stdarg.h>
+#include <mach/notify.h>
+#include <assert.h>
+#include <string.h>
+#include <hurd/ioctl.h>
+
+
+#define typesize(type) (1 << (type))
+
+
+/* Perform the I/O control operation specified by REQUEST on FD.
+ The actual type and use of ARG and the return value depend on REQUEST. */
+int
+DEFUN(__ioctl, (fd, request),
+ int fd AND unsigned long int request DOTS)
+{
+ /* Map individual type fields to Mach IPC types. */
+ static const int mach_types[] =
+ { MACH_MSG_TYPE_CHAR, MACH_MSG_TYPE_INTEGER_16, MACH_MSG_TYPE_INTEGER_32,
+ -1 };
+#define io2mach_type(count, type) \
+ ((mach_msg_type_t) { mach_types[type], typesize (type) * 8, count, 1, 0, 0 })
+
+ /* Extract the type information encoded in the request. */
+ unsigned int type = _IOC_TYPE (request);
+
+ /* Message buffer. */
+ struct
+ {
+ mig_reply_header_t header;
+ char data[3 * sizeof (mach_msg_type_t) +
+ _IOT_COUNT0 (type) * typesize (_IOT_TYPE0 (type)) +
+ _IOT_COUNT1 (type) * typesize (_IOT_TYPE1 (type)) +
+ _IOT_COUNT2 (type) * typesize (_IOT_TYPE2 (type))];
+ } msg;
+ mach_msg_header_t *const m = &msg.header.Head;
+ mach_msg_type_t *t = &msg.header.RetCodeType;
+ mach_msg_id_t msgid;
+ unsigned int reply_size;
+
+ void *arg;
+
+ error_t err;
+
+ /* Send the RPC already packed up in MSG to IOPORT
+ and decode the return value. */
+ error_t send_rpc (io_t ioport)
+ {
+ error_t err;
+
+ m->msgh_size = (char *) t - (char *) &msg;
+ m->msgh_remote_port = ioport;
+ m->msgh_local_port = __mig_get_reply_port ();
+ m->msgh_seqno = 0;
+ m->msgh_id = msgid;
+ m->msgh_bits = MACH_MSGH_BITS (MACH_MSG_TYPE_COPY_SEND,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE);
+ err = HURD_EINTR_RPC (ioport, __mach_msg (m, MACH_SEND_MSG|MACH_RCV_MSG,
+ m->msgh_size, sizeof (msg),
+ m->msgh_local_port,
+ MACH_MSG_TIMEOUT_NONE,
+ MACH_PORT_NULL));
+ switch (err)
+ {
+ case MACH_MSG_SUCCESS:
+ break;
+ case MACH_SEND_INVALID_REPLY:
+ case MACH_RCV_INVALID_NAME:
+ __mig_dealloc_reply_port (m->msgh_local_port);
+ default:
+ return err;
+ }
+
+ if ((m->msgh_bits & MACH_MSGH_BITS_COMPLEX))
+ {
+ /* Allow no ports or VM. */
+ __mach_msg_destroy (m);
+ /* Want to return a different error below for a different msgid. */
+ if (m->msgh_id == msgid + 100)
+ return MIG_TYPE_ERROR;
+ }
+
+ if (m->msgh_id != msgid + 100)
+ return (m->msgh_id == MACH_NOTIFY_SEND_ONCE ?
+ MIG_SERVER_DIED : MIG_REPLY_MISMATCH);
+
+ if (m->msgh_size != reply_size &&
+ m->msgh_size != sizeof (mig_reply_header_t))
+ return MIG_TYPE_ERROR;
+
+ if (*(int *) &msg.header.RetCodeType !=
+ ((union { mach_msg_type_t t; int i; })
+ { t: io2mach_type (1, _IOTS (sizeof msg.header.RetCode)) }).i)
+ return MIG_TYPE_ERROR;
+ return msg.header.RetCode;
+ }
+
+ va_list ap;
+
+ va_start (ap, request);
+ arg = va_arg (ap, void *);
+ va_end (ap);
+
+ {
+ /* Check for a registered handler for REQUEST. */
+ ioctl_handler_t handler = _hurd_lookup_ioctl_handler (request);
+ if (handler)
+ /* This handler groks REQUEST. Se lo puntamonos. */
+ return (*handler) (fd, request, arg);
+ }
+
+ /* Compute the Mach message ID for the RPC from the group and command
+ parts of the ioctl request. */
+ msgid = 100000 + ((_IOC_GROUP (request) - 'f') * 4000); /* Base subsystem */
+ /* Because of MiG's poorly chosen algorithm of adding 100 to a request
+ msgid to produce the reply msgid, we cannot just add the command part
+ of the ioctl request to the subsystem base msgid. For ioctl requests
+ past 99, we must skip blocks of 100 msgids to allow for the reply
+ msgids corresponding to the earlier requests. */
+ if (_IOC_COMMAND (request) >= 100)
+ msgid += 100;
+ if (_IOC_COMMAND (request) >= 200)
+ msgid += 100;
+ msgid += _IOC_COMMAND (request);
+
+ if (_IOC_INOUT (request) & IOC_IN)
+ {
+ /* Pack an argument into the message buffer. */
+ void in (unsigned int count, enum __ioctl_datum type)
+ {
+ if (count > 0)
+ {
+ void *p = &t[1];
+ const size_t len = count * typesize ((unsigned int) type);
+ *t = io2mach_type (count, type);
+ memcpy (p, arg, len);
+ arg += len;
+ p += len;
+ p = (void *) (((unsigned long int) p + sizeof (*t) - 1)
+ & ~(sizeof (*t) - 1));
+ t = p;
+ }
+ }
+
+ /* Pack the argument data. */
+ in (_IOT_COUNT0 (type), _IOT_TYPE0 (type));
+ in (_IOT_COUNT1 (type), _IOT_TYPE1 (type));
+ in (_IOT_COUNT2 (type), _IOT_TYPE2 (type));
+ }
+
+ /* Compute the expected size of the reply. There is a standard header
+ consisting of the message header and the reply code. Then, for out
+ and in/out ioctls, there come the data with their type headers. */
+ reply_size = sizeof (mig_reply_header_t);
+
+ if (_IOC_INOUT (request) & IOC_OUT)
+ {
+ inline void figure_reply (unsigned int count, enum __ioctl_datum type)
+ {
+ if (count > 0)
+ {
+ /* Add the size of the type and data. */
+ reply_size += sizeof (mach_msg_type_t) + typesize (type) * count;
+ /* Align it to word size. */
+ reply_size += sizeof (mach_msg_type_t) - 1;
+ reply_size &= ~(sizeof (mach_msg_type_t) - 1);
+ }
+ }
+ figure_reply (_IOT_COUNT0 (type), _IOT_TYPE0 (type));
+ figure_reply (_IOT_COUNT1 (type), _IOT_TYPE1 (type));
+ figure_reply (_IOT_COUNT2 (type), _IOT_TYPE2 (type));
+ }
+
+ err = HURD_DPORT_USE (fd, _hurd_ctty_output (port, ctty, send_rpc));
+
+ t = (mach_msg_type_t *) msg.data;
+ switch (err)
+ {
+ /* Unpack the message buffer into the argument location. */
+ int out (unsigned int count, unsigned int type,
+ void *store, void **update)
+ {
+ if (count > 0)
+ {
+ const size_t len = count * typesize (type);
+ union { mach_msg_type_t t; int i; } ipctype;
+ ipctype.t = io2mach_type (count, type);
+ if (*(int *) t != ipctype.i)
+ return 1;
+ ++t;
+ memcpy (store, t, len);
+ if (update != NULL)
+ *update += len;
+ t = (void *) (((unsigned long int) t + len + sizeof (*t) - 1)
+ & ~(sizeof (*t) - 1));
+ }
+ return 0;
+ }
+
+ case 0:
+ if (m->msgh_size != reply_size ||
+ ((_IOC_INOUT (request) & IOC_OUT) &&
+ (out (_IOT_COUNT0 (type), _IOT_TYPE0 (type), arg, &arg) ||
+ out (_IOT_COUNT1 (type), _IOT_TYPE1 (type), arg, &arg) ||
+ out (_IOT_COUNT2 (type), _IOT_TYPE2 (type), arg, &arg))))
+ return __hurd_fail (MIG_TYPE_ERROR);
+ return 0;
+
+ case MIG_BAD_ID:
+ case EOPNOTSUPP:
+ /* The server didn't understand the RPC. */
+ err = ENOTTY;
+ default:
+ return __hurd_fail (err);
+ }
+}
+
+weak_alias (__ioctl, ioctl)
diff --git a/sysdeps/mach/hurd/ioctls.h b/sysdeps/mach/hurd/ioctls.h
new file mode 100644
index 0000000000..af44873cb7
--- /dev/null
+++ b/sysdeps/mach/hurd/ioctls.h
@@ -0,0 +1,323 @@
+/* Copyright (C) 1992, 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _IOCTLS_H
+
+#define _IOCTLS_H 1
+
+/* Hurd ioctl request are made up of several fields:
+ bits 31-30: inout direction (enum __ioctl_dir)
+ bits 29-12: type encoding as follows; zero count indicates omitted datum
+ 29-28: datum #0 type (enum __ioctl_datum)
+ 27-26: datum #1 type (enum __ioctl_datum)
+ 25-24: datum #2 type (enum __ioctl_datum)
+ 23-19: datum #0 count [0..31]
+ 18-14: datum #1 count [0..31]
+ 13-12: datum #2 count [0..3]
+ bits 11- 8: group (letter - 'f': ['f'..'v'])
+ bits 7- 0: command [0..127]
+
+ The following macros construct and dissect these fields. */
+
+enum __ioctl_dir
+ {
+ IOC_VOID = 0, /* No parameters. */
+ IOC_OUT = 1, /* Data is written into the user's buffer. */
+ IOC_IN = 2, /* Data is read from the user's buffer. */
+ IOC_INOUT = (IOC_IN|IOC_OUT)
+ };
+
+enum __ioctl_datum { IOC_8, IOC_16, IOC_32 };
+
+/* Construct an ioctl from constructed type plus other fields. */
+#define _IOC(inout, group, num, type) \
+ ((num) | ((((group) - 'f') | ((type) | (inout) << 19) << 4) << 7))
+
+/* Dissect an ioctl into its component fields. */
+#define _IOC_INOUT(request) (((unsigned int) (request) >> 30) & IOC_INOUT)
+#define _IOC_GROUP(request) ('f' + (((unsigned int) (request) >> 7) & 15))
+#define _IOC_COMMAND(request) ((unsigned int) (request) & 0x7f)
+#define _IOC_TYPE(request) (((unsigned int) (request) >> 11) & 0x7ffff)
+
+/* Construct a type information field from
+ the broken-out type and count fields. */
+#define _IOT(t0, c0, t1, c1, t2, c2) \
+ ((c2) | (((c1) | ((c0) | ((t2) | ((t1) | (t0) << 2) << 2) << 5) << 5) << 3))
+
+/* Dissect a type information field into the type and count fields. */
+#define _IOT_TYPE0(type) (((unsigned int) (type) >> 17) & 3)
+#define _IOT_TYPE1(type) (((unsigned int) (type) >> 15) & 3)
+#define _IOT_TYPE2(type) (((unsigned int) (type) >> 13) & 3)
+#define _IOT_COUNT0(type) (((unsigned int) (type) >> 8) & 0x1f)
+#define _IOT_COUNT1(type) (((unsigned int) (type) >> 3) & 0x1f)
+#define _IOT_COUNT2(type) (((unsigned int) (type) >> 0) & 3)
+
+/* Construct an ioctl from all the broken-out fields. */
+#define _IOCT(inout, group, num, t0, c0, t1, c1, t2, c2) \
+ _IOC ((inout), (group), (num), _IOT ((t0), (c0), (t1), (c1), (t2), (c2)))
+
+/* Standard flavors of ioctls.
+ _IOT_foobar is defined either in this file,
+ or where struct foobar is defined. */
+#define _IO(g, n) _IOC (IOC_VOID, (g), (n), 0)
+#define _IOR(g, n, t) _IOC (IOC_OUT, (g), (n), _IOT_##t)
+#define _IOW(g, n, t) _IOC (IOC_IN, (g), (n), _IOT_##t)
+#define _IOWR(g, n, t) _IOC (IOC_INOUT, (g), (n), _IOT_##t)
+
+/* Construct an individual type field for TYPE. */
+#define _IOTS(type) (sizeof (type) >> 1)
+
+/* Construct a type information field for
+ a single argument of the scalar TYPE. */
+#define _IOT_SIMPLE(type) _IOT (_IOTS (type), 1, 0, 0, 0, 0)
+
+/* Basic C types. */
+#define _IOT_int _IOT_SIMPLE (int)
+#define _IOT_char _IOT_SIMPLE (char)
+#define _IOT_short _IOT_SIMPLE (short)
+
+
+/* ioctls verbatim from 4.4 <sys/ioctl.h>, with `struct' keywords removed. */
+
+#define TIOCMODG _IOR('t', 3, int) /* get modem control state */
+#define TIOCMODS _IOW('t', 4, int) /* set modem control state */
+#define TIOCM_LE 0001 /* line enable */
+#define TIOCM_DTR 0002 /* data terminal ready */
+#define TIOCM_RTS 0004 /* request to send */
+#define TIOCM_ST 0010 /* secondary transmit */
+#define TIOCM_SR 0020 /* secondary receive */
+#define TIOCM_CTS 0040 /* clear to send */
+#define TIOCM_CAR 0100 /* carrier detect */
+#define TIOCM_CD TIOCM_CAR
+#define TIOCM_RNG 0200 /* ring */
+#define TIOCM_RI TIOCM_RNG
+#define TIOCM_DSR 0400 /* data set ready */
+ /* 8-10 compat */
+#define TIOCEXCL _IO('t', 13) /* set exclusive use of tty */
+#define TIOCNXCL _IO('t', 14) /* reset exclusive use of tty */
+ /* 15 unused */
+#define TIOCFLUSH _IOW('t', 16, int) /* flush buffers */
+ /* 17-18 compat */
+#define TIOCGETA _IOR('t', 19, termios) /* get termios struct */
+#define TIOCSETA _IOW('t', 20, termios) /* set termios struct */
+#define TIOCSETAW _IOW('t', 21, termios) /* drain output, set */
+#define TIOCSETAF _IOW('t', 22, termios) /* drn out, fls in, set */
+#define TIOCGETD _IOR('t', 26, int) /* get line discipline */
+#define TIOCSETD _IOW('t', 27, int) /* set line discipline */
+ /* 127-124 compat */
+#define TIOCSBRK _IO('t', 123) /* set break bit */
+#define TIOCCBRK _IO('t', 122) /* clear break bit */
+#define TIOCSDTR _IO('t', 121) /* set data terminal ready */
+#define TIOCCDTR _IO('t', 120) /* clear data terminal ready */
+#define TIOCGPGRP _IOR('t', 119, int) /* get pgrp of tty */
+#define TIOCSPGRP _IOW('t', 118, int) /* set pgrp of tty */
+ /* 117-116 compat */
+#define TIOCOUTQ _IOR('t', 115, int) /* output queue size */
+#define TIOCSTI _IOW('t', 114, char) /* simulate terminal input */
+#define TIOCNOTTY _IO('t', 113) /* void tty association */
+#define TIOCPKT _IOW('t', 112, int) /* pty: set/clear packet mode */
+#define TIOCPKT_DATA 0x00 /* data packet */
+#define TIOCPKT_FLUSHREAD 0x01 /* flush packet */
+#define TIOCPKT_FLUSHWRITE 0x02 /* flush packet */
+#define TIOCPKT_STOP 0x04 /* stop output */
+#define TIOCPKT_START 0x08 /* start output */
+#define TIOCPKT_NOSTOP 0x10 /* no more ^S, ^Q */
+#define TIOCPKT_DOSTOP 0x20 /* now do ^S ^Q */
+#define TIOCPKT_IOCTL 0x40 /* state change of pty driver */
+#define TIOCSTOP _IO('t', 111) /* stop output, like ^S */
+#define TIOCSTART _IO('t', 110) /* start output, like ^Q */
+#define TIOCMSET _IOW('t', 109, int) /* set all modem bits */
+#define TIOCMBIS _IOW('t', 108, int) /* bis modem bits */
+#define TIOCMBIC _IOW('t', 107, int) /* bic modem bits */
+#define TIOCMGET _IOR('t', 106, int) /* get all modem bits */
+#define TIOCREMOTE _IOW('t', 105, int) /* remote input editing */
+#define TIOCGWINSZ _IOR('t', 104, winsize) /* get window size */
+#define TIOCSWINSZ _IOW('t', 103, winsize) /* set window size */
+#define TIOCUCNTL _IOW('t', 102, int) /* pty: set/clr usr cntl mode */
+#define UIOCCMD(n) _IO('u', n) /* usr cntl op "n" */
+#define TIOCCONS _IOW('t', 98, int) /* become virtual console */
+#define TIOCSCTTY _IO('t', 97) /* become controlling tty */
+#define TIOCEXT _IOW('t', 96, int) /* pty: external processing */
+#define TIOCSIG _IO('t', 95) /* pty: generate signal */
+#define TIOCDRAIN _IO('t', 94) /* wait till output drained */
+
+#define TTYDISC 0 /* termios tty line discipline */
+#define TABLDISC 3 /* tablet discipline */
+#define SLIPDISC 4 /* serial IP discipline */
+
+
+#define FIOCLEX _IO('f', 1) /* set close on exec on fd */
+#define FIONCLEX _IO('f', 2) /* remove close on exec */
+#define FIONREAD _IOR('f', 127, int) /* get # bytes to read */
+#define FIONBIO _IOW('f', 126, int) /* set/clear non-blocking i/o */
+#define FIOASYNC _IOW('f', 125, int) /* set/clear async i/o */
+#define FIOSETOWN _IOW('f', 124, int) /* set owner */
+#define FIOGETOWN _IOR('f', 123, int) /* get owner */
+
+/* socket i/o controls */
+#define SIOCSHIWAT _IOW('s', 0, int) /* set high watermark */
+#define SIOCGHIWAT _IOR('s', 1, int) /* get high watermark */
+#define SIOCSLOWAT _IOW('s', 2, int) /* set low watermark */
+#define SIOCGLOWAT _IOR('s', 3, int) /* get low watermark */
+#define SIOCATMARK _IOR('s', 7, int) /* at oob mark? */
+#define SIOCSPGRP _IOW('s', 8, int) /* set process group */
+#define SIOCGPGRP _IOR('s', 9, int) /* get process group */
+
+#define SIOCADDRT _IOW('r', 10, ortentry) /* add route */
+#define SIOCDELRT _IOW('r', 11, ortentry) /* delete route */
+
+#define SIOCSIFADDR _IOW('i', 12, ifreq) /* set ifnet address */
+#define OSIOCGIFADDR _IOWR('i',13, ifreq) /* get ifnet address */
+#define SIOCGIFADDR _IOWR('i',33, ifreq) /* get ifnet address */
+#define SIOCSIFDSTADDR _IOW('i', 14, ifreq) /* set p-p address */
+#define OSIOCGIFDSTADDR _IOWR('i',15, ifreq) /* get p-p address */
+#define SIOCGIFDSTADDR _IOWR('i',34, ifreq) /* get p-p address */
+#define SIOCSIFFLAGS _IOW('i', 16, ifreq) /* set ifnet flags */
+#define SIOCGIFFLAGS _IOWR('i',17, ifreq) /* get ifnet flags */
+#define OSIOCGIFBRDADDR _IOWR('i',18, ifreq) /* get broadcast addr */
+#define SIOCGIFBRDADDR _IOWR('i',35, ifreq) /* get broadcast addr */
+#define SIOCSIFBRDADDR _IOW('i',19, ifreq) /* set broadcast addr */
+#define OSIOCGIFCONF _IOWR('i',20, ifconf) /* get ifnet list */
+#define SIOCGIFCONF _IOWR('i',36, ifconf) /* get ifnet list */
+#define OSIOCGIFNETMASK _IOWR('i',21, ifreq) /* get net addr mask */
+#define SIOCGIFNETMASK _IOWR('i',37, ifreq) /* get net addr mask */
+#define SIOCSIFNETMASK _IOW('i',22, ifreq) /* set net addr mask */
+#define SIOCGIFMETRIC _IOWR('i',23, ifreq) /* get IF metric */
+#define SIOCSIFMETRIC _IOW('i',24, ifreq) /* set IF metric */
+#define SIOCDIFADDR _IOW('i',25, ifreq) /* delete IF addr */
+#define SIOCAIFADDR _IOW('i',26, ifaliasreq) /* add/chg IF alias */
+
+#define SIOCSARP _IOW('i', 30, arpreq) /* set arp entry */
+#define OSIOCGARP _IOWR('i',31, arpreq) /* get arp entry */
+#define SIOCGARP _IOWR('i',38, arpreq) /* get arp entry */
+#define SIOCDARP _IOW('i', 32, arpreq) /* delete arp entry */
+
+
+/* Compatibility with 4.3 BSD terminal driver.
+ From 4.4 <sys/ioctl_compat.h>. */
+
+#ifdef USE_OLD_TTY
+# undef TIOCGETD
+# define TIOCGETD _IOR('t', 0, int) /* get line discipline */
+# undef TIOCSETD
+# define TIOCSETD _IOW('t', 1, int) /* set line discipline */
+#else
+# define OTIOCGETD _IOR('t', 0, int) /* get line discipline */
+# define OTIOCSETD _IOW('t', 1, int) /* set line discipline */
+#endif
+#define TIOCHPCL _IO('t', 2) /* hang up on last close */
+#define TIOCGETP _IOR('t', 8,sgttyb)/* get parameters -- gtty */
+#define TIOCSETP _IOW('t', 9,sgttyb)/* set parameters -- stty */
+#define TIOCSETN _IOW('t',10,sgttyb)/* as above, but no flushtty*/
+#define TIOCSETC _IOW('t',17,tchars)/* set special characters */
+#define TIOCGETC _IOR('t',18,tchars)/* get special characters */
+#define TANDEM 0x00000001 /* send stopc on out q full */
+#define CBREAK 0x00000002 /* half-cooked mode */
+#define LCASE 0x00000004 /* simulate lower case */
+#define ECHO 0x00000008 /* echo input */
+#define CRMOD 0x00000010 /* map \r to \r\n on output */
+#define RAW 0x00000020 /* no i/o processing */
+#define ODDP 0x00000040 /* get/send odd parity */
+#define EVENP 0x00000080 /* get/send even parity */
+#define ANYP 0x000000c0 /* get any parity/send none */
+#define NLDELAY 0x00000300 /* \n delay */
+#define NL0 0x00000000
+#define NL1 0x00000100 /* tty 37 */
+#define NL2 0x00000200 /* vt05 */
+#define NL3 0x00000300
+#define TBDELAY 0x00000c00 /* horizontal tab delay */
+#define TAB0 0x00000000
+#define TAB1 0x00000400 /* tty 37 */
+#define TAB2 0x00000800
+#define XTABS 0x00000c00 /* expand tabs on output */
+#define CRDELAY 0x00003000 /* \r delay */
+#define CR0 0x00000000
+#define CR1 0x00001000 /* tn 300 */
+#define CR2 0x00002000 /* tty 37 */
+#define CR3 0x00003000 /* concept 100 */
+#define VTDELAY 0x00004000 /* vertical tab delay */
+#define FF0 0x00000000
+#define FF1 0x00004000 /* tty 37 */
+#define BSDELAY 0x00008000 /* \b delay */
+#define BS0 0x00000000
+#define BS1 0x00008000
+#define ALLDELAY (NLDELAY|TBDELAY|CRDELAY|VTDELAY|BSDELAY)
+#define CRTBS 0x00010000 /* do backspacing for crt */
+#define PRTERA 0x00020000 /* \ ... / erase */
+#define CRTERA 0x00040000 /* " \b " to wipe out char */
+#define TILDE 0x00080000 /* hazeltine tilde kludge */
+#define MDMBUF 0x00100000 /*start/stop output on carrier*/
+#define LITOUT 0x00200000 /* literal output */
+#define TOSTOP 0x00400000 /*SIGSTOP on background output*/
+#define FLUSHO 0x00800000 /* flush output to terminal */
+#define NOHANG 0x01000000 /* (no-op) was no SIGHUP on carrier drop */
+#define L001000 0x02000000
+#define CRTKIL 0x04000000 /* kill line with " \b " */
+#define PASS8 0x08000000
+#define CTLECH 0x10000000 /* echo control chars as ^X */
+#define PENDIN 0x20000000 /* tp->t_rawq needs reread */
+#define DECCTQ 0x40000000 /* only ^Q starts after ^S */
+#define NOFLSH 0x80000000 /* no output flush on signal */
+#define TIOCLBIS _IOW('t', 127, int) /* bis local mode bits */
+#define TIOCLBIC _IOW('t', 126, int) /* bic local mode bits */
+#define TIOCLSET _IOW('t', 125, int) /* set entire local mode word */
+#define TIOCLGET _IOR('t', 124, int) /* get local modes */
+#define LCRTBS (CRTBS>>16)
+#define LPRTERA (PRTERA>>16)
+#define LCRTERA (CRTERA>>16)
+#define LTILDE (TILDE>>16)
+#define LMDMBUF (MDMBUF>>16)
+#define LLITOUT (LITOUT>>16)
+#define LTOSTOP (TOSTOP>>16)
+#define LFLUSHO (FLUSHO>>16)
+#define LNOHANG (NOHANG>>16)
+#define LCRTKIL (CRTKIL>>16)
+#define LPASS8 (PASS8>>16)
+#define LCTLECH (CTLECH>>16)
+#define LPENDIN (PENDIN>>16)
+#define LDECCTQ (DECCTQ>>16)
+#define LNOFLSH (NOFLSH>>16)
+#define TIOCSLTC _IOW('t',117,ltchars)/* set local special chars*/
+#define TIOCGLTC _IOR('t',116,ltchars)/* get local special chars*/
+#define OTIOCCONS _IO('t', 98) /* for hp300 -- sans int arg */
+#define OTTYDISC 0
+#define NETLDISC 1
+#define NTTYDISC 2
+
+/* From 4.4 <sys/ttydev.h>. */
+#ifdef USE_OLD_TTY
+#define B0 0
+#define B50 1
+#define B75 2
+#define B110 3
+#define B134 4
+#define B150 5
+#define B200 6
+#define B300 7
+#define B600 8
+#define B1200 9
+#define B1800 10
+#define B2400 11
+#define B4800 12
+#define B9600 13
+#define EXTA 14
+#define EXTB 15
+#endif /* USE_OLD_TTY */
+
+
+#endif /* ioctls.h */
diff --git a/sysdeps/mach/hurd/isatty.c b/sysdeps/mach/hurd/isatty.c
new file mode 100644
index 0000000000..e04793a6a2
--- /dev/null
+++ b/sysdeps/mach/hurd/isatty.c
@@ -0,0 +1,39 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd/fd.h>
+#include <hurd/term.h>
+
+/* Return 1 if FD is a terminal, 0 if not. */
+int
+DEFUN(__isatty, (fd), int fd)
+{
+ error_t err;
+ mach_port_t id;
+
+ err = HURD_DPORT_USE (fd, __term_getctty (port, &id));
+ if (! err)
+ __mach_port_deallocate (__mach_task_self (), id);
+
+ return !err;
+}
+
+weak_alias (__isatty, isatty)
diff --git a/sysdeps/mach/hurd/kill.c b/sysdeps/mach/hurd/kill.c
new file mode 100644
index 0000000000..0d4af62127
--- /dev/null
+++ b/sysdeps/mach/hurd/kill.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <hurd.h>
+#include <hurd/port.h>
+#include <hurd/signal.h>
+#include <hurd/msg.h>
+
+/* Send signal SIG to process number PID. If PID is zero,
+ send SIG to all processes in the current process's process group.
+ If PID is < -1, send SIG to all processes in process group - PID. */
+int
+__kill (pid_t pid, int sig)
+{
+ int delivered = 0; /* Set when we deliver any signal. */
+ error_t err;
+ mach_port_t proc;
+ struct hurd_userlink ulink;
+
+ inline void kill_pid (pid_t pid) /* Kill one PID. */
+ {
+ /* SIGKILL is not delivered as a normal signal.
+ Sending SIGKILL to a process means to terminate its task. */
+ if (sig == SIGKILL)
+ /* Fetch the process's task port and terminate the task. We
+ loop in case the process execs and changes its task port.
+ If the old task port dies after we fetch it but before we
+ send the RPC, we get MACH_SEND_INVALID_DEST; if it dies
+ after we send the RPC request but before it is serviced, we
+ get MIG_SERVER_DIED. */
+ do
+ {
+ task_t refport;
+ err = __proc_pid2task (proc, pid, &refport);
+ if (!err)
+ {
+ err = __task_terminate (refport);
+ __mach_port_deallocate (__mach_task_self (), refport);
+ }
+ } while (err == MACH_SEND_INVALID_DEST ||
+ err == MIG_SERVER_DIED);
+ else
+ err = HURD_MSGPORT_RPC (__proc_getmsgport (proc, pid, &msgport),
+ __proc_pid2task (proc, pid, &refport) ?
+ __proc_getsidport (proc, &refport) : 0, 1,
+ /* If no msgport, we cannot send a signal. */
+ msgport == MACH_PORT_NULL ? EPERM :
+ __msg_sig_post (msgport, sig, refport));
+ if (! err)
+ delivered = 1;
+ }
+
+ proc = _hurd_port_get (&_hurd_ports[INIT_PORT_PROC], &ulink);
+
+ if (pid <= 0)
+ {
+ /* Send SIG to each process in pgrp (- PID). */
+ pid_t pidbuf[10], *pids = pidbuf;
+ mach_msg_type_number_t i, npids = sizeof (pidbuf) / sizeof (pidbuf[0]);
+
+ err = __proc_getpgrppids (proc, - pid, &pids, &npids);
+ if (!err)
+ {
+ for (i = 0; i < npids; ++i)
+ {
+ kill_pid (pids[i]);
+ if (err == ESRCH)
+ /* The process died already. Ignore it. */
+ err = 0;
+ }
+ if (pids != pidbuf)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) pids, npids * sizeof (pids[0]));
+ }
+ }
+ else
+ kill_pid (pid);
+
+ _hurd_port_free (&_hurd_ports[INIT_PORT_PROC], &ulink, proc);
+
+ /* If we delivered no signals, but ERR is clear, this must mean that
+ every kill_pid call failed with ESRCH, meaning all the processes in
+ the pgrp died between proc_getpgrppids and kill_pid; in that case we
+ fail with ESRCH. */
+ return delivered ? 0 : __hurd_fail (err ?: ESRCH);
+}
+
+weak_alias (__kill, kill)
diff --git a/sysdeps/mach/hurd/libc-ldscript b/sysdeps/mach/hurd/libc-ldscript
new file mode 100644
index 0000000000..26aca50272
--- /dev/null
+++ b/sysdeps/mach/hurd/libc-ldscript
@@ -0,0 +1,5 @@
+/* This linker script is installed as /lib/libc.a.
+ It makes -lc become just like -( -lcrt -lmachuser -lhurduser -).
+ */
+
+GROUP ( libcrt.a libmachuser.a libhurduser.a )
diff --git a/sysdeps/mach/hurd/link.c b/sysdeps/mach/hurd/link.c
new file mode 100644
index 0000000000..11262f5a0f
--- /dev/null
+++ b/sysdeps/mach/hurd/link.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Make a link to FROM called TO. */
+int
+DEFUN(__link, (from, to), CONST char *from AND CONST char *to)
+{
+ error_t err;
+ file_t oldfile, linknode, todir;
+ char *toname;
+
+ oldfile = __file_name_lookup (from, 0, 0);
+ if (oldfile == MACH_PORT_NULL)
+ return -1;
+
+ /* The file_getlinknode RPC returns the port that should be passed to
+ the receiving filesystem (the one containing TODIR) in dir_link. */
+
+ err = __file_getlinknode (oldfile, &linknode);
+ __mach_port_deallocate (__mach_task_self (), oldfile);
+ if (err)
+ return __hurd_fail (err);
+
+ todir = __file_name_split (to, &toname);
+ if (todir != MACH_PORT_NULL)
+ {
+ err = __dir_link (linknode, todir, toname);
+ __mach_port_deallocate (__mach_task_self (), todir);
+ }
+ __mach_port_deallocate (__mach_task_self (), linknode);
+ if (todir == MACH_PORT_NULL)
+ return -1;
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__link, link)
diff --git a/sysdeps/mach/hurd/listen.c b/sysdeps/mach/hurd/listen.c
new file mode 100644
index 0000000000..2f9c412c8b
--- /dev/null
+++ b/sysdeps/mach/hurd/listen.c
@@ -0,0 +1,36 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <sys/socket.h>
+#include <hurd/socket.h>
+
+/* Prepare to accept connections on socket FD.
+ N connection requests will be queued before further requests are refused.
+ Returns 0 on success, -1 for errors. */
+int
+DEFUN(listen, (fd, n), int fd AND unsigned int n)
+{
+ error_t err = HURD_DPORT_USE (fd, __socket_listen (port, n));
+ if (err)
+ return __hurd_dfail (fd, err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/local_lim.h b/sysdeps/mach/hurd/local_lim.h
new file mode 100644
index 0000000000..766bd25244
--- /dev/null
+++ b/sysdeps/mach/hurd/local_lim.h
@@ -0,0 +1,40 @@
+/* Minimum guaranteed maximum values for system limits. Hurd version.
+
+Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* GNU has no arbitrary fixed limits on these things, so we don't
+ define the macros. Some things are unlimited. Some are in fact
+ limited but the limit is run-time dependent and fetched with
+ `sysconf' or `pathconf'.
+
+ POSIX.1 requires that we define NGROUPS_MAX (though none of the others
+ is required). GNU allows any number of supplementary groups,
+ dynamically allocated. So we pick a number which seems vaguely
+ suitable, and `sysconf' will return a number at least as large. */
+
+#define NGROUPS_MAX 256
+
+/* The maximum number of symbolic links that are allowed in a single file
+ name resolution. When a further link is encountered, the call returns
+ ELOOP. This name is a GNU extension; POSIX.1 has no such limit, and BSD
+ calls it MAXSYMLINKS in <sys/param.h>. */
+
+#ifdef __USE_GNU /* 1003.1a defines this */
+#define SYMLOOP_MAX 8
+#endif
diff --git a/sysdeps/mach/hurd/lseek.c b/sysdeps/mach/hurd/lseek.c
new file mode 100644
index 0000000000..396d2b9e09
--- /dev/null
+++ b/sysdeps/mach/hurd/lseek.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Seek to OFFSET on FD, starting from WHENCE. */
+off_t
+DEFUN(__lseek, (fd, offset, whence), int fd AND off_t offset AND int whence)
+{
+ error_t err;
+ if (err = HURD_DPORT_USE (fd, __io_seek (port, offset, whence, &offset)))
+ return __hurd_dfail (fd, err);
+ return offset;
+}
+
+weak_alias (__lseek, lseek)
diff --git a/sysdeps/mach/hurd/lstat.c b/sysdeps/mach/hurd/lstat.c
new file mode 100644
index 0000000000..21eb448fe8
--- /dev/null
+++ b/sysdeps/mach/hurd/lstat.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <fcntl.h>
+#include <hurd.h>
+
+int
+DEFUN(__lstat, (file, buf), CONST char *file AND struct stat *buf)
+{
+ error_t err;
+ file_t port = __file_name_lookup (file, O_NOLINK, 0);
+ if (port == MACH_PORT_NULL)
+ return -1;
+ err = __io_stat (port, buf);
+ __mach_port_deallocate (__mach_task_self (), port);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__lstat, lstat)
diff --git a/sysdeps/mach/hurd/mig-reply.c b/sysdeps/mach/hurd/mig-reply.c
new file mode 100644
index 0000000000..feb03257dd
--- /dev/null
+++ b/sysdeps/mach/hurd/mig-reply.c
@@ -0,0 +1,86 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <mach.h>
+#include <hurd/threadvar.h>
+
+#define GETPORT \
+ mach_port_t *portloc = \
+ (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY)
+#define reply_port (use_threadvar ? *portloc : global_reply_port)
+
+static int use_threadvar;
+static mach_port_t global_reply_port;
+
+/* These functions are called by MiG-generated code. */
+
+/* Called by MiG to get a reply port. */
+mach_port_t
+__mig_get_reply_port (void)
+{
+ GETPORT;
+
+ if (reply_port == MACH_PORT_NULL)
+ reply_port = __mach_reply_port ();
+
+ return reply_port;
+}
+weak_alias (__mig_get_reply_port, mig_get_reply_port)
+
+/* Called by MiG to deallocate the reply port. */
+void
+__mig_dealloc_reply_port (mach_port_t arg)
+{
+ mach_port_t port;
+
+ GETPORT;
+
+ port = reply_port;
+ reply_port = MACH_PORT_NULL; /* So the mod_refs RPC won't use it. */
+ __mach_port_mod_refs (__mach_task_self (), port,
+ MACH_PORT_RIGHT_RECEIVE, -1);
+}
+weak_alias (__mig_dealloc_reply_port, mig_dealloc_reply_port)
+
+/* Called by mig interfaces when done with a port. Used to provide the
+ same interface as needed when a custom allocator is used. */
+void
+__mig_put_reply_port(mach_port_t port)
+{
+ /* Do nothing. */
+}
+weak_alias (__mig_put_reply_port, mig_put_reply_port)
+
+/* Called at startup with STACK == NULL. When per-thread variables are set
+ up, this is called again with STACK set to the new stack being switched
+ to, where per-thread variables should be set up. */
+void
+__mig_init (void *stack)
+{
+ use_threadvar = stack != 0;
+
+ if (use_threadvar)
+ {
+ /* Recycle the reply port used before multithreading was enabled. */
+ mach_port_t *portloc = (mach_port_t *)
+ __hurd_threadvar_location_from_sp (_HURD_THREADVAR_MIG_REPLY, stack);
+ *portloc = global_reply_port;
+ global_reply_port = MACH_PORT_NULL;
+ }
+}
+weak_alias (__mig_init, mig_init)
diff --git a/sysdeps/mach/hurd/mips/exc2signal.c b/sysdeps/mach/hurd/mips/exc2signal.c
new file mode 100644
index 0000000000..f907c89cf0
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/exc2signal.c
@@ -0,0 +1,98 @@
+/* Translate Mach exception codes into signal numbers. MIPS version.
+Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <mach/exception.h>
+
+/* Translate the Mach exception codes, as received in an `exception_raise' RPC,
+ into a signal number and signal subcode. */
+
+void
+_hurd_exception2signal (int exception, int code, int subcode,
+ int *signo, long int *sigcode, int *error)
+{
+ *error = 0;
+
+ switch (exception)
+ {
+ default:
+ *signo = SIGIOT;
+ *sigcode = exception;
+ break;
+
+ case EXC_BAD_ACCESS:
+ if (code == KERN_PROTECTION_FAILURE)
+ *signo = SIGSEGV;
+ else
+ *signo = SIGBUS;
+ *sigcode = subcode;
+ *error = code;
+ break;
+
+ case EXC_BAD_INSTRUCTION:
+ *signo = SIGILL;
+ if (code == EXC_MIPS_II)
+ *sigcode = code;
+ else
+ *sigcode = 0;
+ break;
+
+ case EXC_ARITHMETIC:
+ switch (code)
+ {
+ case EXC_MIPS_OV: /* integer overflow */
+ *signo = SIGFPE;
+ *sigcode = EXC_MIPS_FLT_OVERFLOW;
+ break;
+
+ default:
+ *signo = SIGFPE;
+ *sigcode = 0;
+ break;
+
+ case EXC_MIPS_INT:
+ /* Subcode is the fp_status word saved by the hardware.
+ Give an error code corresponding to the first bit set. */
+ if (subcode == EXC_MIPS_FLT_UNIMP)
+ *signo = SIGILL;
+ else
+ *signo = SIGFPE;
+ *sigcode = subcode;
+ break;
+ }
+ break;
+
+ case EXC_EMULATION:
+ /* 3.0 doesn't give this one, why, I don't know. */
+ *signo = SIGEMT;
+ *sigcode = 0;
+ break;
+
+ case EXC_SOFTWARE:
+ *signo = SIGEMT;
+ *sigcode = 0;
+ break;
+
+ case EXC_BREAKPOINT:
+ *signo = SIGTRAP;
+ *sigcode = code;
+ break;
+ }
+}
diff --git a/sysdeps/mach/hurd/mips/init-fault.c b/sysdeps/mach/hurd/mips/init-fault.c
new file mode 100644
index 0000000000..e6f8acf64d
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/init-fault.c
@@ -0,0 +1,41 @@
+/* Set up a thread_state for proc_handle_exceptions. MIPS version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include <mach/thread_status.h>
+#include <string.h>
+#include <setjmp.h>
+
+extern jmp_buf _hurd_sigthread_fault_env;
+
+static char fault_stack[32];
+static volatile void
+faulted (void)
+{
+ __longjmp (_hurd_sigthread_fault_env, 1);
+}
+
+void
+_hurd_initialize_fault_recovery_state (void *state)
+{
+ struct mips_thread_state *ts = state;
+ memset (ts, 0, sizeof (*ts));
+ ts->r29 = (int) &fault_stack[sizeof (fault_stack)];
+ ts->pc = (int) &faulted;
+}
diff --git a/sysdeps/mach/hurd/mips/longjmp-ctx.c b/sysdeps/mach/hurd/mips/longjmp-ctx.c
new file mode 100644
index 0000000000..0c78f6b4d6
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/longjmp-ctx.c
@@ -0,0 +1,41 @@
+/* Perform a `longjmp' on a `struct sigcontext'. MIPS version.
+Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <setjmp.h>
+#include <hurd/signal.h>
+#include <string.h>
+
+void
+_hurd_longjmp_sigcontext (struct sigcontext *scp, jmp_buf env, int retval)
+{
+ scp->sc_gpr[16] = env[0].__regs[0];
+ scp->sc_gpr[17] = env[0].__regs[1];
+ scp->sc_gpr[18] = env[0].__regs[2];
+ scp->sc_gpr[19] = env[0].__regs[3];
+ scp->sc_gpr[20] = env[0].__regs[4];
+ scp->sc_gpr[21] = env[0].__regs[5];
+ scp->sc_gpr[22] = env[0].__regs[6];
+ scp->sc_gpr[23] = env[0].__regs[7];
+
+ scp->sc_gpr[28] = (int) env[0].__gp;
+ scp->sc_fp = (int) env[0].__fp;
+ scp->sc_sp = (int) env[0].__sp;
+ scp->sc_pc = (int) env[0].__pc;
+ scp->sc_gpr[2] = retval ?: 1;
+}
diff --git a/sysdeps/mach/hurd/mips/longjmp-ts.c b/sysdeps/mach/hurd/mips/longjmp-ts.c
new file mode 100644
index 0000000000..980a2ceb94
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/longjmp-ts.c
@@ -0,0 +1,45 @@
+/* Perform a `longjmp' on a Mach thread_state. MIPS version.
+Copyright (C) 1991, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include <setjmp.h>
+#include <mach/thread_status.h>
+
+
+/* Set up STATE to do the equivalent of `longjmp (ENV, VAL);'. */
+
+void
+_hurd_longjmp_thread_state (void *state, jmp_buf env, int val)
+{
+ struct mips_thread_state *ts = state;
+
+ ts->r16 = env[0].__jmpbuf[0].__regs[0];
+ ts->r17 = env[0].__jmpbuf[0].__regs[1];
+ ts->r18 = env[0].__jmpbuf[0].__regs[2];
+ ts->r19 = env[0].__jmpbuf[0].__regs[3];
+ ts->r20 = env[0].__jmpbuf[0].__regs[4];
+ ts->r21 = env[0].__jmpbuf[0].__regs[5];
+ ts->r22 = env[0].__jmpbuf[0].__regs[6];
+ ts->r23 = env[0].__jmpbuf[0].__regs[7];
+ ts->r28 = (int) env[0].__jmpbuf[0].__gp;
+ ts->r29 = (int) env[0].__jmpbuf[0].__sp;
+ ts->r30 = (int) env[0].__jmpbuf[0].__fp;
+ ts->pc = (int) env[0].__jmpbuf[0].__pc;
+ ts->r2 = val ?: 1;
+}
diff --git a/sysdeps/mach/hurd/mips/sigcontext.h b/sysdeps/mach/hurd/mips/sigcontext.h
new file mode 100644
index 0000000000..81d1f25f25
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/sigcontext.h
@@ -0,0 +1,71 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* Signal handlers are actually called:
+ void handler (int sig, int code, struct sigcontext *scp); */
+
+/* State of this thread when the signal was taken. */
+struct sigcontext
+ {
+ /* These first members are machine-independent. */
+
+ int sc_onstack; /* Nonzero if running on sigstack. */
+ __sigset_t sc_mask; /* Blocked signals to restore. */
+
+ /* MiG reply port this thread is using. */
+ unsigned int sc_reply_port;
+
+ /* Port this thread is doing an interruptible RPC on. */
+ unsigned int sc_intr_port;
+
+ /* Error code associated with this signal (interpreted as `error_t'). */
+ int sc_error;
+
+ /* All following members are machine-dependent. The rest of this
+ structure is written to be laid out identically to:
+ {
+ struct mips_thread_state ts;
+ struct mips_exc_state es;
+ struct mips_float_state fs;
+ }
+ trampoline.c knows this, so it must be changed if this changes. */
+#define sc_mips_thread_state sc_gpr /* Beginning of correspondence. */
+ int sc_gpr[31]; /* "General" registers; [0] is r1. */
+ int sc_mdlo, sc_mdhi; /* Low and high multiplication results. */
+ int sc_pc; /* Instruction pointer. */
+
+ /* struct mips_exc_state */
+#define sc_mips_exc_state sc_cause
+ unsigned int sc_cause; /* Machine-level trap code. */
+#define SC_CAUSE_SST 0x00000044
+ unsigned int sc_badvaddr;
+ unsigned int sc_coproc_used; /* Which coprocessors the thread has used. */
+#define SC_COPROC_USE_COP0 1 /* (by definition) */
+#define SC_COPROC_USE_COP1 2 /* FPA */
+#define SC_COPROC_USE_FPU SC_COPROC_USE_COP1
+#define SC_COPROC_USE_COP2 4
+#define SC_COPROC_USE_COP3 8
+
+ /* struct mips_float_state
+ This is only filled in if the SC_COPROC_USE_FPU bit
+ is set in sc_coproc_used. */
+#define sc_mips_float_state sc_fpr
+ int sc_fpr[32]; /* FP registers. */
+ int sc_fpcsr; /* FPU status register. */
+ int sc_fpeir; /* FP exception instruction register. */
+ };
diff --git a/sysdeps/mach/hurd/mips/sigreturn.c b/sysdeps/mach/hurd/mips/sigreturn.c
new file mode 100644
index 0000000000..7396a8bb22
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/sigreturn.c
@@ -0,0 +1,169 @@
+/* Copyright (C) 1991, 1992, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/threadvar.h>
+#include <stdlib.h>
+
+int
+__sigreturn (struct sigcontext *scp)
+{
+ struct hurd_sigstate *ss;
+ mach_port_t *reply_port;
+
+ if (scp == NULL || (scp->sc_mask & _SIG_CANT_MASK))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss = _hurd_self_sigstate ();
+ __spin_lock (&ss->lock);
+
+ /* Restore the set of blocked signals, and the intr_port slot. */
+ ss->blocked = scp->sc_mask;
+ ss->intr_port = scp->sc_intr_port;
+
+ /* Check for pending signals that were blocked by the old set. */
+ if (ss->pending & ~ss->blocked)
+ {
+ /* There are pending signals that just became unblocked. Wake up the
+ signal thread to deliver them. But first, squirrel away SCP where
+ the signal thread will notice it if it runs another handler, and
+ arrange to have us called over again in the new reality. */
+ ss->context = scp;
+ /* Clear the intr_port slot, since we are not in fact doing
+ an interruptible RPC right now. If SS->intr_port is not null,
+ the SCP context is doing an interruptible RPC, but the signal
+ thread will examine us while we are blocked in the sig_post RPC. */
+ ss->intr_port = MACH_PORT_NULL;
+ __spin_unlock (&ss->lock);
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+ /* If a pending signal was handled, sig_post never returned. */
+ __spin_lock (&ss->lock);
+ }
+
+ if (scp->sc_onstack)
+ {
+ ss->sigaltstack.ss_flags &= ~SA_ONSTACK; /* XXX threadvars */
+ /* XXX cannot unlock until off sigstack */
+ abort ();
+ }
+ else
+ __spin_unlock (&ss->lock);
+
+ /* Destroy the MiG reply port used by the signal handler, and restore the
+ reply port in use by the thread when interrupted. */
+ reply_port =
+ (mach_port_t *) __hurd_threadvar_location (_HURD_THREADVAR_MIG_REPLY);
+ if (*reply_port)
+ __mach_port_destroy (__mach_task_self (), *reply_port);
+ *reply_port = scp->sc_reply_port;
+
+ if (scp->sc_coproc_used & SC_COPROC_USE_FPU)
+ {
+ /* Restore FPU state. */
+#define restore_fpr(n) \
+ asm volatile ("l.d $f" #n ",%0" : : "m" (scp->sc_fpr[n]))
+
+ /* Restore floating-point registers. */
+ restore_fpr (0);
+ restore_fpr (2);
+ restore_fpr (4);
+ restore_fpr (6);
+ restore_fpr (8);
+ restore_fpr (10);
+ restore_fpr (12);
+ restore_fpr (14);
+ restore_fpr (16);
+ restore_fpr (18);
+ restore_fpr (20);
+ restore_fpr (22);
+ restore_fpr (24);
+ restore_fpr (26);
+ restore_fpr (28);
+ restore_fpr (30);
+
+ /* Restore the floating-point control/status register ($f31). */
+ asm volatile ("ctc1 %0,$f31" : : "r" (scp->sc_fpcsr));
+ }
+
+ /* Load all the registers from the sigcontext. */
+#define restore_gpr(n) \
+ asm volatile ("lw $" #n ",%0" : : "m" (scpreg->sc_gpr[n - 1]))
+
+ {
+ register const struct sigcontext *const scpreg asm ("$1") = scp;
+ register int *at asm ("$1");
+
+ /* First restore the multiplication result registers. The compiler
+ will use some temporary registers, so we do this before restoring
+ the general registers. */
+ asm volatile ("mtlo %0" : : "r" (scpreg->sc_mdlo));
+ asm volatile ("mthi %0" : : "r" (scpreg->sc_mdhi));
+
+ /* In the word after the saved PC, store the saved $1 value. */
+ (&scpreg->sc_pc)[1] = scpreg->sc_gpr[0];
+
+ asm volatile (".set noreorder; .set noat;");
+
+ /* Restore the normal registers. */
+ restore_gpr (2);
+ restore_gpr (3);
+ restore_gpr (4);
+ restore_gpr (5);
+ restore_gpr (6);
+ restore_gpr (7);
+ restore_gpr (8);
+ restore_gpr (9);
+ restore_gpr (10);
+ restore_gpr (11);
+ restore_gpr (12);
+ restore_gpr (13);
+ restore_gpr (14);
+ restore_gpr (15);
+ restore_gpr (16);
+ restore_gpr (17);
+ restore_gpr (18);
+ restore_gpr (19);
+ restore_gpr (20);
+ restore_gpr (21);
+ restore_gpr (22);
+ restore_gpr (23);
+ restore_gpr (24);
+ restore_gpr (25);
+ /* Registers 26-27 are kernel-only. */
+ restore_gpr (28);
+ restore_gpr (29); /* Stack pointer. */
+ restore_gpr (30); /* Frame pointer. */
+ restore_gpr (31); /* Return address. */
+
+ at = &scpreg->sc_pc;
+ /* This is an emulated instruction that will find at the address in $1
+ two words: the PC value to restore, and the $1 value to restore. */
+ asm volatile (".word op_sigreturn");
+
+ asm volatile (".set reorder; .set at;");
+ }
+
+ /* NOTREACHED */
+ return -1;
+}
+
+weak_alias (__sigreturn, sigreturn)
diff --git a/sysdeps/mach/hurd/mips/trampoline.c b/sysdeps/mach/hurd/mips/trampoline.c
new file mode 100644
index 0000000000..f03ad5852f
--- /dev/null
+++ b/sysdeps/mach/hurd/mips/trampoline.c
@@ -0,0 +1,260 @@
+/* Set thread_state for sighandler, and sigcontext to recover. MIPS version.
+Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd/signal.h>
+#include "thread_state.h"
+
+
+struct mach_msg_trap_args
+ {
+ /* This is the order of arguments to mach_msg_trap. */
+ mach_msg_header_t *msg;
+ mach_msg_option_t option;
+ mach_msg_size_t send_size;
+ mach_msg_size_t rcv_size;
+ mach_port_t rcv_name;
+ mach_msg_timeout_t timeout;
+ mach_port_t notify;
+ };
+
+
+struct sigcontext *
+_hurd_setup_sighandler (struct hurd_sigstate *ss, __sighandler_t handler,
+ int signo, long int sigcode,
+ int rpc_wait,
+ struct machine_thread_all_state *state)
+{
+
+ __label__ trampoline, rpc_wait_trampoline;
+ void *sigsp;
+ struct sigcontext *scp;
+
+ if (ss->context)
+ {
+ /* We have a previous sigcontext that sigreturn was about
+ to restore when another signal arrived. We will just base
+ our setup on that. */
+ if (! setjmp (_hurd_sigthread_fault_env))
+ {
+ memcpy (&state->basic, &ss->context->sc_mips_thread_state,
+ sizeof (state->basic));
+ memcpy (&state->exc, &ss->context->sc_mips_exc_state,
+ sizeof (state->exc));
+ state->set = (1 << MIPS_THREAD_STATE) | (1 << MIPS_EXC_STATE);
+ if (state->exc.coproc_state & SC_COPROC_USE_FPU)
+ {
+ memcpy (&state->fpu, &ss->context->sc_mips_float_state,
+ sizeof (state->fpu));
+ state->set |= (1 << MIPS_FLOAT_STATE);
+ }
+ assert (! rpc_wait);
+ /* The intr_port slot was cleared before sigreturn sent us the
+ sig_post that made us notice this pending signal, so
+ _hurd_internal_post_signal wouldn't do interrupt_operation.
+ After we return, our caller will set SCP->sc_intr_port (in the
+ new context) from SS->intr_port and clear SS->intr_port. Now
+ that we are restoring this old context recorded by sigreturn,
+ we want to restore its intr_port too; so store it in
+ SS->intr_port now, so it will end up in SCP->sc_intr_port
+ later. */
+ ss->intr_port = ss->context->sc_intr_port;
+ }
+ /* If the sigreturn context was bogus, just ignore it. */
+ ss->context = NULL;
+ }
+ else if (! machine_get_basic_state (ss->thread, state))
+ return NULL;
+
+ if ((ss->actions[signo].sa_flags & SA_ONSTACK) &&
+ !(ss->sigaltstack.ss_flags & (SA_DISABLE|SA_ONSTACK)))
+ {
+ sigsp = ss->sigaltstack.ss_sp + ss->sigaltstack.ss_size;
+ ss->sigaltstack.ss_flags |= SA_ONSTACK;
+ /* XXX need to set up base of new stack for
+ per-thread variables, cthreads. */
+ }
+ else
+ sigsp = (char *) state->basic.r29;
+
+ /* Set up the sigcontext structure on the stack. This is all the stack
+ needs, since the args are passed in registers (below). */
+ sigsp -= sizeof (*scp);
+ scp = sigsp;
+
+ if (! setjmp (_hurd_sigthread_fault_env))
+ {
+ /* Set up the sigcontext from the current state of the thread. */
+
+ scp->sc_onstack = ss->sigaltstack.ss_flags & SA_ONSTACK ? 1 : 0;
+
+ /* struct sigcontext is laid out so that starting at sc_gpr
+ mimics a struct mips_thread_state. */
+ memcpy (&scp->sc_mips_thread_state,
+ &state->basic, sizeof (state->basic));
+
+ /* struct sigcontext is laid out so that starting at sc_cause
+ mimics a struct mips_exc_state. */
+ if (! machine_get_state (ss->thread, state, MIPS_EXC_STATE,
+ &state->exc, &scp->sc_cause,
+ sizeof (state->exc)))
+ return NULL;
+ if ((scp->sc_coproc_used & SC_COPROC_USE_FPU) &&
+ /* struct sigcontext is laid out so that starting at sc_fpr
+ mimics a struct mips_float_state. This state
+ is only meaningful if the coprocessor was used. */
+ ! machine_get_state (ss->thread, state, MIPS_FLOAT_STATE,
+ &state->fpu,
+ &scp->sc_mips_float_state, sizeof (state->fpu)))
+ return NULL;
+ }
+ else
+ /* We got a fault trying to write the stack frame.
+ We cannot set up the signal handler.
+ Returning NULL tells our caller, who will nuke us with a SIGILL. */
+ return NULL;
+
+ /* Modify the thread state to call the trampoline code on the new stack. */
+ if (rpc_wait)
+ {
+ /* The signalee thread was blocked in a mach_msg_trap system call,
+ still waiting for a reply. We will have it run the special
+ trampoline code which retries the message receive before running
+ the signal handler.
+
+ To do this we change the OPTION argument in its registers to
+ enable only message reception, since the request message has
+ already been sent. */
+
+ /* The system call arguments are stored in consecutive registers
+ starting with a0 ($4). */
+ struct mach_msg_trap_args *args = (void *) &state->basic.r4;
+
+ assert (args->option & MACH_RCV_MSG);
+ /* Disable the message-send, since it has already completed. The
+ calls we retry need only wait to receive the reply message. */
+ args->option &= ~MACH_SEND_MSG;
+
+ state->basic.pc = (int) &&rpc_wait_trampoline;
+ state->basic.r29 = (int) sigsp; /* $29 is the stack pointer register. */
+ /* After doing the message receive, the trampoline code will need to
+ update the v0 ($2) value to be restored by sigreturn. To simplify
+ the assembly code, we pass the address of its slot in SCP to the
+ trampoline code in v1 ($3). */
+ state->basic.r3 = (int) &scp->sc_gpr[1];
+ /* We must preserve the mach_msg_trap args in a0..t2 ($4..$10).
+ Pass the handler args to the trampoline code in s1..s3 ($17..$19). */
+ state->basic.r17 = signo;
+ state->basic.r18 = sigcode;
+ state->basic.r19 = (int) scp;
+ }
+ else
+ {
+ state->basic.pc = (int) &&trampoline;
+ state->basic.r29 = (int) sigsp;
+ state->basic.r4 = signo;
+ state->basic.r5 = sigcode;
+ state->basic.r6 = (int) scp;
+ }
+
+ /* We pass the handler function to the trampoline code in at ($1). */
+ state->basic.r1 = (int) handler;
+ /* In the callee-saved register s0 ($16), we save the SCP value to pass
+ to __sigreturn after the handler returns. */
+ state->basic.r16 = (int) scp;
+
+ return scp;
+
+ /* The trampoline code follows. This is not actually executed as part of
+ this function, it is just convenient to write it that way. */
+
+ rpc_wait_trampoline:
+ /* This is the entry point when we have an RPC reply message to receive
+ before running the handler. The MACH_MSG_SEND bit has already been
+ cleared in the OPTION argument in our registers. For our convenience,
+ $3 points to the sc_gpr[1] member of the sigcontext (saved v0 ($2)). */
+ asm volatile
+ (".set noat; .set noreorder; .set nomacro\n"
+ /* Retry the interrupted mach_msg system call. */
+ "li $2, -25\n" /* mach_msg_trap */
+ "syscall\n"
+ /* When the sigcontext was saved, v0 was MACH_RCV_INTERRUPTED. But
+ now the message receive has completed and the original caller of
+ the RPC (i.e. the code running when the signal arrived) needs to
+ see the final return value of the message receive in v0. So
+ store the new v0 value into the sc_gpr[1] member of the sigcontext
+ (whose address is in v1 to make this code simpler). */
+ "sw $2, ($3)\n"
+ /* Since the argument registers needed to have the mach_msg_trap
+ arguments, we've stored the arguments to the handler function
+ in registers s1..s3 ($17..$19). */
+ "move $4, $17\n"
+ "move $5, $18\n"
+ "move $6, $19\n");
+
+ trampoline:
+ /* Entry point for running the handler normally. The arguments to the
+ handler function are already in the standard registers:
+
+ a0 SIGNO
+ a1 SIGCODE
+ a2 SCP
+ */
+ asm volatile
+ ("jal $1; nop\n" /* Call the handler function. */
+ /* Call __sigreturn (SCP); this cannot return. */
+ "j %0\n"
+ "move $4, $16" /* Set up arg from saved SCP in delay slot. */
+ : : "i" (&__sigreturn));
+
+ /* NOTREACHED */
+ asm volatile (".set reorder; .set at; .set macro");
+
+ return NULL;
+}
+
+/* STATE describes a thread that had intr_port set (meaning it was inside
+ HURD_EINTR_RPC), after it has been thread_abort'd. It it looks to have
+ just completed a mach_msg_trap system call that returned
+ MACH_RCV_INTERRUPTED, return nonzero and set *PORT to the receive right
+ being waited on. */
+int
+_hurdsig_rcv_interrupted_p (struct machine_thread_all_state *state,
+ mach_port_t *port)
+{
+ const unsigned int *const pc = (void *) state->basic.pc;
+
+ if (_hurdsig_catch_fault (SIGSEGV))
+ assert (_hurdsig_fault_sigcode == (long int) pc);
+ else
+ {
+ if (state->basic.r2 == MACH_RCV_INTERRUPTED &&
+ pc[-1] == 0xc) /* syscall */
+ {
+ /* We did just return from a mach_msg_trap system call
+ doing a message receive that was interrupted.
+ Examine the parameters to find the receive right. */
+ struct mach_msg_trap_args *args = (void *) &state->basic.r4;
+
+ *port = args->rcv_name;
+ return 1;
+ }
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/mkdir.c b/sysdeps/mach/hurd/mkdir.c
new file mode 100644
index 0000000000..d477815994
--- /dev/null
+++ b/sysdeps/mach/hurd/mkdir.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+#include <hurd.h>
+
+/* Create a directory named FILE_NAME with protections MODE. */
+int
+DEFUN(__mkdir, (file_name, mode), CONST char *file_name AND mode_t mode)
+{
+ error_t err;
+ const char *name;
+ file_t parent = __file_name_split (file_name, (char **) &name);
+ if (parent == MACH_PORT_NULL)
+ return -1;
+ err = __dir_mkdir (parent, name, mode);
+ __mach_port_deallocate (__mach_task_self (), parent);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__mkdir, mkdir)
diff --git a/sysdeps/mach/hurd/mknod.c b/sysdeps/mach/hurd/mknod.c
new file mode 100644
index 0000000000..cf1b4d021e
--- /dev/null
+++ b/sysdeps/mach/hurd/mknod.c
@@ -0,0 +1,114 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+#include "stdio/_itoa.h"
+#include <string.h>
+
+/* Temporary hack; this belongs in a header file, probably types.h. */
+#define major(x) ((int)(((unsigned) (x) >> 8) & 0xff))
+#define minor(x) ((int)((x) & 0xff))
+
+
+/* Create a device file named FILE_NAME, with permission and special bits MODE
+ and device number DEV (which can be constructed from major and minor
+ device numbers with the `makedev' macro above). */
+int
+DEFUN(__mknod, (file_name, mode, dev),
+ CONST char *file_name AND mode_t mode AND dev_t dev)
+{
+ error_t err;
+ file_t dir, node;
+ char *name;
+ char buf[100], *bp;
+ const char *translator;
+ size_t len;
+
+ if (S_ISCHR (mode))
+ {
+ translator = _HURD_CHRDEV;
+ len = sizeof (_HURD_CHRDEV);
+ }
+ else if (S_ISBLK (mode))
+ {
+ translator = _HURD_BLKDEV;
+ len = sizeof (_HURD_BLKDEV);
+ }
+ else if (S_ISFIFO (mode))
+ {
+ translator = _HURD_FIFO;
+ len = sizeof (_HURD_FIFO);
+ }
+ else
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (! S_ISFIFO (mode))
+ {
+ /* We set the translator to "ifmt\0major\0minor\0", where IFMT
+ depends on the S_IFMT bits of our MODE argument, and MAJOR and
+ MINOR are ASCII decimal (octal or hex would do as well)
+ representations of our arguments. Thus the convention is that
+ CHRDEV and BLKDEV translators are invoked with two non-switch
+ arguments, giving the major and minor device numbers in %i format. */
+
+ bp = buf + sizeof (buf);
+ *--bp = '\0';
+ bp = _itoa (minor (dev), bp, 10, 0);
+ *--bp = '\0';
+ bp = _itoa (major (dev), bp, 10, 0);
+ memcpy (bp - len, translator, len);
+ translator = bp - len;
+ len = buf + sizeof (buf) - translator;
+ }
+
+ dir = __file_name_split (file_name, &name);
+ if (dir == MACH_PORT_NULL)
+ return -1;
+
+ /* Create a new, unlinked node in the target directory. */
+ err = __dir_mkfile (dir, O_WRITE, mode & ~S_IFMT & _hurd_umask, &node);
+
+ if (! err)
+ /* Set the node's translator to make it a device. */
+ err = __file_set_translator (node,
+ FS_TRANS_EXCL | FS_TRANS_SET,
+ FS_TRANS_EXCL | FS_TRANS_SET, 0,
+ translator, len,
+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
+
+ if (! err)
+ /* Link the node, now a valid device, into the target directory. */
+ err = __dir_link (node, dir, name);
+
+ __mach_port_deallocate (__mach_task_self (), dir);
+ __mach_port_deallocate (__mach_task_self (), node);
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__mknod, mknod)
diff --git a/sysdeps/mach/hurd/mmap.c b/sysdeps/mach/hurd/mmap.c
new file mode 100644
index 0000000000..e682225ec8
--- /dev/null
+++ b/sysdeps/mach/hurd/mmap.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Map addresses starting near ADDR and extending for LEN bytes. from
+ OFFSET into the file FD describes according to PROT and FLAGS. If ADDR
+ is nonzero, it is the desired mapping address. If the MAP_FIXED bit is
+ set in FLAGS, the mapping will be at ADDR exactly (which must be
+ page-aligned); otherwise the system chooses a convenient nearby address.
+ The return value is the actual mapping address chosen or (caddr_t) -1
+ for errors (in which case `errno' is set). A successful `mmap' call
+ deallocates any previous mapping for the affected region. */
+
+caddr_t
+mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset)
+{
+ error_t err;
+ vm_prot_t vmprot;
+ memory_object_t memobj;
+ vm_address_t mapaddr;
+
+ vmprot = VM_PROT_NONE;
+ if (prot & PROT_READ)
+ vmprot |= VM_PROT_READ;
+ if (prot & PROT_WRITE)
+ vmprot |= VM_PROT_WRITE;
+ if (prot & PROT_EXEC)
+ vmprot |= VM_PROT_EXECUTE;
+
+ switch (flags & MAP_TYPE)
+ {
+ default:
+ return (caddr_t) (long int) __hurd_fail (EINVAL);
+
+ case MAP_ANON:
+ memobj = MACH_PORT_NULL;
+ break;
+
+ case MAP_FILE:
+ {
+ mach_port_t robj, wobj;
+ if (err = HURD_DPORT_USE (fd, __io_map (port, &robj, &wobj)))
+ return (caddr_t) (long int) __hurd_dfail (fd, err);
+ switch (prot & (PROT_READ|PROT_WRITE))
+ {
+ case PROT_READ:
+ memobj = robj;
+ __mach_port_deallocate (__mach_task_self (), wobj);
+ break;
+ case PROT_WRITE:
+ memobj = wobj;
+ __mach_port_deallocate (__mach_task_self (), robj);
+ break;
+ case PROT_READ|PROT_WRITE:
+ __mach_port_deallocate (__mach_task_self (), robj);
+ if (robj == wobj)
+ memobj = wobj;
+ else
+ {
+ __mach_port_deallocate (__mach_task_self (), wobj);
+ return ((caddr_t) (long int)
+ __hurd_fail (EGRATUITOUS)); /* XXX */
+ }
+ break;
+ }
+ break;
+ /* XXX handle MAP_NOEXTEND */
+ }
+ }
+
+ mapaddr = (vm_address_t) addr;
+ err = __vm_map (__mach_task_self (),
+ &mapaddr, (vm_size_t) len, (vm_address_t) 0,
+ flags & MAP_FIXED,
+ memobj, (vm_offset_t) offset,
+ flags & (MAP_COPY|MAP_PRIVATE),
+ vmprot, VM_PROT_ALL,
+ flags & MAP_INHERIT);
+
+ if (memobj != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (), memobj);
+
+ return err ? (caddr_t) (long int) __hurd_fail (err) : (caddr_t) mapaddr;
+}
+
diff --git a/sysdeps/mach/hurd/open.c b/sysdeps/mach/hurd/open.c
new file mode 100644
index 0000000000..0d22e7f36d
--- /dev/null
+++ b/sysdeps/mach/hurd/open.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Open FILE with access OFLAG. If OFLAG includes O_CREAT,
+ a third argument is the file protection. */
+int
+DEFUN(__open, (file, oflag), CONST char *file AND int oflag DOTS)
+{
+ mode_t mode;
+ io_t port;
+
+ if (oflag & O_CREAT)
+ {
+ va_list arg;
+ va_start (arg, oflag);
+ mode = va_arg (arg, mode_t);
+ va_end (arg);
+ }
+ else
+ mode = 0;
+
+ port = __file_name_lookup (file, oflag, mode);
+ if (port == MACH_PORT_NULL)
+ return -1;
+
+ return _hurd_intern_fd (port, oflag, 1);
+}
+
+weak_alias (__open, open)
diff --git a/sysdeps/mach/hurd/opendir.c b/sysdeps/mach/hurd/opendir.c
new file mode 100644
index 0000000000..d843da8aeb
--- /dev/null
+++ b/sysdeps/mach/hurd/opendir.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <hurd.h>
+
+
+/* Open a directory stream on NAME. */
+DIR *
+DEFUN(opendir, (name), CONST char *name)
+{
+ DIR *dirp;
+ file_t port;
+
+ port = __file_name_lookup (name, O_RDONLY, 0);
+ if (port == MACH_PORT_NULL)
+ return NULL;
+
+ /* XXX this port should be deallocated on exec */
+
+ dirp = (DIR *) malloc (sizeof (DIR));
+ if (dirp == NULL)
+ {
+ __mach_port_deallocate (__mach_task_self (), port);
+ return NULL;
+ }
+
+ dirp->__port = port;
+ dirp->__data = dirp->__ptr = NULL;
+ dirp->__entry_data = dirp->__entry_ptr = 0;
+ dirp->__allocation = 0;
+ dirp->__size = 0;
+
+ return dirp;
+}
diff --git a/sysdeps/mach/hurd/pipe.c b/sysdeps/mach/hurd/pipe.c
new file mode 100644
index 0000000000..07c802f5a0
--- /dev/null
+++ b/sysdeps/mach/hurd/pipe.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stddef.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <sys/socket.h>
+#include <hurd/socket.h>
+#include <fcntl.h>
+
+/* Create a one-way communication channel (pipe).
+ If successul, two file descriptors are stored in FDS;
+ bytes written on FDS[1] can be read from FDS[0].
+ Returns 0 if successful, -1 if not. */
+int
+DEFUN(__pipe, (fds), int fds[2])
+{
+ error_t err;
+ socket_t server, sock1, sock2;
+ int d1, d2;
+
+ if (fds == NULL)
+ return __hurd_fail (EINVAL);
+
+ /* Find the local domain socket server. */
+ server = _hurd_socket_server (PF_LOCAL, 0);
+ if (server == MACH_PORT_NULL)
+ return -1;
+
+ /* Create two local domain sockets and connect them together. */
+
+ err = __socket_create (server, SOCK_STREAM, 0, &sock1);
+ if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
+ {
+ /* On the first use of the socket server during the operation,
+ allow for the old server port dying. */
+ server = _hurd_socket_server (PF_LOCAL, 1);
+ if (server == MACH_PORT_NULL)
+ return -1;
+ err = __socket_create (server, SOCK_STREAM, 0, &sock1);
+ }
+ if (err)
+ return __hurd_fail (err);
+ if (err = __socket_create (server, SOCK_STREAM, 0, &sock2))
+ {
+ __mach_port_deallocate (__mach_task_self (), sock1);
+ return __hurd_fail (err);
+ }
+ if (err = __socket_connect2 (sock1, sock2))
+ {
+ __mach_port_deallocate (__mach_task_self (), sock1);
+ __mach_port_deallocate (__mach_task_self (), sock2);
+ return __hurd_fail (err);
+ }
+
+ /* Shut down the unused sides of the sockets. */
+ __socket_shutdown (sock1, 1);
+ __socket_shutdown (sock2, 0);
+
+ /* Put the sockets into file descriptors. */
+
+ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1);
+ if (d1 < 0)
+ {
+ __mach_port_deallocate (__mach_task_self (), sock2);
+ return -1;
+ }
+ d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1);
+ if (d2 < 0)
+ {
+ err = errno;
+ (void) close (d1);
+ return __hurd_fail (err);
+ }
+
+ fds[0] = d1;
+ fds[1] = d2;
+ return 0;
+}
+
+weak_alias (__pipe, pipe)
diff --git a/sysdeps/mach/hurd/ptrace.c b/sysdeps/mach/hurd/ptrace.c
new file mode 100644
index 0000000000..3d8558734f
--- /dev/null
+++ b/sysdeps/mach/hurd/ptrace.c
@@ -0,0 +1,392 @@
+/* Process tracing interface `ptrace' for GNU Hurd.
+Copyright (C) 1991, 1992, 1993, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+#include <stdarg.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/msg.h>
+#include <thread_state.h>
+
+/* Perform process tracing functions. REQUEST is one of the values
+ in <sys/ptrace.h>, and determines the action to be taken.
+ For all requests except PTRACE_TRACEME, PID specifies the process to be
+ traced.
+
+ PID and the other arguments described above for the various requests should
+ appear (those that are used for the particular request) as:
+ pid_t PID, void *ADDR, int DATA, void *ADDR2
+ after PID. */
+int
+ptrace (enum __ptrace_request request, ... )
+{
+ pid_t pid;
+ void *addr, *addr2;
+ natural_t data;
+ va_list ap;
+
+ /* Read data from PID's address space, from ADDR for DATA bytes. */
+ error_t read_data (task_t task, vm_address_t *ourpage, vm_size_t *size)
+ {
+ /* Read the pages containing the addressed range. */
+ error_t err;
+ *size = round_page (addr + data) - trunc_page (addr);
+ err = __vm_read (task, trunc_page (addr), *size, ourpage, size);
+ return err;
+ }
+
+ /* Fetch the thread port for PID's user thread. */
+ error_t fetch_user_thread (task_t task, thread_t *thread)
+ {
+ thread_t threadbuf[3], *threads = threadbuf;
+ mach_msg_type_number_t nthreads = 3, i;
+ error_t err = __task_threads (task, &threads, &nthreads);
+ if (err)
+ return err;
+ if (nthreads == 0)
+ return EINVAL;
+ *thread = threads[0]; /* Assume user thread is first. */
+ for (i = 1; i < nthreads; ++i)
+ __mach_port_deallocate (__mach_task_self (), threads[i]);
+ if (threads != threadbuf)
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) threads, nthreads * sizeof threads[0]);
+ return 0;
+ }
+
+ /* Fetch a thread state structure from PID and store it at ADDR. */
+ int get_regs (int flavor, mach_msg_type_number_t count)
+ {
+ error_t err;
+ task_t task = __pid2task (pid);
+ thread_t thread;
+ if (task == MACH_PORT_NULL)
+ return -1;
+ err = fetch_user_thread (task, &thread);
+ __mach_port_deallocate (__mach_task_self (), task);
+ if (!err)
+ err = __thread_get_state (thread, flavor, addr, &count);
+ __mach_port_deallocate (__mach_task_self (), thread);
+ return err ? __hurd_fail (err) : 0;
+ }
+
+
+ switch (request)
+ {
+ case PTRACE_TRACEME:
+ /* Make this process be traced. */
+ _hurd_exec_flags |= EXEC_TRACED;
+ break;
+
+ case PTRACE_CONT:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ data = va_arg (ap, int);
+ va_end (ap);
+ {
+ /* Send a DATA signal to PID, telling it to take the signal
+ normally even if it's traced. */
+ error_t err; task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ if (data == SIGKILL)
+ err = __task_terminate (task);
+ else
+ {
+ mach_port_t msgport;
+ err = __USEPORT (PROC, __proc_getmsgport (port, pid, &msgport));
+
+ if (!err && addr != (void *) 1)
+ {
+ /* Move the user thread's PC to ADDR. */
+ thread_t thread;
+ err = fetch_user_thread (task, &thread);
+ if (!err)
+ {
+ struct machine_thread_state state;
+ mach_msg_type_number_t count = MACHINE_THREAD_STATE_COUNT;
+ err = __thread_get_state (thread,
+ MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &state, &count);
+ if (!err)
+ {
+ MACHINE_THREAD_STATE_SET_PC (&state, addr);
+ err = __thread_set_state (thread,
+ MACHINE_THREAD_STATE_FLAVOR,
+ (natural_t *) &state, count);
+ }
+
+ }
+ __mach_port_deallocate (__mach_task_self (), thread);
+ }
+
+ if (! err)
+ /* Tell the process to take the signal (or just resume if 0). */
+ err = __msg_sig_post_untraced (msgport, data, task);
+ __mach_port_deallocate (__mach_task_self (), msgport);
+ }
+ __mach_port_deallocate (__mach_task_self (), task);
+ return err ? __hurd_fail (err) : 0;
+ }
+
+ case PTRACE_KILL:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ va_end (ap);
+ /* SIGKILL always just terminates the task,
+ so normal kill is just the same when traced. */
+ return kill (pid, SIGKILL);
+
+ case PTRACE_SINGLESTEP:
+ /* This is a machine-dependent kernel RPC on
+ machines that support it. Punt. */
+ return EOPNOTSUPP;
+
+ case PTRACE_ATTACH:
+ case PTRACE_DETACH:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ va_end (ap);
+ {
+ /* Tell PID to set or clear its trace bit. */
+ error_t err;
+ mach_port_t msgport;
+ task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ err = __USEPORT (PROC, __proc_getmsgport (port, pid, &msgport));
+ if (! err)
+ {
+ err = (request == PTRACE_ATTACH ?
+ __msg_set_some_exec_flags :
+ __msg_clear_some_exec_flags) (msgport, task, EXEC_TRACED);
+#ifdef notyet /* XXX */
+ if (! err)
+ /* Request (or request an end to) SIGCHLD notification
+ when PID stops or dies, and proc_wait working on PID. */
+ err = __USEPORT (PROC,
+ __proc_trace_pid (port, pid,
+ request == PTRACE_ATTACH));
+#endif
+ if (! err)
+ {
+ if (request == PTRACE_ATTACH)
+ /* Now stop the process. */
+ err = __msg_sig_post (msgport, SIGSTOP, task);
+ else
+ /* Resume the process from tracing stop. */
+ err = __msg_sig_post_untraced (msgport, 0, task);
+ }
+ __mach_port_deallocate (__mach_task_self (), msgport);
+ }
+ __mach_port_deallocate (__mach_task_self (), task);
+ return err ? __hurd_fail (err) : 0;
+ }
+
+ case PTRACE_PEEKTEXT:
+ case PTRACE_PEEKDATA:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ va_end (ap);
+ {
+ /* Read the page (or two pages, if the word lies on a boundary)
+ containing the addressed word. */
+ error_t err;
+ vm_address_t ourpage;
+ vm_size_t size;
+ natural_t word;
+ task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ data = sizeof word;
+ ourpage = 0;
+ size = 0;
+ err = read_data (task, &ourpage, &size);
+ __mach_port_deallocate (__mach_task_self (), task);
+ if (err)
+ return __hurd_fail (err);
+ word = *(natural_t *) ((vm_address_t) addr - trunc_page (addr)
+ + ourpage);
+ __vm_deallocate (__mach_task_self (), ourpage, size);
+ return word;
+ }
+
+ case PTRACE_PEEKUSER:
+ case PTRACE_POKEUSER:
+ /* U area, what's that? */
+ return EOPNOTSUPP;
+
+ case PTRACE_GETREGS:
+ case PTRACE_SETREGS:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ va_end (ap);
+ return get_regs (MACHINE_THREAD_STATE_FLAVOR,
+ MACHINE_THREAD_STATE_COUNT);
+
+ case PTRACE_GETFPREGS:
+ case PTRACE_SETFPREGS:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ va_end (ap);
+#ifdef MACHINE_THREAD_FLOAT_STATE_FLAVOR
+ return get_regs (MACHINE_THREAD_FLOAT_STATE_FLAVOR,
+ MACHINE_THREAD_FLOAT_STATE_COUNT);
+#else
+ return EOPNOTSUPP;
+#endif
+
+ case PTRACE_GETFPAREGS:
+ case PTRACE_SETFPAREGS:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ va_end (ap);
+#ifdef MACHINE_THREAD_FPA_STATE_FLAVOR
+ return get_regs (MACHINE_THREAD_FPA_STATE_FLAVOR,
+ MACHINE_THREAD_FPA_STATE_COUNT);
+#else
+ return EOPNOTSUPP;
+#endif
+
+ case PTRACE_POKETEXT:
+ case PTRACE_POKEDATA:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ data = va_arg (ap, int);
+ va_end (ap);
+ {
+ /* Read the page (or two pages, if the word lies on a boundary)
+ containing the addressed word. */
+ error_t err;
+ vm_address_t ourpage;
+ vm_size_t size;
+ task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ data = sizeof (natural_t);
+ ourpage = 0;
+ size = 0;
+ err = read_data (task, &ourpage, &size);
+
+ if (!err)
+ {
+ /* Now modify the specified word and write the page back. */
+ *(natural_t *) ((vm_address_t) addr - trunc_page (addr)
+ + ourpage) = data;
+ err = __vm_write (task, trunc_page (addr), ourpage, size);
+ __vm_deallocate (__mach_task_self (), ourpage, size);
+ }
+
+ __mach_port_deallocate (__mach_task_self (), task);
+ return err ? __hurd_fail (err) : 0;
+ }
+
+ case PTRACE_READDATA:
+ case PTRACE_READTEXT:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ data = va_arg (ap, int);
+ addr2 = va_arg (ap, void *);
+ va_end (ap);
+ {
+ error_t err;
+ vm_address_t ourpage;
+ vm_size_t size;
+ task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ if (((vm_address_t) addr2 + data) % __vm_page_size == 0)
+ {
+ /* Perhaps we can write directly to the user's buffer. */
+ ourpage = (vm_address_t) addr2;
+ size = data;
+ }
+ else
+ {
+ ourpage = 0;
+ size = 0;
+ }
+ err = read_data (task, &ourpage, &size);
+ __mach_port_deallocate (__mach_task_self (), task);
+ if (!err && ourpage != (vm_address_t) addr2)
+ {
+ memcpy (addr2, (void *) ourpage, data);
+ __vm_deallocate (__mach_task_self (), ourpage, size);
+ }
+ return err ? __hurd_fail (err) : 0;
+ }
+
+ case PTRACE_WRITEDATA:
+ case PTRACE_WRITETEXT:
+ va_start (ap, request);
+ pid = va_arg (ap, pid_t);
+ addr = va_arg (ap, void *);
+ data = va_arg (ap, int);
+ addr2 = va_arg (ap, void *);
+ va_end (ap);
+ {
+ error_t err;
+ vm_address_t ourpage;
+ vm_size_t size;
+ task_t task = __pid2task (pid);
+ if (task == MACH_PORT_NULL)
+ return -1;
+ if ((vm_address_t) addr % __vm_page_size == 0 &&
+ (vm_address_t) data % __vm_page_size == 0)
+ {
+ /* Writing whole pages; can go directly from the user's buffer. */
+ ourpage = (vm_address_t) addr2;
+ size = data;
+ err = 0;
+ }
+ else
+ {
+ /* Read the task's pages and modify our own copy. */
+ ourpage = 0;
+ size = 0;
+ err = read_data (task, &ourpage, &size);
+ if (!err)
+ memcpy ((void *) ((vm_address_t) addr - trunc_page (addr)
+ + ourpage),
+ addr2,
+ data);
+ }
+ if (!err)
+ /* Write back the modified pages. */
+ err = __vm_write (task, trunc_page (addr), ourpage, size);
+ __mach_port_deallocate (__mach_task_self (), task);
+ return err ? __hurd_fail (err) : 0;
+ }
+
+ default:
+ errno = EINVAL;
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/read.c b/sysdeps/mach/hurd/read.c
new file mode 100644
index 0000000000..c7fdaf8a4d
--- /dev/null
+++ b/sysdeps/mach/hurd/read.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Read NBYTES into BUF from FD. Return the number read or -1. */
+ssize_t
+DEFUN(__read, (fd, buf, nbytes),
+ int fd AND PTR buf AND size_t nbytes)
+{
+ error_t err = HURD_FD_USE (fd, _hurd_fd_read (descriptor, buf, &nbytes));
+ return err ? __hurd_dfail (fd, err) : nbytes;
+}
+
+weak_alias (__read, read)
diff --git a/sysdeps/mach/hurd/readdir.c b/sysdeps/mach/hurd/readdir.c
new file mode 100644
index 0000000000..185aeee2b1
--- /dev/null
+++ b/sysdeps/mach/hurd/readdir.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <limits.h>
+#include <stddef.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+
+
+/* Read a directory entry from DIRP. */
+struct dirent *
+DEFUN(readdir, (dirp), DIR *dirp)
+{
+ struct dirent *dp;
+
+ if (dirp == NULL)
+ {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ do
+ {
+ if (dirp->__ptr - dirp->__data >= dirp->__size)
+ {
+ /* We've emptied out our buffer. Refill it. */
+
+ char *data = dirp->__data;
+ int nentries;
+ error_t err;
+
+ if (err = __dir_readdir (dirp->__port, &data, &dirp->__size,
+ dirp->__entry_ptr, -1, 0, &nentries))
+ return __hurd_fail (err), NULL;
+
+ /* DATA now corresponds to entry index DIRP->__entry_ptr. */
+ dirp->__entry_data = dirp->__entry_ptr;
+
+ if (data != dirp->__data)
+ {
+ /* The data was passed out of line, so our old buffer is no
+ longer useful. Deallocate the old buffer and reset our
+ information for the new buffer. */
+ __vm_deallocate (__mach_task_self (),
+ (vm_address_t) dirp->__data,
+ dirp->__allocation);
+ dirp->__data = data;
+ dirp->__allocation = round_page (dirp->__size);
+ }
+
+ /* Reset the pointer into the buffer. */
+ dirp->__ptr = dirp->__data;
+
+ if (nentries == 0)
+ /* End of file. */
+ return NULL;
+
+ /* We trust the filesystem to return correct data and so we
+ ignore NENTRIES. */
+ }
+
+ dp = (struct dirent *) dirp->__ptr;
+ dirp->__ptr += dp->d_reclen;
+ ++dirp->__entry_ptr;
+
+ /* Loop to ignore deleted files. */
+ } while (dp->d_fileno == 0);
+
+ return dp;
+}
diff --git a/sysdeps/mach/hurd/readlink.c b/sysdeps/mach/hurd/readlink.c
new file mode 100644
index 0000000000..2f51e200b5
--- /dev/null
+++ b/sysdeps/mach/hurd/readlink.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+#include <string.h>
+
+/* Read the contents of the symbolic link FILE_NAME into no more than
+ LEN bytes of BUF. The contents are not null-terminated.
+ Returns the number of characters read, or -1 for errors. */
+ssize_t
+DEFUN(__readlink, (file_name, buf, len),
+ CONST char *file_name AND char *buf AND size_t len)
+{
+ error_t err;
+ file_t file;
+ char mybuf[2048], *transp = mybuf;
+ mach_msg_type_number_t translen = sizeof (mybuf);
+
+ file = __file_name_lookup (file_name, O_NOTRANS, 0);
+ if (file == MACH_PORT_NULL)
+ return -1;
+
+ err = __file_get_translator (file, &transp, &translen);
+ __mach_port_deallocate (__mach_task_self (), file);
+
+ if (err)
+ return __hurd_fail (err);
+
+ if (translen < sizeof (_HURD_SYMLINK) ||
+ memcmp (transp, _HURD_SYMLINK, sizeof (_HURD_SYMLINK)))
+ /* The file is not actually a symlink. */
+ err = EINVAL;
+ else
+ {
+ /* This is a symlink; its translator is "/hurd/symlink\0target\0". */
+ if (len >= translen - sizeof (_HURD_SYMLINK))
+ {
+ len = translen - sizeof (_HURD_SYMLINK);
+ if (transp[translen - 1] == '\0')
+ /* Remove the null terminator. */
+ --len;
+ }
+ if (buf == NULL)
+ /* This call is just to find out how large a buffer is required. */
+ len = translen - sizeof (_HURD_SYMLINK) - 1;
+ else
+ /* Copy into the user's buffer. */
+ memcpy (buf, transp + sizeof (_HURD_SYMLINK), len);
+ }
+
+ if (transp != mybuf)
+ __vm_deallocate (__mach_task_self (), (vm_address_t) transp, translen);
+
+ return err ? __hurd_fail (err) : len;
+}
+
+weak_alias (__readlink, readlink)
diff --git a/sysdeps/mach/hurd/reboot.c b/sysdeps/mach/hurd/reboot.c
new file mode 100644
index 0000000000..80356fdf5a
--- /dev/null
+++ b/sysdeps/mach/hurd/reboot.c
@@ -0,0 +1,51 @@
+/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/startup.h>
+
+/* Reboot the system. */
+int
+DEFUN(reboot, (howto), int howto)
+{
+ error_t err;
+ startup_t init;
+ mach_port_t hostpriv, devmaster;
+
+ if (err = __USEPORT (PROC, __proc_getprivports (port,
+ &hostpriv, &devmaster)))
+ return __hurd_fail (err);
+ __mach_port_deallocate (__mach_task_self (), devmaster);
+
+ err = __USEPORT (PROC, __proc_getmsgport (port, 1, &init));
+ if (!err)
+ {
+ err = __startup_reboot (init, hostpriv, howto);
+ __mach_port_deallocate (__mach_task_self (), init);
+ }
+
+ __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+ if (err)
+ return __hurd_fail (err);
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/recv.c b/sysdeps/mach/hurd/recv.c
new file mode 100644
index 0000000000..7d06919c4b
--- /dev/null
+++ b/sysdeps/mach/hurd/recv.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1994 Fremach_msg_type_number_t Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <string.h>
+
+/* Read N bytes into BUF from socket FD.
+ Returns the number read or -1 for errors. */
+int
+DEFUN(recv, (fd, buf, n, flags),
+ int fd AND PTR buf AND size_t n AND int flags)
+{
+ error_t err;
+ mach_port_t addrport;
+ char *bufp = buf;
+ mach_msg_type_number_t nread = n;
+ mach_port_t *ports;
+ mach_msg_type_number_t nports;
+ char *cdata = NULL;
+ mach_msg_type_number_t clen = 0;
+
+ if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport,
+ flags, &bufp, &nread,
+ &ports, &nports,
+ &cdata, &clen,
+ &flags,
+ n)))
+ return __hurd_dfail (fd, err);
+
+ __mach_port_deallocate (__mach_task_self (), addrport);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
+
+ if (bufp != buf)
+ {
+ memcpy (buf, bufp, nread);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, nread);
+ }
+
+ return nread;
+}
diff --git a/sysdeps/mach/hurd/recvfrom.c b/sysdeps/mach/hurd/recvfrom.c
new file mode 100644
index 0000000000..09d45c7cc8
--- /dev/null
+++ b/sysdeps/mach/hurd/recvfrom.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <hurd/socket.h>
+#include <string.h>
+
+/* Read N bytes into BUF through socket FD from peer
+ at address ADDR (which is ADDR_LEN bytes long).
+ Returns the number read or -1 for errors. */
+int
+DEFUN(recvfrom, (fd, buf, n, flags, addr, addr_len),
+ int fd AND PTR buf AND size_t n AND int flags AND
+ struct sockaddr *addr AND size_t *addr_len)
+{
+ error_t err;
+ mach_port_t addrport;
+ char *bufp = buf;
+ mach_msg_type_number_t nread = n;
+ mach_port_t *ports;
+ mach_msg_type_number_t nports;
+ char *cdata = NULL;
+ mach_msg_type_number_t clen = 0;
+
+ if (err = HURD_DPORT_USE (fd, __socket_recv (port, &addrport,
+ flags, &bufp, &nread,
+ &ports, &nports,
+ &cdata, &clen,
+ &flags,
+ n)))
+ return __hurd_dfail (fd, err);
+
+ /* Get address data for the returned address port. */
+ {
+ char *buf = (char *) addr;
+ mach_msg_type_number_t buflen = *addr_len;
+ int type;
+
+ err = __socket_whatis_address (addrport, &type, &buf, &buflen);
+ __mach_port_deallocate (__mach_task_self (), addrport);
+ if (err)
+ return __hurd_dfail (fd, err);
+
+ if (buf != (char *) addr)
+ {
+ if (*addr_len < buflen)
+ *addr_len = buflen;
+ memcpy (addr, buf, *addr_len);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) buf, buflen);
+ }
+
+ addr->sa_family = type;
+ }
+
+ /* Toss control data; we don't care. */
+ __vm_deallocate (__mach_task_self (), (vm_address_t) cdata, clen);
+
+ if (bufp != buf)
+ {
+ memcpy (buf, bufp, nread);
+ __vm_deallocate (__mach_task_self (), (vm_address_t) bufp, nread);
+ }
+
+ return nread;
+}
+
diff --git a/sysdeps/mach/hurd/rename.c b/sysdeps/mach/hurd/rename.c
new file mode 100644
index 0000000000..63efbfb43f
--- /dev/null
+++ b/sysdeps/mach/hurd/rename.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <hurd.h>
+
+/* Rename the file OLD to NEW. */
+int
+DEFUN(rename, (old, new), CONST char *old AND CONST char *new)
+{
+ error_t err;
+ file_t olddir, newdir;
+ const char *oldname, *newname;
+
+ olddir = __file_name_split (old, (char **) &oldname);
+ if (olddir == MACH_PORT_NULL)
+ return -1;
+ newdir = __file_name_split (new, (char **) &newname);
+ if (newdir == MACH_PORT_NULL)
+ {
+ __mach_port_deallocate (__mach_task_self (), olddir);
+ return -1;
+ }
+
+ err = __dir_rename (olddir, oldname, newdir, newname);
+ __mach_port_deallocate (__mach_task_self (), olddir);
+ __mach_port_deallocate (__mach_task_self (), newdir);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/rewinddir.c b/sysdeps/mach/hurd/rewinddir.c
new file mode 100644
index 0000000000..66a11d619f
--- /dev/null
+++ b/sysdeps/mach/hurd/rewinddir.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+
+/* Rewind DIRP to the beginning of the directory. */
+void
+DEFUN(rewinddir, (dirp), DIR *dirp)
+{
+ seekdir (dirp, (off_t) 0L);
+}
diff --git a/sysdeps/mach/hurd/rmdir.c b/sysdeps/mach/hurd/rmdir.c
new file mode 100644
index 0000000000..13a199f5ae
--- /dev/null
+++ b/sysdeps/mach/hurd/rmdir.c
@@ -0,0 +1,41 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Remove the directory FILE_NAME. */
+int
+DEFUN(__rmdir, (file_name), CONST char *file_name)
+{
+ error_t err;
+ const char *name;
+ file_t parent = __file_name_split (file_name, (char **) &name);
+ if (parent == MACH_PORT_NULL)
+ return -1;
+ err = __dir_rmdir (parent, name);
+ __mach_port_deallocate (__mach_task_self (), parent);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__rmdir, rmdir)
diff --git a/sysdeps/mach/hurd/sbrk.c b/sysdeps/mach/hurd/sbrk.c
new file mode 100644
index 0000000000..855cab8a60
--- /dev/null
+++ b/sysdeps/mach/hurd/sbrk.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+
+/* Extend the process's data space by INCREMENT.
+ If INCREMENT is negative, shrink data space by - INCREMENT.
+ Return the address of the start of the new data space, or -1 for errors. */
+PTR
+DEFUN(__sbrk, (increment), int increment)
+{
+ PTR result;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_brk_lock);
+ result = (PTR) _hurd_brk;
+ if (increment != 0 && _hurd_set_brk (_hurd_brk + increment) < 0)
+ result = (PTR) -1;
+ __mutex_unlock (&_hurd_brk_lock);
+ HURD_CRITICAL_END;
+
+ return result;
+}
+
+weak_alias (__sbrk, sbrk)
diff --git a/sysdeps/mach/hurd/seekdir.c b/sysdeps/mach/hurd/seekdir.c
new file mode 100644
index 0000000000..9f585eba63
--- /dev/null
+++ b/sysdeps/mach/hurd/seekdir.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <unistd.h>
+
+/* Seek to position POS in DIRP. */
+void
+DEFUN(seekdir, (dirp, pos), DIR *dirp AND __off_t pos)
+{
+ /* Change our entry index pointer to POS and discard any data already
+ read. The next `readdir' call will notice the empty block and read
+ anew from the location in DIRP->__entry_ptr and reset the other state
+ variables. */
+ dirp->__entry_ptr = pos;
+ dirp->__size = 0;
+}
diff --git a/sysdeps/mach/hurd/select.c b/sysdeps/mach/hurd/select.c
new file mode 100644
index 0000000000..d1c5913cb8
--- /dev/null
+++ b/sysdeps/mach/hurd/select.c
@@ -0,0 +1,275 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/* Check the first NFDS descriptors each in READFDS (if not NULL) for read
+ readiness, in WRITEFDS (if not NULL) for write readiness, and in EXCEPTFDS
+ (if not NULL) for exceptional conditions. If TIMEOUT is not NULL, time out
+ after waiting the interval specified therein. Returns the number of ready
+ descriptors, or -1 for errors. */
+int
+DEFUN(__select, (nfds, readfds, writefds, exceptfds, timeout),
+ int nfds AND fd_set *readfds AND fd_set *writefds AND
+ fd_set *exceptfds AND struct timeval *timeout)
+{
+ int i;
+ mach_port_t port;
+ int got;
+ int *types;
+ struct hurd_userlink *ulink;
+ mach_port_t *ports;
+ struct hurd_fd **cells;
+ error_t err;
+ fd_set rfds, wfds, xfds;
+ int firstfd, lastfd;
+ mach_msg_timeout_t to = (timeout != NULL ?
+ (timeout->tv_sec * 1000 +
+ timeout->tv_usec / 1000) :
+ 0);
+
+ /* Use local copies so we can't crash from user bogosity. */
+ if (readfds == NULL)
+ FD_ZERO (&rfds);
+ else
+ rfds = *readfds;
+ if (writefds == NULL)
+ FD_ZERO (&wfds);
+ else
+ wfds = *writefds;
+ if (exceptfds == NULL)
+ FD_ZERO (&xfds);
+ else
+ xfds = *exceptfds;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_dtable_lock);
+
+ if (nfds > _hurd_dtablesize)
+ nfds = _hurd_dtablesize;
+
+ /* Collect the ports for interesting FDs. */
+ cells = __alloca (nfds * sizeof (*cells));
+ ports = __alloca (nfds * sizeof (*ports));
+ types = __alloca (nfds * sizeof (*types));
+ ulink = __alloca (nfds * sizeof (*ulink));
+ firstfd = lastfd = -1;
+ for (i = 0; i < nfds; ++i)
+ {
+ int type = 0;
+ if (readfds != NULL && FD_ISSET (i, &rfds))
+ type |= SELECT_READ;
+ if (writefds != NULL && FD_ISSET (i, &wfds))
+ type |= SELECT_WRITE;
+ if (exceptfds != NULL && FD_ISSET (i, &xfds))
+ type |= SELECT_URG;
+ types[i] = type;
+ if (type)
+ {
+ cells[i] = _hurd_dtable[i];
+ ports[i] = _hurd_port_get (&cells[i]->port, &ulink[i]);
+ if (ports[i] == MACH_PORT_NULL)
+ {
+ /* If one descriptor is bogus, we fail completely. */
+ while (i-- > 0)
+ _hurd_port_free (&cells[i]->port, &ulink[i], ports[i]);
+ errno = EBADF;
+ break;
+ }
+ lastfd = i;
+ if (firstfd == -1)
+ firstfd = i;
+ }
+ }
+
+ __mutex_unlock (&_hurd_dtable_lock);
+ HURD_CRITICAL_END;
+
+ if (i < nfds)
+ return -1;
+
+ /* Get a port to receive the io_select_reply messages on. */
+ port = __mach_reply_port ();
+
+ /* Send them all io_select request messages. */
+ got = 0;
+ err = 0;
+ for (i = firstfd; i <= lastfd; ++i)
+ if (types[i])
+ {
+ if (!err)
+ {
+ int tag = i;
+ err = __io_select (ports[i], port,
+ /* Poll for each but the last. */
+ (i == lastfd && got == 0) ? to : 0,
+ &types[i], &tag);
+ if (!err)
+ {
+ if (tag != i)
+ err = EGRATUITOUS;
+ else if (types[i] & (SELECT_READ|SELECT_URG|SELECT_WRITE))
+ ++got;
+ }
+ }
+ _hurd_port_free (&cells[i]->port, &ulink[i], ports[i]);
+ }
+
+ /* Now wait for reply messages. */
+ if (!err && got == 0 && port != MACH_PORT_NULL)
+ {
+ /* Now wait for io_select_reply messages on PORT,
+ timing out as appropriate. */
+
+ union
+ {
+ mach_msg_header_t head;
+ struct
+ {
+ mach_msg_header_t head;
+ mach_msg_type_t err_type;
+ error_t err;
+ } error;
+ struct
+ {
+ mach_msg_header_t head;
+ mach_msg_type_t err_type;
+ error_t err;
+ mach_msg_type_t result_type;
+ int result;
+ mach_msg_type_t tag_type;
+ int tag;
+ } success;
+ } msg;
+ mach_msg_option_t options = (timeout == NULL ? 0 : MACH_RCV_TIMEOUT);
+ error_t msgerr;
+ while ((msgerr = __mach_msg (&msg.head,
+ MACH_RCV_MSG | options,
+ sizeof msg, 0, port, to,
+ MACH_PORT_NULL)) == MACH_MSG_SUCCESS)
+ {
+ /* We got a message. Decode it. */
+#define IO_SELECT_REPLY_MSGID (21012 + 100) /* XXX */
+ const mach_msg_type_t inttype =
+ { MACH_MSG_TYPE_INTEGER_32, 32, 1, 1, 0, 0 };
+ if (msg.head.msgh_id == IO_SELECT_REPLY_MSGID &&
+ msg.head.msgh_size >= sizeof msg.error &&
+ !(msg.head.msgh_bits & MACH_MSGH_BITS_COMPLEX) &&
+ *(int *) &msg.error.err_type == *(int *) &inttype)
+ {
+ /* This is a properly formatted message so far.
+ See if it is a success or a failure. */
+ if (msg.error.err)
+ {
+ err = msg.error.err;
+ if (msg.head.msgh_size != sizeof msg.error)
+ __mach_msg_destroy (&msg);
+ }
+ else if (msg.head.msgh_size != sizeof msg.success ||
+ *(int *) &msg.success.tag_type != *(int *) &inttype ||
+ *(int *) &msg.success.result_type != *(int *) &inttype)
+ __mach_msg_destroy (&msg);
+ else if ((msg.success.result &
+ (SELECT_READ|SELECT_WRITE|SELECT_URG)) == 0 ||
+ msg.success.tag < firstfd || msg.success.tag > lastfd)
+ err = EGRATUITOUS;
+ else
+ {
+ /* This is a winning io_select_reply message!
+ Record the readiness it indicates and send a reply. */
+ if (types[msg.success.tag] == 0)
+ /* This descriptor is ready and it was not before,
+ so we increment our count of ready descriptors. */
+ ++got;
+ types[msg.success.tag] |= msg.success.result;
+ }
+ }
+
+ if (msg.head.msgh_remote_port != MACH_PORT_NULL)
+ __mach_port_deallocate (__mach_task_self (),
+ msg.head.msgh_remote_port);
+
+ if (got || err == EINTR)
+ {
+ /* Poll for another message. */
+ to = 0;
+ options |= MACH_RCV_TIMEOUT;
+ }
+ }
+
+ if (err == MACH_RCV_TIMED_OUT)
+ /* This is the normal value for ERR. We might have timed out and
+ read no messages. Otherwise, after receiving the first message,
+ we poll for more messages. We receive with a timeout of 0 to
+ effect a poll, so ERR is MACH_RCV_TIMED_OUT when the poll finds no
+ message waiting. */
+ err = 0;
+
+ if (got && err == EINTR)
+ /* Some calls were interrupted, but at least one descriptor
+ is known to be ready now, so we will return success. */
+ err = 0;
+ }
+
+ if (port != MACH_PORT_NULL)
+ /* We must destroy the port if we made some select requests
+ that might send notification on that port after we no longer care.
+ If the port were reused, that notification could confuse the next
+ select call to use the port. The notification might be valid,
+ but the descriptor may have changed to a different server. */
+ __mach_port_destroy (__mach_task_self (), port);
+
+ if (timeout && got == 0 && err == MACH_RCV_TIMED_OUT)
+ /* No io_select call returned success immediately, and the last call
+ blocked for our full timeout period and then timed out. So the
+ multiplex times out too. */
+ return 0;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Set the user bitarrays. */
+ for (i = 0; i < nfds; ++i)
+ {
+ if (readfds != NULL)
+ if (types[i] & SELECT_READ)
+ FD_SET (i, readfds);
+ else
+ FD_CLR (i, readfds);
+ if (writefds != NULL)
+ if (types[i] & SELECT_WRITE)
+ FD_SET (i, writefds);
+ else
+ FD_CLR (i, writefds);
+ if (exceptfds != NULL)
+ if (types[i] & SELECT_URG)
+ FD_SET (i, exceptfds);
+ else
+ FD_CLR (i, exceptfds);
+ }
+
+ return got;
+}
+
+weak_alias (__select, select)
diff --git a/sysdeps/mach/hurd/send.c b/sysdeps/mach/hurd/send.c
new file mode 100644
index 0000000000..153ee93701
--- /dev/null
+++ b/sysdeps/mach/hurd/send.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+
+/* Send N bytes of BUF to socket FD. Returns the number sent or -1. */
+int
+DEFUN(send, (fd, buf, n, flags),
+ int fd AND PTR buf AND size_t n AND int flags)
+{
+ error_t err;
+ int wrote;
+
+ err = HURD_DPORT_USE (fd, __socket_send (port, MACH_PORT_NULL,
+ flags, buf, n,
+ NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ NULL, 0, &wrote));
+
+ return err ? __hurd_dfail (fd, err) : wrote;
+}
diff --git a/sysdeps/mach/hurd/sendto.c b/sysdeps/mach/hurd/sendto.c
new file mode 100644
index 0000000000..c3d4a4e121
--- /dev/null
+++ b/sysdeps/mach/hurd/sendto.c
@@ -0,0 +1,60 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+
+/* Send N bytes of BUF on socket FD to peer at address ADDR (which is
+ ADDR_LEN bytes long). Returns the number sent, or -1 for errors. */
+int
+DEFUN(sendto, (fd, buf, n, flags, addr, addr_len),
+ int fd AND PTR buf AND size_t n AND int flags AND
+ struct sockaddr *addr AND size_t addr_len)
+{
+ addr_port_t aport;
+ error_t err;
+ int wrote;
+
+ /* Get an address port for the desired destination address. */
+ err = HURD_DPORT_USE (fd,
+ ({
+ err = __socket_create_address (port,
+ addr->sa_family,
+ (char *) addr,
+ addr_len,
+ &aport, 1);
+ if (! err)
+ {
+ /* Send the data. */
+ err = __socket_send (port, aport,
+ flags, buf, n,
+ NULL,
+ MACH_MSG_TYPE_COPY_SEND, 0,
+ NULL, 0, &wrote);
+ __mach_port_deallocate (__mach_task_self (),
+ aport);
+ }
+ err;
+ }));
+
+ return err ? __hurd_dfail (fd, err) : wrote;
+}
diff --git a/sysdeps/mach/hurd/setegid.c b/sysdeps/mach/hurd/setegid.c
new file mode 100644
index 0000000000..8ca4abee06
--- /dev/null
+++ b/sysdeps/mach/hurd/setegid.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <sys/types.h>
+#include <hurd/id.h>
+#include <string.h>
+
+/* Set the effective user ID of the calling process to GID. */
+int
+DEFUN(setegid, (gid), gid_t gid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has EGID as the first element in the
+ list of effective gids. */
+
+ size_t ngen = _hurd_id.gen.ngids < 1 ? 1 : _hurd_id.gen.ngids;
+ gid_t newgen[ngen];
+
+ newgen[0] = gid;
+ memcpy (&newgen[1], _hurd_id.gen.gids, (ngen - 1) * sizeof (gid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ _hurd_id.gen.uids, _hurd_id.gen.nuids,
+ _hurd_id.aux.uids, _hurd_id.aux.nuids,
+ newgen, ngen,
+ _hurd_id.aux.gids, _hurd_id.aux.ngids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
diff --git a/sysdeps/mach/hurd/seteuid.c b/sysdeps/mach/hurd/seteuid.c
new file mode 100644
index 0000000000..9c44c4d275
--- /dev/null
+++ b/sysdeps/mach/hurd/seteuid.c
@@ -0,0 +1,67 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <sys/types.h>
+#include <hurd/id.h>
+#include <string.h>
+
+/* Set the effective user ID of the calling process to UID. */
+int
+DEFUN(seteuid, (uid), uid_t uid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has EUID as the first element in the
+ list of effective uids. */
+
+ size_t ngen = _hurd_id.gen.nuids < 1 ? 1 : _hurd_id.gen.nuids;
+ uid_t newgen[ngen];
+
+ newgen[0] = uid;
+ memcpy (&newgen[1], _hurd_id.gen.uids, (ngen - 1) * sizeof (uid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ newgen, ngen,
+ _hurd_id.aux.uids, _hurd_id.aux.nuids,
+ _hurd_id.gen.gids, _hurd_id.gen.ngids,
+ _hurd_id.aux.gids, _hurd_id.aux.ngids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
diff --git a/sysdeps/mach/hurd/setgid.c b/sysdeps/mach/hurd/setgid.c
new file mode 100644
index 0000000000..726b4130be
--- /dev/null
+++ b/sysdeps/mach/hurd/setgid.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/id.h>
+#include <string.h>
+
+/* Set the group ID of the calling process to UID.
+ If the calling process is the super-user, the real
+ and effective group IDs, and the saved set-group-ID to UID;
+ if not, the effective group ID is set to GID. */
+int
+DEFUN(__setgid, (gid), gid_t gid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has GID as the real gid,
+ and as the first element in the list of effective gids. */
+
+ gid_t newgen[_hurd_id.gen.ngids + 1];
+ gid_t newaux[_hurd_id.aux.ngids];
+
+ newgen[0] = gid;
+ memcpy (&newgen[1], _hurd_id.gen.gids,
+ _hurd_id.gen.ngids * sizeof (gid_t));
+ newaux[0] = gid;
+ memcpy (&newaux[1], _hurd_id.aux.gids,
+ (_hurd_id.aux.ngids - 1) * sizeof (gid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, 0, MACH_MSG_TYPE_COPY_SEND,
+ _hurd_id.gen.uids, _hurd_id.gen.nuids,
+ _hurd_id.aux.uids, _hurd_id.aux.nuids,
+ newgen, 1 + _hurd_id.gen.ngids,
+ newaux, _hurd_id.aux.ngids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
+
+weak_alias (__setgid, setgid)
diff --git a/sysdeps/mach/hurd/setgroups.c b/sysdeps/mach/hurd/setgroups.c
new file mode 100644
index 0000000000..c3431477fb
--- /dev/null
+++ b/sysdeps/mach/hurd/setgroups.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <hurd.h>
+#include <hurd/id.h>
+
+/* Set the group set for the current user to GROUPS (N of them). */
+int
+DEFUN(setgroups, (n, groups), size_t n AND CONST gid_t *groups)
+{
+ error_t err;
+ auth_t newauth;
+ size_t i;
+ gid_t new[n];
+
+ /* Fault before taking locks. */
+ for (i = 0; i < n; ++i)
+ new[i] = groups[i];
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+ if (! err)
+ {
+ /* Get a new auth port using those IDs. */
+ err = __USEPORT (AUTH,
+ __auth_makeauth (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ _hurd_id.gen.uids, _hurd_id.gen.nuids,
+ _hurd_id.aux.uids, _hurd_id.aux.nuids,
+ new, n,
+ _hurd_id.aux.gids, _hurd_id.aux.ngids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new auth port and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
diff --git a/sysdeps/mach/hurd/sethostid.c b/sysdeps/mach/hurd/sethostid.c
new file mode 100644
index 0000000000..dc8153caa6
--- /dev/null
+++ b/sysdeps/mach/hurd/sethostid.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1993 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Set the current machine's Internet number to ID.
+ This call is restricted to the super-user. */
+int
+DEFUN(sethostid, (id), long int id)
+{
+ error_t err = __USEPORT (PROC, __proc_sethostid (port, id));
+ return err ? __hurd_fail (err) : 0;
+}
diff --git a/sysdeps/mach/hurd/sethostname.c b/sysdeps/mach/hurd/sethostname.c
new file mode 100644
index 0000000000..2c019cf99e
--- /dev/null
+++ b/sysdeps/mach/hurd/sethostname.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Set the name of the current host to NAME, which is LEN bytes long.
+ This call is restricted to the super-user. */
+int
+DEFUN(sethostname, (name, len),
+ CONST char *name AND size_t len)
+{
+ error_t err = __USEPORT (PROC, __proc_sethostname (port, name, len));
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/setitimer.c b/sysdeps/mach/hurd/setitimer.c
new file mode 100644
index 0000000000..4351c5ea99
--- /dev/null
+++ b/sysdeps/mach/hurd/setitimer.c
@@ -0,0 +1,332 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stddef.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/msg_request.h>
+#include <mach/message.h>
+
+/* XXX Temporary cheezoid implementation of ITIMER_REAL/SIGALRM. */
+
+spin_lock_t _hurd_itimer_lock = SPIN_LOCK_INITIALIZER;
+struct itimerval _hurd_itimerval; /* Current state of the timer. */
+mach_port_t _hurd_itimer_port; /* Port the timer thread blocks on. */
+thread_t _hurd_itimer_thread; /* Thread waiting for timeout. */
+int _hurd_itimer_thread_suspended; /* Nonzero if that thread is suspended. */
+vm_address_t _hurd_itimer_thread_stack_base; /* Base of its stack. */
+vm_address_t _hurd_itimer_thread_stack_size; /* Size of its stack. */
+struct timeval _hurd_itimer_started; /* Time the thread started waiting. */
+
+static inline void
+subtract_timeval (struct timeval *from, const struct timeval *subtract)
+{
+ from->tv_usec -= subtract->tv_usec;
+ from->tv_sec -= subtract->tv_sec;
+ while (from->tv_usec < 0)
+ {
+ --from->tv_sec;
+ from->tv_usec += 1000000;
+ }
+}
+
+/* Function run by the itimer thread.
+ This code must be very careful not ever to require a MiG reply port. */
+
+static void
+timer_thread (void)
+{
+ while (1)
+ {
+ error_t err;
+ /* The only message we ever expect to receive is the reply from the
+ signal thread to a sig_post call we did. We never examine the
+ contents. */
+ struct
+ {
+ mach_msg_header_t header;
+ error_t return_code;
+ } msg;
+
+ /* Wait for a message on a port that noone sends to. The purpose is
+ the receive timeout. Notice interrupts so that if we are
+ thread_abort'd, we will loop around and fetch new values from
+ _hurd_itimerval. */
+ err = __mach_msg (&msg.header,
+ MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT,
+ 0, 0, _hurd_itimer_port,
+ _hurd_itimerval.it_value.tv_sec * 1000 +
+ _hurd_itimerval.it_value.tv_usec / 1000,
+ MACH_PORT_NULL);
+ switch (err)
+ {
+ case MACH_RCV_TIMED_OUT:
+ /* We got the expected timeout. Send a message to the signal
+ thread to tell it to post a SIGALRM signal. We use
+ _hurd_itimer_port as the reply port just so we will block until
+ the signal thread has frobnicated things to reload the itimer or
+ has terminated this thread. */
+ __msg_sig_post_request (_hurd_msgport,
+ _hurd_itimer_port,
+ MACH_MSG_TYPE_MAKE_SEND_ONCE,
+ SIGALRM, __mach_task_self ());
+ break;
+
+ case MACH_RCV_INTERRUPTED:
+ /* We were thread_abort'd. This is to tell us that
+ _hurd_itimerval has changed and we need to reexamine it
+ and start waiting with the new timeout value. */
+ break;
+
+ case MACH_MSG_SUCCESS:
+ /* We got the reply message from the sig_post_request above.
+ Ignore it and reexamine the timer value. */
+ __mach_msg_destroy (&msg.header); /* Just in case. */
+ break;
+
+ default:
+ /* Unexpected lossage. Oh well, keep trying. */
+ break;
+ }
+ }
+}
+
+/* Forward declaration. */
+static sighandler_t preempt_sigalrm (thread_t thread, int signo,
+ long int sigcode, int sigerror);
+
+/* Called before any normal SIGALRM signal is delivered.
+ Reload the itimer, or disable the itimer. */
+
+static int
+setitimer_locked (const struct itimerval *new, struct itimerval *old,
+ void *crit)
+{
+ struct itimerval newval = *new;
+ struct timeval now, remaining, elapsed;
+ struct timeval old_interval;
+ error_t err;
+
+ inline void kill_itimer_thread (void)
+ {
+ __thread_terminate (_hurd_itimer_thread);
+ __vm_deallocate (__mach_task_self (),
+ _hurd_itimer_thread_stack_base,
+ _hurd_itimer_thread_stack_size);
+ _hurd_itimer_thread = MACH_PORT_NULL;
+ }
+
+ if ((newval.it_value.tv_sec | newval.it_value.tv_usec) != 0)
+ {
+ /* Make sure the itimer thread is set up. */
+
+ if (_hurd_signal_preempt[SIGALRM] == NULL)
+ {
+ static struct hurd_signal_preempt preempt =
+ { preempt_sigalrm, 0, 0, NULL };
+ _hurd_signal_preempt[SIGALRM] = &preempt;
+ }
+
+ if (_hurd_itimer_port == MACH_PORT_NULL)
+ {
+ /* Allocate a receive right that the itimer thread will
+ block waiting for a message on. */
+ if (err = __mach_port_allocate (__mach_task_self (),
+ MACH_PORT_RIGHT_RECEIVE,
+ &_hurd_itimer_port))
+ goto out;
+ }
+
+ if (_hurd_itimer_thread == MACH_PORT_NULL)
+ {
+ /* Start up the itimer thread running `timer_thread' (below). */
+ if (err = __thread_create (__mach_task_self (),
+ &_hurd_itimer_thread))
+ return __hurd_fail (err);
+ _hurd_itimer_thread_stack_base = 0; /* Anywhere. */
+ _hurd_itimer_thread_stack_size = __vm_page_size; /* Small stack. */
+ if (err = __mach_setup_thread (__mach_task_self (),
+ _hurd_itimer_thread,
+ &timer_thread,
+ &_hurd_itimer_thread_stack_base,
+ &_hurd_itimer_thread_stack_size))
+ {
+ __thread_terminate (_hurd_itimer_thread);
+ _hurd_itimer_thread = MACH_PORT_NULL;
+ goto out;
+ }
+ _hurd_itimer_thread_suspended = 1;
+ }
+ }
+
+ if ((newval.it_value.tv_sec | newval.it_value.tv_usec) != 0 || old != NULL)
+ {
+ /* Calculate how much time is remaining for the pending alarm. */
+ if (__gettimeofday (&now, NULL) < 0)
+ {
+ __spin_unlock (&_hurd_itimer_lock);
+ _hurd_critical_section_unlock (crit);
+ return -1;
+ }
+ elapsed = now;
+ subtract_timeval (&elapsed, &_hurd_itimer_started);
+ remaining = _hurd_itimerval.it_value;
+ if (timercmp (&remaining, &elapsed, <))
+ {
+ /* Hmm. The timer should have just gone off, but has not been reset.
+ This is a possible timing glitch. The alarm will signal soon. */
+ /* XXX wrong */
+ remaining.tv_sec = 0;
+ remaining.tv_usec = 0;
+ }
+ else
+ subtract_timeval (&remaining, &elapsed);
+
+ /* Remember the old reload interval before changing it. */
+ old_interval = _hurd_itimerval.it_interval;
+
+ /* Record the starting time that the timer interval relates to. */
+ _hurd_itimer_started = now;
+ }
+
+ /* Load the new itimer value. */
+ _hurd_itimerval = newval;
+
+ if ((newval.it_value.tv_sec | newval.it_value.tv_usec) == 0)
+ {
+ /* Disable the itimer. */
+ if (_hurd_itimer_thread && !_hurd_itimer_thread_suspended)
+ {
+ /* Suspend the itimer thread so it does nothing. Then abort its
+ kernel context so that when the thread is resumed, mach_msg
+ will return to timer_thread (below) and it will fetch new
+ values from _hurd_itimerval. */
+ if ((err = __thread_suspend (_hurd_itimer_thread)) ||
+ (err = __thread_abort (_hurd_itimer_thread)))
+ /* If we can't save it for later, nuke it. */
+ kill_itimer_thread ();
+ else
+ _hurd_itimer_thread_suspended = 1;
+ }
+ }
+ /* See if the timeout changed. If so, we must alert the itimer thread. */
+ else if (remaining.tv_sec != new->it_value.tv_sec ||
+ remaining.tv_usec != new->it_value.tv_usec)
+ {
+ /* The timeout value is changing. Tell the itimer thread to
+ reexamine it and start counting down. If the itimer thread is
+ marked as suspended, either we just created it, or it was
+ suspended and thread_abort'd last time the itimer was disabled;
+ either way it will wake up and start waiting for the new timeout
+ value when we resume it. If it is not suspended, the itimer
+ thread is waiting to deliver a pending alarm that we will override
+ (since it would come later than the new alarm being set);
+ thread_abort will make mach_msg return MACH_RCV_INTERRUPTED, so it
+ will loop around and use the new timeout value. */
+ if (err = (_hurd_itimer_thread_suspended
+ ? __thread_resume : __thread_abort) (_hurd_itimer_thread))
+ {
+ kill_itimer_thread ();
+ goto out;
+ }
+ _hurd_itimer_thread_suspended = 0;
+ }
+
+ __spin_unlock (&_hurd_itimer_lock);
+ _hurd_critical_section_unlock (crit);
+
+ if (old != NULL)
+ {
+ old->it_value = remaining;
+ old->it_interval = old_interval;
+ }
+ return 0;
+
+ out:
+ __spin_unlock (&_hurd_itimer_lock);
+ _hurd_critical_section_unlock (crit);
+ return __hurd_fail (err);
+}
+
+/* Set the timer WHICH to *NEW. If OLD is not NULL,
+ set *OLD to the old value of timer WHICH.
+ Returns 0 on success, -1 on errors. */
+int
+DEFUN(__setitimer, (which, new, old),
+ enum __itimer_which which AND
+ struct itimerval *new AND struct itimerval *old)
+{
+ void *crit;
+
+ switch (which)
+ {
+ default:
+ return __hurd_fail (EINVAL);
+
+ case ITIMER_VIRTUAL:
+ case ITIMER_PROF:
+ return __hurd_fail (ENOSYS);
+
+ case ITIMER_REAL:
+ break;
+ }
+
+ crit = _hurd_critical_section_lock ();
+ __spin_lock (&_hurd_itimer_lock);
+ return setitimer_locked (new, old, crit);
+}
+
+static sighandler_t
+preempt_sigalrm (thread_t thread, int signo, long int sigcode, int sigerror)
+{
+ struct itimerval it;
+
+ if (thread != _hurd_sigthread || signo != SIGALRM || sigcode != 0)
+ /* Too much monkey business. */
+ return SIG_DFL;
+
+ /* Either reload or disable the itimer. */
+ __spin_lock (&_hurd_itimer_lock);
+ it = _hurd_itimerval;
+ it.it_value = it.it_interval;
+ setitimer_locked (&it, NULL, NULL);
+
+ /* Continue with normal delivery of SIGALRM. */
+ return SIG_DFL;
+}
+
+static void
+fork_itimer (void)
+{
+ /* We must restart the itimer in the child. */
+
+ struct itimerval it;
+
+ __spin_lock (&_hurd_itimer_lock);
+ _hurd_itimer_thread = MACH_PORT_NULL;
+ it = _hurd_itimerval;
+ it.it_value = it.it_interval;
+
+ setitimer_locked (&it, NULL, NULL);
+}
+text_set_element (_hurd_fork_child_hook, fork_itimer);
+
+weak_alias (__setitimer, setitimer)
diff --git a/sysdeps/mach/hurd/setlogin.c b/sysdeps/mach/hurd/setlogin.c
new file mode 100644
index 0000000000..867d8e25c9
--- /dev/null
+++ b/sysdeps/mach/hurd/setlogin.c
@@ -0,0 +1,32 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Set the login name returned by `getlogin'. */
+int
+DEFUN(setlogin, (name), CONST char *name)
+{
+ error_t err;
+ if (err = __USEPORT (PROC, __proc_setlogin (port, name)))
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/setpgid.c b/sysdeps/mach/hurd/setpgid.c
new file mode 100644
index 0000000000..7c74ef8a4c
--- /dev/null
+++ b/sysdeps/mach/hurd/setpgid.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+
+/* Set the process group ID of the process matching PID to PGID.
+ If PID is zero, the current process's process group ID is set.
+ If PGID is zero, the process ID of the process is used. */
+int
+DEFUN(__setpgid, (pid, pgid), pid_t pid AND pid_t pgid)
+{
+ error_t err;
+ unsigned int stamp;
+
+ stamp = _hurd_pids_changed_stamp; /* Atomic fetch. */
+
+ if (err = __USEPORT (PROC, __proc_setpgrp (port, pid, pgid)))
+ return __hurd_fail (err);
+
+ if (pid == 0 || pid == _hurd_pid)
+ /* Synchronize with the signal thread to make sure we have
+ received and processed proc_newids before returning to the user. */
+ while (_hurd_pids_changed_stamp == stamp)
+ {
+#ifdef noteven
+ /* XXX we have no need for a mutex, but cthreads demands one. */
+ __condition_wait (&_hurd_pids_changed_sync, NULL);
+#else
+ __swtch_pri(0);
+#endif
+ }
+
+ return 0;
+
+}
+
+weak_alias (__setpgid, setpgid)
+weak_alias (__setpgid, setpgrp)
diff --git a/sysdeps/mach/hurd/setpriority.c b/sysdeps/mach/hurd/setpriority.c
new file mode 100644
index 0000000000..644bfdf6fe
--- /dev/null
+++ b/sysdeps/mach/hurd/setpriority.c
@@ -0,0 +1,85 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <hurd.h>
+#include <hurd/resource.h>
+
+/* Set the priority of all processes specified by WHICH and WHO
+ to PRIO. Returns 0 on success, -1 on errors. */
+int
+setpriority (enum __priority_which which, int who, int prio)
+{
+ error_t err;
+ error_t pidloser, priloser;
+ unsigned int npids, ntasks, nwin, nperm, nacces;
+
+ error_t setonepriority (pid_t pid, struct procinfo *pi)
+ {
+ task_t task;
+ error_t piderr = __USEPORT (PROC, __proc_pid2task (port, pid, &task));
+ if (piderr == EPERM)
+ ++nperm;
+ if (piderr != ESRCH)
+ {
+ ++npids;
+ if (piderr && piderr != EPERM)
+ pidloser = piderr;
+ }
+ if (! piderr)
+ {
+ error_t prierr;
+ ++ntasks;
+ prierr = __task_priority (task, NICE_TO_MACH_PRIORITY (prio), 1);
+ __mach_port_deallocate (__mach_task_self (), task);
+ switch (prierr)
+ {
+ case KERN_FAILURE:
+ ++nacces;
+ break;
+ case KERN_SUCCESS:
+ ++nwin;
+ break;
+ case KERN_INVALID_ARGUMENT: /* Task died. */
+ --npids;
+ --ntasks;
+ break;
+ default:
+ priloser = prierr;
+ }
+ }
+ return 0;
+ }
+
+ npids = ntasks = nwin = nperm = nacces = 0;
+ pidloser = priloser = 0;
+ err = _hurd_priority_which_map (which, who, setonepriority);
+
+ if (!err && npids == 0)
+ /* No error, but no pids found. */
+ err = ESRCH;
+ else if (nperm == npids)
+ /* Got EPERM from proc_task2pid for every process. */
+ err = EPERM;
+ else if (nacces == ntasks)
+ /* Got KERN_FAILURE from task_priority for every task. */
+ err = EACCES;
+ else if (nwin == 0)
+ err = pidloser ?: priloser;
+
+ return err ? __hurd_fail (err) : 0;
+}
diff --git a/sysdeps/mach/hurd/setregid.c b/sysdeps/mach/hurd/setregid.c
new file mode 100644
index 0000000000..8b76f7008a
--- /dev/null
+++ b/sysdeps/mach/hurd/setregid.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+#include <string.h>
+
+int
+__setregid (gid_t rgid, gid_t egid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has RGID as the real gid,
+ and EGID as the first element in the list of effective gids. */
+
+ size_t ngen = _hurd_id.gen.ngids < 1 ? 1 : _hurd_id.gen.ngids;
+ size_t naux = _hurd_id.aux.ngids < 1 ? 1 : _hurd_id.aux.ngids;
+ gid_t newaux[naux], newgen[ngen];
+
+ newgen[0] = egid;
+ memcpy (&newgen[1], _hurd_id.gen.gids, (ngen - 1) * sizeof (gid_t));
+ newaux[0] = rgid;
+ memcpy (&newaux[1], _hurd_id.aux.gids, (naux - 1) * sizeof (gid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ _hurd_id.gen.gids, _hurd_id.gen.ngids,
+ _hurd_id.aux.gids, _hurd_id.aux.ngids,
+ newgen, ngen,
+ newaux, naux,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
+
+weak_alias (__setregid, setregid)
diff --git a/sysdeps/mach/hurd/setreuid.c b/sysdeps/mach/hurd/setreuid.c
new file mode 100644
index 0000000000..1dcbf0ee82
--- /dev/null
+++ b/sysdeps/mach/hurd/setreuid.c
@@ -0,0 +1,71 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/id.h>
+#include <string.h>
+
+int
+__setreuid (uid_t ruid, uid_t euid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has RUID as the real uid,
+ and EUID as the first element in the list of effective uids. */
+
+ size_t ngen = _hurd_id.gen.nuids < 1 ? 1 : _hurd_id.gen.nuids;
+ size_t naux = _hurd_id.aux.nuids < 1 ? 1 : _hurd_id.aux.nuids;
+ uid_t newaux[naux], newgen[ngen];
+
+ newgen[0] = euid;
+ memcpy (&newgen[1], _hurd_id.gen.uids, (ngen - 1) * sizeof (uid_t));
+ newaux[0] = ruid;
+ memcpy (&newaux[1], _hurd_id.aux.uids, (naux - 1) * sizeof (uid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, MACH_MSG_TYPE_COPY_SEND, 0,
+ newgen, ngen,
+ newaux, naux,
+ _hurd_id.gen.gids, _hurd_id.gen.ngids,
+ _hurd_id.aux.gids, _hurd_id.aux.ngids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
+
+weak_alias (__setreuid, setreuid)
diff --git a/sysdeps/mach/hurd/setrlimit.c b/sysdeps/mach/hurd/setrlimit.c
new file mode 100644
index 0000000000..6d60d6dd57
--- /dev/null
+++ b/sysdeps/mach/hurd/setrlimit.c
@@ -0,0 +1,58 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <hurd.h>
+#include <hurd/resource.h>
+#include <errno.h>
+#include <hurd/fd.h>
+
+
+/* Set the soft and hard limits for RESOURCE to *RLIMITS.
+ Only the super-user can increase hard limits.
+ Return 0 if successful, -1 if not (and sets errno). */
+int
+DEFUN(setrlimit, (resource, rlimits),
+ enum __rlimit_resource resource AND struct rlimit *rlimits)
+{
+ struct rlimit lim;
+
+ if (rlimits == NULL || (unsigned int) resource >= RLIMIT_NLIMITS)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ lim = *rlimits;
+
+ if (lim.rlim_max != RLIM_INFINITY)
+ {
+ /* We have no enforceable resource limits. */
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (lim.rlim_cur > lim.rlim_max)
+ lim.rlim_cur = lim.rlim_max;
+
+ __mutex_lock (&_hurd_rlimit_lock);
+ _hurd_rlimits[resource] = lim;
+ __mutex_unlock (&_hurd_rlimit_lock);
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/setsid.c b/sysdeps/mach/hurd/setsid.c
new file mode 100644
index 0000000000..22dc965344
--- /dev/null
+++ b/sysdeps/mach/hurd/setsid.c
@@ -0,0 +1,59 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/port.h>
+
+
+/* Create a new session with the calling process as its leader.
+ The process group IDs of the session and the calling process
+ are set to the process ID of the calling process, which is returned. */
+int
+DEFUN_VOID(__setsid)
+{
+ error_t err;
+ unsigned int stamp;
+
+ stamp = _hurd_pids_changed_stamp; /* Atomic fetch. */
+
+ /* Tell the proc server we want to start a new session. */
+ if (err = __USEPORT (PROC, __proc_setsid (port)))
+ return __hurd_fail (err);
+
+ /* Punt our current ctty. */
+ _hurd_setcttyid (MACH_PORT_NULL);
+
+ /* Synchronize with the signal thread to make sure we have
+ received and processed proc_newids before returning to the user. */
+ while (_hurd_pids_changed_stamp == stamp)
+ {
+#ifdef noteven
+ /* XXX we have no need for a mutex, but cthreads demands one. */
+ __condition_wait (&_hurd_pids_changed_sync, NULL);
+#else
+ __swtch_pri(0);
+#endif
+ }
+
+ return 0;
+}
+
+weak_alias (__setsid, setsid)
diff --git a/sysdeps/mach/hurd/setsockopt.c b/sysdeps/mach/hurd/setsockopt.c
new file mode 100644
index 0000000000..4d527696fe
--- /dev/null
+++ b/sysdeps/mach/hurd/setsockopt.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+
+/* Set socket FD's option OPTNAME at protocol level LEVEL
+ to *OPTVAL (which is OPTLEN bytes long).
+ Returns 0 on success, -1 for errors. */
+int
+DEFUN(setsockopt, (fd, level, optname, optval, optlen),
+ int fd AND int level AND int optname AND
+ PTR optval AND size_t optlen)
+{
+ error_t err = HURD_DPORT_USE (fd, __socket_setopt (port,
+ level, optname,
+ optval, optlen));
+ if (err)
+ return __hurd_dfail (fd, err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/settimeofday.c b/sysdeps/mach/hurd/settimeofday.c
new file mode 100644
index 0000000000..1747a443a4
--- /dev/null
+++ b/sysdeps/mach/hurd/settimeofday.c
@@ -0,0 +1,56 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <hurd.h>
+#include <hurd/port.h>
+
+/* Set the current time of day and timezone information.
+ This call is restricted to the super-user. */
+int
+DEFUN(__settimeofday, (tv, tz),
+ CONST struct timeval *tv AND CONST struct timezone *tz)
+{
+ error_t err;
+ mach_port_t hostpriv, devmaster;
+
+ if (tz != NULL)
+ {
+ errno = ENOSYS;
+ return -1;
+ }
+
+ if (err = __USEPORT (PROC, __proc_getprivports (port,
+ &hostpriv, &devmaster)))
+ return __hurd_fail (err);
+ __mach_port_deallocate (__mach_task_self (), devmaster);
+
+ /* `time_value_t' and `struct timeval' are in fact identical with the
+ names changed. */
+ err = __host_set_time (hostpriv, *(time_value_t *) tv);
+ __mach_port_deallocate (__mach_task_self (), hostpriv);
+
+ if (err)
+ return __hurd_fail (err);
+
+ return 0;
+}
+
+weak_alias (__settimeofday, settimeofday)
diff --git a/sysdeps/mach/hurd/setuid.c b/sysdeps/mach/hurd/setuid.c
new file mode 100644
index 0000000000..7084038b0b
--- /dev/null
+++ b/sysdeps/mach/hurd/setuid.c
@@ -0,0 +1,76 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <hurd/id.h>
+#include <string.h>
+
+/* Set the user ID of the calling process to UID.
+ If the calling process is the super-user, the real
+ and effective user IDs, and the saved set-user-ID to UID;
+ if not, the effective user ID is set to UID. */
+int
+DEFUN(__setuid, (uid), uid_t uid)
+{
+ auth_t newauth;
+ error_t err;
+
+ HURD_CRITICAL_BEGIN;
+ __mutex_lock (&_hurd_id.lock);
+ err = _hurd_check_ids ();
+
+ if (!err)
+ {
+ /* Make a new auth handle which has UID as the real uid,
+ and as the first element in the list of effective uids. */
+
+ uid_t newgen[_hurd_id.gen.nuids + 1];
+ uid_t newaux[_hurd_id.aux.nuids];
+
+ newgen[0] = uid;
+ memcpy (&newgen[1], _hurd_id.gen.uids,
+ _hurd_id.gen.nuids * sizeof (uid_t));
+ newaux[0] = uid;
+ memcpy (&newaux[1], _hurd_id.aux.uids,
+ (_hurd_id.aux.nuids - 1) * sizeof (uid_t));
+
+ err = __USEPORT (AUTH, __auth_makeauth
+ (port, NULL, 0, MACH_MSG_TYPE_COPY_SEND,
+ _hurd_id.gen.uids, _hurd_id.gen.nuids,
+ _hurd_id.aux.uids, _hurd_id.aux.nuids,
+ newgen, 1 + _hurd_id.gen.nuids,
+ newaux, _hurd_id.aux.nuids,
+ &newauth));
+ }
+ __mutex_unlock (&_hurd_id.lock);
+ HURD_CRITICAL_END;
+
+ if (err)
+ return __hurd_fail (err);
+
+ /* Install the new handle and reauthenticate everything. */
+ err = __setauth (newauth);
+ __mach_port_deallocate (__mach_task_self (), newauth);
+ return err;
+}
+
+weak_alias (__setuid, setuid)
diff --git a/sysdeps/mach/hurd/shutdown.c b/sysdeps/mach/hurd/shutdown.c
new file mode 100644
index 0000000000..685057b709
--- /dev/null
+++ b/sysdeps/mach/hurd/shutdown.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+
+/* Shut down all or part of the connection open on socket FD.
+ HOW determines what to shut down:
+ 0 = No more receptions;
+ 1 = No more transmissions;
+ 2 = No more receptions or transmissions.
+ Returns 0 on success, -1 for errors. */
+int
+DEFUN(shutdown, (fd, how),
+ int fd AND int how)
+{
+ error_t err = HURD_DPORT_USE (fd, __socket_shutdown (port, how));
+ if (err)
+ return __hurd_dfail (fd, err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/sigaction.c b/sysdeps/mach/hurd/sigaction.c
new file mode 100644
index 0000000000..91de02cd17
--- /dev/null
+++ b/sysdeps/mach/hurd/sigaction.c
@@ -0,0 +1,84 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <signal.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+
+/* If ACT is not NULL, change the action for SIG to *ACT.
+ If OACT is not NULL, put the old action for SIG in *OACT. */
+int
+DEFUN(__sigaction, (sig, act, oact),
+ int sig AND CONST struct sigaction *act AND struct sigaction *oact)
+{
+ struct hurd_sigstate *ss;
+ struct sigaction a, old;
+ sigset_t pending;
+
+ if (sig <= 0 || sig >= NSIG ||
+ (act != NULL && act->sa_handler != SIG_DFL &&
+ ((__sigmask (sig) & _SIG_CANT_MASK) ||
+ act->sa_handler == SIG_ERR)))
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* Copy so we fault before taking locks. */
+ if (act != NULL)
+ a = *act;
+
+ ss = _hurd_self_sigstate ();
+
+ __spin_lock (&ss->lock);
+ old = ss->actions[sig];
+ if (act != NULL)
+ ss->actions[sig] = a;
+
+ if (act != NULL && sig == SIGCHLD)
+ {
+ ss->critical_section = 1;
+ __spin_unlock (&ss->lock);
+
+ /* Inform the proc server whether or not it should send us SIGCHLD for
+ stopped children. We do this in a critical section so that no
+ SIGCHLD can arrive in the middle and be of indeterminate status. */
+ __USEPORT (PROC,
+ __proc_mod_stopchild (port, !(a.sa_flags & SA_NOCLDSTOP)));
+
+ __spin_lock (&ss->lock);
+ ss->critical_section = 0;
+ pending = ss->pending & ~ss->blocked;
+ }
+ else
+ pending = 0;
+
+ __spin_unlock (&ss->lock);
+
+ if (pending)
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+
+ if (oact != NULL)
+ *oact = old;
+
+ return 0;
+}
+
+weak_alias (__sigaction, sigaction)
diff --git a/sysdeps/mach/hurd/sigaltstack.c b/sysdeps/mach/hurd/sigaltstack.c
new file mode 100644
index 0000000000..c4a905213c
--- /dev/null
+++ b/sysdeps/mach/hurd/sigaltstack.c
@@ -0,0 +1,62 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+
+/* Run signals handlers on the stack specified by SS (if not NULL).
+ If OSS is not NULL, it is filled in with the old signal stack status. */
+int
+DEFUN(sigaltstack, (ss, oss),
+ CONST struct sigaltstack *argss AND struct sigaltstack *oss)
+{
+ struct hurd_sigstate *s;
+ struct sigaltstack ss, old;
+
+ /* Fault before taking any locks. */
+ if (argss != NULL)
+ ss = *argss;
+ if (oss != NULL)
+ *(volatile struct sigaltstack *) oss = *oss;
+
+ s = _hurd_self_sigstate ();
+ __spin_lock (&s->lock);
+
+ if (argss != NULL &&
+ (ss.ss_flags & SA_DISABLE) && (s->sigaltstack.ss_flags & SA_ONSTACK))
+ {
+ /* Can't disable a stack that is in use. */
+ __spin_unlock (&s->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ old = s->sigaltstack;
+
+ if (argss != NULL)
+ s->sigaltstack = ss;
+
+ __spin_unlock (&s->lock);
+
+ if (oss != NULL)
+ *oss = old;
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/sigpending.c b/sysdeps/mach/hurd/sigpending.c
new file mode 100644
index 0000000000..8c12ed0bbf
--- /dev/null
+++ b/sysdeps/mach/hurd/sigpending.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+
+
+/* Store in SET all signals that are blocked and pending. */
+int
+DEFUN(sigpending, (set), sigset_t *set)
+{
+ struct hurd_sigstate *ss;
+ sigset_t pending;
+
+ if (set == NULL)
+ {
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss = _hurd_self_sigstate ();
+ __spin_lock (&ss->lock);
+ pending = ss->pending;
+ __spin_unlock (&ss->lock);
+
+ *set = pending;
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/sigprocmask.c b/sysdeps/mach/hurd/sigprocmask.c
new file mode 100644
index 0000000000..bae3266708
--- /dev/null
+++ b/sysdeps/mach/hurd/sigprocmask.c
@@ -0,0 +1,87 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <signal.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/msg.h>
+
+
+/* If SET is not NULL, modify the current set of blocked signals
+ according to HOW, which may be SIG_BLOCK, SIG_UNBLOCK or SIG_SETMASK.
+ If OSET is not NULL, store the old set of blocked signals in *OSET. */
+int
+DEFUN(__sigprocmask, (how, set, oset),
+ int how AND CONST sigset_t *set AND sigset_t *oset)
+{
+ struct hurd_sigstate *ss;
+ sigset_t old, new;
+ sigset_t pending;
+
+ if (set != NULL)
+ new = *set;
+
+ ss = _hurd_self_sigstate ();
+
+ __spin_lock (&ss->lock);
+
+ old = ss->blocked;
+
+ if (set != NULL)
+ {
+ switch (how)
+ {
+ case SIG_BLOCK:
+ ss->blocked |= new;
+ break;
+
+ case SIG_UNBLOCK:
+ ss->blocked &= ~new;
+ break;
+
+ case SIG_SETMASK:
+ ss->blocked = new;
+ break;
+
+ default:
+ __spin_unlock (&ss->lock);
+ errno = EINVAL;
+ return -1;
+ }
+
+ ss->blocked &= ~_SIG_CANT_MASK;
+ }
+
+ pending = ss->pending & ~ss->blocked;
+
+ __spin_unlock (&ss->lock);
+
+ if (oset != NULL)
+ *oset = old;
+
+ if (pending)
+ /* Send a message to the signal thread so it
+ will wake up and check for pending signals. */
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+
+ return 0;
+}
+
+weak_alias (__sigprocmask, sigprocmask)
diff --git a/sysdeps/mach/hurd/sigstack.c b/sysdeps/mach/hurd/sigstack.c
new file mode 100644
index 0000000000..77803ab012
--- /dev/null
+++ b/sysdeps/mach/hurd/sigstack.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1992 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <signal.h>
+#include <hurd.h>
+
+/* Run signals handlers on the stack specified by SS (if not NULL).
+ If OSS is not NULL, it is filled in with the old signal stack status. */
+int
+DEFUN(sigstack, (ss, oss),
+ CONST struct sigstack *ss AND struct sigstack *oss)
+{
+ struct sigaltstack as, oas;
+
+ as.ss_sp = ss->ss_sp;
+ as.ss_size = 0;
+ as.ss_flags = 0;
+
+ if (sigaltstack (&as, &oas) < 0)
+ return -1;
+
+ if (oss != NULL)
+ {
+ oss->ss_sp = oas.ss_sp;
+ oss->ss_onstack = oas.ss_flags & SA_ONSTACK;
+ }
+
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/sigsuspend.c b/sysdeps/mach/hurd/sigsuspend.c
new file mode 100644
index 0000000000..aa0b2876a4
--- /dev/null
+++ b/sysdeps/mach/hurd/sigsuspend.c
@@ -0,0 +1,81 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/signal.h>
+#include <hurd/msg.h>
+
+/* Change the set of blocked signals to SET,
+ wait until a signal arrives, and restore the set of blocked signals. */
+int
+DEFUN(sigsuspend, (set), CONST sigset_t *set)
+{
+ struct hurd_sigstate *ss;
+ sigset_t newmask, oldmask, pending;
+ mach_port_t wait;
+ mach_msg_header_t msg;
+
+ if (set != NULL)
+ /* Crash before locking. */
+ newmask = *set;
+
+ /* Get a fresh port we will wait on. */
+ wait = __mach_reply_port ();
+
+ ss = _hurd_self_sigstate ();
+
+ __spin_lock (&ss->lock);
+
+ oldmask = ss->blocked;
+ if (set != NULL)
+ /* Change to the new blocked signal mask. */
+ ss->blocked = newmask & ~_SIG_CANT_MASK;
+
+ /* Notice if any pending signals just became unblocked. */
+ pending = ss->pending & ~ss->blocked;
+
+ /* Tell the signal thread to message us when a signal arrives. */
+ ss->suspended = wait;
+ __spin_unlock (&ss->lock);
+
+ if (pending)
+ /* Tell the signal thread to check for pending signals. */
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+
+ /* Wait for the signal thread's message. */
+ __mach_msg (&msg, MACH_RCV_MSG, 0, sizeof (msg), wait,
+ MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
+ __mach_port_destroy (__mach_task_self (), wait);
+
+ __spin_lock (&ss->lock);
+ ss->blocked = oldmask; /* Restore the old mask. */
+ pending = ss->pending & ~ss->blocked; /* Again check for pending signals. */
+ __spin_unlock (&ss->lock);
+
+ if (pending)
+ /* Tell the signal thread to check for pending signals. */
+ __msg_sig_post (_hurd_msgport, 0, __mach_task_self ());
+
+ /* We've been interrupted! And a good thing, too.
+ Otherwise we'd never return.
+ That's right; this function always returns an error. */
+ errno = EINTR;
+ return -1;
+}
diff --git a/sysdeps/mach/hurd/socket.c b/sysdeps/mach/hurd/socket.c
new file mode 100644
index 0000000000..b779360780
--- /dev/null
+++ b/sysdeps/mach/hurd/socket.c
@@ -0,0 +1,57 @@
+/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+#include <fcntl.h>
+
+/* Create a new socket of type TYPE in domain DOMAIN, using
+ protocol PROTOCOL. If PROTOCOL is zero, one is chosen automatically.
+ Returns a file descriptor for the new socket, or -1 for errors. */
+int
+DEFUN(socket, (domain, type, protocol),
+ int domain AND enum __socket_type type AND int protocol)
+{
+ error_t err;
+ socket_t sock, server;
+
+ /* Find the socket server for DOMAIN. */
+ server = _hurd_socket_server (domain, 0);
+ if (server == MACH_PORT_NULL)
+ return -1;
+
+ err = __socket_create (server, type, protocol, &sock);
+ if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
+ {
+ /* On the first use of the socket server during the operation,
+ allow for the old server port dying. */
+ server = _hurd_socket_server (domain, 1);
+ if (server == MACH_PORT_NULL)
+ return -1;
+ err = __socket_create (server, type, protocol, &sock);
+ }
+
+ if (err)
+ return __hurd_fail (err);
+
+ return _hurd_intern_fd (sock, O_IGNORE_CTTY, 1);
+}
diff --git a/sysdeps/mach/hurd/socketpair.c b/sysdeps/mach/hurd/socketpair.c
new file mode 100644
index 0000000000..c4d09c707a
--- /dev/null
+++ b/sysdeps/mach/hurd/socketpair.c
@@ -0,0 +1,93 @@
+/* Copyright (C) 1992, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <hurd.h>
+#include <hurd/socket.h>
+#include <hurd/fd.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+/* Create two new sockets, of type TYPE in domain DOMAIN and using
+ protocol PROTOCOL, which are connected to each other, and put file
+ descriptors for them in FDS[0] and FDS[1]. If PROTOCOL is zero,
+ one will be chosen automatically. Returns 0 on success, -1 for errors. */
+int
+DEFUN(socketpair, (domain, type, protocol, fds),
+ int domain AND enum __socket_type type AND int protocol AND int fds[2])
+{
+ error_t err;
+ socket_t server, sock1, sock2;
+ int d1, d2;
+
+ if (fds == NULL)
+ return __hurd_fail (EINVAL);
+
+ /* Find the domain's socket server. */
+ server = _hurd_socket_server (domain, 0);
+ if (server == MACH_PORT_NULL)
+ return -1;
+
+ /* Create two sockets and connect them together. */
+
+ err = __socket_create (server, type, protocol, &sock1);
+ if (err == MACH_SEND_INVALID_DEST || err == MIG_SERVER_DIED)
+ {
+ /* On the first use of the socket server during the operation,
+ allow for the old server port dying. */
+ server = _hurd_socket_server (domain, 1);
+ if (server == MACH_PORT_NULL)
+ return -1;
+ err = __socket_create (server, type, protocol, &sock1);
+ }
+ if (err)
+ return __hurd_fail (err);
+ if (err = __socket_create (server, type, protocol, &sock2))
+ {
+ __mach_port_deallocate (__mach_task_self (), sock1);
+ return __hurd_fail (err);
+ }
+ if (err = __socket_connect2 (sock1, sock2))
+ {
+ __mach_port_deallocate (__mach_task_self (), sock1);
+ __mach_port_deallocate (__mach_task_self (), sock2);
+ return __hurd_fail (err);
+ }
+
+ /* Put the sockets into file descriptors. */
+
+ d1 = _hurd_intern_fd (sock1, O_IGNORE_CTTY, 1);
+ if (d1 < 0)
+ {
+ __mach_port_deallocate (__mach_task_self (), sock2);
+ return -1;
+ }
+ d2 = _hurd_intern_fd (sock2, O_IGNORE_CTTY, 1);
+ if (d2 < 0)
+ {
+ err = errno;
+ (void) close (d1);
+ return __hurd_fail (err);
+ }
+
+ fds[0] = d1;
+ fds[1] = d2;
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/start.c b/sysdeps/mach/hurd/start.c
new file mode 100644
index 0000000000..91be7eaefe
--- /dev/null
+++ b/sysdeps/mach/hurd/start.c
@@ -0,0 +1,316 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <hurd.h>
+#include <hurd/exec.h>
+#include <sysdep.h>
+#include <hurd/threadvar.h>
+#include "set-hooks.h"
+#include "hurdmalloc.h" /* XXX */
+
+/* The first piece of initialized data. */
+int __data_start = 0;
+weak_alias (__data_start, data_start)
+
+mach_port_t *_hurd_init_dtable;
+mach_msg_type_number_t _hurd_init_dtablesize;
+
+unsigned int __hurd_threadvar_max;
+unsigned long int __hurd_threadvar_stack_mask;
+unsigned long int __hurd_threadvar_stack_offset;
+
+/* These are set up by _hurdsig_init. */
+unsigned long int __hurd_sigthread_stack_base;
+unsigned long int __hurd_sigthread_stack_end;
+unsigned long int *__hurd_sigthread_variables;
+
+vm_address_t _hurd_stack_base;
+vm_size_t _hurd_stack_size;
+
+char **__environ;
+weak_alias (__environ, environ)
+
+/* Things that want to be run before _hurd_init or much anything else.
+ Importantly, these are called before anything tries to use malloc. */
+DEFINE_HOOK (_hurd_preinit_hook, (void));
+
+extern void __mach_init (void);
+extern void __libc_init (int argc, char **argv, char **envp);
+extern int main (int argc, char **argv, char **envp);
+
+void *(*_cthread_init_routine) (void); /* Returns new SP to use. */
+void (*_cthread_exit_routine) (int status) __attribute__ ((__noreturn__));
+
+int _hurd_split_args (char *, size_t, char **);
+
+/* These communicate values from _start to start1,
+ where we cannot use the stack for anything. */
+static char *args, *env;
+static mach_port_t *portarray;
+static int *intarray;
+static mach_msg_type_number_t argslen, envlen, portarraysize, intarraysize;
+static int flags;
+static char **argv, **envp;
+static int argc;
+
+
+static void start1 (void) __attribute__ ((__noreturn__));
+
+
+/* Entry point. This is the first thing in the text segment.
+
+ The exec server started the initial thread in our task with this spot the
+ PC, and a stack that is presumably big enough. We do basic Mach
+ initialization so mig-generated stubs work, and then do an exec_startup
+ RPC on our bootstrap port, to which the exec server responds with the
+ information passed in the exec call, as well as our original bootstrap
+ port, and the base address and size of the preallocated stack.
+
+ If using cthreads, we are given a new stack by cthreads initialization and
+ deallocate the stack set up by the exec server. On the new stack we call
+ `start1' (above) to do the rest of the startup work. Since the stack may
+ disappear out from under us in a machine-dependent way, we use a pile of
+ static variables to communicate the information from exec_startup to start1.
+ This is unfortunate but preferable to machine-dependent frobnication to copy
+ the state from the old stack to the new one. */
+
+#ifndef START_ARGS
+#define START_ARGS void
+#endif
+#ifdef START_MACHDEP
+START_MACHDEP
+#define _start _start0
+#endif
+
+void
+_start (START_ARGS)
+{
+ error_t err;
+ mach_port_t in_bootstrap;
+
+ /* Basic Mach initialization, must be done before RPCs can be done. */
+ __mach_init ();
+
+ /* Run things that want to do initialization as soon as possible. We do
+ this before exec_startup so that no out of line data arrives and
+ clutters up the address space before brk initialization. */
+
+ RUN_HOOK (_hurd_preinit_hook, ());
+
+ if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
+ &in_bootstrap))
+ LOSE;
+
+ if (in_bootstrap != MACH_PORT_NULL)
+ {
+ /* Call the exec server on our bootstrap port and
+ get all our standard information from it. */
+
+ argslen = envlen = 0;
+ _hurd_init_dtablesize = portarraysize = intarraysize = 0;
+
+ err = __exec_startup (in_bootstrap,
+ &_hurd_stack_base, &_hurd_stack_size,
+ &flags,
+ &args, &argslen, &env, &envlen,
+ &_hurd_init_dtable, &_hurd_init_dtablesize,
+ &portarray, &portarraysize,
+ &intarray, &intarraysize);
+ __mach_port_deallocate (__mach_task_self (), in_bootstrap);
+ }
+
+ if (err || in_bootstrap == MACH_PORT_NULL)
+ {
+ /* Either we have no bootstrap port, or the RPC to the exec server
+ failed. Try to snarf the args in the canonical Mach way.
+ Hopefully either they will be on the stack as expected, or the
+ stack will be zeros so we don't crash. Set all our other
+ variables to have empty information. */
+
+ /* SNARF_ARGS (ARGC, ARGV, ENVP) snarfs the arguments and environment
+ from the stack, assuming they were put there by the microkernel. */
+ SNARF_ARGS (argc, argv, envp);
+
+ flags = 0;
+ args = env = NULL;
+ argslen = envlen = 0;
+ _hurd_init_dtable = NULL;
+ _hurd_init_dtablesize = 0;
+ portarray = NULL;
+ portarraysize = 0;
+ intarray = NULL;
+ intarraysize = 0;
+ }
+ else
+ argv = envp = NULL;
+
+
+ /* The user might have defined a value for this, to get more variables.
+ Otherwise it will be zero on startup. We must make sure it is set
+ properly before before cthreads initialization, so cthreads can know
+ how much space to leave for thread variables. */
+ if (__hurd_threadvar_max < _HURD_THREADVAR_MAX)
+ __hurd_threadvar_max = _HURD_THREADVAR_MAX;
+
+ /* Do cthreads initialization and switch to the cthread stack. */
+
+ if (_cthread_init_routine != NULL)
+ CALL_WITH_SP (start1, (*_cthread_init_routine) ());
+ else
+ start1 ();
+
+ /* Should never get here. */
+ LOSE;
+}
+
+
+static void
+start1 (void)
+{
+ register int envc = 0;
+
+ {
+ /* Check if the stack we are now on is different from
+ the one described by _hurd_stack_{base,size}. */
+
+ char dummy;
+ const vm_address_t newsp = (vm_address_t) &dummy;
+
+ if (_hurd_stack_size != 0 && (newsp < _hurd_stack_base ||
+ newsp - _hurd_stack_base > _hurd_stack_size))
+ /* The new stack pointer does not intersect with the
+ stack the exec server set up for us, so free that stack. */
+ __vm_deallocate (__mach_task_self (),
+ _hurd_stack_base, _hurd_stack_size);
+ }
+
+ if (__hurd_threadvar_stack_mask == 0)
+ {
+ /* We are not using cthreads, so we will have just a single allocated
+ area for the per-thread variables of the main user thread. */
+ unsigned long int i;
+ __hurd_threadvar_stack_offset
+ = (unsigned long int) malloc (__hurd_threadvar_max *
+ sizeof (unsigned long int));
+ if (__hurd_threadvar_stack_offset == 0)
+ __libc_fatal ("Can't allocate single-threaded per-thread variables.");
+ for (i = 0; i < __hurd_threadvar_max; ++i)
+ ((unsigned long int *) __hurd_threadvar_stack_offset)[i] = 0;
+ }
+
+
+ /* Turn the block of null-separated strings we were passed for the
+ arguments and environment into vectors of pointers to strings. */
+
+ if (! argv)
+ {
+ if (args)
+ /* Count up the arguments so we can allocate ARGV. */
+ argc = _hurd_split_args (args, argslen, NULL);
+ if (! args || argc == 0)
+ {
+ /* No arguments passed; set argv to { NULL }. */
+ argc = 0;
+ args = NULL;
+ argv = (char **) &args;
+ }
+ }
+
+ if (! envp)
+ {
+ if (env)
+ /* Count up the environment variables so we can allocate ENVP. */
+ envc = _hurd_split_args (env, envlen, NULL);
+ if (! env || envc == 0)
+ {
+ /* No environment passed; set __environ to { NULL }. */
+ env = NULL;
+ envp = (char **) &env;
+ }
+ }
+
+ if (! argv)
+ {
+ /* There were some arguments.
+ Allocate space for the vectors of pointers and fill them in. */
+ argv = __alloca ((argc + 1) * sizeof (char *));
+ _hurd_split_args (args, argslen, argv);
+ }
+
+ if (! envp)
+ {
+ /* There was some environment.
+ Allocate space for the vectors of pointers and fill them in. */
+ envp = __alloca ((envc + 1) * sizeof (char *));
+ _hurd_split_args (env, envlen, envp);
+ }
+
+ __environ = envp;
+
+ if (portarray || intarray)
+ /* Initialize library data structures, start signal processing, etc. */
+ _hurd_init (flags, argv, portarray, portarraysize, intarray, intarraysize);
+
+ /* Random library initialization. These functions may assume that
+ _hurd_init has already run (if it is going to), and POSIX.1 facilities
+ are initialized and available. */
+ __libc_init (argc, argv, __environ);
+
+ /* Finally, run the user program. */
+ (_cthread_exit_routine != NULL ? *_cthread_exit_routine : exit)
+ (main (argc, argv, __environ));
+
+ /* Should never get here. */
+ LOSE;
+}
+
+/* Split ARGSLEN bytes at ARGS into words, breaking at NUL characters. If
+ ARGV is not a null pointer, store a pointer to the start of each word in
+ ARGV[n], and null-terminate ARGV. Return the number of words split. */
+
+int
+_hurd_split_args (char *args, size_t argslen, char **argv)
+{
+ char *p = args;
+ size_t n = argslen;
+ int argc = 0;
+
+ while (n > 0)
+ {
+ char *end = memchr (p, '\0', n);
+
+ if (argv)
+ argv[argc] = p;
+ ++argc;
+
+ if (end == NULL)
+ /* The last argument is unterminated. */
+ break;
+
+ n -= end + 1 - p;
+ p = end + 1;
+ }
+
+ if (argv)
+ argv[argc] = NULL;
+ return argc;
+}
diff --git a/sysdeps/mach/hurd/stat.c b/sysdeps/mach/hurd/stat.c
new file mode 100644
index 0000000000..e6df5e66eb
--- /dev/null
+++ b/sysdeps/mach/hurd/stat.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stddef.h>
+#include <hurd.h>
+
+/* Get file information about FILE in BUF. */
+int
+DEFUN(__stat, (file, buf), CONST char *file AND struct stat *buf)
+{
+ error_t err;
+ file_t port = __file_name_lookup (file, 0, 0);
+ if (port == MACH_PORT_NULL)
+ return -1;
+ err = __io_stat (port, buf);
+ __mach_port_deallocate (__mach_task_self (), port);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__stat, stat)
diff --git a/sysdeps/mach/hurd/statbuf.h b/sysdeps/mach/hurd/statbuf.h
new file mode 100644
index 0000000000..4d97dc1c55
--- /dev/null
+++ b/sysdeps/mach/hurd/statbuf.h
@@ -0,0 +1,119 @@
+/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#ifndef _STATBUF_H
+
+#define _STATBUF_H 1
+
+#include <gnu/types.h>
+
+/* NOTE: The size of this structure (32 ints) is known in
+ <hurd/hurd_types.defs>, since it is used in the `io_stat' RPC. MiG
+ does not cope at all well with the passed C structure not being of
+ the expected size. There are some filler words at the end to allow
+ for future expansion. To increase the size of the structure used
+ in the RPC and retain binary compatibility, we would need to assign
+ a new message number. */
+
+struct stat
+ {
+ int st_fstype; /* File system type. */
+ __fsid_t st_fsid; /* File system ID. */
+#define st_dev st_fsid
+
+ __ino_t st_ino; /* File number. */
+ unsigned int st_gen; /* To detect reuse of file numbers. */
+ __dev_t st_rdev; /* Device if special file. */
+ __mode_t st_mode; /* File mode. */
+ __nlink_t st_nlink; /* Number of links. */
+
+ __uid_t st_uid; /* Owner. */
+ __gid_t st_gid; /* Owning group. */
+
+ __off_t st_size; /* Size in bytes. */
+
+ __time_t st_atime; /* Access time, seconds */
+ unsigned long int st_atime_usec; /* and microseconds. */
+ __time_t st_mtime; /* Modification time, seconds */
+ unsigned long int st_mtime_usec; /* and microseconds. */
+ __time_t st_ctime; /* Status change time, seconds */
+ unsigned long int st_ctime_usec; /* and microseconds. */
+
+ unsigned int st_blksize; /* Optimal size for I/O. */
+
+#define _STATBUF_ST_BLKSIZE /* Tell code we have this member. */
+
+ unsigned int st_blocks; /* Number of 512-byte blocks allocated.
+ Not related to `st_blksize'. */
+
+ __uid_t st_author; /* File author. */
+
+ unsigned int st_flags; /* User-defined flags.
+ High 16 bits can be set only by root. */
+
+ int st_spare[11]; /* Room for future expansion. */
+ };
+
+/* Encoding of the file mode. */
+
+#define __S_IFMT 0170000 /* These bits determine file type. */
+
+/* File types. */
+#define __S_IFDIR 0040000 /* Directory. */
+#define __S_IFCHR 0020000 /* Character device. */
+#define __S_IFBLK 0060000 /* Block device. */
+#define __S_IFREG 0100000 /* Regular file. */
+#define __S_IFLNK 0120000 /* Symbolic link. */
+#define __S_IFSOCK 0140000 /* Socket. */
+#define __S_IFIFO 0010000 /* FIFO. */
+
+/* Protection bits. */
+
+#define __S_ISUID 04000 /* Set user ID on execution. */
+#define __S_ISGID 02000 /* Set group ID on execution. */
+#define __S_ISVTX 01000 /* Save swapped text after use (sticky). */
+#define __S_IREAD 00400 /* Read by owner. */
+#define __S_IWRITE 00200 /* Write by owner. */
+#define __S_IEXEC 00100 /* Execute by owner. */
+
+
+#ifdef __USE_GNU
+/* If set, there is no benefit in caching the contents of this file. */
+#define S_INOCACHE 000000200000
+
+/* If the S_IUSEUNK bit is set, then the S_IUNKNOWN bits (see below)
+ control access for unknown users. If S_IUSEUNK is clear, then unknown
+ users are treated as "others" for purposes of access control. */
+#define S_IUSEUNK 000000400000
+/* Mask of protection bits for unknown users (no effective IDs at all). */
+#define S_IUNKNOWN 000007000000
+/* Shift S_IREAD, S_IWRITE, S_IEXEC left this many bits to produce the
+ protection bits for unknown users. */
+#define S_IUNKSHIFT 12
+
+/* All the unused bits. */
+#define S_ISPARE (~(S_IFMT|S_INOCACHE|S_IUNKNOWN|07777))
+#endif
+
+/* Default file creation mask (umask). */
+#ifdef __USE_BSD
+#define CMASK 0022
+#endif
+
+
+#endif /* statbuf.h */
diff --git a/sysdeps/mach/hurd/stdio_init.c b/sysdeps/mach/hurd/stdio_init.c
new file mode 100644
index 0000000000..f083ee85dc
--- /dev/null
+++ b/sysdeps/mach/hurd/stdio_init.c
@@ -0,0 +1,63 @@
+/* Copyright (C) 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <hurd/fd.h>
+#include <hurd/io.h>
+#include <hurd/term.h>
+
+/* Initialize STREAM as necessary.
+ This may change I/O functions, give a buffer, etc.
+ If no buffer is allocated, but the bufsize is set,
+ the bufsize will be used to allocate the buffer. */
+void
+DEFUN(__stdio_init_stream, (stream), FILE *stream)
+{
+ struct hurd_fd *const d = stream->__cookie;
+ struct stat statb;
+ error_t err;
+
+ if (stream->__buffer != NULL || stream->__userbuf)
+ /* If's unbuffered by request, we can't do anything useful. */
+ return;
+
+ /* Find out what sort of file this is. */
+ if (err = HURD_FD_PORT_USE (d, __io_stat (port, &statb)))
+ return;
+
+ if (S_ISCHR (statb.st_mode))
+ {
+ /* It's a character device.
+ Make it line-buffered if it's a terminal. */
+ mach_port_t cttyid;
+ err = HURD_FD_PORT_USE (d, __term_getctty (port, &cttyid));
+ if (! err)
+ {
+ __mach_port_deallocate (__mach_task_self (), cttyid);
+ stream->__linebuf = 1;
+ }
+ }
+
+ /* Use the block-size field to determine
+ the system's optimal buffering size. */
+ stream->__bufsize = statb.st_blksize;
+}
diff --git a/sysdeps/mach/hurd/symlink.c b/sysdeps/mach/hurd/symlink.c
new file mode 100644
index 0000000000..5e67c4e452
--- /dev/null
+++ b/sysdeps/mach/hurd/symlink.c
@@ -0,0 +1,68 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <string.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/paths.h>
+#include <fcntl.h>
+
+/* Make a link to FROM called TO. */
+int
+DEFUN(__symlink, (from, to), CONST char *from AND CONST char *to)
+{
+ error_t err;
+ file_t dir, node;
+ char *name;
+ const size_t len = strlen (from) + 1;
+ char buf[sizeof (_HURD_SYMLINK) + len];
+
+ /* A symlink is a file whose translator is "/hurd/symlink\0target\0". */
+
+ memcpy (buf, _HURD_SYMLINK, sizeof (_HURD_SYMLINK));
+ memcpy (&buf[sizeof (_HURD_SYMLINK)], from, len);
+
+ dir = __file_name_split (to, &name);
+ if (dir == MACH_PORT_NULL)
+ return -1;
+
+ /* Create a new, unlinked node in the target directory. */
+ err = __dir_mkfile (dir, O_WRITE, 0777 & ~_hurd_umask, &node);
+
+ if (! err)
+ /* Set the node's translator to make it a symlink. */
+ err = __file_set_translator (node,
+ FS_TRANS_EXCL|FS_TRANS_SET,
+ FS_TRANS_EXCL|FS_TRANS_SET, 0,
+ buf, sizeof (_HURD_SYMLINK) + len,
+ MACH_PORT_NULL, MACH_MSG_TYPE_COPY_SEND);
+
+ if (! err)
+ /* Link the node, now a valid symlink, into the target directory. */
+ err = __dir_link (node, dir, name);
+
+ __mach_port_deallocate (__mach_task_self (), dir);
+ __mach_port_deallocate (__mach_task_self (), node);
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__symlink, symlink)
diff --git a/sysdeps/mach/hurd/sync.c b/sysdeps/mach/hurd/sync.c
new file mode 100644
index 0000000000..af207e6cdf
--- /dev/null
+++ b/sysdeps/mach/hurd/sync.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+
+/* Make all changes done to all files actually appear on disk. */
+int
+DEFUN_VOID(sync)
+{
+ /* This is not actually synchronous; we don't wait. */
+ error_t err = __USEPORT (CRDIR, __file_syncfs (port, 0, 1));
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/sys/param.h b/sysdeps/mach/hurd/sys/param.h
new file mode 100644
index 0000000000..79f3b0503a
--- /dev/null
+++ b/sysdeps/mach/hurd/sys/param.h
@@ -0,0 +1,135 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+/* This file is deprecated and is provided only for compatibility with
+ Unix systems. It is unwise to include this file on programs which
+ are intended only for GNU systems.
+
+ Parts from:
+
+ * Copyright (c) 1982, 1986, 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)param.h 7.23 (Berkeley) 5/6/91
+ */
+
+
+#ifndef _SYS_PARAM_H
+
+#define _SYS_PARAM_H 1
+#include <features.h>
+
+#define __need_NULL
+#include <stddef.h>
+
+#include <sys/types.h>
+#include <errno.h>
+#include <signal.h>
+#include <endian.h>
+#include <limits.h>
+#ifdef notyet
+#include <ufs/param.h>
+#endif
+
+
+/* What versions of BSD we are compatible with. */
+#define BSD 199306 /* System version (year & month). */
+#define BSD4_3 1
+#define BSD4_4 1
+
+#define GNU 1994100 /* GNU version (year, month, and release). */
+
+
+/* BSD names for some <limits.h> values. We do not define the BSD names
+ for the values which are not statically limited, such as NOFILE. */
+
+#define NGROUPS NGROUPS_MAX
+#define MAXSYMLINKS SYMLOOP_MAX
+#define CANBSIZ MAX_CANON /* XXX ? */
+
+/* ARG_MAX is unlimited, but we define NCARGS for BSD programs that want to
+ compare against some fixed limit. */
+#define NCARGS INT_MAX
+
+/* There is nothing quite equivalent in GNU to Unix "mounts", but there is
+ no limit on the number of simultaneously attached filesystems. */
+#define NMOUNT INT_MAX
+
+
+/* Magical constants. */
+#define NOGROUP 65535 /* Marker for empty group set member. */
+#define NODEV ((dev_t) -1) /* Non-existent device. */
+
+
+/* Bit map related macros. */
+#define setbit(a,i) ((a)[(i)/NBBY] |= 1<<((i)%NBBY))
+#define clrbit(a,i) ((a)[(i)/NBBY] &= ~(1<<((i)%NBBY)))
+#define isset(a,i) ((a)[(i)/NBBY] & (1<<((i)%NBBY)))
+#define isclr(a,i) (((a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0)
+
+/* Macros for counting and rounding. */
+#ifndef howmany
+#define howmany(x, y) (((x)+((y)-1))/(y))
+#endif
+#define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
+#define powerof2(x) ((((x)-1)&(x))==0)
+
+/* Macros for min/max. */
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#define MAX(a,b) (((a)>(b))?(a):(b))
+
+
+/* Scale factor for scaled integers used to count %cpu time and load avgs.
+
+ The number of CPU `tick's that map to a unique `%age' can be expressed
+ by the formula (1 / (2 ^ (FSHIFT - 11))). The maximum load average that
+ can be calculated (assuming 32 bits) can be closely approximated using
+ the formula (2 ^ (2 * (16 - FSHIFT))) for (FSHIFT < 15). */
+
+#define FSHIFT 11 /* Bits to right of fixed binary point. */
+#define FSCALE (1<<FSHIFT)
+
+#endif /* sys/param.h */
diff --git a/sysdeps/mach/hurd/sysd-stdio.c b/sysdeps/mach/hurd/sysd-stdio.c
new file mode 100644
index 0000000000..85dd04bad4
--- /dev/null
+++ b/sysdeps/mach/hurd/sysd-stdio.c
@@ -0,0 +1,237 @@
+/* Copyright (C) 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <hurd.h>
+#include <fcntl.h>
+#include <hurd/fd.h>
+
+
+/* Check ERR for wanting to generate a signal. */
+
+int __stdio_fileno (void *);
+
+static inline int
+fd_fail (struct hurd_fd *fd, error_t err)
+{
+ int signo = _hurd_fd_error_signal (err);
+ if (signo)
+ _hurd_raise_signal (NULL, signo, __stdio_fileno (fd), err);
+ errno = err;
+ return -1;
+}
+
+
+/* Read up to N chars into BUF from COOKIE.
+ Return how many chars were read, 0 for EOF or -1 for error. */
+ssize_t
+DEFUN(__stdio_read, (cookie, buf, n),
+ PTR cookie AND register char *buf AND size_t n)
+{
+ error_t err;
+ struct hurd_fd *fd = cookie;
+
+ if (! fd)
+ return __hurd_fail (EBADF);
+
+ if (err = _hurd_fd_read (fd, buf, &n))
+ return fd_fail (fd, err);
+
+ return n;
+}
+
+/* Write up to N chars from BUF to COOKIE.
+ Return how many chars were written or -1 for error. */
+ssize_t
+DEFUN(__stdio_write, (cookie, buf, n),
+ PTR cookie AND register CONST char *buf AND size_t n)
+{
+ error_t err;
+ size_t wrote, nleft;
+ struct hurd_fd *fd = cookie;
+
+ if (! fd)
+ return __hurd_fail (EBADF);
+
+ nleft = n;
+ do
+ {
+ wrote = nleft;
+ if (err = _hurd_fd_write (fd, buf, &wrote))
+ return fd_fail (fd, err);
+ buf += wrote;
+ nleft -= wrote;
+ } while (nleft > 0);
+
+ return wrote;
+}
+
+/* Move COOKIE's file position *POS bytes, according to WHENCE.
+ The current file position is stored in *POS.
+ Returns zero if successful, nonzero if not. */
+int
+DEFUN(__stdio_seek, (cookie, pos, whence),
+ PTR cookie AND fpos_t *pos AND int whence)
+{
+ error_t err;
+ struct hurd_fd *fd = cookie;
+ if (! fd)
+ return __hurd_fail (EBADF);
+ err = HURD_FD_PORT_USE (fd, __io_seek (port, *pos, whence, pos));
+ return err ? fd_fail (fd, err) : 0;
+}
+
+/* Close the file associated with COOKIE.
+ Return 0 for success or -1 for failure. */
+int
+DEFUN(__stdio_close, (cookie), PTR cookie)
+{
+ error_t error = cookie ? _hurd_fd_close (cookie) : EBADF;
+ return error ? fd_fail (cookie, error) : 0;
+}
+
+
+static inline int
+modeflags (__io_mode m)
+{
+ int flags = 0;
+ if (m.__read)
+ flags |= O_READ;
+ if (m.__write)
+ flags |= O_WRITE;
+ if (m.__append)
+ flags |= O_APPEND;
+ if (m.__create)
+ flags |= O_CREAT;
+ if (m.__truncate)
+ flags |= O_TRUNC;
+ if (m.__exclusive)
+ flags |= O_EXCL;
+ return flags;
+}
+
+/* Open FILENAME with the mode in M. */
+int
+DEFUN(__stdio_open, (filename, m, cookieptr),
+ CONST char *filename AND __io_mode m AND PTR *cookieptr)
+{
+ int flags;
+ file_t port;
+ struct hurd_fd *d;
+
+ flags = modeflags (m);
+ port = __file_name_lookup (filename, flags, 0666 & ~_hurd_umask);
+ if (port == MACH_PORT_NULL)
+ return -1;
+
+ HURD_CRITICAL_BEGIN;
+ d = _hurd_alloc_fd (NULL, 0);
+ if (d != NULL)
+ {
+ _hurd_port2fd (d, port, flags);
+ __spin_unlock (&d->port.lock);
+ }
+ HURD_CRITICAL_END;
+
+ *cookieptr = d;
+ return 0;
+}
+
+
+/* Open FILENAME with the mode in M. Use the same magic cookie
+ already in *COOKIEPTR if possible, closing the old cookie with CLOSEFN. */
+int
+DEFUN(__stdio_reopen, (filename, m, cookieptr),
+ CONST char *filename AND __io_mode m AND
+ PTR *cookieptr AND __io_close_fn closefn)
+{
+ int flags;
+ file_t port;
+ struct hurd_fd *d;
+
+ if (closefn != __stdio_close)
+ {
+ /* The old cookie is Not Of The Body.
+ Just close it and do a normal open. */
+ (*closefn) (*cookieptr);
+ return __stdio_open (filename, m, cookieptr);
+ }
+
+ /* Open a new port on the file. */
+ flags = modeflags (m);
+ port = __file_name_lookup (filename, flags, 0666 & ~_hurd_umask);
+
+ /* Install the new port in the same file descriptor slot the old cookie
+ points to. If opening the file failed, PORT will be MACH_PORT_NULL
+ and installing it in the descriptor will have the effect of closing
+ the old descriptor. */
+
+ d = *cookieptr;
+ HURD_CRITICAL_BEGIN;
+ __spin_lock (&d->port.lock);
+ _hurd_port2fd (d, port, flags);
+ __spin_unlock (&d->port.lock);
+ HURD_CRITICAL_END;
+
+ return port == MACH_PORT_NULL ? -1 : 0;
+}
+
+
+/* Write a message to the error output.
+ Try hard to make it really get out. */
+void
+DEFUN(__stdio_errmsg, (msg, len), CONST char *msg AND size_t len)
+{
+ io_t server;
+ mach_msg_type_number_t wrote;
+
+ server = __getdport (2);
+ __io_write (server, msg, len, -1, &wrote);
+ __mach_port_deallocate (__mach_task_self (), server);
+}
+
+
+/* Return the POSIX.1 file descriptor associated with COOKIE,
+ or -1 for errors. If COOKIE does not relate to any POSIX.1 file
+ descriptor, this should return -1 with errno set to EOPNOTSUPP. */
+int
+DEFUN(__stdio_fileno, (cookie), PTR cookie)
+{
+ int fd;
+
+ if (! cookie)
+ return __hurd_fail (EBADF);
+
+ __mutex_lock (&_hurd_dtable_lock);
+ for (fd = 0; fd < _hurd_dtablesize; ++fd)
+ if (_hurd_dtable[fd] == cookie)
+ {
+ __mutex_unlock (&_hurd_dtable_lock);
+ return fd;
+ }
+ __mutex_unlock (&_hurd_dtable_lock);
+
+ /* This should never happen, because this function should not be
+ installed as a stream's __fileno function unless that stream's cookie
+ points to a file descriptor. */
+ errno = EGRATUITOUS;
+ return -1;
+}
diff --git a/sysdeps/mach/hurd/telldir.c b/sysdeps/mach/hurd/telldir.c
new file mode 100644
index 0000000000..7ce8d1f061
--- /dev/null
+++ b/sysdeps/mach/hurd/telldir.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+
+/* Return the current position of DIRP. */
+off_t
+DEFUN(telldir, (dirp), DIR *dirp)
+{
+ return dirp->__entry_ptr;
+}
diff --git a/sysdeps/mach/hurd/truncate.c b/sysdeps/mach/hurd/truncate.c
new file mode 100644
index 0000000000..7453bfb3a9
--- /dev/null
+++ b/sysdeps/mach/hurd/truncate.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <hurd.h>
+#include <fcntl.h>
+
+/* Truncate FILE_NAME to LENGTH bytes. */
+int
+DEFUN(truncate, (file_name, length),
+ CONST char *file_name AND off_t length)
+{
+ error_t err;
+ file_t file = __file_name_lookup (file_name, O_WRITE, 0);
+
+ if (file == MACH_PORT_NULL)
+ return -1;
+
+ err = __file_truncate (file, length);
+ __mach_port_deallocate (__mach_task_self (), file);
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
diff --git a/sysdeps/mach/hurd/ttyname.c b/sysdeps/mach/hurd/ttyname.c
new file mode 100644
index 0000000000..5b8be3c629
--- /dev/null
+++ b/sysdeps/mach/hurd/ttyname.c
@@ -0,0 +1,38 @@
+/* Copyright (C) 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/term.h>
+#include <hurd/fd.h>
+
+/* Return the pathname of the terminal FD is open on, or NULL on errors.
+ The returned storage is good only until the next call to this function. */
+char *
+ttyname (int fd)
+{
+ error_t err;
+ static char nodename[1024]; /* XXX */
+
+ nodename[0] = '\0';
+ if (err = HURD_DPORT_USE (fd, __term_get_nodename (port, nodename)))
+ return __hurd_dfail (fd, err), NULL;
+
+ return nodename;
+}
diff --git a/sysdeps/mach/hurd/umask.c b/sysdeps/mach/hurd/umask.c
new file mode 100644
index 0000000000..0848dd77cd
--- /dev/null
+++ b/sysdeps/mach/hurd/umask.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 1991, 1992, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/stat.h>
+#include <hurd.h>
+
+/* Set the file creation mask to MASK, returning the old mask. */
+mode_t
+DEFUN(__umask, (mask), mode_t mask)
+{
+ mode_t omask;
+ mask &= 0777;
+ omask = _hurd_umask;
+ _hurd_umask = mask;
+ return omask;
+}
+
+weak_alias (__umask, umask)
diff --git a/sysdeps/mach/hurd/uname.c b/sysdeps/mach/hurd/uname.c
new file mode 100644
index 0000000000..74d9d3799f
--- /dev/null
+++ b/sysdeps/mach/hurd/uname.c
@@ -0,0 +1,31 @@
+/* Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <sys/utsname.h>
+#include <hurd.h>
+#include <hurd/startup.h>
+
+int
+uname (struct utsname *uname)
+{
+ error_t err;
+
+ err = __USEPORT (PROC, __proc_uname (port, uname));
+
+ return err ? __hurd_fail (err) : 0;
+}
diff --git a/sysdeps/mach/hurd/unlink.c b/sysdeps/mach/hurd/unlink.c
new file mode 100644
index 0000000000..b71d7f9f54
--- /dev/null
+++ b/sysdeps/mach/hurd/unlink.c
@@ -0,0 +1,46 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <hurd.h>
+
+
+/* Remove the link named NAME. */
+int
+DEFUN(__unlink, (name), CONST char *name)
+{
+ error_t err;
+ file_t dir;
+ CONST char *file;
+
+ dir = __file_name_split (name, (char **) &file);
+ if (dir == MACH_PORT_NULL)
+ return -1;
+
+ err = __dir_unlink (dir, file);
+ __mach_port_deallocate (__mach_task_self (), dir);
+
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__unlink, unlink)
diff --git a/sysdeps/mach/hurd/utimes.c b/sysdeps/mach/hurd/utimes.c
new file mode 100644
index 0000000000..f8f042598b
--- /dev/null
+++ b/sysdeps/mach/hurd/utimes.c
@@ -0,0 +1,43 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <stddef.h>
+#include <hurd.h>
+
+/* Change the access time of FILE to TVP[0] and
+ the modification time of FILE to TVP[1]. */
+int
+DEFUN(__utimes, (file, tvp),
+ CONST char *file AND struct timeval tvp[2])
+{
+ error_t err;
+ file_t f = __file_name_lookup (file, 0, 0);
+ if (f == MACH_PORT_NULL)
+ return -1;
+ err = __file_utimes (f,
+ *(time_value_t *) &tvp[0], *(time_value_t *) &tvp[1]);
+ __mach_port_deallocate (__mach_task_self (), f);
+ if (err)
+ return __hurd_fail (err);
+ return 0;
+}
+
+weak_alias (__utimes, utimes)
diff --git a/sysdeps/mach/hurd/wait4.c b/sysdeps/mach/hurd/wait4.c
new file mode 100644
index 0000000000..61e985505e
--- /dev/null
+++ b/sysdeps/mach/hurd/wait4.c
@@ -0,0 +1,40 @@
+/* Copyright (C) 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <hurd.h>
+#include <hurd/port.h>
+
+pid_t
+__wait4 (pid_t pid, __WAIT_STATUS_DEFN stat_loc,
+ int options, struct rusage *usage)
+{
+ pid_t dead;
+ error_t err;
+ struct rusage ignored;
+
+ err = __USEPORT (PROC, __proc_wait (port, pid, options, stat_loc,
+ usage ?: &ignored, &dead));
+
+ return err ? (pid_t) __hurd_fail (err) : dead;
+}
+
+weak_alias (__wait4, wait4)
diff --git a/sysdeps/mach/hurd/write.c b/sysdeps/mach/hurd/write.c
new file mode 100644
index 0000000000..c6c3e6c668
--- /dev/null
+++ b/sysdeps/mach/hurd/write.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+This file is part of the GNU C Library.
+
+The GNU C Library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Library General Public License as
+published by the Free Software Foundation; either version 2 of the
+License, or (at your option) any later version.
+
+The GNU C Library 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
+Library General Public License for more details.
+
+You should have received a copy of the GNU Library General Public
+License along with the GNU C Library; see the file COPYING.LIB. If
+not, write to the Free Software Foundation, Inc., 675 Mass Ave,
+Cambridge, MA 02139, USA. */
+
+#include <ansidecl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+ssize_t
+DEFUN(__write, (fd, buf, nbytes),
+ int fd AND CONST PTR buf AND size_t nbytes)
+{
+ error_t err = HURD_FD_USE (fd, _hurd_fd_write (descriptor, buf, &nbytes));
+ return err ? __hurd_dfail (fd, err) : nbytes;
+}
+
+
+
+weak_alias (__write, write)