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