147882Sbostic /*- 248802Sdonn * Copyright (c) 1991 The Regents of the University of California. 347882Sbostic * All rights reserved. 447882Sbostic * 549275Sbostic * %sccs.include.redist.c% 644279Sbostic */ 744279Sbostic 848802Sdonn #ifndef lint 9*57962Sbostic static char sccsid[] = "@(#)crt0.c 5.8 (Berkeley) 02/12/93"; 1048802Sdonn #endif /* not lint */ 1144279Sbostic 1244279Sbostic /* 1344279Sbostic * C start up routine. 1444279Sbostic * Robert Henry, UCB, 20 Oct 81 1544279Sbostic * 1644279Sbostic * We make the following (true) assumptions: 1744279Sbostic * 1) when the kernel calls start, it does a jump to location 2, 1844279Sbostic * and thus avoids the register save mask. We are NOT called 1944279Sbostic * with a calls! see sys1.c:setregs(). 2044279Sbostic * 2) The only register variable that we can trust is sp, 2144279Sbostic * which points to the base of the kernel calling frame. 2244279Sbostic * Do NOT believe the documentation in exec(2) regarding the 2344279Sbostic * values of fp and ap. 2444279Sbostic * 3) We can allocate as many register variables as we want, 2544279Sbostic * and don't have to save them for anybody. 2644279Sbostic * 4) Because of the ways that asm's work, we can't have 2744279Sbostic * any automatic variables allocated on the stack, because 2844279Sbostic * we must catch the value of sp before any automatics are 2944279Sbostic * allocated. 3044279Sbostic */ 3144279Sbostic 32*57962Sbostic #include <stddef.h> 33*57962Sbostic #include <stdlib.h> 34*57962Sbostic #include <string.h> 35*57962Sbostic 3644279Sbostic char **environ = (char **)0; 37*57962Sbostic static char empty[1]; 38*57962Sbostic char *__progname = empty; 3944279Sbostic static int fd; 4044279Sbostic 4148802Sdonn extern unsigned char etext; 4248802Sdonn extern unsigned char eprol asm ("eprol"); 4348802Sdonn extern start() asm("start"); 4444279Sbostic 4548802Sdonn asm(".text; orb #0,d0"); /* 32 bits of zero at location 0 */ 4644279Sbostic 4744279Sbostic start() 4844279Sbostic { 4944279Sbostic struct kframe { 5044279Sbostic int kargc; 5144279Sbostic char *kargv[1]; /* size depends on kargc */ 5244279Sbostic char kargstr[1]; /* size varies */ 5344279Sbostic char kenvstr[1]; /* size varies */ 5444279Sbostic }; 5544279Sbostic /* 5644279Sbostic * ALL REGISTER VARIABLES!!! 5744279Sbostic */ 5848802Sdonn register struct kframe *kfp; /* r10 */ 5944279Sbostic register char **targv; 6044279Sbostic register char **argv; 6144279Sbostic extern int errno; 6250404Smckusick extern void _mcleanup(); 6344279Sbostic 6444279Sbostic #ifdef lint 6544279Sbostic kfp = 0; 6644279Sbostic initcode = initcode = 0; 67*57962Sbostic #else 6844279Sbostic asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */ 69*57962Sbostic #endif 7044279Sbostic for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 7144279Sbostic /* void */ ; 7244279Sbostic if (targv >= (char **)(*argv)) 7344279Sbostic --targv; 7444279Sbostic environ = targv; 7544279Sbostic asm("eprol:"); 7644279Sbostic 7744279Sbostic #ifdef paranoid 7844279Sbostic /* 7944279Sbostic * The standard I/O library assumes that file descriptors 0, 1, and 2 8044279Sbostic * are open. If one of these descriptors is closed prior to the start 8144279Sbostic * of the process, I/O gets very confused. To avoid this problem, we 8244279Sbostic * insure that the first three file descriptors are open before calling 8344279Sbostic * main(). Normally this is undefined, as it adds two unnecessary 8444279Sbostic * system calls. 8544279Sbostic */ 8644279Sbostic do { 8744279Sbostic fd = open("/dev/null", 2); 8844279Sbostic } while (fd >= 0 && fd < 3); 8944279Sbostic close(fd); 90*57962Sbostic #endif 9144279Sbostic 9244279Sbostic #ifdef MCRT0 9350404Smckusick atexit(_mcleanup); 9444279Sbostic monstartup(&eprol, &etext); 95*57962Sbostic #endif 9644279Sbostic errno = 0; 97*57962Sbostic if (argv[0]) 98*57962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL) 99*57962Sbostic __progname = argv[0]; 100*57962Sbostic else 101*57962Sbostic ++__progname; 10244279Sbostic exit(main(kfp->kargc, argv, environ)); 10344279Sbostic } 10444279Sbostic 10544279Sbostic #ifdef CRT0 10644279Sbostic /* 10754908Smckusick * null moncontrol, just in case some routine is compiled for profiling 10844279Sbostic */ 10944279Sbostic moncontrol(val) 11044279Sbostic int val; 11144279Sbostic { 11244279Sbostic 11344279Sbostic } 114*57962Sbostic #endif 115