Annotation of src/usr.bin/hexdump/display.c, Revision 1.7
1.7 ! mickey 1: /* $OpenBSD: display.c,v 1.6 2001/07/12 05:17:10 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.7 ! mickey 38: static char rcsid[] = "$OpenBSD: display.c,v 1.6 2001/07/12 05:17:10 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>
1.7 ! mickey 49: #include <err.h>
1.1 deraadt 50: #include "hexdump.h"
51:
52: enum _vflag vflag = FIRST;
53:
54: static off_t address; /* address/offset in stream */
55: static off_t eaddress; /* end address */
56: static off_t savaddress; /* saved address/offset in stream */
57:
58: #define PRINT { \
59: switch(pr->flags) { \
60: case F_ADDRESS: \
61: (void)printf(pr->fmt, address); \
62: break; \
63: case F_BPAD: \
64: (void)printf(pr->fmt, ""); \
65: break; \
66: case F_C: \
67: conv_c(pr, bp); \
68: break; \
69: case F_CHAR: \
70: (void)printf(pr->fmt, *bp); \
71: break; \
72: case F_DBL: { \
73: double dval; \
74: float fval; \
75: switch(pr->bcnt) { \
76: case 4: \
77: bcopy((char *)bp, (char *)&fval, sizeof(fval)); \
78: (void)printf(pr->fmt, fval); \
79: break; \
80: case 8: \
81: bcopy((char *)bp, (char *)&dval, sizeof(dval)); \
82: (void)printf(pr->fmt, dval); \
83: break; \
84: } \
85: break; \
86: } \
87: case F_INT: { \
88: int ival; \
89: short sval; \
90: switch(pr->bcnt) { \
91: case 1: \
92: (void)printf(pr->fmt, (int)*bp); \
93: break; \
94: case 2: \
95: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \
96: (void)printf(pr->fmt, (int)sval); \
97: break; \
98: case 4: \
99: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \
100: (void)printf(pr->fmt, ival); \
101: break; \
102: } \
103: break; \
104: } \
105: case F_P: \
106: (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \
107: break; \
108: case F_STR: \
109: (void)printf(pr->fmt, (char *)bp); \
110: break; \
111: case F_TEXT: \
112: (void)printf(pr->fmt); \
113: break; \
114: case F_U: \
115: conv_u(pr, bp); \
116: break; \
117: case F_UINT: { \
118: u_int ival; \
119: u_short sval; \
120: switch(pr->bcnt) { \
121: case 1: \
122: (void)printf(pr->fmt, (u_int)*bp); \
123: break; \
124: case 2: \
125: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \
126: (void)printf(pr->fmt, (u_int)sval); \
127: break; \
128: case 4: \
129: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \
130: (void)printf(pr->fmt, ival); \
131: break; \
132: } \
133: break; \
134: } \
135: } \
136: }
137:
1.6 deraadt 138: void
1.1 deraadt 139: display()
140: {
141: extern FU *endfu;
142: register FS *fs;
143: register FU *fu;
144: register PR *pr;
145: register int cnt;
146: register u_char *bp;
147: off_t saveaddress;
148: u_char savech, *savebp, *get();
149:
1.6 deraadt 150: while ((bp = get()))
1.1 deraadt 151: for (fs = fshead, savebp = bp, saveaddress = address; fs;
152: fs = fs->nextfs, bp = savebp, address = saveaddress)
153: for (fu = fs->nextfu; fu; fu = fu->nextfu) {
154: if (fu->flags&F_IGNORE)
155: break;
156: for (cnt = fu->reps; cnt; --cnt)
157: for (pr = fu->nextpr; pr; address += pr->bcnt,
158: bp += pr->bcnt, pr = pr->nextpr) {
159: if (eaddress && address >= eaddress &&
160: !(pr->flags&(F_TEXT|F_BPAD)))
161: bpad(pr);
162: if (cnt == 1 && pr->nospace) {
163: savech = *pr->nospace;
164: *pr->nospace = '\0';
165: }
166: PRINT;
167: if (cnt == 1 && pr->nospace)
168: *pr->nospace = savech;
169: }
170: }
171: if (endfu) {
172: /*
173: * if eaddress not set, error or file size was multiple of
174: * blocksize, and no partial block ever found.
175: */
176: if (!eaddress) {
177: if (!address)
178: return;
179: eaddress = address;
180: }
181: for (pr = endfu->nextpr; pr; pr = pr->nextpr)
182: switch(pr->flags) {
183: case F_ADDRESS:
184: (void)printf(pr->fmt, eaddress);
185: break;
186: case F_TEXT:
187: (void)printf(pr->fmt);
188: break;
189: }
190: }
191: }
192:
1.6 deraadt 193: void
1.1 deraadt 194: bpad(pr)
195: PR *pr;
196: {
197: static char *spec = " -0+#";
198: register char *p1, *p2;
199:
200: /*
201: * remove all conversion flags; '-' is the only one valid
202: * with %s, and it's not useful here.
203: */
204: pr->flags = F_BPAD;
205: *pr->cchar = 's';
206: for (p1 = pr->fmt; *p1 != '%'; ++p1);
1.4 millert 207: for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
1.6 deraadt 208: while ((*p2++ = *p1++))
209: ;
1.1 deraadt 210: }
211:
212: static char **_argv;
213:
214: u_char *
215: get()
216: {
217: extern enum _vflag vflag;
218: extern int length;
219: static int ateof = 1;
220: static u_char *curp, *savp;
221: register int n;
222: int need, nread;
1.5 deraadt 223: int valid_save = 0;
1.1 deraadt 224: u_char *tmpp;
225:
226: if (!curp) {
227: curp = (u_char *)emalloc(blocksize);
228: savp = (u_char *)emalloc(blocksize);
229: } else {
230: tmpp = curp;
231: curp = savp;
232: savp = tmpp;
233: address = savaddress += blocksize;
1.5 deraadt 234: valid_save = 1;
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: */
242: if (!length || ateof && !next((char **)NULL)) {
243: if (need == blocksize)
244: return((u_char *)NULL);
1.5 deraadt 245: if (vflag != ALL && valid_save &&
246: !bcmp(curp, savp, nread)) {
1.1 deraadt 247: if (vflag != DUP)
248: (void)printf("*\n");
249: return((u_char *)NULL);
250: }
251: bzero((char *)curp + nread, need);
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.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))) {
1.7 ! mickey 302: warn("%s", *_argv);
1.1 deraadt 303: exitval = 1;
304: ++_argv;
305: continue;
306: }
307: statok = done = 1;
308: } else {
309: if (done++)
310: return(0);
311: statok = 0;
312: }
313: if (skip)
314: doskip(statok ? *_argv : "stdin", statok);
315: if (*_argv)
316: ++_argv;
317: if (!skip)
318: return(1);
319: }
320: /* NOTREACHED */
321: }
322:
1.6 deraadt 323: void
1.1 deraadt 324: doskip(fname, statok)
325: char *fname;
326: int statok;
327: {
328: struct stat sbuf;
329:
330: if (statok) {
1.7 ! mickey 331: if (fstat(fileno(stdin), &sbuf))
! 332: err(1, "%s", fname);
1.1 deraadt 333: if (skip >= sbuf.st_size) {
334: skip -= sbuf.st_size;
335: address += sbuf.st_size;
336: return;
337: }
338: }
1.7 ! mickey 339: if (fseek(stdin, skip, SEEK_SET))
! 340: err(1, "%s", fname);
1.1 deraadt 341: savaddress = address += skip;
342: skip = 0;
343: }
344:
345: char *
346: emalloc(size)
347: int size;
348: {
349: char *p;
350:
351: if (!(p = malloc((u_int)size)))
1.7 ! mickey 352: err(1, "malloc");
1.1 deraadt 353: bzero(p, size);
354: return(p);
355: }