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