Annotation of 41BSD/sys/newsys/sys1.c, revision 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.