aboutsummaryrefslogtreecommitdiff
path: root/hurd/hurdmsg.c
diff options
context:
space:
mode:
Diffstat (limited to 'hurd/hurdmsg.c')
-rw-r--r--hurd/hurdmsg.c451
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; }