Annotation of MiNT/src/dosmem.c, revision 1.1.1.6

1.1       root        1: /*
                      2: 
1.1.1.3   root        3: Copyright 1990,1991,1992 Eric R. Smith.
                      4: 
1.1.1.6 ! root        5: Copyright 1992,1993,1994 Atari Corporation.
1.1.1.3   root        6: 
                      7: All rights reserved.
1.1       root        8: 
                      9: */
                     10: 
                     11: 
                     12: 
                     13: /*
                     14: 
                     15:  * GEMDOS emulation routines: these are for the GEMDOS system calls
                     16: 
                     17:  * concerning allocating/freeing memory, including Pexec() (since
                     18: 
                     19:  * this allocates memory) and Pterm() (since this, implicitly, frees
                     20: 
                     21:  * it).
                     22: 
                     23:  */
                     24: 
                     25: 
                     26: 
                     27: #include "mint.h"
                     28: 
                     29: 
                     30: 
1.1.1.4   root       31: #define DIRSEP(c) ((c) == '\\')
                     32: 
                     33: 
                     34: 
1.1       root       35: int procdate, proctime;        /* set when any processes are created/destroyed */
                     36: 
                     37: 
                     38: 
                     39: static long do_vfork P_((int));
                     40: 
                     41: 
                     42: 
                     43: /*
                     44: 
                     45:  * new call for TT TOS, for the user to inform DOS of alternate memory
                     46: 
                     47:  * FIXME: we really shouldn't trust the user so completely
                     48: 
1.1.1.3   root       49:  * FIXME: doesn't work if memory protection is on
                     50: 
1.1       root       51:  */
                     52: 
                     53: 
                     54: 
1.1.1.2   root       55: long ARGS_ON_STACK
1.1       root       56: 
                     57: m_addalt(start, size)
                     58: 
                     59:        long start, size;
                     60: 
                     61: {
                     62: 
1.1.1.3   root       63:        extern int no_mem_prot;         /* see main.c and memprot.c */
                     64: 
                     65: 
                     66: 
                     67:        if (!no_mem_prot) return 0;     /* pretend to succeed */
                     68: 
1.1       root       69:        if (!add_region(alt, start, size, M_ALT))
                     70: 
                     71:                return EINTRN;
                     72: 
                     73:        else
                     74: 
                     75:                return 0;
                     76: 
                     77: }
                     78: 
                     79: 
                     80: 
                     81: /*
                     82: 
                     83:  * internal routine for doing Malloc on a particular memory map
                     84: 
                     85:  */
                     86: 
                     87: 
                     88: 
                     89: long
                     90: 
                     91: _do_malloc(map, size, mode)
                     92: 
                     93:        MMAP map;
                     94: 
                     95:        long size;
                     96: 
                     97:        int mode;
                     98: 
                     99: {
                    100: 
                    101:        virtaddr v;
                    102: 
                    103:        MEMREGION *m;
                    104: 
                    105:        long maxsize, mleft;
                    106: 
                    107: 
                    108: 
                    109:        if (size == -1L) {
                    110: 
1.1.1.6 ! root      111:                maxsize = max_rsize(map, 0L);
1.1       root      112: 
                    113:                if (curproc->maxmem) {
                    114: 
                    115:                        mleft = curproc->maxmem - memused(curproc);
                    116: 
                    117:                        if (maxsize > mleft)
                    118: 
                    119:                                maxsize = mleft;
                    120: 
                    121:                        if (maxsize < 0)
                    122: 
                    123:                                maxsize = 0;
                    124: 
                    125:                }
                    126: 
                    127:        /* make sure to round down */
                    128: 
                    129:                return maxsize & ~MASKBITS;
                    130: 
                    131:        }
                    132: 
                    133: 
                    134: 
                    135: /* special case: Malloc(0) should always return 0 */
                    136: 
                    137:        if (size == 0)
                    138: 
                    139:                return 0;
                    140: 
                    141: 
                    142: 
                    143:        if (curproc->maxmem) {          /* memory limit? */
                    144: 
                    145:                if (size > curproc->maxmem - memused(curproc)) {
                    146: 
1.1.1.2   root      147:                        DEBUG(("malloc: memory request would exceed limit"));
1.1       root      148: 
                    149:                        return 0;
                    150: 
                    151:                }
                    152: 
                    153:        }
                    154: 
                    155: 
                    156: 
1.1.1.3   root      157:        m = get_region(map, size, mode);
1.1       root      158: 
                    159:        if (!m) {
                    160: 
                    161:                return 0;
                    162: 
                    163:        }
                    164: 
                    165:        v = attach_region(curproc, m);
                    166: 
                    167:        if (!v) {
                    168: 
                    169:                m->links = 0;
                    170: 
                    171:                free_region(m);
                    172: 
                    173:                return 0;
                    174: 
                    175:        }
                    176: 
                    177: /* NOTE: get_region returns a region with link count 1; since attach_region
                    178: 
                    179:  * increments the link count, we have to remember to decrement the count
                    180: 
                    181:  * to correct for this.
                    182: 
                    183:  */
                    184: 
                    185:        m->links--;
                    186: 
                    187:        if ((mode & F_KEEP)) {  /* request for permanent memory */
                    188: 
                    189:                m->mflags |= M_KEEP;
                    190: 
                    191:        }
                    192: 
                    193:        return (long)v;
                    194: 
                    195: }
                    196: 
                    197: 
                    198: 
1.1.1.2   root      199: long ARGS_ON_STACK
1.1       root      200: 
                    201: m_xalloc(size, mode)
                    202: 
                    203:        long size;
                    204: 
                    205:        int mode;
                    206: 
                    207: {
                    208: 
                    209:        long r, r1;
                    210: 
1.1.1.3   root      211:        int protmode;
                    212: 
1.1.1.4   root      213: #ifdef DEBUG_INFO
1.1.1.3   root      214: 
                    215:        int origmode = mode;
                    216: 
                    217: #endif
                    218: 
1.1       root      219: 
                    220: 
1.1.1.2   root      221:        TRACE(("Mxalloc(%ld,%x)",size,mode));
1.1       root      222: 
                    223: 
                    224: 
1.1.1.3   root      225: /*
                    226: 
                    227:  * AKP: Hack here: if the calling process' PC is in ROM, then this is a
                    228: 
                    229:  * Malloc call made by VDI's v_opnvwk routine.  So we change mode to
                    230: 
                    231:  * include "super accessible."  This is temporary, until VDI catches up
                    232: 
                    233:  * with multitasking TOS.
                    234: 
                    235:  */
                    236: 
                    237: 
                    238: 
                    239:        if (((mode & F_PROTMODE) == 0) &&
                    240: 
                    241:            (curproc->ctxt[SYSCALL].pc > 0x00e00000L) &&
                    242: 
                    243:            (curproc->ctxt[SYSCALL].pc < 0x00efffffL)) {
                    244: 
1.1.1.6 ! root      245: #ifndef MULTITOS
        !           246: 
        !           247:          extern long gem_start;
        !           248: 
        !           249:          if (gem_start && curproc->ctxt[SYSCALL].pc >= gem_start)
        !           250: 
        !           251:            {
        !           252: 
        !           253:              mode |= F_PROT_G + 0x10;
        !           254: 
        !           255:              TRACE (("m_xalloc: AES special (call from ROM)"));
        !           256: 
        !           257:            }
        !           258: 
        !           259:          else
        !           260: 
        !           261: #endif
        !           262: 
        !           263:            {
        !           264: 
1.1.1.3   root      265:                mode |= (F_PROT_S + 0x10) | F_KEEP;
                    266: 
                    267:                TRACE(("m_xalloc: VDI special (call from ROM)"));
1.1       root      268: 
1.1.1.6 ! root      269:            }
        !           270: 
1.1       root      271:        }
                    272: 
1.1.1.3   root      273: /*
                    274: 
                    275:  * If the mode argument comes in a zero, then set it to the default
                    276: 
                    277:  * value from prgflags.  Otherwise subtract one from it to bring it
                    278: 
                    279:  * into line with the actual argument to alloc_region.
                    280: 
                    281:  */
                    282: 
                    283:        protmode = (mode & F_PROTMODE) >> F_PROTSHIFT;
                    284: 
                    285: 
                    286: 
                    287:        if (protmode == 0) {
                    288: 
                    289:            protmode = (curproc->memflags & F_PROTMODE) >> F_PROTSHIFT;
                    290: 
                    291:        }
                    292: 
                    293:        else --protmode;
                    294: 
                    295: 
                    296: 
1.1.1.5   root      297:        if (protmode > PROT_MAX_MODE) {
                    298: 
                    299:            DEBUG(("Mxalloc: invalid protection mode changed to private"));
                    300: 
                    301:            protmode = PROT_P;
                    302: 
                    303:        }
                    304: 
                    305: 
                    306: 
1.1.1.3   root      307: #if 0
                    308: 
                    309: /* I'm very suspicious of the 0x08 flag; I can't see how it could
                    310: 
                    311:  * work as the comment below seems to indicate -- ERS
                    312: 
                    313:  */
                    314: 
                    315: 
                    316: 
                    317: /*
                    318: 
                    319:  * if the mode argument has the 0x08 bit set then you're trying to change
                    320: 
                    321:  * the protection mode of a block you already own. "size" is really its
                    322: 
                    323:  * base address. (new as of 2/6/92)
                    324: 
                    325:  */
                    326: 
                    327:        if (mode & 0x08) change_prot_status(curproc,size,protmode);
                    328: 
                    329: #endif
1.1       root      330: 
                    331: 
                    332: 
1.1.1.3   root      333:        /*
                    334: 
                    335:         * Copy the F_KEEP attribute into protmode.  We didn't do that
                    336: 
                    337:         * before now because change_prot_status don't want to see no
                    338: 
                    339:         * steenking nofree attributes.
                    340: 
                    341:         */
                    342: 
                    343: 
                    344: 
                    345:        protmode |= (mode & F_KEEP);
                    346: 
                    347: 
                    348: 
                    349:        /* mask off all but the ST/alternative RAM bits before further use */
                    350: 
                    351:        mode &= 3;
                    352: 
                    353: 
                    354: 
                    355:        if (mode == 0) {
                    356: 
                    357:                r = _do_malloc(core, size, protmode);
                    358: 
                    359:                goto ret;
                    360: 
                    361:        }
                    362: 
                    363:        else if (mode == 1) {
                    364: 
                    365:                r = _do_malloc(alt, size, protmode);
                    366: 
                    367:                goto ret;
                    368: 
                    369:        }
1.1       root      370: 
                    371:        else if (size == -1) {
                    372: 
                    373:                /* modes 2 and 3 are the same for for size -1 */
                    374: 
1.1.1.3   root      375:                r = _do_malloc(core, -1L, PROT_P);
                    376: 
                    377:                r1 = _do_malloc(alt, -1L, PROT_P);
                    378: 
                    379:                if (r1 > r) r = r1;
                    380: 
                    381:                goto ret;
                    382: 
                    383:        }
                    384: 
                    385:        else if (mode == 2) {
1.1       root      386: 
1.1.1.3   root      387:                r = _do_malloc(core, size, protmode);
1.1       root      388: 
1.1.1.3   root      389:                if (r == 0) r = _do_malloc(alt, size, protmode);
1.1       root      390: 
1.1.1.3   root      391:                goto ret;
1.1       root      392: 
                    393:        }
                    394: 
1.1.1.3   root      395:        else /* if (mode == 3) */ {
1.1       root      396: 
1.1.1.3   root      397:                r = _do_malloc(alt, size, protmode);
1.1       root      398: 
1.1.1.3   root      399:                if (r == 0) r = _do_malloc(core, size, protmode);
1.1       root      400: 
1.1.1.3   root      401:                goto ret;
1.1       root      402: 
                    403:        }
                    404: 
1.1.1.3   root      405: ret:
1.1       root      406: 
1.1.1.3   root      407:        if (r == 0) {
1.1       root      408: 
1.1.1.3   root      409:                DEBUG(("m_xalloc(%lx,%x) returns 0",size,origmode));
1.1       root      410: 
1.1.1.3   root      411:        } else {
                    412: 
                    413:                TRACE(("m_xalloc(%lx,%x) returns %lx",size,origmode,r));
1.1       root      414: 
                    415:        }
                    416: 
1.1.1.3   root      417:        return r;
                    418: 
1.1       root      419: }
                    420: 
                    421: 
                    422: 
