1 /*- 2 * Copyright (c) 1991, 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 * 3) We can allocate as many register variables as we want, 25 * and don't have to save them for anybody. 26 * 4) Because of the ways that asm's work, we can't have 27 * any automatic variables allocated on the stack, because 28 * we must catch the value of sp before any automatics are 29 * allocated. 30 */ 31 32 #include <stddef.h> 33 #include <stdlib.h> 34 #include <string.h> 35 36 char **environ = (char **)0; 37 static char empty[1]; 38 char *__progname = empty; 39 static int fd; 40 41 extern unsigned char etext; 42 extern unsigned char eprol asm ("eprol"); 43 extern start() asm("start"); 44 45 asm(".text; orb #0,d0"); /* 32 bits of zero at location 0 */ 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 /* 56 * ALL REGISTER VARIABLES!!! 57 */ 58 register struct kframe *kfp; /* r10 */ 59 register char **targv; 60 register char **argv; 61 extern int errno; 62 extern void _mcleanup(); 63 64 #ifdef lint 65 kfp = 0; 66 initcode = initcode = 0; 67 #else 68 asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */ 69 #endif 70 for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 71 /* void */ ; 72 if (targv >= (char **)(*argv)) 73 --targv; 74 environ = targv; 75 asm("eprol:"); 76 77 #ifdef paranoid 78 /* 79 * The standard I/O library assumes that file descriptors 0, 1, and 2 80 * are open. If one of these descriptors is closed prior to the start 81 * of the process, I/O gets very confused. To avoid this problem, we 82 * insure that the first three file descriptors are open before calling 83 * main(). Normally this is undefined, as it adds two unnecessary 84 * system calls. 85 */ 86 do { 87 fd = open("/dev/null", 2); 88 } while (fd >= 0 && fd < 3); 89 close(fd); 90 #endif 91 92 #ifdef MCRT0 93 atexit(_mcleanup); 94 monstartup(&eprol, &etext); 95 #endif 96 errno = 0; 97 if (argv[0]) 98 if ((__progname = strrchr(argv[0], '/')) == NULL) 99 __progname = argv[0]; 100 else 101 ++__progname; 102 exit(main(kfp->kargc, argv, environ)); 103 } 104 105 #ifdef CRT0 106 /* 107 * null moncontrol, just in case some routine is compiled for profiling 108 */ 109 moncontrol(val) 110 int val; 111 { 112 113 } 114 #endif 115