Annotation of researchv9/sys/boot/stand/sys.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * @(#)sys.c 1.1 86/02/03 Copyright (c) 1985 by Sun Microsystems, Inc.
                      3:  */
                      4: 
                      5: /*
                      6:  * Basic file system reading code for standalone I/O system.
                      7:  * Simulates a primitive UNIX I/O system (read(), write(), open(), etc).
                      8:  * Does not attempt writes to file systems, tho writing to whole devices
                      9:  * is supported, when the driver supports it.
                     10:  */
                     11: 
                     12: #include "param.h"
                     13: #include "saio.h"
                     14: #include "../h/dir.h"
                     15: #include "../h/time.h"
                     16: #include "../h/vnode.h"
                     17: #include "../ufs/fs.h"
                     18: #include "../ufs/inode.h"
                     19: /*
                     20:  * This struct keeps track of an open file in the standalone I/O system.
                     21:  *
                     22:  * It includes an IOB for device addess, an inode, a buffer for reading
                     23:  * indirect blocks and inodes, and a buffer for the superblock of the
                     24:  * file system (if any).
                     25:  */
                     26: struct iob {
                     27:        struct saioreq  i_si;           /* I/O request block for this file */
                     28:        struct inode    i_ino;          /* Inode for this file */
                     29:        char            i_buf[MAXBSIZE];/* Buffer for reading inodes & dirs */
                     30:        union { 
                     31:                struct fs ui_fs;        /* Superblock for file system */
                     32:                char dummy[SBSIZE];
                     33:        }               i_un;
                     34: };
                     35: #define i_flgs         i_si.si_flgs
                     36: #define i_boottab      i_si.si_boottab
                     37: #define i_devdata      i_si.si_devdata
                     38: #define i_ctlr         i_si.si_ctlr
                     39: #define i_unit         i_si.si_unit
                     40: #define i_boff         i_si.si_boff
                     41: #define i_cyloff       i_si.si_cyloff
                     42: #define i_offset       i_si.si_offset
                     43: #define i_bn           i_si.si_bn
                     44: #define i_ma           i_si.si_ma
                     45: #define i_cc           i_si.si_cc
                     46: #define i_fs           i_un.ui_fs
                     47: 
                     48: /* These are the pools of buffers, iob's, etc. */
                     49: #define        NBUFS   (NIADDR+1)      /* NOT! a variable */
                     50: char           b[NBUFS][MAXBSIZE];
                     51: daddr_t                blknos[NBUFS];
                     52: struct iob     iob[NFILES];
                     53: 
                     54: ino_t  dlook();
                     55: 
                     56: struct dirstuff {
                     57:        int loc;
                     58:        struct iob *io;
                     59: };
                     60: 
                     61: static
                     62: openi(n,io)
                     63:        ino_t n;
                     64:        register struct iob *io;
                     65: {
                     66:        register struct dinode *dp;
                     67: 
                     68:        io->i_offset = 0;
                     69:        io->i_bn = fsbtodb(&io->i_fs, itod(&io->i_fs, n));
                     70:        io->i_cc = io->i_fs.fs_bsize;
                     71:        io->i_ma = io->i_buf;
                     72:        /* FIXME: this call to devread() does not check for errors! */
                     73:        devread(&io->i_si);
                     74:        dp = (struct dinode *)io->i_buf;
                     75:        io->i_ino.i_ic = dp[itoo(&io->i_fs, n)].di_ic;
                     76: }
                     77: 
                     78: static ino_t
                     79: find(path, file)
                     80:        register char *path;
                     81:        struct iob *file;
                     82: {
                     83:        register char *q;
                     84:        char c;
                     85:        ino_t n;
                     86: 
                     87:        if (path==NULL || *path=='\0') {
                     88:                printf("null path\n");
                     89:                return(0);
                     90:        }
                     91: 
                     92:        openi((ino_t) ROOTINO, file);
                     93:        while (*path) {
                     94:                while (*path == '/')
                     95:                        path++;
                     96:                q = path;
                     97:                while(*q != '/' && *q != '\0')
                     98:                        q++;
                     99:                c = *q;
                    100:                *q = '\0';
                    101: 
                    102:                if ((n=dlook(path, file))!=0) {
                    103:                        if (c=='\0')
                    104:                                break;
                    105:                        openi(n, file);
                    106:                        *q = c;
                    107:                        path = q;
                    108:                        continue;
                    109:                } else {
                    110:                        printf("%s not found\n",path);
                    111:                        return(0);
                    112:                }
                    113:        }
                    114:        return(n);
                    115: }
                    116: 
                    117: static daddr_t
                    118: sbmap(io, bn)
                    119:        register struct iob *io;
                    120:        daddr_t bn;
                    121: {
                    122:        register struct inode *ip;
                    123:        register int i, j, sh;
                    124:        register daddr_t nb, *bap;
                    125: 
                    126:        ip = &io->i_ino;
                    127: 
                    128:        /*
                    129:         * blocks 0..NDADDR are direct blocks
                    130:         */
                    131:        if(bn < NDADDR) {
                    132:                nb = ip->i_db[bn];
                    133:                return(nb);
                    134:        }
                    135: 
                    136: #ifndef BOOTBLOCK
                    137:        /*
                    138:         * addresses NIADDR have single and double indirect blocks.
                    139:         * the first step is to determine how many levels of indirection.
                    140:         */
                    141:        sh = 1;
                    142:        bn -= NDADDR;
                    143:        for (j = NIADDR; j > 0; j--) {
                    144:                sh *= NINDIR(&io->i_fs);
                    145:                if (bn < sh)
                    146:                        break;
                    147:                bn -= sh;
                    148:        }
                    149:        if (j == 0) {
                    150:                printf("bn ovf %D\n", bn);
                    151:                return ((daddr_t)0);
                    152:        }
                    153: 
                    154:        /*
                    155:         * fetch the first indirect block address from the inode
                    156:         */
                    157:        nb = ip->i_ib[NIADDR - j];
                    158:        if (nb == 0) {
                    159:                printf("bn void %D\n",bn);
                    160:                return((daddr_t)0);
                    161:        }
                    162: 
                    163:        /*
                    164:         * fetch through the indirect blocks
                    165:         */
                    166:        for (; j <= NIADDR; j++) {
                    167:                if (blknos[j] != nb) {
                    168:                        io->i_bn = fsbtodb(&io->i_fs, nb);
                    169:                        io->i_ma = b[j];
                    170:                        io->i_cc = io->i_fs.fs_bsize;
                    171:                        if (devread(&io->i_si) != io->i_cc)
                    172:                                return((daddr_t)0);
                    173:                        blknos[j] = nb;
                    174:                }
                    175:                bap = (daddr_t *)b[j];
                    176:                sh /= NINDIR(&io->i_fs);
                    177:                i = (bn / sh) % NINDIR(&io->i_fs);
                    178:                nb = bap[i];
                    179:                if(nb == 0) {
                    180:                        printf("bn void %D\n",bn);
                    181:                        return((daddr_t)0);
                    182:                }
                    183:        }
                    184:        return(nb);
                    185: #else BOOTBLOCK
                    186:        return((daddr_t)0);
                    187: #endif BOOTBLOCK
                    188: }
                    189: 
                    190: static ino_t
                    191: dlook(s, io)
                    192:        char *s;
                    193:        register struct iob *io;
                    194: {
                    195:        register struct direct *dp;
                    196:        register struct inode *ip;
                    197:        struct dirstuff dirp;
                    198:        register int len;
                    199: 
                    200:        ip = &io->i_ino;
                    201: #ifndef BOOTBLOCK
                    202:        if (s == NULL || *s == '\0')
                    203:                return(0);
                    204:        if ((ip->i_mode&IFMT) != IFDIR) {
                    205:                printf("not a directory\n");
                    206:                return(0);
                    207:        }
                    208:        if (ip->i_size == 0) {
                    209:                printf("zero length directory\n");
                    210:                return(0);
                    211:        }
                    212: #endif
                    213:        len = strlen(s);
                    214:        dirp.loc = 0;
                    215:        dirp.io = io;
                    216:        for (dp = readdir(&dirp); dp != NULL; dp = readdir(&dirp)) {
                    217:                if(dp->d_ino == 0)
                    218:                        continue;
                    219:                if (dp->d_namlen == len && !strcmp(s, dp->d_name))
                    220:                        return(dp->d_ino);
                    221: #ifndef BOOTBLOCK
                    222:                /* Allow "*" to print all names at that level, w/out match */
                    223:                if (!strcmp(s, "*"))
                    224:                        printf("%s\n", dp->d_name);
                    225: #endif
                    226:        }
                    227:        return(0);
                    228: }
                    229: 
                    230: /*
                    231:  * get next entry in a directory.
                    232:  */
                    233: struct direct *
                    234: readdir(dirp)
                    235:        register struct dirstuff *dirp;
                    236: {
                    237:        register struct direct *dp;
                    238:        register struct iob *io;
                    239:        register daddr_t lbn, d;
                    240:        register int off;
                    241: 
                    242:        io = dirp->io;
                    243:        for(;;) {
                    244:                if (dirp->loc >= io->i_ino.i_size)
                    245:                        return NULL;
                    246:                off = blkoff(&io->i_fs, dirp->loc);
                    247:                if (off == 0) {
                    248:                        lbn = lblkno(&io->i_fs, dirp->loc);
                    249:                        d = sbmap(io, lbn);
                    250:                        if(d == 0)
                    251:                                return NULL;
                    252:                        io->i_bn = fsbtodb(&io->i_fs, d);
                    253:                        io->i_ma = io->i_buf;
                    254:                        io->i_cc = blksize(&io->i_fs, &io->i_ino, lbn);
                    255:                        if (devread(&io->i_si) != io->i_cc)
                    256:                                return NULL;
                    257:                }
                    258:                dp = (struct direct *)(io->i_buf + off);
                    259:                dirp->loc += dp->d_reclen;
                    260:                if (dp->d_ino == 0)
                    261:                        continue;
                    262:                return (dp);
                    263:        }
                    264: }
                    265: 
                    266: lseek(fdesc, addr, ptr)
                    267:        int     fdesc;
                    268:        register off_t  addr;
                    269:        int     ptr;
                    270: {
                    271:        register struct iob *io;
                    272: 
                    273: #ifndef BOOTBLOCK
                    274:        fdesc -= 3;
                    275:        if (fdesc < 0 || fdesc >= NFILES ||
                    276:            ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0)
                    277:                return(-1);
                    278: #else
                    279:        io = &iob[fdesc - 3];
                    280: #endif
                    281:        io->i_si.si_flgs &= ~F_EOF;
                    282:        io->i_offset = addr;
                    283:        io->i_bn = addr / DEV_BSIZE;
                    284:        io->i_cc = 0;
                    285:        return(0);
                    286: }
                    287: 
                    288: /* FIXME: possibly make this static and pass iob, eliminating assorted tests? */
                    289: getc(fdesc)
                    290:        int     fdesc;
                    291: {
                    292:        register struct iob *io;
                    293:        register struct fs *fs;
                    294:        register char *p;
                    295:        register int c, off, size, diff;
                    296:        register daddr_t lbn;
                    297: 
                    298: 
                    299: #ifndef BOOTBLOCK
                    300:        if (fdesc >= 0 && fdesc <= 2)
                    301:                return(getchar());
                    302:        fdesc -= 3;
                    303:        if (fdesc < 0 || fdesc >= NFILES ||
                    304:            ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
                    305:                return(-1);
                    306: #else
                    307:        io = &iob[fdesc -= 3];
                    308: #endif
                    309:        p = io->i_ma;
                    310:        if (io->i_cc <= 0) {
                    311:                if ((io->i_flgs & F_FILE) != 0) {
                    312:                        diff = io->i_ino.i_size - io->i_offset;
                    313:                        if (diff <= 0)
                    314:                                return (-1);
                    315:                        fs = &io->i_fs;
                    316:                        lbn = lblkno(fs, io->i_offset);
                    317:                        io->i_bn = fsbtodb(fs, sbmap(io, lbn));
                    318:                        off = blkoff(fs, io->i_offset);
                    319:                        size = blksize(fs, &io->i_ino, lbn);
                    320:                } else {
                    321:                        io->i_bn = io->i_offset / DEV_BSIZE;
                    322:                        off = 0;
                    323:                        size = DEV_BSIZE;
                    324:                }
                    325:                io->i_ma = io->i_buf;
                    326:                io->i_cc = size;
                    327:                if (devread(&io->i_si) != io->i_cc)     /* Trap errors */
                    328:                        return(-1);
                    329:                if ((io->i_flgs & F_FILE) != 0) {
                    330:                        if (io->i_offset - off + size >= io->i_ino.i_size)
                    331:                                io->i_cc = diff + off;
                    332:                        io->i_cc -= off;
                    333:                }
                    334:                p = &io->i_buf[off];
                    335:        }
                    336:        io->i_cc--;
                    337:        io->i_offset++;
                    338:        c = (unsigned)*p++;
                    339:        io->i_ma = p;
                    340:        return(c);
                    341: }
                    342: 
                    343: 
                    344: read(fdesc, buf, count)
                    345:        int     fdesc;
                    346:        register char   *buf;
                    347:        int     count;
                    348: {
                    349:        register i,j;
                    350:        register struct iob *file;
                    351: 
                    352: #ifndef BOOTBLOCK
                    353:        if (fdesc >= 0 && fdesc <= 2) {
                    354:                i = count;
                    355:                do {
                    356:                        *buf = getchar();
                    357:                } while (--i && *buf++ != '\n');
                    358:                return(count - i);
                    359:        }
                    360:        fdesc -= 3;
                    361:        if (fdesc < 0 || fdesc >= NFILES ||
                    362:            ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
                    363:                return(-1);
                    364:        if ((file->i_flgs&F_READ) == 0)
                    365:                return(-1);
                    366:        fdesc += 3;
                    367: #else BOOTBLOCK
                    368:        file = &iob[fdesc - 3];
                    369: #endif BOOTBLOCK
                    370:        if ((file->i_flgs & F_FILE) == 0) {
                    371:                file->i_cc = count;
                    372:                file->i_ma = buf;
                    373:                file->i_bn = (file->i_offset / DEV_BSIZE);
                    374:                i = devread(&file->i_si);
                    375:                file->i_offset += count;
                    376:                return(i);
                    377:        } else {
                    378:                if (file->i_offset+count > file->i_ino.i_size)
                    379:                        count = file->i_ino.i_size - file->i_offset;
                    380:                if ((i = count) <= 0)
                    381:                        return(0);
                    382: #ifdef BOOTBLOCK
                    383:                do {
                    384:                        *buf++ = getc(fdesc);
                    385:                } while (--i);
                    386: #else BOOTBLOCK
                    387:                while (i > 0) {
                    388:                        if ((j = file->i_cc) <= 0) {
                    389:                                *buf++ = getc(fdesc);
                    390:                                i--;
                    391:                        } else {
                    392:                                if (i < j)
                    393:                                        j = i;
                    394:                                bcopy(file->i_ma, buf, (unsigned)j);
                    395:                                buf += j;
                    396:                                file->i_ma += j;
                    397:                                file->i_offset += j;
                    398:                                file->i_cc -= j;
                    399:                                i -= j;
                    400:                        }
                    401:                }
                    402: #endif BOOTBLOCK
                    403:                return(count);
                    404:        }
                    405: }
                    406: 
                    407: #ifndef BOOTBLOCK
                    408: write(fdesc, buf, count)
                    409:        int     fdesc;
                    410:        char    *buf;
                    411:        int     count;
                    412: {
                    413:        register i;
                    414:        register struct iob *file;
                    415: 
                    416:        if (fdesc >= 0 && fdesc <= 2) {
                    417:                i = count;
                    418:                while (i--)
                    419:                        putchar(*buf++);
                    420:                return(count);
                    421:        }
                    422:        fdesc -= 3;
                    423:        if (fdesc < 0 || fdesc >= NFILES ||
                    424:            ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
                    425:                return(-1);
                    426:        if ((file->i_flgs&F_WRITE) == 0)
                    427:                return(-1);
                    428:        if (count % DEV_BSIZE)
                    429:                printf("count=%d?\n", count);
                    430:        file->i_cc = count;
                    431:        file->i_ma = buf;
                    432:        file->i_bn = (file->i_offset / DEV_BSIZE);
                    433:        i = devwrite(&file->i_si);
                    434:        file->i_offset += count;
                    435:        return(i);
                    436: }
                    437: #endif BOOTBLOCK
                    438: 
                    439: /*
                    440:  * Open a file on a physical device, or open the device itself.
                    441:  *
                    442:  * The device is identified by a struct bootparam which gives pointers
                    443:  * to the struct boottab, containing the device open, strategy and close
                    444:  * routines; and the device parameters such as controller #, unit #, etc.
                    445:  *
                    446:  * If *str == 0, the device is opened, else the named file in the file
                    447:  * system on the device is opened.
                    448:  */
                    449: int
                    450: physopen(bp, str, how)
                    451:        register struct bootparam *bp;
                    452:        char            *str;
                    453:        int             how;
                    454: {
                    455:        int fdesc;
                    456:        register struct iob *file;
                    457: 
                    458: #ifdef BOOTBLOCK
                    459:        fdesc = 0;
                    460:        file = &iob[0];
                    461:        file->i_flgs |= F_ALLOC;
                    462: #else BOOTBLOCK
                    463:        fdesc = getiob();               /* Allocate an IOB */
                    464:        file = &iob[fdesc];
                    465: #endif BOOTBLOCK
                    466: 
                    467:        file->i_boottab = bp->bp_boottab; /* Record pointer to boot table */
                    468:        file->i_ctlr = bp->bp_ctlr;
                    469:        file->i_unit = bp->bp_unit;
                    470:        file->i_boff = bp->bp_part;
                    471:        file->i_ino.i_dev = 0;  /* Call it device 0 for chuckles */
                    472: 
                    473:        return(openfile(fdesc, file, str, how));
                    474: }
                    475: 
                    476: #ifndef BOOTBLOCK
                    477: 
                    478: int    openfirst = 1;
                    479: 
                    480: /*
                    481:  * Allocate an IOB for a newly opened file.
                    482:  */
                    483: int
                    484: getiob()
                    485: {
                    486:        register int fdesc;
                    487: 
                    488:        if (openfirst) {
                    489:                openfirst = 0;
                    490:                for (fdesc = 0; fdesc < NFILES; fdesc++)
                    491:                        iob[fdesc].i_flgs = 0;
                    492:        }
                    493: 
                    494:        for (fdesc = 0; fdesc < NFILES; fdesc++)
                    495:                if (iob[fdesc].i_flgs == 0)
                    496:                        goto gotfile;
                    497:        _stop("No more file slots");
                    498: gotfile:
                    499:        (&iob[fdesc])->i_flgs |= F_ALLOC;
                    500:        return fdesc;
                    501: }
                    502: 
                    503: /* Hex string scanner for open() */
                    504: static char *
                    505: openhex(p, ip)
                    506:        register char *p;
                    507:        int *ip;
                    508: {
                    509:        register int ac = 0;
                    510: 
                    511:        while (*p) {
                    512:                if (*p >= '0' && *p <= '9')
                    513:                        ac = (ac<<4) + (*p - '0');
                    514:                else if (*p >= 'a' && *p <= 'f')
                    515:                        ac = (ac<<4) + (*p - 'a' + 10);
                    516:                else if (*p >= 'A' && *p <= 'F')
                    517:                        ac = (ac<<4) + (*p - 'A' + 10);
                    518:                else
                    519:                        break;
                    520:                p++;
                    521:        }
                    522:        if (*p == ',')
                    523:                p++;
                    524:        *ip = ac;
                    525:        return (p);
                    526: }
                    527: 
                    528: /*
                    529:  * Open a device or file-in-file-system-on-device.
                    530:  */
                    531: int
                    532: open(str, how)
                    533:        char    *str;
                    534:        int     how;
                    535: {
                    536:        register char *cp;
                    537:        register struct iob *file;
                    538:        register struct boottab *dp;
                    539:        register struct boottab **tablep;
                    540:        int     fdesc;
                    541:        long    atol();
                    542: 
                    543:        extern struct boottab *(devsw[]);
                    544: 
                    545:        fdesc = getiob();               /* Allocate an IOB */
                    546:        file = &iob[fdesc];
                    547: 
                    548:        for (cp = str; *cp && *cp != '('; cp++)
                    549:                        ;
                    550:        if (*cp++ != '(') {
                    551:                file->i_flgs = 0;
                    552:                goto badsyntax;
                    553:        }
                    554:        for (tablep = devsw; 0 != (dp = *tablep); tablep++) {
                    555:                if (str[0] == dp->b_dev[0] && str[1] == dp->b_dev[1])
                    556:                        goto gotdev;
                    557:        }
                    558:        printf("Unknown device: %c%c; known devices:\n", str[0], str[1]);
                    559:        for (tablep = devsw; 0 != (dp = *tablep); tablep++)
                    560:                printf("  %s\n", dp->b_desc);
                    561:        file->i_flgs = 0;
                    562:        return(-1);
                    563: gotdev:
                    564:        file->i_boottab = dp;           /* Record pointer to boot table */
                    565:        file->i_ino.i_dev = tablep-devsw;
                    566: #ifdef sun
                    567:        cp = openhex(cp, &file->i_ctlr);
                    568: #endif
                    569:        cp = openhex(cp, &file->i_unit);
                    570:        cp = openhex(cp, (int *)&file->i_boff);
                    571:        if (*cp == '\0') goto doit;
                    572:        if (*cp != ')') {
                    573: badsyntax:
                    574:                printf("%s: bad syntax, try dev(ctlr,unit,part)name\n", str);
                    575:                return -1;
                    576:        }
                    577:        do
                    578:                cp++;
                    579:        while (*cp == ' ');
                    580: 
                    581: doit:
                    582:        return(openfile(fdesc, file, cp, how));
                    583: }
                    584: #endif NOOPEN
                    585: 
                    586: 
                    587: /*
                    588:  * File processing for open call
                    589:  */
                    590: openfile(fdesc, file, cp, how)
                    591:        int             fdesc;
                    592:        struct iob      *file;
                    593:        char            *cp;
                    594:        int             how;
                    595: {
                    596:        ino_t   ino;
                    597: 
                    598:        if (devopen(&file->i_si)) {
                    599:                file->i_flgs = 0;
                    600:                return(-1);     /* if devopen fails, open fails */
                    601:        }
                    602: 
                    603:        if (*cp == '\0') {      /* Opening a device */
                    604:                file->i_flgs |= how+1;
                    605:                file->i_cc = 0;
                    606:                file->i_offset = 0;
                    607:                return(fdesc+3);
                    608:        }
                    609:        /* Opening a file system; read the superblock. */
                    610:        file->i_ma = (char *)(&file->i_fs);
                    611:        file->i_cc = SBSIZE;
                    612:        file->i_bn = SBLOCK;
                    613:        file->i_offset = 0;
                    614:        if (devread(&file->i_si) != SBSIZE) {
                    615:                file->i_flgs = 0;
                    616:                return(-1);
                    617:        }
                    618: #ifndef BOOTBLOCK
                    619:        if (file->i_fs.fs_magic != FS_MAGIC) {
                    620:                printf("Not a file system\n");
                    621:                return(-1);
                    622:        }
                    623: #endif
                    624:        if ((ino = find(cp, file)) == 0) {
                    625:                file->i_flgs = 0;
                    626:                return(-1);
                    627:        }
                    628: #ifndef BOOTBLOCK
                    629:        if (how != 0) {
                    630:                printf("Can't write files yet.. Sorry\n");
                    631:                file->i_flgs = 0;
                    632:                return(-1);
                    633:        }
                    634: #endif
                    635:        openi(ino, file);
                    636:        file->i_offset = 0;
                    637:        file->i_cc = 0;
                    638:        file->i_flgs |= F_FILE | (how+1);
                    639:        return(fdesc+3);
                    640: }
                    641: 
                    642: 
                    643: close(fdesc)
                    644:        int     fdesc;
                    645: {
                    646:        register struct iob *file;
                    647: 
                    648:        fdesc -= 3;
                    649:        if (fdesc < 0 || fdesc >= NFILES ||
                    650:            ((file = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
                    651:                return(-1);
                    652:        devclose(&file->i_si);  /* For a file-in-filesys or for raw dev */
                    653:        file->i_flgs = 0;
                    654:        return(0);
                    655: }
                    656: 
                    657: exit()
                    658: {
                    659:        _stop((char *)0);
                    660: }
                    661: 
                    662: _stop(s)
                    663:        char    *s;
                    664: {
                    665:        register int i;
                    666: 
                    667:        for (i = 0; i < NFILES; i++)
                    668:                if (iob[i].i_flgs != 0)
                    669:                        close(i);
                    670:        if (s) printf("%s\n", s);
                    671:        _exit();
                    672: }

unix.superglobalmegacorp.com

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