1.1.1.2   root      423: long ARGS_ON_STACK
1.1       root      424: 
                    425: m_alloc(size)
                    426: 
                    427:        long size;
                    428: 
                    429: {
                    430: 
                    431:        long r;
                    432: 
                    433: 
                    434: 
1.1.1.2   root      435:        TRACE(("Malloc(%lx)", size));
1.1       root      436: 
                    437:        if (curproc->memflags & F_ALTALLOC)
                    438: 
                    439:                r = m_xalloc(size, 3);
                    440: 
                    441:        else
                    442: 
                    443:                r = m_xalloc(size, 0);
                    444: 
1.1.1.2   root      445:        TRACE(("Malloc: returning %lx", r));
1.1       root      446: 
                    447:        return r;
                    448: 
                    449: }
                    450: 
                    451: 
                    452: 
1.1.1.2   root      453: long ARGS_ON_STACK
1.1       root      454: 
                    455: m_free(block)
                    456: 
                    457:        virtaddr block;
                    458: 
                    459: {
                    460: 
                    461:        MEMREGION *m;
                    462: 
                    463:        int i;
                    464: 
                    465: 
                    466: 
1.1.1.2   root      467:        TRACE(("Mfree(%lx)", block));
1.1       root      468: 
                    469:        if (!block) {
                    470: 
1.1.1.2   root      471:                DEBUG(("Mfree: null pointer"));
1.1       root      472: 
                    473:                return EIMBA;
                    474: 
                    475:        }
                    476: 
                    477: 
                    478: 
                    479: /* search backwards so that most recently allocated incarnations of
                    480: 
                    481:    shared memory blocks are freed first (this doesn't matter very often)
                    482: 
                    483:  */
                    484: 
                    485: 
                    486: 
                    487:        for (i = curproc->num_reg - 1; i >= 0; i--) {
                    488: 
                    489:                if (curproc->addr[i] == block) {
                    490: 
                    491:                        m = curproc->mem[i];
                    492: 
                    493:                        assert(m != NULL);
                    494: 
                    495:                        assert(m->loc == (long)block);
                    496: 
                    497:                        curproc->mem[i] = 0;
                    498: 
                    499:                        curproc->addr[i] = 0;
                    500: 
                    501:                        m->links--;
                    502: 
                    503:                        if (m->links == 0) {
                    504: 
                    505:                                free_region(m);
                    506: 
                    507:                        }
                    508: 
                    509:                        return 0;
                    510: 
                    511:                }
                    512: 
                    513:        }
                    514: 
                    515: 
                    516: 
                    517: /* hmmm... if we didn't find the region, perhaps it's a global
                    518: 
                    519:  * one (with the M_KEEP flag set) belonging to a process that
                    520: 
                    521:  * terminated
                    522: 
                    523:  */
                    524: 
                    525:        for (i = rootproc->num_reg - 1; i >= 0; i--) {
                    526: 
                    527:                if (rootproc->addr[i] == block) {
                    528: 
                    529:                        m = rootproc->mem[i];
                    530: 
                    531:                        assert(m != NULL);
                    532: 
                    533:                        assert(m->loc == (long)block);
                    534: 
                    535:                        if (!(m->mflags & M_KEEP))
                    536: 
                    537:                                continue;
                    538: 
1.1.1.3   root      539:                        TRACE(("Freeing M_KEPT memory"));
                    540: 
1.1       root      541:                        rootproc->mem[i] = 0;
                    542: 
                    543:                        rootproc->addr[i] = 0;
                    544: 
                    545:                        m->links--;
                    546: 
                    547:                        if (m->links == 0) {
                    548: 
                    549:                                free_region(m);
                    550: 
                    551:                        }
                    552: 
                    553:                        return 0;
                    554: 
                    555:                }
                    556: 
                    557:        }
                    558: 
                    559: 
                    560: 
                    561: 
                    562: 
1.1.1.2   root      563:        DEBUG(("Mfree: bad address %lx", block));
1.1       root      564: 
                    565:        return EIMBA;
                    566: 
                    567: }
                    568: 
                    569: 
                    570: 
1.1.1.2   root      571: long ARGS_ON_STACK
1.1       root      572: 
                    573: m_shrink(dummy, block, size)
                    574: 
                    575:        int dummy;
                    576: 
                    577:        virtaddr block;
                    578: 
                    579:        long size;
                    580: 
                    581: {
                    582: 
                    583:        MEMREGION *m;
                    584: 
                    585:        int i;
                    586: 
                    587: 
                    588: 
1.1.1.2   root      589:        UNUSED(dummy);
                    590: 
                    591:        TRACE(("Mshrink: %lx to %ld", block, size));
1.1       root      592: 
                    593:        if (!block) {
                    594: 
1.1.1.2   root      595:                DEBUG(("Mshrink: null pointer"));
1.1       root      596: 
                    597:                return EIMBA;
                    598: 
                    599:        }
                    600: 
                    601: 
                    602: 
                    603:        for (i = 0; i < curproc->num_reg; i++) {
                    604: 
                    605:                if (curproc->addr[i] == block) {
                    606: 
                    607:                        m = curproc->mem[i];
                    608: 
                    609:                        assert(m != NULL);
                    610: 
                    611:                        assert(m->loc == (long)block);
                    612: 
                    613:                        return shrink_region(m, size);
                    614: 
                    615:                }
                    616: 
                    617:        }
                    618: 
1.1.1.2   root      619:        DEBUG(("Mshrink: bad address (%lx)", block));
1.1       root      620: 
                    621:        return EIMBA;
                    622: 
                    623: }
                    624: 
                    625: 
                    626: 
