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