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*57962Sbostic static char sccsid[] = "@(#)crt0.c 5.12 (Berkeley) 02/12/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 26*57962Sbostic #include <stddef.h> 27*57962Sbostic #include <stdlib.h> 28*57962Sbostic #include <string.h> 29*57962Sbostic 309438Smckusick char **environ = (char **)0; 31*57962Sbostic static char empty[1]; 32*57962Sbostic 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 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; 64*57962Sbostic #else 6548971Sdonn kfp = (struct kframe *) environ; 66*57962Sbostic #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); 87*57962Sbostic #endif 8825247Smckusick 899438Smckusick #ifdef MCRT0 9050405Smckusick atexit(_mcleanup); 919438Smckusick monstartup(&eprol, &etext); 92*57962Sbostic #endif 9325247Smckusick errno = 0; 94*57962Sbostic if (argv[0]) 95*57962Sbostic if ((__progname = strrchr(argv[0], '/')) == NULL) 96*57962Sbostic __progname = argv[0]; 97*57962Sbostic else 98*57962Sbostic ++__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 */ 10611795Speter moncontrol(val) 10711795Speter int val; 10811795Speter { 10911795Speter 11011795Speter } 111*57962Sbostic #endif 112