2 * Copyright (c) 1991, 1993
3 * The Regents of the University of California. All rights reserved.
5 * This code is derived from software contributed to Berkeley by
6 * Edward Sze-Tyan Wang.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
40 static char sccsid[] = "@(#)forward.c 8.1 (Berkeley) 6/6/93";
43 #include <sys/types.h>
47 #include <sys/event.h>
59 static void rlines __P((FILE *, long, struct stat *));
61 /* defines for inner loop actions */
67 * forward -- display the file, from an offset, forward.
69 * There are eight separate cases for this -- regular and non-regular
70 * files, by bytes or lines and from the beginning or end of the file.
72 * FBYTES byte offset from the beginning of the file
74 * NOREG read, counting bytes
76 * FLINES line offset from the beginning of the file
77 * REG read, counting lines
78 * NOREG read, counting lines
80 * RBYTES byte offset from the end of the file
82 * NOREG cyclically read characters into a wrap-around buffer
85 * REG mmap the file and step back until reach the correct offset.
86 * NOREG cyclically read lines into a wrap-around array of buffers
89 forward(fp, style, off, sbp)
96 int action = USE_SLEEP;
104 if (S_ISREG(sbp->st_mode)) {
105 if (sbp->st_size < off)
107 if (fseek(fp, off, SEEK_SET) == -1) {
112 if ((ch = getc(fp)) == EOF) {
124 if ((ch = getc(fp)) == EOF) {
131 if (ch == '\n' && !--off)
136 if (S_ISREG(sbp->st_mode)) {
137 if (sbp->st_size >= off &&
138 fseek(fp, -off, SEEK_END) == -1) {
142 } else if (off == 0) {
143 while (getc(fp) != EOF);
153 if (S_ISREG(sbp->st_mode))
155 if (fseek(fp, 0L, SEEK_END) == -1) {
160 rlines(fp, off, sbp);
162 while (getc(fp) != EOF);
181 while ((ch = getc(fp)) != EOF)
182 if (putchar(ch) == EOF)
188 (void)fflush(stdout);
196 struct timespec ts = { 0, 0 };
198 if (Fflag && fileno(fp) != STDIN_FILENO) {
199 ev[n].ident = fileno(fp);
200 ev[n].filter = EVFILT_VNODE;
201 ev[n].flags = EV_ADD | EV_ENABLE | EV_CLEAR;
202 ev[n].fflags = NOTE_DELETE | NOTE_RENAME;
205 ev[n].ident = fileno(fp);
206 ev[n].filter = EVFILT_READ;
207 ev[n].flags = EV_ADD | EV_ENABLE;
210 if (kevent(kq, ev, n, NULL, 0, &ts) < 0) {
221 if (kevent(kq, NULL, 0, ev, 1, NULL) < 0)
224 if (ev->filter == EVFILT_VNODE) {
225 /* file was rotated, wait until it reappears */
227 } else if (ev->data < 0) {
228 /* file shrank, reposition to end */
229 if (fseek(fp, 0L, SEEK_END) == -1) {
237 (void) usleep(250000);
240 if (Fflag && fileno(fp) != STDIN_FILENO &&
241 stat(fname, &sb2) != -1) {
242 if (sb2.st_ino != sbp->st_ino ||
243 sb2.st_dev != sbp->st_dev ||
244 sb2.st_rdev != sbp->st_rdev ||
246 fp = freopen(fname, "r", fp);
262 * rlines -- display the last offset lines of the file.
274 if (!(size = sbp->st_size))
277 if (size > SIZE_T_MAX) {
283 if ((start = mmap(NULL, (size_t)size,
284 PROT_READ, MAP_SHARED, fileno(fp), (off_t)0)) == MAP_FAILED) {
289 /* Last char is special, ignore whether newline or not. */
290 for (p = start + size - 1; --size;)
291 if (*--p == '\n' && !--off) {
296 /* Set the file pointer to reflect the length displayed. */
297 size = sbp->st_size - size;
299 if (fseek(fp, (long)sbp->st_size, SEEK_SET) == -1) {
303 if (munmap(start, (size_t)sbp->st_size)) {