Annotation of coherent/d/286_KERNEL/USRSRC/286/exec.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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