Annotation of src/usr.bin/hexdump/display.c, Revision 1.4
1.4 ! millert 1: /* $OpenBSD: display.c,v 1.3 1996/06/26 05:34:17 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.4 ! millert 38: static char rcsid[] = "$OpenBSD: display.c,v 1.3 1996/06/26 05:34:17 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:
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;
219: u_char *tmpp;
220:
221: if (!curp) {
222: curp = (u_char *)emalloc(blocksize);
223: savp = (u_char *)emalloc(blocksize);
224: } else {
225: tmpp = curp;
226: curp = savp;
227: savp = tmpp;
228: address = savaddress += blocksize;
229: }
230: for (need = blocksize, nread = 0;;) {
231: /*
232: * if read the right number of bytes, or at EOF for one file,
233: * and no other files are available, zero-pad the rest of the
234: * block and set the end flag.
235: */
236: if (!length || ateof && !next((char **)NULL)) {
237: if (need == blocksize)
238: return((u_char *)NULL);
239: if (vflag != ALL && !bcmp(curp, savp, nread)) {
240: if (vflag != DUP)
241: (void)printf("*\n");
242: return((u_char *)NULL);
243: }
244: bzero((char *)curp + nread, need);
245: eaddress = address + nread;
246: return(curp);
247: }
248: n = fread((char *)curp + nread, sizeof(u_char),
249: length == -1 ? need : MIN(length, need), stdin);
250: if (!n) {
251: if (ferror(stdin))
252: (void)fprintf(stderr, "hexdump: %s: %s\n",
253: _argv[-1], strerror(errno));
254: ateof = 1;
255: continue;
256: }
257: ateof = 0;
258: if (length != -1)
259: length -= n;
260: if (!(need -= n)) {
261: if (vflag == ALL || vflag == FIRST ||
262: bcmp(curp, savp, blocksize)) {
263: if (vflag == DUP || vflag == FIRST)
264: vflag = WAIT;
265: return(curp);
266: }
267: if (vflag == WAIT)
268: (void)printf("*\n");
269: vflag = DUP;
270: address = savaddress += blocksize;
271: need = blocksize;
272: nread = 0;
273: }
274: else
275: nread += n;
276: }
277: }
278:
279: extern off_t skip; /* bytes to skip */
280:
281: next(argv)
282: char **argv;
283: {
1.2 deraadt 284: extern int exitval;
1.1 deraadt 285: static int done;
286: int statok;
287:
288: if (argv) {
289: _argv = argv;
290: return(1);
291: }
292: for (;;) {
293: if (*_argv) {
294: if (!(freopen(*_argv, "r", stdin))) {
295: (void)fprintf(stderr, "hexdump: %s: %s\n",
296: *_argv, strerror(errno));
297: exitval = 1;
298: ++_argv;
299: continue;
300: }
301: statok = done = 1;
302: } else {
303: if (done++)
304: return(0);
305: statok = 0;
306: }
307: if (skip)
308: doskip(statok ? *_argv : "stdin", statok);
309: if (*_argv)
310: ++_argv;
311: if (!skip)
312: return(1);
313: }
314: /* NOTREACHED */
315: }
316:
317: doskip(fname, statok)
318: char *fname;
319: int statok;
320: {
321: struct stat sbuf;
322:
323: if (statok) {
324: if (fstat(fileno(stdin), &sbuf)) {
325: (void)fprintf(stderr, "hexdump: %s: %s.\n",
326: fname, strerror(errno));
327: exit(1);
328: }
329: if (skip >= sbuf.st_size) {
330: skip -= sbuf.st_size;
331: address += sbuf.st_size;
332: return;
333: }
334: }
335: if (fseek(stdin, skip, SEEK_SET)) {
336: (void)fprintf(stderr, "hexdump: %s: %s.\n",
337: fname, strerror(errno));
338: exit(1);
339: }
340: savaddress = address += skip;
341: skip = 0;
342: }
343:
344: char *
345: emalloc(size)
346: int size;
347: {
348: char *p;
349:
350: if (!(p = malloc((u_int)size)))
351: nomem();
352: bzero(p, size);
353: return(p);
354: }
355:
356: nomem()
357: {
358: (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));
359: exit(1);
360: }