Annotation of coherent/d/PS2_KERNEL/i286/exec.c, revision 1.1.1.1

1.1       root        1: /* $Header: /kernel/kersrc/i286/RCS/exec.c,v 1.1 92/07/17 15:21:27 bin Exp Locker: bin $ */
                      2: /* (lgl-
                      3:  *     The information contained herein is a trade secret of Mark Williams
                      4:  *     Company, and  is confidential information.  It is provided  under a
                      5:  *     license agreement,  and may be  copied or disclosed  only under the
                      6:  *     terms of  that agreement.  Any  reproduction or disclosure  of this
                      7:  *     material without the express written authorization of Mark Williams
                      8:  *     Company or persuant to the license agreement is unlawful.
                      9:  *
                     10:  *     COHERENT Version 2.3.37
                     11:  *     Copyright (c) 1982, 1983, 1984.
                     12:  *     An unpublished work by Mark Williams Company, Chicago.
                     13:  *     All rights reserved.
                     14:  -lgl) */
                     15: /*
                     16:  * This file contains a special version
                     17:  * of "sys exec" for the i8086. This version has
                     18:  * no driver load code in it (save space) and has
                     19:  * special load code so that the text of a shared
                     20:  * and separated image can be shared.
                     21:  * Loadable kernel processes are partially supported:
                     22:  * the process text and data must be ld'ed with the system
                     23:  * and the l.out executed must have no loadable or allocateable
                     24:  * segments.
                     25:  *
                     26:  * $Log:       exec.c,v $
                     27:  * Revision 1.1  92/07/17  15:21:27  bin
                     28:  * Initial revision
                     29:  * 
                     30:  * Revision 1.1        88/03/24  17:39:26      src
                     31:  * Initial revision
                     32:  * 
                     33:  * 88/01/21    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     34:  * Segments are now de-associated from processes before freeing the segment.
                     35:  *
                     36:  * 87/12/03    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     37:  * ld_start() now reverts to kernel mode [depth=0] from user mode [depth=1].
                     38:  *
                     39:  * 87/11/25    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     40:  * vaddr_t bp->b_vaddr --> faddr_t bp->b_faddr.
                     41:  *
                     42:  * 87/11/14    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     43:  * Init code+data now split into icodep/icodes and idatap/idatas.
                     44:  *
                     45:  * 87/11/05    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     46:  * New seg struct now used to allow extended addressing.
                     47:  *
                     48:  * 87/10/09    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     49:  * pload() now handles new format [separate code] loadable device drivers.
                     50:  *
                     51:  * 87/10/08    Allan Cornish           /usr/src/sys/i8086/src/exec.c
                     52:  * Exsread() initializes the (IO).io_flag field to 0.
                     53:  */
                     54: #include <sys/coherent.h>
                     55: #include <acct.h>
                     56: #include <sys/buf.h>
                     57: #include <canon.h>
                     58: #include <sys/con.h>
                     59: #include <errno.h>
                     60: #include <sys/filsys.h>
                     61: #include <sys/ino.h>
                     62: #include <sys/inode.h>
                     63: #include <l.out.h>
                     64: #include <sys/proc.h>
                     65: #include <sys/sched.h>
                     66: #include <sys/seg.h>
                     67: #include <signal.h>
                     68: #include <sys/i8086.h>
                     69: 
                     70: /*
                     71:  * Sizes.
                     72:  */
                     73: #define        sh      ((fsize_t)sizeof(struct ldheader))
                     74: #define si     lssize[L_SHRI]
                     75: #define pi     lssize[L_PRVI]
                     76: #define bi     lssize[L_BSSI]
                     77: #define sd     lssize[L_SHRD]
                     78: #define pd     lssize[L_PRVD]
                     79: #define bd     lssize[L_BSSD]
                     80: 
                     81: /*
                     82:  * Segments.
                     83:  */
                     84: #define upsp   pp->p_segp[SIUSERP]
                     85: #define sssp   pp->p_segp[SISTACK]
                     86: #define        sisp    pp->p_segp[SISTEXT]
                     87: #define pisp   pp->p_segp[SIPTEXT]
                     88: #define pdsp   pp->p_segp[SIPDATA]
                     89: 
                     90: /*
                     91:  * Loadable driver initiation point.
                     92:  */
                     93: static
                     94: ld_start()
                     95: {
                     96:        register SEG * sp;
                     97:        register int ret;
                     98: 
                     99:        /*
                    100:         * Kernel processes start by default at user level.
                    101:         * Revert to kernel level.
                    102:         */
                    103:        if ( depth == 1 )
                    104:                depth--;
                    105: 
                    106:        /*
                    107:         * Initialize memory references.
                    108:         */
                    109:        u.u_btime = timer.t_time;
                    110:        sproto();
                    111:        segload();
                    112: 
                    113: 
                    114:        /*
                    115:         * Invoke the driver if it has a shared or private code segment.
                    116:         */
                    117:        ret = 100;
                    118:        if ( (sp = SELF->p_segp[SISTEXT]) || (sp = SELF->p_segp[SIPTEXT]) ) {
                    119:                ret = ld_xcall( sp->s_faddr );
                    120:        }
                    121: 
                    122:        uexit( ret );
                    123: }
                    124: 
                    125: /*
                    126:  * Set up the first process, a small programme which will exec
                    127:  * the init programme.
                    128:  */
                    129: eveinit(sp)
                    130: SEG *sp;
                    131: {
                    132:        register PROC *pp;
                    133:        SELF = pp = eprocp;
                    134: 
                    135:        /*
                    136:         * Record user area.
                    137:         */
                    138:        pp->p_segp[SIUSERP] = sp;
                    139: 
                    140:        /*
                    141:         * Allocate, record, initialize code segment, make it executable.
                    142:         */
                    143:        if ((sp=salloc((fsize_t)icodes, 0)) == NULL)
                    144:                panic("eveinit(code)");
                    145:        pp->p_segp[SIPTEXT] = sp;
                    146:        kfcopy( icodep, sp->s_faddr, icodes );
                    147:        sp->s_flags |= SFTEXT;
                    148:        vremap(sp);
                    149: 
                    150:        /*
                    151:         * Allocate, record, and initialize data segment.
                    152:         */
                    153:        if ((sp=salloc((fsize_t)idatas, 0)) == NULL)
                    154:                panic("eveinit(data)");
                    155:        pp->p_segp[SIPDATA] = sp;
                    156:        kfcopy( idatap, sp->s_faddr, idatas );
                    157: 
                    158:        /*
                    159:         * Allocate and record stack segment.
                    160:         */
                    161:        if ((sp=salloc((fsize_t)UPASIZE, SFDOWN)) == NULL)
                    162:                panic("eveinit()");
                    163:        pp->p_segp[SISTACK] = sp;
                    164: 
                    165:        /*
                    166:         * Start process.
                    167:         */
                    168:        u.u_argp = 0;
                    169:        if (sproto() == 0)
                    170:                panic("eveinit()");
                    171:        segload();
                    172: }
                    173: 
                    174: /*
                    175:  * Load a driver which has already been linked into the system image.
                    176:  */
                    177: pload( np )
                    178: char * np;
                    179: {
                    180:        register INODE * ip;
                    181:        register PROC  * cpp;
                    182:        struct seg     * sp;
                    183:        fsize_t         lssize[NUSEG];          /* Segment sizes */
                    184:        int             lflag;                  /* l_flags from l.out */
                    185:        vaddr_t         pc;                     /* l_entry from l.out */
                    186:        int             r;                      /* Flag for "exload" */
                    187:        int             s;
                    188:        extern char     end[];
                    189: 
                    190: 
                    191:        if (super() == 0) {
                    192:                return( -1 );
                    193:        }
                    194: 
                    195:        /*
                    196:         * Coalesce memory BEFORE loading driver, since it can't be moved.
                    197:         */
                    198:        krunch(10000);
                    199: 
                    200:        if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
                    201:                return( -1 );
                    202:        }
                    203: 
                    204:        /*
                    205:         * New format loadable drivers must have separate code/data.
                    206:         * It must have executable code, but no initialized data.
                    207:         * Uninitialized data must match the kernel data size.
                    208:         */
                    209:        if ( ((lflag & (LF_KER|LF_SHR|LF_SEP)) != (LF_SEP|LF_KER))
                    210:          || (si==0) || (sd!=0) || (pd!=0) || (bd != (int)end) ) {
                    211:                u.u_error = EBADFMT;
                    212:                idetach(ip);
                    213:                return( -1 );
                    214:        }
                    215: 
                    216:        /*
                    217:         * Allocate and initialize driver code segment.
                    218:         * NOTE: Must be system segment to prevent relocation.
                    219:         */
                    220:        sp = ssalloc(&r, ip, SFTEXT|SFHIGH|SFNSWP|SFSYST, si+pi+bi, sh, si+pi);
                    221: 
                    222:        /*
                    223:         * Release driver object file.
                    224:         */
                    225:        idetach(ip);
                    226: 
                    227:        if ( r < 0 ) {
                    228:                u.u_error = ENOMEM;
                    229:                return( -1 );
                    230:        }
                    231: 
                    232:        /*
                    233:         * Spawn kernel process to service driver.
                    234:         */
                    235:        if ((cpp = process(ld_start)) == NULL ) {
                    236:                u.u_error = ENOMEM;
                    237:                sfree(sp);
                    238:                return( -1 );
                    239:        }
                    240: 
                    241:        /*
                    242:         * Record the basename of the loaded driver.
                    243:         */
                    244:        kscopy( u.u_direct.d_name, cpp->p_segp[SIUSERP],
                    245:                offset(uproc,u_comm[0]), sizeof(u.u_comm) );
                    246: 
                    247:        /*
                    248:         * Record the driver code segment in the process's private code.
                    249:         */
                    250:        cpp->p_segp[SIPTEXT] = sp;
                    251:        cpp->p_cval = CVCHILD;
                    252:        cpp->p_sval = SVCHILD;
                    253:        cpp->p_rval = RVCHILD;
                    254:        cpp->p_ppid = 1;
                    255: 
                    256:        /*
                    257:         * Make the process executable.
                    258:         */
                    259:        s = sphi();
                    260:        setrun( cpp );
                    261:        spl( s );
                    262: 
                    263:        /*
                    264:         * Return driver process id.
                    265:         */
                    266:        return( cpp->p_pid );
                    267: }
                    268: 
                    269: /*
                    270:  * Given a major number, undo the previous function.
                    271:  */
                    272: puload(m)
                    273: int m;
                    274: {
                    275:        register CON *cp;
                    276:        register DRV *dp;
                    277: 
                    278:        dp = &drvl[m];
                    279:        lock(dp->d_gate);
                    280:        if (m>=drvn || (cp=dp->d_conp)==NULL) {
                    281:                u.u_error = ENXIO;
                    282:                goto ret;
                    283:        }
                    284:        (*cp->c_uload)();
                    285:        if ( ! u.u_error)
                    286:                dp->d_conp = NULL;
                    287: ret:
                    288:        unlock(dp->d_gate);
                    289:        return (0);
                    290: }
                    291: 
                    292: /*
                    293:  * Pass control to an image in a file.
                    294:  * Make sure the format is acceptable. Release
                    295:  * the old segments. Read in the new ones. Some special
                    296:  * care is taken so that shared and (more important) shared
                    297:  * and separated images can be run on the 8086.
                    298:  */
                    299: pexece(np, argp, envp)
                    300: char   *np;
                    301: char   *argp[];
                    302: char   *envp[];
                    303: {
                    304:        register INODE  *ip;                    /* Load file INODE */
                    305:        register PROC   *pp;                    /* A cheap copy of SELF */
                    306:        register SEG    *ssp;                   /* New stack segment */
                    307:        register SEG    *segp;
                    308:        register fsize_t        ss;                     /* Segment size temp. */
                    309:        register int    i;                      /* For looping over segments */
                    310:        int             r;                      /* Flag for "exload" */
                    311:        int             lflag;                  /* l_flags from l.out */
                    312:        vaddr_t         pc;                     /* l_entry from l.out */
                    313:        vaddr_t         sp;                     /* Initial stack pointer */
                    314:        fsize_t         lssize[NUSEG];          /* Segment sizes */
                    315:        fsize_t         codsize;                /* Total if CS segment  */
                    316:        fsize_t         datsize;                /* Total of DS segment  */
                    317:        extern fsize_t  exround();              /* Paragraph rounder */
                    318: 
                    319:        pp = SELF;
                    320:        if ((ip=exlopen(np, lssize, &lflag, &pc)) == NULL) {
                    321:                return;
                    322:        }
                    323: 
                    324:        if ( (lflag & LF_SEP) == 0 ) {
                    325:                u.u_error = EBADFMT;
                    326:                idetach(ip);
                    327:                return;
                    328:        }
                    329: 
                    330:        /*
                    331:         * Kernel processes are now supported through the sload() system call.
                    332:         * 87/10/09     Allan Cornish.
                    333:         */
                    334:        if ((lflag&LF_KER) != 0) {
                    335:                u.u_error = EBADFMT;
                    336:                idetach(ip);
                    337:                return;
                    338:        }
                    339: 
                    340:        /*
                    341:         * If a shared and separated image
                    342:         * has stuff in segments that makes it impossible
                    343:         * to share, give an error immediately so that we don't
                    344:         * lose the parent.
                    345:         */
                    346:        lflag &= LF_SHR|LF_SEP;
                    347: 
                    348:        if (lflag==(LF_SHR|LF_SEP) && (pi!=0 || bi!=0)) {
                    349:                u.u_error = EBADFMT;
                    350:                idetach(ip);
                    351:                return;
                    352:        }
                    353: 
                    354:        if ((ssp=exstack(&sp, argp, envp)) == NULL) {
                    355:                idetach(ip);
                    356:                return;
                    357:        }
                    358: 
                    359:        switch (lflag) {
                    360:        case LF_SEP:
                    361:                codsize = si+pi+bi;
                    362:                datsize = ssp->s_size+sd+pd+bd;
                    363:                break;
                    364:        case LF_SHR|LF_SEP:
                    365:                codsize = si;
                    366:                datsize = ssp->s_size+exround(sd)+pd+bd;
                    367:                break;
                    368:        }
                    369:        codsize = (codsize+(BSIZE-1)) & ~(BSIZE-1);
                    370:        datsize = (datsize+(BSIZE-1)) & ~(BSIZE-1);
                    371:        if ( (codsize >= MAXU) || (datsize >= MAXU) ) {
                    372:                u.u_error = E2BIG;
                    373:                idetach(ip);
                    374:                return;
                    375:        }
                    376: 
                    377:        /*
                    378:         * At this point the file has been
                    379:         * validated as an object module, and the
                    380:         * argument list has been built. Release all of
                    381:         * the original segments. At this point we have
                    382:         * committed to the new image. A "sys exec" that
                    383:         * gets an I/O error is doomed.
                    384:         * NOTE: User-area segment is NOT released.
                    385:         *       Segment pointer in proc is erased BEFORE invoking sfree().
                    386:         */
                    387:        for ( i = 1; i < NUSEG; ++i ) {
                    388:                if ((segp = pp->p_segp[i]) != NULL) {
                    389:                        pp->p_segp[i] = NULL;
                    390:                        sfree(segp);
                    391:                }
                    392:        }
                    393: 
                    394:        /*
                    395:         * Read in the loadable segments.
                    396:         */
                    397:        sssp = ssp;
                    398:        switch (lflag) {
                    399:        case 0:
                    400:                ss = si+pi+sd+pd;
                    401:                pdsp = ssalloc(&r, ip, 0, ss+bi+bd, sh, ss);
                    402:                if (r < 0)
                    403:                        goto out;
                    404:                break;
                    405: 
                    406:        case LF_SHR:
                    407:                ss = exround(si+sd);
                    408:                pdsp = ssalloc(&r, ip, 0, ss+pi+pd+bi+bd, sh, si);
                    409:                if (r < 0)
                    410:                        goto out;
                    411:                if (exsread(pdsp, ip, sd, sh+si+pi, si) == NULL)
                    412:                        goto out;
                    413:                if (exsread(pdsp, ip, pi, sh+si, ss) == NULL)
                    414:                        goto out;
                    415:                if (exsread(pdsp, ip, pd, sh+si+pi+sd, ss+pi) == NULL)
                    416:                        goto out;
                    417:                break;
                    418: 
                    419:        case LF_SEP:
                    420:                pisp = ssalloc(&r, ip, SFTEXT, si+pi+bi, sh, si+pi);
                    421:                if (r < 0)
                    422:                        goto out;
                    423:                pdsp = ssalloc(&r, ip, 0, sd+pd+bd, sh+si+pi, sd+pd);
                    424:                if (r < 0)
                    425:                        goto out;
                    426:                break;
                    427: 
                    428:        case LF_SHR|LF_SEP:
                    429:                /* pi=0, bi=0 */
                    430:                sisp = ssalloc(&r, ip, SFSHRX|SFTEXT, si, sh, si);
                    431:                if (r < 0)
                    432:                        goto out;
                    433:                ss = exround(sd);
                    434:                pdsp = ssalloc(&r, ip, 0, ss+pd+bd, sh+si, sd);
                    435:                if (r<0 || exsread(pdsp, ip, pd, sh+si+sd, ss) == NULL)
                    436:                        goto out;
                    437:        }
                    438:        if (sproto() == 0)
                    439:                 goto out;
                    440: #if 0
                    441:        if ( (datsize != pdsp->s_size) ||
                    442:             ( (lflag==LF_SEP) && (codsize != pisp->s_size) ) ||
                    443:             ( (lflag==(LF_SEP|LF_SHR)) && (codsize != sisp->s_size) ) ) {
                    444:                printf("\nExec ERROR:  codsize: 0x%X  datsize: 0x%X\n", 
                    445:                                        codsize, datsize);
                    446:                printf(
                    447:                "pdsp->s_size: 0x%X  pisp->s_size: 0x%X  sisp->s_size: 0x%X\n",
                    448:                        pdsp->s_size, pisp->s_size, sisp->s_size);
                    449:        }
                    450: #endif
                    451:        /*
                    452:         * The new image is read in
                    453:         * and mapped. Perform the final grunge
                    454:         * (set-uid stuff, accounting, loading up
                    455:         * registers, etc).
                    456:         */
                    457:        u.u_flag &= ~AFORK;
                    458:        kkcopy(u.u_direct.d_name, u.u_comm, sizeof(u.u_comm));
                    459:        if (iaccess(ip, IPR) == 0) {    /* Can't read ? no dump or trace */
                    460:                pp->p_flags |= PFNDMP;
                    461:                pp->p_flags &= ~PFTRAC;
                    462:        }
                    463:        if (iaccess(ip, IPW) == 0)      /* Can't write ? no trace */
                    464:                pp->p_flags &= ~PFTRAC;
                    465:        if ((ip->i_mode&ISUID) != 0) {  /* Set user id ? no trace */
                    466:                pp->p_uid = u.u_uid = ip->i_uid;
                    467:                pp->p_flags &= ~PFTRAC;
                    468:        }
                    469:        if ((ip->i_mode&ISGID) != 0) {  /* Set group id ? no trace */
                    470:                u.u_gid = ip->i_gid;
                    471:                pp->p_flags &= ~PFTRAC;
                    472:        }
                    473:        for (i=0; i<NSIG; ++i)
                    474:                if (u.u_sfunc[i] != SIG_IGN)
                    475:                        u.u_sfunc[i] = SIG_DFL;
                    476:        if ((pp->p_flags&PFTRAC) != 0)  /* Being traced */
                    477:                sendsig(SIGTRAP, pp);
                    478:        idetach(ip);
                    479:        msetusr(pc, sp);
                    480:        segload();
                    481:        return (0);
                    482: 
                    483:        /*
                    484:         * We did not make it.
                    485:         * Release the INODE for the load
                    486:         * file, and return through the "sys exit"
                    487:         * code with a "SIGSYS", or with the signal actually received
                    488:         * if we are aborting due to interrupted exec.
                    489:         */
                    490: out:
                    491:        idetach(ip);
                    492:        if (u.u_error == EINTR)
                    493:                pexit(nondsig());
                    494:        pexit(SIGSYS);
                    495: }
                    496: 
                    497: /*
                    498:  * Open an l.out, make sure it is an l.out and executable and return the
                    499:  * appropriate information.
                    500:  */
                    501: INODE *
                    502: exlopen(np, ssizep, flagp, pcp)
                    503: char *np;
                    504: fsize_t *ssizep;
                    505: int *flagp;
                    506: vaddr_t *pcp;
                    507: {
                    508:        register INODE *ip;
                    509:        register struct ldheader *ldp;
                    510:        register int n;
                    511:        register BUF *bp;
                    512:        int m;
                    513: 
                    514:        /*
                    515:         * Make sure the file is really an executable l.out and read the
                    516:         * header in.
                    517:         */
                    518:        if (ftoi(np, 'r') != 0)
                    519:                return (NULL);
                    520:        ip = u.u_cdiri;
                    521:        if (iaccess(ip, IPE) == 0) {
                    522:                idetach(ip);
                    523:                return (NULL);
                    524:        }
                    525:        if ((ip->i_mode&(IPE|IPE<<3|IPE<<6))==0 || (ip->i_mode&IFMT)!=IFREG) {
                    526:                u.u_error = EACCES;
                    527:                idetach(ip);
                    528:                return (NULL);
                    529:        }
                    530:        if ((bp=vread(ip, (daddr_t)0)) == NULL) {
                    531:                u.u_error = EBADFMT;
                    532:                idetach(ip);
                    533:                return (NULL);
                    534:        }
                    535: 
                    536:        /*
                    537:         * Copy everything we need from the l.out header and check magic
                    538:         * number and machine type.
                    539:         */
                    540:        ldp = FP_OFF(bp->b_faddr);
                    541:        m = ldp->l_magic;
                    542:        canint(m);
                    543:        if (m != L_MAGIC) {
                    544:                u.u_error = ENOEXEC;
                    545:                brelease(bp);
                    546:                idetach(ip);
                    547:                return (NULL);
                    548:        }
                    549:        m = ldp->l_machine;
                    550:        canint(m);
                    551:        if (m != mactype) {
                    552:                u.u_error = EBADFMT;
                    553:                brelease(bp);
                    554:                idetach(ip);
                    555:                return (NULL);
                    556:        }
                    557:        kkcopy(ldp->l_ssize, ssizep, NXSEG*sizeof(fsize_t));
                    558:        for (n=0; n<NXSEG; n++)
                    559:                cansize(ssizep[n]);
                    560:        *flagp = ldp->l_flag;
                    561:        canint(*flagp);
                    562:        *pcp = ldp->l_entry;
                    563:        canvaddr(*pcp);
                    564:        brelease(bp);
                    565:        return (ip);
                    566: }
                    567: 
                    568: /*
                    569:  * Given a segment `sp', read `ss' bytes from the inode `ip' starting
                    570:  * at seek address `sa' into offset `so' in the segment.
                    571:  */
                    572: SEG *
                    573: exsread(sp, ip, ss, sa, so)
                    574: register SEG *sp;
                    575: INODE *ip;
                    576: fsize_t ss;
                    577: fsize_t sa;
                    578: fsize_t so;
                    579: {
                    580:        while (ss > 0) {
                    581:                u.u_io.io_seg = IOPHY;
                    582:                u.u_io.io_seek = sa;
                    583:                u.u_io.io_phys = sp->s_paddr + so;
                    584:                u.u_io.io_flag = 0;
                    585:                if (ss >= 4096) {
                    586:                        u.u_io.io_ioc = 4096;
                    587:                        ss -= 4096;
                    588:                } else {
                    589:                        u.u_io.io_ioc = ss;
                    590:                        ss = 0;
                    591:                }
                    592:                sp->s_lrefc++;
                    593:                iread(ip, &u.u_io);
                    594:                sp->s_lrefc--;
                    595:                if (nondsig()) {
                    596:                        u.u_error = EINTR;
                    597:                        break;
                    598:                }
                    599:                sa += 4096;
                    600:                so += 4096;
                    601:        }
                    602:        if (u.u_error == 0)
                    603:                return (sp);
                    604:        return (NULL);
                    605: }
                    606: 
                    607: /*
                    608:  * Given a pointer to a list of arguments and a pointer to a list of
                    609:  * environments, return a stack with the arguments and environments on it.
                    610:  */
                    611: SEG *
                    612: exstack(iusp, argp, envp)
                    613: char **iusp;           /* Back patch sp value */
                    614: char *argp[];          /* Arguments for new process */
                    615: char *envp[];          /* Environments for new process */
                    616: {
                    617:        SEG *sp;                /* Stack segment pointer */
                    618:        struct adata {          /* Storage for arg and env data */
                    619:                char    **up;           /* User vector pointer */
                    620:                int     np;             /* Number of pointers in vector */
                    621:                int     nc;             /* Number of characters in strings */
                    622:        } arg, env;
                    623:        struct sdata {          /* To keep segment pointers */
                    624:                vaddr_t base;           /* Top of segment virtual */
                    625:                vaddr_t ap;             /* Argc, argv, envp pointer */
                    626:                vaddr_t vp;             /* Argv[i], envp[i] pointer */
                    627:                vaddr_t cp;             /* Argv[i][j], envp[i][j] pointer */
                    628:        } aux, stk;
                    629:        aold_t aold;                    /* Auxiliary map storage */
                    630:        register char **usrvp;          /* Vector pointer into user seg */
                    631:        register char *usrcp;           /* Character pointer into user seg */
                    632:        register int c;                 /* Character fetched from user */
                    633:        register int chrsz;             /* Size of strings */
                    634:        register struct adata *adp;     /* Arg and env scanner */
                    635:        register int vecsz;             /* Size of vectors */
                    636:        register int stksz;             /* Size of stack argument region */
                    637: 
                    638:        /* Validate and evaluate size of args and envs */
                    639:        arg.up = argp;
                    640:        env.up = envp;
                    641:        chrsz = 0;
                    642:        vecsz = 0;
                    643:        for (adp = &arg; ; adp = &env) {
                    644:                adp->np = 0;
                    645:                adp->nc = 0;
                    646:                if (excount(adp->up, &adp->np, &adp->nc) == 0)
                    647:                        return (NULL);
                    648:                chrsz += adp->nc * sizeof(char);
                    649:                vecsz += adp->np * sizeof(char *);
                    650:                if (adp == &env)
                    651:                        break;
                    652:        }
                    653: 
                    654:        /* Calculate stack size and allocate it */
                    655:        chrsz = roundu(chrsz, sizeof(int));
                    656:        stksz = sizeof(int)             /* argc */
                    657:                + sizeof(char **)       /* argv */
                    658:                + sizeof(char **)       /* envp */
                    659:                + vecsz                 /* argv[i] and envp[i] */
                    660:                + chrsz                 /* *argv[i] and *envp[i] */
                    661:                + sizeof(int)           /* Mystery zero word */
                    662:                + sizeof(char *)        /* Splimit for z8000 */
                    663:                + sizeof(int);          /* errno */
                    664:        stksz += ISTSIZE;
                    665:        if (stksz > MADSIZE) {
                    666:                u.u_error = E2BIG;
                    667:                return (NULL);
                    668:        }
                    669:        if ((sp=salloc((fsize_t)stksz, SFDOWN)) == NULL)
                    670:                return (NULL);
                    671:        stksz -= ISTSIZE;
                    672: 
                    673:        /*
                    674:         * Initialize segment data.
                    675:         */
                    676:        asave(aold);
                    677: 
                    678:        abase(FP_SEL(sp->s_faddr));
                    679:        aux.base = sp->s_size;
                    680:        aux.ap = aux.base - stksz;
                    681:        aux.vp = aux.ap + sizeof(int) + 2*sizeof(char **);
                    682:        aux.cp = aux.vp + vecsz;
                    683: 
                    684:        stk.base = ISTVIRT;
                    685:        stk.ap = stk.base - stksz;
                    686:        stk.vp = stk.ap + sizeof(int) + 2*sizeof(char **);
                    687:        stk.cp = stk.vp + vecsz;
                    688: 
                    689:        /*
                    690:         * Write argc.
                    691:         */
                    692:        aputi((int *)aux.ap, arg.np-1);
                    693:        aux.ap += sizeof(int);
                    694: 
                    695:        /*
                    696:         * Arguments and environments.
                    697:         */
                    698:        for (adp = &arg; ; adp = &env) {
                    699: 
                    700:                /* Write argv or envp */
                    701:                aputp((char ***)aux.ap, (char **)stk.vp);
                    702:                aux.ap += sizeof(char **);
                    703:                if ((usrvp = adp->up) != NULL) {
                    704: 
                    705:                        /* Write argv[i] or envp[i] */
                    706:                        while ((usrcp = getupd(usrvp++)) != NULL) {
                    707:                                aputp((char **)aux.vp, (char *)stk.cp);
                    708:                                aux.vp += sizeof(char *);
                    709:                                stk.vp += sizeof(char *);
                    710: 
                    711:                                /* Write argv[i][j] or envp[i][j] */
                    712:                                do {
                    713:                                        c = getubd(usrcp++);
                    714:                                        aputc((char *)aux.cp, c);
                    715:                                        aux.cp += sizeof(char);
                    716:                                        stk.cp += sizeof(char);
                    717:                                } while (c != '\0');
                    718:                        }
                    719:                }
                    720: 
                    721:                /* Write argv[argc] or envp[envc] */
                    722:                aputp((char **)aux.vp, NULL);
                    723:                aux.vp += sizeof(char *);
                    724:                stk.vp += sizeof(char *);
                    725:                if (adp == &env)
                    726:                        break;
                    727:        }
                    728: 
                    729:        /*
                    730:         * Clear out the slop.
                    731:         */
                    732:        aux.base -= sizeof(int);
                    733:        aputi((int *) aux.base, 0);             /* errno */
                    734:        aux.base -= sizeof(char *);
                    735:        aputp((char **) aux.base, (char *)stk.base - sp->s_size + SOVSIZE);
                    736:        aux.base -= sizeof(int);
                    737:        aputi((int *) aux.base, 0);             /* mystery word */
                    738: 
                    739:        arest(aold);
                    740: 
                    741:        /*
                    742:         * Patch some values and return.
                    743:         */
                    744:        *iusp = stk.ap;         /* Patch initial usp */
                    745:        u.u_argc = arg.np-1;
                    746:        u.u_argp = stk.vp;      /* Points after NULL of envs */
                    747:        return (sp);
                    748: }
                    749: 
                    750: /*
                    751:  * Given a pointer to a list of arguments, a pointer to an argument count
                    752:  * and a pointer to a byte count, update incrementally the argument count
                    753:  * and the byte count.
                    754:  */
                    755: excount(usrvp, nap, nbp)
                    756: register char **usrvp;
                    757: int *nap;
                    758: int *nbp;
                    759: {
                    760:        register char *usrcp;
                    761:        register int c;
                    762:        register unsigned nb;
                    763:        register unsigned na;
                    764: 
                    765:        na = 1;
                    766:        nb = 0;
                    767:        if (usrvp != NULL) {
                    768:                for (;;) {
                    769:                        usrcp = getupd(usrvp++);
                    770:                        if (u.u_error)
                    771:                                return (0);
                    772:                        if (usrcp == NULL)
                    773:                                break;
                    774:                        na++;
                    775:                        for (;;) {
                    776:                                c = getubd(usrcp++);
                    777:                                if (u.u_error)
                    778:                                        return (0);
                    779:                                nb++;
                    780:                                if (c == '\0')
                    781:                                        break;
                    782:                        }
                    783:                }
                    784:        }
                    785:        *nap += na;
                    786:        *nbp += nb;
                    787:        return (1);
                    788: }
                    789: 
                    790: /*
                    791:  * Round up a size to a paragraph
                    792:  * (mod 16) boundry.
                    793:  * This is really mod 512 to make swapping work
                    794:  */
                    795: fsize_t
                    796: exround(s)
                    797: fsize_t        s;
                    798: {
                    799:        return ((s+15)&~0x0F);
                    800: }

unix.superglobalmegacorp.com

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