1.1.1.2   root      627: long ARGS_ON_STACK
1.1       root      628: 
                    629: p_exec(mode, ptr1, ptr2, ptr3)
                    630: 
                    631:        int mode;
                    632: 
                    633:        void *ptr1, *ptr2, *ptr3;
                    634: 
                    635: {
                    636: 
1.1.1.2   root      637:        MEMREGION *base,
                    638: 
                    639:                *env = 0;       /* assignment suppresses spurious warning */
1.1       root      640: 
1.1.1.2   root      641:        MEMREGION *text = 0;    /* for shared text regions */
                    642: 
                    643:        PROC *p;
1.1       root      644: 
                    645:        long r, flags = 0;
                    646: 
                    647:        int i;
                    648: 
                    649:        char mkbase = 0, mkload = 0, mkgo = 0, mkwait = 0, mkfree = 0;
                    650: 
                    651:        char overlay = 0;
                    652: 
                    653:        char thread = 0;
                    654: 
1.1.1.2   root      655:        char ptrace;
                    656: 
1.1       root      657:        char mkname = 0, *newname, *lastslash;
                    658: 
                    659:        char localname[PNAMSIZ+1];
                    660: 
                    661:        XATTR xattr;
                    662: 
1.1.1.3   root      663:        int newpid;
                    664: 
1.1.1.6 ! root      665: #ifndef MULTITOS
        !           666: 
        !           667:        extern BASEPAGE *gem_base;
        !           668: 
        !           669: #endif
        !           670: 
1.1.1.3   root      671: 
                    672: 
1.1.1.4   root      673: #ifdef DEBUG_INFO
                    674: 
1.1.1.3   root      675: /* tfmt and tail_offs are used for debugging only */
                    676: 
                    677:        const char *tfmt = "Pexec(%d,%s,\"%s\",%lx)";
                    678: 
                    679:        int tail_offs = 1;
                    680: 
1.1.1.4   root      681: #endif
                    682: 
1.1       root      683: 
                    684: 
1.1.1.2   root      685: /* the high bit of mode controls process tracing */
                    686: 
                    687:        switch(mode & 0x7fff) {
1.1       root      688: 
                    689:        case 0:
                    690: 
                    691:                mkwait = 1;             /* fall through */
                    692: 
                    693:        case 100:
                    694: 
                    695:                mkload = mkgo = mkfree = 1;
                    696: 
                    697:                mkname = 1;
                    698: 
                    699:                break;
                    700: 
                    701:        case 200:                       /* overlay current process */
                    702: 
                    703:                mkload = mkgo = 1;
                    704: 
                    705:                overlay = mkname = 1;
                    706: 
                    707:                break;
                    708: 
                    709:        case 3:
                    710: 
                    711:                mkload = 1;
                    712: 
                    713:                break;
                    714: 
                    715:        case 6:
                    716: 
                    717:                mkfree = 1;
                    718: 
                    719:                /* fall through */
                    720: 
                    721:        case 4:
                    722: 
                    723:                mkwait = mkgo = 1;
                    724: 
1.1.1.4   root      725:                thread = (mode == 4);
                    726: 
                    727: #ifdef DEBUG_INFO
                    728: 
1.1.1.3   root      729:                tfmt = "Pexec(%d,%lx,BP:%lx,%lx)";
                    730: 
                    731:                tail_offs = 0;
1.1       root      732: 
1.1.1.4   root      733: #endif
                    734: 
1.1       root      735:                break;
                    736: 
                    737:        case 106:
                    738: 
                    739:                mkfree = 1;             /* fall through */
                    740: 
                    741:        case 104:
                    742: 
                    743:                thread = (mode == 104);
                    744: 
                    745:                mkgo = 1;
                    746: 
                    747:                mkname = (ptr1 != 0);
                    748: 
1.1.1.4   root      749: #ifdef DEBUG_INFO
                    750: 
1.1.1.3   root      751:                tfmt = "Pexec(%d,%s,BP:%lx,%lx)";
                    752: 
                    753:                tail_offs = 0;
1.1.1.2   root      754: 
1.1.1.4   root      755: #endif
                    756: 
1.1.1.2   root      757:                break;
                    758: 
                    759:        case 206:
                    760: 
                    761: #if 0
                    762: 
                    763:        /* mkfree has no effect when overlay is set, since
                    764: 
                    765:         * in this case the "parent" and "child" are the same
                    766: 
                    767:         * process; since the "child" will run in memory that the
                    768: 
                    769:         * "parent" allocated, we don't want that memory freed!
                    770: 
                    771:         */
                    772: 
                    773:                mkfree = 1;
                    774: 
                    775: #endif
                    776: 
                    777:                /* fall through */
                    778: 
                    779:        case 204:
                    780: 
                    781:                mkgo = overlay = 1;
                    782: 
                    783:                mkname = (ptr1 != 0);
                    784: 
1.1.1.4   root      785: #ifdef DEBUG_INFO
                    786: 
1.1.1.3   root      787:                tfmt = "Pexec(%d,%s,BP:%lx,%lx)";
                    788: 
                    789:                tail_offs = 0;
1.1       root      790: 
1.1.1.4   root      791: #endif
                    792: 
1.1       root      793:                break;
                    794: 
                    795:        case 7:
                    796: 
                    797:                flags = (long)ptr1;     /* set program flags */
                    798: 
1.1.1.5   root      799:                if (((flags & F_PROTMODE) >> F_PROTSHIFT) > PROT_MAX_MODE) {
                    800: 
                    801:                    DEBUG (("Pexec: invalid protection mode changed to private"));
                    802: 
                    803:                    flags = (flags & ~F_PROTMODE) | F_PROT_P;
                    804: 
                    805:                }
                    806: 
1.1.1.6 ! root      807: #ifndef MULTITOS
        !           808: 
        !           809:                if ((flags & F_PROTMODE) == 0 && curproc->base == gem_base)
        !           810: 
        !           811:                  {
        !           812: 
        !           813:                    flags |= F_PROT_G;
        !           814: 
        !           815:                    TRACE (("p_exec: AES special"));
        !           816: 
        !           817:                  }
        !           818: 
        !           819: #endif
        !           820: 
1.1       root      821:                                        /* and fall through */
                    822: 
                    823:        case 5:
                    824: 
                    825:                mkbase = 1;
                    826: 
1.1.1.4   root      827: #ifdef DEBUG_INFO
                    828: 
1.1.1.3   root      829:                tfmt = "Pexec(%d,%lx,%s,%lx)";
                    830: 
                    831:                tail_offs = 0;
1.1       root      832: 
1.1.1.4   root      833: #endif
                    834: 
1.1       root      835:                break;
                    836: 
                    837:        default:
                    838: 
1.1.1.3   root      839:                DEBUG(("Pexec(%d,%lx,%lx,%lx): bad mode",mode,ptr1,ptr2,ptr3));
1.1       root      840: 
                    841:                return EINVFN;
                    842: 
                    843:        }
                    844: 
                    845: 
                    846: 
1.1.1.3   root      847:        TRACE((tfmt,mode,ptr1,(char *)ptr2+tail_offs,ptr3));
                    848: 
                    849: 
                    850: 
                    851: /* Pexec with mode 0x8000 indicates tracing should be active */
                    852: 
1.1.1.2   root      853:        ptrace = (!mkwait && (mode & 0x8000));
                    854: 
                    855: 
                    856: 
1.1       root      857: /* in most cases, we'll want a process struct to exist,
                    858: 
                    859:  * so make sure one is around. Note that we must be
                    860: 
                    861:  * careful to free it later!
                    862: 
                    863:  */
                    864: 
                    865: 
                    866: 
1.1.1.3   root      867: TRACE(("Checking for memory for new PROC structure"));
                    868: 
1.1       root      869:        p = 0;
                    870: 
                    871:        if (!overlay) {
                    872: 
                    873:                p = new_proc();
                    874: 
                    875:                if (!p) {
                    876: 
1.1.1.2   root      877:                        DEBUG(("Pexec: couldn't get a PROC struct"));
1.1       root      878: 
                    879:                        return ENSMEM;
                    880: 
                    881:                }
                    882: 
                    883:        }
                    884: 
                    885: 
                    886: 
1.1.1.3   root      887: TRACE(("creating environment"));
                    888: 
1.1       root      889: 
                    890: 
                    891:        if (mkload || mkbase) {
                    892: 
1.1.1.4   root      893:                env = create_env((char *)ptr3, flags);
1.1       root      894: 
                    895:                if (!env) {
                    896: 
1.1.1.2   root      897:                        DEBUG(("Pexec: unable to create environment"));
1.1       root      898: 
                    899:                        if (p) dispose_proc(p);
                    900: 
                    901:                        return ENSMEM;
                    902: 
                    903:                }
                    904: 
                    905:        }
                    906: 
                    907: 
                    908: 
1.1.1.3   root      909: TRACE(("creating base page"));
                    910: 
                    911: 
                    912: 
1.1       root      913:        if (mkbase) {
                    914: 
1.1.1.6 ! root      915:                base = create_base((char *)ptr2, env, flags, 0L, 0L, 0L, 0L, 0L, 0L);
1.1       root      916: 
                    917:                if (!base) {
                    918: 
1.1.1.2   root      919:                        DEBUG(("Pexec: unable to create basepage"));
1.1       root      920: 
                    921:                        detach_region(curproc, env);
                    922: 
                    923:                        if (p) dispose_proc(p);
                    924: 
                    925:                        return ENSMEM;
                    926: 
                    927:                }
                    928: 
1.1.1.3   root      929: TRACELOW(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
1.1.1.2   root      930: 
1.1       root      931:        }
                    932: 
                    933:        else if (mkload) {
                    934: 
1.1.1.6 ! root      935:                char cbuf[128], *tail = ptr2;
        !           936: 
        !           937:                if (overlay) {
        !           938: 
        !           939:                        static char fbuf[PATH_MAX];
1.1.1.2   root      940: 
1.1.1.6 ! root      941:                        cbuf[127] = 0;
        !           942: 
        !           943:                        ptr1 = strncpy (fbuf, ptr1, PATH_MAX-2);
        !           944: 
        !           945:                        tail = strncpy (cbuf, ptr2, 127);
        !           946: 
        !           947:                }
        !           948: 
        !           949: #if 0
        !           950: 
        !           951:                base = load_region((char *)ptr1, env, (char *)tail,
        !           952: 
        !           953:                        &xattr, &text, &flags, 0);
        !           954: 
        !           955: #else
        !           956: 
        !           957:                base = load_region((char *)ptr1, env, (char *)tail,
        !           958: 
        !           959:                        &xattr, &text, &flags, overlay);
        !           960: 
        !           961: #endif
1.1       root      962: 
                    963:                if (!base) {
                    964: 
1.1.1.2   root      965:                        DEBUG(("Pexec: load_region failed"));
1.1       root      966: 
                    967:                        detach_region(curproc, env);
                    968: 
                    969:                        if (p) dispose_proc(p);
                    970: 
                    971:                        return mint_errno;
                    972: 
                    973:                }
                    974: 
1.1.1.2   root      975: TRACE(("Pexec: basepage region(%lx) is %ld bytes at %lx", base, base->len, base->loc));
                    976: 
1.1       root      977:        }
                    978: 
1.1.1.2   root      979:        else {  /* mode == 4,6,104,106,204, or 206 -- just go */
1.1       root      980: 
                    981:                base = addr2mem((virtaddr)ptr2);
                    982: 
                    983:                if (base)
                    984: 
                    985:                        env = addr2mem(*(void **)(base->loc + 0x2c));
                    986: 
                    987:                else
                    988: 
                    989:                        env = 0;
                    990: 
                    991:                if (!env) {
                    992: 
1.1.1.4   root      993:                        DEBUG(("Pexec: memory not owned by parent"));
                    994: 
1.1       root      995:                        if (p) dispose_proc(p);
                    996: 
                    997:                        return EIMBA;
                    998: 
                    999:                }
                   1000: 
1.1.1.4   root     1001: #if 0
                   1002: 
                   1003:       /* make sure that the PC we are about to use is in a region which is
                   1004: 
                   1005:        * attached to the process; this is most commonly a problem for
                   1006: 
                   1007:        * shared text segment programs.
                   1008: 
                   1009:        * BUG: we should verify that the PC is in a region to which the
                   1010: 
                   1011:        * child process should legitimately have access.
                   1012: 
                   1013:        */
                   1014: 
                   1015:               text = addr2region(((BASEPAGE *)base->loc)->p_tbase);
                   1016: 
                   1017:               if (text == base) {
                   1018: 
                   1019:               /* text segment is part of base region */
                   1020: 
                   1021:                       text = NULL;
                   1022: 
                   1023:               }
                   1024: 
                   1025: #endif
                   1026: 
1.1       root     1027:        }
                   1028: 
                   1029: 
                   1030: 
                   1031: /* make a local copy of the name, in case we are overlaying the current
                   1032: 
                   1033:  * process
                   1034: 
                   1035:  */
                   1036: 
                   1037:        if (mkname) {
                   1038: 
                   1039:                lastslash = 0;
                   1040: 
                   1041:                newname = ptr1;
                   1042: 
                   1043:                while (*newname) {
                   1044: 
                   1045:                        if (*newname == '\\' || *newname == '/')
                   1046: 
                   1047:                                lastslash = newname;
                   1048: 
                   1049:                        ++newname;
                   1050: 
                   1051:                }
                   1052: 
                   1053:                if (!lastslash)
                   1054: 
                   1055:                        lastslash = ptr1;
                   1056: 
                   1057:                else
                   1058: 
                   1059:                        lastslash++;
                   1060: 
                   1061: 
                   1062: 
                   1063:                i = 0; newname = localname;
                   1064: 
                   1065:                while (i++ < PNAMSIZ) {
                   1066: 
                   1067:                        if (*lastslash == '.' || *lastslash == 0) {
                   1068: 
                   1069:                                *newname = 0; break;
                   1070: 
                   1071:                        }
                   1072: 
                   1073:                        else
                   1074: 
                   1075:                                *newname++ = *lastslash++;
                   1076: 
                   1077:                }
                   1078: 
                   1079:                *newname = 0;
                   1080: 
                   1081:        }
                   1082: 
                   1083: 
                   1084: 
1.1.1.3   root     1085:        if (mkload || mkbase) {
                   1086: 
                   1087:            /*
                   1088: 
                   1089:             * Now that the file's loaded, flags is set to the prgflags
                   1090: 
                   1091:             * for the file.  In the case of mkbase it's been right all along.
                   1092: 
                   1093:             * Here's where we change the protection on the environment to
                   1094: 
                   1095:             * match those flags.
                   1096: 
                   1097:             */
                   1098: 
                   1099:            mark_region(env,(short)((flags & F_PROTMODE) >> F_PROTSHIFT));
                   1100: 
                   1101:        }
                   1102: 
                   1103: 
                   1104: 
1.1       root     1105:        if (p) {
                   1106: 
                   1107:        /* free the PROC struct so fork_proc will succeed */
                   1108: 
1.1.1.3   root     1109:        /* FIXME: it would be much better to pass the PROC as a parameter
                   1110: 
                   1111:         * to fork_proc!!
                   1112: 
                   1113:         */
                   1114: 
1.1       root     1115:                dispose_proc(p);
                   1116: 
                   1117:                p = 0;
                   1118: 
                   1119:        }
                   1120: 
                   1121: 
                   1122: 
                   1123:        if (mkgo) {
                   1124: 
                   1125:                BASEPAGE *b;
                   1126: 
                   1127: 
                   1128: 
1.1.1.3   root     1129:        /* tell the child who the parent was */
                   1130: 
                   1131:                b = (BASEPAGE *)base->loc;
                   1132: 
                   1133: 
                   1134: 
1.1       root     1135:                if (overlay) {
                   1136: 
1.1.1.3   root     1137:                        b->p_parent = curproc->base->p_parent;
                   1138: 
1.1       root     1139:                        p = curproc;
                   1140: 
                   1141:                /* make sure that exec_region doesn't free the base and env */
                   1142: 
                   1143:                        base->links++;
                   1144: 
                   1145:                        env->links++;
                   1146: 
1.1.1.2   root     1147:                        if (text) text->links++;
                   1148: 
1.1       root     1149:                }
                   1150: 
                   1151:                else {
                   1152: 
1.1.1.3   root     1153:                        b->p_parent = curproc->base;
                   1154: 
1.1       root     1155:                        p = fork_proc();
                   1156: 
                   1157:                }
                   1158: 
                   1159:                if (!p) {
                   1160: 
                   1161:                        if (mkbase) {
                   1162: 
                   1163:                                detach_region(curproc, base);
                   1164: 
                   1165:                                detach_region(curproc, env);
                   1166: 
1.1.1.2   root     1167:                                if (text) detach_region(curproc, text);
                   1168: 
1.1       root     1169:                        }
                   1170: 
                   1171:                        return mint_errno;
                   1172: 
                   1173:                }
                   1174: 
1.1.1.5   root     1175: 
                   1176: 
                   1177:        /* jr: add Pexec information to PROC struct */
                   1178: 
                   1179:                strncpy(p->cmdlin, b->p_cmdlin, 128);
                   1180: 
                   1181:                p->fname[0] = 0;
                   1182: 
                   1183:                if (mkload) {
                   1184: 
                   1185:                        char tmp[PATH_MAX];
                   1186: 
                   1187:                        char *source = ptr1;
                   1188: 
                   1189:                        tmp[1] = ':';
                   1190: 
                   1191:                        if (source[1] == ':') {
                   1192: 
                   1193:                                tmp[0] = source[0];
                   1194: 
                   1195:                                source += 2;
                   1196: 
                   1197:                        } else
                   1198: 
                   1199:                                tmp[0] = 'A' + curproc->curdrv;
                   1200: 
                   1201:                        if (DIRSEP(source[0]))  /* absolute path? */
                   1202: 
                   1203:                        {
                   1204: 
                   1205:                                strncpy (&tmp[2], &source[0], PATH_MAX-2);
                   1206: 
                   1207:                                strcpy (p->fname, tmp);
                   1208: 
                   1209:                        } else {
                   1210: 
                   1211:                                if (! d_getcwd (&tmp[2], tmp[0] - 'A' + 1, PATH_MAX - 2))
                   1212: 
                   1213:                                        ksprintf (p->fname, "%s\\%s", tmp, source);
                   1214: 
                   1215:                        }
                   1216: 
                   1217:                }
                   1218: 
                   1219: 
                   1220: 
1.1.1.2   root     1221:                if (ptrace)
                   1222: 
                   1223:                        p->ptracer = pid2proc(p->ppid);
                   1224: 
                   1225: 
                   1226: 
                   1227:        /* Even though the file system won't allow unauthorized access
1.1       root     1228: 
1.1.1.2   root     1229:         * to setuid/setgid programs, it's better to err on the side of
1.1       root     1230: 
1.1.1.2   root     1231:         * caution and forbid them to be traced (since the parent can arrange
                   1232: 
                   1233:         * to share the child's address space, not all accesses need to
                   1234: 
1.1.1.3   root     1235:         * go through the file system.)
1.1.1.2   root     1236: 
                   1237:         */
                   1238: 
                   1239:                if (mkload && mkgo && !p->ptracer) {    /* setuid/setgid is OK */
1.1       root     1240: 
                   1241:                        if (xattr.mode & S_ISUID)
                   1242: 
                   1243:                                p->euid = xattr.uid;
                   1244: 
                   1245:                        if (xattr.mode & S_ISGID)
                   1246: 
                   1247:                                p->egid = xattr.gid;
                   1248: 
                   1249:                }
                   1250: 
1.1.1.3   root     1251:        /* exec_region frees the memory attached to p; that's always what
1.1       root     1252: 
1.1.1.3   root     1253:         * we want, since fork_proc duplicates the memory, and since
1.1       root     1254: 
1.1.1.3   root     1255:         * if we didn't call fork_proc then we're overlaying.
1.1       root     1256: 
1.1.1.3   root     1257:         * NOTE: after this call, we may not be able to access the
1.1.1.2   root     1258: 
1.1.1.3   root     1259:         * original address space that the Pexec was taking place in
1.1       root     1260: 
1.1.1.3   root     1261:         * (if this is an overlaid Pexec, we just freed that memory).
1.1       root     1262: 
1.1.1.3   root     1263:         */
1.1       root     1264: 
1.1.1.3   root     1265:                (void)exec_region(p, base, thread);
                   1266: 
                   1267:                attach_region(p, env);
1.1       root     1268: 
1.1.1.3   root     1269:                attach_region(p, base);
1.1       root     1270: 
1.1.1.3   root     1271:                if (text) attach_region(p, text);
1.1       root     1272: 
                   1273: 
                   1274: 
                   1275:                if (mkname) {
                   1276: 
                   1277:        /* interesting coincidence -- if a process needs a name, it usually
                   1278: 
                   1279:         * needs to have its domain reset to DOM_TOS. Doing it this way
                   1280: 
                   1281:         * (instead of doing it in exec_region) means that Pexec(4,...)
                   1282: 
                   1283:         * can be used to create new threads of execution which retain
                   1284: 
                   1285:         * the same domain.
                   1286: 
                   1287:         */
                   1288: 
                   1289:                        if (!thread)
                   1290: 
                   1291:                                p->domain = DOM_TOS;
                   1292: 
                   1293: 
                   1294: 
                   1295:        /* put in the new process name we saved above */
                   1296: 
                   1297:                        strcpy(p->name, localname);
                   1298: 
                   1299:                }
                   1300: 
                   1301: 
                   1302: 
1.1.1.2   root     1303:        /* turn on tracing for the new process */
                   1304: 
                   1305:                if (p->ptracer)
                   1306: 
                   1307:                        p->ctxt[CURRENT].ptrace = 1;
                   1308: 
                   1309: 
                   1310: 
1.1       root     1311:        /* set the time/date stamp of u:\proc */
                   1312: 
                   1313:                proctime = timestamp;
                   1314: 
                   1315:                procdate = datestamp;
                   1316: 
                   1317: 
                   1318: 
                   1319:                if (overlay) {
                   1320: 
                   1321:                        /* correct for temporary increase in links (see above) */
                   1322: 
                   1323:                        base->links--;
                   1324: 
                   1325:                        env->links--;
                   1326: 
1.1.1.2   root     1327:                        if (text) text->links--;
                   1328: 
1.1       root     1329:                        /* let our parent run, if it Vfork'd() */
                   1330: 
                   1331:                        if ( (p = pid2proc(curproc->ppid)) != 0 ) {
                   1332: 
                   1333:                                if (p->wait_q == WAIT_Q && 
                   1334: 
                   1335:                                    p->wait_cond == (long)curproc) {
                   1336: 
1.1.1.3   root     1337:                                        short sr = spl7();
                   1338: 
1.1       root     1339:                                        rm_q(WAIT_Q, p);
                   1340: 
                   1341:                                        add_q(READY_Q, p);
                   1342: 
1.1.1.3   root     1343:                                        spl(sr);
                   1344: 
1.1       root     1345:                                }
                   1346: 
                   1347:                        }
                   1348: 
                   1349: 
                   1350: 
                   1351:                /* OK, let's run our new code */
                   1352: 
1.1.1.6 ! root     1353:                /* we guarantee ourselves at least 3 timeslices to do an Mshrink */
1.1       root     1354: 
                   1355:                        assert(curproc->magic == CTXT_MAGIC);
                   1356: 
1.1.1.6 ! root     1357:                        fresh_slices(3);
1.1       root     1358: 
                   1359:                        leave_kernel();
                   1360: 
1.1.1.3   root     1361:                        change_context(&(curproc->ctxt[CURRENT]));
1.1       root     1362: 
                   1363:                }
                   1364: 
                   1365:                else {
                   1366: 
                   1367:        /* we want this process to run ASAP */
                   1368: 
                   1369:        /* so we temporarily give it high priority and put it first on the
                   1370: 
                   1371:         * run queue
                   1372: 
                   1373:         */
                   1374: 
1.1.1.6 ! root     1375:                        run_next(p, 3);
1.1       root     1376: 
                   1377:                }
                   1378: 
                   1379:        }
                   1380: 
                   1381: 
                   1382: 
                   1383:        if (mkfree) {
                   1384: 
                   1385:                detach_region(curproc, base);
                   1386: 
                   1387:                detach_region(curproc, env);
                   1388: 
1.1.1.2   root     1389:                if (text) detach_region(curproc, text);
                   1390: 
1.1       root     1391:        }
                   1392: 
                   1393: 
                   1394: 
                   1395:        if (mkwait) {
                   1396: 
                   1397:                long oldsigint, oldsigquit;
                   1398: 
                   1399: 
                   1400: 
                   1401:                oldsigint = curproc->sighandle[SIGINT];
                   1402: 
                   1403:                oldsigquit = curproc->sighandle[SIGQUIT];
                   1404: 
                   1405:                curproc->sighandle[SIGINT] =
                   1406: 
                   1407:                         curproc->sighandle[SIGQUIT] = SIG_IGN;
                   1408: 
                   1409: 
                   1410: 
1.1.1.3   root     1411:                newpid = p->pid;
1.1       root     1412: 
                   1413:                for(;;) {
                   1414: 
                   1415:                        r = p_wait3(0, (long *)0);
                   1416: 
                   1417:                        if (r < 0) {
                   1418: 
                   1419:                                ALERT("p_exec: wait error");
                   1420: 
                   1421:                                return EINTRN;
                   1422: 
                   1423:                        }
                   1424: 
1.1.1.3   root     1425:                        if ( newpid == ((r&0xffff0000L) >> 16) ) {
1.1       root     1426: 
1.1.1.3   root     1427:                                TRACE(("leaving Pexec; child return code %ld", r));
1.1       root     1428: 
1.1.1.2   root     1429:                                r = r & 0x0000ffffL;
1.1       root     1430: 
                   1431:                                break;
                   1432: 
                   1433:                        }
                   1434: 
                   1435:                        if (curproc->pid)
                   1436: 
1.1.1.2   root     1437:                                DEBUG(("Pexec: wrong child found"));
1.1       root     1438: 
                   1439:                }
                   1440: 
                   1441:                curproc->sighandle[SIGINT] = oldsigint;
                   1442: 
                   1443:                curproc->sighandle[SIGQUIT] = oldsigquit;
                   1444: 
                   1445:                return r;
                   1446: 
                   1447:        }
                   1448: 
                   1449:        else if (mkgo) {
                   1450: 
1.1.1.3   root     1451:        /* warning: after the yield() the "p" structure may not exist any more
                   1452: 
                   1453:         * (if the child exits right away)
                   1454: 
                   1455:         */
                   1456: 
                   1457:                newpid = p->pid;
                   1458: 
1.1       root     1459:                yield();        /* let the new process run */
                   1460: 
1.1.1.3   root     1461:                return newpid;
1.1       root     1462: 
                   1463:        } else {
                   1464: 
1.1.1.6 ! root     1465:                /* guarantee ourselves at least 3 timeslices to do an Mshrink */
        !          1466: 
        !          1467:                fresh_slices(3);
        !          1468: 
1.1.1.2   root     1469:                TRACE(("leaving Pexec with basepage address %lx", base->loc));
1.1       root     1470: 
                   1471:                return base->loc;
                   1472: 
                   1473:        }
                   1474: 
                   1475: }
                   1476: 
                   1477: 
                   1478: 
                   1479: /*
                   1480: 
                   1481:  * terminate a process, with return code "code". If que == ZOMBIE_Q, free
                   1482: 
                   1483:  * all resources attached to the child; if que == TSR_Q, free everything
                   1484: 
1.1.1.2   root     1485:  * but memory.
                   1486: 
                   1487:  * NOTE: terminate() should be called only when the process is to be
                   1488: 
                   1489:  * "terminated with extreme prejuidice". Most times, p_term or p_termres
                   1490: 
                   1491:  * are the functions to use, since they allow the user to do some cleaning
                   1492: 
                   1493:  * up, etc.
1.1       root     1494: 
                   1495:  */
                   1496: 
                   1497: 
                   1498: 
                   1499: long
                   1500: 
                   1501: terminate(code, que)
                   1502: 
                   1503:        int code, que;
                   1504: 
                   1505: {
                   1506: 
                   1507:        extern PROC *dlockproc[];       /* in dosdir.c */
                   1508: 
                   1509:        PROC *p;
                   1510: 
                   1511:        FILEPTR *fp;
                   1512: 
                   1513:        MEMREGION *m;
                   1514: 
1.1.1.3   root     1515:        MEMREGION **hold_mem;
                   1516: 
                   1517:        virtaddr *hold_addr;
                   1518: 
1.1       root     1519:        int  i, wakemint = 0;
                   1520: 
1.1.1.3   root     1521:        DIR *dirh, *nexth;
                   1522: 
1.1       root     1523:        extern short bconbsiz;  /* in bios.c */
                   1524: 
                   1525: 
                   1526: 
                   1527:        if (bconbsiz)
                   1528: 
                   1529:                (void) bflush();
                   1530: 
                   1531: 
                   1532: 
                   1533:        assert(que == ZOMBIE_Q || que == TSR_Q);
                   1534: 
                   1535: 
                   1536: 
                   1537:        if (curproc->pid == 0) {
                   1538: 
                   1539:                FATAL("attempt to terminate MiNT");
                   1540: 
                   1541:        }
                   1542: 
                   1543: 
                   1544: 
1.1.1.6 ! root     1545: /* cancel all user-specified interrupt signals */
        !          1546: 
        !          1547:        cancelsigintrs();
        !          1548: 
1.1       root     1549: /* cancel all pending timeouts for this process */
                   1550: 
                   1551:        cancelalltimeouts();
                   1552: 
                   1553: /* cancel alarm clock */
                   1554: 
                   1555:        curproc->alarmtim = 0;
                   1556: 
                   1557: 
                   1558: 
                   1559: /* release any drives locked by Dlock */
                   1560: 
                   1561:        for(i = 0; i < NUM_DRIVES; i++) {
                   1562: 
                   1563:                if (dlockproc[i] == curproc) {
                   1564: 
                   1565:                        dlockproc[i] = 0;
                   1566: 
                   1567:                        changedrv(i);
                   1568: 
                   1569:                }
                   1570: 
                   1571:        }
                   1572: 
                   1573: 
                   1574: 
1.1.1.6 ! root     1575: #if 0
        !          1576: 
1.1       root     1577: /* release the controlling terminal, if we're a process group leader */
                   1578: 
                   1579:        fp = curproc->handle[-1];
                   1580: 
                   1581:        if (fp && is_terminal(fp) && curproc->pgrp == curproc->pid) {
                   1582: 
                   1583:                struct tty *tty = (struct tty *)fp->devinfo;
                   1584: 
                   1585:                if (curproc->pgrp == tty->pgrp)
                   1586: 
                   1587:                        tty->pgrp = 0;
                   1588: 
                   1589:        }
                   1590: 
1.1.1.6 ! root     1591: #else
        !          1592: 
        !          1593: #if 0
        !          1594: 
        !          1595: /* release the controlling terminal, if we're the last member of this pgroup */
        !          1596: 
        !          1597:        fp = curproc->control;
        !          1598: 
        !          1599:        if (fp && is_terminal(fp)) {
        !          1600: 
        !          1601:                struct tty *tty = (struct tty *)fp->devinfo;
        !          1602: 
        !          1603:                int pgrp = curproc->pgrp;
1.1       root     1604: 
                   1605: 
1.1.1.6 ! root     1606: 
        !          1607:                if (pgrp == tty->pgrp) {
        !          1608: 
        !          1609:                        PROC *p;
        !          1610: 
        !          1611:                        FILEPTR *pfp;
        !          1612: 
        !          1613: 
        !          1614: 
        !          1615:                        if (tty->use_cnt > 1) {
        !          1616: 
        !          1617:                                for (p = proclist; p; p = p->gl_next) {
        !          1618: 
        !          1619:                                        if (p->pgrp == pgrp && p != curproc &&
        !          1620: 
        !          1621:                                            (0 != (pfp = p->control)) &&
        !          1622: 
        !          1623:                                            pfp->fc.index == fp->fc.index &&
        !          1624: 
        !          1625:                                            pfp->fc.dev == fp->fc.dev)
        !          1626: 
        !          1627:                                                goto found;
        !          1628: 
        !          1629:                                }
        !          1630: 
        !          1631:                        } else {
        !          1632: 
        !          1633:                                for (p = proclist; p; p = p->gl_next) {
        !          1634: 
        !          1635:                                        if (p->pgrp == pgrp && p != curproc &&
        !          1636: 
        !          1637:                                            p->control == fp)
        !          1638: 
        !          1639:                                                goto found;
        !          1640: 
        !          1641:                                }
        !          1642: 
        !          1643:                        }
        !          1644: 
        !          1645:                        tty->pgrp = 0;
        !          1646: 
        !          1647:                }
        !          1648: 
        !          1649: found:
        !          1650: 
        !          1651:                ;
        !          1652: 
        !          1653:        }
        !          1654: 
        !          1655: #endif
        !          1656: 
        !          1657: #endif
        !          1658: 
        !          1659:        /* close all files */
1.1       root     1660: 
                   1661:        for (i = MIN_HANDLE; i < MAX_OPEN; i++) {
                   1662: 
1.1.1.2   root     1663:                if ((fp = curproc->handle[i]) != 0)
1.1       root     1664: 
                   1665:                        do_close(fp);
                   1666: 
                   1667:                curproc->handle[i] = 0;
                   1668: 
                   1669:        }
                   1670: 
1.1.1.6 ! root     1671:        /* close any unresolved Fsfirst/Fsnext directory searches */
1.1       root     1672: 
                   1673:        for (i = 0; i < NUM_SEARCH; i++) {
                   1674: 
                   1675:                if (curproc->srchdta[i]) {
                   1676: 
                   1677:                        DIR *dirh = &curproc->srchdir[i];
                   1678: 
                   1679:                        (*dirh->fc.fs->closedir)(dirh);
                   1680: 
1.1.1.3   root     1681:                        release_cookie(&dirh->fc);
                   1682: 
                   1683:                        dirh->fc.fs = 0;
                   1684: 
1.1       root     1685:                }
                   1686: 
                   1687:        }
                   1688: 
                   1689: 
                   1690: 
1.1.1.3   root     1691: /* close pending opendir/readdir searches */
                   1692: 
                   1693:        for (dirh = curproc->searches; dirh; ) {
                   1694: 
1.1.1.4   root     1695:                if (dirh->fc.fs) {
                   1696: 
                   1697:                        (*dirh->fc.fs->closedir)(dirh);
1.1.1.3   root     1698: 
1.1.1.4   root     1699:                        release_cookie(&dirh->fc);
1.1.1.3   root     1700: 
1.1.1.4   root     1701:                }
1.1.1.3   root     1702: 
                   1703:                nexth = dirh->next;
                   1704: 
                   1705:                kfree(dirh);
                   1706: 
                   1707:                dirh = nexth;
                   1708: 
                   1709:        }
                   1710: 
                   1711: 
                   1712: 
                   1713: /* release the directory cookies held by the process */
                   1714: 
                   1715:        for (i = 0; i < NUM_DRIVES; i++) {
                   1716: 
                   1717:                release_cookie(&curproc->curdir[i]);
                   1718: 
                   1719:                curproc->curdir[i].fs = 0;
                   1720: 
                   1721:                release_cookie(&curproc->root[i]);
                   1722: 
                   1723:                curproc->root[i].fs = 0;
                   1724: 
                   1725:        }
                   1726: 
                   1727: 
                   1728: 
1.1       root     1729: /* release all semaphores owned by this process */
                   1730: 
                   1731:        free_semaphores(curproc->pid);
                   1732: 
                   1733: 
                   1734: 
                   1735: /* free all memory */
                   1736: 
1.1.1.3   root     1737: /* if mflags & M_KEEP then attach it to process 0 */
                   1738: 
1.1       root     1739:        if (que == ZOMBIE_Q) {
                   1740: 
                   1741:                for (i = curproc->num_reg - 1; i >=0; i--) {
                   1742: 
                   1743:                        m = curproc->mem[i];
                   1744: 
                   1745:                        curproc->mem[i] = 0; curproc->addr[i] = 0;
                   1746: 
                   1747:                        if (m) {
                   1748: 
                   1749:                /* don't free specially allocated memory */
                   1750: 
1.1.1.6 ! root     1751:                                if ((m->mflags & M_KEEP) && (m->links <= 1)) {
1.1       root     1752: 
                   1753:                                        if (curproc != rootproc)
                   1754: 
                   1755:                                            attach_region(rootproc, m);
                   1756: 
                   1757:                                }
                   1758: 
1.1.1.6 ! root     1759: /* Leave shared text regions in memory, get_region will reclaim them if
        !          1760: 
        !          1761:    memory runs low. Assume that we will never have 65535 processes
        !          1762: 
        !          1763:    using a particular memory region. */
        !          1764: 
1.1       root     1765:                                m->links--;
                   1766: 
                   1767:                                if (m->links == 0) {
                   1768: 
1.1.1.6 ! root     1769:                                        if (m->mflags & M_SHTEXT_T)
        !          1770: 
        !          1771:                                                m->links = 0xffff;
        !          1772: 
        !          1773:                                        else
        !          1774: 
        !          1775:                                                free_region(m);
1.1       root     1776: 
                   1777:                                }
                   1778: 
                   1779:                        }
                   1780: 
                   1781:                }
                   1782: 
                   1783: 
                   1784: 
1.1.1.3   root     1785:                /*
                   1786: 
                   1787:                 * mark the mem & addr arrays as void so the memory
                   1788: 
                   1789:                 * protection code won't try to walk them. Do this before
                   1790: 
                   1791:                 * freeing them so we don't try to walk them when marking
                   1792: 
                   1793:                 * those pages themselves as free!
                   1794: 
                   1795:                 *
                   1796: 
                   1797:                 * Note: when a process terminates, the MMU root pointer
                   1798: 
                   1799:                 * still points to that process' page table, until the next
                   1800: 
                   1801:                 * process is dispatched.  This is OK, since the process'
                   1802: 
                   1803:                 * page table is in system memory, and it isn't going to be
                   1804: 
                   1805:                 * freed.  It is going to wind up on the free process list,
                   1806: 
                   1807:                 * though, after dispose_proc. This might be Not A Good
                   1808: 
                   1809:                 * Thing.
                   1810: 
                   1811:                 */
                   1812: 
                   1813: 
                   1814: 
                   1815:                hold_addr = curproc->addr;
                   1816: 
                   1817:                hold_mem = curproc->mem;
                   1818: 
                   1819: 
                   1820: 
                   1821:                curproc->mem = NULL;
                   1822: 
                   1823:                curproc->addr = NULL;
1.1       root     1824: 
                   1825:                curproc->num_reg = 0;
                   1826: 
1.1.1.3   root     1827: 
                   1828: 
                   1829:                kfree(hold_addr);
                   1830: 
                   1831:                kfree(hold_mem);
                   1832: 
1.1       root     1833:        }
                   1834: 
                   1835: /*     else
                   1836: 
                   1837:                 make TSR process non-swappable */
                   1838: 
                   1839: 
                   1840: 
                   1841: /*
                   1842: 
                   1843:  * make sure that any open files that refer to this process are
                   1844: 
                   1845:  * closed
                   1846: 
                   1847:  */
                   1848: 
1.1.1.5   root     1849:        changedrv(PROC_RDEV_BASE | curproc->pid);
1.1       root     1850: 
                   1851: 
                   1852: 
                   1853: /* find our parent (if parent not found, then use process 0 as parent
                   1854: 
                   1855:  * since that process is constantly in a wait loop)
                   1856: 
                   1857:  */
                   1858: 
                   1859: 
                   1860: 
                   1861:        p = pid2proc(curproc->ppid);
                   1862: 
                   1863:        if (!p) {
                   1864: 
1.1.1.2   root     1865:                TRACE(("terminate: parent not found"));
1.1       root     1866: 
                   1867:                p = pid2proc(0);
                   1868: 
                   1869:        }
                   1870: 
                   1871: 
                   1872: 
                   1873: /* NOTE: normally just post_sig is sufficient for sending a signal; but
                   1874: 
                   1875:  * in this particular case, we have to worry about processes that are
                   1876: 
                   1877:  * blocking all signals because they Vfork'd and are waiting for us to
                   1878: 
                   1879:  * finish (which is indicated by a wait_cond matching our PROC
                   1880: 
                   1881:  * structure), and also processes that are ignoring SIGCHLD but are
                   1882: 
                   1883:  * waiting for us.
                   1884: 
                   1885:  */
                   1886: 
                   1887:        if (p->wait_q == WAIT_Q && 
                   1888: 
1.1.1.2   root     1889:            (p->wait_cond == (long)curproc || p->wait_cond == (long)p_waitpid) ) {
1.1       root     1890: 
1.1.1.3   root     1891:                short sr = spl7();
                   1892: 
1.1.1.2   root     1893:                TRACE(("terminate: waking up parent"));
1.1       root     1894: 
                   1895:                rm_q(WAIT_Q, p);
                   1896: 
                   1897:                add_q(READY_Q, p);
                   1898: 
1.1.1.3   root     1899:                spl(sr);
                   1900: 
1.1       root     1901:        }
                   1902: 
1.1.1.2   root     1903:        if (curproc->ptracer && curproc->ptracer != p) {
                   1904: 
                   1905:                /* BUG: should we ensure curproc->ptracer is awake ? */
                   1906: 
                   1907:                post_sig(curproc->ptracer, SIGCHLD);    /* tell tracing process */
                   1908: 
                   1909:        }
                   1910: 
1.1       root     1911:        post_sig(p, SIGCHLD);           /* inform of process termination */
                   1912: 
                   1913: 
                   1914: 
1.1.1.2   root     1915: /* find our children, and orphan them
                   1916: 
                   1917:  * also, check for processes we were tracing, and
                   1918: 
                   1919:  * cancel the trace
                   1920: 
                   1921:  */
1.1       root     1922: 
                   1923:        i = curproc->pid;
                   1924: 
                   1925:        for (p = proclist; p; p = p->gl_next) {
                   1926: 
                   1927:                if (p->ppid == i) {
                   1928: 
                   1929:                        p->ppid = 0;    /* have the system adopt it */
                   1930: 
                   1931:                        if (p->wait_q == ZOMBIE_Q) 
                   1932: 
                   1933:                                wakemint = 1;   /* we need to wake proc. 0 */
                   1934: 
                   1935:                }
                   1936: 
1.1.1.2   root     1937:                if (p->ptracer == curproc) {
                   1938: 
                   1939:                        p->ptracer = 0;
                   1940: 
                   1941: /*
                   1942: 
                   1943:  * `FEATURE': we terminate traced processes when the tracer terminates.
                   1944: 
                   1945:  * It might plausibly be argued that it would be better to let them
                   1946: 
                   1947:  * continue, to let some (new) tracer take them over. On the other hand,
                   1948: 
                   1949:  * if the tracer terminated normally, it should have used Fcntl(PTRACESFLAGS)
                   1950: 
                   1951:  * to reset the trace nicely, so something must be wrong for us to have
                   1952: 
                   1953:  * reached here.
                   1954: 
                   1955:  */
                   1956: 
                   1957:                        post_sig(p, SIGTERM);   /* arrange for termination */
                   1958: 
                   1959:                }
                   1960: 
1.1       root     1961:        }
                   1962: 
                   1963: 
                   1964: 
                   1965:        if (wakemint) {
                   1966: 
                   1967:                p = rootproc;           /* pid 0 */
                   1968: 
                   1969:                if (p->wait_q == WAIT_Q) {
                   1970: 
1.1.1.3   root     1971:                        short sr = spl7();
                   1972: 
1.1       root     1973:                        rm_q(WAIT_Q, p);
                   1974: 
                   1975:                        add_q(READY_Q, p);
                   1976: 
1.1.1.3   root     1977:                        spl(sr);
                   1978: 
1.1       root     1979:                }
                   1980: 
                   1981:        }
                   1982: 
                   1983: 
                   1984: 
                   1985: /* this makes sure that our children are inherited by the system;
                   1986: 
                   1987:  * plus, it may help avoid problems if somehow a signal gets
                   1988: 
                   1989:  * through to us
                   1990: 
                   1991:  */
                   1992: 
                   1993:        for(i = 0; i < NSIG; i++)
                   1994: 
                   1995:                curproc->sighandle[i] = SIG_IGN;
                   1996: 
                   1997: 
                   1998: 
                   1999: /* finally, reset the time/date stamp for u:\proc */
                   2000: 
                   2001:        proctime = timestamp;
                   2002: 
                   2003:        procdate = datestamp;
                   2004: 
                   2005: 
                   2006: 
1.1.1.2   root     2007:        sleep(que, (long)(unsigned)code);
1.1       root     2008: 
                   2009: 
                   2010: 
1.1.1.2   root     2011: /* we shouldn't ever get here */
1.1       root     2012: 
1.1.1.2   root     2013:        FATAL("terminate: sleep woke up when it shouldn't have");
1.1       root     2014: 
1.1.1.2   root     2015:        return 0;
1.1       root     2016: 
                   2017: }
                   2018: 
                   2019: 
                   2020: 
                   2021: /*
                   2022: 
                   2023:  * TOS process termination entry points:
                   2024: 
1.1.1.2   root     2025:  * p_term terminates the process, freeing its memory
1.1       root     2026: 
                   2027:  * p_termres lets the process hang around resident in memory, after
                   2028: 
                   2029:  * shrinking its transient program area to "save" bytes
                   2030: 
                   2031:  */
                   2032: 
                   2033: 
                   2034: 
1.1.1.2   root     2035: long ARGS_ON_STACK
1.1       root     2036: 
                   2037: p_term(code)
                   2038: 
                   2039:        int code;
                   2040: 
                   2041: {
                   2042: 
                   2043:        CONTEXT *syscall;
                   2044: 
                   2045: 
                   2046: 
1.1.1.2   root     2047:        TRACE(("Pterm(%d)", code));
1.1       root     2048: 
                   2049: /* call the process termination vector */
                   2050: 
                   2051:        syscall = &curproc->ctxt[SYSCALL];
                   2052: 
                   2053: 
                   2054: 
                   2055:        if (syscall->term_vec != (long)rts) {
                   2056: 
1.1.1.2   root     2057:                TRACE(("term_vec: user has something to do"));
1.1       root     2058: 
                   2059: /*
                   2060: 
                   2061:  * we handle the termination vector just like Supexec(), by
                   2062: 
                   2063:  * sending signal 0 to the process. See supexec() in xbios.c for details.
                   2064: 
1.1.1.2   root     2065:  * Note that we _always_ want to unwind the signal stack, and setting
1.1       root     2066: 
1.1.1.2   root     2067:  * bit 1 of curproc->sigmask tells handle_sig to do that -- see signal.c.
1.1       root     2068: 
                   2069:  */
                   2070: 
                   2071:                curproc->sigmask |= 1L;
                   2072: 
                   2073:                (void)supexec((Func)syscall->term_vec, 0L, 0L, 0L, 0L, 
                   2074: 
                   2075:                                (long)code);
                   2076: 
                   2077: /*
                   2078: 
                   2079:  * if we arrive here, continue with the termination...
                   2080: 
                   2081:  */
                   2082: 
                   2083:        }
                   2084: 
                   2085:        return terminate(code, ZOMBIE_Q);
                   2086: 
                   2087: }
                   2088: 
                   2089: 
                   2090: 
1.1.1.2   root     2091: long ARGS_ON_STACK
1.1       root     2092: 
                   2093: p_term0()
                   2094: 
                   2095: {
                   2096: 
                   2097:        return p_term(0);
                   2098: 
                   2099: }
                   2100: 
                   2101: 
                   2102: 
1.1.1.2   root     2103: long ARGS_ON_STACK
1.1       root     2104: 
                   2105: p_termres(save, code)
                   2106: 
                   2107:        long save;
                   2108: 
                   2109:        int code;
                   2110: 
                   2111: {
                   2112: 
                   2113:        MEMREGION *m;
                   2114: 
1.1.1.3   root     2115:        int i;
                   2116: 
1.1       root     2117: 
                   2118: 
1.1.1.2   root     2119:        TRACE(("Ptermres(%ld, %d)", save, code));
1.1       root     2120: 
                   2121:        m = curproc->mem[1];    /* should be the basepage (0 is env.) */
                   2122: 
                   2123:        if (m) {
                   2124: 
                   2125:                (void)shrink_region(m, save);
                   2126: 
                   2127:        }
                   2128: 
1.1.1.3   root     2129: /*
                   2130: 
                   2131:  * make all of the TSR's private memory globally accessible;
                   2132: 
                   2133:  * this means that more TSR's will "do the right thing"
                   2134: 
                   2135:  * without having to have prgflags set.
                   2136: 
                   2137:  */
                   2138: 
                   2139:        for (i = 0; i < curproc->num_reg; i++) {
                   2140: 
                   2141:                m = curproc->mem[i];
                   2142: 
                   2143:                if (m && m->links == 1) {       /* only the TSR is owner */
                   2144: 
                   2145:                        if (get_prot_mode(m) == PROT_P) {
                   2146: 
                   2147:                                mark_region(m, PROT_G);
                   2148: 
                   2149:                        }
                   2150: 
                   2151:                }
                   2152: 
                   2153:        }
                   2154: 
1.1       root     2155:        return terminate(code, TSR_Q);
                   2156: 
                   2157: }
                   2158: 
                   2159: 
                   2160: 
                   2161: /*
                   2162: 
                   2163:  * routine for waiting for children to die. Return has the pid of the
                   2164: 
                   2165:  * found child in the high word, and the child's exit code in
                   2166: 
                   2167:  * the low word. If no children exist, return "File Not Found".
                   2168: 
                   2169:  * If (nohang & 1) is nonzero, then return a 0 immediately if we have
                   2170: 
                   2171:  * no dead children but some living ones that we still have to wait
                   2172: 
                   2173:  * for. If (nohang & 2) is nonzero, then we return any stopped
                   2174: 
                   2175:  * children; otherwise, only children that have exited or are stopped
                   2176: 
                   2177:  * due to a trace trap are returned.
                   2178: 
                   2179:  * If "rusage" is non-zero and a child is found, put the child's
                   2180: 
                   2181:  * resource usage into it (currently only the user and system time are
                   2182: 
1.1.1.2   root     2183:  * sent back).
                   2184: 
                   2185:  * The pid argument specifies a set of child processes for which status
                   2186: 
                   2187:  * is requested:
                   2188: 
                   2189:  *     If pid is equal to -1, status is requested for any child process.
                   2190: 
                   2191:  *
                   2192: 
                   2193:  *     If pid is greater than zero, it specifies the process ID of a
                   2194: 
                   2195:  *     single child process for which status is requested.
                   2196: 
                   2197:  *
                   2198: 
                   2199:  *     If pid is equal to zero, status is requested for any child
                   2200: 
                   2201:  *     process whose process group ID is equal to that of the calling
                   2202: 
                   2203:  *     process.
                   2204: 
                   2205:  *
                   2206: 
                   2207:  *     If pid is less than -1, status is requested for any child process
                   2208: 
                   2209:  *     whose process group ID is equal to the absolute value of pid.
                   2210: 
                   2211:  *
                   2212: 
                   2213:  * Note this call is a real standard crosser... POSIX.1 doesn't have the
                   2214: 
                   2215:  * rusage stuff, BSD doesn't have the pid stuff; both are useful, so why
                   2216: 
                   2217:  * not have it all!
1.1       root     2218: 
                   2219:  */
                   2220: 
                   2221: 
                   2222: 
1.1.1.2   root     2223: long ARGS_ON_STACK
1.1       root     2224: 
1.1.1.2   root     2225: p_waitpid(pid, nohang, rusage)
                   2226: 
                   2227:        int pid;
1.1       root     2228: 
                   2229:        int nohang;
                   2230: 
                   2231:        long *rusage;
                   2232: 
                   2233: {
                   2234: 
                   2235:        long r;
                   2236: 
                   2237:        PROC *p, *q;
                   2238: 
                   2239:        int ourpid;
                   2240: 
                   2241:        int found;
                   2242: 
                   2243: 
                   2244: 
1.1.1.2   root     2245:        TRACE(("Pwaitpid(%d, %d, %lx)", pid, nohang, rusage));
1.1       root     2246: 
                   2247:        ourpid = curproc->pid;
                   2248: 
                   2249: 
                   2250: 
                   2251: /* if there are terminated children, clean up and return their info;
                   2252: 
                   2253:  * if there are children, but still running, wait for them;
                   2254: 
                   2255:  * if there are no children, return an error
                   2256: 
                   2257:  */
                   2258: 
                   2259: 
                   2260: 
                   2261:        do {
                   2262: 
                   2263: /* look for any children */
                   2264: 
                   2265:                found = 0;
                   2266: 
                   2267:                for (p = proclist; p; p = p->gl_next) {
                   2268: 
1.1.1.2   root     2269:                        if ((p->ppid == ourpid || p->ptracer == curproc) &&
                   2270: 
                   2271:                            (pid == -1 ||
                   2272: 
                   2273:                            (pid > 0 && pid == p->pid) ||
                   2274: 
                   2275:                            (pid == 0 && p->pgrp == ourpid) ||
                   2276: 
                   2277:                            (pid < -1 && p->pgrp == -pid))) {
1.1       root     2278: 
                   2279:                                found++;
                   2280: 
                   2281:                                if (p->wait_q == ZOMBIE_Q || p->wait_q == TSR_Q)
                   2282: 
                   2283:                                        break;
                   2284: 
                   2285: 
                   2286: 
                   2287: /* p->wait_cond == 0 if a stopped process has already been waited for */
                   2288: 
                   2289:                                if (p->wait_q == STOP_Q && p->wait_cond) {
                   2290: 
                   2291:                                    if ((nohang & 2) ||
                   2292: 
1.1.1.2   root     2293:                                        ((p->wait_cond&0x1f00) == (SIGTRAP<<8)))
1.1       root     2294: 
                   2295:                                            break;
                   2296: 
                   2297:                                }
                   2298: 
                   2299:                        }
                   2300: 
                   2301:                }
                   2302: 
                   2303:                if (!p) {
                   2304: 
                   2305:                        if (found) {
                   2306: 
                   2307:                                if (nohang & 1)
                   2308: 
                   2309:                                        return 0;
                   2310: 
                   2311:                                if (curproc->pid)
                   2312: 
1.1.1.2   root     2313:                                        TRACE(("Pwaitpid: going to sleep"));
1.1       root     2314: 
1.1.1.2   root     2315:                                sleep(WAIT_Q, (long)p_waitpid);
1.1       root     2316: 
                   2317:                        }
                   2318: 
                   2319:                        else {
                   2320: 
1.1.1.2   root     2321:                                DEBUG(("Pwaitpid: no children found"));
1.1       root     2322: 
                   2323:                                return EFILNF;
                   2324: 
                   2325:                        }
                   2326: 
                   2327:                }
                   2328: 
                   2329:        } while (!p);
                   2330: 
                   2331: 
                   2332: 
                   2333: /* OK, we've found our child */
                   2334: 
                   2335: /* calculate the return code from the child's exit code and pid */
                   2336: 
                   2337:        r = (((unsigned long)p->pid) << 16) | (p->wait_cond & 0x0000ffff);
                   2338: 
                   2339: 
                   2340: 
                   2341: /* check resource usage */
                   2342: 
                   2343:        if (rusage) {
                   2344: 
1.1.1.6 ! root     2345:                *rusage++ = p->usrtime + p->chldutime;
1.1       root     2346: 
1.1.1.6 ! root     2347:                *rusage = p->systime + p->chldstime;
1.1       root     2348: 
                   2349:        }
                   2350: 
                   2351: 
                   2352: 
1.1.1.2   root     2353: /* avoid adding adopted trace processes usage to the foster parent */
                   2354: 
                   2355:        if (curproc->pid == p->ppid) {
1.1       root     2356: 
1.1.1.2   root     2357:        /* add child's resource usage to parent's */
1.1       root     2358: 
1.1.1.2   root     2359:                if (p->wait_q == TSR_Q || p->wait_q == ZOMBIE_Q) {
1.1       root     2360: 
1.1.1.6 ! root     2361:                        curproc->chldstime += p->systime + p->chldstime;
1.1.1.2   root     2362: 
1.1.1.6 ! root     2363:                        curproc->chldutime += p->usrtime + p->chldutime;
1.1.1.2   root     2364: 
                   2365:                }
1.1       root     2366: 
                   2367:        }
                   2368: 
                   2369: 
                   2370: 
1.1.1.2   root     2371: /* if it was stopped, mark it as having been found and again return */
1.1       root     2372: 
1.1.1.2   root     2373:        if (p->wait_q == STOP_Q) {
1.1       root     2374: 
1.1.1.2   root     2375:                p->wait_cond = 0;
1.1       root     2376: 
                   2377:                return r;
                   2378: 
                   2379:        }
                   2380: 
                   2381: 
                   2382: 
1.1.1.2   root     2383: /* We have to worry about processes which attach themselves to running
1.1       root     2384: 
1.1.1.2   root     2385:  * processes which they want to trace. We fix things up so that the
1.1       root     2386: 
1.1.1.2   root     2387:  * second time the signal gets delivered we will go all the way to the
                   2388: 
                   2389:  * end of this function.
                   2390: 
                   2391:  */
                   2392: 
                   2393:        if (p->ptracer && p->ptracer->pid != p->ppid) {
                   2394: 
                   2395:                if (curproc == p->ptracer) {
                   2396: 
                   2397:                /* deliver the signal to the tracing process first */
                   2398: 
                   2399:                        TRACE(("Pwaitpid(ptracer): returning status to tracing process"));
                   2400: 
                   2401:                        p->ptracer = NULL;
                   2402: 
1.1.1.6 ! root     2403:                        if (p->ppid != -1)
        !          2404: 
        !          2405:                                return r;
1.1.1.2   root     2406: 
                   2407:                }
                   2408: 
                   2409:                else {
                   2410: 
                   2411:                /* Hmmm, the real parent got here first */
                   2412: 
                   2413:                        TRACE(("Pwaitpid(ptracer): returning status to parent process"));
                   2414: 
                   2415:                        p->ppid = -1;
                   2416: 
                   2417:                        return r;
                   2418: 
                   2419:                }
                   2420: 
                   2421:        }
                   2422: 
                   2423:        
                   2424: 
                   2425: /* if it was a TSR, mark it as having been found and return */
                   2426: 
                   2427:        if (p->wait_q == TSR_Q) {
                   2428: 
                   2429:                p->ppid = -1;
1.1       root     2430: 
                   2431:                return r;
                   2432: 
                   2433:        }
                   2434: 
                   2435: 
                   2436: 
                   2437: /* it better have been on the ZOMBIE queue from here on in... */
                   2438: 
                   2439:        assert(p->wait_q == ZOMBIE_Q);
                   2440: 
                   2441:        assert(p != curproc);
                   2442: 
                   2443: 
                   2444: 
                   2445: /* take the child off both the global and ZOMBIE lists */
                   2446: 
1.1.1.5   root     2447:        { short sr = spl7();
                   2448: 
1.1       root     2449:        rm_q(ZOMBIE_Q, p);
                   2450: 
1.1.1.5   root     2451:        spl(sr);
                   2452: 
                   2453:        }
                   2454: 
1.1       root     2455: 
                   2456: 
                   2457:        if (proclist == p) {
                   2458: 
                   2459:                proclist = p->gl_next;
                   2460: 
                   2461:                p->gl_next = 0;
                   2462: 
                   2463:        }
                   2464: 
                   2465:        else {
                   2466: 
                   2467:                q = proclist;
                   2468: 
                   2469:                while(q && q->gl_next != p)
                   2470: 
                   2471:                        q = q->gl_next;
                   2472: 
                   2473:                assert(q);
                   2474: 
                   2475:                q->gl_next = p->gl_next;
                   2476: 
                   2477:                p->gl_next = 0;
                   2478: 
                   2479:        }
                   2480: 
                   2481: 
                   2482: 
                   2483:        dispose_proc(p);        /* free the PROC structure */
                   2484: 
                   2485: 
                   2486: 
                   2487:        return r;
                   2488: 
                   2489: }
                   2490: 
                   2491: 
                   2492: 
1.1.1.2   root     2493: /* p_wait3: BSD process termination primitive, here to maintain
                   2494: 
                   2495:  * compatibility with existing binaries.
                   2496: 
                   2497:  */
                   2498: 
                   2499: long ARGS_ON_STACK
                   2500: 
                   2501: p_wait3(nohang, rusage)
                   2502: 
                   2503:        int nohang;
                   2504: 
                   2505:        long *rusage;
                   2506: 
                   2507: {
                   2508: 
                   2509:        return p_waitpid(-1, nohang, rusage);
                   2510: 
                   2511: }
                   2512: 
                   2513: 
                   2514: 
1.1       root     2515: /* p_wait: block until a child has exited, and don't worry about
                   2516: 
                   2517:    resource stats. this is provided as a convenience, and to maintain
                   2518: 
                   2519:    compatibility with existing binaries (yes, I'm lazy...). we could
                   2520: 
1.1.1.2   root     2521:    make do with Pwaitpid().
1.1       root     2522: 
                   2523:  */
                   2524: 
                   2525: 
                   2526: 
1.1.1.2   root     2527: long ARGS_ON_STACK
1.1       root     2528: 
                   2529: p_wait()
                   2530: 
                   2531: {
                   2532: 
1.1.1.2   root     2533: /*
                   2534: 
                   2535:  * BEWARE:
                   2536: 
                   2537:  * POSIX says that wait() should be implemented as
                   2538: 
                   2539:  * Pwaitpid(-1, 0, (long *)0). Pwait is really not
                   2540: 
                   2541:  * useful for much at all, but we'll keep it around
                   2542: 
                   2543:  * for a while (with it's old, crufty semantics)
                   2544: 
                   2545:  * for backwards compatibility. People implementing
                   2546: 
                   2547:  * POSIX style libraries should use Pwaitpid even
                   2548: 
                   2549:  * to implement wait().
                   2550: 
                   2551:  */
                   2552: 
1.1       root     2553:        return p_wait3(2, (long *)0);
                   2554: 
                   2555: }
                   2556: 
                   2557: 
                   2558: 
                   2559: /*
                   2560: 
                   2561:  * do_vfork(save): create a duplicate of  the current process. This is
                   2562: 
                   2563:  * essentially a vfork() algorithm, except that if (save == 1) the
                   2564: 
                   2565:  * parent's address space is saved, and then restored when the process
                   2566: 
                   2567:  * is made runnable again. The parent is suspended until either the child
                   2568: 
                   2569:  * process (the duplicate) exits or does a Pexec which overlays its
                   2570: 
                   2571:  * memory space.
                   2572: 
                   2573:  *
                   2574: 
                   2575:  * "txtsize" is the size of the process' TEXT area, if it has a valid one;
                   2576: 
                   2577:  * this is part of the second memory region attached (the basepage one)
                   2578: 
                   2579:  * and need not be saved (we assume processes don't write on their own
                   2580: 
                   2581:  * code segment)
                   2582: 
                   2583:  */
                   2584: 
                   2585: 
                   2586: 
                   2587: static long
                   2588: 
                   2589: do_vfork(save)
                   2590: 
                   2591:        int save;
                   2592: 
                   2593: {
                   2594: 
                   2595:        PROC *p;
                   2596: 
                   2597:        long sigmask;
                   2598: 
                   2599:        MEMREGION *m, *savemem = 0;
                   2600: 
                   2601:        long savesize, txtsize;
                   2602: 
1.1.1.4   root     2603:        int i, newpid;
1.1       root     2604: 
                   2605:        char *saveplace;
                   2606: 
                   2607: 
                   2608: 
                   2609:        p = fork_proc();
                   2610: 
                   2611:        if (!p) {
                   2612: 
1.1.1.2   root     2613:                DEBUG(("do_vfork: couldn't get new PROC struct"));
1.1       root     2614: 
                   2615:                return mint_errno;
                   2616: 
                   2617:        }
                   2618: 
                   2619: /* set u:\proc time+date */
                   2620: 
                   2621:        proctime = timestamp;
                   2622: 
                   2623:        procdate = datestamp;
                   2624: 
                   2625: 
                   2626: 
                   2627: /*
                   2628: 
                   2629:  * maybe save the parent's address space
                   2630: 
                   2631:  */
                   2632: 
                   2633:        txtsize = p->txtsize;
                   2634: 
                   2635: 
                   2636: 
                   2637:        if (save) {
                   2638: 
1.1.1.2   root     2639:                TRACE(("do_vfork: saving parent"));
1.1       root     2640: 
                   2641:                savesize = memused(curproc) - txtsize;
                   2642: 
1.1.1.6 ! root     2643:                if (!txtsize && (p->base->p_flags & F_SHTEXT)) {
        !          2644: 
        !          2645:                        for (i = 0; i < curproc->num_reg; i++) {
        !          2646: 
        !          2647:                                m = curproc->mem[i];
        !          2648: 
        !          2649:                                if (m && (m->mflags & M_SHTEXT)) {
        !          2650: 
        !          2651:                                        savesize -= m->len;
        !          2652: 
        !          2653:                                        break;
        !          2654: 
        !          2655:                                }
        !          2656: 
        !          2657:                        }
        !          2658: 
        !          2659:                }
        !          2660: 
1.1       root     2661:                assert(savesize >= 0);
                   2662: 
                   2663: 
                   2664: 
1.1.1.3   root     2665:                saveplace = (char *)alloc_region(alt, savesize, PROT_P);
1.1       root     2666: 
                   2667:                if (!saveplace)
                   2668: 
1.1.1.3   root     2669:                        saveplace = (char *)alloc_region(core, savesize, PROT_P);
1.1       root     2670: 
                   2671: 
                   2672: 
                   2673:                if (!saveplace) {
                   2674: 
1.1.1.2   root     2675:                        DEBUG(("do_vfork: can't save parent's memory"));
1.1       root     2676: 
                   2677:                        p->ppid = 0;            /* abandon the child */
                   2678: 
                   2679:                        post_sig(p, SIGKILL);   /* then kill it */
                   2680: 
                   2681:                        p->ctxt[CURRENT].pc = (long)check_sigs;
                   2682: 
1.1.1.6 ! root     2683:                        p->ctxt[CURRENT].sr |= 0x2000; /* use supervisor stack */
        !          2684: 
        !          2685: #if 0  /* stack set up in fork_proc() */
1.1       root     2686: 
                   2687:                        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
                   2688: 
1.1.1.6 ! root     2689: #endif
        !          2690: 
1.1       root     2691:                        p->pri = MAX_NICE+1;
                   2692: 
                   2693:                        run_next(p, 1);
                   2694: 
                   2695:                        yield();
                   2696: 
                   2697:                        return ENSMEM;
                   2698: 
                   2699:                }
                   2700: 
                   2701:                savemem = addr2mem((virtaddr)saveplace);
                   2702: 
                   2703:                assert(savemem);
                   2704: 
1.1.1.6 ! root     2705:                savemem->mflags |= M_FSAVED;
        !          2706: 
1.1       root     2707:                for (i = 0; i < curproc->num_reg; i++) {
                   2708: 
                   2709:                        m = curproc->mem[i];
                   2710: 
1.1.1.6 ! root     2711:                        if (m && !(m->mflags & (M_SEEN|M_FSAVED|M_SHTEXT))) {
        !          2712: 
        !          2713:                                m->mflags |= M_SEEN; /* save links only once */
        !          2714: 
        !          2715: 
1.1       root     2716: 
                   2717:                                if (i != 1 || txtsize == 0) {
                   2718: 
                   2719:                                    quickmove(saveplace, (char *)m->loc, m->len);
                   2720: 
                   2721:                                    saveplace += m->len;
                   2722: 
                   2723:                                }
                   2724: 
                   2725:                                else {
                   2726: 
                   2727:                                    quickmove(saveplace, (char *)m->loc+txtsize,
                   2728: 
                   2729:                                        m->len - txtsize);
                   2730: 
                   2731:                                    saveplace += m->len - txtsize;
                   2732: 
                   2733:                                }
                   2734: 
                   2735:                        }
                   2736: 
                   2737:                }
                   2738: 
1.1.1.6 ! root     2739:                for (i = 0; i < curproc->num_reg; i++) {
        !          2740: 
        !          2741:                        if (curproc->mem[i])
        !          2742: 
        !          2743:                                curproc->mem[i]->mflags &= ~M_SEEN;
        !          2744: 
        !          2745:                }
        !          2746: 
1.1       root     2747:        }
                   2748: 
                   2749:                                
                   2750: 
                   2751:        p->ctxt[CURRENT] = p->ctxt[SYSCALL];
                   2752: 
                   2753:        p->ctxt[CURRENT].regs[0] = 0;   /* child returns a 0 from call */
                   2754: 
                   2755:        p->ctxt[CURRENT].sr &= ~(0x2000); /* child must be in user mode */
                   2756: 
                   2757: #if 0          /* set up in fork_proc() */
                   2758: 
                   2759:        p->ctxt[CURRENT].ssp = (long)(p->stack + ISTKSIZE);
                   2760: 
                   2761: #endif
                   2762: 
                   2763: 
                   2764: 
                   2765: /* watch out for job control signals, since our parent can never wake
                   2766: 
                   2767:  * up to respond to them. solution: block them; exec_region (in mem.c)
                   2768: 
                   2769:  * clears the signal mask, so an exec() will unblock them.
                   2770: 
                   2771:  */
                   2772: 
                   2773:        p->sigmask |= (1L << SIGTSTP) | (1L << SIGTTIN) | (1L << SIGTTOU);
                   2774: 
                   2775: 
                   2776: 
1.1.1.2   root     2777:        TRACE(("do_vfork: parent going to sleep, wait_cond == %lx",
1.1       root     2778: 
1.1.1.2   root     2779:                (long)p));
1.1       root     2780: 
                   2781: 
                   2782: 
                   2783: /* WARNING: This sleep() must absolutely not wake up until the child
                   2784: 
                   2785:  * has released the memory space correctly. That's why we mask off
                   2786: 
                   2787:  * all signals.
                   2788: 
                   2789:  */
                   2790: 
                   2791:        sigmask = curproc->sigmask;
                   2792: 
1.1.1.6 ! root     2793:        curproc->sigmask = ~(((unsigned long)1 << SIGKILL) | 1);
1.1       root     2794: 
                   2795: 
                   2796: 
1.1.1.5   root     2797:        { short sr = spl7();
                   2798: 
1.1       root     2799:        add_q(READY_Q, p);              /* put it on the ready queue */
                   2800: 
                   2801:        sleep(WAIT_Q, (long)p);                 /* while we wait for it */
                   2802: 
1.1.1.5   root     2803:        spl(sr);
                   2804: 
                   2805:        }
                   2806: 
1.1.1.2   root     2807:        TRACE(("do_vfork: parent waking up"));
1.1       root     2808: 
                   2809: 
                   2810: 
                   2811:        if (save) {
                   2812: 
1.1.1.6 ! root     2813:                fork_restore(curproc, 0L);
1.1       root     2814: 
1.1.1.6 ! root     2815:        }
1.1       root     2816: 
1.1.1.6 ! root     2817:        curproc->sigmask = sigmask;
1.1       root     2818: 
1.1.1.6 ! root     2819: /* note that the PROC structure pointed to by p may be freed during
1.1       root     2820: 
1.1.1.6 ! root     2821:  * the check_sigs call!
1.1       root     2822: 
1.1.1.6 ! root     2823:  */
1.1       root     2824: 
1.1.1.6 ! root     2825:        newpid = p->pid;
1.1       root     2826: 
1.1.1.6 ! root     2827:        check_sigs();   /* did we get any signals while sleeping? */
1.1       root     2828: 
1.1.1.6 ! root     2829:        return newpid;
1.1       root     2830: 
1.1.1.6 ! root     2831: }
1.1       root     2832: 
                   2833: 
                   2834: 
1.1.1.6 ! root     2835: /*
1.1       root     2836: 
1.1.1.6 ! root     2837:  * fork_restore(p): restore process memory after a blocking fork
        !          2838: 
        !          2839:  */
        !          2840: 
        !          2841: 
        !          2842: 
        !          2843: void fork_restore(p, savemem)
        !          2844: 
        !          2845: PROC *p;
        !          2846: 
        !          2847: MEMREGION *savemem;
        !          2848: 
        !          2849: {
        !          2850: 
        !          2851:        MEMREGION *m;
        !          2852: 
        !          2853:        long txtsize = p->txtsize;
        !          2854: 
        !          2855:        char *saveplace;
        !          2856: 
        !          2857:        int i;
        !          2858: 
        !          2859:        extern int no_mem_prot;
        !          2860: 
        !          2861: 
        !          2862: 
        !          2863:        if (!savemem) {
        !          2864: 
        !          2865:                for (i = 0; i < p->num_reg; i++) {
        !          2866: 
        !          2867:                        m = p->mem[i];
        !          2868: 
        !          2869:                        if (m && (m->mflags & M_FSAVED)) {
        !          2870: 
        !          2871:                                savemem = m;
        !          2872: 
        !          2873:                                break;
1.1       root     2874: 
                   2875:                        }
                   2876: 
                   2877:                }
                   2878: 
1.1.1.6 ! root     2879:                if (!savemem)
        !          2880: 
        !          2881:                        return;
1.1       root     2882: 
                   2883:        }
                   2884: 
1.1.1.6 ! root     2885:        saveplace = (char *)savemem->loc;
1.1       root     2886: 
1.1.1.4   root     2887: 
                   2888: 
1.1.1.6 ! root     2889:        TRACE(("do_vfork: parent restoring memory"));
1.1.1.4   root     2890: 
1.1.1.6 ! root     2891: #if 1
1.1.1.4   root     2892: 
1.1.1.6 ! root     2893:        if (p != curproc && !no_mem_prot)
1.1       root     2894: 
1.1.1.6 ! root     2895: /* memprot doesn't like it?  try p's mmu context... */
        !          2896: 
        !          2897:                set_mmu (p->ctxt[CURRENT].crp, p->ctxt[CURRENT].tc);
        !          2898: 
        !          2899: #endif
        !          2900: 
        !          2901:        for (i = 0; i < p->num_reg; i++) {
        !          2902: 
        !          2903:                m = p->mem[i];
        !          2904: 
        !          2905:                if (m && !(m->mflags & (M_SEEN|M_FSAVED|M_SHTEXT))) {
        !          2906: 
        !          2907:                        m->mflags |= M_SEEN;
        !          2908: 
        !          2909:                        if (i != 1 || txtsize == 0) {
        !          2910: 
        !          2911:                            quickmove((char *)m->loc, saveplace, m->len);
        !          2912: 
        !          2913:                            saveplace += m->len;
        !          2914: 
        !          2915:                        }
        !          2916: 
        !          2917:                        else {
        !          2918: 
        !          2919:                            quickmove((char *)m->loc+txtsize, saveplace,
        !          2920: 
        !          2921:                                m->len - txtsize);
        !          2922: 
        !          2923:                            saveplace += m->len - txtsize;
        !          2924: 
        !          2925:                        }
        !          2926: 
        !          2927:                }
        !          2928: 
        !          2929:        }
        !          2930: 
        !          2931:        for (i = 0; i < p->num_reg; i++) {
        !          2932: 
        !          2933:                if (p->mem[i])
        !          2934: 
        !          2935:                        p->mem[i]->mflags &= ~M_SEEN;
        !          2936: 
        !          2937:        }
        !          2938: 
        !          2939: #if 1
        !          2940: 
        !          2941:        if (p != curproc && !no_mem_prot)
        !          2942: 
        !          2943:                set_mmu (curproc->ctxt[CURRENT].crp, curproc->ctxt[CURRENT].tc);
        !          2944: 
        !          2945: #endif
        !          2946: 
        !          2947:        detach_region(p, savemem);
1.1       root     2948: 
                   2949: }
                   2950: 
                   2951: 
                   2952: 
                   2953: /*
                   2954: 
                   2955:  * here are the interfaces that the user sees. Pvfork() doesn't save
                   2956: 
                   2957:  * the child's address space; Pfork() does. Someday Pfork() should
                   2958: 
                   2959:  * allow asynchronous execution of both child and parent, but this
                   2960: 
                   2961:  * will do for now.
                   2962: 
                   2963:  */
                   2964: 
                   2965: 
                   2966: 
1.1.1.2   root     2967: long ARGS_ON_STACK
1.1       root     2968: 
                   2969: p_vfork()
                   2970: 
                   2971: {
                   2972: 
                   2973:        return do_vfork(0);
                   2974: 
                   2975: }
                   2976: 
                   2977: 
                   2978: 
1.1.1.2   root     2979: long ARGS_ON_STACK
1.1       root     2980: 
                   2981: p_fork()
                   2982: 
                   2983: {
                   2984: 
                   2985:        return do_vfork(1);
                   2986: 
                   2987: }
                   2988: 

unix.superglobalmegacorp.com

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