|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 13734 (0x35a6)
Types: TextFile
Notes: UNIX file
Names: »exec.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »sys/coh/exec.c«
/* (-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);
}