Annotation of 41BSD/sys/newsys/sys1.c, revision 1.1.1.1

1.1       root        1: From uucp Thu Jan 10 01:37:58 1980
                      2: >From dmr Thu Jan 10 04:25:49 1980 remote from research
                      3: The system has been changed so that if a file being executed
                      4: begins with the magic characters #! , the rest of the line is understood
                      5: to be the name of an interpreter for the executed file.
                      6: Previously (and in fact still) the shell did much of this job;
                      7: it automatically executed itself on a text file with executable mode
                      8: when the text file's name was typed as a command.
                      9: Putting the facility into the system gives the following
                     10: benefits.
                     11: 
                     12: 1) It makes shell scripts more like real executable files,
                     13: because they can be the subject of 'exec.'
                     14: 
                     15: 2) If you do a 'ps' while such a command is running, its real
                     16: name appears instead of 'sh'.
                     17: Likewise, accounting is done on the basis of the real name.
                     18: 
                     19: 3) Shell scripts can be set-user-ID.
                     20: 
                     21: 4) It is simpler to have alternate shells available;
                     22: e.g. if you like the Berkeley csh there is no question about
                     23: which shell is to interpret a file.
                     24: 
                     25: 5) It will allow other interpreters to fit in more smoothly.
                     26: 
                     27: To take advantage of this wonderful opportunity,
                     28: put
                     29: 
                     30:        #! /bin/sh
                     31: 
                     32: at the left margin of the first line of your shell scripts.
                     33: Blanks after ! are OK.  Use a complete pathname (no search is done).
                     34: At the moment the whole line is restricted to 16 characters but
                     35: this limit will be raised.
                     36: 
                     37: 
                     38: From uucp Thu Jan 10 01:37:49 1980
                     39: >From dmr Thu Jan 10 04:23:53 1980 remote from research
                     40: #include "../h/param.h"
                     41: #include "../h/systm.h"
                     42: #include "../h/map.h"
                     43: #include "../h/dir.h"
                     44: #include "../h/user.h"
                     45: #include "../h/proc.h"
                     46: #include "../h/buf.h"
                     47: #include "../h/reg.h"
                     48: #include "../h/inode.h"
                     49: #include "../h/seg.h"
                     50: #include "../h/acct.h"
                     51: 
                     52: 
                     53: /*
                     54:  * exec system call, with and without environments.
                     55:  */
                     56: struct execa {
                     57:        char    *fname;
                     58:        char    **argp;
                     59:        char    **envp;
                     60: };
                     61: 
                     62: exec()
                     63: {
                     64:        ((struct execa *)u.u_ap)->envp = NULL;
                     65:        exece();
                     66: }
                     67: 
                     68: exece()
                     69: {
                     70:        register nc;
                     71:        register char *cp;
                     72:        register struct buf *bp;
                     73:        register struct execa *uap;
                     74:        int na, ne, bno, ucp, ap, c, indir, uid, gid;
                     75:        struct inode *ip;
                     76: 
                     77:        bno = 0;
                     78:        bp = 0;
                     79:        indir = 0;
                     80:        if ((ip = namei(uchar, 0)) == NULL)
                     81:                return;
                     82:        uid = u.u_uid;
                     83:        gid = u.u_gid;
                     84:        if (ip->i_mode&ISUID)
                     85:                uid = ip->i_uid;
                     86:        if (ip->i_mode&ISGID)
                     87:                gid = ip->i_gid;
                     88: again:
                     89:        if(access(ip, IEXEC))
                     90:                goto bad;
                     91:        if((ip->i_mode & IFMT) != IFREG ||
                     92:           (ip->i_mode & (IEXEC|(IEXEC>>3)|(IEXEC>>6))) == 0) {
                     93:                u.u_error = EACCES;
                     94:                goto bad;
                     95:        }
                     96:        /*
                     97:         * read in first few bytes
                     98:         * of file for segment
                     99:         * types and sizes:
                    100:         * ux_mag = 407/410/411/405
                    101:         *  407 is plain executable
                    102:         *  410 is RO text
                    103:         *  411 is separated ID
                    104:         *  405 is overlaid text
                    105:         *
                    106:         * Also, an ascii line beginning
                    107:         * with '#!' is the file name of a shell.
                    108:         */
                    109:        u.u_base = (caddr_t)&u.u_exdata;
                    110:        u.u_count = sizeof(u.u_exdata);
                    111:        u.u_offset = 0;
                    112:        u.u_segflg = 1;
                    113:        readi(ip);
                    114:        u.u_segflg = 0;
                    115:        if(u.u_error)
                    116:                goto bad;
                    117:        if (u.u_count > sizeof(u.u_exdata) - sizeof(u.u_exdata.A)
                    118:          && u.u_exdata.S[0] != '#') {
                    119:                u.u_error = ENOEXEC;
                    120:                goto bad;
                    121:        }
                    122:        if(u.u_exdata.A.ux_mag == 0407)
                    123:                ;
                    124:        else if (u.u_exdata.A.ux_mag == 0411)
                    125:                ;
                    126:        else if (u.u_exdata.A.ux_mag == 0405)
                    127:                ;
                    128:        else if (u.u_exdata.A.ux_mag == 0410)
                    129:                ;
                    130:        else if (u.u_exdata.S[0]=='#' && u.u_exdata.S[1]=='!' && indir==0) {
                    131:                cp = &u.u_exdata.S[2];
                    132:                while (*cp==' ' && cp<&u.u_exdata.S[SHSIZ])
                    133:                        cp++;
                    134:                u.u_dirp = cp;
                    135:                while (cp < &u.u_exdata.S[SHSIZ-1]  && *cp != '\n')
                    136:                        cp++;
                    137:                *cp = '\0';
                    138:                indir++;
                    139:                iput(ip);
                    140:                ip = namei(schar, 0);
                    141:                if (ip==NULL)
                    142:                        return;
                    143:                goto again;
                    144:        } else {
                    145:                u.u_error = ENOEXEC;
                    146:                goto bad;
                    147:        }
                    148:        /*
                    149:         * Collect arguments on "file" in swap space.
                    150:         */
                    151:        na = 0;
                    152:        ne = 0;
                    153:        nc = 0;
                    154:        uap = (struct execa *)u.u_ap;
                    155:        while ((bno = malloc(argmap,(NCARGS+BSIZE-1)/BSIZE)) == 0)
                    156:                sleep((caddr_t)&argmap, PRIBIO);
                    157:        if (uap->argp) for (;;) {
                    158:                ap = NULL;
                    159:                if (indir && na==1)
                    160:                        ap = uap->fname;
                    161:                else if (uap->argp) {
                    162:                        ap = fuword((caddr_t)uap->argp);
                    163:                        uap->argp++;
                    164:                }
                    165:                if (ap==NULL && uap->envp) {
                    166:                        uap->argp = NULL;
                    167:                        if ((ap = fuword((caddr_t)uap->envp)) == NULL)
                    168:                                break;
                    169:                        uap->envp++;
                    170:                        ne++;
                    171:                }
                    172:                if (ap==NULL)
                    173:                        break;
                    174:                na++;
                    175:                if(ap == -1)
                    176:                        u.u_error = EFAULT;
                    177:                do {
                    178:                        if (nc >= NCARGS-1)
                    179:                                u.u_error = E2BIG;
                    180:                        if ((c = fubyte((caddr_t)ap++)) < 0)
                    181:                                u.u_error = EFAULT;
                    182:                        if (u.u_error)
                    183:                                goto bad;
                    184:                        if ((nc&BMASK) == 0) {
                    185:                                if (bp)
                    186:                                        bawrite(bp);
                    187:                                bp = getblk(swapdev, swplo+bno+(nc>>BSHIFT));
                    188:                                cp = bp->b_un.b_addr;
                    189:                        }
                    190:                        nc++;
                    191:                        *cp++ = c;
                    192:                } while (c>0);
                    193:        }
                    194:        if (bp)
                    195:                bawrite(bp);
                    196:        bp = 0;
                    197:        nc = (nc + NBPW-1) & ~(NBPW-1);
                    198:        getxfile(ip, nc, uid, gid);
                    199:        if (u.u_error || u.u_exdata.A.ux_mag==0405)
                    200:                goto bad;
                    201: 
                    202:        /*
                    203:         * copy back arglist
                    204:         */
                    205:        ucp = -nc - NBPW;
                    206:        ap = ucp - na*NBPW - 3*NBPW;
                    207:        u.u_ar0[R6] = ap;
                    208:        suword((caddr_t)ap, na-ne);
                    209:        nc = 0;
                    210:        for (;;) {
                    211:                ap += NBPW;
                    212:                if (na==ne) {
                    213:                        suword((caddr_t)ap, 0);
                    214:                        ap += NBPW;
                    215:                }
                    216:                if (--na < 0)
                    217:                        break;
                    218:                suword((caddr_t)ap, ucp);
                    219:                do {
                    220:                        if ((nc&BMASK) == 0) {
                    221:                                if (bp)
                    222:                                        brelse(bp);
                    223:                                bp = bread(swapdev, swplo+bno+(nc>>BSHIFT));
                    224:                                bp->b_flags &= ~B_DELWRI;
                    225:                                cp = bp->b_un.b_addr;
                    226:                                if (nc==0 && indir)
                    227:                                        bcopy(cp, (caddr_t)u.u_dbuf, DIRSIZ);
                    228:                        }
                    229:                        subyte((caddr_t)ucp++, (c = *cp++));
                    230:                        nc++;
                    231:                } while(c&0377);
                    232:        }
                    233:        suword((caddr_t)ap, 0);
                    234:        suword((caddr_t)ucp, 0);
                    235:        setregs();
                    236: bad:
                    237:        if (bp)
                    238:                brelse(bp);
                    239:        if(bno) {
                    240:                mfree(argmap, (NCARGS+BSIZE-1)/BSIZE, bno);
                    241:                wakeup((caddr_t)&argmap);
                    242:        }
                    243:        iput(ip);
                    244: }
                    245: 
                    246: /*
                    247:  * Read in and set up memory for executed file.
                    248:  */
                    249: getxfile(ip, nargc, uid, gid)
                    250: register struct inode *ip;
                    251: {
                    252:        register unsigned ds;
                    253:        register sep;
                    254:        register unsigned ts, ss;
                    255:        int i;
                    256:        long lsize;
                    257: 
                    258:        sep = 0;
                    259:        if(u.u_exdata.A.ux_mag == 0407) {
                    260:                lsize = (long)u.u_exdata.A.ux_dsize + u.u_exdata.A.ux_tsize;
                    261:                u.u_exdata.A.ux_dsize = lsize;
                    262:                if (lsize != u.u_exdata.A.ux_dsize) {   /* check overflow */
                    263:                        u.u_error = ENOMEM;
                    264:                        return;
                    265:                }
                    266:                u.u_exdata.A.ux_tsize = 0;
                    267:        } else if (u.u_exdata.A.ux_mag == 0411)
                    268:                sep++;
                    269:        if(u.u_exdata.A.ux_tsize!=0 && (ip->i_flag&ITEXT)==0 && ip->i_count!=1) {
                    270:                u.u_error = ETXTBSY;
                    271:                return;
                    272:        }
                    273: 
                    274:        /*
                    275:         * find text and data sizes
                    276:         * try them out for possible
                    277:         * overflow of max sizes
                    278:         */
                    279:        ts = btoc(u.u_exdata.A.ux_tsize);
                    280:        lsize = (long)u.u_exdata.A.ux_dsize + u.u_exdata.A.ux_bsize;
                    281:        if (lsize != (unsigned)lsize) {
                    282:                u.u_error = ENOMEM;
                    283:                return;
                    284:        }
                    285:        ds = btoc(lsize);
                    286:        ss = SSIZE + btoc(nargc);
                    287:        if (u.u_exdata.A.ux_mag==0405) {
                    288:                if (u.u_sep==0 && ctos(ts) != ctos(u.u_tsize) || nargc) {
                    289:                        u.u_error = ENOMEM;
                    290:                        return;
                    291:                }
                    292:                ds = u.u_dsize;
                    293:                ss = u.u_ssize;
                    294:                sep = u.u_sep;
                    295:                xfree();
                    296:                xalloc(ip);
                    297:                u.u_ar0[PC] = u.u_exdata.A.ux_entloc & ~01;
                    298:        } else {
                    299:                if(estabur(ts, ds, ss, sep, RO))
                    300:                        return;
                    301:        
                    302:                /*
                    303:                 * allocate and clear core
                    304:                 * at this point, committed
                    305:                 * to the new image
                    306:                 */
                    307:                u.u_prof.pr_scale = 0;
                    308:                xfree();
                    309:                i = USIZE+ds+ss;
                    310:                expand(i);
                    311:                while(--i >= USIZE)
                    312:                        clearseg(u.u_procp->p_addr+i);
                    313:                xalloc(ip);
                    314:        
                    315:                /*
                    316:                 * read in data segment
                    317:                 */
                    318:                estabur((unsigned)0, ds, (unsigned)0, 0, RO);
                    319:                u.u_base = 0;
                    320:                u.u_offset = sizeof(u.u_exdata.A)+u.u_exdata.A.ux_tsize;
                    321:                u.u_count = u.u_exdata.A.ux_dsize;
                    322:                readi(ip);
                    323:                /*
                    324:                 * set SUID/SGID protections, if no tracing
                    325:                 */
                    326:                if ((u.u_procp->p_flag&STRC)==0) {
                    327:                        u.u_uid = uid;
                    328:                        u.u_gid = gid;
                    329:                } else
                    330:                        psignal(u.u_procp, SIGTRC);
                    331:        }
                    332:        u.u_tsize = ts;
                    333:        u.u_dsize = ds;
                    334:        u.u_ssize = ss;
                    335:        u.u_sep = sep;
                    336:        estabur(ts, ds, ss, sep, RO);
                    337: }
                    338: 
                    339: /*
                    340:  * Clear registers on exec
                    341:  */
                    342: setregs()
                    343: {
                    344:        register int *rp;
                    345:        register char *cp;
                    346:        register i;
                    347: 
                    348:        for(rp = &u.u_signal[0]; rp < &u.u_signal[NSIG]; rp++)
                    349:                if((*rp & 1) == 0)
                    350:                        *rp = 0;
                    351:        for(cp = &regloc[0]; cp < &regloc[6];)
                    352:                u.u_ar0[*cp++] = 0;
                    353:        u.u_ar0[PC] = u.u_exdata.A.ux_entloc & ~01;
                    354:        for(rp = (int *)&u.u_fps; rp < (int *)&u.u_fps.u_fpregs[6];)
                    355:                *rp++ = 0;
                    356:        for(i=0; i<NOFILE; i++) {
                    357:                if (u.u_pofile[i]&EXCLOSE) {
                    358:                        closef(u.u_ofile[i]);
                    359:                        u.u_ofile[i] = NULL;
                    360:                        u.u_pofile[i] &= ~EXCLOSE;
                    361:                }
                    362:        }
                    363:        /*
                    364:         * Remember file name for accounting.
                    365:         */
                    366:        u.u_acflag &= ~AFORK;
                    367:        bcopy((caddr_t)u.u_dbuf, (caddr_t)u.u_comm, DIRSIZ);
                    368: }
                    369: 
                    370: /*
                    371:  * exit system call:
                    372:  * pass back caller's arg
                    373:  */
                    374: rexit()
                    375: {
                    376:        register struct a {
                    377:                int     rval;
                    378:        } *uap;
                    379: 
                    380:        uap = (struct a *)u.u_ap;
                    381:        exit((uap->rval & 0377) << 8);
                    382: }
                    383: 
                    384: /*
                    385:  * Release resources.
                    386:  * Save u. area for parent to look at.
                    387:  * Enter zombie state.
                    388:  * Wake up parent and init processes,
                    389:  * and dispose of children.
                    390:  */
                    391: exit(rv)
                    392: {
                    393:        register int i;
                    394:        register struct proc *p, *q;
                    395:        register struct file *f;
                    396: 
                    397:        p = u.u_procp;
                    398:        p->p_flag &= ~(STRC|SULOCK);
                    399:        p->p_clktim = 0;
                    400:        for(i=0; i<NSIG; i++)
                    401:                u.u_signal[i] = 1;
                    402:        for(i=0; i<NOFILE; i++) {
                    403:                f = u.u_ofile[i];
                    404:                u.u_ofile[i] = NULL;
                    405:                closef(f);
                    406:        }
                    407:        plock(u.u_cdir);
                    408:        iput(u.u_cdir);
                    409:        if (u.u_rdir) {
                    410:                plock(u.u_rdir);
                    411:                iput(u.u_rdir);
                    412:        }
                    413:        xfree();
                    414:        acct();
                    415:        mfree(coremap, p->p_size, p->p_addr);
                    416:        p->p_stat = SZOMB;
                    417:        ((struct xproc *)p)->xp_xstat = rv;
                    418:        ((struct xproc *)p)->xp_utime = u.u_cutime + u.u_utime;
                    419:        ((struct xproc *)p)->xp_stime = u.u_cstime + u.u_stime;
                    420:        for(q = &proc[0]; q < &proc[NPROC]; q++)
                    421:                if(q->p_ppid == p->p_pid) {
                    422:                        wakeup((caddr_t)&proc[1]);
                    423:                        q->p_ppid = 1;
                    424:                        if (q->p_stat==SSTOP)
                    425:                                setrun(q);
                    426:                }
                    427:        for(q = &proc[0]; q < &proc[NPROC]; q++)
                    428:                if(p->p_ppid == q->p_pid) {
                    429:                        wakeup((caddr_t)q);
                    430:                        swtch();
                    431:                        /* no return */
                    432:                }
                    433:        swtch();
                    434: }
                    435: 
                    436: /*
                    437:  * Wait system call.
                    438:  * Search for a terminated (zombie) child,
                    439:  * finally lay it to rest, and collect its status.
                    440:  * Look also for stopped (traced) children,
                    441:  * and pass back status from them.
                    442:  */
                    443: wait()
                    444: {
                    445:        register f;
                    446:        register struct proc *p;
                    447: 
                    448:        f = 0;
                    449: 
                    450: loop:
                    451:        for(p = &proc[0]; p < &proc[NPROC]; p++)
                    452:        if(p->p_ppid == u.u_procp->p_pid) {
                    453:                f++;
                    454:                if(p->p_stat == SZOMB) {
                    455:                        u.u_r.V.r_val1 = p->p_pid;
                    456:                        u.u_r.V.r_val2 = ((struct xproc *)p)->xp_xstat;
                    457:                        u.u_cutime += ((struct xproc *)p)->xp_utime;
                    458:                        u.u_cstime += ((struct xproc *)p)->xp_stime;
                    459:                        p->p_pid = 0;
                    460:                        p->p_ppid = 0;
                    461:                        p->p_pgrp = 0;
                    462:                        p->p_sig = 0;
                    463:                        p->p_flag = 0;
                    464:                        p->p_wchan = 0;
                    465:                        p->p_stat = NULL;
                    466:                        return;
                    467:                }
                    468:                if(p->p_stat == SSTOP) {
                    469:                        if((p->p_flag&SWTED) == 0) {
                    470:                                p->p_flag |= SWTED;
                    471:                                u.u_r.V.r_val1 = p->p_pid;
                    472:                                u.u_r.V.r_val2 = (fsig(p)<<8) | 0177;
                    473:                                return;
                    474:                        }
                    475:                        continue;
                    476:                }
                    477:        }
                    478:        if(f) {
                    479:                sleep((caddr_t)u.u_procp, PWAIT);
                    480:                goto loop;
                    481:        }
                    482:        u.u_error = ECHILD;
                    483: }
                    484: 
                    485: /*
                    486:  * fork system call.
                    487:  */
                    488: fork()
                    489: {
                    490:        register struct proc *p1, *p2;
                    491:        register a;
                    492: 
                    493:        /*
                    494:         * Make sure there's enough swap space for max
                    495:         * core image, thus reducing chances of running out
                    496:         */
                    497:        if ((a = malloc(swapmap, ctod(MAXMEM))) == 0) {
                    498:                u.u_error = ENOMEM;
                    499:                goto out;
                    500:        }
                    501:        mfree(swapmap, ctod(MAXMEM), a);
                    502:        a = 0;
                    503:        p2 = NULL;
                    504:        for(p1 = &proc[0]; p1 < &proc[NPROC]; p1++) {
                    505:                if (p1->p_stat==NULL && p2==NULL)
                    506:                        p2 = p1;
                    507:                else {
                    508:                        if (p1->p_uid==u.u_uid && p1->p_stat!=NULL)
                    509:                                a++;
                    510:                }
                    511:        }
                    512:        /*
                    513:         * Disallow if
                    514:         *  No processes at all;
                    515:         *  not su and too many procs owned; or
                    516:         *  not su and would take last slot.
                    517:         */
                    518:        if (p2==NULL || (u.u_uid!=0 && (p2==&proc[NPROC-1] || a>MAXUPRC))) {
                    519:                u.u_error = EAGAIN;
                    520:                goto out;
                    521:        }
                    522:        p1 = u.u_procp;
                    523:        if(newproc()) {
                    524:                u.u_r.V.r_val1 = p1->p_pid;
                    525:                u.u_start = time;
                    526:                u.u_cstime = 0;
                    527:                u.u_stime = 0;
                    528:                u.u_cutime = 0;
                    529:                u.u_utime = 0;
                    530:                u.u_acflag = AFORK;
                    531:                return;
                    532:        }
                    533:        u.u_r.V.r_val1 = p2->p_pid;
                    534: 
                    535: out:
                    536:        u.u_ar0[R7] += NBPW;
                    537: }
                    538: 
                    539: /*
                    540:  * break system call.
                    541:  *  -- bad planning: "break" is a dirty word in C.
                    542:  */
                    543: sbreak()
                    544: {
                    545:        struct a {
                    546:                char    *nsiz;
                    547:        };
                    548:        register a, n, d;
                    549:        int i;
                    550: 
                    551:        /*
                    552:         * set n to new data size
                    553:         * set d to new-old
                    554:         * set n to new total size
                    555:         */
                    556: 
                    557:        n = btoc((int)((struct a *)u.u_ap)->nsiz);
                    558:        if(!u.u_sep)
                    559:                n -= ctos(u.u_tsize) * stoc(1);
                    560:        if(n < 0)
                    561:                n = 0;
                    562:        d = n - u.u_dsize;
                    563:        n += USIZE+u.u_ssize;
                    564:        if(estabur(u.u_tsize, u.u_dsize+d, u.u_ssize, u.u_sep, RO))
                    565:                return;
                    566:        u.u_dsize += d;
                    567:        if(d > 0)
                    568:                goto bigger;
                    569:        a = u.u_procp->p_addr + n - u.u_ssize;
                    570:        i = n;
                    571:        n = u.u_ssize;
                    572:        while(n--) {
                    573:                copyseg(a-d, a);
                    574:                a++;
                    575:        }
                    576:        expand(i);
                    577:        return;
                    578: 
                    579: bigger:
                    580:        expand(n);
                    581:        a = u.u_procp->p_addr + n;
                    582:        n = u.u_ssize;
                    583:        while(n--) {
                    584:                a--;
                    585:                copyseg(a-d, a);
                    586:        }
                    587:        while(d--)
                    588:                clearseg(--a);
                    589: }
                    590: 
                    591: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.