1 /*- 2 * Copyright (c) 1982, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 06/01/93"; 10 #endif /* not lint */ 11 12 /* 13 * C start up routine. 14 * Robert Henry, UCB, 20 Oct 81 15 * 16 * We make the following (true) assumptions: 17 * 1) when the kernel calls start, it does a jump to location 2, 18 * and thus avoids the register save mask. We are NOT called 19 * with a calls! see sys1.c:setregs(). 20 * 2) The only register variable that we can trust is sp, 21 * which points to the base of the kernel calling frame. 22 * Do NOT believe the documentation in exec(2) regarding the 23 * values of fp and ap. 24 */ 25 26 #include <stddef.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 char **environ = (char **)0; 31 static char empty[1]; 32 char *__progname = empty; 33 static int fd; 34 35 extern unsigned char etext; 36 extern unsigned char eprol asm ("eprol"); 37 extern start() asm("start"); 38 39 /* 40 * Two kluges: store sp at entry in environ, and 41 * install 16 bits of 0 at location 0 (a zero register save mask). 42 * These two hacks remove limits on the use of local 43 * and register variables in start(). 44 */ 45 asm(".text; .word 0; movl sp,_environ; jbr start+2"); 46 47 start() 48 { 49 struct kframe { 50 int kargc; 51 char *kargv[1]; /* size depends on kargc */ 52 char kargstr[1]; /* size varies */ 53 char kenvstr[1]; /* size varies */ 54 }; 55 register struct kframe *kfp; 56 register char **targv; 57 register char **argv; 58 extern int errno; 59 extern void _mcleanup(); 60 61 #ifdef lint 62 kfp = 0; 63 initcode = initcode = 0; 64 #else 65 kfp = (struct kframe *) environ; 66 #endif 67 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 68 /* void */ ; 69 if (targv >= (char **)(*argv)) 70 --targv; 71 environ = targv; 72 asm("eprol:"); 73 74 #ifdef paranoid 75 /* 76 * The standard I/O library assumes that file descriptors 0, 1, and 2 77 * are open. If one of these descriptors is closed prior to the start 78 * of the process, I/O gets very confused. To avoid this problem, we 79 * insure that the first three file descriptors are open before calling 80 * main(). Normally this is undefined, as it adds two unnecessary 81 * system calls. 82 */ 83 do { 84 fd = open("/dev/null", 2); 85 } while (fd >= 0 && fd < 3); 86 close(fd); 87 #endif 88 89 #ifdef MCRT0 90 atexit(_mcleanup); 91 monstartup(&eprol, &etext); 92 #endif 93 errno = 0; 94 if (argv[0]) 95 if ((__progname = strrchr(argv[0], '/')) == NULL) 96 __progname = argv[0]; 97 else 98 ++__progname; 99 exit(main(kfp->kargc, argv, environ)); 100 } 101 102 #ifdef CRT0 103 /* 104 * null moncontrol, just in case some routine is compiled for profiling 105 */ 106 moncontrol(val) 107 int val; 108 { 109 110 } 111 #endif 112