xref: /csrg-svn/lib/csu/vax/crt0.c (revision 55307)
147884Sbostic /*-
247884Sbostic  * Copyright (c) 1982 The Regents of the University of California.
347884Sbostic  * All rights reserved.
447884Sbostic  *
549278Sbostic  * %sccs.include.redist.c%
621414Sdist  */
75102Smckusick 
849278Sbostic #ifndef lint
9*55307Smckusick static char sccsid[] = "@(#)crt0.c	5.11 (Berkeley) 07/16/92";
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 
269438Smckusick char **environ = (char **)0;
2725247Smckusick static int fd;
285102Smckusick 
299438Smckusick extern	unsigned char	etext;
3048971Sdonn extern	unsigned char	eprol asm ("eprol");
3148971Sdonn extern			start() asm("start");
3248971Sdonn 
3348971Sdonn /*
3448971Sdonn  * Two kluges: store sp at entry in environ, and
3548971Sdonn  * install 16 bits of 0 at location 0 (a zero register save mask).
3648971Sdonn  * These two hacks remove limits on the use of local
3748971Sdonn  * and register variables in start().
3848971Sdonn  */
3948971Sdonn asm(".text; .word 0; movl sp,_environ; jbr start+2");
4048971Sdonn 
415102Smckusick start()
425102Smckusick {
435102Smckusick 	struct kframe {
445102Smckusick 		int	kargc;
455102Smckusick 		char	*kargv[1];	/* size depends on kargc */
465102Smckusick 		char	kargstr[1];	/* size varies */
475102Smckusick 		char	kenvstr[1];	/* size varies */
485102Smckusick 	};
4948971Sdonn 	register struct kframe *kfp;
505102Smckusick 	register char **targv;
515102Smckusick 	register char **argv;
5225247Smckusick 	extern int errno;
5350405Smckusick 	extern void _mcleanup();
545102Smckusick 
555102Smckusick #ifdef lint
565102Smckusick 	kfp = 0;
579438Smckusick 	initcode = initcode = 0;
585102Smckusick #else not lint
5948971Sdonn 	kfp = (struct kframe *) environ;
605102Smckusick #endif not lint
615102Smckusick 	for (argv = targv = &kfp->kargv[0]; *targv++; /* void */)
625102Smckusick 		/* void */ ;
635102Smckusick 	if (targv >= (char **)(*argv))
645102Smckusick 		--targv;
655102Smckusick 	environ = targv;
669438Smckusick asm("eprol:");
6725247Smckusick 
6825247Smckusick #ifdef paranoid
6925247Smckusick 	/*
7025247Smckusick 	 * The standard I/O library assumes that file descriptors 0, 1, and 2
7125247Smckusick 	 * are open. If one of these descriptors is closed prior to the start
7225247Smckusick 	 * of the process, I/O gets very confused. To avoid this problem, we
7325247Smckusick 	 * insure that the first three file descriptors are open before calling
7425247Smckusick 	 * main(). Normally this is undefined, as it adds two unnecessary
7525247Smckusick 	 * system calls.
7625247Smckusick 	 */
7725247Smckusick 	do	{
7825247Smckusick 		fd = open("/dev/null", 2);
7925247Smckusick 	} while (fd >= 0 && fd < 3);
8025247Smckusick 	close(fd);
8125247Smckusick #endif paranoid
8225247Smckusick 
839438Smckusick #ifdef MCRT0
8450405Smckusick 	atexit(_mcleanup);
859438Smckusick 	monstartup(&eprol, &etext);
869438Smckusick #endif MCRT0
8725247Smckusick 	errno = 0;
885102Smckusick 	exit(main(kfp->kargc, argv, environ));
895102Smckusick }
905102Smckusick 
919438Smckusick #ifdef CRT0
925102Smckusick /*
93*55307Smckusick  * null moncontrol, just in case some routine is compiled for profiling
945102Smckusick  */
9511795Speter moncontrol(val)
9611795Speter 	int val;
9711795Speter {
9811795Speter 
9911795Speter }
1009438Smckusick #endif CRT0
101