use new definition of ENDIAN
[unix-history] / usr / src / sys / kern / kern_exec.c
index 2a9bc56..d83ba16 100644 (file)
@@ -1,8 +1,15 @@
-/*     kern_exec.c     6.8     84/11/20        */
+/*
+ * Copyright (c) 1982, 1986 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ *
+ *     @(#)kern_exec.c 7.4 (Berkeley) %G%
+ */
 
 #include "../machine/reg.h"
 #include "../machine/pte.h"
 #include "../machine/psl.h"
 
 #include "../machine/reg.h"
 #include "../machine/pte.h"
 #include "../machine/psl.h"
+#include "../machine/mtpr.h"
 
 #include "param.h"
 #include "systm.h"
 
 #include "param.h"
 #include "systm.h"
 #include "acct.h"
 #include "exec.h"
 
 #include "acct.h"
 #include "exec.h"
 
-#ifdef vax
-#include "../vax/mtpr.h"
-#endif
-
 /*
  * exec system call, with and without environments.
  */
 /*
  * exec system call, with and without environments.
  */
@@ -46,20 +49,23 @@ execve()
        register char *cp;
        register struct buf *bp;
        register struct execa *uap;
        register char *cp;
        register struct buf *bp;
        register struct execa *uap;
-       int na, ne, ucp, ap, len, cc;
+       int na, ne, ucp, ap, cc;
+       unsigned len;
        int indir, uid, gid;
        char *sharg;
        struct inode *ip;
        swblk_t bno;
        char cfname[MAXCOMLEN + 1];
        int indir, uid, gid;
        char *sharg;
        struct inode *ip;
        swblk_t bno;
        char cfname[MAXCOMLEN + 1];
-#define        SHSIZE  32
-       char cfarg[SHSIZE];
+       char cfarg[MAXINTERP];
        union {
        union {
-               char    ex_shell[SHSIZE];       /* #! and name of interpreter */
+               char    ex_shell[MAXINTERP];    /* #! and interpreter name */
                struct  exec ex_exec;
        } exdata;
        register struct nameidata *ndp = &u.u_nd;
        int resid, error;
                struct  exec ex_exec;
        } exdata;
        register struct nameidata *ndp = &u.u_nd;
        int resid, error;
+#ifdef SECSIZE
+       extern long argdbsize;                  /* XXX */
+#endif SECSIZE
 
        ndp->ni_nameiop = LOOKUP | FOLLOW;
        ndp->ni_segflg = UIO_USERSPACE;
 
        ndp->ni_nameiop = LOOKUP | FOLLOW;
        ndp->ni_segflg = UIO_USERSPACE;
@@ -103,17 +109,17 @@ execve()
         */
        exdata.ex_shell[0] = '\0';      /* for zero length files */
        u.u_error = rdwri(UIO_READ, ip, (caddr_t)&exdata, sizeof (exdata),
         */
        exdata.ex_shell[0] = '\0';      /* for zero length files */
        u.u_error = rdwri(UIO_READ, ip, (caddr_t)&exdata, sizeof (exdata),
-           0, 1, &resid);
+           (off_t)0, 1, &resid);
        if (u.u_error)
                goto bad;
 #ifndef lint
        if (u.u_error)
                goto bad;
 #ifndef lint
-       if (resid > sizeof (exdata) - sizeof (exdata.ex_exec.a_magic) &&
+       if (resid > sizeof(exdata) - sizeof(exdata.ex_exec) &&
            exdata.ex_shell[0] != '#') {
                u.u_error = ENOEXEC;
                goto bad;
        }
 #endif
            exdata.ex_shell[0] != '#') {
                u.u_error = ENOEXEC;
                goto bad;
        }
 #endif
-       switch (exdata.ex_exec.a_magic) {
+       switch ((int)exdata.ex_exec.a_magic) {
 
        case 0407:
                exdata.ex_exec.a_data += exdata.ex_exec.a_text;
 
        case 0407:
                exdata.ex_exec.a_data += exdata.ex_exec.a_text;
@@ -136,7 +142,7 @@ execve()
                        goto bad;
                }
                cp = &exdata.ex_shell[2];               /* skip "#!" */
                        goto bad;
                }
                cp = &exdata.ex_shell[2];               /* skip "#!" */
