]>
Commit | Line | Data |
---|---|---|
6d7e8eda | 1 | /* Copyright (C) 1992-2023 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 | ||
34 | kern_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 | ||
45 | kern_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 | ||
60 | kern_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 | ||
94 | kern_return_t | |
95 | _S_msg_set_init_ports (mach_port_t msgport, mach_port_t auth, | |
0eb230cc | 96 | const 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 | ||
116 | static kern_return_t | |
117 | get_int (int which, int *value) | |
118 | { | |
119 | switch (which) | |
120 | { | |
121 | case INIT_UMASK: | |
122 | *value = _hurd_umask; | |
123 | return 0; | |
28f540f4 RM |
124 | case INIT_SIGPENDING: |
125 | { | |
653d74f1 | 126 | struct hurd_sigstate *ss = _hurd_global_sigstate; |
28f540f4 RM |
127 | __spin_lock (&ss->lock); |
128 | *value = ss->pending; | |
129 | __spin_unlock (&ss->lock); | |
130 | return 0; | |
131 | } | |
132 | case INIT_SIGIGN: | |
133 | { | |
653d74f1 | 134 | struct hurd_sigstate *ss = _hurd_global_sigstate; |
28f540f4 RM |
135 | sigset_t ign; |
136 | int sig; | |
137 | __spin_lock (&ss->lock); | |
138 | __sigemptyset (&ign); | |
139 | for (sig = 1; sig < NSIG; ++sig) | |
140 | if (ss->actions[sig].sa_handler == SIG_IGN) | |
141 | __sigaddset (&ign, sig); | |
142 | __spin_unlock (&ss->lock); | |
143 | *value = ign; | |
144 | return 0; | |
145 | } | |
146 | default: | |
147 | return EINVAL; | |
148 | } | |
149 | } | |
150 | ||
151 | kern_return_t | |
152 | _S_msg_get_init_int (mach_port_t msgport, mach_port_t auth, | |
853f0eea | 153 | int which, int *value) |
28f540f4 RM |
154 | { |
155 | AUTHCHECK; | |
156 | ||
157 | return get_int (which, value); | |
158 | } | |
159 | ||
160 | kern_return_t | |
161 | _S_msg_get_init_ints (mach_port_t msgport, mach_port_t auth, | |
853f0eea | 162 | int **values, mach_msg_type_number_t *nvalues) |
28f540f4 RM |
163 | { |
164 | error_t err; | |
165 | mach_msg_type_number_t i; | |
166 | ||
167 | AUTHCHECK; | |
168 | ||
169 | if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) values, | |
170 | INIT_INT_MAX * sizeof (int), 1)) | |
171 | return err; | |
172 | *nvalues = INIT_INT_MAX; | |
173 | ||
174 | for (i = 0; i < INIT_INT_MAX; ++i) | |
175 | switch (err = get_int (i, &(*values)[i])) | |
176 | { | |
177 | case 0: /* Success. */ | |
178 | break; | |
179 | case EINVAL: /* Unknown index. */ | |
180 | (*values)[i] = 0; | |
181 | break; | |
182 | default: /* Lossage. */ | |
183 | __vm_deallocate (__mach_task_self (), | |
184 | (vm_address_t) *values, INIT_INT_MAX * sizeof (int)); | |
185 | return err; | |
186 | } | |
187 | ||
188 | return 0; | |
189 | } | |
190 | ||
191 | ||
192 | static kern_return_t | |
193 | set_int (int which, int value) | |
194 | { | |
195 | switch (which) | |
196 | { | |
197 | case INIT_UMASK: | |
198 | _hurd_umask = value; | |
199 | return 0; | |
200 | ||
201 | /* These are pretty odd things to do. But you asked for it. */ | |
28f540f4 RM |
202 | case INIT_SIGPENDING: |
203 | { | |
653d74f1 | 204 | struct hurd_sigstate *ss = _hurd_global_sigstate; |
28f540f4 RM |
205 | __spin_lock (&ss->lock); |
206 | ss->pending = value; | |
207 | __spin_unlock (&ss->lock); | |
208 | return 0; | |
209 | } | |
210 | case INIT_SIGIGN: | |
211 | { | |
653d74f1 | 212 | struct hurd_sigstate *ss = _hurd_global_sigstate; |
28f540f4 RM |
213 | int sig; |
214 | const sigset_t ign = value; | |
215 | __spin_lock (&ss->lock); | |
216 | for (sig = 1; sig < NSIG; ++sig) | |
217 | { | |
218 | if (__sigismember (&ign, sig)) | |
219 | ss->actions[sig].sa_handler = SIG_IGN; | |
220 | else if (ss->actions[sig].sa_handler == SIG_IGN) | |
221 | ss->actions[sig].sa_handler = SIG_DFL; | |
222 | } | |
223 | __spin_unlock (&ss->lock); | |
224 | return 0; | |
fe4d0ab7 MB |
225 | |
226 | case INIT_TRACEMASK: | |
227 | _hurdsig_traced = value; | |
228 | return 0; | |
28f540f4 RM |
229 | } |
230 | default: | |
231 | return EINVAL; | |
232 | } | |
233 | } | |
234 | ||
235 | kern_return_t | |
236 | _S_msg_set_init_int (mach_port_t msgport, mach_port_t auth, | |
853f0eea | 237 | int which, int value) |
28f540f4 RM |
238 | { |
239 | AUTHCHECK; | |
240 | ||
241 | return set_int (which, value); | |
242 | } | |
243 | ||
244 | kern_return_t | |
245 | _S_msg_set_init_ints (mach_port_t msgport, mach_port_t auth, | |
0eb230cc | 246 | const int *values, mach_msg_type_number_t nvalues) |
28f540f4 RM |
247 | { |
248 | error_t err; | |
249 | mach_msg_type_number_t i; | |
250 | ||
251 | AUTHCHECK; | |
252 | ||
253 | for (i = 0; i < INIT_INT_MAX; ++i) | |
254 | switch (err = set_int (i, values[i])) | |
255 | { | |
256 | case 0: /* Success. */ | |
257 | break; | |
258 | case EINVAL: /* Unknown index. */ | |
259 | break; | |
260 | default: /* Lossage. */ | |
261 | return err; | |
262 | } | |
263 | ||
264 | return 0; | |
265 | } | |
266 | \f | |
267 | ||
268 | kern_return_t | |
853f0eea RM |
269 | _S_msg_get_fd (mach_port_t msgport, mach_port_t auth, int which, |
270 | mach_port_t *result, mach_msg_type_name_t *result_type) | |
28f540f4 RM |
271 | { |
272 | AUTHCHECK; | |
273 | ||
274 | /* This creates a new user reference for the send right. | |
275 | Our reply message will move that reference to the caller. */ | |
276 | *result = __getdport (which); | |
277 | if (*result == MACH_PORT_NULL) | |
278 | return errno; | |
279 | *result_type = MACH_MSG_TYPE_MOVE_SEND; | |
280 | ||
281 | return 0; | |
282 | } | |
283 | ||
284 | kern_return_t | |
285 | _S_msg_set_fd (mach_port_t msgport, mach_port_t auth, | |
853f0eea | 286 | int which, mach_port_t port) |
28f540f4 RM |
287 | { |
288 | AUTHCHECK; | |
289 | ||
290 | /* We consume the reference if successful. */ | |
291 | return HURD_FD_USE (which, (_hurd_port2fd (descriptor, port, 0), 0)); | |
292 | } | |
293 | \f | |
294 | /* Snarfing and frobbing environment variables. */ | |
295 | ||
296 | kern_return_t | |
297 | _S_msg_get_env_variable (mach_port_t msgport, | |
0eb230cc | 298 | const_string_t variable, // |
853f0eea | 299 | char **data, mach_msg_type_number_t *datalen) |
28f540f4 | 300 | { |
2b25f93f UD |
301 | error_t err; |
302 | mach_msg_type_number_t valuelen; | |
28f540f4 RM |
303 | const char *value = getenv (variable); |
304 | ||
305 | if (value == NULL) | |
306 | return ENOENT; | |
307 | ||
2b25f93f UD |
308 | valuelen = strlen (value); |
309 | if (valuelen > *datalen) | |
310 | { | |
9c84384c | 311 | if (err = __vm_allocate (__mach_task_self (), |
2b25f93f UD |
312 | (vm_address_t *) data, valuelen, 1)) |
313 | return err; | |
314 | } | |
315 | ||
316 | memcpy (*data, value, valuelen); | |
317 | *datalen = valuelen; | |
318 | ||
28f540f4 RM |
319 | return 0; |
320 | } | |
321 | ||
322 | ||
323 | kern_return_t | |
324 | _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth, | |
0eb230cc ST |
325 | const_string_t variable, // |
326 | const_string_t value, // | |
853f0eea | 327 | int replace) |
28f540f4 RM |
328 | { |
329 | AUTHCHECK; | |
330 | ||
dba2bdbe | 331 | if (__setenv (variable, value, replace)) /* XXX name space */ |
28f540f4 RM |
332 | return errno; |
333 | return 0; | |
334 | } | |
335 | ||
336 | kern_return_t | |
337 | _S_msg_get_environment (mach_port_t msgport, | |
853f0eea | 338 | char **data, mach_msg_type_number_t *datalen) |
28f540f4 RM |
339 | { |
340 | /* Pack the environment into an array with nulls separating elements. */ | |
341 | if (__environ != NULL) | |
342 | { | |
343 | char *ap, **p; | |
344 | size_t envlen = 0; | |
345 | ||
346 | for (p = __environ; *p != NULL; ++p) | |
347 | envlen += strlen (*p) + 1; | |
348 | ||
349 | if (envlen > *datalen) | |
350 | { | |
351 | if (__vm_allocate (__mach_task_self (), | |
352 | (vm_address_t *) data, envlen, 1)) | |
353 | return ENOMEM; | |
354 | } | |
355 | ||
356 | ap = *data; | |
357 | for (p = __environ; *p != NULL; ++p) | |
358 | ap = __memccpy (ap, *p, '\0', ULONG_MAX); | |
359 | ||
360 | *datalen = envlen; | |
361 | } | |
362 | else | |
363 | *datalen = 0; | |
364 | ||
365 | return 0; | |
366 | } | |
367 | ||
368 | kern_return_t | |
369 | _S_msg_set_environment (mach_port_t msgport, mach_port_t auth, | |
0eb230cc | 370 | const char *data, mach_msg_type_number_t datalen) |
28f540f4 RM |
371 | { |
372 | int _hurd_split_args (char *, mach_msg_type_number_t, char **); | |
373 | int envc; | |
374 | char **envp; | |
375 | ||
376 | AUTHCHECK; | |
377 | ||
8f0c527e | 378 | envc = __argz_count (data, datalen); |
28f540f4 RM |
379 | envp = malloc ((envc + 1) * sizeof (char *)); |
380 | if (envp == NULL) | |
381 | return errno; | |
8f0c527e | 382 | __argz_extract (data, datalen, envp); |
28f540f4 RM |
383 | __environ = envp; /* XXX cooperate with loadenv et al */ |
384 | return 0; | |
385 | } | |
386 | \f | |
28f540f4 | 387 | |
28f540f4 RM |
388 | kern_return_t |
389 | _S_msg_get_dtable (mach_port_t process, | |
a51faeee | 390 | mach_port_t auth, |
853f0eea RM |
391 | portarray_t *dtable, |
392 | mach_msg_type_name_t *dtablePoly, | |
393 | mach_msg_type_number_t *dtableCnt) | |
a51faeee ST |
394 | { |
395 | mach_port_t *ports; | |
396 | mach_msg_type_number_t i; | |
397 | error_t err; | |
398 | ||
399 | AUTHCHECK; | |
400 | ||
401 | HURD_CRITICAL_BEGIN; | |
402 | __mutex_lock (&_hurd_dtable_lock); | |
403 | ||
404 | if (err = __vm_allocate (__mach_task_self (), (vm_address_t *) &ports, | |
405 | _hurd_dtablesize * sizeof(mach_port_t), 1)) | |
406 | goto out; | |
407 | ||
408 | for (i = 0; i < _hurd_dtablesize; i++) | |
409 | { | |
410 | struct hurd_fd *cell = _hurd_dtable[i]; | |
411 | if (cell == NULL) | |
412 | ports[i] = MACH_PORT_NULL; | |
413 | else | |
414 | { | |
415 | __spin_lock (&cell->port.lock); | |
416 | if (cell->port.port == MACH_PORT_NULL) | |
417 | ports[i] = MACH_PORT_NULL; | |
418 | else | |
419 | { | |
420 | ports[i] = cell->port.port; | |
421 | /* We will move this send right. */ | |
422 | __mach_port_mod_refs (__mach_task_self (), ports[i], | |
423 | MACH_PORT_RIGHT_SEND, +1); | |
424 | } | |
425 | __spin_unlock (&cell->port.lock); | |
426 | } | |
427 | } | |
428 | ||
429 | *dtable = ports; | |
430 | *dtablePoly = MACH_MSG_TYPE_MOVE_SEND; | |
431 | *dtableCnt = _hurd_dtablesize; | |
432 | ||
433 | out: | |
434 | __mutex_unlock (&_hurd_dtable_lock); | |
435 | HURD_CRITICAL_END; | |
436 | return err; | |
437 | } | |
438 | ||
439 | /* XXX */ | |
28f540f4 RM |
440 | |
441 | kern_return_t | |
442 | _S_msg_set_dtable (mach_port_t process, | |
853f0eea | 443 | mach_port_t refport, |
0eb230cc | 444 | const_portarray_t dtable, |
853f0eea | 445 | mach_msg_type_number_t dtableCnt) |
28f540f4 | 446 | { return EOPNOTSUPP; } |