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