DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦bec85626f⟧ TextFile

    Length: 13734 (0x35a6)
    Types: TextFile
    Notes: UNIX file
    Names: »exec.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦2d53db1df⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »sys/coh/exec.c« 

TextFile

/* (-lgl
 * 	The information contained herein is a trade secret of Mark Williams
 * 	Company, and  is confidential information.  It is provided  under a
 * 	license agreement,  and may be  copied or disclosed  only under the
 * 	terms of  that agreement.  Any  reproduction or disclosure  of this
 * 	material without the express written authorization of Mark Williams
 * 	Company or persuant to the license agreement is unlawful.
 * 
 * 	COHERENT Version 0.7.3
 * 	Copyright (c) 1982, 1983, 1984.
 * 	An unpublished work by Mark Williams Company, Chicago.
 * 	All rights reserved.
 -lgl) */
/*
 * Coherent.
 * Exec and driver load code.
 */
#include <coherent.h>
#include <acct.h>
#include <buf.h>
#include <canon.h>
#include <con.h>
#include <errno.h>
#include <filsys.h>
#include <ino.h>
#include <inode.h>
#include <l.out.h>
#include <proc.h>
#include <seg.h>
#include <signal.h>
#include <uproc.h>

/*
 * Sizes.
 */
#define	sh	((size_t)sizeof(struct ldheader))
#define si	lssize[L_SHRI]
#define pi	lssize[L_PRVI]
#define bi	lssize[L_BSSI]
#define sd	lssize[L_SHRD]
#define pd	lssize[L_PRVD]
#define bd	lssize[L_BSSD]

/*
 * Segments.
 */
#define upsp	pp->p_segp[SIUSERP]
#define	lssp	pp->p_segp[SISSLIB]
#define	lpsp	pp->p_segp[SIPSLIB]
#define sssp	pp->p_segp[SISTACK]
#define	sisp	pp->p_segp[SISTEXT]
#define pisp	pp->p_segp[SIPTEXT]
#define sdsp	pp->p_segp[SISDATA]
#define pdsp	pp->p_segp[SIPDATA]

/*
 * Set up the first process, a small programme which will exec
 * the init programme.
 */
eveinit(sp)
SEG *sp;
{
	register PROC *pp;

	SELF = pp = eprocp;
	pp->p_segp[SIUSERP] = sp;
	if ((sp=salloc((size_t)icodes, 0)) == NULL)
		panic("eveinit()");
	pp->p_segp[SIPDATA] = sp;
	kscopy(icodep, sp, 0, icodes);
	if ((sp=salloc((size_t)UPASIZE, SFDOWN)) == NULL)
		panic("eveinit()");
	pp->p_segp[SISTACK] = sp;
	u.u_argp = 0;
	if (sproto() == 0)
		panic("eveinit()");
	segload();
}

/*
 * Given a major number, a file containing a device driver and a configuration
 * pointer, load the driver on the major number.
 */
pload(m, np, cp)
char *np;
CON *cp;
{
	register INODE *ip;
	register SEG *sp;
	register DRV *dp;
	register size_t ss;
	dold_t dold;
	int lflag;
	int r;
	vaddr_t pc;
	size_t lssize[NUSEG];

	if (m >= drvn) {
		u.u_error = ENXIO;
		return;
	}
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	ss = pi+si+pd+sd;
	sp = ssalloc(&r, ip, SFSHRX, ss+bi+bd, sh, ss);
	idetach(ip);
	if (r < 0)
		return;
	dp = &drvl[m];
	lock(dp->d_gate);
	if (dp->d_conp != NULL) {
		unlock(dp->d_gate);
		sfree(sp);
		u.u_error = EDBUSY;
		return;
	}
	dp->d_time = 0;
	dp->d_conp = cp;
	dp->d_segp = sp;
	dp->d_map = sp->s_mbase;
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_load)();
	drest(dold);
	unlock(dp->d_gate);
}

/*
 * Given a major number, undo the previous function.
 */
puload(m)
int m;
{
	register CON *cp;
	register DRV *dp;
	dold_t dold;

	dp = &drvl[m];
	lock(dp->d_gate);
	if (m>=drvn || dp->d_segp==NULL || (cp=dp->d_conp)==NULL) {
		u.u_error = ENXIO;
		goto ret;
	}
	dsave(dold);
	dmapv(dp->d_map);
	(*cp->c_uload)();
	drest(dold);
	if (u.u_error)
		goto ret;
	sfree(dp->d_segp);
	dp->d_conp = NULL;
	dp->d_segp = NULL;
	dp->d_map = 0;
ret:
	unlock(dp->d_gate);
	return (0);
}

