home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / glibc-1.06 / sysdeps / mach / hurd / start.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-03  |  6.9 KB  |  267 lines

  1. /* Copyright (C) 1991, 1992 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
  16. not, write to the Free Software Foundation, Inc., 675 Mass Ave,
  17. Cambridge, MA 02139, USA.  */
  18.  
  19. #include <ansidecl.h>
  20. #include <errno.h>
  21. #include <hurd.h>
  22. #include <sysdep.h>
  23.  
  24. /* The first piece of initialized data.  */
  25. int __data_start = 0;
  26.  
  27. struct _hurd_port _hurd_cwdir, _hurd_crdir;
  28. mode_t _hurd_umask;
  29. int _hurd_ctty_fstype;
  30. fsid_t _hurd_ctty_fsid;
  31. ino_t _hurd_ctty_fileid;
  32.  
  33. mach_port_t *_hurd_init_dtable;
  34. size_t _hurd_init_dtablesize;
  35.  
  36. volatile int errno;        /* XXX wants to be per-thread */
  37.  
  38. char **__environ;
  39.  
  40. extern void EXFUN(__libc_init, (NOARGS));
  41. extern void EXFUN(__mach_init, (NOARGS));
  42. extern int EXFUN(main, (int argc, char **argv, char **envp));
  43.  
  44. extern void *(*_cthread_init_routine) (void); /* Returns new SP to use.  */
  45. extern void (*_cthread_exit_routine) (int status);
  46.  
  47. #ifndef    SET_SP
  48. #error "Machine-dependent cthread startup code needs to exist."
  49. #endif
  50.  
  51. #ifndef    GET_STACK
  52. #error "Machine-dependent stack startup code needs to exist."
  53. #endif
  54.  
  55. #ifndef LOSE
  56. #define    LOSE    __task_terminate (__mach_task_self ())
  57. #endif
  58.  
  59. static int count (char *, size_t);
  60. static void makevec (char *, size_t, char **);
  61.  
  62. /* Entry point.  The exec server started the initial thread in our task with
  63.    this spot the PC, and a stack that is presumably big enough.
  64.    The stack base address (|sp - this| is the size of the stack) is
  65.    in the return-value register (%eax for i386, etc.).  */
  66. void
  67. _start (void)
  68. {
  69.   error_t err;
  70.   mach_port_t in_bootstrap;
  71.   char *args, *env;
  72.   mach_port_t *portarray;
  73.   int *intarray;
  74.   size_t argslen, envlen, portarraysize, intarraysize;
  75.   int flags;
  76.  
  77.   int argc, envc;
  78.   char **argv;
  79.  
  80.   char *p;
  81.  
  82.   GET_STACK (_hurd_stack_low, _hurd_stack_high);
  83.  
  84.   /* Basic Mach initialization, must be done before RPCs can be done.  */
  85.   __mach_init ();
  86.  
  87.   if (_cthread_init_routine != NULL)
  88.     {                /* XXXXXXXXXXXXXXXXXXXXXXXX */
  89.       void *newsp = (*_cthread_init_routine) ();
  90.       SET_SP (newsp);
  91.       if (newsp < _hurd_stack_low || newsp > _hurd_stack_high)
  92.     __vm_deallocate (__mach_task_self (),
  93.              _hurd_stack_low,
  94.              _hurd_stack_high - _hurd_stack_low);
  95.     }
  96.  
  97.   if (err = __task_get_special_port (__mach_task_self (), TASK_BOOTSTRAP_PORT,
  98.                      &in_bootstrap))
  99.     LOSE;
  100.  
  101.   if (in_bootstrap != MACH_PORT_NULL)
  102.     {
  103.       err = __exec_startup (in_bootstrap,
  104.                 &flags,
  105.                 &args, &argslen, &env, &envlen,
  106.                 &_hurd_init_dtable, &_hurd_init_dtablesize,
  107.                 &portarray, &portarraysize,
  108.                 &intarray, &intarraysize);
  109.       __mach_port_deallocate (__mach_task_self (), in_bootstrap);
  110.     }
  111.  
  112.   if (err || in_bootstrap == MACH_PORT_NULL)
  113.     {
  114.       static char *noargs = NULL, *noenv = NULL;
  115.       argc = 0;
  116.       argv = &noargs;
  117.       __environ = &noenv;
  118.       _hurd_init_dtable = NULL;
  119.       _hurd_init_dtablesize = 0;
  120.       portarray = NULL;
  121.       portarraysize = 0;
  122.       intarray = NULL;
  123.       intarraysize = 0;
  124.     }
  125.   else
  126.     {
  127.       /* Turn the block of null-separated strings we were passed for the
  128.      arguments and environment into vectors of pointers to strings.  */
  129.       
  130.       argc = count (args, argslen);
  131.       envc = count (env, envlen);
  132.       
  133.       if (err = __vm_allocate (__mach_task_self (),
  134.                    &argv, round_page ((argc + 1 + envc + 1) *
  135.                           sizeof (char *)),
  136.                    1))
  137.     __libc_fatal ("hurd: Can't allocate space for argv and environ\n");
  138.       __environ = &argv[argc + 1];
  139.       
  140.       makevec (args, argslen, argv);
  141.       makevec (env, envlen, __environ);
  142.     }
  143.  
  144.   /* Initialize library data structures, start signal processing, etc.  */
  145.   _hurd_init (argv,
  146.           portarray, portarraysize,
  147.           intarray, intarraysize);
  148.  
  149.  
  150.   /* Random library initialization.  */
  151.   __libc_init (argc, argv, __environ);
  152.  
  153.  
  154.   /* Finally, run the user program.  */
  155.   (_cthread_exit_routine != NULL ? *_cthread_exit_routine : exit)
  156.     (main (argc, argv, __environ));
  157. }
  158.  
  159. static int
  160. count (char *args, size_t argslen)
  161. {
  162.   char *p = args;
  163.   size_t n = argslen;
  164.   int argc;
  165.   while (n > 0)
  166.     {
  167.       char *end = memchr (p, '\0', n);
  168.  
  169.       ++argc;
  170.  
  171.       if (end == NULL)
  172.     /* The last argument is unterminated.  */
  173.     break;
  174.  
  175.       n -= end + 1 - p;
  176.       p = end + 1;
  177.     }
  178.   return argc;
  179. }
  180.  
  181. static void
  182. makevec (char *args, size_t argslen, char **argv)
  183. {
  184.   char *p = args;
  185.   size_t n = argslen;
  186.   int argc = 0;
  187.  
  188.   while (n > 0)
  189.     {
  190.       char *end = memchr (p, '\0', n);
  191.  
  192.       argv[argc++] = p;
  193.  
  194.       if (end == NULL)
  195.     /* The last argument is unterminated.  */
  196.     break;
  197.  
  198.       n -= end + 1 - p;
  199.       p = end + 1;
  200.     }
  201.  
  202.   argv[argc] = NULL;
  203. }
  204.  
  205. /* Initialize the library data structures from the
  206.    ints and ports passed to us by the exec server.
  207.  
  208.    PORTARRAY and INTARRAY are vm_deallocate'd.  */
  209.  
  210. void
  211. _hurd_init (char **argv,
  212.         mach_port_t *portarray, size_t portarraysize,
  213.         int *intarray, size_t intarraysize)
  214. {
  215.   int i;
  216.  
  217.   /* See what ports we were passed.  */
  218.   for (i = 0; i < portarraysize; ++i)
  219.     switch (i)
  220.       {
  221. #define    initport(upper, lower) \
  222.       case INIT_PORT_##upper: \
  223.     _hurd_port_init (&_hurd_##lower, portarray[i]); \
  224.     break
  225.  
  226.       /* Install the standard ports in their cells.  */
  227.     initport (CWDIR, cwdir);
  228.     initport (CRDIR, crdir);
  229.     initport (AUTH, auth);
  230.  
  231.       case INIT_PORT_PROC:
  232.     /* Install the proc port and tell the proc server we exist.  */
  233.     _hurd_proc_init (portarray[i], argv);
  234.     break;
  235.  
  236.       case INIT_PORT_BOOTSTRAP:
  237.     /* When the user asks for the bootstrap port,
  238.        he will get the one the exec server passed us.  */
  239.     __task_set_special_port (__mach_task_self (),
  240.                  TASK_BOOTSTRAP_PORT, portarray[i]);
  241.     /* FALLTHROUGH */
  242.  
  243.       default:
  244.     /* Wonder what that could be.  */
  245.     __mach_port_deallocate (__mach_task_self (), portarray[i]);
  246.     break;
  247.       }
  248.  
  249.   if (intarraysize > INIT_UMASK)
  250.     _hurd_umask = intarray[INIT_UMASK] & 0777;
  251.   else
  252.     _hurd_umask = 0022;        /* XXX */
  253.   if (intarraysize > INIT_CTTY_FILEID) /* Knows that these are sequential.  */
  254.     {
  255.       _hurd_ctty_fstype = intarray[INIT_CTTY_FSTYPE];
  256.       _hurd_ctty_fsid.val[0] = intarray[INIT_CTTY_FSID1];
  257.       _hurd_ctty_fsid.val[1] = intarray[INIT_CTTY_FSID2];
  258.       _hurd_ctty_fileid = intarray[INIT_CTTY_FILEID];
  259.     }
  260.  
  261.  
  262.   /* All done with init ints and ports.  */
  263.   __vm_deallocate (__mach_task_self (), intarray, nints * sizeof (int));
  264.   __vm_deallocate (__mach_task_self (),
  265.            portarray, nports * sizeof (mach_port_t));
  266. }
  267.