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