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*57962Sbostic static char sccsid[] = "@(#)crt0.c 5.9 (Berkeley) 02/12/93"; 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 21*57962Sbostic #include <stddef.h> 22*57962Sbostic #include <stdlib.h> 23*57962Sbostic #include <string.h> 24*57962Sbostic 2541009Swilliam char **environ = (char **)0; 26*57962Sbostic static char empty[1]; 27*57962Sbostic char *__progname = empty; 2841009Swilliam static int fd; 2941009Swilliam 3048797Sdonn asm(".text"); 3148797Sdonn asm(".long 0xc000c000"); 3248797Sdonn 3341009Swilliam extern unsigned char etext; 3448797Sdonn extern unsigned char eprol asm ("eprol"); 3548797Sdonn extern start() asm("start"); 3648797Sdonn 3741009Swilliam start() 3841009Swilliam { 3941009Swilliam struct kframe { 4041009Swilliam int kargc; 4141009Swilliam char *kargv[1]; /* size depends on kargc */ 4241009Swilliam char kargstr[1]; /* size varies */ 4341009Swilliam char kenvstr[1]; /* size varies */ 4441009Swilliam }; 4541009Swilliam /* 4641009Swilliam * ALL REGISTER VARIABLES!!! 4741009Swilliam */ 4841009Swilliam register struct kframe *kfp; /* r10 */ 4941009Swilliam register char **targv; 5041009Swilliam register char **argv; 5141009Swilliam extern int errno; 5250406Smckusick extern void _mcleanup(); 5341009Swilliam 5441009Swilliam #ifdef lint 5541009Swilliam kfp = 0; 5641009Swilliam initcode = initcode = 0; 57*57962Sbostic #else 5848797Sdonn asm("lea 4(%ebp),%ebx"); /* catch it quick */ 59*57962Sbostic #endif 6041009Swilliam for (argv = targv = &kfp->kargv[0]; *targv++; /* void */) 6141009Swilliam /* void */ ; 6241009Swilliam if (targv >= (char **)(*argv)) 6341009Swilliam --targv; 6441009Swilliam environ = targv; 6541009Swilliam asm("eprol:"); 6641009Swilliam 6741009Swilliam #ifdef paranoid 6841009Swilliam /* 6941009Swilliam * The standard I/O library assumes that file descriptors 0, 1, and 2 7041009Swilliam * are open. If one of these descriptors is closed prior to the start 7141009Swilliam * of the process, I/O gets very confused. To avoid this problem, we 7241009Swilliam * insure that the first three file descriptors are open before calling 7341009Swilliam * main(). Normally this is undefined, as it adds two unnecessary 7441009Swilliam * system calls. 7541009Swilliam */ 7641009Swilliam do { 7741009Swilliam fd = open("/dev/null", 2); 7841009Swilliam } while (fd >= 0 && fd < 3); 7941009Swilliam close(fd); 80*57962Sbostic #endif 8141009Swilliam 8241009Swilliam #ifdef MCRT0 8350406Smckusick atexit(_mcleanup); 8441009Swilliam monstartup(&eprol, &etext); 85*57962Sbostic #endif 8641009Swilliam errno = 0; 87*57962Sbostic if (argv[0]) 88*57962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL) 89*57962Sbostic __progname = argv[0]; 90*57962Sbostic else 91*57962Sbostic ++__progname; 9241009Swilliam exit(main(kfp->kargc, argv, environ)); 9341009Swilliam } 9441009Swilliam 9541009Swilliam #ifdef CRT0 9641009Swilliam /* 9755303Smckusick * null moncontrol just in case some routine is compiled for profiling 9841009Swilliam */ 9941009Swilliam moncontrol(val) 10041009Swilliam int val; 10141009Swilliam { 10241009Swilliam 10341009Swilliam } 104*57962Sbostic #endif 105