11590Srgrimes/*- 21590Srgrimes * Copyright (c) 1991, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * This code is derived from software contributed to Berkeley by 61590Srgrimes * Edward Sze-Tyan Wang. 71590Srgrimes * 81590Srgrimes * Redistribution and use in source and binary forms, with or without 91590Srgrimes * modification, are permitted provided that the following conditions 101590Srgrimes * are met: 111590Srgrimes * 1. Redistributions of source code must retain the above copyright 121590Srgrimes * notice, this list of conditions and the following disclaimer. 131590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 141590Srgrimes * notice, this list of conditions and the following disclaimer in the 151590Srgrimes * documentation and/or other materials provided with the distribution. 161590Srgrimes * 4. Neither the name of the University nor the names of its contributors 171590Srgrimes * may be used to endorse or promote products derived from this software 181590Srgrimes * without specific prior written permission. 191590Srgrimes * 201590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 211590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 221590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 231590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 241590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 251590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 261590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 271590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 281590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 291590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 301590Srgrimes * SUCH DAMAGE. 311590Srgrimes */ 321590Srgrimes 3387712Smarkm#include <sys/cdefs.h> 3487712Smarkm 3587712Smarkm__FBSDID("$FreeBSD$"); 3687712Smarkm 371590Srgrimes#ifndef lint 3887712Smarkmstatic const char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93"; 3969528Sasmodai#endif 401590Srgrimes 411590Srgrimes#include <sys/types.h> 421590Srgrimes#include <sys/stat.h> 4387712Smarkm 4487712Smarkm#include <err.h> 4587712Smarkm#include <errno.h> 461590Srgrimes#include <fcntl.h> 471590Srgrimes#include <stdio.h> 481590Srgrimes#include <stdlib.h> 491590Srgrimes#include <string.h> 5087712Smarkm#include <unistd.h> 5187712Smarkm 521590Srgrimes#include "extern.h" 531590Srgrimes 541590Srgrimes/* 551590Srgrimes * bytes -- read bytes to an offset from the end and display. 561590Srgrimes * 571590Srgrimes * This is the function that reads to a byte offset from the end of the input, 581590Srgrimes * storing the data in a wrap-around buffer which is then displayed. If the 591590Srgrimes * rflag is set, the data is displayed in lines in reverse order, and this 601590Srgrimes * routine has the usual nastiness of trying to find the newlines. Otherwise, 611590Srgrimes * it is displayed from the character closest to the beginning of the input to 621590Srgrimes * the end. 631590Srgrimes */ 6417339Sadamint 65193488Sbrianbytes(FILE *fp, const char *fn, off_t off) 661590Srgrimes{ 6769552Sasmodai int ch, len, tlen; 6869552Sasmodai char *ep, *p, *t; 691590Srgrimes int wrap; 701590Srgrimes char *sp; 711590Srgrimes 721590Srgrimes if ((sp = p = malloc(off)) == NULL) 7317825Speter err(1, "malloc"); 741590Srgrimes 751590Srgrimes for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) { 761590Srgrimes *p = ch; 771590Srgrimes if (++p == ep) { 781590Srgrimes wrap = 1; 791590Srgrimes p = sp; 801590Srgrimes } 811590Srgrimes } 821590Srgrimes if (ferror(fp)) { 83193488Sbrian ierr(fn); 84172719Skib free(sp); 8517339Sadam return 1; 861590Srgrimes } 871590Srgrimes 881590Srgrimes if (rflag) { 891590Srgrimes for (t = p - 1, len = 0; t >= sp; --t, ++len) 901590Srgrimes if (*t == '\n' && len) { 911590Srgrimes WR(t + 1, len); 921590Srgrimes len = 0; 931590Srgrimes } 941590Srgrimes if (wrap) { 951590Srgrimes tlen = len; 961590Srgrimes for (t = ep - 1, len = 0; t >= p; --t, ++len) 971590Srgrimes if (*t == '\n') { 981590Srgrimes if (len) { 991590Srgrimes WR(t + 1, len); 1001590Srgrimes len = 0; 1011590Srgrimes } 1021590Srgrimes if (tlen) { 1031590Srgrimes WR(sp, tlen); 1041590Srgrimes tlen = 0; 1051590Srgrimes } 1061590Srgrimes } 1071590Srgrimes if (len) 1081590Srgrimes WR(t + 1, len); 1091590Srgrimes if (tlen) 1101590Srgrimes WR(sp, tlen); 1111590Srgrimes } 1121590Srgrimes } else { 1131590Srgrimes if (wrap && (len = ep - p)) 1141590Srgrimes WR(p, len); 11587712Smarkm len = p - sp; 11687712Smarkm if (len) 1171590Srgrimes WR(sp, len); 1181590Srgrimes } 119172719Skib 120172719Skib free(sp); 12117341Sadam return 0; 1221590Srgrimes} 1231590Srgrimes 1241590Srgrimes/* 1251590Srgrimes * lines -- read lines to an offset from the end and display. 1261590Srgrimes * 1271590Srgrimes * This is the function that reads to a line offset from the end of the input, 1281590Srgrimes * storing the data in an array of buffers which is then displayed. If the 1291590Srgrimes * rflag is set, the data is displayed in lines in reverse order, and this 1301590Srgrimes * routine has the usual nastiness of trying to find the newlines. Otherwise, 1311590Srgrimes * it is displayed from the line closest to the beginning of the input to 1321590Srgrimes * the end. 1331590Srgrimes */ 13417339Sadamint 135193488Sbrianlines(FILE *fp, const char *fn, off_t off) 1361590Srgrimes{ 1371590Srgrimes struct { 138116156Smarkm int blen; 1391590Srgrimes u_int len; 1401590Srgrimes char *l; 14187712Smarkm } *llines; 142172719Skib int ch, rc; 14387712Smarkm char *p, *sp; 144116156Smarkm int blen, cnt, recno, wrap; 1451590Srgrimes 146245184Sdelphij if ((llines = calloc(off, sizeof(*llines))) == NULL) 147245184Sdelphij err(1, "calloc"); 148173285Scharnier p = sp = NULL; 1491590Srgrimes blen = cnt = recno = wrap = 0; 150172719Skib rc = 0; 1511590Srgrimes 1521590Srgrimes while ((ch = getc(fp)) != EOF) { 1531590Srgrimes if (++cnt > blen) { 1541590Srgrimes if ((sp = realloc(sp, blen += 1024)) == NULL) 15517825Speter err(1, "realloc"); 1561590Srgrimes p = sp + cnt - 1; 1571590Srgrimes } 1581590Srgrimes *p++ = ch; 1591590Srgrimes if (ch == '\n') { 160116156Smarkm if ((int)llines[recno].blen < cnt) { 16187712Smarkm llines[recno].blen = cnt + 256; 16287712Smarkm if ((llines[recno].l = realloc(llines[recno].l, 16387712Smarkm llines[recno].blen)) == NULL) 16417825Speter err(1, "realloc"); 1651590Srgrimes } 16687712Smarkm bcopy(sp, llines[recno].l, llines[recno].len = cnt); 1671590Srgrimes cnt = 0; 1681590Srgrimes p = sp; 1691590Srgrimes if (++recno == off) { 1701590Srgrimes wrap = 1; 1711590Srgrimes recno = 0; 1721590Srgrimes } 1731590Srgrimes } 1741590Srgrimes } 1751590Srgrimes if (ferror(fp)) { 176193488Sbrian ierr(fn); 177172719Skib rc = 1; 178172719Skib goto done; 1791590Srgrimes } 1801590Srgrimes if (cnt) { 18187712Smarkm llines[recno].l = sp; 182173838Savatar sp = NULL; 18387712Smarkm llines[recno].len = cnt; 1841590Srgrimes if (++recno == off) { 1851590Srgrimes wrap = 1; 1861590Srgrimes recno = 0; 1871590Srgrimes } 1881590Srgrimes } 1891590Srgrimes 1901590Srgrimes if (rflag) { 191116156Smarkm for (cnt = recno - 1; cnt >= 0; --cnt) 19287712Smarkm WR(llines[cnt].l, llines[cnt].len); 1931590Srgrimes if (wrap) 194116156Smarkm for (cnt = off - 1; cnt >= recno; --cnt) 19587712Smarkm WR(llines[cnt].l, llines[cnt].len); 1961590Srgrimes } else { 1971590Srgrimes if (wrap) 198116156Smarkm for (cnt = recno; cnt < off; ++cnt) 19987712Smarkm WR(llines[cnt].l, llines[cnt].len); 200116156Smarkm for (cnt = 0; cnt < recno; ++cnt) 20187712Smarkm WR(llines[cnt].l, llines[cnt].len); 2021590Srgrimes } 203172719Skibdone: 204172719Skib for (cnt = 0; cnt < off; cnt++) 205172719Skib free(llines[cnt].l); 206172719Skib free(sp); 207172719Skib free(llines); 208172719Skib return (rc); 2091590Srgrimes} 210