xref: /minix3/usr.bin/tail/read.c (revision a967d739abf6b9e18d75e99925030c41b4f075ca)
1*a967d739SClaudio Martella /*	$NetBSD: read.c,v 1.17 2011/09/03 10:59:10 christos Exp $	*/
2*a967d739SClaudio Martella 
3*a967d739SClaudio Martella /*-
4*a967d739SClaudio Martella  * Copyright (c) 1991, 1993
5*a967d739SClaudio Martella  *	The Regents of the University of California.  All rights reserved.
6*a967d739SClaudio Martella  *
7*a967d739SClaudio Martella  * This code is derived from software contributed to Berkeley by
8*a967d739SClaudio Martella  * Edward Sze-Tyan Wang.
9*a967d739SClaudio Martella  *
10*a967d739SClaudio Martella  * Redistribution and use in source and binary forms, with or without
11*a967d739SClaudio Martella  * modification, are permitted provided that the following conditions
12*a967d739SClaudio Martella  * are met:
13*a967d739SClaudio Martella  * 1. Redistributions of source code must retain the above copyright
14*a967d739SClaudio Martella  *    notice, this list of conditions and the following disclaimer.
15*a967d739SClaudio Martella  * 2. Redistributions in binary form must reproduce the above copyright
16*a967d739SClaudio Martella  *    notice, this list of conditions and the following disclaimer in the
17*a967d739SClaudio Martella  *    documentation and/or other materials provided with the distribution.
18*a967d739SClaudio Martella  * 3. Neither the name of the University nor the names of its contributors
19*a967d739SClaudio Martella  *    may be used to endorse or promote products derived from this software
20*a967d739SClaudio Martella  *    without specific prior written permission.
21*a967d739SClaudio Martella  *
22*a967d739SClaudio Martella  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
23*a967d739SClaudio Martella  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24*a967d739SClaudio Martella  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25*a967d739SClaudio Martella  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
26*a967d739SClaudio Martella  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27*a967d739SClaudio Martella  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28*a967d739SClaudio Martella  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29*a967d739SClaudio Martella  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30*a967d739SClaudio Martella  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31*a967d739SClaudio Martella  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*a967d739SClaudio Martella  * SUCH DAMAGE.
33*a967d739SClaudio Martella  */
34*a967d739SClaudio Martella 
35*a967d739SClaudio Martella #include <sys/cdefs.h>
36*a967d739SClaudio Martella #ifndef lint
37*a967d739SClaudio Martella #if 0
38*a967d739SClaudio Martella static char sccsid[] = "@(#)read.c	8.1 (Berkeley) 6/6/93";
39*a967d739SClaudio Martella #endif
40*a967d739SClaudio Martella __RCSID("$NetBSD: read.c,v 1.17 2011/09/03 10:59:10 christos Exp $");
41*a967d739SClaudio Martella #endif /* not lint */
42*a967d739SClaudio Martella 
43*a967d739SClaudio Martella #include <sys/types.h>
44*a967d739SClaudio Martella #include <sys/stat.h>
45*a967d739SClaudio Martella #include <fcntl.h>
46*a967d739SClaudio Martella #include <errno.h>
47*a967d739SClaudio Martella #include <unistd.h>
48*a967d739SClaudio Martella #include <stdio.h>
49*a967d739SClaudio Martella #include <stdlib.h>
50*a967d739SClaudio Martella #include <string.h>
51*a967d739SClaudio Martella #include "extern.h"
52*a967d739SClaudio Martella 
53*a967d739SClaudio Martella /*
54*a967d739SClaudio Martella  * displaybytes -- read bytes to an offset from the end and display.
55*a967d739SClaudio Martella  *
56*a967d739SClaudio Martella  * This is the function that reads to a byte offset from the end of the input,
57*a967d739SClaudio Martella  * storing the data in a wrap-around buffer which is then displayed.  If the
58*a967d739SClaudio Martella  * rflag is set, the data is displayed in lines in reverse order, and this
59*a967d739SClaudio Martella  * routine has the usual nastiness of trying to find the newlines.  Otherwise,
60*a967d739SClaudio Martella  * it is displayed from the character closest to the beginning of the input to
61*a967d739SClaudio Martella  * the end.
62*a967d739SClaudio Martella  *
63*a967d739SClaudio Martella  * Non-zero return means than a (non-fatal) error occurred.
64*a967d739SClaudio Martella  */
65*a967d739SClaudio Martella int
displaybytes(FILE * fp,off_t off)66*a967d739SClaudio Martella displaybytes(FILE *fp, off_t off)
67*a967d739SClaudio Martella {
68*a967d739SClaudio Martella 	int ch, len, tlen;
69*a967d739SClaudio Martella 	char *ep, *p, *t;
70*a967d739SClaudio Martella 	int wrap;
71*a967d739SClaudio Martella 	char *sp;
72*a967d739SClaudio Martella 
73*a967d739SClaudio Martella 	if ((sp = p = malloc(off)) == NULL)
74*a967d739SClaudio Martella 		xerr(1, "malloc");
75*a967d739SClaudio Martella 
76*a967d739SClaudio Martella 	for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
77*a967d739SClaudio Martella 		*p = ch;
78*a967d739SClaudio Martella 		if (++p == ep) {
79*a967d739SClaudio Martella 			wrap = 1;
80*a967d739SClaudio Martella 			p = sp;
81*a967d739SClaudio Martella 		}
82*a967d739SClaudio Martella 	}
83*a967d739SClaudio Martella 	if (ferror(fp)) {
84*a967d739SClaudio Martella 		ierr();
85*a967d739SClaudio Martella 		return 1;
86*a967d739SClaudio Martella 	}
87*a967d739SClaudio Martella 
88*a967d739SClaudio Martella 	if (rflag) {
89*a967d739SClaudio Martella 		for (t = p - 1, len = 0; t >= sp; --t, ++len)
90*a967d739SClaudio Martella 			if (*t == '\n' && len) {
91*a967d739SClaudio Martella 				WR(t + 1, len);
92*a967d739SClaudio Martella 				len = 0;
93*a967d739SClaudio Martella 		}
94*a967d739SClaudio Martella 		if (wrap) {
95*a967d739SClaudio Martella 			tlen = len;
96*a967d739SClaudio Martella 			for (t = ep - 1, len = 0; t >= p; --t, ++len)
97*a967d739SClaudio Martella 				if (*t == '\n') {
98*a967d739SClaudio Martella 					if (len) {
99*a967d739SClaudio Martella 						WR(t + 1, len);
100*a967d739SClaudio Martella 						len = 0;
101*a967d739SClaudio Martella 					}
102*a967d739SClaudio Martella 					if (tlen) {
103*a967d739SClaudio Martella 						WR(sp, tlen);
104*a967d739SClaudio Martella 						tlen = 0;
105*a967d739SClaudio Martella 					}
106*a967d739SClaudio Martella 				}
107*a967d739SClaudio Martella 			if (len)
108*a967d739SClaudio Martella 				WR(t + 1, len);
109*a967d739SClaudio Martella 			if (tlen)
110*a967d739SClaudio Martella 				WR(sp, tlen);
111*a967d739SClaudio Martella 		}
112*a967d739SClaudio Martella 	} else {
113*a967d739SClaudio Martella 		if (wrap && (len = ep - p))
114*a967d739SClaudio Martella 			WR(p, len);
115*a967d739SClaudio Martella 		if ((len = p - sp) != 0)
116*a967d739SClaudio Martella 			WR(sp, len);
117*a967d739SClaudio Martella 	}
118*a967d739SClaudio Martella 	return 0;
119*a967d739SClaudio Martella }
120*a967d739SClaudio Martella 
121*a967d739SClaudio Martella /*
122*a967d739SClaudio Martella  * displaylines -- read lines to an offset from the end and display.
123*a967d739SClaudio Martella  *
124*a967d739SClaudio Martella  * This is the function that reads to a line offset from the end of the input,
125*a967d739SClaudio Martella  * storing the data in an array of buffers which is then displayed.  If the
126*a967d739SClaudio Martella  * rflag is set, the data is displayed in lines in reverse order, and this
127*a967d739SClaudio Martella  * routine has the usual nastiness of trying to find the newlines.  Otherwise,
128*a967d739SClaudio Martella  * it is displayed from the line closest to the beginning of the input to
129*a967d739SClaudio Martella  * the end.
130*a967d739SClaudio Martella  *
131*a967d739SClaudio Martella  * Non-zero return means than a (non-fatal) error occurred.
132*a967d739SClaudio Martella  */
133*a967d739SClaudio Martella int
displaylines(FILE * fp,off_t off)134*a967d739SClaudio Martella displaylines(FILE *fp, off_t off)
135*a967d739SClaudio Martella {
136*a967d739SClaudio Martella 	struct {
137*a967d739SClaudio Martella 		int blen;
138*a967d739SClaudio Martella 		int len;
139*a967d739SClaudio Martella 		char *l;
140*a967d739SClaudio Martella 	} *lines;
141*a967d739SClaudio Martella 	int ch;
142*a967d739SClaudio Martella 	char *p;
143*a967d739SClaudio Martella 	int blen, cnt, recno, wrap;
144*a967d739SClaudio Martella 	char *sp, *n;
145*a967d739SClaudio Martella 
146*a967d739SClaudio Martella 	p = NULL;
147*a967d739SClaudio Martella 	if ((lines = malloc(off * sizeof(*lines))) == NULL)
148*a967d739SClaudio Martella 		xerr(1, "malloc");
149*a967d739SClaudio Martella 
150*a967d739SClaudio Martella 	memset(lines, 0, sizeof(*lines) * off);
151*a967d739SClaudio Martella 
152*a967d739SClaudio Martella 	sp = NULL;
153*a967d739SClaudio Martella 	blen = cnt = recno = wrap = 0;
154*a967d739SClaudio Martella 
155*a967d739SClaudio Martella 	while ((ch = getc(fp)) != EOF) {
156*a967d739SClaudio Martella 		if (++cnt > blen) {
157*a967d739SClaudio Martella 			if ((n = realloc(sp, blen + 1024)) == NULL)
158*a967d739SClaudio Martella 				xerr(1, "realloc");
159*a967d739SClaudio Martella 			sp = n;
160*a967d739SClaudio Martella 			blen += 1024;
161*a967d739SClaudio Martella 			p = sp + cnt - 1;
162*a967d739SClaudio Martella 		}
163*a967d739SClaudio Martella 		*p++ = ch;
164*a967d739SClaudio Martella 		if (ch == '\n') {
165*a967d739SClaudio Martella 			if (lines[recno].blen < cnt) {
166*a967d739SClaudio Martella 				if ((n = realloc(lines[recno].l,
167*a967d739SClaudio Martella 				    cnt + 256)) == NULL)
168*a967d739SClaudio Martella 					xerr(1, "realloc");
169*a967d739SClaudio Martella 				lines[recno].l = n;
170*a967d739SClaudio Martella 				lines[recno].blen = cnt + 256;
171*a967d739SClaudio Martella 			}
172*a967d739SClaudio Martella 			memmove(lines[recno].l, sp, lines[recno].len = cnt);
173*a967d739SClaudio Martella 			cnt = 0;
174*a967d739SClaudio Martella 			p = sp;
175*a967d739SClaudio Martella 			if (++recno == off) {
176*a967d739SClaudio Martella 				wrap = 1;
177*a967d739SClaudio Martella 				recno = 0;
178*a967d739SClaudio Martella 			}
179*a967d739SClaudio Martella 		}
180*a967d739SClaudio Martella 	}
181*a967d739SClaudio Martella 	if (ferror(fp)) {
182*a967d739SClaudio Martella 		free(lines);
183*a967d739SClaudio Martella 		ierr();
184*a967d739SClaudio Martella 		return 1;
185*a967d739SClaudio Martella 	}
186*a967d739SClaudio Martella 	if (cnt) {
187*a967d739SClaudio Martella 		lines[recno].l = sp;
188*a967d739SClaudio Martella 		lines[recno].len = cnt;
189*a967d739SClaudio Martella 		if (++recno == off) {
190*a967d739SClaudio Martella 			wrap = 1;
191*a967d739SClaudio Martella 			recno = 0;
192*a967d739SClaudio Martella 		}
193*a967d739SClaudio Martella 	}
194*a967d739SClaudio Martella 
195*a967d739SClaudio Martella 	if (rflag) {
196*a967d739SClaudio Martella 		for (cnt = recno - 1; cnt >= 0; --cnt)
197*a967d739SClaudio Martella 			WR(lines[cnt].l, lines[cnt].len);
198*a967d739SClaudio Martella 		if (wrap)
199*a967d739SClaudio Martella 			for (cnt = off - 1; cnt >= recno; --cnt)
200*a967d739SClaudio Martella 				WR(lines[cnt].l, lines[cnt].len);
201*a967d739SClaudio Martella 	} else {
202*a967d739SClaudio Martella 		if (wrap)
203*a967d739SClaudio Martella 			for (cnt = recno; cnt < off; ++cnt)
204*a967d739SClaudio Martella 				WR(lines[cnt].l, lines[cnt].len);
205*a967d739SClaudio Martella 		for (cnt = 0; cnt < recno; ++cnt)
206*a967d739SClaudio Martella 			WR(lines[cnt].l, lines[cnt].len);
207*a967d739SClaudio Martella 	}
208*a967d739SClaudio Martella 	free(lines);
209*a967d739SClaudio Martella 	return 0;
210*a967d739SClaudio Martella }
211