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