Blame hurd/hurdmsg.c

Packit 6c4009
/* Copyright (C) 1992-2018 Free Software Foundation, Inc.
Packit 6c4009
   This file is part of the GNU C Library.
Packit 6c4009
Packit 6c4009
   The GNU C Library is free software; you can redistribute it and/or
Packit 6c4009
   modify it under the terms of the GNU Lesser General Public
Packit 6c4009
   License as published by the Free Software Foundation; either
Packit 6c4009
   version 2.1 of the License, or (at your option) any later version.
Packit 6c4009
Packit 6c4009
   The GNU C Library is distributed in the hope that it will be useful,
Packit 6c4009
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 6c4009
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 6c4009
   Lesser General Public License for more details.
Packit 6c4009
Packit 6c4009
   You should have received a copy of the GNU Lesser General Public
Packit 6c4009
   License along with the GNU C Library; if not, see
Packit 6c4009
   <http://www.gnu.org/licenses/>.  */
Packit 6c4009
Packit 6c4009
#include <hurd.h>
Packit 6c4009
#include <hurd/msg_server.h>
Packit 6c4009
#include <hurd/fd.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <limits.h>
Packit 6c4009
#include <string.h>
Packit 6c4009
#include <argz.h>
Packit 6c4009
Packit 6c4009
Packit 6c4009
#define AUTHCHECK \
Packit 6c4009
  if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
Packit 6c4009
    return EPERM
Packit 6c4009
Packit 6c4009
Packit 6c4009
/* Snarfing and frobbing the init ports.  */
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
  _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
Packit 6c4009
			mach_port_t *result, mach_msg_type_name_t *result_type)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
  *result_type = MACH_MSG_TYPE_MOVE_SEND;
Packit 6c4009
  /* This function adds a new user reference for the *RESULT it gives back.
Packit 6c4009
     Our reply message uses a move-send right that consumes this reference.  */
Packit 6c4009
  return _hurd_ports_get (which, result);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		      int which, mach_port_t port)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  err = _hurd_ports_set (which, port);
Packit 6c4009
  if (err == 0)
Packit 6c4009
    __mach_port_deallocate (__mach_task_self (), port);
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		       mach_port_t **ports,
Packit 6c4009
		       mach_msg_type_name_t *ports_type,
Packit 6c4009
		       mach_msg_type_number_t *nports)
Packit 6c4009
{
Packit 6c4009
  mach_msg_type_number_t i;
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
Packit 6c4009
			   _hurd_nports * sizeof (mach_port_t), 1))
Packit 6c4009
    return err;
Packit 6c4009
  *nports = _hurd_nports;
Packit 6c4009
Packit 6c4009
  for (i = 0; i < _hurd_nports; ++i)
Packit 6c4009
    /* This function adds a new user ref for the *RESULT it gives back.
Packit 6c4009
       Our reply message uses move-send rights that consumes this ref.  */
Packit 6c4009
    if (err = _hurd_ports_get (i, &(*ports)[i]))
Packit 6c4009
      {
Packit 6c4009
	/* Died part way through.  Deallocate the ports already fetched.  */
Packit 6c4009
	while (i-- > 0)
Packit 6c4009
	  __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
Packit 6c4009
	__vm_deallocate (__mach_task_self (),
Packit 6c4009
			 (vm_address_t) *ports,
Packit 6c4009
			 *nports * sizeof (mach_port_t));
Packit 6c4009
	return err;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  *ports_type = MACH_MSG_TYPE_MOVE_SEND;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		       mach_port_t *ports, mach_msg_type_number_t nports)
