]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/hurdmsg.c
Prefer https to http for gnu.org and fsf.org URLs
[thirdparty/glibc.git] / hurd / hurdmsg.c
CommitLineData
04277e02 1/* Copyright (C) 1992-2019 Free Software Foundation, Inc.
c84142e8
UD
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 14 You should have received a copy of the GNU Lesser General Public
59ba27a6 15 License along with the GNU C Library; if not, see
5a82c748 16 <https://www.gnu.org/licenses/>. */
28f540f4
RM
17
18#include <hurd.h>
19#include <hurd/msg_server.h>
20#include <hurd/fd.h>
21#include <unistd.h>
22#include <limits.h>
23#include <string.h>
8f0c527e 24#include <argz.h>
28f540f4
RM
25
26
27#define AUTHCHECK \
28 if (auth != mach_task_self () && ! __USEPORT (AUTH, port == auth)) \
29 return EPERM
30
31
32/* Snarfing and frobbing the init ports. */
33
34kern_return_t
853f0eea
RM
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)
28f540f4
RM
37{
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);
43}
44
45kern_return_t
46_S_msg_set_init_port (mach_port_t msgport, mach_port_t auth,
853f0eea 47 int which, mach_port_t port)
28f540f4
RM
48{
49 error_t err;
50
51 AUTHCHECK;
52
53 err = _hurd_ports_set (which, port);
54 if (err == 0)
55 __mach_port_deallocate (__mach_task_self (), port);
56
57 return 0;
58}
59
60kern_return_t
61_S_msg_get_init_ports (mach_port_t msgport, mach_port_t auth,
853f0eea
RM
62 mach_port_t **ports,
63 mach_msg_type_name_t *ports_type,
64 mach_msg_type_number_t *nports)
28f540f4
RM
65{
66 mach_msg_type_number_t i;
67 error_t err;
68
69 AUTHCHECK;
70
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;
75
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]))
80 {
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;
88 }
89
90 *ports_type = MACH_MSG_TYPE_MOVE_SEND;
91 return 0;
92}
93
94kern_return_t
95_S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth,
853f0eea 96 mach_port_t *ports, mach_msg_type_number_t nports)
28f540f4
RM
97{
98 mach_msg_type_number_t i;
99 error_t err;
100
101 AUTHCHECK;
102
103 for (i = 0; i < _hurd_nports; ++i)
104 {
105 if (err = _hurd_ports_set (i, ports[i]))
106 return err;
107 else
108 __mach_port_deallocate (__mach_task_self (), ports[i]);
109 }
110
111 return 0;
112}
113\f
114/* Snarfing and frobbing the init ints. */
115
116static kern_return_t
117get_int (int which, int *value)
118{
119 switch (which)
120 {
121 case INIT_UMASK:
122 *value = _hurd_umask;
123 return 0;
124 case INIT_SIGMASK:
125 {
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;
131 }
132 case INIT_SIGPENDING:
133 {
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;
139 }
140 case INIT_SIGIGN:
141 {
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;
153 }
154 default:
155 return EINVAL;
156 }
157}
158
159kern_return_t
160_S_msg_get_init_int (mach_port_t msgport, mach_port_t auth,
853f0eea 161 int which, int *value)
28f540f4
RM
162{
163 AUTHCHECK;
164
165 return get_int (which, value);
166}
167
168kern_return_t
169_S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth,
853f0eea 170 int **values, mach_msg_type_number_t *nvalues)
28f540f4
RM
171{
172 error_t err;
173 mach_msg_type_number_t i;
174
175 AUTHCHECK;
176
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;
181
182 for (i = 0; i < INIT_INT_MAX; ++i)
183 switch (err = get_int (i, &(*values)[i]))
184 {
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;
194 }
195
196 return 0;
197}
198
199
200static kern_return_t
201set_int (int which, int value)
202{
203 switch (which)
204 {
205 case INIT_UMASK:
206 _hurd_umask = value;
207 return 0;
208
209 /* These are pretty odd things to do. But you asked for it. */
210 case INIT_SIGMASK:
211 {
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;
217 }
218 case INIT_SIGPENDING:
219 {
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;
225 }
226 case INIT_SIGIGN:
227 {
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)
233 {
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;
238 }
239 __spin_unlock (&ss->lock);
240 return 0;
fe4d0ab7
MB
241
242 case INIT_TRACEMASK:
243 _hurdsig_traced = value;
244 return 0;
28f540f4
RM
245 }
246 default:
247 return EINVAL;
248 }
249}
250
251kern_return_t
252_S_msg_set_init_int (mach_port_t msgport, mach_port_t auth,
853f0eea 253 int which, int value)
28f540f4
RM
254{
255 AUTHCHECK;
256
257 return set_int (which, value);
258}
259
260kern_return_t
261_S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth,
853f0eea 262 int *values, mach_msg_type_number_t nvalues)
28f540f4
RM
263{
264 error_t err;
265 mach_msg_type_number_t i;
266
267 AUTHCHECK;
268
269 for (i = 0; i < INIT_INT_MAX; ++i)
270 switch (err = set_int (i, values[i]))
271 {
272 case 0: /* Success. */
273 break;
274 case EINVAL: /* Unknown index. */
275 break;
276 default: /* Lossage. */
277 return err;
278 }
279
280 return 0;
281}
282\f
283
284kern_return_t
853f0eea
RM
285_S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which,
286 mach_port_t *result, mach_msg_type_name_t *result_type)
28f540f4
RM
287{
288 AUTHCHECK;
289
290 /* This creates a new user reference for the send right.
291 Our reply message will move that reference to the caller. */
292 *result = __getdport (which);
293 if (*result == MACH_PORT_NULL)
294 return errno;
295 *result_type = MACH_MSG_TYPE_MOVE_SEND;
296
297 return 0;
298}
299
300kern_return_t
301_S_msg_set_fd (mach_port_t msgport, mach_port_t auth,
853f0eea 302 int which, mach_port_t port)
28f540f4
RM
303{
304 AUTHCHECK;
305
306 /* We consume the reference if successful. */
307 return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0));
308}
309\f
310/* Snarfing and frobbing environment variables. */
311
312kern_return_t
313_S_msg_get_env_variable (mach_port_t msgport,
853f0eea
RM
314 char *variable,
315 char **data, mach_msg_type_number_t *datalen)
28f540f4 316{
2b25f93f
UD
317 error_t err;
318 mach_msg_type_number_t valuelen;
28f540f4
RM
319 const char *value = getenv (variable);
320
321 if (value == NULL)
322 return ENOENT;
323
2b25f93f
UD
324 valuelen = strlen (value);
325 if (valuelen > *datalen)
326 {
9c84384c 327 if (err = __vm_allocate (__mach_task_self (),
2b25f93f
UD
328 (vm_address_t *) data, valuelen, 1))
329 return err;
330 }
331
332 memcpy (*data, value, valuelen);
333 *datalen = valuelen;
334
28f540f4
RM
335 return 0;
336}
337
338
339kern_return_t
340_S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth,
853f0eea
RM
341 char *variable,
342 char *value,
343 int replace)
28f540f4
RM
344{
345 AUTHCHECK;
346
dba2bdbe 347 if (__setenv (variable, value, replace)) /* XXX name space */
28f540f4
RM
348 return errno;
349 return 0;
350}
351
352kern_return_t
353_S_msg_get_environment (mach_port_t msgport,
853f0eea 354 char **data, mach_msg_type_number_t *datalen)
28f540f4
RM
355{
356 /* Pack the environment into an array with nulls separating elements. */
357 if (__environ != NULL)
358 {
359 char *ap, **p;
360 size_t envlen = 0;
361
362 for (p = __environ; *p != NULL; ++p)
363 envlen += strlen (*p) + 1;
364
365 if (envlen > *datalen)
366 {
367 if (__vm_allocate (__mach_task_self (),
368 (vm_address_t *) data, envlen, 1))
369 return ENOMEM;
370 }
371
372 ap = *data;
373 for (p = __environ; *p != NULL; ++p)
374 ap = __memccpy (ap, *p, '\0', ULONG_MAX);
375
376 *datalen = envlen;
377 }
378 else
379 *datalen = 0;
380
381 return 0;
382}
383
384kern_return_t
385_S_msg_set_environment (mach_port_t msgport, mach_port_t auth,
853f0eea 386 char *data, mach_msg_type_number_t datalen)
28f540f4
RM
387{
388 int _hurd_split_args (char *, mach_msg_type_number_t, char **);
389 int envc;
390 char **envp;
391
392 AUTHCHECK;
393
8f0c527e 394 envc = __argz_count (data, datalen);
28f540f4
RM
395 envp = malloc ((envc + 1) * sizeof (char *));
396 if (envp == NULL)
397 return errno;
8f0c527e 398 __argz_extract (data, datalen, envp);
28f540f4
RM
399 __environ = envp; /* XXX cooperate with loadenv et al */
400 return 0;
401}
402\f
28f540f4
RM
403
404/* XXX */
405
406kern_return_t
407_S_msg_get_dtable (mach_port_t process,
853f0eea
RM
408 mach_port_t refport,
409 portarray_t *dtable,
410 mach_msg_type_name_t *dtablePoly,
411 mach_msg_type_number_t *dtableCnt)
28f540f4
RM
412{ return EOPNOTSUPP; }
413
414kern_return_t
415_S_msg_set_dtable (mach_port_t process,
853f0eea
RM
416 mach_port_t refport,
417 portarray_t dtable,
418 mach_msg_type_number_t dtableCnt)
28f540f4 419{ return EOPNOTSUPP; }