147882Sbostic /*-
2*60975Sbostic * Copyright (c) 1991, 1993
3*60975Sbostic * The Regents of the University of California. All rights reserved.
447882Sbostic *
549275Sbostic * %sccs.include.redist.c%
644279Sbostic */
744279Sbostic
848802Sdonn #ifndef lint
9*60975Sbostic static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 06/01/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
3257962Sbostic #include <stddef.h>
3357962Sbostic #include <stdlib.h>
3457962Sbostic #include <string.h>
3557962Sbostic
3644279Sbostic char **environ = (char **)0;
3757962Sbostic static char empty[1];
3857962Sbostic 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
start()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;
6757962Sbostic #else
6844279Sbostic asm("lea a6@(4),%0" : "=r" (kfp)); /* catch it quick */
6957962Sbostic #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);
9057962Sbostic #endif
9144279Sbostic
9244279Sbostic #ifdef MCRT0
9350404Smckusick atexit(_mcleanup);
9444279Sbostic monstartup(&eprol, &etext);
9557962Sbostic #endif
9644279Sbostic errno = 0;
9757962Sbostic if (argv[0])
9857962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL)
9957962Sbostic __progname = argv[0];
10057962Sbostic else
10157962Sbostic ++__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 */
moncontrol(val)10944279Sbostic moncontrol(val)
11044279Sbostic int val;
11144279Sbostic {
11244279Sbostic
11344279Sbostic }
11457962Sbostic #endif
115