-               while (cp < &exdata.ex_shell[SHSIZE]) {
+               while (cp < &exdata.ex_shell[MAXINTERP]) {
                        if (*cp == '\t')
                                *cp = ' ';
                        else if (*cp == '\n') {
                        if (*cp == '\t')
                                *cp = ' ';
                        else if (*cp == '\n') {
@@ -155,21 +161,14 @@ execve()
                ndp->ni_dirp = cp;
                while (*cp && *cp != ' ')
                        cp++;
                ndp->ni_dirp = cp;
                while (*cp && *cp != ' ')
                        cp++;
-               sharg = NULL;
+               cfarg[0] = '\0';
                if (*cp) {
                        *cp++ = '\0';
                        while (*cp == ' ')
                                cp++;
                if (*cp) {
                        *cp++ = '\0';
                        while (*cp == ' ')
                                cp++;
-                       if (*cp) {
-                               bcopy((caddr_t)cp, (caddr_t)cfarg, SHSIZE);
-                               sharg = cfarg;
-                       }
+                       if (*cp)
+                               bcopy((caddr_t)cp, (caddr_t)cfarg, MAXINTERP);
                }
                }
-               if (ndp->ni_dent.d_namlen > MAXCOMLEN)
-                       ndp->ni_dent.d_namlen = MAXCOMLEN;
-               bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
-                   (unsigned)(ndp->ni_dent.d_namlen + 1));
-               cfname[MAXCOMLEN] = '\0';
                indir = 1;
                iput(ip);
                ndp->ni_nameiop = LOOKUP | FOLLOW;
                indir = 1;
                iput(ip);
                ndp->ni_nameiop = LOOKUP | FOLLOW;
@@ -177,6 +176,9 @@ execve()
                ip = namei(ndp);
                if (ip == NULL)
                        return;
                ip = namei(ndp);
                if (ip == NULL)
                        return;
+               bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)cfname,
+                   MAXCOMLEN);
+               cfname[MAXCOMLEN] = '\0';
                goto again;
        }
 
                goto again;
        }
 
@@ -188,9 +190,13 @@ execve()
        nc = 0;
        cc = 0;
        uap = (struct execa *)u.u_ap;
        nc = 0;
        cc = 0;
        uap = (struct execa *)u.u_ap;
+#ifdef SECSIZE
+       bno = rmalloc(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize);
+#else SECSIZE
        bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
        bno = rmalloc(argmap, (long)ctod(clrnd((int)btoc(NCARGS))));
+#endif SECSIZE
        if (bno == 0) {
        if (bno == 0) {
-               swkill(u.u_procp, "exece");
+               swkill(u.u_procp, "exec: no swap space");
                goto bad;
        }
        if (bno % CLSIZE)
                goto bad;
        }
        if (bno % CLSIZE)
