]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurdmsg.c
2004-04-30 Roland McGrath <roland@frob.com>
[thirdparty/glibc.git] / hurd / hurdmsg.c
CommitLineData
c84142e8
UD
1/* Copyright (C) 1992, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3
4 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
c84142e8
UD
8
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
41bdb6e2 12 Lesser General Public License for more details.
c84142e8 13
41bdb6e2
AJ
14 You should have received a copy of the GNU Lesser General Public
15 License along with the GNU C Library; if not, write to the Free
16 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17 02111-1307 USA. */
28f540f4
RM
18
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>
8f0c527e 25#include <argz.h>
28f540f4
RM
26
27
28#define AUTHCHECK \
29 if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
30 return EPERM
31
32
33/* Snarfing and frobbing the init ports. */
34
35kern_return_t
853f0eea
RM
36 _S_msg_get_init_port (mach_port_t msgport, mach_port_t auth, int which,
37 mach_port_t *result, mach_msg_type_name_t *result_type)
28f540f4
RM
38{
39 AUTHCHECK;
40 *result_type = MACH_MSG_TYPE_MOVE_SEND;
41 /* This function adds a new user reference for the *RESULT it gives back.
42 Our reply message uses a move-send right that consumes this reference. */
43 return _hurd_ports_get (which, result);
44}
45
46kern_return_t
47_S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
853f0eea 48 int which, mach_port_t port)
28f540f4
RM
49{
50 error_t err;
51
52 AUTHCHECK;
53
54 err = _hurd_ports_set (which, port);
55 if (err == 0)
56 __mach_port_deallocate (__mach_task_self (), port);
57
58 return 0;
59}
60
61kern_return_t
62_S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
853f0eea
RM
63 mach_port_t **ports,
64 mach_msg_type_name_t *ports_type,
65 mach_msg_type_number_t *nports)
28f540f4
RM
66{
67 mach_msg_type_number_t i;
68 error_t err;
69
70 AUTHCHECK;
71
72 if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) ports,
73 _hurd_nports * sizeof (mach_port_t), 1))
74 return err;
75 *nports = _hurd_nports;
76
77 for (i = 0; i < _hurd_nports; ++i)
78 /* This function adds a new user ref for the *RESULT it gives back.
79 Our reply message uses move-send rights that consumes this ref. */
80 if (err = _hurd_ports_get (i, &(*ports)[i]))
81 {
82 /* Died part way through. Deallocate the ports already fetched. */
83 while (i-- > 0)
84 __mach_port_deallocate (__mach_task_self (), (*ports)[i]);
85 __vm_deallocate (__mach_task_self (),
86 (vm_address_t) *ports,
87 *nports * sizeof (mach_port_t));
88 return err;
89 }
90
91 *ports_type = MACH_MSG_TYPE_MOVE_SEND;
92 return 0;
93}
94
95kern_return_t
96_S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
853f0eea 97 mach_port_t *ports, mach_msg_type_number_t nports)
28f540f4
RM
98{
99 mach_msg_type_number_t i;
100 error_t err;
101
102 AUTHCHECK;
103
104 for (i = 0; i < _hurd_nports; ++i)
105 {
106 if (err = _hurd_ports_set (i, ports[i]))
107 return err;
108 else
109 __mach_port_deallocate (__mach_task_self (), ports[i]);
110 }
111
112 return 0;
113}
114\f
115/* Snarfing and frobbing the init ints. */
116
117static kern_return_t
118get_int (int which, int *value)
119{
120 switch (which)
121 {
122 case INIT_UMASK:
123 *value = _hurd_umask;
124 return 0;
125 case INIT_SIGMASK:
126 {
127 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
128 __spin_lock (&ss->lock);
129 *value = ss->blocked;
130 __spin_unlock (&ss->lock);
131 return 0;
132 }
133 case INIT_SIGPENDING:
134 {
135 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
136 __spin_lock (&ss->lock);
137 *value = ss->pending;
138 __spin_unlock (&ss->lock);
139 return 0;
140 }
141 case INIT_SIGIGN:
142 {
143 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
144 sigset_t ign;
145 int sig;
146 __spin_lock (&ss->lock);
147 __sigemptyset (&ign);
148 for (sig = 1; sig < NSIG; ++sig)
149 if (ss->actions[sig].sa_handler == SIG_IGN)
150 __sigaddset (&ign, sig);
151 __spin_unlock (&ss->lock);
152 *value = ign;
153 return 0;
154 }
155 default:
156 return EINVAL;
157 }
158}
159
160kern_return_t
161_S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
853f0eea 162 int which, int *value)
28f540f4
RM
163{
164 AUTHCHECK;
165
166 return get_int (which, value);
167}
168
169kern_return_t
170_S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
853f0eea 171 int **values, mach_msg_type_number_t *nvalues)
28f540f4
RM
172{
173 error_t err;
174 mach_msg_type_number_t i;
175
176 AUTHCHECK;
177
178 if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values,
179 INIT_INT_MAX * sizeof (int), 1))
180 return err;
181 *nvalues = INIT_INT_MAX;
182
183 for (i = 0; i < INIT_INT_MAX; ++i)
184 switch (err = get_int (i, &(*values)[i]))
185 {
186 case 0: /* Success. */
187 break;
188 case EINVAL: /* Unknown index. */
189 (*values)[i] = 0;
190 break;
191 default: /* Lossage. */
192 __vm_deallocate (__mach_task_self (),
193 (vm_address_t) *values, INIT_INT_MAX * sizeof (int));
194 return err;
195 }
196
197 return 0;
198}
199
200
201static kern_return_t
202set_int (int which, int value)
203{
204 switch (which)
205 {
206 case INIT_UMASK:
207 _hurd_umask = value;
208 return 0;
209
210 /* These are pretty odd things to do. But you asked for it. */
211 case INIT_SIGMASK:
212 {
213 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
214 __spin_lock (&ss->lock);
215 ss->blocked = value;
216 __spin_unlock (&ss->lock);
217 return 0;
218 }
219 case INIT_SIGPENDING:
220 {
221 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
222 __spin_lock (&ss->lock);
223 ss->pending = value;
224 __spin_unlock (&ss->lock);
225 return 0;
226 }
227 case INIT_SIGIGN:
228 {
229 struct hurd_sigstate *ss = _hurd_thread_sigstate (_hurd_sigthread);
230 int sig;
231 const sigset_t ign = value;
232 __spin_lock (&ss->lock);
233 for (sig = 1; sig < NSIG; ++sig)
234 {
235 if (__sigismember (&ign, sig))
236 ss->actions[sig].sa_handler = SIG_IGN;
237 else if (ss->actions[sig].sa_handler == SIG_IGN)
238 ss->actions[sig].sa_handler = SIG_DFL;
239 }
240 __spin_unlock (&ss->lock);
241 return 0;
fe4d0ab7
MB
242
243 case INIT_TRACEMASK:
244 _hurdsig_traced = value;
245 return 0;
28f540f4
RM
246 }
247 default:
248 return EINVAL;
249 }
250}
251
252kern_return_t
253_S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
853f0eea 254 int which, int value)
28f540f4
RM
255{
256 AUTHCHECK;
257
258 return set_int (which, value);
259}
260
261kern_return_t
262_S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
853f0eea 263 int *values, mach_msg_type_number_t nvalues)
28f540f4
RM
264{
265 error_t err;
266 mach_msg_type_number_t i;
267
268 AUTHCHECK;
269
270 for (i = 0; i < INIT_INT_MAX; ++i)
271 switch (err = set_int (i, values[i]))
272 {
273 case 0: /* Success. */
274 break;
275 case EINVAL: /* Unknown index. */
276 break;
277 default: /* Lossage. */
278 return err;
279 }
280
281 return 0;
282}
283\f
284
285kern_return_t
853f0eea
RM
286_S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
287 mach_port_t *result, mach_msg_type_name_t *result_type)
28f540f4
RM
288{
289 AUTHCHECK;
290
291 /* This creates a new user reference for the send right.
292 Our reply message will move that reference to the caller. */
293 *result = __getdport (which);
294 if (*result == MACH_PORT_NULL)
295 return errno;
296 *result_type = MACH_MSG_TYPE_MOVE_SEND;
297
298 return 0;
299}
300
301kern_return_t
302_S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
853f0eea 303 int which, mach_port_t port)
28f540f4
RM
304{
305 AUTHCHECK;
306
307 /* We consume the reference if successful. */
308 return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
309}
310\f
311/* Snarfing and frobbing environment variables. */
312
313kern_return_t
314_S_msg_get_env_variable (mach_port_t msgport,
853f0eea
RM
315 char *variable,
316 char **data, mach_msg_type_number_t *datalen)
28f540f4 317{
2b25f93f
UD
318 error_t err;
319 mach_msg_type_number_t valuelen;
28f540f4
RM
320 const char *value = getenv (variable);
321
322 if (value == NULL)
323 return ENOENT;
324
2b25f93f
UD
325 valuelen = strlen (value);
326 if (valuelen > *datalen)
327 {
328 if (err = __vm_allocate (__mach_task_self (),
329 (vm_address_t *) data, valuelen, 1))
330 return err;
331 }
332
333 memcpy (*data, value, valuelen);
334 *datalen = valuelen;
335
28f540f4
RM
336 return 0;
337}
338
339
340kern_return_t
341_S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
853f0eea
RM
342 char *variable,
343 char *value,
344 int replace)
28f540f4
RM
345{
346 AUTHCHECK;
347
348 if (setenv (variable, value, replace)) /* XXX name space */
349 return errno;
350 return 0;
351}
352
353kern_return_t
354_S_msg_get_environment (mach_port_t msgport,
853f0eea 355 char **data, mach_msg_type_number_t *datalen)
28f540f4
RM
356{
357 /* Pack the environment into an array with nulls separating elements. */
358 if (__environ != NULL)
359 {
360 char *ap, **p;
361 size_t envlen = 0;
362
363 for (p = __environ; *p != NULL; ++p)
364 envlen += strlen (*p) + 1;
365
366 if (envlen > *datalen)
367 {
368 if (__vm_allocate (__mach_task_self (),
369 (vm_address_t *) data, envlen, 1))
370 return ENOMEM;
371 }
372
373 ap = *data;
374 for (p = __environ; *p != NULL; ++p)
375 ap = __memccpy (ap, *p, '\0', ULONG_MAX);
376
377 *datalen = envlen;
378 }
379 else
380 *datalen = 0;
381
382 return 0;
383}
384
385kern_return_t
386_S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
853f0eea 387 char *data, mach_msg_type_number_t datalen)
28f540f4
RM
388{
389 int _hurd_split_args (char *, mach_msg_type_number_t, char **);
390 int envc;
391 char **envp;
392
393 AUTHCHECK;
394
8f0c527e 395 envc = __argz_count (data, datalen);
28f540f4
RM
396 envp = malloc ((envc + 1) * sizeof (char *));
397 if (envp == NULL)
398 return errno;
8f0c527e 399 __argz_extract (data, datalen, envp);
28f540f4
RM
400 __environ = envp; /* XXX cooperate with loadenv et al */
401 return 0;
402}
403\f
28f540f4
RM
404
405/* XXX */
406
407kern_return_t
408_S_msg_get_dtable (mach_port_t process,
853f0eea
RM
409 mach_port_t refport,
410 portarray_t *dtable,
411 mach_msg_type_name_t *dtablePoly,
412 mach_msg_type_number_t *dtableCnt)
28f540f4
RM
413{ return EOPNOTSUPP; }
414
415kern_return_t
416_S_msg_set_dtable (mach_port_t process,
853f0eea
RM
417 mach_port_t refport,
418 portarray_t dtable,
419 mach_msg_type_number_t dtableCnt)
28f540f4 420{ return EOPNOTSUPP; }