Files
oldlinux-files/gnu/glibc/glibc-1.05.tar/glibc-1.05/sysdeps/mach/hurd/start.c
2024-02-19 00:24:47 -05:00

267 lines
7.1 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* Copyright (C) 1991, 1992 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public License as
published by the Free Software Foundation; either version 2 of the
License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with the GNU C Library; see the file COPYING.LIB. If
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
Cambridge, MA 02139, USA. */
#include <ansidecl.h>
#include <errno.h>
#include <hurd.h>
#include <sysdep.h>
/* The first piece of initialized data. */
int __data_start = 0;
struct _hurd_port _hurd_cwdir, _hurd_crdir;
mode_t _hurd_umask;
int _hurd_ctty_fstype;
fsid_t _hurd_ctty_fsid;
ino_t _hurd_ctty_fileid;
mach_port_t *_hurd_init_dtable;
size_t _hurd_init_dtablesize;
volatile int errno; /* XXX wants to be per-thread */
char **__environ;
extern void EXFUN(__libc_init, (NOARGS));
extern void EXFUN(__mach_init, (NOARGS));
extern int EXFUN(main, (int argc, char **argv, char **envp));
extern void *(*_cthread_init_routine) (void); /* Returns new SP to use. */
extern void (*_cthread_exit_routine) (int status);
#ifndef SET_SP
#error "Machine-dependent cthread startup code needs to exist."
#endif
#ifndef GET_STACK
#error "Machine-dependent stack startup code needs to exist."
#endif
#ifndef LOSE
#define LOSE __task_terminate (__mach_task_self ())
#endif
static int count (char *, size_t);
static void makevec (char *, size_t, char **);
/* Entry point. The exec server started the initial thread in our task with
this spot the PC, and a stack that is presumably big enough.
The stack base address (|sp - this| is the size of the stack) is
in the return-value register (%eax for i386, etc.). */
void
_start (void)
{
error_t err;
mach_port_t in_bootstrap;
char *args, *env;
mach_port_t *portarray;
int *intarray;
size_t argslen, envlen, portarraysize, intarraysize;
int flags;
int argc, envc;
char **argv;
char *p;
GET_STACK (_hurd_stack_low, _hurd_stack_high);
/* Basic Mach initialization, must be done before RPCs can be done. */
__mach_init ();
if (_cthread_init_routine != NULL)
{ /* XXXXXXXXXXXXXXXXXXXXXXXX */
void *newsp = (*_cthread_init_routine) ();
SET_SP (newsp);
if (newsp < _hurd_stack_low || newsp > _hurd_stack_high)
__vm_deallocate (__mach_task_self (),
_hurd_stack_low,
_hurd_stack_high - _hurd_stack_low);
}
if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
&in_bootstrap))
LOSE;
if (in_bootstrap != MACH_PORT_NULL)
{
err = __exec_startup (in_bootstrap,
&flags,
&args, &argslen, &env, &envlen,
&_hurd_init_dtable, &_hurd_init_dtablesize,
&portarray, &portarraysize,
&intarray, &intarraysize);
__mach_port_deallocate (__mach_task_self (), in_bootstrap);
}
if (err || in_bootstrap == MACH_PORT_NULL)
{
static char *noargs = NULL, *noenv = NULL;
argc = 0;
argv = &null;
__environ = &noenv;
_hurd_init_dtable = NULL;
_hurd_init_dtablesize = 0;
portarray = NULL;
portarraysize = 0;
intarray = NULL;
intarraysize = 0;
}
else
{
/* Turn the block of null-separated strings we were passed for the
arguments and environment into vectors of pointers to strings. */
argc = count (args, argslen);
envc = count (env, envlen);
if (err = __vm_allocate (__mach_task_self (),
&argv, round_page ((argc + 1 + envc + 1) *
sizeof (char *)),
1))
__libc_fatal ("hurd: Can't allocate space for argv and environ\n");
__environ = &argv[argc + 1];
makevec (args, argslen, argv);
makevec (env, envlen, __environ);
}
/* Initialize library data structures, start signal processing, etc. */
_hurd_init (argv,
portarray, portarraysize,
intarray, intarraysize);
/* Random library initialization. */
__libc_init (argc, argv, __environ);
/* Finally, run the user program. */
(_cthread_exit_routine != NULL ? *_cthread_exit_routine : exit)
(main (argc, argv, __environ));
}
static int
count (char *args, size_t argslen)
{
char *p = args;
size_t n = argslen;
int argc;
while (n > 0)
{
char *end = memchr (p, '\0', n);
++argc;
if (end == NULL)
/* The last argument is unterminated. */
break;
n -= end + 1 - p;
p = end + 1;
}
return argc;
}
static void
makevec (char *args, size_t argslen, char **argv)
{
char *p = args;
size_t n = argslen;
int argc = 0;
while (n > 0)
{
char *end = memchr (p, '\0', n);
argv[argc++] = p;
if (end == NULL)
/* The last argument is unterminated. */
break;
n -= end + 1 - p;
p = end + 1;
}
argv[argc] = NULL;
}
/* Initialize the library data structures from the
ints and ports passed to us by the exec server.
PORTARRAY and INTARRAY are vm_deallocate'd. */
void
_hurd_init (char **argv,
mach_port_t *portarray, size_t portarraysize,
int *intarray, size_t intarraysize)
{
int i;
/* See what ports we were passed. */
for (i = 0; i < portarraysize; ++i)
switch (i)
{
#define initport(upper, lower) \
case INIT_PORT_##upper: \
_hurd_port_init (&_hurd_##lower, portarray[i]); \
break
/* Install the standard ports in their cells. */
initport (CWDIR, cwdir);
initport (CRDIR, crdir);
initport (AUTH, auth);
case INIT_PORT_PROC:
/* Install the proc port and tell the proc server we exist. */
_hurd_proc_init (portarray[i], argv);
break;
case INIT_PORT_BOOTSTRAP:
/* When the user asks for the bootstrap port,
he will get the one the exec server passed us. */
__task_set_special_port (__mach_task_self (),
TASK_BOOTSTRAP_PORT, portarray[i]);
/* FALLTHROUGH */
default:
/* Wonder what that could be. */
__mach_port_deallocate (__mach_task_self (), portarray[i]);
break;
}
if (intarraysize > INIT_UMASK)
_hurd_umask = intarray[INIT_UMASK] & 0777;
else
_hurd_umask = 0022; /* XXX */
if (intarraysize > INIT_CTTY_FILEID) /* Knows that these are sequential. */
{
_hurd_ctty_fstype = intarray[INIT_CTTY_FSTYPE];
_hurd_ctty_fsid.val[0] = intarray[INIT_CTTY_FSID1];
_hurd_ctty_fsid.val[1] = intarray[INIT_CTTY_FSID2];
_hurd_ctty_fileid = intarray[INIT_CTTY_FILEID];
}
/* All done with init ints and ports. */
__vm_deallocate (__mach_task_self (), intarray, nints * sizeof (int));
__vm_deallocate (__mach_task_self (),
portarray, nports * sizeof (mach_port_t));
}