|
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 - 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); }