@@ -200,7 +206,15 @@ execve()
         */
        if (uap->argp) for (;;) {
                ap = NULL;
         */
        if (uap->argp) for (;;) {
                ap = NULL;
-               if (indir && (na == 1 || na == 2 && sharg))
+               sharg = NULL;
+               if (indir && na == 0) {
+                       sharg = cfname;
+                       ap = (int)sharg;
+                       uap->argp++;            /* ignore argv[0] */
+               } else if (indir && (na == 1 && cfarg[0])) {
+                       sharg = cfarg;
+                       ap = (int)sharg;
+               } else if (indir && (na == 1 || na == 2 && cfarg[0]))
                        ap = (int)uap->fname;
                else if (uap->argp) {
                        ap = fuword((caddr_t)uap->argp);
                        ap = (int)uap->fname;
                else if (uap->argp) {
                        ap = fuword((caddr_t)uap->argp);
@@ -215,14 +229,14 @@ execve()
                        break;
                na++;
                if (ap == -1) {
                        break;
                na++;
                if (ap == -1) {
-                       error = EFAULT;
+                       u.u_error = EFAULT;
                        break;
                }
                do {
                        if (cc <= 0) {
                                /*
                                 * We depend on NCARGS being a multiple of
                        break;
                }
                do {
                        if (cc <= 0) {
                                /*
                                 * We depend on NCARGS being a multiple of
-                                * CLSIZE*NBPG.  This way we need only check
+                                * CLBYTES.  This way we need only check
                                 * overflow before each buffer allocation.
                                 */
                                if (nc >= NCARGS-1) {
                                 * overflow before each buffer allocation.
                                 */
                                if (nc >= NCARGS-1) {
@@ -231,15 +245,23 @@ execve()
                                }
                                if (bp)
                                        bdwrite(bp);
                                }
                                if (bp)
                                        bdwrite(bp);
-                               cc = CLSIZE*NBPG;
+                               cc = CLBYTES;
+#ifdef SECSIZE
+                               bp = getblk(argdev, bno + nc / argdbsize, cc,
+                                   argdbsize);
+#else SECSIZE
                                bp = getblk(argdev, bno + ctod(nc/NBPG), cc);
                                bp = getblk(argdev, bno + ctod(nc/NBPG), cc);
+#endif SECSIZE
                                cp = bp->b_un.b_addr;
                        }
                                cp = bp->b_un.b_addr;
                        }
-                       if (indir && na == 2 && sharg != NULL)
-                               error = copystr(sharg, cp, cc, &len);
-                       else
-                               error = copyinstr((caddr_t)ap, cp, cc, &len);
-                       ap += len;
+                       if (sharg) {
+                               error = copystr(sharg, cp, (unsigned)cc, &len);
+                               sharg += len;
+                       } else {
+                               error = copyinstr((caddr_t)ap, cp, (unsigned)cc,
+                                   &len);
+                               ap += len;
+                       }
                        cp += len;
                        nc += len;
                        cc -= len;
                        cp += len;
                        nc += len;
                        cc -= len;
@@ -256,16 +278,16 @@ execve()
                bdwrite(bp);
        bp = 0;
        nc = (nc + NBPW-1) & ~(NBPW-1);
                bdwrite(bp);
        bp = 0;
        nc = (nc + NBPW-1) & ~(NBPW-1);
-       if (indir) {
-               ndp->ni_dent.d_namlen = strlen(cfname);
-               bcopy((caddr_t)cfname, (caddr_t)ndp->ni_dent.d_name,
-                   (unsigned)(ndp->ni_dent.d_namlen + 1));
-       }
        getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
        if (u.u_error) {
 badarg:
                for (cc = 0; cc < nc; cc += CLSIZE*NBPG) {
        getxfile(ip, &exdata.ex_exec, nc + (na+4)*NBPW, uid, gid);
        if (u.u_error) {
 badarg:
                for (cc = 0; cc < nc; cc += CLSIZE*NBPG) {
+#ifdef SECSIZE
+                       bp = baddr(argdev, bno + cc / argdbsize, CLSIZE*NBPG,
+                           argdbsize);
+#else SECSIZE
                        bp = baddr(argdev, bno + ctod(cc/NBPG), CLSIZE*NBPG);
                        bp = baddr(argdev, bno + ctod(cc/NBPG), CLSIZE*NBPG);
+#endif SECSIZE
                        if (bp) {
                                bp->b_flags |= B_AGE;           /* throw away */
                                bp->b_flags &= ~B_DELWRI;       /* cancel io */
                        if (bp) {
                                bp->b_flags |= B_AGE;           /* throw away */
                                bp->b_flags &= ~B_DELWRI;       /* cancel io */
@@ -275,6 +297,8 @@ badarg:
                }
                goto bad;
        }
                }
                goto bad;
        }
+       iput(ip);
+       ip = NULL;
 
        /*
         * Copy back arglist.
 
        /*
         * Copy back arglist.
@@ -298,13 +322,19 @@ badarg:
                        if (cc <= 0) {
                                if (bp)
                                        brelse(bp);
                        if (cc <= 0) {
                                if (bp)
                                        brelse(bp);
-                               cc = CLSIZE*NBPG;
+                               cc = CLBYTES;
+#ifdef SECSIZE
+                               bp = bread(argdev, bno + nc / argdbsize, cc,
+                                   argdbsize);
+#else SECSIZE
                                bp = bread(argdev, bno + ctod(nc / NBPG), cc);
                                bp = bread(argdev, bno + ctod(nc / NBPG), cc);
+#endif SECSIZE
                                bp->b_flags |= B_AGE;           /* throw away */
                                bp->b_flags &= ~B_DELWRI;       /* cancel io */
                                cp = bp->b_un.b_addr;
                        }
                                bp->b_flags |= B_AGE;           /* throw away */
                                bp->b_flags &= ~B_DELWRI;       /* cancel io */
                                cp = bp->b_un.b_addr;
                        }
-                       error = copyoutstr(cp, (caddr_t)ucp, cc, &len);
+                       error = copyoutstr(cp, (caddr_t)ucp, (unsigned)cc,
+                           &len);
                        ucp += len;
                        cp += len;
                        nc += len;
                        ucp += len;
                        cp += len;
                        nc += len;
@@ -314,19 +344,59 @@ badarg:
                        panic("exec: EFAULT");
        }
        (void) suword((caddr_t)ap, 0);
                        panic("exec: EFAULT");
        }
        (void) suword((caddr_t)ap, 0);
+
+       /*
+        * Reset caught signals.  Held signals
+        * remain held through p_sigmask.
+        */
+       while (u.u_procp->p_sigcatch) {
+               nc = ffs((long)u.u_procp->p_sigcatch);
+               u.u_procp->p_sigcatch &= ~sigmask(nc);
+               u.u_signal[nc] = SIG_DFL;
+       }
+       /*
+        * Reset stack state to the user stack.
+        * Clear set of signals caught on the signal stack.
+        */
+       u.u_onstack = 0;
+       u.u_sigsp = 0;
+       u.u_sigonstack = 0;
+
+       for (nc = u.u_lastfile; nc >= 0; --nc) {
+               if (u.u_pofile[nc] & UF_EXCLOSE) {
+                       closef(u.u_ofile[nc]);
+                       u.u_ofile[nc] = NULL;
+                       u.u_pofile[nc] = 0;
+               }
+               u.u_pofile[nc] &= ~UF_MAPPED;
+       }
+       while (u.u_lastfile >= 0 && u.u_ofile[u.u_lastfile] == NULL)
+               u.u_lastfile--;
        setregs(exdata.ex_exec.a_entry);
        /*
         * Remember file name for accounting.
         */
        u.u_acflag &= ~AFORK;
        setregs(exdata.ex_exec.a_entry);
        /*
         * Remember file name for accounting.
         */
        u.u_acflag &= ~AFORK;
-       bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm,
-           (unsigned)(ndp->ni_dent.d_namlen + 1));
+       if (indir)
+               bcopy((caddr_t)cfname, (caddr_t)u.u_comm, MAXCOMLEN);
+       else {
+               if (ndp->ni_dent.d_namlen > MAXCOMLEN)
+                       ndp->ni_dent.d_namlen = MAXCOMLEN;
+               bcopy((caddr_t)ndp->ni_dent.d_name, (caddr_t)u.u_comm,
+                   (unsigned)(ndp->ni_dent.d_namlen + 1));
+       }
 bad:
        if (bp)
                brelse(bp);
        if (bno)
 bad:
        if (bp)
                brelse(bp);
        if (bno)
+#ifdef SECSIZE
+               rmfree(argmap, (clrnd((int)btoc(NCARGS))) * CLBYTES / argdbsize,
+                   bno);
+#else SECSIZE
                rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
                rmfree(argmap, (long)ctod(clrnd((int) btoc(NCARGS))), bno);
-       iput(ip);
+#endif SECSIZE
+       if (ip)
+               iput(ip);
 }
 
 /*
 }
 
 /*
@@ -337,14 +407,14 @@ getxfile(ip, ep, nargc, uid, gid)
        register struct exec *ep;
        int nargc, uid, gid;
 {
        register struct exec *ep;
        int nargc, uid, gid;
 {
-       register size_t ts, ds, ss;
+       size_t ts, ds, ids, uds, ss;
        int pagi;
 
        if (ep->a_magic == 0413)
                pagi = SPAGI;
        else
                pagi = 0;
        int pagi;
 
        if (ep->a_magic == 0413)
                pagi = SPAGI;
        else
                pagi = 0;
-       if (ip->i_flag & IXMOD) {                       /* XXX */
+       if (ip->i_text && (ip->i_text->x_flag & XTRC)) {
                u.u_error = ETXTBSY;
                goto bad;
        }
                u.u_error = ETXTBSY;
                goto bad;
        }
