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