From 29dd101b6858922dac6d23c67a2ad2454734ab02 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Wed, 9 Apr 1980 23:04:26 -0800 Subject: [PATCH] date and time created 80/04/09 16:04:26 by bill SCCS-vsn: sys/kern/kern_proc.c 3.1 --- usr/src/sys/kern/kern_proc.c | 606 +++++++++++++++++++++++++++++++++++ 1 file changed, 606 insertions(+) create mode 100644 usr/src/sys/kern/kern_proc.c diff --git a/usr/src/sys/kern/kern_proc.c b/usr/src/sys/kern/kern_proc.c new file mode 100644 index 0000000000..8af1856a5e --- /dev/null +++ b/usr/src/sys/kern/kern_proc.c @@ -0,0 +1,606 @@ +/* kern_proc.c 3.1 %H% */ + +#include "../h/param.h" +#include "../h/systm.h" +#include "../h/map.h" +#include "../h/mtpr.h" +#include "../h/dir.h" +#include "../h/user.h" +#include "../h/proc.h" +#include "../h/buf.h" +#include "../h/reg.h" +#include "../h/inode.h" +#include "../h/seg.h" +#include "../h/acct.h" +#include "../h/pte.h" +#include "../h/vm.h" +#include "../h/text.h" + +/* + * exec system call, with and without environments. + */ +struct execa { + char *fname; + char **argp; + char **envp; +}; + +exec() +{ + ((struct execa *)u.u_ap)->envp = NULL; + exece(); +} + +exece() +{ + register nc; + register char *cp; + register struct buf *bp; + register struct execa *uap; + int na, ne, ucp, ap, c; + struct inode *ip; + swblk_t bno; + + if ((ip = namei(uchar, 0)) == NULL) + return; + bno = 0; + bp = 0; + if(access(ip, IEXEC)) + goto bad; + if((ip->i_mode & IFMT) != IFREG || + (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) { + u.u_error = EACCES; + goto bad; + } + /* + * Collect arguments on "file" in swap space. + */ + na = 0; + ne = 0; + nc = 0; + uap = (struct execa *)u.u_ap; + if ((bno = malloc(swapmap, ctod(clrnd((int) btoc(NCARGS))))) == 0) { + swkill(u.u_procp, "exece"); + goto bad; + } + if (bno % CLSIZE) + panic("execa malloc"); + if (uap->argp) for (;;) { + ap = NULL; + if (uap->argp) { + ap = fuword((caddr_t)uap->argp); + uap->argp++; + } + if (ap==NULL && uap->envp) { + uap->argp = NULL; + if ((ap = fuword((caddr_t)uap->envp)) == NULL) + break; + uap->envp++; + ne++; + } + if (ap==NULL) + break; + na++; + if(ap == -1) + u.u_error = EFAULT; + do { + if (nc >= NCARGS-1) + u.u_error = E2BIG; + if ((c = fubyte((caddr_t)ap++)) < 0) + u.u_error = EFAULT; + if (u.u_error) + goto badarg; + if ((nc&BMASK) == 0) { + if (bp) + bdwrite(bp); + bp = getblk(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); + cp = bp->b_un.b_addr; + } + nc++; + *cp++ = c; + } while (c>0); + } + if (bp) + bdwrite(bp); + bp = 0; + nc = (nc + NBPW-1) & ~(NBPW-1); + if (getxfile(ip, nc) || u.u_error) { +badarg: + for (c = 0; c < nc; c += BSIZE) + if (bp = baddr(swapdev, dbtofsb(swplo+bno)+(c>>BSHIFT))) { + bp->b_flags |= B_AGE; /* throw away */ + bp->b_flags &= ~B_DELWRI; /* cancel io */ + brelse(bp); + bp = 0; + } + goto bad; + } + + /* + * copy back arglist + */ + + ucp = USRSTACK - nc - NBPW; + ap = ucp - na*NBPW - 3*NBPW; + u.u_ar0[SP] = ap; + VOID suword((caddr_t)ap, na-ne); + nc = 0; + for (;;) { + ap += NBPW; + if (na==ne) { + VOID suword((caddr_t)ap, 0); + ap += NBPW; + } + if (--na < 0) + break; + VOID suword((caddr_t)ap, ucp); + do { + if ((nc&BMASK) == 0) { + if (bp) + brelse(bp); + bp = bread(swapdev, (daddr_t)(dbtofsb(swplo+bno)+(nc>>BSHIFT))); + bp->b_flags |= B_AGE; /* throw away */ + bp->b_flags &= ~B_DELWRI; /* cancel io */ + cp = bp->b_un.b_addr; + } + VOID subyte((caddr_t)ucp++, (c = *cp++)); + nc++; + } while(c&0377); + } + VOID suword((caddr_t)ap, 0); + VOID suword((caddr_t)ucp, 0); + setregs(); +bad: + if (bp) + brelse(bp); + if (bno) + mfree(swapmap, ctod(clrnd((int) btoc(NCARGS))), bno); + iput(ip); +} + +/* + * Read in and set up memory for executed file. + * Zero return is normal; + * non-zero means only the text is being replaced + */ +getxfile(ip, nargc) +register struct inode *ip; +{ + register sep; + register size_t ts, ds, ss; + register int overlay; + int pagi = 0; + + /* + * read in first few bytes + * of file for segment + * sizes: + * ux_mag = 407/410/411/405 + * 407 is plain executable + * 410 is RO text + * 411 is separated ID + * 405 is overlaid text + * 412 is demand paged plain executable (NOT IMPLEMENTED) + * 413 is demand paged RO text + */ + + u.u_base = (caddr_t)&u.u_exdata; + u.u_count = sizeof(u.u_exdata); + u.u_offset = 0; + u.u_segflg = 1; + readi(ip); + u.u_segflg = 0; + if(u.u_error) + goto bad; + if (u.u_count!=0) { + u.u_error = ENOEXEC; + goto bad; + } + sep = 0; + overlay = 0; + switch (u.u_exdata.ux_mag) { + + case 0405: + overlay++; + break; + + case 0412: + u.u_error = ENOEXEC; + goto bad; + + case 0407: + u.u_exdata.ux_dsize += u.u_exdata.ux_tsize; + u.u_exdata.ux_tsize = 0; + break; + + case 0413: + pagi = SPAGI; + /* fall into ... */ + + case 0410: + if (u.u_exdata.ux_tsize == 0) { + u.u_error = ENOEXEC; + goto bad; + } + break; + + case 0411: + u.u_error = ENOEXEC; + goto bad; + + default: + u.u_error = ENOEXEC; + goto bad; + } + if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) { + u.u_error = ETXTBSY; + goto bad; + } + + /* + * find text and data sizes + * try them out for possible + * exceed of max sizes + */ + + ts = clrnd(btoc(u.u_exdata.ux_tsize)); + ds = clrnd(btoc((u.u_exdata.ux_dsize+u.u_exdata.ux_bsize))); + ss = clrnd(SSIZE + btoc(nargc)); + if (overlay) { + if ((u.u_procp->p_flag & SPAGI) || u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) { + u.u_error = ENOMEM; + goto bad; + } + ds = u.u_dsize; + ss = u.u_ssize; + sep = u.u_sep; + xfree(); + xalloc(ip, pagi); + u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ + } else { + if (chksize(ts, ds, ss)) + goto bad; + u.u_cdmap = zdmap; + u.u_csmap = zdmap; + if (swpexpand(ds, ss, &u.u_cdmap, &u.u_csmap) == NULL) + goto bad; + + /* + * At this point, committed to the new image! + * Release virtual memory resources of old process, and + * initialize the virtual memory of the new process. + * If we resulted from vfork(), instead wakeup our + * parent who will set SVFDONE when he has taken back + * our resources. + */ + u.u_prof.pr_scale = 0; + if ((u.u_procp->p_flag & SVFORK) == 0) + vrelvm(); + else { + u.u_procp->p_flag &= ~SVFORK; + u.u_procp->p_flag |= SKEEP; + wakeup((caddr_t)u.u_procp); + while ((u.u_procp->p_flag & SVFDONE) == 0) + sleep((caddr_t)u.u_procp, PZERO - 1); + u.u_procp->p_flag &= ~(SVFDONE|SKEEP); + } + u.u_procp->p_flag &= ~(SPAGI|SANOM|SUANOM); + u.u_procp->p_flag |= pagi; + u.u_dmap = u.u_cdmap; + u.u_smap = u.u_csmap; + vgetvm(ts, ds, ss); + + if (pagi == 0) { + /* + * Read in data segment. + */ + u.u_base = (char *)ctob(ts); + u.u_offset = sizeof(u.u_exdata)+u.u_exdata.ux_tsize; + u.u_count = u.u_exdata.ux_dsize; + readi(ip); + } + xalloc(ip, pagi); + if (pagi && u.u_procp->p_textp) + vinifod((struct fpte *)dptopte(u.u_procp, 0), + PG_FTEXT, u.u_procp->p_textp->x_iptr, + 1 + ts/CLSIZE, (int)btoc(u.u_exdata.ux_dsize)); + + /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */ + mtpr(TBIA,1); + + /* + * set SUID/SGID protections, if no tracing + */ + if ((u.u_procp->p_flag&STRC)==0) { + if(ip->i_mode&ISUID) + if(u.u_uid != 0) { + u.u_uid = ip->i_uid; + u.u_procp->p_uid = ip->i_uid; + } + if(ip->i_mode&ISGID) + u.u_gid = ip->i_gid; + } else + psignal(u.u_procp, SIGTRC); + } + u.u_tsize = ts; + u.u_dsize = ds; + u.u_ssize = ss; + u.u_sep = sep; +bad: + return(overlay); +} + +/* + * Clear registers on exec + */ +setregs() +{ + register int *rp; + register i; + + for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++) + if((*rp & 1) == 0) + *rp = 0; +/* + for(rp = &u.u_ar0[0]; rp < &u.u_ar0[16];) + *rp++ = 0; +*/ + u.u_ar0[PC] = u.u_exdata.ux_entloc + 2; /* skip over entry mask */ + for(i=0; irval & 0377) << 8); +} + +/* + * Release resources. + * Save u. area for parent to look at. + * Enter zombie state. + * Wake up parent and init processes, + * and dispose of children. + */ +exit(rv) +{ + register int i; + register struct proc *p, *q; + register struct file *f; + register int x; + +#ifdef PGINPROF + vmsizmon(); +#endif + p = u.u_procp; + p->p_flag &= ~(STRC|SULOCK); + p->p_flag |= SWEXIT; + p->p_clktim = 0; + rate.v_pgin -= p->p_aveflt; + p->p_aveflt = 0; + for(i=0; ip_flag & SVFORK) == 0) + vrelvm(); + else { + p->p_flag &= ~SVFORK; + wakeup((caddr_t)p); + while ((p->p_flag & SVFDONE) == 0) + sleep((caddr_t)p, PZERO - 1); + p->p_flag &= ~SVFDONE; + } + for(i=0; ip_stat = SZOMB; + i = PIDHASH(p->p_pid); + x = p - proc; + if (pidhash[i] == x) + pidhash[i] = p->p_idhash; + else { + for (i = pidhash[i]; i != 0; i = proc[i].p_idhash) + if (proc[i].p_idhash == x) { + proc[i].p_idhash = p->p_idhash; + goto done; + } + panic("exit"); + } +done: + ((struct xproc *)p)->xp_xstat = rv; /* overlay */ + ((struct xproc *)p)->xp_vm = u.u_vm; /* overlay */ + vmsadd(&((struct xproc *)p)->xp_vm, &u.u_cvm); + for(q = &proc[0]; q < &proc[NPROC]; q++) + if(q->p_ppid == p->p_pid) { + wakeup((caddr_t)&proc[1]); + q->p_ppid = 1; + if (q->p_stat==SSTOP) + setrun(q); + } + q = pfind(p->p_ppid); + if (q) + wakeup((caddr_t)q); + swtch(); +} + +wait() +{ + + wait1((struct vtimes *)0); +} + +/* + * Wait system call. + * Search for a terminated (zombie) child, + * finally lay it to rest, and collect its status. + * Look also for stopped (traced) children, + * and pass back status from them. + */ +wait1(vp) + struct vtimes *vp; +{ + register f; + register struct proc *p; + + f = 0; + +loop: + for(p = &proc[0]; p < &proc[NPROC]; p++) + if(p->p_ppid == u.u_procp->p_pid) { + f++; + if(p->p_stat == SZOMB) { + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = ((struct xproc *)p)->xp_xstat; + ((struct xproc *)p)->xp_xstat = 0; + if (vp) + *vp = ((struct xproc *)p)->xp_vm; + vmsadd(&u.u_cvm, &((struct xproc *)p)->xp_vm); + ((struct xproc *)p)->xp_vm = zvms; + p->p_stat = NULL; + p->p_pid = 0; + p->p_ppid = 0; + p->p_sig = 0; + p->p_pgrp = 0; + p->p_flag = 0; + p->p_wchan = 0; + return; + } + if(p->p_stat == SSTOP) { + if((p->p_flag&SWTED) == 0) { + p->p_flag |= SWTED; + u.u_r.r_val1 = p->p_pid; + u.u_r.r_val2 = (fsig(p)<<8) | 0177; + return; + } + continue; + } + } + if(f) { + sleep((caddr_t)u.u_procp, PWAIT); + goto loop; + } + u.u_error = ECHILD; +} + +/* + * fork system call. + */ +fork() +{ + + u.u_cdmap = zdmap; + u.u_csmap = zdmap; + if (swpexpand(u.u_dsize, u.u_ssize, &u.u_cdmap, &u.u_csmap) == 0) { + u.u_r.r_val2 = 0; + return; + } + fork1(0); +} + +fork1(isvfork) +{ + register struct proc *p1, *p2; + register a; + + a = 0; + p2 = NULL; + for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) { + if (p1->p_stat==NULL && p2==NULL) + p2 = p1; + else { + if (p1->p_uid==u.u_uid && p1->p_stat!=NULL) + a++; + } + } + /* + * Disallow if + * No processes at all; + * not su and too many procs owned; or + * not su and would take last slot. + */ + if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) { + u.u_error = EAGAIN; + if (!isvfork) { + VOID vsexpand(0, &u.u_cdmap, 1); + VOID vsexpand(0, &u.u_csmap, 1); + } + goto out; + } + p1 = u.u_procp; + if(newproc(isvfork)) { + u.u_r.r_val1 = p1->p_pid; + u.u_r.r_val2 = 1; /* child */ + u.u_start = time; + u.u_acflag = AFORK; + return; + } + u.u_r.r_val1 = p2->p_pid; + +out: + u.u_r.r_val2 = 0; +} + +/* + * break system call. + * -- bad planning: "break" is a dirty word in C. + */ +sbreak() +{ + struct a { + char *nsiz; + }; + register int n, d; + + /* + * set n to new data size + * set d to new-old + */ + + n = btoc(((struct a *)u.u_ap)->nsiz); + if (!u.u_sep) + n -= ctos(u.u_tsize) * stoc(1); + if (n < 0) + n = 0; + d = clrnd(n - u.u_dsize); + if (chksize(u.u_tsize, u.u_dsize+d, u.u_ssize)) + return; + if (swpexpand(u.u_dsize+d, u.u_ssize, &u.u_dmap, &u.u_smap)==0) + return; + expand(d, P0BR); +} -- 2.20.1