read.c revision 69552
129347Speter/*- 229347Speter * Copyright (c) 1991, 1993 329347Speter * The Regents of the University of California. All rights reserved. 429347Speter * 529347Speter * This code is derived from software contributed to Berkeley by 629347Speter * Edward Sze-Tyan Wang. 729347Speter * 829347Speter * Redistribution and use in source and binary forms, with or without 929347Speter * modification, are permitted provided that the following conditions 1029347Speter * are met: 1129347Speter * 1. Redistributions of source code must retain the above copyright 1229347Speter * notice, this list of conditions and the following disclaimer. 1329347Speter * 2. Redistributions in binary form must reproduce the above copyright 1429347Speter * notice, this list of conditions and the following disclaimer in the 1529347Speter * documentation and/or other materials provided with the distribution. 1629347Speter * 3. All advertising materials mentioning features or use of this software 1729347Speter * must display the following acknowledgement: 1829347Speter * This product includes software developed by the University of 1929347Speter * California, Berkeley and its contributors. 2029347Speter * 4. Neither the name of the University nor the names of its contributors 2129347Speter * may be used to endorse or promote products derived from this software 2229347Speter * without specific prior written permission. 2329347Speter * 2429347Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2529347Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2629347Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2729347Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2850477Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2929347Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3029347Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3129347Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3229347Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3329347Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3499593Smike * SUCH DAMAGE. 3599593Smike */ 3629347Speter 3772093Sasmodai#ifndef lint 3829347Speter#if 0 3929347Speterstatic char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93"; 4099593Smike#endif 4199593Smikestatic const char rcsid[] = 4229347Speter "$FreeBSD: head/usr.bin/tail/read.c 69552 2000-12-03 17:05:45Z asmodai $"; 4333059Sbde#endif /* not lint */ 4429347Speter 4529347Speter#include <sys/types.h> 4629347Speter#include <sys/stat.h> 4729347Speter#include <fcntl.h> 4829347Speter#include <errno.h> 4929347Speter#include <unistd.h> 5029347Speter#include <stdio.h> 5129347Speter#include <stdlib.h> 5229347Speter#include <string.h> 5329347Speter#include <err.h> 5429347Speter#include "extern.h" 5529347Speter 5629347Speter/* 5729347Speter * bytes -- read bytes to an offset from the end and display. 5829347Speter * 5929347Speter * This is the function that reads to a byte offset from the end of the input, 6029347Speter * storing the data in a wrap-around buffer which is then displayed. If the 6129347Speter * rflag is set, the data is displayed in lines in reverse order, and this 6229347Speter * routine has the usual nastiness of trying to find the newlines. Otherwise, 6329347Speter * it is displayed from the character closest to the beginning of the input to 6429347Speter * the end. 6529347Speter */ 6629347Speterint 6729347Speterbytes(fp, off) 6829347Speter FILE *fp; 6999710Smike off_t off; 7094997Salfred{ 7194997Salfred int ch, len, tlen; 7299593Smike char *ep, *p, *t; 7331727Swollman int wrap; 7431727Swollman char *sp; 7529347Speter 7629347Speter if ((sp = p = malloc(off)) == NULL) 7729347Speter err(1, "malloc"); 7829347Speter 7929347Speter for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) { 8029347Speter *p = ch; 8129347Speter if (++p == ep) { 8299593Smike wrap = 1; 8399593Smike p = sp; 8431727Swollman } 8531727Swollman } 8631727Swollman if (ferror(fp)) { 8729373Speter ierr(); 8833059Sbde return 1; 8933059Sbde } 9033059Sbde 9129373Speter if (rflag) { 9233059Sbde for (t = p - 1, len = 0; t >= sp; --t, ++len) 9329373Speter if (*t == '\n' && len) { 9499593Smike WR(t + 1, len); 9599593Smike len = 0; 9655205Speter } 9733059Sbde if (wrap) { 98275986Sdchagin tlen = len; 99275986Sdchagin for (t = ep - 1, len = 0; t >= p; --t, ++len) 100275986Sdchagin if (*t == '\n') { 101275986Sdchagin if (len) { 102275986Sdchagin WR(t + 1, len); 103275986Sdchagin len = 0; 104275986Sdchagin } 105275986Sdchagin if (tlen) { 106275986Sdchagin WR(sp, tlen); 107275986Sdchagin tlen = 0; 108275986Sdchagin } 109275986Sdchagin } 110275986Sdchagin if (len) 11129347Speter WR(t + 1, len); 11299593Smike if (tlen) 113275986Sdchagin WR(sp, tlen); 114275986Sdchagin } 115275986Sdchagin } else { 116275986Sdchagin if (wrap && (len = ep - p)) 117275986Sdchagin WR(p, len); 11829347Speter if (len = p - sp) 11929347Speter WR(sp, len); 12055205Speter } 12133059Sbde return 0; 12229347Speter} 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. 133 */ 134int 135lines(fp, off) 136 FILE *fp; 137 off_t off; 138{ 139 struct { 140 u_int blen; 141 u_int len; 142 char *l; 143 } *lines; 144 int ch; 145 char *p; 146 int blen, cnt, recno, wrap; 147 char *sp; 148 149 if ((lines = malloc(off * sizeof(*lines))) == NULL) 150 err(1, "malloc"); 151 bzero(lines, off * sizeof(*lines)); 152 sp = NULL; 153 blen = cnt = recno = wrap = 0; 154 155 while ((ch = getc(fp)) != EOF) { 156 if (++cnt > blen) { 157 if ((sp = realloc(sp, blen += 1024)) == NULL) 158 err(1, "realloc"); 159 p = sp + cnt - 1; 160 } 161 *p++ = ch; 162 if (ch == '\n') { 163 if (lines[recno].blen < cnt) { 164 lines[recno].blen = cnt + 256; 165 if ((lines[recno].l = realloc(lines[recno].l, 166 lines[recno].blen)) == NULL) 167 err(1, "realloc"); 168 } 169 bcopy(sp, lines[recno].l, lines[recno].len = cnt); 170 cnt = 0; 171 p = sp; 172 if (++recno == off) { 173 wrap = 1; 174 recno = 0; 175 } 176 } 177 } 178 if (ferror(fp)) { 179 ierr(); 180 return 1; 181 } 182 if (cnt) { 183 lines[recno].l = sp; 184 lines[recno].len = cnt; 185 if (++recno == off) { 186 wrap = 1; 187 recno = 0; 188 } 189 } 190 191 if (rflag) { 192 for (cnt = recno - 1; cnt >= 0; --cnt) 193 WR(lines[cnt].l, lines[cnt].len); 194 if (wrap) 195 for (cnt = off - 1; cnt >= recno; --cnt) 196 WR(lines[cnt].l, lines[cnt].len); 197 } else { 198 if (wrap) 199 for (cnt = recno; cnt < off; ++cnt) 200 WR(lines[cnt].l, lines[cnt].len); 201 for (cnt = 0; cnt < recno; ++cnt) 202 WR(lines[cnt].l, lines[cnt].len); 203 } 204 return 0; 205} 206