]>
Commit | Line | Data |
---|---|---|
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 | |
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. | |
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 | |
12 | Library General Public License for more details. | |
13 | ||
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 not, | |
16 | write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
17 | Boston, MA 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 | ||
35 | kern_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 | ||
46 | kern_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 | ||
61 | kern_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 | ||
95 | kern_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 | ||
117 | static kern_return_t | |
118 | get_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 | ||
160 | kern_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 | ||
169 | kern_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 | ||
201 | static kern_return_t | |
202 | set_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 | ||
252 | kern_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 | ||
261 | kern_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 | ||
285 | kern_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 | ||
301 | kern_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 | ||
313 | kern_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 RM |
317 | { |
318 | const char *value = getenv (variable); | |
319 | ||
320 | if (value == NULL) | |
321 | return ENOENT; | |
322 | ||
323 | /* XXX this pointer might become invalid */ | |
324 | *data = value; | |
325 | *datalen = strlen (value); | |
326 | return 0; | |
327 | } | |
328 | ||
329 | ||
330 | kern_return_t | |
331 | _S_msg_set_env_variable (mach_port_t msgport, mach_port_t auth, | |
853f0eea RM |
332 | char *variable, |
333 | char *value, | |
334 | int replace) | |
28f540f4 RM |
335 | { |
336 | AUTHCHECK; | |
337 | ||
338 | if (setenv (variable, value, replace)) /* XXX name space */ | |
339 | return errno; | |
340 | return 0; | |
341 | } | |
342 | ||
343 | kern_return_t | |
344 | _S_msg_get_environment (mach_port_t msgport, | |
853f0eea | 345 | char **data, mach_msg_type_number_t *datalen) |
28f540f4 RM |
346 | { |
347 | /* Pack the environment into an array with nulls separating elements. */ | |
348 | if (__environ != NULL) | |
349 | { | |
350 | char *ap, **p; | |
351 | size_t envlen = 0; | |
352 | ||
353 | for (p = __environ; *p != NULL; ++p) | |
354 | envlen += strlen (*p) + 1; | |
355 | ||
356 | if (envlen > *datalen) | |
357 | { | |
358 | if (__vm_allocate (__mach_task_self (), | |
359 | (vm_address_t *) data, envlen, 1)) | |
360 | return ENOMEM; | |
361 | } | |
362 | ||
363 | ap = *data; | |
364 | for (p = __environ; *p != NULL; ++p) | |
365 | ap = __memccpy (ap, *p, '\0', ULONG_MAX); | |
366 | ||
367 | *datalen = envlen; | |
368 | } | |
369 | else | |
370 | *datalen = 0; | |
371 | ||
372 | return 0; | |
373 | } | |
374 | ||
375 | kern_return_t | |
376 | _S_msg_set_environment (mach_port_t msgport, mach_port_t auth, | |
853f0eea | 377 | char *data, mach_msg_type_number_t datalen) |
28f540f4 RM |
378 | { |
379 | int _hurd_split_args (char *, mach_msg_type_number_t, char **); | |
380 | int envc; | |
381 | char **envp; | |
382 | ||
383 | AUTHCHECK; | |
384 | ||
8f0c527e | 385 | envc = __argz_count (data, datalen); |
28f540f4 RM |
386 | envp = malloc ((envc + 1) * sizeof (char *)); |
387 | if (envp == NULL) | |
388 | return errno; | |
8f0c527e | 389 | __argz_extract (data, datalen, envp); |
28f540f4 RM |
390 | __environ = envp; /* XXX cooperate with loadenv et al */ |
391 | return 0; | |
392 | } | |
393 | \f | |
28f540f4 RM |
394 | |
395 | /* XXX */ | |
396 | ||
397 | kern_return_t | |
398 | _S_msg_get_dtable (mach_port_t process, | |
853f0eea RM |
399 | mach_port_t refport, |
400 | portarray_t *dtable, | |
401 | mach_msg_type_name_t *dtablePoly, | |
402 | mach_msg_type_number_t *dtableCnt) | |
28f540f4 RM |
403 | { return EOPNOTSUPP; } |
404 | ||
405 | kern_return_t | |
406 | _S_msg_set_dtable (mach_port_t process, | |
853f0eea RM |
407 | mach_port_t refport, |
408 | portarray_t dtable, | |
409 | mach_msg_type_number_t dtableCnt) | |
28f540f4 | 410 | { return EOPNOTSUPP; } |