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