Annotation of 43BSD/contrib/apl/src/ay.c, revision 1.1.1.1

1.1       root        1: static char Sccsid[] = "ay.c @(#)ay.c  1.1     10/1/82 Berkeley ";
                      2: #
                      3: 
                      4: /*
                      5:  *      APL Buffered I/O routines
                      6:  *
                      7:  *
                      8:  * The following routines perform all of the I/O required by APL.
                      9:  * They are designed to maximize buffer utilization while maintaining
                     10:  * reliable operation.  For a machine such as the PDP-11, the number
                     11:  * of buffers, defined in apl.h, should be around 4 for best results.
                     12:  * For a machine such as the VAX 11/780, a larger number may be desirable
                     13:  * for better results.
                     14:  *
                     15:  */
                     16: 
                     17: #include "apl.h"                /* Header definitions */
                     18: #ifdef NBUF                     /* Don't do any of this unless buffering
                     19:                                 * was requested by defining NBUF
                     20:                                 */
                     21: 
                     22: #define        realfd(x)       files[x].fd_dup
                     23: 
                     24: openf(fname, mode)
                     25: char *fname;
                     26: {
                     27: 
                     28:        int fd;
                     29: 
                     30: 
                     31:        /* The first order of business is to open the
                     32:         * file.  If this fails, return -1.
                     33:         */
                     34: 
                     35:        if ((fd=open(fname,mode)) < 0) return(fd);
                     36: 
                     37: 
                     38:        /* Now, perform all of the work necessary for setting
                     39:         * up the file tables.  This code is shared by "openf"
                     40:         * and "creatf" since both open files.
                     41:         */
                     42: 
                     43:        openup(fd);
                     44:        return(fd);
                     45: }
                     46: 
                     47: creatf(fname, mode)
                     48: char *fname;
                     49: {
                     50: 
                     51:        int fd;
                     52: 
                     53: 
                     54:        /* The first order of business is to create the
                     55:         * file.  If this fails, return -1.
                     56:         */
                     57: 
                     58:        if ((fd=creat(fname,mode)) < 0) return(fd);
                     59: 
                     60: 
                     61:        /* Now, perform all of the work necessary for setting
                     62:         * up the file tables.  This code is shared by "openf"
                     63:         * and "creatf" since both open files.
                     64:         */
                     65: 
                     66:        openup(fd);
                     67:        return(fd);
                     68: }
                     69: 
                     70: openup(fd)
                     71: {
                     72:        struct stat stat_buf;
                     73:        register struct fds *p, *q;
                     74:        register j;
                     75: 
                     76: 
                     77:        /* Try to perform an "fstat" call on the file.  This
                     78:         * information is required for all file descriptors
                     79:         * to prevent reading from a file while data destined
                     80:         * for that file is still buffered for output.  If for
                     81:         * some reason the "fstat" fails, arbitrarily set
                     82:         * the major/minor number and inode number to zero.
                     83:         */
                     84: 
                     85:        if (fstat(fd, &stat_buf) < 0){
                     86:                write(2, "Can't \"stat\" new fd\n", 20);
                     87:                stat_buf.st_dev = 0;
                     88:                stat_buf.st_ino = 0;
                     89:        }
                     90: 
                     91: 
                     92:        /* Copy the information into the "files" structure, which
                     93:         * maintains such data on all open files.
                     94:         */
                     95: 
                     96:        p = &files[fd];
                     97:        p->fd_dev = stat_buf.st_dev;    /* Major/minor device numbers */
                     98:        p->fd_ind = stat_buf.st_ino;    /* Inode number */
                     99:        p->fd_open = 1;                 /* File is open */
                    100:        p->fd_buf = -1;                 /* No buffer is currently assigned */
                    101:        p->fd_dup = fd;                 /* All it duplicates is itself */
                    102:        p->fd_lastop = 0;               /* Lastop was read (default) */
                    103:        p->fd_pipe = !!lseek(fd, 0L, 1);        /* Seek will fail if a pipe */
                    104: 
                    105: 
                    106:        /* Determine if the new fd is unique or not.  If not,
                    107:         * make sure any matching fd's know that they no longer
                    108:         * are either.
                    109:         */
                    110: 
                    111:        p->fd_uniq = 1;                 /* Assume uniqueness */
                    112:        for(j=0; j<NFDS; j++){
                    113:                if (!files[j].fd_open) continue;        /* File not open */
                    114: 
                    115:                q = &files[realfd(j)];
                    116:                if (p->fd_ind == q->fd_ind && p->fd_dev == q->fd_dev)
                    117:                        p->fd_uniq = q->fd_uniq = 0;
                    118:        }
                    119:        check();                                        /*DEBUG*/
                    120: }
                    121: 
                    122: dupf(fd)
                    123: {
                    124: 
                    125:        int fd2;
                    126:        register struct fds *p, *q;
                    127: 
                    128: 
                    129:        /* Duplicating a file descriptor does not require an "fstat"
                    130:         * on the new file descriptor, because its device and inode
                    131:         * are already recorded.  However, duplicate file descriptors
                    132:         * complicate I/O because they MUST be linked to the same
                    133:         * buffer.
                    134:         */
                    135: 
                    136:        if ((fd2=dup(fd)) < 0) return(fd2);     /* Get new fd */
                    137: 
                    138:        /* Copy all of the information into the "files" for the new
                    139:         * file descriptor.  The uniqueness of the original fd is copied
                    140:         * to the new fd -- they both represent the same thing.
                    141:         */
                    142: 
                    143:        p = &files[fd];                 /* Point to appropriate places */
                    144:        q = &files[fd2];
                    145: 
                    146:        q->fd_dev = p->fd_dev;          /* Major/minor device number */
                    147:        q->fd_ind = p->fd_ind;          /* Inode number */
                    148:        q->fd_buf = -1;                 /* Buffer is assigned to princ. fd */
                    149:        q->fd_uniq = p->fd_uniq;        /* Uniqueness of dev/inode */
                    150:        q->fd_dup = p->fd_dup;          /* Point new entry to old one */
                    151:        q->fd_open = 1;                 /* File is now open */
                    152:        q->fd_lastop = p->fd_lastop;    /* Last operation is the same */
                    153: 
                    154:        return(fd2);                    /* Return new fd */
                    155: }
                    156: 
                    157: closef(fd)
                    158: {
                    159: 
                    160:        register j;
                    161:        register struct fds *p, *q;
                    162:        int fd2, count;
                    163: 
                    164:        /* Closing a file is easier than opening it, but some precautions
                    165:         * are necessary.  For instance, if a "dup" was performed to
                    166:         * obtain some new file descriptor and the original file is
                    167:         * now being closed, the duplicated file must retain all
                    168:         * pertinent information.  Thus, the first order of business
                    169:         * is to scan the list of file descriptors for duplicates.
                    170:         */
                    171: 
                    172:        p = &files[fd];                 /* Entry for dying fd */
                    173: 
                    174:        count = 0;                      /* Number of remaining dups */
                    175:        fd2 = -1;                       /* New fd reference for dups */
                    176: 
                    177:        if (p->fd_dup == fd) for (j=0; j<NFDS; j++){
                    178:                if (j == fd) continue;          /* Don't look at fd */
                    179:                q = &files[j];
                    180:                if (!q->fd_open) continue;      /* Not open */
                    181:                if (q->fd_dup != fd) continue;
                    182:                if (fd2 == -1){
                    183:                        fd2 = j;                /* New reference */
                    184:                        q->fd_buf = p->fd_buf;  /* Vital data */
                    185:                        q->fd_open = 1;
                    186:                        q->fd_lastop = p->fd_lastop;
                    187:                }
                    188:                q->fd_dup = fd2;
                    189:                count++;
                    190:        }
                    191: 
                    192: 
                    193:        /* Flush and release the buffer associated with this fd. */
                    194: 
                    195:        newbuf(files[realfd(fd)].fd_buf, -1);
                    196: 
                    197: 
                    198:        /* Mark the entry in the file descriptor table as "closed"
                    199:         * and check the uniqueness of any remaining fd's pointing to
                    200:         * the same area.  Be sure the buffer is released.
                    201:         */
                    202: 
                    203:        p->fd_open = 0;
                    204:        p->fd_dup = fd;
                    205:        p->fd_buf = -1;
                    206: 
                    207:        for(j=0; j<NFDS; j++){
                    208:                if (j == fd) continue;          /* Skip the same fd */
                    209:                q = &files[fd];
                    210:                if (!q->fd_open) continue;      /* Skip closed files */
                    211:                if (p->fd_dev == q->fd_dev && p->fd_ind == q->fd_ind) break;
                    212:        }
                    213: 
                    214:        if (j<NFDS) q->fd_uniq = 1;             /* Assume new fd is unique */
                    215:        while(++j < NFDS){                      /* Now check to be sure */
                    216:                p = &files[j];
                    217:                if (p->fd_dev == q->fd_dev && p->fd_ind == q->fd_ind)
                    218:                        p->fd_uniq = q->fd_uniq = 0;
                    219:        }
                    220: 
                    221: 
                    222:        /* Actually perform the close of the fd, and return the status
                    223:         * of that system call.
                    224:         */
                    225: 
                    226:        return(close(fd));
                    227: }
                    228: 
                    229: 
                    230: initbuf()
                    231: {
                    232: 
                    233:        /* Initialize buffer structure, then use "openup" to set up
                    234:         * file descriptors 0, and 1, which should already be
                    235:         * open from parent process.  If 0 and 1 have the same inode
                    236:         * and major/minor number they will be considered to be
                    237:         * duplicates.  Fils descriptor 2 will be closed and set to
                    238:         * duplicate file descriptor 1.
                    239:         */
                    240: 
                    241:        register j;
                    242:        register struct fds *p, *q;
                    243: 
                    244: 
                    245:        /* Initialize file descriptor table */
                    246: 
                    247:        for(j=0; j<NFDS; j++){
                    248:                files[j].fd_open = 0;                   /* Closed */
                    249:                files[j].fd_dup = j;                    /* Dup = fd */
                    250:                files[j].fd_buf = -1;                   /* No buffer */
                    251:                files[j].fd_pipe = 0;                   /* Not pipe */
                    252:        }
                    253: 
                    254: 
                    255:        /* Initialize buffer table */
                    256: 
                    257:        for(j=0; j<NBUF; j++) iobuf[j].b_fd = -1;       /* Available */
                    258: 
                    259: 
                    260:        /* "Open" devices 0, and 1 */
                    261: 
                    262:        openup(0);
                    263:        openup(1);
                    264:        p = &files[0];
                    265:        q = &files[1];
                    266:        if (p->fd_ind == q->fd_ind && p->fd_dev == q->fd_dev){
                    267:                q->fd_dup = 0;
                    268:                p->fd_uniq = q->fd_uniq = 1;
                    269:        }
                    270: 
                    271: 
                    272:        /* File descriptor 2 duplicates fd 1 */
                    273: 
                    274:        close(2);
                    275:        dupf(1);
                    276: }
                    277: 
                    278: newbuf(bufnum, fd)
                    279: {
                    280: 
                    281:        register struct iobuf *bp;
                    282:        register struct fds *fp;
                    283:        register j;
                    284:        static int bufcnt = 0;
                    285: 
                    286: 
                    287:        /* The two arguments for this routine specify a buffer to
                    288:         * be operated upon and a file descriptor.  There are three
                    289:         * legal cases:
                    290:         *
                    291:         * bufnum < 0,  fd >= 0 -- assign new buffer to file descriptor fd
                    292:         * bufnum >= 0, fd >= 0 -- assign buffer "bufnum" to fd
                    293:         * bufnum >= 0, fd < 0  -- de-assign buffer "bufnum"
                    294:         */
                    295: 
                    296:        if ((bufnum < 0 && fd < 0) || bufnum >= NBUF || fd >= NFDS)
                    297:                return(-1);                             /* Invalid args */
                    298: 
                    299:        fd = (fd < 0) ? fd : realfd(fd);                /* Handle dups */
                    300: 
                    301: 
                    302:        /* Step one -- if a buffer was specified, flush it.  If the
                    303:         * last operation was a write, then write out the rest of
                    304:         * the buffer.  If the last operation was a read, then perform
                    305:         * a seek backwards on the corresponding fd to reposition the
                    306:         * next read.
                    307:         */
                    308: 
                    309:        if (bufnum >= 0){
                    310:                bp = &iobuf[bufnum];
                    311:                if (bp->b_len && (bp->b_fd >= 0))
                    312:                        if (files[bp->b_fd].fd_lastop)
                    313:                                write(bp->b_fd, bp->b_buf, bp->b_len);
                    314:                        else
                    315:                                lseek(bp->b_fd, (long)-bp->b_len, 1);
                    316: 
                    317:                bp->b_len = 0;                  /* Reset length */
                    318:                bp->b_next = 0;                 /* Reset next position */
                    319: 
                    320: 
                    321:                /* Step one point five -- if a file descriptor was
                    322:                 * specified, check to insure that it is open.  Then,
                    323:                 * reassign the buffer to that fd.
                    324:                 */
                    325: 
                    326:                if(bp->b_fd >= 0)               /* Drop old assignment */
                    327:                        files[bp->b_fd].fd_buf = -1;
                    328: 
                    329:                bp->b_fd = fd;                  /* Give buffer new fd */
                    330:                if (fd < 0) return(0);          /* If fd < 0, done */
                    331: 
                    332:                fp = &files[fd];                /* Point to new structure */
                    333: 
                    334:                if (!fp->fd_open){              /* New file is not open */
                    335:                        bp->b_fd = -1;          /* Drop assignment */
                    336:                        return(-1);
                    337:                }
                    338: 
                    339:                fp->fd_buf = bufnum;            /* New assignment */
                    340:                return(0);
                    341: 
                    342:        }
                    343: 
                    344: 
                    345:        /* Step two -- if no buffer was specified, but a file descriptor
                    346:         * was, then some existing buffer must be allocated to that fd.
                    347:         */
                    348: 
                    349:        fp = &files[fd];
                    350: 
                    351: 
                    352:        /* First, check to see if a buffer is already assigned */
                    353: 
                    354:        for (j=0; j<NBUF; j++)
                    355:                if (iobuf[j].b_fd == fd){
                    356:                        bufcnt = j;
                    357:                        goto recursive;
                    358:                }
                    359: 
                    360: 
                    361:        /* Next, scan the table of buffers looking for one
                    362:         * which is not assigned.
                    363:         */
                    364: 
                    365:        for (j=0; j<NBUF; j++) if (iobuf[j].b_fd < 0){
                    366:                bufcnt = j;
                    367:                goto recursive;
                    368:        }
                    369: 
                    370: 
                    371:        /* If no vacant buffer was found, then a buffer must
                    372:         * be allocated arbitrarily.  The static local variable
                    373:         * "bufcnt" is used for this purpose.  It contains the
                    374:         * number of the last assigned buffer.  Buffers are
                    375:         * switched in a sort-of "round robin" approach.
                    376:         */
                    377: 
                    378:        j = bufcnt;
                    379:        do {
                    380:                bp = &iobuf[j];
                    381:                fp = &files[bp->b_fd];
                    382:                if (fp->fd_pipe && (!fp->fd_lastop) && bp->b_len > 0)
                    383:                        continue;
                    384:                bufcnt = j;
                    385:                goto recursive;
                    386:        } while((j = (j+1)%NBUF) != bufcnt);
                    387:        return(-1);
                    388: 
                    389: 
                    390:        /* Now, with a recursive call to this routine,
                    391:         * switch to the new buffer.
                    392:         */
                    393: 
                    394: recursive: return(newbuf(bufcnt, fd));
                    395: 
                    396: }
                    397: 
                    398: #ifndef realfd
                    399: realfd(fd)
                    400: {
                    401: 
                    402:        register struct fds *fp;
                    403: 
                    404: 
                    405:        /* Process duplicate file descriptors.  If the main fd is
                    406:         * nonnegative, use the value of the dup number for the true fd.
                    407:         * No change is made if the file is closed.
                    408:         */
                    409: 
                    410:        fp = &files[fd];
                    411:        if (!fp->fd_open) return(fd);
                    412:        return(fp->fd_dup < 0 ? fd : fp->fd_dup);
                    413: }
                    414: #endif
                    415: 
                    416: 
                    417: readf(fd, buffer, length)
                    418: char *buffer;
                    419: {
                    420: 
                    421:        register struct fds *fp;
                    422:        register struct iobuf *bp;
                    423:        register j;
                    424:        int change, trlog, again;
                    425: 
                    426: 
                    427:        /* Handle duplicate files first.  If this file descriptor is
                    428:         * a duplicate of another one, then the other's buffer and
                    429:         * other information must be used.
                    430:         */
                    431: 
                    432:        fd = realfd(fd);
                    433: 
                    434: 
                    435:        /* If a read is to be performed on a file, all output to that
                    436:         * file must first be flushed.  If the file descriptor's last
                    437:         * function was output, use "newbuf" to flush the output,
                    438:         * retaining the buffer, and then set the mode to input.  This
                    439:         * must be done for all entries in "files" which have the same
                    440:         * major/minor number as the current file.
                    441:         */
                    442: 
                    443: 
                    444: 
                    445:        fp = &files[fd];
                    446:        if (!fp->fd_open) return(-1);           /* File not open */
                    447:        if (fp->fd_uniq){
                    448:                if (fp->fd_lastop && fp->fd_buf >= 0)
                    449:                        newbuf(fp->fd_buf, fd);
                    450:        } else for(j=0; j<NFDS; j++){
                    451:                fp = &files[realfd(j)];
                    452:                if (fp->fd_dev == files[fd].fd_dev
                    453:                        && fp->fd_ind == files[fd].fd_ind
                    454:                        && fp->fd_open
                    455:                        && fp->fd_lastop
                    456:                        && fp->fd_buf >= 0){
                    457:                                newbuf(fp->fd_buf, j);
                    458:                }
                    459:        }
                    460: 
                    461: 
                    462:        /* The above code nicely took care of any buffer associated
                    463:         * with the current fd.  Now, set the last operation on this fd
                    464:         * to read, and if no buffer is currently assigned, get one.
                    465:         */
                    466: 
                    467:        fp = &files[fd];
                    468:        fp->fd_lastop = 0;
                    469: 
                    470:        if (fp->fd_buf < 0)
                    471:                if (newbuf(-1, fd) < 0) return(read(fd, buffer, length));
                    472: 
                    473: 
                    474:        /* The flag "again" determines whether or not the read buffer
                    475:         * should be refilled when the end of it is reached.  Basically,
                    476:         * "again" is set to 0 when a read of less than one buffer length
                    477:         * occurs.  This way, terminal reads can stop at the carriage
                    478:         * return, but disc reads can still buffer in BLEN-byte chunks
                    479:         */
                    480: 
                    481:        again = 1;
                    482: 
                    483: 
                    484:        /* The variable "trlog" keeps track of how many bytes have been
                    485:         * transferred into the buffer supplied by the routine which
                    486:         * called "readf".  Initially, this number is -1 (EOF).
                    487:         */
                    488: 
                    489:        trlog = -1;
                    490: 
                    491: 
                    492:        /* The main loop is rather simple -- the buffer is continually
                    493:         * emptied and refilled until all of the requested data has been
                    494:         * transferred.
                    495:         */
                    496: 
                    497:        bp = &iobuf[fp->fd_buf];
                    498:        while(1){
                    499:                if (length <= 0) return(trlog);
                    500:                if (bp->b_len == 0 && again){
                    501:                        again = (bp->b_len=read(fd,bp->b_buf,BLEN)) == BLEN;
                    502:                        bp->b_next = 0;
                    503:                }
                    504:                if (bp->b_len <= 0) return(trlog);
                    505:                if (trlog < 0) trlog++;
                    506:                change = (bp->b_len < length) ? bp->b_len : length;
                    507:                for (j=0; j<change; j++)
                    508:                        buffer[trlog+j] = bp->b_buf[bp->b_next+j];
                    509:                trlog += change;
                    510:                bp->b_len -= change;
                    511:                bp->b_next += change;
                    512:                length -= change;
                    513:        }
                    514: }
                    515: 
                    516: 
                    517: writef(fd, buffer, length)
                    518: char *buffer;
                    519: {
                    520: 
                    521:        register struct fds *fp;
                    522:        register struct iobuf *bp;
                    523:        register j;
                    524:        int change, trlog, again;
                    525: 
                    526: 
                    527:        /* Handle duplicate files first.  If this file descriptor is
                    528:         * a duplicate of another one, then the other's buffer and
                    529:         * other information must be used.
                    530:         */
                    531: 
                    532:        fd = realfd(fd);
                    533: 
                    534: 
                    535:        /* If a write is to be performed on a file, all input from that
                    536:         * file must first be flushed.  If the file descriptor's last
                    537:         * function was input, use "newbuf" to flush the input,
                    538:         * retaining the buffer, and then set the mode to output.  This
                    539:         * must be done for all entries in "files" which have the same
                    540:         * major/minor number as the current file.
                    541:         */
                    542: 
                    543:        fp = &files[fd];
                    544:        if (!fp->fd_open) return(-1);            /* File not open */
                    545:        if (fp->fd_uniq){
                    546:                if ((!fp->fd_lastop) && fp->fd_buf >= 0)
                    547:                        newbuf(fp->fd_buf, fd);
                    548: 
                    549:        } else for(j=0; j<NFDS; j++){
                    550:                fp = &files[realfd(j)];
                    551:                if (fp->fd_dev == files[fd].fd_dev
                    552:                        && fp->fd_ind == files[fd].fd_ind
                    553:                        && fp->fd_open
                    554:                        && (!fp->fd_lastop)
                    555:                        && fp->fd_buf >= 0){
                    556:                                newbuf(fp->fd_buf, j);
                    557:                }
                    558:        }
                    559: 
                    560: 
                    561:        /* The above code nicely took care of any buffer associated
                    562:         * with the current fd.  Now, set the last operation on this fd
                    563:         * to write, and if no buffer is currently assigned, get one.
                    564:         */
                    565: 
                    566:        fp = &files[fd];
                    567:        fp->fd_lastop = 1;
                    568: 
                    569:        if (fp->fd_buf < 0)
                    570:                if (newbuf(-1, fd) < 0) return(write(fd,buffer,length));
                    571: 
                    572: 
                    573:        /* The main loop of output, like the main loop for input, is
                    574:         * rather simple.  In fact, output is easier.  It is only
                    575:         * necessary to check when the buffer is full and to flush it
                    576:         * as necessary to the file.
                    577:         */
                    578: 
                    579:        bp = &iobuf[fp->fd_buf];
                    580:        trlog = 0;
                    581:        while(1){
                    582:                if (!length) return(trlog);
                    583:                if (bp->b_len >= BLEN){
                    584:                        write(fd, bp->b_buf, bp->b_len);
                    585:                        bp->b_next = bp->b_len = 0;
                    586:                }
                    587: 
                    588:                change = ((BLEN - bp->b_len) < length) ?
                    589:                        (BLEN - bp->b_len) : length;
                    590: 
                    591:                for (j=0; j<change; j++)
                    592:                        bp->b_buf[j+bp->b_next] = buffer[j+trlog];
                    593: 
                    594:                trlog += change;
                    595:                bp->b_next = bp->b_len += change;
                    596:                length -= change;
                    597:        }
                    598: }
                    599: 
                    600: long lseekf(fd, p1, p2)
                    601: int fd, p2;
                    602: long p1;
                    603: {
                    604: 
                    605:        register struct fds *fp;
                    606:        register j;
                    607:        long lseek();
                    608: 
                    609: 
                    610:        /* A seek on a file requires a flush of the buffer for that
                    611:         * file and for any other file descriptors which are pointing
                    612:         * to the same file.
                    613:         */
                    614: 
                    615:        fd = realfd(fd);                /* Take care of dups */
                    616:        fp = &files[fd];
                    617: 
                    618:        if (!fp->fd_open) return(-1);   /* not open */
                    619: 
                    620:        if (fp->fd_uniq){
                    621:                if (fp->fd_buf >= 0) newbuf(fp->fd_buf, fd);
                    622:        } else for(j=0; j<NFDS; j++){
                    623:                fp = &files[j];
                    624:                if (fp->fd_dev == files[fd].fd_dev
                    625:                        && fp->fd_ind == files[fd].fd_ind
                    626:                        && fp->fd_open
                    627:                        && fp->fd_buf >= 0)
                    628:                                newbuf(fp->fd_buf, j);
                    629:        }
                    630: 
                    631: 
                    632:        /* Now that all of the preliminaries are over, the actual
                    633:         * seek can be performed.
                    634:         */
                    635: 
                    636:        return(lseek(fd, p1, p2));
                    637: }
                    638: 
                    639: fstatf(fd, stat_buf)
                    640: struct stat *stat_buf;
                    641: {
                    642: 
                    643:        register fd2;
                    644: 
                    645:        fd2 = realfd(fd);
                    646:        newbuf(files[fd2].fd_buf, fd2);
                    647:        return(fstat(fd, stat_buf));
                    648: 
                    649: }
                    650: 
                    651: bflush(){
                    652: 
                    653:        register j;
                    654: 
                    655:        /* Flush all buffers */
                    656: 
                    657:        for(j=0; j<NBUF; j++) newbuf(j, -1);
                    658: }
                    659: 
                    660: check()
                    661: {
                    662:        register j, k;
                    663: 
                    664:        for (j=0; j<NFDS; j++)
                    665:                if ((k=files[j].fd_buf) >= 0)
                    666:                        if (iobuf[k].b_fd != j){
                    667:                                write(2, "CONSISTENCY CHECK!\n", 19);
                    668:                                if (files[j].fd_dup != j)
                    669:                                        write(2, "BAD DUP ENTRY\n", 14);
                    670:                        }
                    671: 
                    672: 
                    673:        for (j=0; j<NBUF; j++)
                    674:                if ((k=iobuf[j].b_fd) >= 0)
                    675:                        if (files[k].fd_buf != j)
                    676:                                write(2, "CONSISTENCY CHECK2!\n", 20);
                    677: 
                    678: }
                    679: 
                    680: #endif
                    681: 
                    682: empty(fd){
                    683: 
                    684:        struct stat sbuf;
                    685:        register struct fds *fp;
                    686: 
                    687:        /* Simulate the Rand Corp.'s "empty" system call on a
                    688:         * V7 system by seeing if the given fd is a pipe, and if
                    689:         * so, whether or not it is empty.
                    690:         */
                    691: 
                    692: #ifdef NBUF
                    693:        fp = &files[realfd(fd)];
                    694: 
                    695:        if (!fp->fd_pipe || !fp->fd_open)
                    696:                return(-1);             /* Not a pipe */
                    697: 
                    698:        if (fp->fd_buf >= 0 && iobuf[fp->fd_buf].b_len > 0)
                    699:                return(0);              /* Data pending in buffer */
                    700: #endif
                    701: 
                    702:        if (fstat(fd, &sbuf) < 0)
                    703:                return(-1);             /* Can't "stat" it */
                    704: 
                    705:        return(sbuf.st_size == 0);
                    706: }

unix.superglobalmegacorp.com

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