home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.bin / tail / forward.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-02-13  |  5.2 KB  |  203 lines

  1. /*-
  2.  * Copyright (c) 1991 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * This code is derived from software contributed to Berkeley by
  6.  * Edward Sze-Tyan Wang.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)forward.c    5.4 (Berkeley) 2/12/92";
  39. #endif /* not lint */
  40.  
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <sys/time.h>
  44. #include <sys/mman.h>
  45. #include <fcntl.h>
  46. #include <errno.h>
  47. #include <unistd.h>
  48. #include <stdio.h>
  49. #include <stdlib.h>
  50. #include <string.h>
  51. #include "extern.h"
  52.  
  53. static void rlines __P((FILE *, long, struct stat *));
  54.  
  55. /*
  56.  * forward -- display the file, from an offset, forward.
  57.  *
  58.  * There are eight separate cases for this -- regular and non-regular
  59.  * files, by bytes or lines and from the beginning or end of the file.
  60.  *
  61.  * FBYTES    byte offset from the beginning of the file
  62.  *    REG    seek
  63.  *    NOREG    read, counting bytes
  64.  *
  65.  * FLINES    line offset from the beginning of the file
  66.  *    REG    read, counting lines
  67.  *    NOREG    read, counting lines
  68.  *
  69.  * RBYTES    byte offset from the end of the file
  70.  *    REG    seek
  71.  *    NOREG    cyclically read characters into a wrap-around buffer
  72.  *
  73.  * RLINES
  74.  *    REG    mmap the file and step back until reach the correct offset.
  75.  *    NOREG    cyclically read lines into a wrap-around array of buffers
  76.  */
  77. void
  78. forward(fp, style, off, sbp)
  79.     FILE *fp;
  80.     enum STYLE style;
  81.     long off;
  82.     struct stat *sbp;
  83. {
  84.     register int ch;
  85.     struct timeval second;
  86.     fd_set zero;
  87.  
  88.     switch(style) {
  89.     case FBYTES:
  90.         if (off == 0)
  91.             break;
  92.         if (S_ISREG(sbp->st_mode)) {
  93.             if (sbp->st_size < off)
  94.                 off = sbp->st_size;
  95.             if (fseek(fp, off, SEEK_SET) == -1)
  96.                 ierr();
  97.         } else while (off--)
  98.             if ((ch = getc(fp)) == EOF) {
  99.                 if (ferror(fp))
  100.                     ierr();
  101.                     break;
  102.                 }
  103.         break;
  104.     case FLINES:
  105.         if (off == 0)
  106.             break;
  107.         for (;;) {
  108.             if ((ch = getc(fp)) == EOF) {
  109.                 if (ferror(fp))
  110.                     ierr();
  111.                 break;
  112.             }
  113.             if (ch == '\n' && !--off)
  114.                 break;
  115.         }
  116.         break;
  117.     case RBYTES:
  118.         if (S_ISREG(sbp->st_mode)) {
  119.             if (sbp->st_size >= off &&
  120.                 fseek(fp, -off, SEEK_END) == -1)
  121.                 ierr();
  122.         } else if (off == 0) {
  123.             while (getc(fp) != EOF);
  124.             if (ferror(fp))
  125.                 ierr();
  126.         } else
  127.             bytes(fp, off);
  128.         break;
  129.     case RLINES:
  130.         if (S_ISREG(sbp->st_mode))
  131.             if (!off) {
  132.                 if (fseek(fp, 0L, SEEK_END) == -1)
  133.                     ierr();
  134.             } else
  135.                 rlines(fp, off, sbp);
  136.         else if (off == 0) {
  137.             while (getc(fp) != EOF);
  138.             if (ferror(fp))
  139.                 ierr();
  140.         } else
  141.             lines(fp, off);
  142.         break;
  143.     }
  144.  
  145.     /*
  146.      * We pause for one second after displaying any data that has
  147.      * accumulated since we read the file.
  148.      */
  149.     if (fflag) {
  150.         FD_ZERO(&zero);
  151.         second.tv_sec = 1;
  152.         second.tv_usec = 0;
  153.     }
  154.  
  155.     for (;;) {
  156.         while ((ch = getc(fp)) != EOF)
  157.             if (putchar(ch) == EOF)
  158.                 oerr();
  159.         if (ferror(fp))
  160.             ierr();
  161.         (void)fflush(stdout);
  162.         if (!fflag)
  163.             break;
  164.         /* Sleep is eight system calls.  Do it fast. */
  165.         if (select(0, &zero, &zero, &zero, &second) == -1)
  166.             err("select: %s", strerror(errno));
  167.         clearerr(fp);
  168.     }
  169. }
  170.  
  171. /*
  172.  * rlines -- display the last offset lines of the file.
  173.  */
  174. static void
  175. rlines(fp, off, sbp)
  176.     FILE *fp;
  177.     long off;
  178.     struct stat *sbp;
  179. {
  180.     register off_t size;
  181.     register char *p;
  182.  
  183.     if (!(size = sbp->st_size))
  184.         return;
  185.  
  186.     if ((p = mmap(NULL,
  187.         size, PROT_READ, MAP_FILE, fileno(fp), (off_t)0)) == (caddr_t)-1)
  188.         err("%s", strerror(errno));
  189.  
  190.     /* Last char is special, ignore whether newline or not. */
  191.     for (p += size - 1; --size;)
  192.         if (*--p == '\n' && !--off) {
  193.             ++p;
  194.             break;
  195.         }
  196.  
  197.     /* Set the file pointer to reflect the length displayed. */
  198.     size = sbp->st_size - size;
  199.     WR(p, size);
  200.     if (fseek(fp, sbp->st_size, SEEK_SET) == -1)
  201.         ierr();
  202. }
  203.