1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to Berkeley by 6 * Edward Sze-Tyan Wang. 7 * 8 * %sccs.include.redist.c% 9 */ 10 11 #ifndef lint 12 static char sccsid[] = "@(#)read.c 5.1 (Berkeley) 07/21/91"; 13 #endif /* not lint */ 14 15 #include <sys/types.h> 16 #include <sys/stat.h> 17 #include <fcntl.h> 18 #include <errno.h> 19 #include <unistd.h> 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <string.h> 23 #include "extern.h" 24 25 /* 26 * bytes -- read bytes to an offset from the end and display. 27 * 28 * This is the function that reads to a byte offset from the end of the input, 29 * storing the data in a wrap-around buffer which is then displayed. If the 30 * rflag is set, the data is displayed in lines in reverse order, and this 31 * routine has the usual nastiness of trying to find the newlines. Otherwise, 32 * it is displayed from the character closest to the beginning of the input to 33 * the end. 34 */ 35 void 36 bytes(fp, off) 37 register FILE *fp; 38 long off; 39 { 40 register int ch, len, tlen; 41 register char *ep, *p, *t; 42 int wrap; 43 char *sp; 44 45 if ((sp = p = malloc(off)) == NULL) 46 err("%s", strerror(errno)); 47 48 for (wrap = 0, ep = p + off; (ch = getc(fp)) != EOF;) { 49 *p = ch; 50 if (++p == ep) { 51 wrap = 1; 52 p = sp; 53 } 54 } 55 if (ferror(fp)) 56 ierr(); 57 58 if (rflag) { 59 for (t = p - 1, len = 0; t >= sp; --t, ++len) 60 if (*t == '\n' && len) { 61 WR(t + 1, len); 62 len = 0; 63 } 64 if (wrap) { 65 tlen = len; 66 for (t = ep - 1, len = 0; t >= p; --t, ++len) 67 if (*t == '\n') { 68 if (len) { 69 WR(t + 1, len); 70 len = 0; 71 } 72 if (tlen) { 73 WR(sp, tlen); 74 tlen = 0; 75 } 76 } 77 if (len) 78 WR(t + 1, len); 79 if (tlen) 80 WR(sp, tlen); 81 } 82 } else { 83 if (wrap && (len = ep - p)) 84 WR(p, len); 85 if (len = p - sp) 86 WR(sp, len); 87 } 88 } 89 90 /* 91 * lines -- read lines to an offset from the end and display. 92 * 93 * This is the function that reads to a line offset from the end of the input, 94 * storing the data in an array of buffers which is then displayed. If the 95 * rflag is set, the data is displayed in lines in reverse order, and this 96 * routine has the usual nastiness of trying to find the newlines. Otherwise, 97 * it is displayed from the line closest to the beginning of the input to 98 * the end. 99 */ 100 void 101 lines(fp, off) 102 register FILE *fp; 103 long off; 104 { 105 struct { 106 u_int blen; 107 u_int len; 108 char *l; 109 } *lines; 110 register int ch; 111 register char *p; 112 u_int blen, cnt, recno; 113 int wrap; 114 char *sp; 115 116 if ((lines = malloc(off * sizeof(*lines))) == NULL) 117 err("%s", strerror(errno)); 118 119 sp = NULL; 120 blen = cnt = recno = wrap = 0; 121 122 while ((ch = getc(fp)) != EOF) { 123 if (++cnt > blen) { 124 if ((sp = realloc(sp, blen += 1024)) == NULL) 125 err("%s", strerror(errno)); 126 p = sp + cnt - 1; 127 } 128 *p++ = ch; 129 if (ch == '\n') { 130 if (lines[recno].blen < cnt) { 131 lines[recno].blen = cnt + 256; 132 if ((lines[recno].l = realloc(lines[recno].l, 133 lines[recno].blen)) == NULL) 134 err("%s", strerror(errno)); 135 } 136 bcopy(sp, lines[recno].l, lines[recno].len = cnt); 137 cnt = 0; 138 p = sp; 139 if (++recno == off) { 140 wrap = 1; 141 recno = 0; 142 } 143 } 144 } 145 if (ferror(fp)) 146 ierr(); 147 if (cnt) { 148 lines[recno].l = sp; 149 lines[recno].len = cnt; 150 if (++recno == off) { 151 wrap = 1; 152 recno = 0; 153 } 154 } 155 156 if (rflag) { 157 for (cnt = recno - 1; cnt >= 0; --cnt) 158 WR(lines[cnt].l, lines[cnt].len); 159 if (wrap) 160 for (cnt = off - 1; cnt >= recno; --cnt) 161 WR(lines[cnt].l, lines[cnt].len); 162 } else { 163 if (wrap) 164 for (cnt = recno; cnt < off; ++cnt) 165 WR(lines[cnt].l, lines[cnt].len); 166 for (cnt = 0; cnt < recno; ++cnt) 167 WR(lines[cnt].l, lines[cnt].len); 168 } 169 } 170