BSD 4 development
authorBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 16:35:32 +0000 (08:35 -0800)
committerBill Joy <wnj@ucbvax.Berkeley.EDU>
Sun, 9 Nov 1980 16:35:32 +0000 (08:35 -0800)
Work on file usr/src/sys/sys/prf.c
Work on file usr/src/sys/sys/main.c
Work on file usr/src/sys/sys/sig.c
Work on file usr/src/sys/sys/sys1.c
Work on file usr/src/sys/sys/trap.c

Synthesized-from: CSRG//cd1/4.0

usr/src/sys/sys/main.c [new file with mode: 0644]
usr/src/sys/sys/prf.c [new file with mode: 0644]
usr/src/sys/sys/sig.c [new file with mode: 0644]
usr/src/sys/sys/sys1.c [new file with mode: 0644]
usr/src/sys/sys/trap.c [new file with mode: 0644]

diff --git a/usr/src/sys/sys/main.c b/usr/src/sys/sys/main.c
new file mode 100644 (file)
index 0000000..d57eebe
--- /dev/null
@@ -0,0 +1,245 @@
+/*     main.c  4.2     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/filsys.h"
+#include "../h/mount.h"
+#include "../h/map.h"
+#include "../h/proc.h"
+#include "../h/inode.h"
+#include "../h/seg.h"
+#include "../h/conf.h"
+#include "../h/buf.h"
+#include "../h/mtpr.h"
+#include "../h/pte.h"
+#include "../h/clock.h"
+#include "../h/vm.h"
+#include "../h/cmap.h"
+#include "../h/text.h"
+#include "../h/vlimit.h"
+
+/*
+ * Initialization code.
+ * Called from cold start routine as
+ * soon as a stack and segmentation
+ * have been established.
+ * Functions:
+ *     clear and free user core
+ *     turn on clock
+ *     hand craft 0th process
+ *     call all initialization routines
+ *     fork - process 0 to schedule
+ *          - process 2 to page out
+ *          - process 1 execute bootstrap
+ *
+ * loop at loc 13 (0xd) in user mode -- /etc/init
+ *     cannot be executed.
+ */
+main(firstaddr)
+{
+       register int i;
+
+       cpusid = mfpr(SID);             /* get system identification */
+#ifdef FASTVAX
+       rqinit();
+#endif
+       startup(firstaddr);
+       if (lotsfree == 0)
+               lotsfree = LOTSFREE;
+
+       /*
+        * set up system process 0 (swapper)
+        */
+
+       proc[0].p_p0br = (struct pte *)mfpr(P0BR);
+       proc[0].p_szpt = 1;
+       proc[0].p_addr = uaddr(&proc[0]);
+       proc[0].p_stat = SRUN;
+       proc[0].p_flag |= SLOAD|SSYS;
+       proc[0].p_nice = NZERO;
+       u.u_procp = &proc[0];
+       u.u_cmask = CMASK;
+       for (i = 1; i < sizeof(u.u_limit)/sizeof(u.u_limit[0]); i++)
+               switch (i) {
+
+               case LIM_STACK:
+                       u.u_limit[i] = 512*1024;
+                       continue;
+               case LIM_DATA:
+                       u.u_limit[i] = ctob(MAXDSIZ);
+                       continue;
+               default:
+                       u.u_limit[i] = INFINITY;
+                       continue;
+               }
+       clkstart();
+
+       /*
+        * Initialize devices and
+        * set up 'known' i-nodes
+        */
+
+       ihinit();
+       bhinit();
+       cinit();
+       binit();
+       bswinit();
+       iinit();
+       rootdir = iget(rootdev, (ino_t)ROOTINO);
+       rootdir->i_flag &= ~ILOCK;
+       u.u_cdir = iget(rootdev, (ino_t)ROOTINO);
+       u.u_cdir->i_flag &= ~ILOCK;
+       u.u_rdir = NULL;
+       u.u_dmap = zdmap;
+       u.u_smap = zdmap;
+
+       /*
+        * make page-out daemon (process 2)
+        * the daemon has ctopt(NSWBUF*CLSIZE*KLMAX) pages of page
+        * table so that it can map dirty pages into
+        * its address space during asychronous pushes.
+        */
+
+       mpid = 1;
+       proc[0].p_szpt = clrnd(ctopt(NSWBUF*CLSIZE*KLMAX + UPAGES));
+       proc[1].p_stat = SZOMB;         /* force it to be in proc slot 2 */
+       if (newproc(0)) {
+               proc[2].p_flag |= SLOAD|SSYS;
+               proc[2].p_dsize = u.u_dsize = NSWBUF*CLSIZE*KLMAX; 
+               pageout();
+       }
+
+       /*
+        * make init process and
+        * enter scheduling loop
+        */
+
+       mpid = 0;
+       proc[1].p_stat = 0;
+       proc[0].p_szpt = CLSIZE;
+       if (newproc(0)) {
+               expand(clrnd((int)btoc(szicode)), P0BR);
+               (void) swpexpand(u.u_dsize, 0, &u.u_dmap, &u.u_smap);
+               (void) copyout((caddr_t)icode, (caddr_t)0, (unsigned)szicode);
+               /*
+                * Return goes to loc. 0 of user init
+                * code just copied out.
+                */
+               return;
+       }
+       proc[0].p_szpt = 1;
+       sched();
+}
+
+/*
+ * iinit is called once (from main)
+ * very early in initialization.
+ * It reads the root's super block
+ * and initializes the current date
+ * from the last modified date.
+ *
+ * panic: iinit -- cannot read the super
+ * block. Usually because of an IO error.
+ */
+iinit()
+{
+       register struct buf *cp, *bp;
+       register struct filsys *fp;
+
+       (*bdevsw[major(rootdev)].d_open)(rootdev, 1);
+       bp = bread(rootdev, SUPERB);
+       cp = geteblk();
+       if(u.u_error)
+               panic("iinit");
+       bcopy(bp->b_un.b_addr, cp->b_un.b_addr, sizeof(struct filsys));
+       brelse(bp);
+       mount[0].m_bufp = cp;
+       mount[0].m_dev = rootdev;
+       fp = cp->b_un.b_filsys;
+       fp->s_flock = 0;
+       fp->s_ilock = 0;
+       fp->s_ronly = 0;
+       fp->s_lasti = 1;
+       fp->s_nbehind = 0;
+       clkinit(fp->s_time);
+       bootime = time;
+}
+
+/*
+ * This is the set of buffers proper, whose heads
+ * were declared in buf.h.  There can exist buffer
+ * headers not pointing here that are used purely
+ * as arguments to the I/O routines to describe
+ * I/O to be done-- e.g. swap headers swbuf[] for
+ * swapping.
+ *
+ * These are actually allocated kernel map slots and space is
+ * allocated in locore.s for them.
+ */
+char   buffers[NBUF][BSIZE];
+
+/*
+ * Initialize the buffer I/O system by freeing
+ * all buffers and setting all device buffer lists to empty.
+ */
+binit()
+{
+       register struct buf *bp;
+       register struct buf *dp;
+       register int i;
+       struct bdevsw *bdp;
+       struct swdevt *swp;
+
+       bfreelist.b_forw = bfreelist.b_back =
+           bfreelist.av_forw = bfreelist.av_back = &bfreelist;
+       for (i=0; i<NBUF; i++) {
+               bp = &buf[i];
+               bp->b_dev = NODEV;
+               bp->b_un.b_addr = buffers[i];
+               bp->b_back = &bfreelist;
+               bp->b_forw = bfreelist.b_forw;
+               bfreelist.b_forw->b_back = bp;
+               bfreelist.b_forw = bp;
+               bp->b_flags = B_BUSY;
+               brelse(bp);
+       }
+       for (bdp = bdevsw; bdp->d_open; bdp++) {
+               dp = bdp->d_tab;
+               if(dp) {
+                       dp->b_forw = dp;
+                       dp->b_back = dp;
+               }
+               nblkdev++;
+       }
+       /*
+        * Count swap devices, and adjust total swap space available.
+        * Some of this space will not be available until a vswapon()
+        * system is issued, usually when the system goes multi-user.
+        */
+       nswdev = 0;
+       for (swp = swdevt; swp->sw_dev; swp++)
+               nswdev++;
+       if (nswdev == 0)
+               panic("binit");
+       nswap *= nswdev;
+       maxpgio *= nswdev;
+       swfree(0);
+}
+
+/*
+ * Initialize linked list of free swap
+ * headers. These do not actually point
+ * to buffers, but rather to pages that
+ * are being swapped in and out.
+ */
+bswinit()
+{
+       register int i;
+
+       bswlist.av_forw = &swbuf[0];
+       for (i=0; i<NSWBUF-1; i++)
+               swbuf[i].av_forw = &swbuf[i+1];
+       swbuf[NSWBUF-1].av_forw = NULL;
+}
diff --git a/usr/src/sys/sys/prf.c b/usr/src/sys/sys/prf.c
new file mode 100644 (file)
index 0000000..06309a6
--- /dev/null
@@ -0,0 +1,226 @@
+/*     prf.c   4.3     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/seg.h"
+#include "../h/buf.h"
+#include "../h/conf.h"
+#include "../h/mtpr.h"
+#include "../h/reboot.h"
+
+#ifdef TRACE
+#define        TRCBUFS 4096
+char   trcbuf[TRCBUFS];
+char   *trcbufp = trcbuf;
+int    trcwrap;
+int    trcprt = TRCBUFS;
+#endif
+
+/*
+ * In case console is off,
+ * panicstr contains argument to last
+ * call to panic.
+ */
+
+char   *panicstr;
+
+/*
+ * Scaled down version of C Library printf.
+ * Only %s %u %d (==%u) %o %x %D are recognized.
+ * Used to print diagnostic information
+ * directly on console tty.
+ * Since it is not interrupt driven,
+ * all system activities are pretty much
+ * suspended.
+ * Printf should not be used for chit-chat.
+ */
+/*VARARGS1*/
+printf(fmt, x1)
+register char *fmt;
+unsigned x1;
+{
+
+       prf(fmt, &x1, 0);
+}
+
+#ifdef TRACE
+trace(fmt, x1)
+register char *fmt;
+unsigned x1;
+{
+
+       prf(fmt, &x1, 1);
+}
+
+#endif
+
+prf(fmt, adx, trace)
+register char *fmt;
+register unsigned int *adx;
+{
+       register c;
+       char *s;
+
+loop:
+       while((c = *fmt++) != '%') {
+               if(c == '\0')
+                       return;
+               putchar(c, trace);
+       }
+       c = *fmt++;
+       if (c == 'X')
+               printx((long)*adx, trace);
+       else if (c == 'd' || c == 'u' || c == 'o' || c == 'x')
+               printn((long)*adx, c=='o'? 8: (c=='x'? 16:10), trace);
+       else if (c == 's') {
+               s = (char *)*adx;
+               while (c = *s++)
+#ifdef TRACE
+                       if (trace) {
+                               *trcbufp++ = c;
+                               if (trcbufp >= &trcbuf[TRCBUFS]) {
+                                       trcbufp = trcbuf;
+                                       trcwrap = 1;
+                               }
+                       } else
+#endif
+                               putchar(c, trace);
+       } else if (c == 'D') {
+               printn(*(long *)adx, 10, trace);
+               adx += (sizeof(long) / sizeof(int)) - 1;
+       }
+       adx++;
+       goto loop;
+}
+
+printx(x, trace)
+long x;
+{
+       int i;
+
+       for (i = 0; i < 8; i++)
+               putchar("0123456789ABCDEF"[(x>>((7-i)*4))&0xf], trace);
+}
+
+/*
+ * Print an unsigned integer in base b.
+ */
+printn(n, b, trace)
+long n;
+{
+       register long a;
+
+       if (n<0) {      /* shouldn't happen */
+               putchar('-', trace);
+               n = -n;
+       }
+       if(a = n/b)
+               printn(a, b, trace);
+       putchar("0123456789ABCDEF"[(int)(n%b)], trace);
+}
+
+/*
+ * Panic is called on unresolvable fatal errors.
+ * It syncs, prints "panic: mesg", and then reboots.
+ */
+panic(s)
+char *s;
+{
+       panicstr = s;
+       printf("panic: %s\n", s);
+       (void) spl0();
+       for(;;)
+               boot(RB_PANIC, RB_AUTOBOOT);
+}
+
+/*
+ * prdev prints a warning message of the
+ * form "mesg on dev x/y".
+ * x and y are the major and minor parts of
+ * the device argument.
+ */
+prdev(str, dev)
+char *str;
+dev_t dev;
+{
+
+       printf("%s on dev %u/%u\n", str, major(dev), minor(dev));
+}
+
+/*
+ * deverr prints a diagnostic from
+ * a device driver.
+ * It prints the device, block number,
+ * and an octal word (usually some error
+ * status register) passed as argument.
+ */
+deverror(bp, o1, o2)
+register struct buf *bp;
+{
+
+       prdev("err", bp->b_dev);
+       printf("bn=%d er=%x,%x\n", bp->b_blkno, o1,o2);
+}
+
+#ifdef TRACE
+dumptrc()
+{
+       register char *cp;
+       register int pos, nch;
+
+       nch = trcprt;
+       if (nch < 0 || nch > TRCBUFS)
+               nch = TRCBUFS;
+       pos = (trcbufp - trcbuf) - nch;
+       if (pos < 0)
+               if (trcwrap)
+                       pos += TRCBUFS;
+               else {
+                       nch += pos;
+                       pos = 0;
+               }
+       for (cp = &trcbuf[pos]; nch > 0; nch--) {
+               putchar(*cp++, 0);
+               if (cp >= &trcbuf[TRCBUFS])
+                       cp = trcbuf;
+       }
+}
+#else
+/*ARGSUSED*/
+dumptrc(nch)
+       int nch;
+{
+
+}
+#endif
+
+char   *msgbufp = msgbuf;      /* Next saved printf character */
+/*
+ * Print a character on console or in internal trace buffer.
+ * If destination is console then the last MSGBUFS characters
+ * are saved in msgbuf for inspection later.
+ */
+/*ARGSUSED*/
+putchar(c, trace)
+register c;
+{
+
+#ifdef TRACE
+       if (trace) {
+               *trcbufp++ = c;
+               if (trcbufp >= &trcbuf[TRCBUFS]) {
+                       trcbufp = trcbuf;
+                       trcwrap = 1;
+               }
+               return;
+       }
+#endif
+       if (c != '\0' && c != '\r' && c != 0177) {
+               *msgbufp++ = c;
+               if (msgbufp >= &msgbuf[MSGBUFS])
+                       msgbufp = msgbuf;
+       }
+       if (c == 0)
+               return;
+       cnputc(c);
+}
diff --git a/usr/src/sys/sys/sig.c b/usr/src/sys/sys/sig.c
new file mode 100644 (file)
index 0000000..237fd54
--- /dev/null
@@ -0,0 +1,722 @@
+/*     sig.c   4.3     11/9/80 */
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/inode.h"
+#include "../h/reg.h"
+#include "../h/text.h"
+#include "../h/seg.h"
+#include "../h/mtpr.h"
+#include "../h/pte.h"
+#include "../h/psl.h"
+#include "../h/vm.h"
+#include "../h/buf.h"
+#include "../h/vlimit.h"
+
+/*
+ * Priority for tracing
+ */
+#define        IPCPRI  PZERO
+
+/*
+ * Tracing variables.
+ * Used to pass trace command from
+ * parent to child being traced.
+ * This data base cannot be
+ * shared and is locked
+ * per user.
+ */
+struct
+{
+       int     ip_lock;
+       int     ip_req;
+       int     *ip_addr;
+       int     ip_data;
+} ipc;
+
+/*
+ * Send the specified signal to
+ * all processes with 'pgrp' as
+ * process group.
+ * Called by tty.c for quits and
+ * interrupts.
+ */
+gsignal(pgrp, sig)
+register pgrp;
+{
+       register struct proc *p;
+
+       if(pgrp == 0)
+               return;
+       for(p = &proc[0]; p < &proc[NPROC]; p++)
+               if(p->p_pgrp == pgrp)
+                       psignal(p, sig);
+}
+
+/*
+ * Send the specified signal to
+ * the specified process.
+ */
+psignal(p, sig)
+register struct proc *p;
+register int sig;
+{
+       register s;
+       register int (*action)();
+       long sigmask;
+
+       if((unsigned)sig >= NSIG)
+               return;
+       sigmask = (1L << (sig-1));
+
+       /*
+        * If proc is traced, always give parent a chance.
+        * Otherwise get the signal action from the bits in the proc table.
+        */
+       if (p->p_flag & STRC)
+               action = SIG_DFL;
+       else {
+               s = (p->p_siga1&sigmask) != 0;
+               s <<= 1;
+               s |= (p->p_siga0&sigmask) != 0;
+               action = (int(*)())s;
+               /*
+                * If the signal is ignored, we forget about it immediately.
+                */
+               if (action == SIG_IGN)
+                       return;
+       }
+       if (sig)
+               p->p_sig |= sigmask;
+       /*
+        * Defer further processing for signals which are held.
+        */
+       if (action == SIG_HOLD)
+               return;
+       s = spl6();
+       switch (p->p_stat) {
+
+       case SSLEEP:
+               /*
+                * If process is sleeping at negative priority
+                * we can't interrupt the sleep... the signal will
+                * be noticed when the process returns through
+                * trap() or syscall().
+                */
+               if (p->p_pri <= PZERO)
+                       goto out;
+               /*
+                * Process is sleeping and traced... make it runnable
+                * so it can discover the signal in issig() and stop
+                * for the parent.
+                */
+               if (p->p_flag&STRC)
+                       goto run;
+               switch (sig) {
+
+               case SIGSTOP:
+               case SIGTSTP:
+               case SIGTTIN:
+               case SIGTTOU:
+                       /*
+                        * These are the signals which by default
+                        * stop a process.
+                        */
+                       if (action != SIG_DFL)
+                               goto run;
+                       /*
+                        * Don't clog system with children of init
+                        * stopped from the keyboard.
+                        */
+                       if (sig != SIGSTOP && p->p_pptr == &proc[1]) {
+                               psignal(p, SIGKILL);
+                               p->p_sig &= ~sigmask;
+                               return;
+                       }
+                       /*
+                        * If a child in vfork(), stopping could
+                        * cause deadlock.
+                        */
+                       if (p->p_flag&SVFORK)
+                               goto out;
+                       p->p_sig &= ~sigmask;
+                       p->p_cursig = sig;
+                       stop(p);
+                       goto out;
+
+               case SIGTINT:
+               case SIGCHLD:
+                       /*
+                        * These signals are special in that they
+                        * don't get propogated... if the process
+                        * isn't interested, forget it.
+                        */
+                       if (action != SIG_DFL)
+                               goto run;
+                       p->p_sig &= ~sigmask;           /* take it away */
+                       goto out;
+
+               default:
+                       /*
+                        * All other signals cause the process to run
+                        */
+                       goto run;
+               }
+               /*NOTREACHED*/
+
+       case SSTOP:
+               /*
+                * If traced process is already stopped,
+                * then no further action is necessary.
+                */
+               if (p->p_flag&STRC)
+                       goto out;
+               switch (sig) {
+
+               case SIGKILL:
+                       /*
+                        * Kill signal always sets processes running.
+                        */
+                       goto run;
+
+               case SIGCONT:
+                       /*
+                        * If the process catches SIGCONT, let it handle
+                        * the signal itself.  If it isn't waiting on
+                        * an event, then it goes back to run state.
+                        * Otherwise, process goes back to sleep state.
+                        */
+                       if (action != SIG_DFL || p->p_wchan == 0)
+                               goto run;
+                       p->p_stat = SSLEEP;
+                       goto out;
+
+               case SIGSTOP:
+               case SIGTSTP:
+               case SIGTTIN:
+               case SIGTTOU:
+                       /*
+                        * Already stopped, don't need to stop again.
+                        * (If we did the shell could get confused.)
+                        */
+                       p->p_sig &= ~sigmask;           /* take it away */
+                       goto out;
+
+               default:
+                       /*
+                        * If process is sleeping interruptibly, then
+                        * unstick it so that when it is continued
+                        * it can look at the signal.
+                        * But don't setrun the process as its not to
+                        * be unstopped by the signal alone.
+                        */
+                       if (p->p_wchan && p->p_pri > PZERO)
+                               unsleep(p);
+                       goto out;
+               }
+               /*NOTREACHED*/
+
+       default:
+               /*
+                * SRUN, SIDL, SZOMB do nothing with the signal.
+                * It will either never be noticed, or noticed very soon.
+                */
+               goto out;
+       }
+       /*NOTREACHED*/
+run:
+       /*
+        * Raise priority to at least PUSER.
+        */
+       if (p->p_pri > PUSER)
+               if ((p != u.u_procp || noproc) && p->p_stat == SRUN &&
+                   (p->p_flag & SLOAD)) {
+                       remrq(p);
+                       p->p_pri = PUSER;
+                       setrq(p);
+               } else
+                       p->p_pri = PUSER;
+       setrun(p);
+out:
+       splx(s);
+}
+
+/*
+ * Returns true if the current
+ * process has a signal to process.
+ * The signal to process is put in p_cursig.
+ * This is asked at least once each time a process enters the
+ * system (though this can usually be done without actually
+ * calling issig by checking the pending signal masks.)
+ * A signal does not do anything
+ * directly to a process; it sets
+ * a flag that asks the process to
+ * do something to itself.
+ */
+issig()
+{
+       register struct proc *p;
+       register int sig;
+       long sigbits;
+       long sigmask;
+
+       p = u.u_procp;
+       for (;;) {
+               sigbits = p->p_sig;
+               if ((p->p_flag&STRC) == 0)
+                       sigbits &= ~p->p_ignsig;
+               if (p->p_flag&SVFORK)
+#define bit(a) (1<<(a-1))
+                       sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU));
+               if (sigbits == 0)
+                       break;
+               sig = ffs(sigbits);
+               sigmask = 1L << (sig-1);
+               p->p_sig &= ~sigmask;           /* take the signal! */
+               p->p_cursig = sig;
+               if (p->p_flag&STRC && (p->p_flag&SVFORK)==0) {
+                       /*
+                        * If traced, always stop, and stay
+                        * stopped until released by the parent.
+                        */
+                       do {
+                               stop(p);
+                               swtch();
+                       } while (!procxmt() && p->p_flag&STRC);
+                       /*
+                        * If parent wants us to take the signal,
+                        * then it will leave it in p->p_cursig;
+                        * otherwise we just look for signals again.
+                        */
+                       sig = p->p_cursig;
+                       if (sig == 0)
+                               continue;
+               }
+               switch (u.u_signal[sig]) {
+
+               case SIG_DFL:
+                       /*
+                        * Don't take default actions on system processes.
+                        */
+                       if (p <= &proc[2])
+                               break;
+                       switch (sig) {
+
+                       case SIGTSTP:
+                       case SIGTTIN:
+                       case SIGTTOU:
+                               /*
+                                * Children of init aren't allowed to stop
+                                * on signals from the keyboard.
+                                */
+                               if (p->p_pptr == &proc[1]) {
+                                       psignal(p, SIGKILL);
+                                       continue;
+                               }
+                               /* fall into ... */
+
+                       case SIGSTOP:
+                               if (p->p_flag&STRC)
+                                       continue;
+                               stop(p);
+                               swtch();
+                               continue;
+
+                       case SIGTINT:
+                       case SIGCONT:
+                       case SIGCHLD:
+                               /*
+                                * These signals are normally not
+                                * sent if the action is the default.
+                                * This can happen only if you reset the
+                                * signal action from an action which was
+                                * not deferred to SIG_DFL before the
+                                * system gets a chance to post the signal.
+                                */
+                               continue;               /* == ignore */
+
+                       default:
+                               goto send;
+                       }
+                       /*NOTREACHED*/
+
+               case SIG_HOLD:
+               case SIG_IGN:
+                       /*
+                        * Masking above should prevent us
+                        * ever trying to take action on a held
+                        * or ignored signal, unless process is traced.
+                        */
+                       if ((p->p_flag&STRC) == 0)
+                               printf("issig\n");
+                       continue;
+
+               default:
+                       /*
+                        * This signal has an action, let
+                        * psig process it.
+                        */
+                       goto send;
+               }
+               /*NOTREACHED*/
+       }
+       /*
+        * Didn't find a signal to send.
+        */
+       p->p_cursig = 0;
+       return (0);
+
+send:
+       /*
+        * Let psig process the signal.
+        */
+       return (sig);
+}
+
+ffs(mask)
+register long mask;
+{
+       register int i;
+
+       for(i=1; i<NSIG; i++) {
+               if(mask & 1)
+                       return(i);
+               mask >>= 1;
+       }
+       return(0);
+}
+
+/*
+ * Put the argument process into the stopped
+ * state and notify the parent via wakeup and/or signal.
+ */
+stop(p)
+       register struct proc *p;
+{
+
+       p->p_stat = SSTOP;
+       p->p_flag &= ~SWTED;
+       wakeup((caddr_t)p->p_pptr);
+       /*
+        * Avoid sending signal to parent if process is traced
+        */
+       if (p->p_flag&STRC)
+               return;
+       psignal(p->p_pptr, SIGCHLD);
+}
+
+/*
+ * Perform the action specified by
+ * the current signal.
+ * The usual sequence is:
+ *     if(issig())
+ *             psig();
+ * The signal bit has already been cleared by issig,
+ * and the current signal number stored in p->p_cursig.
+ */
+psig()
+{
+       register struct proc *rp = u.u_procp;
+       register int n = rp->p_cursig;
+       long sigmask = 1L << (n-1);
+       register int (*action)();
+
+       if (rp->p_cursig == 0)
+               panic("psig");
+       action = u.u_signal[n];
+       if (action != SIG_DFL) {
+               if (action == SIG_IGN || action == SIG_HOLD)
+                       panic("psig action");
+               u.u_error = 0;
+               if(n != SIGILL && n != SIGTRAP)
+                       u.u_signal[n] = 0;
+               /*
+                * If this catch value indicates automatic holding of
+                * subsequent signals, set the hold value.
+                */
+               if (SIGISDEFER(action)) {
+                       (void) spl6();
+                       if ((int)SIG_HOLD & 1)
+                               rp->p_siga0 |= sigmask;
+                       else
+                               rp->p_siga0 &= ~sigmask;
+                       if ((int)SIG_HOLD & 2)
+                               rp->p_siga1 |= sigmask;
+                       else
+                               rp->p_siga1 &= ~sigmask;
+                       u.u_signal[n] = SIG_HOLD;
+                       (void) spl0();
+                       action = SIGUNDEFER(action);
+               }
+               sendsig(action, n);
+               rp->p_cursig = 0;
+               return;
+       }
+       switch (n) {
+
+       case SIGILL:
+       case SIGIOT:
+       case SIGBUS:
+       case SIGQUIT:
+       case SIGTRAP:
+       case SIGEMT:
+       case SIGFPE:
+       case SIGSEGV:
+       case SIGSYS:
+               u.u_arg[0] = n;
+               if(core())
+                       n += 0200;
+       }
+       exit(n);
+}
+
+/*
+ * Create a core image on the file "core"
+ * If you are looking for protection glitches,
+ * there are probably a wealth of them here
+ * when this occurs to a suid command.
+ *
+ * It writes UPAGES block of the
+ * user.h area followed by the entire
+ * data+stack segments.
+ */
+
+core()
+{
+       register struct inode *ip;
+       extern schar();
+
+/*
+       if (coresw)
+               panic("core");
+*/
+       if (coresw) {
+               int i;
+               for (i = 0; i < 10; i++)
+                       if (u.u_comm[i])
+                               putchar(u.u_comm[i], 0);
+               printf(", uid %d\n", u.u_uid);
+               if (coresw&2)
+                       asm("halt");
+       }
+       if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= u.u_limit[LIM_CORE])
+               return (0);
+       u.u_error = 0;
+       u.u_dirp = "core";
+       ip = namei(schar, 1);
+       if(ip == NULL) {
+               if(u.u_error)
+                       return(0);
+               ip = maknode(0666);
+               if (ip==NULL)
+                       return(0);
+       }
+       if(!access(ip, IWRITE) &&
+          (ip->i_mode&IFMT) == IFREG && ip->i_vfdcnt == 0 &&
+#ifdef UCB
+          u.u_uid == u.u_ruid && ip->i_nlink == 1) {
+#else
+          u.u_uid == u.u_ruid) {
+#endif
+               itrunc(ip);
+               u.u_offset = 0;
+               u.u_base = (caddr_t)&u;
+               u.u_count = ctob(UPAGES);
+               u.u_segflg = 1;
+               writei(ip);
+               u.u_base = (char *)ctob(u.u_tsize);
+               u.u_count = ctob(u.u_dsize);
+               u.u_segflg = 0;
+               writei(ip);
+               u.u_base = (char *)(USRSTACK - ctob(u.u_ssize));
+               u.u_count = ctob(u.u_ssize);
+               writei(ip);
+       } else
+               u.u_error = EFAULT;
+       iput(ip);
+       return(u.u_error==0);
+}
+
+/*
+ * grow the stack to include the SP
+ * true return if successful.
+ */
+grow(sp)
+unsigned sp;
+{
+       register si;
+
+       if(sp >= USRSTACK-ctob(u.u_ssize))
+               return(0);
+       si = clrnd(btoc((USRSTACK-sp)) - u.u_ssize + SINCR);
+       if (ctob(u.u_ssize+si) > u.u_limit[LIM_STACK])
+               return(0);
+       if (chksize(u.u_tsize, u.u_dsize, u.u_ssize+si))
+               return(0);
+       if (swpexpand(u.u_dsize, u.u_ssize+si, &u.u_dmap, &u.u_smap)==0)
+               return(0);
+       
+       expand(si, P1BR);
+       return(1);
+}
+
+/*
+ * sys-trace system call.
+ */
+ptrace()
+{
+       register struct proc *p;
+       register struct a {
+               int     req;
+               int     pid;
+               int     *addr;
+               int     data;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       if (uap->req <= 0) {
+               u.u_procp->p_flag |= STRC;
+               return;
+       }
+       p = pfind(uap->pid);
+       if (p == 0 || p->p_stat != SSTOP || p->p_ppid != u.u_procp->p_pid) {
+               u.u_error = ESRCH;
+               return;
+       }
+       while (ipc.ip_lock)
+               sleep((caddr_t)&ipc, IPCPRI);
+       ipc.ip_lock = p->p_pid;
+       ipc.ip_data = uap->data;
+       ipc.ip_addr = uap->addr;
+       ipc.ip_req = uap->req;
+       p->p_flag &= ~SWTED;
+       while (ipc.ip_req > 0) {
+               if (p->p_stat==SSTOP)
+                       setrun(p);
+               sleep((caddr_t)&ipc, IPCPRI);
+       }
+       u.u_r.r_val1 = ipc.ip_data;
+       if (ipc.ip_req < 0)
+               u.u_error = EIO;
+       ipc.ip_lock = 0;
+       wakeup((caddr_t)&ipc);
+}
+
+int ipcreg[] = {R0, R1, R2, R3, R4, R5, R6, R7, R8, R9, R10, R11, AP, FP, SP, PC};
+/*
+ * Code that the child process
+ * executes to implement the command
+ * of the parent process in tracing.
+ */
+procxmt()
+{
+       register int i;
+       register *p;
+       register struct text *xp;
+
+       if (ipc.ip_lock != u.u_procp->p_pid)
+               return(0);
+       u.u_procp->p_slptime = 0;
+       i = ipc.ip_req;
+       ipc.ip_req = 0;
+       switch (i) {
+
+       /* read user I */
+       case 1:
+               if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
+                       goto error;
+               ipc.ip_data = fuiword((caddr_t)ipc.ip_addr);
+               break;
+
+       /* read user D */
+       case 2:
+               if (!useracc((caddr_t)ipc.ip_addr, 4, B_READ))
+                       goto error;
+               ipc.ip_data = fuword((caddr_t)ipc.ip_addr);
+               break;
+
+       /* read u */
+       case 3:
+               i = (int)ipc.ip_addr;
+               if (i<0 || i >= ctob(UPAGES))
+                       goto error;
+               ipc.ip_data = ((physadr)&u)->r[i>>2];
+               break;
+
+       /* write user I */
+       /* Must set up to allow writing */
+       case 4:
+               /*
+                * If text, must assure exclusive use
+                */
+               if (xp = u.u_procp->p_textp) {
+                       if (xp->x_count!=1 || xp->x_iptr->i_mode&ISVTX)
+                               goto error;
+                       xp->x_iptr->i_flag &= ~ITEXT;
+               }
+               i = -1;
+               if (chgprot((caddr_t)ipc.ip_addr, RW) &&
+                   chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RW))
+                       i = suiword((caddr_t)ipc.ip_addr, ipc.ip_data);
+               (void) chgprot((caddr_t)ipc.ip_addr, RO);
+               (void) chgprot((caddr_t)ipc.ip_addr+(sizeof(int)-1), RO);
+               if (i < 0)
+                       goto error;
+               if (xp)
+                       xp->x_flag |= XWRIT;
+               break;
+
+       /* write user D */
+       case 5:
+               if (suword((caddr_t)ipc.ip_addr, 0) < 0)
+                       goto error;
+               (void) suword((caddr_t)ipc.ip_addr, ipc.ip_data);
+               break;
+
+       /* write u */
+       case 6:
+               i = (int)ipc.ip_addr;
+               p = (int *)&((physadr)&u)->r[i>>2];
+               for (i=0; i<16; i++)
+                       if (p == &u.u_ar0[ipcreg[i]])
+                               goto ok;
+               if (p == &u.u_ar0[PS]) {
+                       ipc.ip_data |= PSL_CURMOD|PSL_PRVMOD;
+                       ipc.ip_data &=  ~PSL_USERCLR;
+                       goto ok;
+               }
+               goto error;
+
+       ok:
+               *p = ipc.ip_data;
+               break;
+
+       /* set signal and continue */
+       /* one version causes a trace-trap */
+       case 9:
+       case 7:
+               if ((int)ipc.ip_addr != 1)
+                       u.u_ar0[PC] = (int)ipc.ip_addr;
+               if ((unsigned)ipc.ip_data > NSIG)
+                       goto error;
+               u.u_procp->p_cursig = ipc.ip_data;      /* see issig */
+               if (i == 9)
+                       u.u_ar0[PS] |= PSL_T;
+               wakeup((caddr_t)&ipc);
+               return (1);
+
+       /* force exit */
+       case 8:
+               wakeup((caddr_t)&ipc);
+               exit(u.u_procp->p_cursig);
+
+       default:
+       error:
+               ipc.ip_req = -1;
+       }
+       wakeup((caddr_t)&ipc);
+       return(0);
+}
diff --git a/usr/src/sys/sys/sys1.c b/usr/src/sys/sys/sys1.c
new file mode 100644 (file)
index 0000000..3949f50
--- /dev/null
@@ -0,0 +1,670 @@
+/*     sys1.c  4.2     11/9/80 */
+
+#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 "/usr/include/wait.h"
+#include "../h/pte.h"
+#include "../h/vm.h"
+#include "../h/text.h"
+#include "../h/psl.h"
+#include "../h/vlimit.h"
+#include "../h/file.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(argmap, 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) {
+                               if (bp)
+                                       brelse(bp);
+                               bp = 0;
+                               goto badarg;
+                       }
+                       if ((nc&BMASK) == 0) {
+                               if (bp)
+                                       bdwrite(bp);
+                               bp = getblk(argdev,
+                                   (daddr_t)(dbtofsb(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);
+       getxfile(ip, nc + (na+4)*NBPW);
+       if (u.u_error) {
+badarg:
+               for (c = 0; c < nc; c += BSIZE)
+                       if (bp = baddr(argdev, dbtofsb(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(argdev,
+                                   (daddr_t)(dbtofsb(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(argmap, ctod(clrnd((int) btoc(NCARGS))), bno);
+       iput(ip);
+}
+
+/*
+ * Read in and set up memory for executed file.
+ */
+getxfile(ip, nargc)
+register struct inode *ip;
+{
+       register size_t ts, ds, ss;
+       int pagi = 0;
+
+       /*
+        * read in first few bytes
+        * of file for segment
+        * sizes:
+        * ux_mag = 407/410/413
+        *  407 is plain executable
+        *  410 is RO text
+        *  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;
+       }
+       switch (u.u_exdata.ux_mag) {
+
+       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;
+
+       default:
+               u.u_error = ENOEXEC;
+               goto bad;
+       }
+       if(u.u_exdata.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
+               register struct file *fp;
+
+               for (fp = file; fp < &file[NFILE]; fp++)
+                       if (fp->f_inode == ip && (fp->f_flag&FWRITE)) {
+                               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 (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|SNUSIG);
+       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, 0);
+
+       /*
+        * 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, SIGTRAP);
+       u.u_tsize = ts;
+       u.u_dsize = ds;
+       u.u_ssize = ss;
+bad:
+       return;
+}
+
+/*
+ * Clear registers on exec
+ */
+setregs()
+{
+       register int (**rp)();
+       register i;
+       long sigmask;
+
+       for(rp = &u.u_signal[0], sigmask = 1L; rp < &u.u_signal[NSIG];
+           sigmask <<= 1, rp++) {
+               switch (*rp) {
+
+               case SIG_IGN:
+               case SIG_DFL:
+               case SIG_HOLD:
+                       continue;
+
+               default:
+                       /*
+                        * Normal or deferring catch; revert to default.
+                        */
+                       (void) spl6();
+                       *rp = SIG_DFL;
+                       if ((int)*rp & 1)
+                               u.u_procp->p_siga0 |= sigmask;
+                       else
+                               u.u_procp->p_siga1 &= ~sigmask;
+                       if ((int)*rp & 2)
+                               u.u_procp->p_siga1 |= sigmask;
+                       else
+                               u.u_procp->p_siga1 &= ~sigmask;
+                       (void) spl0();
+                       continue;
+               }
+       }
+/*
+       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; i<NOFILE; i++) {
+               if (u.u_pofile[i]&EXCLOSE) {
+                       closef(u.u_ofile[i]);
+                       u.u_ofile[i] = NULL;
+                       u.u_pofile[i] &= ~EXCLOSE;
+               }
+       }
+       /*
+        * Remember file name for accounting.
+        */
+       u.u_acflag &= ~AFORK;
+       bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ);
+}
+
+/*
+ * exit system call:
+ * pass back caller's arg
+ */
+rexit()
+{
+       register struct a {
+               int     rval;
+       } *uap;
+
+       uap = (struct a *)u.u_ap;
+       exit((uap->rval & 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;
+       (void) spl6();
+       if ((int)SIG_IGN & 1)
+               p->p_siga0 = ~0;
+       else
+               p->p_siga0 = 0;
+       if ((int)SIG_IGN & 2)
+               p->p_siga1 = ~0;
+       else
+               p->p_siga1 = 0;
+       (void) spl0();
+       p->p_cpticks = 0;
+       p->p_pctcpu = 0;
+       for(i=0; i<NSIG; i++)
+               u.u_signal[i] = SIG_IGN;
+       /*
+        * Release virtual memory.  If we resulted from
+        * a vfork(), instead give the resources back to
+        * the parent.
+        */
+       if ((p->p_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; i<NOFILE; i++) {
+               f = u.u_ofile[i];
+               u.u_ofile[i] = NULL;
+               closef(f);
+       }
+       plock(u.u_cdir);
+       iput(u.u_cdir);
+       if (u.u_rdir) {
+               plock(u.u_rdir);
+               iput(u.u_rdir);
+       }
+       u.u_limit[LIM_FSIZE] = INFINITY;
+       acct();
+       vrelpt(u.u_procp);
+       vrelu(u.u_procp, 0);
+       multprog--;
+/*     spl7();                 /* clock will get mad because of overlaying */
+       p->p_stat = SZOMB;
+       noproc = 1;
+       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");
+       }
+       if (p->p_pid == 1)
+               panic("init died");
+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_pptr == p) {
+                       q->p_pptr = &proc[1];
+                       q->p_ppid = 1;
+                       wakeup((caddr_t)&proc[1]);
+                       /*
+                        * Traced processes are killed
+                        * since their existence means someone is screwing up.
+                        * Stopped processes are sent a hangup and a continue.
+                        * This is designed to be ``safe'' for setuid
+                        * processes since they must be willing to tolerate
+                        * hangups anyways.
+                        */
+                       if (q->p_flag&STRC) {
+                               q->p_flag &= ~STRC;
+                               psignal(q, SIGKILL);
+                       } else if (q->p_stat == SSTOP) {
+                               psignal(q, SIGHUP);
+                               psignal(q, SIGCONT);
+                       }
+                       /*
+                        * Protect this process from future
+                        * tty signals, clear TSTP/TTIN/TTOU if pending,
+                        * and set SDETACH bit on procs.
+                        */
+                       (void) spgrp(q, -1);
+               }
+       wakeup((caddr_t)p->p_pptr);
+       psignal(p->p_pptr, SIGCHLD);
+       swtch();
+}
+
+wait()
+{
+       struct vtimes vm;
+       struct vtimes *vp;
+
+       if ((u.u_ar0[PS] & PSL_ALLCC) != PSL_ALLCC) {
+               wait1(0, (struct vtimes *)0);
+               return;
+       }
+       vp = (struct vtimes *)u.u_ar0[R1];
+       wait1(u.u_ar0[R0], &vm);
+       if (u.u_error)
+               return;
+       (void) copyout((caddr_t)&vm, (caddr_t)vp, sizeof (struct vtimes));
+}
+
+/*
+ * 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(options, vp)
+       register options;
+       struct vtimes *vp;
+{
+       register f;
+       register struct proc *p;
+
+       f = 0;
+loop:
+       for(p = &proc[0]; p < &proc[NPROC]; p++)
+       if(p->p_pptr == u.u_procp) {
+               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_pptr = 0;
+                       p->p_sig = 0;
+                       p->p_siga0 = 0;
+                       p->p_siga1 = 0;
+                       p->p_pgrp = 0;
+                       p->p_flag = 0;
+                       p->p_wchan = 0;
+                       p->p_cursig = 0;
+                       return;
+               }
+               if (p->p_stat == SSTOP && (p->p_flag&SWTED)==0 &&
+                   (p->p_flag&STRC || options&WUNTRACED)) {
+                       p->p_flag |= SWTED;
+                       u.u_r.r_val1 = p->p_pid;
+                       u.u_r.r_val2 = (p->p_cursig<<8) | WSTOPPED;
+                       return;
+               }
+       }
+       if (f==0) {
+               u.u_error = ECHILD;
+               return;
+       }
+       if (options&WNOHANG) {
+               u.u_r.r_val1 = 0;
+               return;
+       }
+       if ((u.u_procp->p_flag&SNUSIG) && setjmp(u.u_qsav)) {
+               u.u_eosys = RESTARTSYS;
+               return;
+       }
+       sleep((caddr_t)u.u_procp, PWAIT);
+       goto loop;
+}
+
+/*
+ * 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 (ctob(u.u_dsize+d) > u.u_limit[LIM_DATA]) {
+               u.u_error = ENOMEM;
+               return;
+       }
+       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);
+}
diff --git a/usr/src/sys/sys/trap.c b/usr/src/sys/sys/trap.c
new file mode 100644 (file)
index 0000000..b393671
--- /dev/null
@@ -0,0 +1,225 @@
+/*     trap.c  4.2     11/9/80 */
+
+
+#include "../h/param.h"
+#include "../h/systm.h"
+#include "../h/dir.h"
+#include "../h/user.h"
+#include "../h/proc.h"
+#include "../h/reg.h"
+#include "../h/seg.h"
+#include "../h/trap.h"
+#include "../h/psl.h"
+#include "../h/pte.h"
+#include "../h/inline.h"
+
+#define        USER    040             /* user-mode flag added to type */
+
+struct sysent  sysent[128];
+
+/*
+ * Called from the trap handler when a processor trap occurs.
+ */
+/*ARGSUSED*/
+trap(sp, type, code, pc, psl)
+unsigned code;
+{
+       register int *locr0 = ((int *)&psl)-PS;
+       register int i;
+       register struct proc *p;
+       time_t syst;
+
+       syst = u.u_vm.vm_stime;
+       if (USERMODE(locr0[PS])) {
+               type |= USER;
+               u.u_ar0 = locr0;
+       }
+       switch (type) {
+
+       default:
+               printf("trap type %d, code = %x\n", type, code);
+               panic("trap");
+
+       case PROTFLT + USER:    /* protection fault */
+               i = SIGBUS;
+               break;
+
+       case PRIVINFLT + USER:  /* privileged instruction fault */
+       case RESADFLT + USER:   /* reserved addressing fault */
+       case RESOPFLT + USER:   /* resereved operand fault */
+               i = SIGILL;
+               break;
+
+       case RESCHED + USER:    /* Allow process switch */
+               goto out;
+
+       case ARITHTRAP + USER:
+               i = SIGFPE;
+               break;
+
+       /*
+        * If the user SP is above the stack segment,
+        * grow the stack automatically.
+        */
+       case SEGFLT + USER: /* segmentation exception */
+               if(grow((unsigned)locr0[SP]) || grow(code))
+                       goto out;
+               i = SIGSEGV;
+               break;
+
+       case TABLEFLT:          /* allow page table faults in kernel mode */
+       case TABLEFLT + USER:   /* page table fault */
+               panic("page table fault");
+
+       case PAGEFLT:           /* allow page faults in kernel mode */
+       case PAGEFLT + USER:    /* page fault */
+               i = u.u_error;
+               pagein(code);   /* bring in page containing virtual addr */
+               u.u_error = i;
+/*
+               if (type == PAGEFLT)
+*/
+                       return;
+/*
+               goto out;
+*/
+
+       case BPTFLT + USER:     /* bpt instruction fault */
+       case TRCTRAP + USER:    /* trace trap */
+               locr0[PS] &= ~PSL_T;    /* turn off trace bit */
+               i = SIGTRAP;
+               break;
+
+       case XFCFLT + USER:     /* xfc instruction fault */
+               i = SIGEMT;
+               break;
+
+       case COMPATFLT + USER:  /* compatibility mode fault */
+               u.u_cfcode = code;
+               i = SIGILL;
+               break;
+       }
+       psignal(u.u_procp, i);
+out:
+       p = u.u_procp;
+       if (p->p_cursig || ISSIG(p))
+               psig();
+       p->p_pri = p->p_usrpri;
+       if (runrun) {
+               /*
+                * Since we are u.u_procp, clock will normally just change
+                * our priority without moving us from one queue to another
+                * (since the running process is not on a queue.)
+                * If that happened after we setrq ourselves but before we
+                * swtch()'ed, we might not be on the queue indicated by
+                * our priority.
+                */
+               (void) spl6();
+               setrq(p);
+               swtch();
+       }
+       if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime))
+               addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst);
+       curpri = p->p_pri;
+}
+
+/*
+ * Called from the trap handler when a system call occurs
+ */
+/*ARGSUSED*/
+syscall(sp, type, code, pc, psl)
+unsigned code;
+{
+       register int *locr0 = ((int *)&psl)-PS;
+       register caddr_t params;                /* known to be r10 below */
+       register int i;                         /* known to be r9 below */
+       register struct sysent *callp;
+       register struct proc *p;
+       time_t syst;
+       int opc;
+
+       syst = u.u_vm.vm_stime;
+       if (!USERMODE(locr0[PS]))
+               panic("syscall");
+       u.u_ar0 = locr0;
+       params = (caddr_t)locr0[AP] + NBPW;
+       u.u_error = 0;
+       opc = pc - 2;
+       if (code > 63)
+               opc -= 2;
+       callp = &sysent[code&0177];
+       if (callp == sysent) {
+               i = fuword(params);
+               params += NBPW;
+               callp = &sysent[i&0177];
+       }
+       if (i = callp->sy_narg * sizeof (int)) {
+               asm("prober $3,r9,(r10)");              /* GROT */
+               asm("bnequ ok");                        /* GROT */
+               u.u_error = EFAULT;                     /* GROT */
+               goto bad;                               /* GROT */
+asm("ok:");                                            /* GROT */
+               asm("movc3 r9,(r10),_u+U_ARG");         /* GROT */
+       }
+       u.u_ap = u.u_arg;
+       u.u_dirp = (caddr_t)u.u_arg[0];
+       u.u_r.r_val1 = 0;
+       u.u_r.r_val2 = locr0[R1];
+       if (setjmp(u.u_qsav)) {
+               if (u.u_error == 0 && u.u_eosys == JUSTRETURN)
+                       u.u_error = EINTR;
+       } else {
+               u.u_eosys = JUSTRETURN;
+               (*(callp->sy_call))();
+       }
+       locr0[PS] &= ~PSL_C;
+       if (u.u_eosys == RESTARTSYS)
+               pc = opc;
+       else if (u.u_eosys == SIMULATERTI)
+               dorti();
+       else if (u.u_error) {
+bad:
+               locr0[R0] = u.u_error;
+               locr0[PS] |= PSL_C;     /* carry bit */
+       } else {
+               locr0[R0] = u.u_r.r_val1;
+               locr0[R1] = u.u_r.r_val2;
+       }
+       p = u.u_procp;
+       if (p->p_cursig || ISSIG(p))
+               psig();
+       p->p_pri = p->p_usrpri;
+       if (runrun) {
+               /*
+                * Since we are u.u_procp, clock will normally just change
+                * our priority without moving us from one queue to another
+                * (since the running process is not on a queue.)
+                * If that happened after we setrq ourselves but before we
+                * swtch()'ed, we might not be on the queue indicated by
+                * our priority.
+                */
+               (void) spl6();
+               setrq(p);
+               swtch();
+       }
+       if (u.u_prof.pr_scale && (syst -= u.u_vm.vm_stime))
+               addupc((caddr_t)locr0[PC], &u.u_prof, (int)-syst);
+       curpri = p->p_pri;
+}
+
+/*
+ * nonexistent system call-- set fatal error code.
+ */
+nosys()
+{
+
+       u.u_error = 100;
+}
+
+/*
+ * Ignored system call
+ */
+nullsys()
+{
+
+}