Annotation of src/usr.bin/hexdump/display.c, Revision 1.25
1.25 ! guenther 1: /* $OpenBSD: display.c,v 1.24 2016/03/15 04:19:13 mmcc Exp $ */
1.9 pvalchev 2: /* $NetBSD: display.c,v 1.12 2001/12/07 15:14:29 bjh21 Exp $ */
1.3 deraadt 3:
1.1 deraadt 4: /*
1.9 pvalchev 5: * Copyright (c) 1989, 1993
6: * The Regents of the University of California. All rights reserved.
1.1 deraadt 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.
1.11 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 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:
33: #include <sys/stat.h>
1.9 pvalchev 34:
35: #include <ctype.h>
36: #include <err.h>
1.1 deraadt 37: #include <errno.h>
38: #include <stdio.h>
39: #include <stdlib.h>
40: #include <string.h>
1.9 pvalchev 41: #include <unistd.h>
42:
1.1 deraadt 43: #include "hexdump.h"
44:
1.21 deraadt 45: #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
46:
1.1 deraadt 47: enum _vflag vflag = FIRST;
48:
49: static off_t address; /* address/offset in stream */
50: static off_t eaddress; /* end address */
51:
1.24 mmcc 52: static void bpad(PR *);
53: static void doskip(const char *, int);
54: static u_char *get(void);
55: static __inline void print(PR *, u_char *);
1.1 deraadt 56:
1.6 deraadt 57: void
1.12 deraadt 58: display(void)
1.1 deraadt 59: {
1.8 mpech 60: FS *fs;
61: FU *fu;
62: PR *pr;
63: int cnt;
64: u_char *bp;
1.1 deraadt 65: off_t saveaddress;
1.9 pvalchev 66: u_char savech, *savebp;
1.1 deraadt 67:
1.9 pvalchev 68: savech = 0;
69: while ((bp = get()) != NULL)
1.1 deraadt 70: for (fs = fshead, savebp = bp, saveaddress = address; fs;
71: fs = fs->nextfs, bp = savebp, address = saveaddress)
72: for (fu = fs->nextfu; fu; fu = fu->nextfu) {
73: if (fu->flags&F_IGNORE)
74: break;
75: for (cnt = fu->reps; cnt; --cnt)
76: for (pr = fu->nextpr; pr; address += pr->bcnt,
77: bp += pr->bcnt, pr = pr->nextpr) {
78: if (eaddress && address >= eaddress &&
1.9 pvalchev 79: !(pr->flags & (F_TEXT|F_BPAD)))
1.1 deraadt 80: bpad(pr);
81: if (cnt == 1 && pr->nospace) {
82: savech = *pr->nospace;
83: *pr->nospace = '\0';
84: }
1.9 pvalchev 85: print(pr, bp);
1.1 deraadt 86: if (cnt == 1 && pr->nospace)
87: *pr->nospace = savech;
88: }
89: }
90: if (endfu) {
91: /*
1.9 pvalchev 92: * If eaddress not set, error or file size was multiple of
1.1 deraadt 93: * blocksize, and no partial block ever found.
94: */
95: if (!eaddress) {
96: if (!address)
97: return;
98: eaddress = address;
99: }
100: for (pr = endfu->nextpr; pr; pr = pr->nextpr)
101: switch(pr->flags) {
102: case F_ADDRESS:
1.25 ! guenther 103: (void)printf(pr->fmt, (int64_t)eaddress);
1.1 deraadt 104: break;
105: case F_TEXT:
1.9 pvalchev 106: (void)printf("%s", pr->fmt);
1.1 deraadt 107: break;
108: }
109: }
110: }
111:
1.14 deraadt 112: static __inline void
1.12 deraadt 113: print(PR *pr, u_char *bp)
1.9 pvalchev 114: {
115: double f8;
116: float f4;
117: int16_t s2;
118: int32_t s4;
119: int64_t s8;
120: u_int16_t u2;
121: u_int32_t u4;
122: u_int64_t u8;
123:
124: switch(pr->flags) {
125: case F_ADDRESS:
1.25 ! guenther 126: (void)printf(pr->fmt, (int64_t)address);
1.9 pvalchev 127: break;
128: case F_BPAD:
129: (void)printf(pr->fmt, "");
130: break;
131: case F_C:
132: conv_c(pr, bp);
133: break;
134: case F_CHAR:
135: (void)printf(pr->fmt, *bp);
136: break;
137: case F_DBL:
138: switch(pr->bcnt) {
139: case 4:
140: memmove(&f4, bp, sizeof(f4));
141: (void)printf(pr->fmt, f4);
142: break;
143: case 8:
144: memmove(&f8, bp, sizeof(f8));
145: (void)printf(pr->fmt, f8);
146: break;
147: }
148: break;
149: case F_INT:
150: switch(pr->bcnt) {
151: case 1:
1.25 ! guenther 152: (void)printf(pr->fmt, (int64_t)*bp);
1.9 pvalchev 153: break;
154: case 2:
155: memmove(&s2, bp, sizeof(s2));
1.25 ! guenther 156: (void)printf(pr->fmt, (int64_t)s2);
1.9 pvalchev 157: break;
158: case 4:
159: memmove(&s4, bp, sizeof(s4));
1.25 ! guenther 160: (void)printf(pr->fmt, (int64_t)s4);
1.9 pvalchev 161: break;
162: case 8:
163: memmove(&s8, bp, sizeof(s8));
164: (void)printf(pr->fmt, s8);
165: break;
166: }
167: break;
168: case F_P:
169: (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
170: break;
171: case F_STR:
172: (void)printf(pr->fmt, (char *)bp);
173: break;
174: case F_TEXT:
175: (void)printf("%s", pr->fmt);
176: break;
177: case F_U:
178: conv_u(pr, bp);
179: break;
180: case F_UINT:
181: switch(pr->bcnt) {
182: case 1:
1.25 ! guenther 183: (void)printf(pr->fmt, (uint64_t)*bp);
1.9 pvalchev 184: break;
185: case 2:
186: memmove(&u2, bp, sizeof(u2));
1.25 ! guenther 187: (void)printf(pr->fmt, (uint64_t)u2);
1.9 pvalchev 188: break;
189: case 4:
190: memmove(&u4, bp, sizeof(u4));
1.25 ! guenther 191: (void)printf(pr->fmt, (uint64_t)u4);
1.9 pvalchev 192: break;
193: case 8:
194: memmove(&u8, bp, sizeof(u8));
195: (void)printf(pr->fmt, u8);
196: break;
197: }
198: break;
199: }
200: }
201:
1.24 mmcc 202: static void
1.12 deraadt 203: bpad(PR *pr)
1.1 deraadt 204: {
1.9 pvalchev 205: static const char *spec = " -0+#";
1.8 mpech 206: char *p1, *p2;
1.1 deraadt 207:
208: /*
1.9 pvalchev 209: * Remove all conversion flags; '-' is the only one valid
1.1 deraadt 210: * with %s, and it's not useful here.
211: */
212: pr->flags = F_BPAD;
1.9 pvalchev 213: pr->cchar[0] = 's';
214: pr->cchar[1] = '\0';
1.1 deraadt 215: for (p1 = pr->fmt; *p1 != '%'; ++p1);
1.4 millert 216: for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
1.9 pvalchev 217: while ((*p2++ = *p1++) != '\0');
1.1 deraadt 218: }
219:
220: static char **_argv;
221:
1.24 mmcc 222: static u_char *
1.12 deraadt 223: get(void)
1.1 deraadt 224: {
225: static int ateof = 1;
226: static u_char *curp, *savp;
1.8 mpech 227: int n;
1.1 deraadt 228: int need, nread;
229: u_char *tmpp;
230:
231: if (!curp) {
1.23 tb 232: if ((curp = calloc(1, blocksize)) == NULL ||
233: (savp = calloc(1, blocksize)) == NULL)
234: err(1, NULL);
1.1 deraadt 235: } else {
236: tmpp = curp;
237: curp = savp;
238: savp = tmpp;
1.9 pvalchev 239: address += blocksize;
1.1 deraadt 240: }
241: for (need = blocksize, nread = 0;;) {
242: /*
243: * if read the right number of bytes, or at EOF for one file,
244: * and no other files are available, zero-pad the rest of the
245: * block and set the end flag.
246: */
1.9 pvalchev 247: if (!length || (ateof && !next(NULL))) {
1.1 deraadt 248: if (need == blocksize)
1.9 pvalchev 249: return(NULL);
250: if (!need && vflag != ALL &&
251: !memcmp(curp, savp, nread)) {
1.1 deraadt 252: if (vflag != DUP)
253: (void)printf("*\n");
1.9 pvalchev 254: return(NULL);
1.1 deraadt 255: }
1.9 pvalchev 256: memset((char *)curp + nread, 0, need);
1.1 deraadt 257: eaddress = address + nread;
258: return(curp);
259: }
260: n = fread((char *)curp + nread, sizeof(u_char),
1.21 deraadt 261: length == -1 ? need : MINIMUM(length, need), stdin);
1.1 deraadt 262: if (!n) {
263: if (ferror(stdin))
1.7 mickey 264: warn("%s", _argv[-1]);
1.1 deraadt 265: ateof = 1;
266: continue;
267: }
268: ateof = 0;
269: if (length != -1)
270: length -= n;
271: if (!(need -= n)) {
1.9 pvalchev 272: if (vflag == ALL || vflag == FIRST ||
273: memcmp(curp, savp, blocksize)) {
1.1 deraadt 274: if (vflag == DUP || vflag == FIRST)
275: vflag = WAIT;
276: return(curp);
277: }
278: if (vflag == WAIT)
279: (void)printf("*\n");
280: vflag = DUP;
1.9 pvalchev 281: address += blocksize;
1.1 deraadt 282: need = blocksize;
283: nread = 0;
284: }
285: else
286: nread += n;
287: }
288: }
289:
1.6 deraadt 290: int
1.12 deraadt 291: next(char **argv)
1.1 deraadt 292: {
293: static int done;
294: int statok;
295:
296: if (argv) {
297: _argv = argv;
298: return(1);
299: }
300: for (;;) {
301: if (*_argv) {
302: if (!(freopen(*_argv, "r", stdin))) {
1.7 mickey 303: warn("%s", *_argv);
1.16 miod 304: exitval = done = 1;
1.1 deraadt 305: ++_argv;
306: continue;
307: }
308: statok = done = 1;
309: } else {
310: if (done++)
311: return(0);
312: statok = 0;
313: }
1.20 millert 314: if (iobuf != NULL)
315: setvbuf(stdin, iobuf, _IOFBF, iobufsiz);
1.1 deraadt 316: if (skip)
317: doskip(statok ? *_argv : "stdin", statok);
318: if (*_argv)
319: ++_argv;
1.20 millert 320: if (!skip)
1.1 deraadt 321: return(1);
322: }
323: /* NOTREACHED */
324: }
325:
1.24 mmcc 326: static void
1.12 deraadt 327: doskip(const char *fname, int statok)
1.1 deraadt 328: {
1.17 miod 329: off_t cnt;
1.9 pvalchev 330: struct stat sb;
1.1 deraadt 331:
332: if (statok) {
1.9 pvalchev 333: if (fstat(fileno(stdin), &sb))
334: err(1, "fstat %s", fname);
1.17 miod 335: if (S_ISREG(sb.st_mode)) {
1.22 schwarze 336: if (skip > sb.st_size) {
1.17 miod 337: address += sb.st_size;
338: skip -= sb.st_size;
339: } else {
340: if (fseeko(stdin, skip, SEEK_SET))
341: err(1, "fseeko %s", fname);
342: address += skip;
343: skip = 0;
344: }
1.1 deraadt 345: return;
346: }
347: }
1.17 miod 348:
349: for (cnt = 0; cnt < skip; ++cnt)
350: if (getchar() == EOF)
351: break;
352: address += cnt;
353: skip -= cnt;
1.1 deraadt 354: }