diff options
Diffstat (limited to 'hurd/hurdmsg.c')
-rw-r--r-- | hurd/hurdmsg.c | 451 |
1 files changed, 451 insertions, 0 deletions
diff --git a/hurd/hurdmsg.c b/hurd/hurdmsg.c new file mode 100644 index 0000000000..57b6b8dd67 --- /dev/null +++ b/hurd/hurdmsg.c @@ -0,0 +1,451 @@ +/* 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 <hurd.h> +#include <hurd/msg_server.h> +#include <hurd/fd.h> +#include <unistd.h> +#include <limits.h> +#include <string.h> + + +#define AUTHCHECK \ + if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \ + return EPERM + + +/* Snarfing and frobbing the init ports. */ + +kern_return_t +_S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which, + mach_port_t *result, mach_msg_type_name_t *result_type) +{ + AUTHCHECK; + *result_type = MACH_MSG_TYPE_MOVE_SEND; + /* This function adds a new user reference for the *RESULT it gives back. + Our reply message uses a move-send right that consumes this reference. */ + return _hurd_ports_get (which, result); +} + +kern_return_t +_S_msg_set_init_port (mach_port_t msgport, mach_port_t auth, + int which, mach_port_t port) +{ + error_t err; + + AUTHCHECK; + + err = _hurd_ports_set (which, port); + if (err == 0) + __mach_port_deallocate (__mach_task_self (), port); + + return 0; +} + +kern_return_t +_S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth, + mach_port_t **ports, + mach_msg_type_name_t *ports_type, + mach_msg_type_number_t *nports) +{ + mach_msg_type_number_t i; + error_t err; + + AUTHCHECK; + + if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports, + _hurd_nports * sizeof (mach_port_t), 1)) + return err; + *nports = _hurd_nports; + + for (i = 0; i < _hurd_nports; ++i) + /* This function adds a new user ref for the *RESULT it gives back. + Our reply message uses move-send rights that consumes this ref. */ + if (err = _hurd_ports_get (i, &(*ports)[i])) + { + /* Died part way through. Deallocate the ports already fetched. */ + while (i-- > 0) + __mach_port_deallocate (__mach_task_self (), (*ports)[i]); + __vm_deallocate (__mach_task_self (), + (vm_address_t) *ports, + *nports * sizeof (mach_port_t)); + return err; + } + + *ports_type = MACH_MSG_TYPE_MOVE_SEND; + return 0; +} + +kern_return_t +_S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth, + mach_port_t *ports, mach_msg_type_number_t nports) +{ + mach_msg_type_number_t i; + error_t err; + + AUTHCHECK; + + for (i = 0; i < _hurd_nports; ++i) + { + if (err = _hurd_ports_set (i, ports[i])) + return err; + else + __mach_port_deallocate (__mach_task_self (), ports[i]); + } + + return 0; +} + +/* Snarfing and frobbing the init ints. */ + +static kern_return_t +get_int (int which, int *value) +{ + switch (which) + { + case INIT_UMASK: + *value = _hurd_umask; + return 0; + case INIT_SIGMASK: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + __spin_lock (&ss->lock); + *value = ss->blocked; + __spin_unlock (&ss->lock); + return 0; + } + case INIT_SIGPENDING: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + __spin_lock (&ss->lock); + *value = ss->pending; + __spin_unlock (&ss->lock); + return 0; + } + case INIT_SIGIGN: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + sigset_t ign; + int sig; + __spin_lock (&ss->lock); + __sigemptyset (&ign); + for (sig = 1; sig < NSIG; ++sig) + if (ss->actions[sig].sa_handler == SIG_IGN) + __sigaddset (&ign, sig); + __spin_unlock (&ss->lock); + *value = ign; + return 0; + } + default: + return EINVAL; + } +} + +kern_return_t +_S_msg_get_init_int (mach_port_t msgport, mach_port_t auth, + int which, int *value) +{ + AUTHCHECK; + + return get_int (which, value); +} + +kern_return_t +_S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth, + int **values, mach_msg_type_number_t *nvalues) +{ + error_t err; + mach_msg_type_number_t i; + + AUTHCHECK; + + if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values, + INIT_INT_MAX * sizeof (int), 1)) + return err; + *nvalues = INIT_INT_MAX; + + for (i = 0; i < INIT_INT_MAX; ++i) + switch (err = get_int (i, &(*values)[i])) + { + case 0: /* Success. */ + break; + case EINVAL: /* Unknown index. */ + (*values)[i] = 0; + break; + default: /* Lossage. */ + __vm_deallocate (__mach_task_self (), + (vm_address_t) *values, INIT_INT_MAX * sizeof (int)); + return err; + } + + return 0; +} + + +static kern_return_t +set_int (int which, int value) +{ + switch (which) + { + case INIT_UMASK: + _hurd_umask = value; + return 0; + + /* These are pretty odd things to do. But you asked for it. */ + case INIT_SIGMASK: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + __spin_lock (&ss->lock); + ss->blocked = value; + __spin_unlock (&ss->lock); + return 0; + } + case INIT_SIGPENDING: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + __spin_lock (&ss->lock); + ss->pending = value; + __spin_unlock (&ss->lock); + return 0; + } + case INIT_SIGIGN: + { + struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread); + int sig; + const sigset_t ign = value; + __spin_lock (&ss->lock); + for (sig = 1; sig < NSIG; ++sig) + { + if (__sigismember (&ign, sig)) + ss->actions[sig].sa_handler = SIG_IGN; + else if (ss->actions[sig].sa_handler == SIG_IGN) + ss->actions[sig].sa_handler = SIG_DFL; + } + __spin_unlock (&ss->lock); + return 0; + } + default: + return EINVAL; + } +} + +kern_return_t +_S_msg_set_init_int (mach_port_t msgport, mach_port_t auth, + int which, int value) +{ + AUTHCHECK; + + return set_int (which, value); +} + +kern_return_t +_S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth, + int *values, mach_msg_type_number_t nvalues) +{ + error_t err; + mach_msg_type_number_t i; + + AUTHCHECK; + + for (i = 0; i < INIT_INT_MAX; ++i) + switch (err = set_int (i, values[i])) + { + case 0: /* Success. */ + break; + case EINVAL: /* Unknown index. */ + break; + default: /* Lossage. */ + return err; + } + + return 0; +} + + +kern_return_t +_S_msg_get_fd (mach_port_t msgport, mach_port_t auth, + int which, mach_port_t *result, mach_msg_type_name_t *result_type) +{ + AUTHCHECK; + + /* This creates a new user reference for the send right. + Our reply message will move that reference to the caller. */ + *result = __getdport (which); + if (*result == MACH_PORT_NULL) + return errno; + *result_type = MACH_MSG_TYPE_MOVE_SEND; + + return 0; +} + +kern_return_t +_S_msg_set_fd (mach_port_t msgport, mach_port_t auth, + int which, mach_port_t port) +{ + AUTHCHECK; + + /* We consume the reference if successful. */ + return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0)); +} + +/* Snarfing and frobbing environment variables. */ + +kern_return_t +_S_msg_get_env_variable (mach_port_t msgport, + char *variable, + char **data, mach_msg_type_number_t *datalen) +{ + const char *value = getenv (variable); + + if (value == NULL) + return ENOENT; + + /* XXX this pointer might become invalid */ + *data = value; + *datalen = strlen (value); + return 0; +} + + +kern_return_t +_S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth, + char *variable, + char *value, + int replace) +{ + AUTHCHECK; + + if (setenv (variable, value, replace)) /* XXX name space */ + return errno; + return 0; +} + +kern_return_t +_S_msg_get_environment (mach_port_t msgport, + char **data, mach_msg_type_number_t *datalen) +{ + /* Pack the environment into an array with nulls separating elements. */ + if (__environ != NULL) + { + char *ap, **p; + size_t envlen = 0; + + for (p = __environ; *p != NULL; ++p) + envlen += strlen (*p) + 1; + + if (envlen > *datalen) + { + if (__vm_allocate (__mach_task_self (), + (vm_address_t *) data, envlen, 1)) + return ENOMEM; + } + + ap = *data; + for (p = __environ; *p != NULL; ++p) + ap = __memccpy (ap, *p, '\0', ULONG_MAX); + + *datalen = envlen; + } + else + *datalen = 0; + + return 0; +} + +kern_return_t +_S_msg_set_environment (mach_port_t msgport, mach_port_t auth, + char *data, mach_msg_type_number_t datalen) +{ + int _hurd_split_args (char *, mach_msg_type_number_t, char **); + int envc; + char **envp; + + AUTHCHECK; + + envc = _hurd_split_args (data, datalen, NULL); + envp = malloc ((envc + 1) * sizeof (char *)); + if (envp == NULL) + return errno; + _hurd_split_args (data, datalen, envp); + __environ = envp; /* XXX cooperate with loadenv et al */ + return 0; +} + +/* Get and frob the exec flags. */ + +kern_return_t +_S_msg_get_exec_flags (mach_port_t process, mach_port_t auth, + int *flags) +{ + AUTHCHECK; + + *flags = _hurd_exec_flags; + return 0; +} + +kern_return_t +_S_msg_set_all_exec_flags (mach_port_t process, mach_port_t auth, + int flags) +{ + AUTHCHECK; + + _hurd_exec_flags = flags; + return 0; +} + +kern_return_t +_S_msg_set_some_exec_flags (mach_port_t process, mach_port_t auth, + int flags) +{ + AUTHCHECK; + + _hurd_exec_flags |= flags; + return 0; +} + +kern_return_t +_S_msg_clear_some_exec_flags (mach_port_t process, mach_port_t auth, + int flags) +{ + AUTHCHECK; + + _hurd_exec_flags &= ~flags; + return 0; +} + + +/* XXX */ + +kern_return_t +_S_msg_get_dtable (mach_port_t process, + mach_port_t refport, + portarray_t *dtable, + mach_msg_type_name_t *dtablePoly, + mach_msg_type_number_t *dtableCnt) +{ return EOPNOTSUPP; } + +kern_return_t +_S_msg_set_dtable (mach_port_t process, + mach_port_t refport, + portarray_t dtable, + mach_msg_type_number_t dtableCnt) +{ return EOPNOTSUPP; } + +kern_return_t +_S_msg_startup_dosync (mach_port_t process) +{ return EOPNOTSUPP; } |