read.c revision 69552
1251881Speter/*- 2251881Speter * Copyright (c) 1991, 1993 3251881Speter * The Regents of the University of California. All rights reserved. 4251881Speter * 5251881Speter * This code is derived from software contributed to Berkeley by 6251881Speter * Edward Sze-Tyan Wang. 7251881Speter * 8251881Speter * Redistribution and use in source and binary forms, with or without 9251881Speter * modification, are permitted provided that the following conditions 10251881Speter * are met: 11251881Speter * 1. Redistributions of source code must retain the above copyright 12251881Speter * notice, this list of conditions and the following disclaimer. 13251881Speter * 2. Redistributions in binary form must reproduce the above copyright 14251881Speter * notice, this list of conditions and the following disclaimer in the 15251881Speter * documentation and/or other materials provided with the distribution. 16251881Speter * 3. All advertising materials mentioning features or use of this software 17251881Speter * must display the following acknowledgement: 18251881Speter * This product includes software developed by the University of 19251881Speter * California, Berkeley and its contributors. 20251881Speter * 4. Neither the name of the University nor the names of its contributors 21251881Speter * may be used to endorse or promote products derived from this software 22251881Speter * without specific prior written permission. 23251881Speter * 24251881Speter * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25251881Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26251881Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27251881Speter * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28251881Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29251881Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30251881Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31251881Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32251881Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33251881Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34251881Speter * SUCH DAMAGE. 35251881Speter */ 36251881Speter 37251881Speter#ifndef lint 38251881Speter#if 0 39251881Speterstatic char sccsid[] = "@(#)read.c 8.1 (Berkeley) 6/6/93"; 40251881Speter#endif 41251881Speterstatic const char rcsid[] = 42251881Speter "$FreeBSD: head/usr.bin/tail/read.c 69552 2000-12-03 17:05:45Z asmodai $"; 43251881Speter#endif /* not lint */ 44251881Speter 45251881Speter#include <sys/types.h> 46251881Speter#include <sys/stat.h> 47251881Speter#include <fcntl.h> 48251881Speter#include <errno.h> 49251881Speter#include <unistd.h> 50251881Speter#include <stdio.h> 51251881Speter#include <stdlib.h> 52251881Speter#include <string.h> 53251881Speter#include <err.h> 54251881Speter#include "extern.h" 55251881Speter 56251881Speter/* 57251881Speter * bytes -- read bytes to an offset from the end and display. 58251881Speter * 59251881Speter * This is the function that reads to a byte offset from the end of the input, 60251881Speter * storing the data in a wrap-around buffer which is then displayed. If the 61251881Speter * rflag is set, the data is displayed in lines in reverse order, and this 62251881Speter * routine has the usual nastiness of trying to find the newlines. Otherwise, 63251881Speter * it is displayed from the character closest to the beginning of the input to 64262253Speter * the end. 65262253Speter */ 66262253Speterint 67262253Speterbytes(fp, off) 68251881Speter FILE *fp; 69251881Speter off_t off; 70262253Speter{ 71251881Speter int ch, len, tlen; 72262253Speter char *ep, *p, *t; 73262253Speter int wrap; 74262253Speter char *sp; 75262253Speter 76251881Speter if ((sp = p = malloc(off)) == NULL) 77251881Speter err(1, "malloc"); 78251881Speter 79251881Speter for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) { 80251881Speter *p = ch; 81251881Speter if (++p == ep) { 82251881Speter wrap = 1; 83251881Speter p = sp; 84251881Speter } 85251881Speter } 86251881Speter if (ferror(fp)) { 87251881Speter ierr(); 88251881Speter return 1; 89251881Speter } 90251881Speter 91251881Speter if (rflag) { 92251881Speter for (t = p - 1, len = 0; t >= sp; --t, ++len) 93251881Speter if (*t == '\n' && len) { 94251881Speter WR(t + 1, len); 95251881Speter len = 0; 96251881Speter } 97251881Speter if (wrap) { 98251881Speter tlen = len; 99251881Speter for (t = ep - 1, len = 0; t >= p; --t, ++len) 100251881Speter if (*t == '\n') { 101251881Speter if (len) { 102251881Speter WR(t + 1, len); 103251881Speter len = 0; 104251881Speter } 105251881Speter if (tlen) { 106251881Speter WR(sp, tlen); 107251881Speter tlen = 0; 108251881Speter } 109251881Speter } 110251881Speter if (len) 111251881Speter WR(t + 1, len); 112251881Speter if (tlen) 113251881Speter WR(sp, tlen); 114251881Speter } 115251881Speter } else { 116251881Speter if (wrap && (len = ep - p)) 117251881Speter WR(p, len); 118251881Speter if (len = p - sp) 119251881Speter WR(sp, len); 120251881Speter } 121251881Speter return 0; 122251881Speter} 123251881Speter 124251881Speter/* 125251881Speter * lines -- read lines to an offset from the end and display. 126251881Speter * 127251881Speter * This is the function that reads to a line offset from the end of the input, 128251881Speter * storing the data in an array of buffers which is then displayed. If the 129251881Speter * rflag is set, the data is displayed in lines in reverse order, and this 130251881Speter * routine has the usual nastiness of trying to find the newlines. Otherwise, 131251881Speter * it is displayed from the line closest to the beginning of the input to 132251881Speter * the end. 133251881Speter */ 134251881Speterint 135251881Speterlines(fp, off) 136251881Speter FILE *fp; 137251881Speter off_t off; 138251881Speter{ 139251881Speter struct { 140251881Speter u_int blen; 141251881Speter u_int len; 142251881Speter char *l; 143251881Speter } *lines; 144251881Speter int ch; 145251881Speter char *p; 146251881Speter int blen, cnt, recno, wrap; 147253734Speter char *sp; 148253734Speter 149253734Speter if ((lines = malloc(off * sizeof(*lines))) == NULL) 150253734Speter err(1, "malloc"); 151251881Speter bzero(lines, off * sizeof(*lines)); 152251881Speter sp = NULL; 153251881Speter blen = cnt = recno = wrap = 0; 154251881Speter 155251881Speter while ((ch = getc(fp)) != EOF) { 156251881Speter if (++cnt > blen) { 157251881Speter if ((sp = realloc(sp, blen += 1024)) == NULL) 158251881Speter err(1, "realloc"); 159251881Speter p = sp + cnt - 1; 160251881Speter } 161251881Speter *p++ = ch; 162251881Speter if (ch == '\n') { 163253734Speter if (lines[recno].blen < cnt) { 164251881Speter lines[recno].blen = cnt + 256; 165251881Speter if ((lines[recno].l = realloc(lines[recno].l, 166251881Speter lines[recno].blen)) == NULL) 167251881Speter err(1, "realloc"); 168251881Speter } 169251881Speter bcopy(sp, lines[recno].l, lines[recno].len = cnt); 170251881Speter cnt = 0; 171251881Speter p = sp; 172251881Speter if (++recno == off) { 173251881Speter wrap = 1; 174251881Speter recno = 0; 175251881Speter } 176251881Speter } 177251881Speter } 178251881Speter if (ferror(fp)) { 179251881Speter ierr(); 180251881Speter return 1; 181251881Speter } 182251881Speter if (cnt) { 183251881Speter lines[recno].l = sp; 184251881Speter lines[recno].len = cnt; 185251881Speter if (++recno == off) { 186251881Speter wrap = 1; 187251881Speter recno = 0; 188251881Speter } 189251881Speter } 190251881Speter 191251881Speter if (rflag) { 192251881Speter for (cnt = recno - 1; cnt >= 0; --cnt) 193251881Speter WR(lines[cnt].l, lines[cnt].len); 194251881Speter if (wrap) 195251881Speter for (cnt = off - 1; cnt >= recno; --cnt) 196251881Speter WR(lines[cnt].l, lines[cnt].len); 197251881Speter } else { 198251881Speter if (wrap) 199251881Speter for (cnt = recno; cnt < off; ++cnt) 200251881Speter WR(lines[cnt].l, lines[cnt].len); 201251881Speter for (cnt = 0; cnt < recno; ++cnt) 202251881Speter WR(lines[cnt].l, lines[cnt].len); 203251881Speter } 204251881Speter return 0; 205251881Speter} 206251881Speter