141009Swilliam /*-
2*60977Sbostic * Copyright (c) 1990, 1993
3*60977Sbostic * The Regents of the University of California. All rights reserved.
441009Swilliam *
549276Sbostic * %sccs.include.redist.c%
641009Swilliam */
741009Swilliam
849276Sbostic #ifndef lint
9*60977Sbostic static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 06/01/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
2157962Sbostic #include <stddef.h>
2257962Sbostic #include <stdlib.h>
2357962Sbostic #include <string.h>
2457962Sbostic
2541009Swilliam char **environ = (char **)0;
2657962Sbostic static char empty[1];
2757962Sbostic 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
start()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;
5757962Sbostic #else
5848797Sdonn asm("lea 4(%ebp),%ebx"); /* catch it quick */
5957962Sbostic #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);
8057962Sbostic #endif
8141009Swilliam
8241009Swilliam #ifdef MCRT0
8350406Smckusick atexit(_mcleanup);
8441009Swilliam monstartup(&eprol, &etext);
8557962Sbostic #endif
8641009Swilliam errno = 0;
8757962Sbostic if (argv[0])
8857962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL)
8957962Sbostic __progname = argv[0];
9057962Sbostic else
9157962Sbostic ++__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 */
moncontrol(val)9941009Swilliam moncontrol(val)
10041009Swilliam int val;
10141009Swilliam {
10241009Swilliam
10341009Swilliam }
10457962Sbostic #endif
105