/*
 * Given the name of an executable l.out, a null terminated argument
 * list and a null terminated environment list, execute the l.out with the
 * given arguments and environments.
 */
pexece(np, argp, envp)
char	*np;
char	*argp[];
char	*envp[];
{
	register INODE	*ip;			/* Load file INODE */
	register PROC	*pp;			/* A cheap copy of SELF */
	register SEG	*ssp;			/* New stack segment */
	register size_t	ss;			/* Segment size temp. */
	register int	hialloc = 1;		/* Set if kernel process */
	register int	i;			/* For looping over segments */
	int		r;			/* Flag for "exload" */
	int		lflag;			/* l_flags from l.out */
	vaddr_t		pc;			/* l_entry from l.out */
	vaddr_t		sp;			/* Initial stack pointer */
	size_t		lssize[NUSEG];		/* Segment sizes */

	pp = SELF;
	if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL)
		return;
	ssp = NULL;
	if ((lflag&LF_KER) != 0) {
		pp->p_flags |= PFKERN;
		if (super() == 0) {
			idetach(ip);
			return;
		}
#if Z8001
	} else if ((lflag&LF_SLIB) != 0) {
		pp->p_flags |= PFSLIB|PFLOCK;
		if (super() == 0) {
			idetach(ip);
			return;
		}
		if (slprocp != NULL) {
			u.u_error = ENOEXEC;
			idetach(ip);
			return;
		}
	} else if ((lflag&LF_SLREF)!=0 && slprocp==NULL) {
			/*
			 * Perhaps should be made its own errno.
			 */
		u.u_error = ENOEXEC;
		idetach(ip);
		return;
#endif
	} else {
		hialloc = 0;
		if ((ssp = exstack(&sp, argp, envp)) == NULL) {
			idetach(ip);
			return;
		}
	}
	/*
	 * At this point the file has been
	 * validated as an object module, and the
	 * argument list has been built. Release all of
	 * the original segments. At this point we have
	 * committed to the new image. A "sys exec" that
	 * gets an I/O error is doomed.
	 */
	for (i=1; i<NUSEG; ++i) {
		if (pp->p_segp[i] != NULL) {
			sfree(pp->p_segp[i]);
			pp->p_segp[i] = NULL;
		}
	}
	sssp = ssp;
	/*
	 * Read in load module.
	 */
	switch (lflag&(LF_SHR|LF_SEP)) {
	case 0:
		ss = si+pi+sd+pd;
		pdsp = ssalloc(&r, ip, hialloc?SFHIGH:0, ss+bi+bd, sh, ss);
		if (r < 0)
			goto out;
		break;

	case LF_SHR:
		sdsp = ssalloc(&r, ip, SFSHRX, si+sd, sh, si);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(sdsp, ip, sd, sh+si+pi, si) == 0)
				goto out;
		}
		pdsp = ssalloc(&r, ip, 0, pi+pd+bi+bd, sh+si, pi);
		if (r < 0)
			goto out;
		if (r == 0) {
			if (exsread(pdsp, ip, pd, sh+si+pi+sd, pi) == 0)
				goto out;
		}
		break;

	case LF_SEP:
		pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+bi, sd+pd);
		if (r < 0)
			goto out;
		break;

	case LF_SHR|LF_SEP:
		sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
		if (r < 0)
			goto out;
		pisp = ssalloc(&r, ip, SFTEXT, pi+bi, sh+si, pi);
		if (r < 0)
			goto out;
		sdsp = ssalloc(&r, ip, SFSHRX, sd, sh+si+pi, sd);
		if (r < 0)
			goto out;
		pdsp = ssalloc(&r, ip, 0, pd+bd, sh+si+pi+sd, pd);
		if (r < 0)
			goto out;
	}
#if Z8001
	if ((lflag & LF_SLIB) != 0) {
		if (sisp!=NULL || pisp!=NULL || sdsp==NULL) {
			u.u_error = ENOEXEC;
			goto out;
		}
		slprocp = pp;
	} else if ((lflag & LF_SLREF) != 0) {
		register PROC *slpp;

		if ((slpp = slprocp) == NULL
		 || (lssp = slpp->p_segp[SISDATA]) == NULL
		 || (lssp = segdupl(lssp)) == NULL) {
			u.u_error = ENOEXEC;
			goto out;
		}
		if ((lpsp = slpp->p_segp[SIPDATA]) != NULL
		 && (lpsp = segdupl(lpsp)) == NULL) {
			u.u_error = ENOEXEC;
			goto out;
		}
	}
