141009Swilliam /*- 241009Swilliam * Copyright (c) 1990 The Regents of the University of California. 341009Swilliam * All rights reserved. 441009Swilliam * 549276Sbostic * %sccs.include.redist.c% 641009Swilliam */ 741009Swilliam 849276Sbostic #ifndef lint 9*55303Smckusick static char sccsid[] = "@(#)crt0.c 5.8 (Berkeley) 07/16/92"; 1049276Sbostic #endif /* not lint */ 1141009Swilliam 1241009Swilliam /* 1341009Swilliam * C start up routine. 1441009Swilliam * Robert Henry, UCB, 20 Oct 81 1541009Swilliam * 1641918Swilliam * We make the following (true) assumption: 1741918Swilliam * 1) The only register variable that we can trust is ebp, 1841009Swilliam * which points to the base of the kernel calling frame. 1941009Swilliam */ 2041009Swilliam 2141009Swilliam char **environ = (char **)0; 2241009Swilliam static int fd; 2341009Swilliam 2448797Sdonn asm(".text"); 2548797Sdonn asm(".long 0xc000c000"); 2648797Sdonn 2741009Swilliam extern unsigned char etext; 2848797Sdonn extern unsigned char eprol asm ("eprol"); 2948797Sdonn extern start() asm("start"); 3048797Sdonn 3141009Swilliam start() 3241009Swilliam { 3341009Swilliam struct kframe { 3441009Swilliam int kargc; 3541009Swilliam char *kargv[1]; /* size depends on kargc */ 3641009Swilliam char kargstr[1]; /* size varies */ 3741009Swilliam char kenvstr[1]; /* size varies */ 3841009Swilliam }; 3941009Swilliam /* 4041009Swilliam * ALL REGISTER VARIABLES!!! 4141009Swilliam */ 4241009Swilliam register struct kframe *kfp; /* r10 */ 4341009Swilliam register char **targv; 4441009Swilliam register char **argv; 4541009Swilliam extern int errno; 4650406Smckusick extern void _mcleanup(); 4741009Swilliam 4841009Swilliam #ifdef lint 4941009Swilliam kfp = 0; 5041009Swilliam initcode = initcode = 0; 5141009Swilliam #else not lint 5248797Sdonn asm("lea 4(%ebp),%ebx"); /* catch it quick */ 5341009Swilliam #endif not lint 5441009Swilliam for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 5541009Swilliam /* void */ ; 5641009Swilliam if (targv >= (char **)(*argv)) 5741009Swilliam --targv; 5841009Swilliam environ = targv; 5941009Swilliam asm("eprol:"); 6041009Swilliam 6141009Swilliam #ifdef paranoid 6241009Swilliam /* 6341009Swilliam * The standard I/O library assumes that file descriptors 0, 1, and 2 6441009Swilliam * are open. If one of these descriptors is closed prior to the start 6541009Swilliam * of the process, I/O gets very confused. To avoid this problem, we 6641009Swilliam * insure that the first three file descriptors are open before calling 6741009Swilliam * main(). Normally this is undefined, as it adds two unnecessary 6841009Swilliam * system calls. 6941009Swilliam */ 7041009Swilliam do { 7141009Swilliam fd = open("/dev/null", 2); 7241009Swilliam } while (fd >= 0 && fd < 3); 7341009Swilliam close(fd); 7441009Swilliam #endif paranoid 7541009Swilliam 7641009Swilliam #ifdef MCRT0 7750406Smckusick atexit(_mcleanup); 7841009Swilliam monstartup(&eprol, &etext); 7941009Swilliam #endif MCRT0 8041009Swilliam errno = 0; 8141009Swilliam exit(main(kfp->kargc, argv, environ)); 8241009Swilliam } 8341009Swilliam 8441009Swilliam #ifdef CRT0 8541009Swilliam /* 86*55303Smckusick * null moncontrol just in case some routine is compiled for profiling 8741009Swilliam */ 8841009Swilliam moncontrol(val) 8941009Swilliam int val; 9041009Swilliam { 9141009Swilliam 9241009Swilliam } 93*55303Smckusick #endif /* CRT0 */ 94