Annotation of src/usr.bin/hexdump/display.c, Revision 1.6
1.6 ! deraadt 1: /* $OpenBSD: display.c,v 1.5 1998/12/16 01:28:24 deraadt Exp $ */
1.3 deraadt 2:
1.1 deraadt 3: /*
4: * Copyright (c) 1989 The Regents of the University of California.
5: * All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by the University of
18: * California, Berkeley and its contributors.
19: * 4. Neither the name of the University nor the names of its contributors
20: * may be used to endorse or promote products derived from this software
21: * without specific prior written permission.
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33: * SUCH DAMAGE.
34: */
35:
36: #ifndef lint
37: /*static char sccsid[] = "from: @(#)display.c 5.11 (Berkeley) 3/9/91";*/
1.6 ! deraadt 38: static char rcsid[] = "$OpenBSD: display.c,v 1.5 1998/12/16 01:28:24 deraadt Exp $";
1.1 deraadt 39: #endif /* not lint */
40:
41: #include <sys/param.h>
42: #include <sys/stat.h>
43: #include <unistd.h>
44: #include <errno.h>
45: #include <ctype.h>
46: #include <stdio.h>
47: #include <stdlib.h>
48: #include <string.h>
49: #include "hexdump.h"
50:
51: enum _vflag vflag = FIRST;
52:
53: static off_t address; /* address/offset in stream */
54: static off_t eaddress; /* end address */
55: static off_t savaddress; /* saved address/offset in stream */
56:
57: #define PRINT { \
58: switch(pr->flags) { \
59: case F_ADDRESS: \
60: (void)printf(pr->fmt, address); \
61: break; \
62: case F_BPAD: \
63: (void)printf(pr->fmt, ""); \
64: break; \
65: case F_C: \
66: conv_c(pr, bp); \
67: break; \
68: case F_CHAR: \
69: (void)printf(pr->fmt, *bp); \
70: break; \
71: case F_DBL: { \
72: double dval; \
73: float fval; \
74: switch(pr->bcnt) { \
75: case 4: \
76: bcopy((char *)bp, (char *)&fval, sizeof(fval)); \
77: (void)printf(pr->fmt, fval); \
78: break; \
79: case 8: \
80: bcopy((char *)bp, (char *)&dval, sizeof(dval)); \
81: (void)printf(pr->fmt, dval); \
82: break; \
83: } \
84: break; \
85: } \
86: case F_INT: { \
87: int ival; \
88: short sval; \
89: switch(pr->bcnt) { \
90: case 1: \
91: (void)printf(pr->fmt, (int)*bp); \
92: break; \
93: case 2: \
94: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \
95: (void)printf(pr->fmt, (int)sval); \
96: break; \
97: case 4: \
98: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \
99: (void)printf(pr->fmt, ival); \
100: break; \
101: } \
102: break; \
103: } \
104: case F_P: \
105: (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \
106: break; \
107: case F_STR: \
108: (void)printf(pr->fmt, (char *)bp); \
109: break; \
110: case F_TEXT: \
111: (void)printf(pr->fmt); \
112: break; \
113: case F_U: \
114: conv_u(pr, bp); \
115: break; \
116: case F_UINT: { \
117: u_int ival; \
118: u_short sval; \
119: switch(pr->bcnt) { \
120: case 1: \
121: (void)printf(pr->fmt, (u_int)*bp); \
122: break; \
123: case 2: \
124: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \
125: (void)printf(pr->fmt, (u_int)sval); \
126: break; \
127: case 4: \
128: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \
129: (void)printf(pr->fmt, ival); \
130: break; \
131: } \
132: break; \
133: } \
134: } \
135: }
136:
1.6 ! deraadt 137: void
1.1 deraadt 138: display()
139: {
140: extern FU *endfu;
141: register FS *fs;
142: register FU *fu;
143: register PR *pr;
144: register int cnt;
145: register u_char *bp;
146: off_t saveaddress;
147: u_char savech, *savebp, *get();
148:
1.6 ! deraadt 149: while ((bp = get()))
1.1 deraadt 150: for (fs = fshead, savebp = bp, saveaddress = address; fs;
151: fs = fs->nextfs, bp = savebp, address = saveaddress)
152: for (fu = fs->nextfu; fu; fu = fu->nextfu) {
153: if (fu->flags&F_IGNORE)
154: break;
155: for (cnt = fu->reps; cnt; --cnt)
156: for (pr = fu->nextpr; pr; address += pr->bcnt,
157: bp += pr->bcnt, pr = pr->nextpr) {
158: if (eaddress && address >= eaddress &&
159: !(pr->flags&(F_TEXT|F_BPAD)))
160: bpad(pr);
161: if (cnt == 1 && pr->nospace) {
162: savech = *pr->nospace;
163: *pr->nospace = '\0';
164: }
165: PRINT;
166: if (cnt == 1 && pr->nospace)
167: *pr->nospace = savech;
168: }
169: }
170: if (endfu) {
171: /*
172: * if eaddress not set, error or file size was multiple of
173: * blocksize, and no partial block ever found.
174: */
175: if (!eaddress) {
176: if (!address)
177: return;
178: eaddress = address;
179: }
180: for (pr = endfu->nextpr; pr; pr = pr->nextpr)
181: switch(pr->flags) {
182: case F_ADDRESS:
183: (void)printf(pr->fmt, eaddress);
184: break;
185: case F_TEXT:
186: (void)printf(pr->fmt);
187: break;
188: }
189: }
190: }
191:
1.6 ! deraadt 192: void
1.1 deraadt 193: bpad(pr)
194: PR *pr;
195: {
196: static char *spec = " -0+#";
197: register char *p1, *p2;
198:
199: /*
200: * remove all conversion flags; '-' is the only one valid
201: * with %s, and it's not useful here.
202: */
203: pr->flags = F_BPAD;
204: *pr->cchar = 's';
205: for (p1 = pr->fmt; *p1 != '%'; ++p1);
1.4 millert 206: for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
1.6 ! deraadt 207: while ((*p2++ = *p1++))
! 208: ;
1.1 deraadt 209: }
210:
211: static char **_argv;
212:
213: u_char *
214: get()
215: {
216: extern enum _vflag vflag;
217: extern int length;
218: static int ateof = 1;
219: static u_char *curp, *savp;
220: register int n;
221: int need, nread;
1.5 deraadt 222: int valid_save = 0;
1.1 deraadt 223: u_char *tmpp;
224:
225: if (!curp) {
226: curp = (u_char *)emalloc(blocksize);
227: savp = (u_char *)emalloc(blocksize);
228: } else {
229: tmpp = curp;
230: curp = savp;
231: savp = tmpp;
232: address = savaddress += blocksize;
1.5 deraadt 233: valid_save = 1;
1.1 deraadt 234: }
235: for (need = blocksize, nread = 0;;) {
236: /*
237: * if read the right number of bytes, or at EOF for one file,
238: * and no other files are available, zero-pad the rest of the
239: * block and set the end flag.
240: */
241: if (!length || ateof && !next((char **)NULL)) {
242: if (need == blocksize)
243: return((u_char *)NULL);
1.5 deraadt 244: if (vflag != ALL && valid_save &&
245: !bcmp(curp, savp, nread)) {
1.1 deraadt 246: if (vflag != DUP)
247: (void)printf("*\n");
248: return((u_char *)NULL);
249: }
250: bzero((char *)curp + nread, need);
251: eaddress = address + nread;
252: return(curp);
253: }
254: n = fread((char *)curp + nread, sizeof(u_char),
255: length == -1 ? need : MIN(length, need), stdin);
256: if (!n) {
257: if (ferror(stdin))
258: (void)fprintf(stderr, "hexdump: %s: %s\n",
259: _argv[-1], strerror(errno));
260: ateof = 1;
261: continue;
262: }
263: ateof = 0;
264: if (length != -1)
265: length -= n;
266: if (!(need -= n)) {
1.5 deraadt 267: if (vflag == ALL || vflag == FIRST || !valid_save ||
1.1 deraadt 268: bcmp(curp, savp, blocksize)) {
269: if (vflag == DUP || vflag == FIRST)
270: vflag = WAIT;
271: return(curp);
272: }
273: if (vflag == WAIT)
274: (void)printf("*\n");
275: vflag = DUP;
276: address = savaddress += blocksize;
277: need = blocksize;
278: nread = 0;
279: }
280: else
281: nread += n;
282: }
283: }
284:
285: extern off_t skip; /* bytes to skip */
286:
1.6 ! deraadt 287: int
1.1 deraadt 288: next(argv)
289: char **argv;
290: {
1.2 deraadt 291: extern int exitval;
1.1 deraadt 292: static int done;
293: int statok;
294:
295: if (argv) {
296: _argv = argv;
297: return(1);
298: }
299: for (;;) {
300: if (*_argv) {
301: if (!(freopen(*_argv, "r", stdin))) {
302: (void)fprintf(stderr, "hexdump: %s: %s\n",
303: *_argv, strerror(errno));
304: exitval = 1;
305: ++_argv;
306: continue;
307: }
308: statok = done = 1;
309: } else {
310: if (done++)
311: return(0);
312: statok = 0;
313: }
314: if (skip)
315: doskip(statok ? *_argv : "stdin", statok);
316: if (*_argv)
317: ++_argv;
318: if (!skip)
319: return(1);
320: }
321: /* NOTREACHED */
322: }
323:
1.6 ! deraadt 324: void
1.1 deraadt 325: doskip(fname, statok)
326: char *fname;
327: int statok;
328: {
329: struct stat sbuf;
330:
331: if (statok) {
332: if (fstat(fileno(stdin), &sbuf)) {
333: (void)fprintf(stderr, "hexdump: %s: %s.\n",
334: fname, strerror(errno));
335: exit(1);
336: }
337: if (skip >= sbuf.st_size) {
338: skip -= sbuf.st_size;
339: address += sbuf.st_size;
340: return;
341: }
342: }
343: if (fseek(stdin, skip, SEEK_SET)) {
344: (void)fprintf(stderr, "hexdump: %s: %s.\n",
345: fname, strerror(errno));
346: exit(1);
347: }
348: savaddress = address += skip;
349: skip = 0;
350: }
351:
352: char *
353: emalloc(size)
354: int size;
355: {
356: char *p;
357:
358: if (!(p = malloc((u_int)size)))
359: nomem();
360: bzero(p, size);
361: return(p);
362: }
363:
1.6 ! deraadt 364: void
1.1 deraadt 365: nomem()
366: {
367: (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));
368: exit(1);
369: }