147884Sbostic /*-
2*60985Sbostic * Copyright (c) 1982, 1993
3*60985Sbostic * The Regents of the University of California. All rights reserved.
447884Sbostic *
549278Sbostic * %sccs.include.redist.c%
621414Sdist */
75102Smckusick
849278Sbostic #ifndef lint
9*60985Sbostic static char sccsid[] = "@(#)crt0.c 8.1 (Berkeley) 06/01/93";
1049278Sbostic #endif /* not lint */
1121414Sdist
125102Smckusick /*
135102Smckusick * C start up routine.
145102Smckusick * Robert Henry, UCB, 20 Oct 81
155102Smckusick *
165102Smckusick * We make the following (true) assumptions:
175102Smckusick * 1) when the kernel calls start, it does a jump to location 2,
185102Smckusick * and thus avoids the register save mask. We are NOT called
195102Smckusick * with a calls! see sys1.c:setregs().
205102Smckusick * 2) The only register variable that we can trust is sp,
215102Smckusick * which points to the base of the kernel calling frame.
225102Smckusick * Do NOT believe the documentation in exec(2) regarding the
235102Smckusick * values of fp and ap.
245102Smckusick */
255102Smckusick
2657962Sbostic #include <stddef.h>
2757962Sbostic #include <stdlib.h>
2857962Sbostic #include <string.h>
2957962Sbostic
309438Smckusick char **environ = (char **)0;
3157962Sbostic static char empty[1];
3257962Sbostic char *__progname = empty;
3325247Smckusick static int fd;
345102Smckusick
359438Smckusick extern unsigned char etext;
3648971Sdonn extern unsigned char eprol asm ("eprol");
3748971Sdonn extern start() asm("start");
3848971Sdonn
3948971Sdonn /*
4048971Sdonn * Two kluges: store sp at entry in environ, and
4148971Sdonn * install 16 bits of 0 at location 0 (a zero register save mask).
4248971Sdonn * These two hacks remove limits on the use of local
4348971Sdonn * and register variables in start().
4448971Sdonn */
4548971Sdonn asm(".text; .word 0; movl sp,_environ; jbr start+2");
4648971Sdonn
start()475102Smckusick start()
485102Smckusick {
495102Smckusick struct kframe {
505102Smckusick int kargc;
515102Smckusick char *kargv[1]; /* size depends on kargc */
525102Smckusick char kargstr[1]; /* size varies */
535102Smckusick char kenvstr[1]; /* size varies */
545102Smckusick };
5548971Sdonn register struct kframe *kfp;
565102Smckusick register char **targv;
575102Smckusick register char **argv;
5825247Smckusick extern int errno;
5950405Smckusick extern void _mcleanup();
605102Smckusick
615102Smckusick #ifdef lint
625102Smckusick kfp = 0;
639438Smckusick initcode = initcode = 0;
6457962Sbostic #else
6548971Sdonn kfp = (struct kframe *) environ;
6657962Sbostic #endif
675102Smckusick for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
685102Smckusick /* void */ ;
695102Smckusick if (targv >= (char **)(*argv))
705102Smckusick --targv;
715102Smckusick environ = targv;
729438Smckusick asm("eprol:");
7325247Smckusick
7425247Smckusick #ifdef paranoid
7525247Smckusick /*
7625247Smckusick * The standard I/O library assumes that file descriptors 0, 1, and 2
7725247Smckusick * are open. If one of these descriptors is closed prior to the start
7825247Smckusick * of the process, I/O gets very confused. To avoid this problem, we
7925247Smckusick * insure that the first three file descriptors are open before calling
8025247Smckusick * main(). Normally this is undefined, as it adds two unnecessary
8125247Smckusick * system calls.
8225247Smckusick */
8325247Smckusick do {
8425247Smckusick fd = open("/dev/null", 2);
8525247Smckusick } while (fd >= 0 && fd < 3);
8625247Smckusick close(fd);
8757962Sbostic #endif
8825247Smckusick
899438Smckusick #ifdef MCRT0
9050405Smckusick atexit(_mcleanup);
919438Smckusick monstartup(&eprol, &etext);
9257962Sbostic #endif
9325247Smckusick errno = 0;
9457962Sbostic if (argv[0])
9557962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL)
9657962Sbostic __progname = argv[0];
9757962Sbostic else
9857962Sbostic ++__progname;
995102Smckusick exit(main(kfp->kargc, argv, environ));
1005102Smckusick }
1015102Smckusick
1029438Smckusick #ifdef CRT0
1035102Smckusick /*
10455307Smckusick * null moncontrol, just in case some routine is compiled for profiling
1055102Smckusick */
moncontrol(val)10611795Speter moncontrol(val)
10711795Speter int val;
10811795Speter {
10911795Speter
11011795Speter }
11157962Sbostic #endif
112