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