Packit 6c4009
{
Packit 6c4009
  mach_msg_type_number_t i;
Packit 6c4009
  error_t err;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  for (i = 0; i < _hurd_nports; ++i)
Packit 6c4009
    {
Packit 6c4009
      if (err = _hurd_ports_set (i, ports[i]))
Packit 6c4009
	return err;
Packit 6c4009
      else
Packit 6c4009
	__mach_port_deallocate (__mach_task_self (), ports[i]);
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
/* Snarfing and frobbing the init ints.  */
Packit 6c4009
Packit 6c4009
static kern_return_t
Packit 6c4009
get_int (int which, int *value)
Packit 6c4009
{
Packit 6c4009
  switch (which)
Packit 6c4009
    {
Packit 6c4009
    case INIT_UMASK:
Packit 6c4009
      *value = _hurd_umask;
Packit 6c4009
      return 0;
Packit 6c4009
    case INIT_SIGMASK:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	*value = ss->blocked;
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    case INIT_SIGPENDING:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	*value = ss->pending;
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    case INIT_SIGIGN:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	sigset_t ign;
Packit 6c4009
	int sig;
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	__sigemptyset (&ign;;
Packit 6c4009
	for (sig = 1; sig < NSIG; ++sig)
Packit 6c4009
	  if (ss->actions[sig].sa_handler == SIG_IGN)
Packit 6c4009
	    __sigaddset (&ign, sig);
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	*value = ign;
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    default:
Packit 6c4009
      return EINVAL;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		     int which, int *value)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  return get_int (which, value);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		      int **values, mach_msg_type_number_t *nvalues)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  mach_msg_type_number_t i;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
Packit 6c4009
			   INIT_INT_MAX * sizeof (int), 1))
Packit 6c4009
    return err;
Packit 6c4009
  *nvalues = INIT_INT_MAX;
Packit 6c4009
Packit 6c4009
  for (i = 0; i < INIT_INT_MAX; ++i)
Packit 6c4009
    switch (err = get_int (i, &(*values)[i]))
Packit 6c4009
      {
Packit 6c4009
      case 0:			/* Success.  */
Packit 6c4009
	break;
Packit 6c4009
      case EINVAL:		/* Unknown index.  */
Packit 6c4009
	(*values)[i] = 0;
Packit 6c4009
	break;
Packit 6c4009
      default:			/* Lossage.  */
Packit 6c4009
	__vm_deallocate (__mach_task_self (),
Packit 6c4009
			 (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
Packit 6c4009
	return err;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
static kern_return_t
Packit 6c4009
set_int (int which, int value)
Packit 6c4009
{
Packit 6c4009
  switch (which)
Packit 6c4009
    {
Packit 6c4009
    case INIT_UMASK:
Packit 6c4009
      _hurd_umask = value;
Packit 6c4009
      return 0;
Packit 6c4009
Packit 6c4009
      /* These are pretty odd things to do.  But you asked for it.  */
Packit 6c4009
    case INIT_SIGMASK:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	ss->blocked = value;
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    case INIT_SIGPENDING:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	ss->pending = value;
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    case INIT_SIGIGN:
Packit 6c4009
      {
Packit 6c4009
	struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
Packit 6c4009
	int sig;
Packit 6c4009
	const sigset_t ign = value;
Packit 6c4009
	__spin_lock (&ss->lock);
Packit 6c4009
	for (sig = 1; sig < NSIG; ++sig)
Packit 6c4009
	  {
Packit 6c4009
	    if (__sigismember (&ign, sig))
Packit 6c4009
	      ss->actions[sig].sa_handler = SIG_IGN;
Packit 6c4009
	    else if (ss->actions[sig].sa_handler == SIG_IGN)
Packit 6c4009
	      ss->actions[sig].sa_handler = SIG_DFL;
Packit 6c4009
	  }
Packit 6c4009
	__spin_unlock (&ss->lock);
Packit 6c4009
	return 0;
Packit 6c4009
Packit 6c4009
      case INIT_TRACEMASK:
Packit 6c4009
	_hurdsig_traced = value;
Packit 6c4009
	return 0;
Packit 6c4009
      }
Packit 6c4009
    default:
Packit 6c4009
      return EINVAL;
Packit 6c4009
    }
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		     int which, int value)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  return set_int (which, value);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
		      int *values, mach_msg_type_number_t nvalues)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  mach_msg_type_number_t i;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  for (i = 0; i < INIT_INT_MAX; ++i)
Packit 6c4009
    switch (err = set_int (i, values[i]))
Packit 6c4009
      {
Packit 6c4009
      case 0:			/* Success.  */
Packit 6c4009
	break;
Packit 6c4009
      case EINVAL:		/* Unknown index.  */
Packit 6c4009
	break;
Packit 6c4009
      default:			/* Lossage.  */
Packit 6c4009
	return err;
Packit 6c4009
      }
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
Packit 6c4009
	       mach_port_t *result, mach_msg_type_name_t *result_type)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  /* This creates a new user reference for the send right.
Packit 6c4009
     Our reply message will move that reference to the caller.  */
Packit 6c4009
  *result = __getdport (which);
Packit 6c4009
  if (*result == MACH_PORT_NULL)
Packit 6c4009
    return errno;
Packit 6c4009
  *result_type = MACH_MSG_TYPE_MOVE_SEND;
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
	       int which, mach_port_t port)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  /* We consume the reference if successful.  */
Packit 6c4009
  return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
/* Snarfing and frobbing environment variables.  */
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_env_variable (mach_port_t msgport,
Packit 6c4009
			 char *variable,
Packit 6c4009
			 char **data, mach_msg_type_number_t *datalen)
Packit 6c4009
{
Packit 6c4009
  error_t err;
Packit 6c4009
  mach_msg_type_number_t valuelen;
Packit 6c4009
  const char *value = getenv (variable);
Packit 6c4009
Packit 6c4009
  if (value == NULL)
Packit 6c4009
    return ENOENT;
Packit 6c4009
Packit 6c4009
  valuelen = strlen (value);
Packit 6c4009
  if (valuelen > *datalen)
Packit 6c4009
    {
Packit 6c4009
      if (err = __vm_allocate (__mach_task_self (),
Packit 6c4009
			       (vm_address_t *) data, valuelen, 1))
Packit 6c4009
	return err;
Packit 6c4009
    }
Packit 6c4009
Packit 6c4009
  memcpy (*data, value, valuelen);
Packit 6c4009
  *datalen = valuelen;
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
			 char *variable,
Packit 6c4009
			 char *value,
Packit 6c4009
			 int replace)
Packit 6c4009
{
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  if (__setenv (variable, value, replace)) /* XXX name space */
Packit 6c4009
    return errno;
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_environment (mach_port_t msgport,
Packit 6c4009
			char **data, mach_msg_type_number_t *datalen)
Packit 6c4009
{
Packit 6c4009
  /* Pack the environment into an array with nulls separating elements.  */
Packit 6c4009
  if (__environ != NULL)
Packit 6c4009
    {
Packit 6c4009
      char *ap, **p;
Packit 6c4009
      size_t envlen = 0;
Packit 6c4009
Packit 6c4009
      for (p = __environ; *p != NULL; ++p)
Packit 6c4009
	envlen += strlen (*p) + 1;
Packit 6c4009
Packit 6c4009
      if (envlen > *datalen)
Packit 6c4009
	{
Packit 6c4009
	  if (__vm_allocate (__mach_task_self (),
Packit 6c4009
			     (vm_address_t *) data, envlen, 1))
Packit 6c4009
	    return ENOMEM;
Packit 6c4009
	}
Packit 6c4009
Packit 6c4009
      ap = *data;
Packit 6c4009
      for (p = __environ; *p != NULL; ++p)
Packit 6c4009
	ap = __memccpy (ap, *p, '\0', ULONG_MAX);
Packit 6c4009
Packit 6c4009
      *datalen = envlen;
Packit 6c4009
    }
Packit 6c4009
  else
Packit 6c4009
    *datalen = 0;
Packit 6c4009
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
Packit 6c4009
			char *data, mach_msg_type_number_t datalen)
Packit 6c4009
{
Packit 6c4009
  int _hurd_split_args (char *, mach_msg_type_number_t, char **);
Packit 6c4009
  int envc;
Packit 6c4009
  char **envp;
Packit 6c4009
Packit 6c4009
  AUTHCHECK;
Packit 6c4009
Packit 6c4009
  envc = __argz_count (data, datalen);
Packit 6c4009
  envp = malloc ((envc + 1) * sizeof (char *));
Packit 6c4009
  if (envp == NULL)
Packit 6c4009
    return errno;
Packit 6c4009
  __argz_extract (data, datalen, envp);
Packit 6c4009
  __environ = envp;		/* XXX cooperate with loadenv et al */
Packit 6c4009
  return 0;
Packit 6c4009
}
Packit 6c4009

Packit 6c4009
Packit 6c4009
/* XXX */
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_get_dtable (mach_port_t process,
Packit 6c4009
		   mach_port_t refport,
Packit 6c4009
		   portarray_t *dtable,
Packit 6c4009
		   mach_msg_type_name_t *dtablePoly,
Packit 6c4009
		   mach_msg_type_number_t *dtableCnt)
Packit 6c4009
{ return EOPNOTSUPP; }
Packit 6c4009
Packit 6c4009
kern_return_t
Packit 6c4009
_S_msg_set_dtable (mach_port_t process,
Packit 6c4009
		   mach_port_t refport,
Packit 6c4009
		   portarray_t dtable,
Packit 6c4009
		   mach_msg_type_number_t dtableCnt)
Packit 6c4009
{ return EOPNOTSUPP; }