@@ -365,11 +435,15 @@ getxfile(ip, ep, nargc, uid, gid)
 
        /*
         * Compute text and data sizes and make sure not too large.
 
        /*
         * Compute text and data sizes and make sure not too large.
+        * NB - Check data and bss separately as they may overflow 
+        * when summed together.
         */
        ts = clrnd(btoc(ep->a_text));
         */
        ts = clrnd(btoc(ep->a_text));
+       ids = clrnd(btoc(ep->a_data));
+       uds = clrnd(btoc(ep->a_bss));
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
        ss = clrnd(SSIZE + btoc(nargc));
        ds = clrnd(btoc(ep->a_data + ep->a_bss));
        ss = clrnd(SSIZE + btoc(nargc));
-       if (chksize((unsigned)ts, (unsigned)ds, (unsigned)ss))
+       if (chksize((unsigned)ts, (unsigned)ids, (unsigned)uds, (unsigned)ss))
                goto bad;
 
        /*
                goto bad;
 
        /*
@@ -409,21 +483,34 @@ getxfile(ip, ep, nargc, uid, gid)
                    rdwri(UIO_READ, ip,
                        (char *)ctob(dptov(u.u_procp, 0)),
                        (int)ep->a_data,
                    rdwri(UIO_READ, ip,
                        (char *)ctob(dptov(u.u_procp, 0)),
                        (int)ep->a_data,
-                       (int)(sizeof (struct exec) + ep->a_text),
+                       (off_t)(sizeof (struct exec) + ep->a_text),
                        0, (int *)0);
        xalloc(ip, ep, pagi);
                        0, (int *)0);
        xalloc(ip, ep, pagi);
+#if defined(tahoe)
+       /*
+        * Define new keys.
+        */
+       if (u.u_procp->p_textp == 0) {  /* use existing code key if shared */
+               ckeyrelease(u.u_procp->p_ckey);
+               u.u_procp->p_ckey = getcodekey();
+       }
+       mtpr(CCK, u.u_procp->p_ckey);
+       dkeyrelease(u.u_procp->p_dkey);
+       u.u_procp->p_dkey = getdatakey();
+       mtpr(DCK, u.u_procp->p_dkey);
+#endif
        if (pagi && u.u_procp->p_textp)
                vinifod((struct fpte *)dptopte(u.u_procp, 0),
                    PG_FTEXT, u.u_procp->p_textp->x_iptr,
        if (pagi && u.u_procp->p_textp)
                vinifod((struct fpte *)dptopte(u.u_procp, 0),
                    PG_FTEXT, u.u_procp->p_textp->x_iptr,
-                   (long)(1 + ts/CLSIZE), (int)btoc(ep->a_data));
+                   (long)(1 + ts/CLSIZE), (size_t)btoc(ep->a_data));
 
 
-#ifdef vax
+#if defined(vax) || defined(tahoe)
        /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
        mtpr(TBIA, 0);
 #endif
 
        if (u.u_error)
        /* THIS SHOULD BE DONE AT A LOWER LEVEL, IF AT ALL */
        mtpr(TBIA, 0);
 #endif
 
        if (u.u_error)
