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