Home | History | Annotate | Line # | Download | only in tail
      1  1.17  christos /*	$NetBSD: read.c,v 1.17 2011/09/03 10:59:10 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.17  christos __RCSID("$NetBSD: read.c,v 1.17 2011/09/03 10:59:10 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.15     lukem  * displaybytes -- 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.15     lukem displaybytes(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.16  christos 		xerr(1, "malloc");
     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.17  christos 		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.13  christos 		if ((len = p - sp) != 0)
    116   1.1     glass 			WR(sp, len);
    117   1.1     glass 	}
    118  1.17  christos 	return 0;
    119   1.1     glass }
    120   1.1     glass 
    121   1.1     glass /*
    122  1.15     lukem  * displaylines -- 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.15     lukem displaylines(FILE *fp, off_t off)
    135   1.1     glass {
    136   1.1     glass 	struct {
    137  1.15     lukem 		int blen;
    138  1.15     lukem 		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.16  christos 		xerr(1, "malloc");
    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.16  christos 				xerr(1, "realloc");
    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.16  christos 					xerr(1, "realloc");
    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.17  christos 		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.17  christos 	return 0;
    210   1.1     glass }
    211