diff options
author | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 1995-02-18 01:27:10 +0000 |
commit | 28f540f45bbacd939bfd07f213bcad2bf730b1bf (patch) | |
tree | 15f07c4c43d635959c6afee96bde71fb1b3614ee /sysdeps/mach | |
download | glibc-28f540f45bbacd939bfd07f213bcad2bf730b1bf.tar.gz |
initial import
Diffstat (limited to 'sysdeps/mach')
196 files changed, 14904 insertions, 0 deletions
diff --git a/sysdeps/mach/Makefile b/sysdeps/mach/Makefile new file mode 100644 index 0000000000..fab174c0d6 --- /dev/null +++ b/sysdeps/mach/Makefile @@ -0,0 +1,74 @@ +# 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 mach-srcdir-computed +mach-srcdir-computed := yes + +# If we were configured with `--with-mach=DIR', then config.make sets +# mach-srcdir to DIR. Otherwise guess we are in a big source tree. +ifndef mach-srcdir +mach-srcdir = ../mach +endif + +# mach-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 := mach/mach.defs # Random file that identifies the Mach source dir. +f := $(strip $f) +mach-srcdir := $(firstword $(patsubst %/$f,%,$(wildcard $(addsuffix /$f,\ + $(objpfx)$(mach-srcdir) $(..)$(mach-srcdir)))) $(mach-srcdir)) + +endif # ! mach-srcdir-computed + +ifdef in-Makerules + +# Look for header files in mach/ under the top-level library source directory. +includes += -I$(..)mach + +# When compiling, use the Mach header files directly from the kernel sources. +includes += -I$(mach-srcdir) + +# Find Mach header files in the kernel source. +vpath mach/%.h $(mach-srcdir) +vpath device/%.h $(mach-srcdir) + +ifneq (mach,$(subdir)) +# Subdirectories other than mach/ might use the generated Mach headers. +# So make sure we get a chance to run in mach/ to make them before all else. + +ifdef objpfx +mach-objpfx = $(objpfx) +else +mach-objpfx = $(..)mach/ +endif + +# These are all the generated files that <mach.h> includes. +mach-before-compile := $(mach-objpfx)mach-shortcuts.h \ + $(patsubst %,$(mach-objpfx)mach/mach_%.h,\ + interface port host) + +# This patsubst generates patterns like `m%h-shortcuts.h', which are damn +# likely to match just the corresponding particular file we want. +$(patsubst mach%,m\%h%,$(mach-before-compile)): # Run only if doesn't exist. + $(MAKE) -C $(..)mach generated no_deps=t + +before-compile += $(mach-before-compile) +endif + +endif # in-Makerules diff --git a/sysdeps/mach/Subdirs b/sysdeps/mach/Subdirs new file mode 100644 index 0000000000..fc6ac35d83 --- /dev/null +++ b/sysdeps/mach/Subdirs @@ -0,0 +1 @@ +mach diff --git a/sysdeps/mach/_strerror.c b/sysdeps/mach/_strerror.c new file mode 100644 index 0000000000..4740902a10 --- /dev/null +++ b/sysdeps/mach/_strerror.c @@ -0,0 +1,60 @@ +/* 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 <stdio.h> +#include <string.h> +#include <mach/error.h> +#include <mach/errorlib.h> + +/* Return a string describing the errno code in ERRNUM. */ +char * +DEFUN(_strerror_internal, (errnum, buf), int errnum AND char buf[1024]) +{ + int system; + int sub; + int code; + const struct error_system *es; + extern void __mach_error_map_compat (int *); + + __mach_error_map_compat (&errnum); + + system = err_get_system (errnum); + sub = err_get_sub (errnum); + code = err_get_code (errnum); + + if (system > err_max_system) + { + sprintf (buf, "Unknown error system %d", system); + return buf; + } + + es = &__mach_error_systems[system]; + + if (sub >= es->max_sub) + return (char *) es->bad_sub; + + if (code >= es->subsystem[sub].max_code) + { + sprintf (buf, "Unknown error %d in system %d subsystem %d", + code, system, sub); + return buf; + } + + return (char *) es->subsystem[sub].codes[code]; +} diff --git a/sysdeps/mach/adjtime.c b/sysdeps/mach/adjtime.c new file mode 100644 index 0000000000..f20153565b --- /dev/null +++ b/sysdeps/mach/adjtime.c @@ -0,0 +1,46 @@ +/* Copyright (C) 1991, 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; + + hostpriv = __pid2task (-1); + if (hostpriv == MACH_PORT_NULL) + return -1; + err = __host_adjust_time (hostpriv, delta, 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/alpha/machine-lock.h b/sysdeps/mach/alpha/machine-lock.h new file mode 100644 index 0000000000..42e21d8df2 --- /dev/null +++ b/sysdeps/mach/alpha/machine-lock.h @@ -0,0 +1,80 @@ +/* Machine-specific definition for spin locks. 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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile long int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0L + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + __asm__ __volatile__ ("mb; stq $31, %0; mb" + : "=m" (__lock)); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + register long int __rtn, __tmp; + + do + { + __asm__ __volatile__ ("mb; ldq_l %0,%1" /* Load lock value into TMP. */ + : "=r" (__tmp) : "m" (*__lock)); + __rtn = 2; /* Load locked value into RTN. */ + if (__tmp) + /* The lock is already taken. */ + return 0; + + /* The lock is not taken; try to get it now. */ + __asm__ __volatile__ ("stq_c %0,%1" + : "=r" (__rtn), "=m" (*__lock) + : "0" (__rtn), "1" (*__lock)); + /* RTN is clear if stq_c was interrupted; loop to try the lock again. */ + } while (! __rtn); + /* RTN is now nonzero; we have the lock. */ + return __rtn; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock != 0; +} + + +#endif /* machine-lock.h */ diff --git a/sysdeps/mach/alpha/machine-sp.h b/sysdeps/mach/alpha/machine-sp.h new file mode 100644 index 0000000000..6a8a3c6d40 --- /dev/null +++ b/sysdeps/mach/alpha/machine-sp.h @@ -0,0 +1,36 @@ +/* Machine-specific function to return the stack pointer. 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +_EXTERN_INLINE void * +__thread_stack_pointer (void) +{ + register void *__sp__ __asm__ ("$30"); + return __sp__; +} + +#endif /* machine-sp.h */ diff --git a/sysdeps/mach/alpha/syscall.S b/sysdeps/mach/alpha/syscall.S new file mode 100644 index 0000000000..31ccb5fc30 --- /dev/null +++ b/sysdeps/mach/alpha/syscall.S @@ -0,0 +1,39 @@ +/* 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 <sysdep.h> +#include <mach/machine/alpha_instruction.h> + +ENTRY (syscall) + .frame sp,0,ra + mov a0, v0 /* Load system call number from first arg. */ + mov a1, a0 + mov a2, a1 + mov a3, a2 + mov a4, a3 + mov a5, a4 + /* Load the remaining possible args (up to 11) from the stack. */ + ldq a5,0(sp) + ldq t0,8(sp) + ldq t1,16(sp) + ldq t2,24(sp) + ldq t3,32(sp) + ldq t4,40(sp) + call_pal op_chmk + RET + .end syscall diff --git a/sysdeps/mach/alpha/sysdep.h b/sysdeps/mach/alpha/sysdep.h new file mode 100644 index 0000000000..a32766270b --- /dev/null +++ b/sysdeps/mach/alpha/sysdep.h @@ -0,0 +1,41 @@ +/* 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. */ + +#define MOVE(x,y) mov x, y + +#define LOSE asm volatile ("call_pal 0") /* halt */ + +#define START_MACHDEP \ + asm ("_start: mov $30, $16\n" /* Put initial SP in a0. */ \ + " br $27, 1f\n" /* Load GP from PC. */ \ + "1: ldgp $29, 0($27)\n" \ + " jmp $26, _start0"); /* Jump to _start0; don't return. */ +#define START_ARGS char **sparg +#define SNARF_ARGS(argc, argv, envp) \ + (envp = &(argv = &sparg[1])[(argc = *(int *) sparg) + 1]) + +#define CALL_WITH_SP(fn, sp) \ + ({ register long int __fn = (long int) fn, __sp = (long int) sp; \ + asm volatile ("mov %0,$30; jmp $31, (%1); ldgp $29, 0(%1)" \ + : : "r" (__sp), "r" (__fn)); }) + +#define ENTRY(name) LEAF(name, ***loser no arg count***) + +#define STACK_GROWTH_DOWN + +#include_next <sysdep.h> diff --git a/sysdeps/mach/alpha/thread_state.h b/sysdeps/mach/alpha/thread_state.h new file mode 100644 index 0000000000..28b0a15758 --- /dev/null +++ b/sysdeps/mach/alpha/thread_state.h @@ -0,0 +1,39 @@ +/* Mach thread state definitions for machine-independent code. 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 <mach/machine/thread_status.h> + +#define MACHINE_THREAD_STATE_FLAVOR ALPHA_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT ALPHA_THREAD_STATE_COUNT + +#define machine_thread_state alpha_thread_state + +#define PC pc +#define SP r30 +#define SYSRETURN r0 + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct alpha_thread_state basic; + struct alpha_exc_state exc; + struct alpha_float_state fpu; + }; + +#include_next <thread_state.h> diff --git a/sysdeps/mach/configure b/sysdeps/mach/configure new file mode 100644 index 0000000000..fb1d8b0979 --- /dev/null +++ b/sysdeps/mach/configure @@ -0,0 +1,17 @@ + +# If configure is passed `--with-mach=DIR', set `mach-srcdir' to DIR in +# config.make. + +ac_help="$ac_help + --with-mach=DIRECTORY find Mach kernel source code in DIRECTORY [../mach]" +# Check whether --with-mach or --without-mach was given. +withval="$with_mach" +if test -n "$withval"; then + case z"$with_mach" in +z | zno | zyes) ;; # Not specified, or specified with no value. +z*) config_vars="$config_vars +mach-srcdir = $with_mach" ;; +esac + +fi + diff --git a/sysdeps/mach/configure.in b/sysdeps/mach/configure.in new file mode 100644 index 0000000000..2628886f1f --- /dev/null +++ b/sysdeps/mach/configure.in @@ -0,0 +1,15 @@ +sinclude(./aclocal.m4)dnl Autoconf lossage. +GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory. + +# If configure is passed `--with-mach=DIR', set `mach-srcdir' to DIR in +# config.make. + +AC_ARG_WITH(mach, dnl +[ --with-mach=DIRECTORY find Mach kernel source code in DIRECTORY [../mach]], + [dnl +case z"$with_mach" in +z | zno | zyes) ;; # Not specified, or specified with no value. +z*) config_vars="$config_vars +mach-srcdir = $with_mach" ;; +esac +]) diff --git a/sysdeps/mach/getpagesize.c b/sysdeps/mach/getpagesize.c new file mode 100644 index 0000000000..84f227f04f --- /dev/null +++ b/sysdeps/mach/getpagesize.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1991, 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 <unistd.h> +#include <errno.h> +#include <mach.h> + +/* Return the system page size. */ +size_t +DEFUN_VOID(__getpagesize) +{ + return __vm_page_size; +} + +weak_alias (__getpagesize, getpagesize) diff --git a/sysdeps/mach/gettimeofday.c b/sysdeps/mach/gettimeofday.c new file mode 100644 index 0000000000..9271490ad5 --- /dev/null +++ b/sysdeps/mach/gettimeofday.c @@ -0,0 +1,47 @@ +/* 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 <errno.h> +#include <sys/time.h> +#include <mach.h> + +/* Get the current time of day and timezone information, + putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. + Returns 0 on success, -1 on errors. */ +int +DEFUN(__gettimeofday, (tv, tz), + struct timeval *tv AND struct timezone *tz) +{ + kern_return_t err; + + if (tz != NULL) + { + errno = ENOSYS; + return -1; + } + + if (err = __host_get_time (__mach_host_self (), (time_value_t *) tv)) + { + errno = err; + return -1; + } + return 0; +} + +weak_alias (__gettimeofday, gettimeofday) diff --git a/sysdeps/mach/hppa/machine-lock.h b/sysdeps/mach/hppa/machine-lock.h new file mode 100644 index 0000000000..0a178357a3 --- /dev/null +++ b/sysdeps/mach/hppa/machine-lock.h @@ -0,0 +1,63 @@ +/* Machine-specific definition for spin locks. 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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile int __spin_lock_t __attribute__ ((__aligned__ (16))); + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER -1 + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + *__lock = -1; +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (__spin_lock_t *__lock) +{ + register int __result; + __asm__ __volatile__ ("ldcws %0, %1" : "=m" (*__lock), "=r" (__result)); + return __result != 0; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock == 0; +} + + +#endif /* machine-lock.h */ 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, + ¬ify_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) diff --git a/sysdeps/mach/i386/machine-lock.h b/sysdeps/mach/i386/machine-lock.h new file mode 100644 index 0000000000..bdc57e0997 --- /dev/null +++ b/sysdeps/mach/i386/machine-lock.h @@ -0,0 +1,66 @@ +/* Machine-specific definition for spin locks. 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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0 + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + register int __unlocked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__unlocked), "=m" (*__lock) : "0" (0)); +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (__spin_lock_t *__lock) +{ + register int __locked; + __asm__ __volatile ("xchgl %0, %1" + : "=&r" (__locked), "=m" (*__lock) : "0" (1)); + return !__locked; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock != 0; +} + + +#endif /* machine-lock.h */ diff --git a/sysdeps/mach/i386/machine-sp.h b/sysdeps/mach/i386/machine-sp.h new file mode 100644 index 0000000000..7fd15413f5 --- /dev/null +++ b/sysdeps/mach/i386/machine-sp.h @@ -0,0 +1,38 @@ +/* Machine-specific function to return the stack pointer. 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +_EXTERN_INLINE void * +__thread_stack_pointer (void) +{ + void *__sp__; + __asm__ ("movl %%esp, %0" : "=r" (__sp__)); + return __sp__; +} + +#endif /* machine-sp.h */ + diff --git a/sysdeps/mach/i386/syscall.S b/sysdeps/mach/i386/syscall.S new file mode 100644 index 0000000000..1e9fbb81e8 --- /dev/null +++ b/sysdeps/mach/i386/syscall.S @@ -0,0 +1,26 @@ +/* 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 <sysdep.h> + +ENTRY (syscall) + popl %ecx /* Pop return address into %ecx. */ + popl %eax /* Pop syscall number into %eax. */ + pushl %ecx /* Push back return address. */ + .byte 0x9a, 0, 0, 0, 0, 7, 0 /* lcall $7, $0 -- gas bug */ + ret diff --git a/sysdeps/mach/i386/sysdep.h b/sysdeps/mach/i386/sysdep.h new file mode 100644 index 0000000000..8d482a0485 --- /dev/null +++ b/sysdeps/mach/i386/sysdep.h @@ -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. */ + +#define MOVE(x,y) movl x , y + +#define LOSE asm volatile ("hlt") + +#define SNARF_ARGS(argc, argv, envp) \ + do \ + { \ + int *entry_sp; \ + register char **p; \ + \ + asm ("leal 4(%%ebp), %0" : "=r" (entry_sp)); \ + \ + argc = *entry_sp; \ + argv = (char **) (entry_sp + 1); \ + p = argv; \ + while (*p++ != NULL) \ + ; \ + if (p >= (char **) argv[0]) \ + --p; \ + envp = p; \ + } while (0) + +#define CALL_WITH_SP(fn, sp) \ + asm volatile ("movl %0, %%esp; jmp %1" : : \ + "g" (sp), "m" (*(long int *) (fn)) : "%esp") + +#define STACK_GROWTH_DOWN + +#include_next <sysdep.h> diff --git a/sysdeps/mach/i386/thread_state.h b/sysdeps/mach/i386/thread_state.h new file mode 100644 index 0000000000..89779b60ed --- /dev/null +++ b/sysdeps/mach/i386/thread_state.h @@ -0,0 +1,38 @@ +/* Mach thread state definitions for machine-independent code. 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 <mach/machine/thread_status.h> + +#define MACHINE_THREAD_STATE_FLAVOR i386_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT i386_THREAD_STATE_COUNT + +#define machine_thread_state i386_thread_state + +#define PC eip +#define SP uesp +#define SYSRETURN eax + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct i386_thread_state basic; + struct i386_float_state fpu; + }; + +#include_next <thread_state.h> diff --git a/sysdeps/mach/mips/Dist b/sysdeps/mach/mips/Dist new file mode 100644 index 0000000000..f2699bf887 --- /dev/null +++ b/sysdeps/mach/mips/Dist @@ -0,0 +1 @@ +cacheflush.c diff --git a/sysdeps/mach/mips/Makefile b/sysdeps/mach/mips/Makefile new file mode 100644 index 0000000000..a890ae7b46 --- /dev/null +++ b/sysdeps/mach/mips/Makefile @@ -0,0 +1,3 @@ +ifeq ($(subdir),gnulib) +sysdep_routines += cacheflush +endif diff --git a/sysdeps/mach/mips/cacheflush.c b/sysdeps/mach/mips/cacheflush.c new file mode 100644 index 0000000000..5325e6fd1e --- /dev/null +++ b/sysdeps/mach/mips/cacheflush.c @@ -0,0 +1,44 @@ +/* Flush the insn cache after GCC writes a closure on the stack. Mach/MIPS. +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 <mach.h> +#include <mach/vm_attributes.h> + +/* Stupid name, but this is what GCC generates (config/mips/mips.h). */ +void +cacheflush (void *addr, size_t size, int flag) +{ + vm_machine_attribute_val_t val; + + switch (flag) + { + case 0: /* ? */ + val = MATTR_VAL_DCACHE_FLUSH; + case 1: /* This is the only value GCC uses. */ + val = MATTR_VAL_ICACHE_FLUSH; + break; + default: + val = MATTR_VAL_CACHE_FLUSH; + } + + __vm_machine_attribute (__mach_task_self (), + (vm_address_t) addr, size, + MATTR_CACHE, + &val); +} diff --git a/sysdeps/mach/mips/machine-lock.h b/sysdeps/mach/mips/machine-lock.h new file mode 100644 index 0000000000..628aae41bb --- /dev/null +++ b/sysdeps/mach/mips/machine-lock.h @@ -0,0 +1,73 @@ +/* Machine-specific definition for spin locks. 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. */ + +#ifndef _MACHINE_LOCK_H +#define _MACHINE_LOCK_H + +/* The type of a spin lock variable. */ + +typedef __volatile int __spin_lock_t; + +/* Value to initialize `__spin_lock_t' variables to. */ + +#define __SPIN_LOCK_INITIALIZER 0 + + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +/* Unlock LOCK. */ + +_EXTERN_INLINE void +__spin_unlock (__spin_lock_t *__lock) +{ + *__lock = 0; +} + +/* Try to lock LOCK; return nonzero if we locked it, zero if another has. */ + +_EXTERN_INLINE int +__spin_try_lock (register __spin_lock_t *__lock) +{ + register int __rtn; + __asm__ __volatile (".set noreorder"); +#if 0 + __asm__ __volatile ("lw %0,0(%1)": "=r" (__rtn) : "r" (__lock)); + __asm__ __volatile ("sw %0,0(%0)": : "r" (__lock)); + __asm__ __volatile ("xor %0,%1,%0": "=r" (__rtn) : "r" (__lock)); +#else + /* Use the Mach microkernel's emulated TAS pseudo-instruction. */ + register int __rtn __asm__ ("a0"); + __asm__ __volatile (".word 0xf ! %0 " : "=r" (__rtn) : "0" (__lock)); +#endif + __asm__ __volatile (".set reorder"); + return __rtn ^ (int) __lock; +} + +/* Return nonzero if LOCK is locked. */ + +_EXTERN_INLINE int +__spin_lock_locked (__spin_lock_t *__lock) +{ + return *__lock != 0; +} + + +#endif /* machine-lock.h */ diff --git a/sysdeps/mach/mips/machine-sp.h b/sysdeps/mach/mips/machine-sp.h new file mode 100644 index 0000000000..7406658f53 --- /dev/null +++ b/sysdeps/mach/mips/machine-sp.h @@ -0,0 +1,38 @@ +/* Machine-specific function to return the stack pointer. 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. */ + +#ifndef _MACHINE_SP_H +#define _MACHINE_SP_H + +/* Return the current stack pointer. */ + +#ifndef _EXTERN_INLINE +#define _EXTERN_INLINE extern __inline +#endif + +_EXTERN_INLINE void * +__thread_stack_pointer (void) +{ + void *__sp__; + __asm__ ("move %0,$29" : "=r" (__sp__)); + return __sp__; +} + +#endif /* machine-sp.h */ + diff --git a/sysdeps/mach/mips/syscall.S b/sysdeps/mach/mips/syscall.S new file mode 100644 index 0000000000..bf56b401dd --- /dev/null +++ b/sysdeps/mach/mips/syscall.S @@ -0,0 +1,37 @@ +/* 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 <sysdep.h> + +ENTRY (syscall) + .frame sp,0,ra + move v0, a0 /* Load system call number from first arg. */ + move a0, a1 /* Move the next three args up a register. */ + move a1, a2 + move a2, a3 + /* Load the remaining possible args (up to 11) from the stack. */ + lw t0,16(sp) + lw t1,20(sp) + lw t2,24(sp) + lw t3,28(sp) + lw t4,32(sp) + lw t5,36(sp) + lw t6,40(sp) + syscall /* Do the system call. */ + j ra /* Return to caller. */ + .end syscall diff --git a/sysdeps/mach/mips/sysdep.h b/sysdeps/mach/mips/sysdep.h new file mode 100644 index 0000000000..7609be5931 --- /dev/null +++ b/sysdeps/mach/mips/sysdep.h @@ -0,0 +1,69 @@ +/* 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. */ + +#define MOVE(x,y) move y , x + +#if 0 +#define LOSE asm volatile ("1: b 1b") +#endif + +#define SNARF_ARGS(argc, argv, envp) \ + do \ + { \ + int *entry_sp; \ + register char **p; \ + \ + asm ("addu %0,$30,4" : "=r" (entry_sp)); \ + \ + argc = *entry_sp; \ + argv = (char **) (entry_sp + 1); \ + p = argv; \ + while (*p++ != NULL) \ + ; \ + if (p >= (char **) argv[0]) \ + --p; \ + envp = p; \ + } while (0) + +#define CALL_WITH_SP(fn, sp) \ + ({ register int __fn = fn, __sp = (int) sp; \ + asm volatile ("move $sp,%0; j %1" : : "r" (__sp), "r" (__fn));}) + +#define STACK_GROWTH_DOWN + +#ifdef P40 +#include <syscall.h> + +#define SYSCALL(name, args) \ + .globl syscall_error; \ + kernel_trap(name,SYS_##name,args); \ + beq $1,$0,1f; \ + j syscall_error; \ +1: + +#define SYSCALL__(name, args) \ + .globl syscall_error; \ + kernel_trap(__##name,SYS_##name,args); \ + beq $1,$0,1f; \ + j syscall_error; \ +1: + +#define ret j ra; nop +#endif + +#include_next <sysdep.h> diff --git a/sysdeps/mach/mips/thread_state.h b/sysdeps/mach/mips/thread_state.h new file mode 100644 index 0000000000..f4f4b429cf --- /dev/null +++ b/sysdeps/mach/mips/thread_state.h @@ -0,0 +1,37 @@ +/* Mach thread state definitions for machine-independent code. 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. */ + +#define MACHINE_THREAD_STATE_FLAVOR MIPS_THREAD_STATE +#define MACHINE_THREAD_STATE_COUNT MIPS_THREAD_STATE_COUNT + +#define machine_thread_state mips_thread_state + +#define PC pc +#define SP r29 +#define SYSRETURN r2 + +struct machine_thread_all_state + { + int set; /* Mask of bits (1 << FLAVOR). */ + struct mips_thread_state basic; + struct mips_exc_state exc; + struct mips_float_state fpu; + }; + +#include_next <thread_state.h> diff --git a/sysdeps/mach/mprotect.c b/sysdeps/mach/mprotect.c new file mode 100644 index 0000000000..5f1dbe8b5c --- /dev/null +++ b/sysdeps/mach/mprotect.c @@ -0,0 +1,50 @@ +/* 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 <mach.h> + +/* Change the memory protection of the region starting at ADDR and + extending LEN bytes to PROT. Returns 0 if successful, -1 for errors + (and sets errno). */ + +int +mprotect (caddr_t addr, size_t len, int prot) +{ + kern_return_t err; + vm_prot_t vmprot; + + 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; + + if (err = __vm_protect (__mach_task_self (), + (vm_address_t) addr, (vm_size_t) len, + 0, vmprot)) + { + errno = err; + return -1; + } + return 0; +} diff --git a/sysdeps/mach/munmap.c b/sysdeps/mach/munmap.c new file mode 100644 index 0000000000..5ca11298f3 --- /dev/null +++ b/sysdeps/mach/munmap.c @@ -0,0 +1,39 @@ +/* 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 <mach.h> + +/* Deallocate any mapping for the region starting at ADDR and extending LEN + bytes. Returns 0 if successful, -1 for errors (and sets errno). */ + +int +munmap (caddr_t addr, size_t len) +{ + kern_return_t err; + if (err = __vm_deallocate (__mach_task_self (), + (vm_address_t) addr, (vm_size_t) len)) + { + errno = err; + return -1; + } + return 0; +} + diff --git a/sysdeps/mach/sleep.c b/sysdeps/mach/sleep.c new file mode 100644 index 0000000000..0e613d3eec --- /dev/null +++ b/sysdeps/mach/sleep.c @@ -0,0 +1,45 @@ +/* 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 <signal.h> +#include <time.h> +#include <unistd.h> +#include <mach.h> + +/* Make the process sleep for SECONDS seconds, or until a signal arrives + and is not ignored. The function returns the number of seconds less + than SECONDS which it actually slept (zero if it slept the full time). + There is no return value to indicate error, but if `sleep' returns + SECONDS, it probably didn't work. */ +unsigned int +DEFUN(sleep, (seconds), unsigned int seconds) +{ + time_t before, after; + mach_port_t recv; + + recv = __mach_reply_port (); + + before = time ((time_t *) NULL); + (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, seconds * 1000, MACH_PORT_NULL); + after = time ((time_t *) NULL); + __mach_port_destroy (__mach_task_self (), recv); + + return seconds - (after - before); +} diff --git a/sysdeps/mach/start.c b/sysdeps/mach/start.c new file mode 100644 index 0000000000..26abc23f53 --- /dev/null +++ b/sysdeps/mach/start.c @@ -0,0 +1,89 @@ +/* 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 <stddef.h> +#include <stdlib.h> +#include <errno.h> +#include <unistd.h> +#include <sysdep.h> + +#ifndef __GNUC__ + #error This file uses GNU C extensions; you must compile with GCC. +#endif + +/* The first piece of initialized data. */ +int __data_start = 0; + +volatile int errno; + +#ifndef HAVE_GNU_LD +#define __environ environ +#endif +char **__environ; + +extern void __mach_init (void); +extern void __libc_init (int argc, char **argv, char **envp); +extern int main (int argc, char **argv, char **envp); + +/* These are uninitialized common definitions so they will be zero + by default. If the user links in C threads, that will provide initialized + definitions that override these. */ +void *(*_cthread_init_routine) (void); /* Returns new SP to use. */ +void (*_cthread_exit_routine) (int status); + + +/* These are for communication from _start to start1, + where we cannot use the stack for anything. */ +static int start_argc; +static char **start_argv; + +/* _start calls this on the new stack. */ +static volatile void +start1 (void) +{ + __libc_init (start_argc, start_argv, __environ); + + (_cthread_exit_routine != NULL ? *_cthread_exit_routine : exit) + (main (start_argc, start_argv, __environ)); + + /* Should never get here. */ + LOSE; +} + +#ifndef START_ARGS +#define START_ARGS void +#ifdef START_MACHDEP +START_MACHDEP +#define _start _start0 +#endif + +void +_start (START_ARGS) +{ + SNARF_ARGS (start_argc, start_argv, __environ); + + __mach_init (); + + if (_cthread_init_routine != NULL) + CALL_WITH_SP (start1, (*_cthread_init_routine) ()); + else + start1 (); + + /* Should never get here. */ + LOSE; +} diff --git a/sysdeps/mach/sys/reboot.h b/sysdeps/mach/sys/reboot.h new file mode 100644 index 0000000000..6435fea00c --- /dev/null +++ b/sysdeps/mach/sys/reboot.h @@ -0,0 +1,153 @@ +/* + * Mach Operating System + * Copyright (c) 1993,1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ +/* + * HISTORY + * $Log$ + * Revision 1.1 1993/08/03 22:25:15 roland + * entered into RCS + * + * Revision 1.1 1993/08/03 22:25:15 roland + * entered into RCS + * + * Revision 2.8 93/03/11 13:46:40 danner + * u_long -> u_int. + * [93/03/09 danner] + * + * Revision 2.7 92/05/21 17:25:11 jfriedl + * Appended 'U' to constants that would otherwise be signed. + * [92/05/16 jfriedl] + * + * Revision 2.6 91/06/19 11:59:44 rvb + * Second byte of boothowto is flags for "startup" program. + * [91/06/18 rvb] + * Add ifndef ASSEMBLER so that vax_init.s can include it. + * [91/06/11 rvb] + * + * Revision 2.5 91/05/14 17:40:11 mrt + * Correcting copyright + * + * Revision 2.4 91/02/05 17:56:48 mrt + * Changed to new Mach copyright + * [91/02/01 17:49:12 mrt] + * + * Revision 2.3 90/08/27 22:12:56 dbg + * Added definitions used by Mach Kernel: RB_DEBUGGER, RB_UNIPROC, + * RB_NOBOOTRC, RB_ALTBOOT. Moved RB_KDB to 0x04 (Mach value). + * Removed RB_RDONLY, RB_DUMP, RB_NOSYNC. + * [90/08/14 dbg] + * + */ + +/* + * Copyright (c) 1982, 1986, 1988 Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms are permitted + * provided that the above copyright notice and this paragraph are + * duplicated in all such forms and that any documentation, + * advertising materials, and other materials related to such + * distribution and use acknowledge that the software was developed + * by the University of California, Berkeley. The name of the + * University may not be used to endorse or promote products derived + * from this software without specific prior written permission. + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + * + * @(#)reboot.h 7.5 (Berkeley) 6/27/88 + */ + +#ifndef _SYS_REBOOT_H_ +#define _SYS_REBOOT_H_ + +/* + * Arguments to reboot system call. + * These are converted to switches, and passed to startup program, + * and on to init. + */ +#define RB_AUTOBOOT 0 /* flags for system auto-booting itself */ + +#define RB_ASKNAME 0x01 /* -a: ask for file name to reboot from */ +#define RB_SINGLE 0x02 /* -s: reboot to single user only */ +#define RB_KDB 0x04 /* -d: kernel debugger symbols loaded */ +#define RB_HALT 0x08 /* -h: enter KDB at bootup */ + /* for host_reboot(): don't reboot, + just halt */ +#define RB_INITNAME 0x10 /* -i: name given for /etc/init (unused) */ +#define RB_DFLTROOT 0x20 /* use compiled-in rootdev */ +#define RB_NOBOOTRC 0x20 /* -b: don't run /etc/rc.boot */ +#define RB_ALTBOOT 0x40 /* use /boot.old vs /boot */ +#define RB_UNIPROC 0x80 /* -u: start only one processor */ + +#define RB_SHIFT 8 /* second byte is for ux */ + +#define RB_DEBUGGER 0x1000 /* for host_reboot(): enter kernel + debugger from user level */ + +/* + * Constants for converting boot-style device number to type, + * adaptor (uba, mba, etc), unit number and partition number. + * Type (== major device number) is in the low byte + * for backward compatibility. Except for that of the "magic + * number", each mask applies to the shifted value. + * Format: + * (4) (4) (4) (4) (8) (8) + * -------------------------------- + * |MA | AD| CT| UN| PART | TYPE | + * -------------------------------- + */ +#define B_ADAPTORSHIFT 24 +#define B_ADAPTORMASK 0x0f +#define B_ADAPTOR(val) (((val) >> B_ADAPTORSHIFT) & B_ADAPTORMASK) +#define B_CONTROLLERSHIFT 20 +#define B_CONTROLLERMASK 0xf +#define B_CONTROLLER(val) (((val)>>B_CONTROLLERSHIFT) & B_CONTROLLERMASK) +#define B_UNITSHIFT 16 +#define B_UNITMASK 0xf +#define B_UNIT(val) (((val) >> B_UNITSHIFT) & B_UNITMASK) +#define B_PARTITIONSHIFT 8 +#define B_PARTITIONMASK 0xff +#define B_PARTITION(val) (((val) >> B_PARTITIONSHIFT) & B_PARTITIONMASK) +#define B_TYPESHIFT 0 +#define B_TYPEMASK 0xff +#define B_TYPE(val) (((val) >> B_TYPESHIFT) & B_TYPEMASK) + +#define B_MAGICMASK ((u_int)0xf0000000U) +#define B_DEVMAGIC ((u_int)0xa0000000U) + +#define MAKEBOOTDEV(type, adaptor, controller, unit, partition) \ + (((type) << B_TYPESHIFT) | ((adaptor) << B_ADAPTORSHIFT) | \ + ((controller) << B_CONTROLLERSHIFT) | ((unit) << B_UNITSHIFT) | \ + ((partition) << B_PARTITIONSHIFT) | B_DEVMAGIC) + + +#ifdef KERNEL +#ifndef ASSEMBLER +extern int boothowto; +#endif ASSEMBLER +#endif + +#endif /* _SYS_REBOOT_H_ */ diff --git a/sysdeps/mach/syscall.h b/sysdeps/mach/syscall.h new file mode 100644 index 0000000000..6e4ed4d64e --- /dev/null +++ b/sysdeps/mach/syscall.h @@ -0,0 +1 @@ +/* The Mach syscalls are in <mach/syscall_sw.h>. */ diff --git a/sysdeps/mach/sysdep.h b/sysdeps/mach/sysdep.h new file mode 100644 index 0000000000..9a8dbd5163 --- /dev/null +++ b/sysdeps/mach/sysdep.h @@ -0,0 +1,82 @@ +/* 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. */ + +#ifdef ASSEMBLER + +/* Get the Mach definitions of ENTRY and kernel_trap. */ +#include <mach/machine/syscall_sw.h> + +/* The Mach definitions assume underscores should be prepended to + symbol names. Redefine them to do so only when appropriate. */ +#undef EXT +#undef LEXT +#define EXT(x) C_SYMBOL_NAME(x) +#define LEXT(x) C_SYMBOL_NAME(x##:) + +#endif + +/* This is invoked by things run when there is random lossage, before they + try to do anything else. Just to be safe, deallocate the reply port so + bogons arriving on it don't foul up future RPCs. */ + +#ifndef ASSEMBLER +#define FATAL_PREPARE_INCLUDE <mach/mig_support.h> +#define FATAL_PREPARE __mig_dealloc_reply_port (MACH_PORT_NULL) +#endif + +/* sysdeps/mach/MACHINE/sysdep.h should define the following macros. */ + +/* Produce a text assembler label for the C global symbol NAME. */ +#ifndef ENTRY +#define ENTRY(name) .error ENTRY not defined by sysdeps/mach/MACHINE/sysdep.h +/* This is not used on all machines. */ +#endif + +/* Set variables ARGC, ARGV, and ENVP for the arguments + left on the stack by the microkernel. */ +#ifndef SNARF_ARGS +#define SNARF_ARGS(argc, argv, envp) +#error SNARF_ARGS not defined by sysdeps/mach/MACHINE/sysdep.h +#endif + +/* Call the C function FN with no arguments, + on a stack starting at SP (as returned by *_cthread_init_routine). + You don't need to deal with FN returning; it shouldn't. */ +#ifndef CALL_WITH_SP +#define CALL_WITH_SP(fn, sp) +#error CALL_WITH_SP not defined by sysdeps/mach/MACHINE/sysdep.h +#endif + +/* LOSE can be defined as the `halt' instruction or something + similar which will cause the process to die in a characteristic + way suggesting a bug. */ +#ifndef LOSE +#define LOSE ({ volatile int zero = 0; zero / zero; }) +#endif + +/* One of these should be defined to specify the stack direction. */ +#if !defined (STACK_GROWTH_UP) && !defined (STACK_GROWTH_DOWN) +#error stack direction unspecified +#endif + +/* Used by some assembly code. */ +#ifdef NO_UNDERSCORES +#define C_SYMBOL_NAME(name) name +#else +#define C_SYMBOL_NAME(name) _##name +#endif diff --git a/sysdeps/mach/thread_state.h b/sysdeps/mach/thread_state.h new file mode 100644 index 0000000000..06f168bb55 --- /dev/null +++ b/sysdeps/mach/thread_state.h @@ -0,0 +1,87 @@ +/* Generic definitions for dealing with Mach thread states. +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. */ + + +/* Everything else is called `thread_state', but CMU's header file is + called `thread_status'. Oh boy. */ +#include <mach/thread_status.h> + +/* The machine-dependent thread_state.h file can either define these + macros, or just define PC and SP to the register names. */ + +#ifndef MACHINE_THREAD_STATE_SET_PC +#define MACHINE_THREAD_STATE_SET_PC(ts, pc) \ + ((ts)->PC = (unsigned long int) (pc)) +#endif +#ifndef MACHINE_THREAD_STATE_SET_SP +#ifdef STACK_GROWTH_UP +#define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \ + ((ts)->SP = (unsigned long int) (stack)) +#else +#define MACHINE_THREAD_STATE_SET_SP(ts, stack, size) \ + ((ts)->SP = (unsigned long int) (stack) + (size)) +#endif +#endif + +/* These functions are of use in machine-dependent signal trampoline + implementations. */ + +#include <string.h> /* size_t, memcpy */ +#include <mach/mach_interface.h> /* __thread_get_state */ + +static inline int +machine_get_state (thread_t thread, struct machine_thread_all_state *state, + int flavor, void *stateptr, void *scpptr, size_t size) +{ + if (state->set & (1 << flavor)) + { + /* Copy the saved state. */ + memcpy (scpptr, stateptr, size); + return 1; + } + else + { + /* Noone asked about this flavor of state before; fetch the state + directly from the kernel into the sigcontext. */ + mach_msg_type_number_t got = (size / sizeof (int)); + return (! __thread_get_state (thread, flavor, scpptr, &got) + && got == (size / sizeof (int))); + } +} + +static inline int +machine_get_basic_state (thread_t thread, + struct machine_thread_all_state *state) +{ + mach_msg_type_number_t count; + + if (state->set & (1 << MACHINE_THREAD_STATE_FLAVOR)) + return 1; + + count = MACHINE_THREAD_STATE_COUNT; + if (__thread_get_state (thread, MACHINE_THREAD_STATE_FLAVOR, + (natural_t *) &state->basic, + &count) != KERN_SUCCESS || + count != MACHINE_THREAD_STATE_COUNT) + /* What kind of thread?? */ + return 0; /* XXX */ + + state->set |= 1 << MACHINE_THREAD_STATE_FLAVOR; + return 1; +} diff --git a/sysdeps/mach/usleep.c b/sysdeps/mach/usleep.c new file mode 100644 index 0000000000..90d47d8c24 --- /dev/null +++ b/sysdeps/mach/usleep.c @@ -0,0 +1,43 @@ +/* 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 <mach.h> +#include <sys/time.h> + +/* Sleep USECONDS microseconds, or until a previously set timer goes off. */ +unsigned int +DEFUN(usleep, (useconds), unsigned int useconds) +{ + mach_port_t recv; + struct timeval before, after; + + recv = __mach_reply_port (); + + if (__gettimeofday (&before, NULL) < 0) + return useconds; + (void) __mach_msg (NULL, MACH_RCV_MSG|MACH_RCV_TIMEOUT|MACH_RCV_INTERRUPT, + 0, 0, recv, (useconds + 999) / 1000, MACH_PORT_NULL); + __mach_port_destroy (mach_task_self (), recv); + if (__gettimeofday (&after, NULL) < 0) + return 0; + + return useconds - (((after.tv_sec - before.tv_sec) * 1000000) + + (after.tv_usec - before.tv_usec)); +} |