Annotation of src/usr.bin/tail/read.c, Revision 1.14
1.14 ! deraadt 1: /* $OpenBSD: read.c,v 1.13 2008/06/02 06:01:15 otto Exp $ */
1.1 deraadt 2: /* $NetBSD: read.c,v 1.4 1994/11/23 07:42:07 jtc Exp $ */
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.
1.7 millert 19: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #include <sys/types.h>
37: #include <sys/stat.h>
1.8 kjell 38: #include <sys/limits.h>
1.3 millert 39:
40: #include <err.h>
1.1 deraadt 41: #include <stdio.h>
42: #include <stdlib.h>
43: #include <string.h>
1.3 millert 44: #include <unistd.h>
45:
1.1 deraadt 46: #include "extern.h"
47:
48: /*
49: * bytes -- read bytes to an offset from the end and display.
50: *
51: * This is the function that reads to a byte offset from the end of the input,
52: * storing the data in a wrap-around buffer which is then displayed. If the
53: * rflag is set, the data is displayed in lines in reverse order, and this
54: * routine has the usual nastiness of trying to find the newlines. Otherwise,
55: * it is displayed from the character closest to the beginning of the input to
56: * the end.
1.4 ericj 57: *
1.5 mpech 58: * A non-zero return means an (non-fatal) error occurred.
1.4 ericj 59: *
1.1 deraadt 60: */
1.4 ericj 61: int
1.9 kjell 62: bytes(FILE *fp, off_t off)
1.1 deraadt 63: {
1.8 kjell 64: int ch;
65: size_t len, tlen;
1.6 mpech 66: char *ep, *p, *t;
1.1 deraadt 67: int wrap;
68: char *sp;
69:
1.8 kjell 70: if (off > SIZE_T_MAX)
71: errx(1, "offset too large");
72:
1.1 deraadt 73: if ((sp = p = malloc(off)) == NULL)
1.3 millert 74: err(1, NULL);
1.1 deraadt 75:
76: for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) {
77: *p = ch;
78: if (++p == ep) {
79: wrap = 1;
80: p = sp;
81: }
82: }
83: if (ferror(fp)) {
84: ierr();
1.10 otto 85: free(sp);
1.4 ericj 86: return(1);
1.1 deraadt 87: }
88:
89: if (rflag) {
90: for (t = p - 1, len = 0; t >= sp; --t, ++len)
91: if (*t == '\n' && len) {
92: WR(t + 1, len);
93: len = 0;
94: }
95: if (wrap) {
96: tlen = len;
97: for (t = ep - 1, len = 0; t >= p; --t, ++len)
98: if (*t == '\n') {
99: if (len) {
100: WR(t + 1, len);
101: len = 0;
102: }
103: if (tlen) {
104: WR(sp, tlen);
105: tlen = 0;
106: }
107: }
108: if (len)
109: WR(t + 1, len);
110: if (tlen)
111: WR(sp, tlen);
112: }
113: } else {
114: if (wrap && (len = ep - p))
115: WR(p, len);
1.3 millert 116: if ((len = p - sp))
1.1 deraadt 117: WR(sp, len);
118: }
1.10 otto 119:
120: free(sp);
1.4 ericj 121: return(0);
1.1 deraadt 122: }
123:
124: /*
125: * lines -- read lines to an offset from the end and display.
126: *
127: * This is the function that reads to a line offset from the end of the input,
128: * storing the data in an array of buffers which is then displayed. If the
129: * rflag is set, the data is displayed in lines in reverse order, and this
130: * routine has the usual nastiness of trying to find the newlines. Otherwise,
131: * it is displayed from the line closest to the beginning of the input to
132: * the end.
1.4 ericj 133: *
1.5 mpech 134: * A non-zero return means an (non-fatal) error occurred.
1.4 ericj 135: *
1.1 deraadt 136: */
1.4 ericj 137: int
1.9 kjell 138: lines(FILE *fp, off_t off)
1.1 deraadt 139: {
140: struct {
1.8 kjell 141: size_t blen;
142: size_t len;
1.1 deraadt 143: char *l;
144: } *lines;
1.11 otto 145: int ch, rc = 0;
1.6 mpech 146: char *p = NULL;
1.8 kjell 147: int wrap;
148: size_t cnt, recno, blen, newsize;
149: char *sp = NULL, *newp = NULL;
150:
151: if (off > SIZE_T_MAX)
152: errx(1, "offset too large");
1.1 deraadt 153:
1.3 millert 154: if ((lines = calloc(off, sizeof(*lines))) == NULL)
155: err(1, NULL);
1.1 deraadt 156:
157: blen = cnt = recno = wrap = 0;
158:
159: while ((ch = getc(fp)) != EOF) {
160: if (++cnt > blen) {
1.8 kjell 161: newsize = blen + 1024;
162: if ((newp = realloc(sp, newsize)) == NULL)
1.3 millert 163: err(1, NULL);
1.8 kjell 164: sp = newp;
165: blen = newsize;
1.1 deraadt 166: p = sp + cnt - 1;
167: }
168: *p++ = ch;
169: if (ch == '\n') {
170: if (lines[recno].blen < cnt) {
1.8 kjell 171: newsize = cnt + 256;
172: if ((newp = realloc(lines[recno].l,
173: newsize)) == NULL)
1.3 millert 174: err(1, NULL);
1.8 kjell 175: lines[recno].l = newp;
176: lines[recno].blen = newsize;
1.1 deraadt 177: }
1.3 millert 178: memcpy(lines[recno].l, sp, (lines[recno].len = cnt));
1.1 deraadt 179: cnt = 0;
180: p = sp;
181: if (++recno == off) {
182: wrap = 1;
183: recno = 0;
184: }
185: }
186: }
187: if (ferror(fp)) {
188: ierr();
1.11 otto 189: rc = 1;
190: goto done;
1.1 deraadt 191: }
192: if (cnt) {
193: lines[recno].l = sp;
194: lines[recno].len = cnt;
1.13 otto 195: sp = NULL;
1.1 deraadt 196: if (++recno == off) {
197: wrap = 1;
198: recno = 0;
199: }
200: }
201:
202: if (rflag) {
1.8 kjell 203: for (cnt = recno; cnt > 0; --cnt)
204: WR(lines[cnt - 1].l, lines[cnt - 1].len);
1.1 deraadt 205: if (wrap)
1.8 kjell 206: for (cnt = off; cnt > recno; --cnt)
207: WR(lines[cnt - 1].l, lines[cnt - 1].len);
1.1 deraadt 208: } else {
209: if (wrap)
210: for (cnt = recno; cnt < off; ++cnt)
211: WR(lines[cnt].l, lines[cnt].len);
212: for (cnt = 0; cnt < recno; ++cnt)
213: WR(lines[cnt].l, lines[cnt].len);
214: }
1.11 otto 215: done:
216: for (cnt = 0; cnt < off; cnt++)
217: free(lines[cnt].l);
218: free(sp);
219: free(lines);
220: return(rc);
1.1 deraadt 221: }