]>
Commit | Line | Data |
---|---|---|
99b306dc | 1 | /* Operating system support for run-time dynamic linker. Hurd version. |
22930c9b | 2 | Copyright (C) 1995, 1996 Free Software Foundation, Inc. |
99b306dc RM |
3 | This file is part of the GNU C Library. |
4 | ||
5 | The GNU C Library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU Library General Public License as | |
7 | published by the Free Software Foundation; either version 2 of the | |
8 | License, or (at your option) any later version. | |
9 | ||
10 | The GNU C Library is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | Library General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU Library General Public | |
16 | License along with the GNU C Library; see the file COPYING.LIB. If | |
17 | not, write to the Free Software Foundation, Inc., 675 Mass Ave, | |
18 | Cambridge, MA 02139, USA. */ | |
19 | ||
20 | #include <hurd.h> | |
21 | #include <link.h> | |
22 | #include <unistd.h> | |
23 | #include <fcntl.h> | |
24 | #include <stdlib.h> | |
25 | #include <sys/mman.h> | |
26 | #include <sys/wait.h> | |
27 | #include <assert.h> | |
28 | #include <sysdep.h> | |
29 | #include <mach/mig_support.h> | |
30 | #include "hurdstartup.h" | |
31 | #include <mach/host_info.h> | |
ec967c06 | 32 | #include "../stdio-common/_itoa.h" |
99b306dc RM |
33 | #include <hurd/auth.h> |
34 | #include <hurd/term.h> | |
35 | #include <stdarg.h> | |
db2286f6 | 36 | #include <ctype.h> |
99b306dc RM |
37 | |
38 | #include "dl-machine.h" | |
39 | ||
a1a9d215 RM |
40 | extern void __mach_init (void); |
41 | ||
99b306dc RM |
42 | extern int _dl_argc; |
43 | extern char **_dl_argv; | |
44 | extern char **_environ; | |
45 | ||
46 | struct hurd_startup_data *_dl_hurd_data; | |
47 | ||
5bf62f2d RM |
48 | unsigned int __hurd_threadvar_max = _HURD_THREADVAR_MAX; |
49 | static unsigned long int threadvars[_HURD_THREADVAR_MAX]; | |
50 | unsigned long int __hurd_threadvar_stack_offset | |
51 | = (unsigned long int) &threadvars; | |
4ca84cff RM |
52 | unsigned long int __hurd_sigthread_stack_base; |
53 | unsigned long int __hurd_sigthread_stack_end; | |
54 | unsigned long int *__hurd_sigthread_variables; | |
55 | unsigned long int __hurd_threadvar_stack_mask; | |
5bf62f2d RM |
56 | |
57 | ||
58 | /* XXX loser kludge for vm_map kernel bug */ | |
59 | static vm_address_t fmha; | |
60 | static vm_size_t fmhs; | |
4ca84cff | 61 | static void unfmh(void){ |
5bf62f2d | 62 | __vm_deallocate(__mach_task_self(),fmha,fmhs);} |
4ca84cff | 63 | static void fmh(void) { |
5bf62f2d RM |
64 | error_t err;int x;mach_port_t p; |
65 | vm_address_t a=0x08000000U,max=VM_MAX_ADDRESS; | |
66 | while (!(err=__vm_region(__mach_task_self(),&a,&fmhs,&x,&x,&x,&x,&p,&x))){ | |
67 | __mach_port_deallocate(__mach_task_self(),p); | |
68 | if (a+fmhs>=0x80000000U){ | |
d819080c | 69 | max=a; break;} |
5bf62f2d RM |
70 | fmha=a+=fmhs;} |
71 | if (err) assert(err==KERN_NO_SPACE); | |
d819080c | 72 | if (!fmha)fmhs=0;else{ |
5bf62f2d RM |
73 | fmhs=max-fmha; |
74 | err = __vm_map (__mach_task_self (), | |
75 | &fmha, fmhs, 0, 0, MACH_PORT_NULL, 0, 1, | |
76 | VM_PROT_NONE, VM_PROT_NONE, VM_INHERIT_COPY); | |
d819080c | 77 | assert_perror(err);} |
5bf62f2d RM |
78 | } |
79 | /* XXX loser kludge for vm_map kernel bug */ | |
80 | ||
81 | ||
82 | ||
99b306dc RM |
83 | Elf32_Addr |
84 | _dl_sysdep_start (void **start_argptr, | |
85 | void (*dl_main) (const Elf32_Phdr *phdr, Elf32_Word phent, | |
86 | Elf32_Addr *user_entry)) | |
87 | { | |
879bf2e6 RM |
88 | extern void _start (); |
89 | ||
99b306dc RM |
90 | void go (int *argdata) |
91 | { | |
879bf2e6 | 92 | extern unsigned int _dl_skip_args; /* rtld.c */ |
99b306dc RM |
93 | char **p; |
94 | ||
95 | /* Cache the information in various global variables. */ | |
a1a9d215 | 96 | _dl_argc = *argdata; |
879bf2e6 | 97 | _dl_argv = 1 + (char **) argdata; |
99b306dc | 98 | _environ = &_dl_argv[_dl_argc + 1]; |
879bf2e6 RM |
99 | for (p = _environ; *p++;); /* Skip environ pointers and terminator. */ |
100 | ||
101 | if ((void *) p == _dl_argv[0]) | |
102 | { | |
103 | static struct hurd_startup_data nodata; | |
104 | _dl_hurd_data = &nodata; | |
105 | nodata.user_entry = (vm_address_t) &_start; | |
106 | } | |
107 | else | |
108 | _dl_hurd_data = (void *) p; | |
99b306dc RM |
109 | |
110 | _dl_secure = _dl_hurd_data->flags & EXEC_SECURE; | |
111 | ||
ec967c06 RM |
112 | if (_dl_hurd_data->flags & EXEC_STACK_ARGS && |
113 | _dl_hurd_data->user_entry == 0) | |
114 | _dl_hurd_data->user_entry = (vm_address_t) &_start; | |
115 | ||
5bf62f2d | 116 | unfmh(); /* XXX */ |
879bf2e6 RM |
117 | |
118 | if (_dl_hurd_data->user_entry == (vm_address_t) &_start) | |
119 | /* We were invoked as a command, not as the program interpreter. | |
120 | The generic ld.so code supports this: it will parse the args | |
121 | as "ld.so PROGRAM [ARGS...]". For booting the Hurd, we | |
122 | support an additional special syntax: | |
123 | ld.so [-LIBS...] PROGRAM [ARGS...] | |
124 | Each LIBS word consists of "FILENAME=MEMOBJ"; | |
125 | for example "-/lib/libc.so=123" says that the contents of | |
126 | /lib/libc.so are found in a memory object whose port name | |
127 | in our task is 123. */ | |
6a76c115 | 128 | while (_dl_argc > 2 && _dl_argv[1][0] == '-' && _dl_argv[1][1] != '-') |
879bf2e6 RM |
129 | { |
130 | char *lastslash, *memobjname, *p; | |
131 | struct link_map *l; | |
132 | mach_port_t memobj; | |
133 | error_t err; | |
134 | ||
135 | ++_dl_skip_args; | |
136 | --_dl_argc; | |
137 | p = _dl_argv++[1] + 1; | |
138 | ||
139 | memobjname = strchr (p, '='); | |
140 | if (! memobjname) | |
141 | _dl_sysdep_fatal ("Bogus library spec: ", p, "\n", NULL); | |
142 | *memobjname++ = '\0'; | |
db2286f6 RM |
143 | memobj = 0; |
144 | while (*memobjname != '\0') | |
145 | memobj = (memobj * 10) + (*memobjname++ - '0'); | |
ec967c06 | 146 | |
879bf2e6 RM |
147 | /* Add a user reference on the memory object port, so we will |
148 | still have one after _dl_map_object_from_fd calls our | |
149 | `close'. */ | |
150 | err = __mach_port_mod_refs (__mach_task_self (), memobj, | |
151 | MACH_PORT_RIGHT_SEND, +1); | |
152 | assert_perror (err); | |
ec967c06 | 153 | |
879bf2e6 RM |
154 | lastslash = strrchr (p, '/'); |
155 | l = _dl_map_object_from_fd (lastslash ? lastslash + 1 : p, | |
156 | memobj, strdup (p)); | |
157 | ||
158 | /* Squirrel away the memory object port where it | |
159 | can be retrieved by the program later. */ | |
160 | l->l_info[DT_NULL] = (void *) memobj; | |
161 | } | |
162 | ||
99b306dc RM |
163 | /* Call elf/rtld.c's main program. It will set everything |
164 | up and leave us to transfer control to USER_ENTRY. */ | |
165 | (*dl_main) ((const Elf32_Phdr *) _dl_hurd_data->phdr, | |
166 | _dl_hurd_data->phdrsz / sizeof (Elf32_Phdr), | |
167 | &_dl_hurd_data->user_entry); | |
168 | ||
879bf2e6 RM |
169 | if (_dl_skip_args && _dl_argv[-_dl_skip_args] == (char *) p) |
170 | { | |
171 | /* We are ignoring the first few arguments, but we have no Hurd | |
172 | startup data. It is magical convention that ARGV[0] == P in | |
173 | this case. The startup code in init-first.c will get confused | |
174 | if this is not the case, so we must rearrange things to make | |
175 | it so. Overwrite the original ARGV[0] at P with | |
176 | ARGV[_dl_skip_args]. */ | |
177 | assert ((char *) p < _dl_argv[0]); | |
178 | _dl_argv[0] = strcpy ((char *) p, _dl_argv[0]); | |
179 | } | |
180 | ||
99b306dc RM |
181 | { |
182 | extern void _dl_start_user (void); | |
183 | /* Unwind the stack to ARGDATA and simulate a return from _dl_start | |
184 | to the RTLD_START code which will run the user's entry point. */ | |
185 | RETURN_TO (argdata, &_dl_start_user, _dl_hurd_data->user_entry); | |
186 | } | |
187 | } | |
188 | ||
a1a9d215 RM |
189 | /* Set up so we can do RPCs. */ |
190 | __mach_init (); | |
191 | ||
5bf62f2d RM |
192 | fmh(); /* XXX */ |
193 | ||
99b306dc RM |
194 | /* See hurd/hurdstartup.c; this deals with getting information |
195 | from the exec server and slicing up the arguments. | |
196 | Then it will call `go', above. */ | |
197 | _hurd_startup (start_argptr, &go); | |
198 | ||
199 | LOSE; | |
54da5be3 | 200 | abort (); |
99b306dc | 201 | } |
4cb20290 RM |
202 | |
203 | void | |
204 | _dl_sysdep_start_cleanup (void) | |
205 | { | |
206 | /* Deallocate the reply port and task port rights acquired by | |
207 | __mach_init. We are done with them now, and the user will | |
208 | reacquire them for himself when he wants them. */ | |
209 | __mig_dealloc_reply_port (MACH_PORT_NULL); | |
210 | __mach_port_deallocate (__mach_task_self (), __mach_task_self_); | |
211 | } | |
99b306dc RM |
212 | \f |
213 | int | |
214 | _dl_sysdep_open_zero_fill (void) | |
215 | { | |
216 | return (int) MACH_PORT_NULL; | |
217 | } | |
218 | ||
219 | ||
220 | void | |
221 | _dl_sysdep_fatal (const char *msg, ...) | |
222 | { | |
99b306dc RM |
223 | va_list ap; |
224 | ||
225 | va_start (ap, msg); | |
226 | do | |
227 | { | |
228 | size_t len = strlen (msg); | |
229 | mach_msg_type_number_t nwrote; | |
230 | do | |
231 | { | |
54da5be3 | 232 | if (__io_write (_hurd_init_dtable[2], msg, len, -1, &nwrote)) |
99b306dc RM |
233 | break; |
234 | len -= nwrote; | |
235 | msg += nwrote; | |
236 | } while (nwrote > 0); | |
237 | msg = va_arg (ap, const char *); | |
238 | } while (msg); | |
239 | va_end (ap); | |
240 | ||
241 | _exit (127); | |
242 | } | |
243 | ||
244 | ||
6a76c115 RM |
245 | void |
246 | _dl_sysdep_message (const char *msg, ...) | |
247 | { | |
248 | va_list ap; | |
249 | ||
250 | va_start (ap, msg); | |
251 | do | |
252 | { | |
253 | size_t len = strlen (msg); | |
254 | mach_msg_type_number_t nwrote; | |
255 | do | |
256 | { | |
257 | if (__io_write (_hurd_init_dtable[1], msg, len, -1, &nwrote)) | |
258 | break; | |
259 | len -= nwrote; | |
260 | msg += nwrote; | |
261 | } while (nwrote > 0); | |
262 | msg = va_arg (ap, const char *); | |
263 | } while (msg); | |
264 | va_end (ap); | |
265 | } | |
266 | \f | |
99b306dc RM |
267 | /* Minimal open/close/mmap implementation sufficient for initial loading of |
268 | shared libraries. These are weak definitions so that when the | |
269 | dynamic linker re-relocates itself to be user-visible (for -ldl), | |
270 | it will get the user's definition (i.e. usually libc's). */ | |
271 | ||
272 | int | |
273 | open (const char *file_name, int mode, ...) | |
274 | { | |
99b306dc RM |
275 | enum retry_type doretry; |
276 | char retryname[1024]; /* XXX string_t LOSES! */ | |
277 | file_t startdir, newpt, fileport; | |
278 | int dealloc_dir; | |
279 | int nloops; | |
b122c703 | 280 | error_t err; |
99b306dc RM |
281 | |
282 | assert (mode == O_RDONLY); | |
283 | ||
99b306dc RM |
284 | startdir = _dl_hurd_data->portarray[file_name[0] == '/' ? |
285 | INIT_PORT_CRDIR : INIT_PORT_CWDIR]; | |
286 | ||
287 | while (file_name[0] == '/') | |
288 | file_name++; | |
289 | ||
b122c703 RM |
290 | if (err = __dir_lookup (startdir, file_name, mode, 0, |
291 | &doretry, retryname, &fileport)) | |
292 | return __hurd_fail (err); | |
99b306dc RM |
293 | |
294 | dealloc_dir = 0; | |
295 | nloops = 0; | |
ec967c06 | 296 | |
99b306dc RM |
297 | while (1) |
298 | { | |
299 | if (dealloc_dir) | |
300 | __mach_port_deallocate (__mach_task_self (), startdir); | |
b122c703 RM |
301 | if (err) |
302 | return __hurd_fail (err); | |
99b306dc RM |
303 | |
304 | switch (doretry) | |
305 | { | |
306 | case FS_RETRY_REAUTH: | |
307 | { | |
308 | mach_port_t ref = __mach_reply_port (); | |
b122c703 RM |
309 | err = __io_reauthenticate (fileport, ref, MACH_MSG_TYPE_MAKE_SEND); |
310 | if (! err) | |
311 | err = __auth_user_authenticate | |
99b306dc | 312 | (_dl_hurd_data->portarray[INIT_PORT_AUTH], |
99b306dc RM |
313 | ref, MACH_MSG_TYPE_MAKE_SEND, |
314 | &newpt); | |
315 | __mach_port_destroy (__mach_task_self (), ref); | |
316 | } | |
317 | __mach_port_deallocate (__mach_task_self (), fileport); | |
b122c703 RM |
318 | if (err) |
319 | return __hurd_fail (err); | |
99b306dc RM |
320 | fileport = newpt; |
321 | /* Fall through. */ | |
322 | ||
323 | case FS_RETRY_NORMAL: | |
324 | #ifdef SYMLOOP_MAX | |
325 | if (nloops++ >= SYMLOOP_MAX) | |
b122c703 | 326 | return __hurd_fail (ELOOP); |
99b306dc RM |
327 | #endif |
328 | ||
329 | /* An empty RETRYNAME indicates we have the final port. */ | |
330 | if (retryname[0] == '\0') | |
331 | { | |
332 | mach_port_t memobj_rd, memobj_wr; | |
99b306dc RM |
333 | |
334 | dealloc_dir = 1; | |
335 | ||
336 | opened: | |
337 | /* We have the file open. Now map it. */ | |
b122c703 | 338 | err = __io_map (fileport, &memobj_rd, &memobj_wr); |
99b306dc RM |
339 | if (dealloc_dir) |
340 | __mach_port_deallocate (__mach_task_self (), fileport); | |
b122c703 RM |
341 | if (err) |
342 | return __hurd_fail (err); | |
99b306dc RM |
343 | if (memobj_wr != MACH_PORT_NULL) |
344 | __mach_port_deallocate (__mach_task_self (), memobj_wr); | |
345 | ||
346 | return (int) memobj_rd; | |
347 | } | |
348 | ||
349 | startdir = fileport; | |
350 | dealloc_dir = 1; | |
351 | file_name = retryname; | |
352 | break; | |
353 | ||
354 | case FS_RETRY_MAGICAL: | |
355 | switch (retryname[0]) | |
356 | { | |
357 | case '/': | |
358 | startdir = _dl_hurd_data->portarray[INIT_PORT_CRDIR]; | |
359 | dealloc_dir = 0; | |
360 | if (fileport != MACH_PORT_NULL) | |
361 | __mach_port_deallocate (__mach_task_self (), fileport); | |
362 | file_name = &retryname[1]; | |
363 | break; | |
364 | ||
365 | case 'f': | |
db2286f6 RM |
366 | if (retryname[1] == 'd' && retryname[2] == '/' && |
367 | isdigit (retryname[3])) | |
99b306dc | 368 | { |
db2286f6 RM |
369 | /* We can't use strtol for the decoding here |
370 | because it brings in hairy locale bloat. */ | |
371 | char *p; | |
372 | int fd = 0; | |
373 | for (p = &retryname[3]; isdigit (*p); ++p) | |
374 | fd = (fd * 10) + (*p - '0'); | |
375 | /* Check for excess text after the number. A slash is | |
376 | valid; it ends the component. Anything else does not | |
377 | name a numeric file descriptor. */ | |
378 | if (*p != '/' && *p != '\0') | |
b122c703 | 379 | return __hurd_fail (ENOENT); |
99b306dc RM |
380 | if (fd < 0 || fd >= _dl_hurd_data->dtablesize || |
381 | _dl_hurd_data->dtable[fd] == MACH_PORT_NULL) | |
b122c703 RM |
382 | /* If the name was a proper number, but the file |
383 | descriptor does not exist, we return EBADF instead | |
384 | of ENOENT. */ | |
385 | return __hurd_fail (EBADF); | |
99b306dc | 386 | fileport = _dl_hurd_data->dtable[fd]; |
db2286f6 | 387 | if (*p == '\0') |
99b306dc RM |
388 | { |
389 | /* This descriptor is the file port we want. */ | |
390 | dealloc_dir = 0; | |
391 | goto opened; | |
392 | } | |
393 | else | |
394 | { | |
395 | /* Do a normal retry on the remaining components. */ | |
396 | startdir = fileport; | |
397 | dealloc_dir = 1; | |
db2286f6 | 398 | file_name = p + 1; /* Skip the slash. */ |
99b306dc RM |
399 | break; |
400 | } | |
401 | } | |
402 | else | |
403 | goto bad_magic; | |
404 | break; | |
405 | ||
406 | case 'm': | |
407 | if (retryname[1] == 'a' && retryname[2] == 'c' && | |
408 | retryname[3] == 'h' && retryname[4] == 't' && | |
409 | retryname[5] == 'y' && retryname[6] == 'p' && | |
410 | retryname[7] == 'e') | |
411 | { | |
412 | error_t err; | |
413 | struct host_basic_info hostinfo; | |
414 | mach_msg_type_number_t hostinfocnt = HOST_BASIC_INFO_COUNT; | |
415 | char *p; | |
416 | if (err = __host_info (__mach_host_self (), HOST_BASIC_INFO, | |
417 | (natural_t *) &hostinfo, | |
418 | &hostinfocnt)) | |
419 | return err; | |
420 | if (hostinfocnt != HOST_BASIC_INFO_COUNT) | |
421 | return EGRATUITOUS; | |
422 | p = _itoa (hostinfo.cpu_subtype, &retryname[8], 10, 0); | |
423 | *--p = '/'; | |
424 | p = _itoa (hostinfo.cpu_type, &retryname[8], 10, 0); | |
425 | if (p < retryname) | |
426 | abort (); /* XXX write this right if this ever happens */ | |
427 | if (p > retryname) | |
428 | strcpy (retryname, p); | |
429 | startdir = fileport; | |
430 | dealloc_dir = 1; | |
431 | } | |
432 | else | |
433 | goto bad_magic; | |
434 | break; | |
435 | ||
436 | case 't': | |
437 | if (retryname[1] == 't' && retryname[2] == 'y') | |
438 | switch (retryname[3]) | |
439 | { | |
440 | error_t opentty (file_t *result) | |
441 | { | |
442 | error_t err; | |
443 | file_t unauth; | |
444 | err = __termctty_open_terminal | |
445 | (_dl_hurd_data->portarray[INIT_PORT_CTTYID], | |
446 | mode, &unauth); | |
447 | if (! err) | |
448 | { | |
449 | mach_port_t ref = __mach_reply_port (); | |
54da5be3 | 450 | err = __io_reauthenticate |
99b306dc RM |
451 | (unauth, ref, MACH_MSG_TYPE_MAKE_SEND); |
452 | if (! err) | |
453 | err = __auth_user_authenticate | |
454 | (_dl_hurd_data->portarray[INIT_PORT_AUTH], | |
99b306dc RM |
455 | ref, MACH_MSG_TYPE_MAKE_SEND, |
456 | result); | |
457 | __mach_port_deallocate (__mach_task_self (), | |
458 | unauth); | |
459 | __mach_port_destroy (__mach_task_self (), ref); | |
460 | } | |
461 | return err; | |
462 | } | |
463 | ||
464 | case '\0': | |
b122c703 RM |
465 | if (err = opentty (&fileport)) |
466 | return __hurd_fail (err); | |
99b306dc RM |
467 | dealloc_dir = 1; |
468 | goto opened; | |
469 | case '/': | |
b122c703 RM |
470 | if (err = opentty (&startdir)) |
471 | return __hurd_fail (err); | |
99b306dc RM |
472 | dealloc_dir = 1; |
473 | strcpy (retryname, &retryname[4]); | |
474 | break; | |
475 | default: | |
476 | goto bad_magic; | |
477 | } | |
478 | else | |
479 | goto bad_magic; | |
480 | break; | |
481 | ||
482 | default: | |
483 | bad_magic: | |
b122c703 | 484 | return __hurd_fail (EGRATUITOUS); |
99b306dc | 485 | } |
ec967c06 | 486 | break; |
99b306dc RM |
487 | |
488 | default: | |
b122c703 | 489 | return __hurd_fail (EGRATUITOUS); |
99b306dc RM |
490 | } |
491 | ||
b122c703 RM |
492 | err = __dir_lookup (startdir, file_name, mode, 0, |
493 | &doretry, retryname, &fileport); | |
99b306dc RM |
494 | } |
495 | } | |
496 | ||
497 | int | |
498 | close (int fd) | |
499 | { | |
500 | if (fd != (int) MACH_PORT_NULL) | |
501 | __mach_port_deallocate (__mach_task_self (), (mach_port_t) fd); | |
502 | return 0; | |
503 | } | |
504 | ||
505 | caddr_t | |
506 | mmap (caddr_t addr, size_t len, int prot, int flags, int fd, off_t offset) | |
507 | { | |
b122c703 | 508 | error_t err; |
99b306dc RM |
509 | vm_prot_t vmprot; |
510 | vm_address_t mapaddr; | |
511 | ||
512 | vmprot = VM_PROT_NONE; | |
513 | if (prot & PROT_READ) | |
514 | vmprot |= VM_PROT_READ; | |
515 | if (prot & PROT_WRITE) | |
516 | vmprot |= VM_PROT_WRITE; | |
517 | if (prot & PROT_EXEC) | |
518 | vmprot |= VM_PROT_EXECUTE; | |
519 | ||
520 | mapaddr = (vm_address_t) addr; | |
b122c703 RM |
521 | err = __vm_map (__mach_task_self (), |
522 | &mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/, | |
523 | !(flags & MAP_FIXED), | |
524 | (mach_port_t) fd, (vm_offset_t) offset, | |
525 | flags & (MAP_COPY|MAP_PRIVATE), | |
526 | vmprot, VM_PROT_ALL, | |
755f55b0 | 527 | (flags & MAP_SHARED) ? VM_INHERIT_SHARE : VM_INHERIT_COPY); |
22930c9b RM |
528 | if (err == KERN_NO_SPACE && (flags & MAP_FIXED)) |
529 | { | |
530 | /* XXX this is not atomic as it is in unix! */ | |
531 | /* The region is already allocated; deallocate it first. */ | |
532 | err = __vm_deallocate (__mach_task_self (), mapaddr, len); | |
533 | if (! err) | |
534 | err = __vm_map (__mach_task_self (), | |
535 | &mapaddr, (vm_size_t) len, 0 /*ELF_MACHINE_USER_ADDRESS_MASK*/, | |
536 | !(flags & MAP_FIXED), | |
537 | (mach_port_t) fd, (vm_offset_t) offset, | |
538 | flags & (MAP_COPY|MAP_PRIVATE), | |
539 | vmprot, VM_PROT_ALL, | |
540 | (flags & MAP_SHARED) | |
541 | ? VM_INHERIT_SHARE : VM_INHERIT_COPY); | |
542 | } | |
543 | ||
b122c703 | 544 | return err ? (caddr_t) __hurd_fail (err) : (caddr_t) mapaddr; |
99b306dc RM |
545 | } |
546 | ||
547 | void | |
548 | _exit (int status) | |
549 | { | |
54da5be3 | 550 | __proc_mark_exit (_dl_hurd_data->portarray[INIT_PORT_PROC], |
0e3426bb | 551 | W_EXITCODE (status, 0), 0); |
99b306dc RM |
552 | while (__task_terminate (__mach_task_self ())) |
553 | __mach_task_self_ = (__mach_task_self) (); | |
554 | } | |
555 | ||
556 | weak_symbol (_exit) | |
557 | weak_symbol (open) | |
558 | weak_symbol (close) | |
559 | weak_symbol (mmap) | |
560 | \f | |
99b306dc | 561 | |
54da5be3 RM |
562 | /* This function is called by interruptible RPC stubs. For initial |
563 | dynamic linking, just use the normal mach_msg. Since this defn is | |
99b306dc RM |
564 | weak, the real defn in libc.so will override it if we are linked into |
565 | the user program (-ldl). */ | |
54da5be3 RM |
566 | |
567 | error_t | |
568 | _hurd_intr_rpc_mach_msg (mach_msg_header_t *msg, | |
569 | mach_msg_option_t option, | |
570 | mach_msg_size_t send_size, | |
571 | mach_msg_size_t rcv_size, | |
572 | mach_port_t rcv_name, | |
573 | mach_msg_timeout_t timeout, | |
574 | mach_port_t notify) | |
575 | { | |
576 | return __mach_msg (msg, option, send_size, rcv_size, rcv_name, | |
577 | timeout, notify); | |
578 | } | |
579 | weak_symbol (_hurd_intr_rpc_mach_msg) |