-               swkill(u.u_procp, "i/o error mapping pages");
+               swkill(u.u_procp, "exec: I/O error mapping pages");
        /*
         * set SUID/SGID protections, if no tracing
         */
        /*
         * set SUID/SGID protections, if no tracing
         */
@@ -437,42 +524,9 @@ getxfile(ip, ep, nargc, uid, gid)
        u.u_dsize = ds;
        u.u_ssize = ss;
        u.u_prof.pr_scale = 0;
        u.u_dsize = ds;
        u.u_ssize = ss;
        u.u_prof.pr_scale = 0;
+#if defined(tahoe)
+       u.u_pcb.pcb_savacc.faddr = (float *)NULL;
+#endif
 bad:
        return;
 }
 bad:
        return;
 }
-
-/*
- * Clear registers on exec
- */
-setregs(entry)
-       u_long entry;
-{
-       register int i;
-       register struct proc *p = u.u_procp;
-
-       /*
-        * Reset caught signals.  Held signals
-        * remain held through p_sigmask.
-        */
-       while (p->p_sigcatch) {
-               (void) spl6();
-               i = ffs(p->p_sigcatch);
-               p->p_sigcatch &= ~(1 << (i - 1));
-               u.u_signal[i] = SIG_DFL;
-               (void) spl0();
-       }
-#ifdef notdef
-       /* should pass args to init on the stack */
-       for (rp = &u.u_ar0[0]; rp < &u.u_ar0[16];)
-               *rp++ = 0;
-#endif
-       u.u_ar0[PC] = entry + 2;
-       for (i=0; i<NOFILE; i++) {
-               if (u.u_pofile[i]&UF_EXCLOSE) {
-                       closef(u.u_ofile[i]);
-                       u.u_ofile[i] = NULL;
-                       u.u_pofile[i] = 0;
-               }
-               u.u_pofile[i] &= ~UF_MAPPED;
-       }
-}