Annotation of src/usr.bin/hexdump/display.c, Revision 1.5
1.5 ! deraadt 1: /* $OpenBSD: display.c,v 1.4 1997/01/17 07:12:37 millert 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.5 ! deraadt 38: static char rcsid[] = "$OpenBSD: display.c,v 1.4 1997/01/17 07:12:37 millert 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:
137: display()
138: {
139: extern FU *endfu;
140: register FS *fs;
141: register FU *fu;
142: register PR *pr;
143: register int cnt;
144: register u_char *bp;
145: off_t saveaddress;
146: u_char savech, *savebp, *get();
147:
148: while (bp = get())
149: for (fs = fshead, savebp = bp, saveaddress = address; fs;
150: fs = fs->nextfs, bp = savebp, address = saveaddress)
151: for (fu = fs->nextfu; fu; fu = fu->nextfu) {
152: if (fu->flags&F_IGNORE)
153: break;
154: for (cnt = fu->reps; cnt; --cnt)
155: for (pr = fu->nextpr; pr; address += pr->bcnt,
156: bp += pr->bcnt, pr = pr->nextpr) {
157: if (eaddress && address >= eaddress &&
158: !(pr->flags&(F_TEXT|F_BPAD)))
159: bpad(pr);
160: if (cnt == 1 && pr->nospace) {
161: savech = *pr->nospace;
162: *pr->nospace = '\0';
163: }
164: PRINT;
165: if (cnt == 1 && pr->nospace)
166: *pr->nospace = savech;
167: }
168: }
169: if (endfu) {
170: /*
171: * if eaddress not set, error or file size was multiple of
172: * blocksize, and no partial block ever found.
173: */
174: if (!eaddress) {
175: if (!address)
176: return;
177: eaddress = address;
178: }
179: for (pr = endfu->nextpr; pr; pr = pr->nextpr)
180: switch(pr->flags) {
181: case F_ADDRESS:
182: (void)printf(pr->fmt, eaddress);
183: break;
184: case F_TEXT:
185: (void)printf(pr->fmt);
186: break;
187: }
188: }
189: }
190:
191: bpad(pr)
192: PR *pr;
193: {
194: static char *spec = " -0+#";
195: register char *p1, *p2;
196:
197: /*
198: * remove all conversion flags; '-' is the only one valid
199: * with %s, and it's not useful here.
200: */
201: pr->flags = F_BPAD;
202: *pr->cchar = 's';
203: for (p1 = pr->fmt; *p1 != '%'; ++p1);
1.4 millert 204: for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
1.1 deraadt 205: while (*p2++ = *p1++);
206: }
207:
208: static char **_argv;
209:
210: u_char *
211: get()
212: {
213: extern enum _vflag vflag;
214: extern int length;
215: static int ateof = 1;
216: static u_char *curp, *savp;
217: register int n;
218: int need, nread;
1.5 ! deraadt 219: int valid_save = 0;
1.1 deraadt 220: u_char *tmpp;
221:
222: if (!curp) {
223: curp = (u_char *)emalloc(blocksize);
224: savp = (u_char *)emalloc(blocksize);
225: } else {
226: tmpp = curp;
227: curp = savp;
228: savp = tmpp;
229: address = savaddress += blocksize;
1.5 ! deraadt 230: valid_save = 1;
1.1 deraadt 231: }
232: for (need = blocksize, nread = 0;;) {
233: /*
234: * if read the right number of bytes, or at EOF for one file,
235: * and no other files are available, zero-pad the rest of the
236: * block and set the end flag.
237: */
238: if (!length || ateof && !next((char **)NULL)) {
239: if (need == blocksize)
240: return((u_char *)NULL);
1.5 ! deraadt 241: if (vflag != ALL && valid_save &&
! 242: !bcmp(curp, savp, nread)) {
1.1 deraadt 243: if (vflag != DUP)
244: (void)printf("*\n");
245: return((u_char *)NULL);
246: }
247: bzero((char *)curp + nread, need);
248: eaddress = address + nread;
249: return(curp);
250: }
251: n = fread((char *)curp + nread, sizeof(u_char),
252: length == -1 ? need : MIN(length, need), stdin);
253: if (!n) {
254: if (ferror(stdin))
255: (void)fprintf(stderr, "hexdump: %s: %s\n",
256: _argv[-1], strerror(errno));
257: ateof = 1;
258: continue;
259: }
260: ateof = 0;
261: if (length != -1)
262: length -= n;
263: if (!(need -= n)) {
1.5 ! deraadt 264: if (vflag == ALL || vflag == FIRST || !valid_save ||
1.1 deraadt 265: bcmp(curp, savp, blocksize)) {
266: if (vflag == DUP || vflag == FIRST)
267: vflag = WAIT;
268: return(curp);
269: }
270: if (vflag == WAIT)
271: (void)printf("*\n");
272: vflag = DUP;
273: address = savaddress += blocksize;
274: need = blocksize;
275: nread = 0;
276: }
277: else
278: nread += n;
279: }
280: }
281:
282: extern off_t skip; /* bytes to skip */
283:
284: next(argv)
285: char **argv;
286: {
1.2 deraadt 287: extern int exitval;
1.1 deraadt 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))) {
298: (void)fprintf(stderr, "hexdump: %s: %s\n",
299: *_argv, strerror(errno));
300: exitval = 1;
301: ++_argv;
302: continue;
303: }
304: statok = done = 1;
305: } else {
306: if (done++)
307: return(0);
308: statok = 0;
309: }
310: if (skip)
311: doskip(statok ? *_argv : "stdin", statok);
312: if (*_argv)
313: ++_argv;
314: if (!skip)
315: return(1);
316: }
317: /* NOTREACHED */
318: }
319:
320: doskip(fname, statok)
321: char *fname;
322: int statok;
323: {
324: struct stat sbuf;
325:
326: if (statok) {
327: if (fstat(fileno(stdin), &sbuf)) {
328: (void)fprintf(stderr, "hexdump: %s: %s.\n",
329: fname, strerror(errno));
330: exit(1);
331: }
332: if (skip >= sbuf.st_size) {
333: skip -= sbuf.st_size;
334: address += sbuf.st_size;
335: return;
336: }
337: }
338: if (fseek(stdin, skip, SEEK_SET)) {
339: (void)fprintf(stderr, "hexdump: %s: %s.\n",
340: fname, strerror(errno));
341: exit(1);
342: }
343: savaddress = address += skip;
344: skip = 0;
345: }
346:
347: char *
348: emalloc(size)
349: int size;
350: {
351: char *p;
352:
353: if (!(p = malloc((u_int)size)))
354: nomem();
355: bzero(p, size);
356: return(p);
357: }
358:
359: nomem()
360: {
361: (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));
362: exit(1);
363: }