mirror of
				https://sourceware.org/git/glibc.git
				synced 2025-10-26 00:57:39 +03:00 
			
		
		
		
	2001-07-06 Paul Eggert <eggert@twinsun.com> * manual/argp.texi: Remove ignored LGPL copyright notice; it's not appropriate for documentation anyway. * manual/libc-texinfo.sh: "Library General Public License" -> "Lesser General Public License". 2001-07-06 Andreas Jaeger <aj@suse.de> * All files under GPL/LGPL version 2: Place under LGPL version 2.1.
		
			
				
	
	
		
			421 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			421 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /* Copyright (C) 1992, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
 | ||
|    This file is part of the GNU C Library.
 | ||
| 
 | ||
|    The GNU C Library is free software; you can redistribute it and/or
 | ||
|    modify it under the terms of the GNU Lesser General Public
 | ||
|    License as published by the Free Software Foundation; either
 | ||
|    version 2.1 of the License, or (at your option) any later version.
 | ||
| 
 | ||
|    The GNU C Library is distributed in the hope that it will be useful,
 | ||
|    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | ||
|    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 | ||
|    Lesser General Public License for more details.
 | ||
| 
 | ||
|    You should have received a copy of the GNU Lesser General Public
 | ||
|    License along with the GNU C Library; if not, write to the Free
 | ||
|    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 | ||
|    02111-1307 USA.  */
 | ||
| 
 | ||
| #include <hurd.h>
 | ||
| #include <hurd/msg_server.h>
 | ||
| #include <hurd/fd.h>
 | ||
| #include <unistd.h>
 | ||
| #include <limits.h>
 | ||
| #include <string.h>
 | ||
| #include <argz.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;
 | ||
| 
 | ||
|       case INIT_TRACEMASK:
 | ||
| 	_hurdsig_traced = value;
 | ||
| 	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)
 | ||
| {
 | ||
|   error_t err;
 | ||
|   mach_msg_type_number_t valuelen;
 | ||
|   const char *value = getenv (variable);
 | ||
| 
 | ||
|   if (value == NULL)
 | ||
|     return ENOENT;
 | ||
| 
 | ||
|   valuelen = strlen (value);
 | ||
|   if (valuelen > *datalen)
 | ||
|     {
 | ||
|       if (err = __vm_allocate (__mach_task_self (), 
 | ||
| 			       (vm_address_t *) data, valuelen, 1))
 | ||
| 	return err;
 | ||
|     }
 | ||
| 
 | ||
|   memcpy (*data, value, valuelen);
 | ||
|   *datalen = valuelen;
 | ||
| 
 | ||
|   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 = __argz_count (data, datalen);
 | ||
|   envp = malloc ((envc + 1) * sizeof (char *));
 | ||
|   if (envp == NULL)
 | ||
|     return errno;
 | ||
|   __argz_extract (data, datalen, envp);
 | ||
|   __environ = envp;		/* XXX cooperate with loadenv et al */
 | ||
|   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; }
 |