#endif
	if (sproto() == 0)
		goto out;
	/*
	 * The new image is read in
	 * and mapped. Perform the final grunge
	 * (set-uid stuff, accounting, loading up
	 * registers, etc).
	 */
	u.u_flag &= ~AFORK;
	kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
	if (iaccess(ip, IPR) == 0)
		pp->p_flags |= PFNDMP;
	if ((ip->i_mode&ISUID) != 0)
		pp->p_uid = u.u_uid = ip->i_uid;
	if ((ip->i_mode&ISGID) != 0)
		u.u_gid = ip->i_gid;
	for (i=0; i<NSIG; ++i) {
		if (u.u_sfunc[i] != SIG_IGN)
			u.u_sfunc[i] = SIG_DFL;
	}
	if ((pp->p_flags&PFTRAC) != 0)
		sendsig(SIGTRAP, pp);
	idetach(ip);
	segload();
	msetusr(pc, sp);
	return (0);

	/*
	 * We did not make it.
	 * Release the INODE for the load
	 * file, and return through the "sys exit"
	 * code with a "SIGSYS".
	 */
out:
	idetach(ip);
	pexit(SIGSYS);
}

/*
 * Open an l.out, make sure it is an l.out and executable and return the
 * appropriate information.
 */
INODE *
exlopen(np, ssizep, flagp, pcp)
char *np;
size_t *ssizep;
int *flagp;
vaddr_t *pcp;
{
	register INODE *ip;
	register struct ldheader *ldp;
	register int n;
	register BUF *bp;
	int m;

	/*
	 * Make sure the file is really an executable l.out and read the
	 * header in.
	 */
	if (ftoi(np, 'r') != 0)
		return (NULL);
	ip = u.u_cdiri;
	if (iaccess(ip, IPE) == 0) {
		idetach(ip);
		return (NULL);
	}
	if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
		u.u_error = EACCES;
		idetach(ip);
		return (NULL);
	}
	if ((bp=vread(ip, (daddr_t)0)) == NULL) {
		u.u_error = EBADFMT;
		idetach(ip);
		return (NULL);
	}

	/*
	 * Copy everything we need from the l.out header and check magic
	 * number and machine type.
	 */
	ldp = bp->b_vaddr;
	m = ldp->l_magic;
	canint(m);
	if (m != L_MAGIC) {
		u.u_error = ENOEXEC;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	m = ldp->l_machine;
	canint(m);
	if (m != mactype) {
		u.u_error = EBADFMT;
		brelease(bp);
		idetach(ip);
		return (NULL);
	}
	kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(size_t));
	for (n=0; n<NXSEG; n++)
		cansize(ssizep[n]);
	*flagp = ldp->l_flag;
	canint(*flagp);
	*pcp = ldp->l_entry;
	canvaddr(*pcp);
	brelease(bp);
	return (ip);
}

/*
 * Given a segment `sp', read `ss' bytes from the inode `ip' starting
 * at seek address `sa' into offset `so' in the segment.
 */
exsread(sp, ip, ss, sa, so)
register SEG *sp;
INODE *ip;
size_t sa;
register size_t ss;
size_t so;
{
	register int n;

	u.u_io.io_seg = IOPHY;
	u.u_io.io_seek = sa;
	u.u_io.io_phys = ctob((paddr_t)sp->s_mbase) + so;
	u.u_error = 0;
	while (u.u_error==0 && ss!=0) {
		n = ss>SCHUNK ? SCHUNK : ss;
		u.u_io.io_ioc = n;
		ss -= n;
		iread(ip, &u.u_io);
		u.u_io.io_seek += n;	/* Coherent bug? */
	}
	return (u.u_error==0);
}

/*
 * Given a pointer to a list of arguments and a pointer to a list of
 * environments, return a stack with the arguments and environments on it.
 */
