initial import
[glibc.git] / hurd / hurdmsg.c
blob57b6b8dd679578c45a296765e21784d1c1a64441
1 /* Copyright (C) 1992, 1994, 1995 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
19 #include <hurd.h>
20 #include <hurd/msg_server.h>
21 #include <hurd/fd.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <string.h>
27 #define AUTHCHECK \
28 if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
29 return EPERM
32 /* Snarfing and frobbing the init ports. */
34 kern_return_t
35 _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
36 mach_port_t *result, mach_msg_type_name_t *result_type)
38 AUTHCHECK;
39 *result_type = MACH_MSG_TYPE_MOVE_SEND;
40 /* This function adds a new user reference for the *RESULT it gives back.
41 Our reply message uses a move-send right that consumes this reference. */
42 return _hurd_ports_get (which, result);
45 kern_return_t
46 _S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
47 int which, mach_port_t port)
49 error_t err;
51 AUTHCHECK;
53 err = _hurd_ports_set (which, port);
54 if (err == 0)
55 __mach_port_deallocate (__mach_task_self (), port);
57 return 0;
60 kern_return_t
61 _S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
62 mach_port_t **ports,
63 mach_msg_type_name_t *ports_type,
64 mach_msg_type_number_t *nports)
66 mach_msg_type_number_t i;
67 error_t err;
69 AUTHCHECK;
71 if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
72 _hurd_nports * sizeof (mach_port_t), 1))
73 return err;
74 *nports = _hurd_nports;
76 for (i = 0; i < _hurd_nports; ++i)
77 /* This function adds a new user ref for the *RESULT it gives back.
78 Our reply message uses move-send rights that consumes this ref. */
79 if (err = _hurd_ports_get (i, &(*ports)[i]))
81 /* Died part way through. Deallocate the ports already fetched. */
82 while (i-- > 0)
83 __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
84 __vm_deallocate (__mach_task_self (),
85 (vm_address_t) *ports,
86 *nports * sizeof (mach_port_t));
87 return err;
90 *ports_type = MACH_MSG_TYPE_MOVE_SEND;
91 return 0;
94 kern_return_t
95 _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
96 mach_port_t *ports, mach_msg_type_number_t nports)
98 mach_msg_type_number_t i;
99 error_t err;
101 AUTHCHECK;
103 for (i = 0; i < _hurd_nports; ++i)
105 if (err = _hurd_ports_set (i, ports[i]))
106 return err;
107 else
108 __mach_port_deallocate (__mach_task_self (), ports[i]);
111 return 0;
114 /* Snarfing and frobbing the init ints. */
116 static kern_return_t
117 get_int (int which, int *value)
119 switch (which)
121 case INIT_UMASK:
122 *value = _hurd_umask;
123 return 0;
124 case INIT_SIGMASK:
126 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
127 __spin_lock (&ss->lock);
128 *value = ss->blocked;
129 __spin_unlock (&ss->lock);
130 return 0;
132 case INIT_SIGPENDING:
134 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
135 __spin_lock (&ss->lock);
136 *value = ss->pending;
137 __spin_unlock (&ss->lock);
138 return 0;
140 case INIT_SIGIGN:
142 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
143 sigset_t ign;
144 int sig;
145 __spin_lock (&ss->lock);
146 __sigemptyset (&ign);
147 for (sig = 1; sig < NSIG; ++sig)
148 if (ss->actions[sig].sa_handler == SIG_IGN)
149 __sigaddset (&ign, sig);
150 __spin_unlock (&ss->lock);
151 *value = ign;
152 return 0;
154 default:
155 return EINVAL;
159 kern_return_t
160 _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
161 int which, int *value)
163 AUTHCHECK;
165 return get_int (which, value);
168 kern_return_t
169 _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
170 int **values, mach_msg_type_number_t *nvalues)
172 error_t err;
173 mach_msg_type_number_t i;
175 AUTHCHECK;
177 if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
178 INIT_INT_MAX * sizeof (int), 1))
179 return err;
180 *nvalues = INIT_INT_MAX;
182 for (i = 0; i < INIT_INT_MAX; ++i)
183 switch (err = get_int (i, &(*values)[i]))
185 case 0: /* Success. */
186 break;
187 case EINVAL: /* Unknown index. */
188 (*values)[i] = 0;
189 break;
190 default: /* Lossage. */
191 __vm_deallocate (__mach_task_self (),
192 (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
193 return err;
196 return 0;
200 static kern_return_t
201 set_int (int which, int value)
203 switch (which)
205 case INIT_UMASK:
206 _hurd_umask = value;
207 return 0;
209 /* These are pretty odd things to do. But you asked for it. */
210 case INIT_SIGMASK:
212 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
213 __spin_lock (&ss->lock);
214 ss->blocked = value;
215 __spin_unlock (&ss->lock);
216 return 0;
218 case INIT_SIGPENDING:
220 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
221 __spin_lock (&ss->lock);
222 ss->pending = value;
223 __spin_unlock (&ss->lock);
224 return 0;
226 case INIT_SIGIGN:
228 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
229 int sig;
230 const sigset_t ign = value;
231 __spin_lock (&ss->lock);
232 for (sig = 1; sig < NSIG; ++sig)
234 if (__sigismember (&ign, sig))
235 ss->actions[sig].sa_handler = SIG_IGN;
236 else if (ss->actions[sig].sa_handler == SIG_IGN)
237 ss->actions[sig].sa_handler = SIG_DFL;
239 __spin_unlock (&ss->lock);
240 return 0;
242 default:
243 return EINVAL;
247 kern_return_t
248 _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
249 int which, int value)
251 AUTHCHECK;
253 return set_int (which, value);
256 kern_return_t
257 _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
258 int *values, mach_msg_type_number_t nvalues)
260 error_t err;
261 mach_msg_type_number_t i;
263 AUTHCHECK;
265 for (i = 0; i < INIT_INT_MAX; ++i)
266 switch (err = set_int (i, values[i]))
268 case 0: /* Success. */
269 break;
270 case EINVAL: /* Unknown index. */
271 break;
272 default: /* Lossage. */
273 return err;
276 return 0;
280 kern_return_t
281 _S_msg_get_fd (mach_port_t msgport, mach_port_t auth,
282 int which, mach_port_t *result, mach_msg_type_name_t *result_type)
284 AUTHCHECK;
286 /* This creates a new user reference for the send right.
287 Our reply message will move that reference to the caller. */
288 *result = __getdport (which);
289 if (*result == MACH_PORT_NULL)
290 return errno;
291 *result_type = MACH_MSG_TYPE_MOVE_SEND;
293 return 0;
296 kern_return_t
297 _S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
298 int which, mach_port_t port)
300 AUTHCHECK;
302 /* We consume the reference if successful. */
303 return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
306 /* Snarfing and frobbing environment variables. */
308 kern_return_t
309 _S_msg_get_env_variable (mach_port_t msgport,
310 char *variable,
311 char **data, mach_msg_type_number_t *datalen)
313 const char *value = getenv (variable);
315 if (value == NULL)
316 return ENOENT;
318 /* XXX this pointer might become invalid */
319 *data = value;
320 *datalen = strlen (value);
321 return 0;
325 kern_return_t
326 _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
327 char *variable,
328 char *value,
329 int replace)
331 AUTHCHECK;
333 if (setenv (variable, value, replace)) /* XXX name space */
334 return errno;
335 return 0;
338 kern_return_t
339 _S_msg_get_environment (mach_port_t msgport,
340 char **data, mach_msg_type_number_t *datalen)
342 /* Pack the environment into an array with nulls separating elements. */
343 if (__environ != NULL)
345 char *ap, **p;
346 size_t envlen = 0;
348 for (p = __environ; *p != NULL; ++p)
349 envlen += strlen (*p) + 1;
351 if (envlen > *datalen)
353 if (__vm_allocate (__mach_task_self (),
354 (vm_address_t *) data, envlen, 1))
355 return ENOMEM;
358 ap = *data;
359 for (p = __environ; *p != NULL; ++p)
360 ap = __memccpy (ap, *p, '\0', ULONG_MAX);
362 *datalen = envlen;
364 else
365 *datalen = 0;
367 return 0;
370 kern_return_t
371 _S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
372 char *data, mach_msg_type_number_t datalen)
374 int _hurd_split_args (char *, mach_msg_type_number_t, char **);
375 int envc;
376 char **envp;
378 AUTHCHECK;
380 envc = _hurd_split_args (data, datalen, NULL);
381 envp = malloc ((envc + 1) * sizeof (char *));
382 if (envp == NULL)
383 return errno;
384 _hurd_split_args (data, datalen, envp);
385 __environ = envp; /* XXX cooperate with loadenv et al */
386 return 0;
389 /* Get and frob the exec flags. */
391 kern_return_t
392 _S_msg_get_exec_flags (mach_port_t process, mach_port_t auth,
393 int *flags)
395 AUTHCHECK;
397 *flags = _hurd_exec_flags;
398 return 0;
401 kern_return_t
402 _S_msg_set_all_exec_flags (mach_port_t process, mach_port_t auth,
403 int flags)
405 AUTHCHECK;
407 _hurd_exec_flags = flags;
408 return 0;
411 kern_return_t
412 _S_msg_set_some_exec_flags (mach_port_t process, mach_port_t auth,
413 int flags)
415 AUTHCHECK;
417 _hurd_exec_flags |= flags;
418 return 0;
421 kern_return_t
422 _S_msg_clear_some_exec_flags (mach_port_t process, mach_port_t auth,
423 int flags)
425 AUTHCHECK;
427 _hurd_exec_flags &= ~flags;
428 return 0;
432 /* XXX */
434 kern_return_t
435 _S_msg_get_dtable (mach_port_t process,
436 mach_port_t refport,
437 portarray_t *dtable,
438 mach_msg_type_name_t *dtablePoly,
439 mach_msg_type_number_t *dtableCnt)
440 { return EOPNOTSUPP; }
442 kern_return_t
443 _S_msg_set_dtable (mach_port_t process,
444 mach_port_t refport,
445 portarray_t dtable,
446 mach_msg_type_number_t dtableCnt)
447 { return EOPNOTSUPP; }
449 kern_return_t
450 _S_msg_startup_dosync (mach_port_t process)
451 { return EOPNOTSUPP; }