]>
Commit | Line | Data |
---|---|---|
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 PE |
15 | License along with the GNU C Library; if not, see |
16 | <http://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, | |
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 | ||
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; | |
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 | ||
159 | kern_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 | ||
168 | kern_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 | ||
200 | static kern_return_t | |
201 | set_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 | ||
251 | kern_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 | ||
260 | kern_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 | ||
284 | kern_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 | ||
300 | kern_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 | ||
312 | kern_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 | ||
339 | kern_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 | ||
352 | kern_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 | ||
384 | kern_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 | ||
406 | kern_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 | ||
414 | kern_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; } |