SEG *
exstack(iusp, argp, envp)
char **iusp;		/* Back patch sp value */
char *argp[];		/* Arguments for new process */
char *envp[];		/* Environments for new process */
{
	SEG *sp;		/* Stack segment pointer */
	struct adata {		/* Storage for arg and env data */
		char	**up;		/* User vector pointer */
		int	np;		/* Number of pointers in vector */
		int	nc;		/* Number of characters in strings */
	} arg, env;
	struct sdata {		/* To keep segment pointers */
		vaddr_t	base;		/* Top of segment virtual */
		vaddr_t	ap;		/* Argc, argv, envp pointer */
		vaddr_t	vp;		/* Argv[i], envp[i] pointer */
		vaddr_t	cp;		/* Argv[i][j], envp[i][j] pointer */
	} aux, stk;
	aold_t aold;			/* Auxiliary map storage */
	register char **usrvp;		/* Vector pointer into user seg */
	register char *usrcp;		/* Character pointer into user seg */
	register int c;			/* Character fetched from user */
	register int chrsz;		/* Size of strings */
	register struct adata *adp;	/* Arg and env scanner */
	register int vecsz;		/* Size of vectors */
	register int stksz;		/* Size of stack argument region */

	/* Validate and evaluate size of args and envs */
	arg.up = argp;
	env.up = envp;
	chrsz = 0;
	vecsz = 0;
	for (adp = &arg; ; adp = &env) {
		adp->np = 0;
		adp->nc = 0;
		if (excount(adp->up, &adp->np, &adp->nc) == 0)
			return (NULL);
		chrsz += adp->nc * sizeof(char);
		vecsz += adp->np * sizeof(char *);
		if (adp == &env)
			break;
	}

	/* Calculate stack size and allocate it */
	chrsz = roundu(chrsz, sizeof(int));
	stksz = sizeof(int)		/* argc */
		+ sizeof(char **)	/* argv */
		+ sizeof(char **)	/* envp */
		+ vecsz			/* argv[i] and envp[i] */
		+ chrsz			/* *argv[i] and *envp[i] */
		+ sizeof(int)		/* Mystery zero word */
		+ sizeof(char *)	/* Splimit for z8000 */
		+ sizeof(int);		/* errno */
	stksz += ISTSIZE;
	if (stksz > MADSIZE) {
		u.u_error = E2BIG;
		return (NULL);
	}
	if ((sp=salloc((size_t)stksz, SFDOWN)) == NULL)
		return (NULL);
	stksz -= ISTSIZE;

	/*
	 * Initialize segment data.
	 */
	asave(aold);

	aux.base = (vaddr_t)abase(sp->s_mbase) + ctob(sp->s_size);
	aux.ap = aux.base - stksz;
	aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
	aux.cp = aux.vp + vecsz;

	stk.base = ISTVIRT;
	stk.ap = stk.base - stksz;
	stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
	stk.cp = stk.vp + vecsz;

	/*
	 * Write argc.
	 */
	aputi((int *)aux.ap, arg.np-1);
	aux.ap += sizeof(int);

	/*
	 * Arguments and environments.
	 */
	for (adp = &arg; ; adp = &env) {

		/* Write argv or envp */
		aputp((char ***)aux.ap, (char **)stk.vp);
		aux.ap += sizeof(char **);
		if ((usrvp = adp->up) != NULL) {

			/* Write argv[i] or envp[i] */
			while ((usrcp = getupd(usrvp++)) != NULL) {
				aputp((char **)aux.vp, (char *)stk.cp);
				aux.vp += sizeof(char *);
				stk.vp += sizeof(char *);

				/* Write argv[i][j] or envp[i][j] */
				do {
					c = getubd(usrcp++);
					aputc((char *)aux.cp, c);
					aux.cp += sizeof(char);
					stk.cp += sizeof(char);
				} while (c != '\0');
			}
		}

		/* Write argv[argc] or envp[envc] */
		aputp((char **)aux.vp, NULL);
		aux.vp += sizeof(char *);
		stk.vp += sizeof(char *);
		if (adp == &env)
			break;
	}

	/*
	 * Clear out the slop.
	 */
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* errno */
	aux.base -= sizeof(char *);
	aputp((char **) aux.base, (char *)stk.base-ctob(sp->s_size)+SOVSIZE);
	aux.base -= sizeof(int);
	aputi((int *) aux.base, 0);		/* mystery word */

	arest(aold);

	/*
	 * Patch some values and return.
	 */
	*iusp = (char *)stk.ap;	/* Patch initial usp */
	u.u_argc = arg.np-1;
	u.u_argp = stk.vp;	/* Points after NULL of envs */
	return (sp);
}

/*
 * Given a pointer to a list of arguments, a pointer to an argument count
 * and a pointer to a byte count, update incrementally the argument count
 * and the byte count.
 */
excount(usrvp, nap, nbp)
register char **usrvp;
int *nap;
int *nbp;
{
	register char *usrcp;
	register int c;
	register unsigned nb;
	register unsigned na;

	na = 1;
	nb = 0;
	if (usrvp != NULL) {
		for (;;) {
			usrcp = getupd(usrvp++);
			if (u.u_error)
				return (0);
			if (usrcp == NULL)
				break;
			na++;
			for (;;) {
				c = getubd(usrcp++);
				if (u.u_error)
					return (0);
				nb++;
				if (c == '\0')
					break;
			}
		}
	}
	*nap += na;
	*nbp += nb;
	return (1);
}