display.c revision 1.1.1.2 1 /*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. 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[] = "@(#)display.c 8.1 (Berkeley) 6/6/93";
36 #endif /* not lint */
37
38 #include <sys/param.h>
39 #include <sys/stat.h>
40
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
54 static inline void print __P((PR *, u_char *));
55
56 void
57 display()
58 {
59 extern FU *endfu;
60 register FS *fs;
61 register FU *fu;
62 register PR *pr;
63 register int cnt;
64 register u_char *bp;
65 off_t saveaddress;
66 u_char savech, *savebp;
67
68 while (bp = get())
69 for (fs = fshead, savebp = bp, saveaddress = address; fs;
70 fs = fs->nextfs, bp = savebp, address = saveaddress)
71 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
72 if (fu->flags&F_IGNORE)
73 break;
74 for (cnt = fu->reps; cnt; --cnt)
75 for (pr = fu->nextpr; pr; address += pr->bcnt,
76 bp += pr->bcnt, pr = pr->nextpr) {
77 if (eaddress && address >= eaddress &&
78 !(pr->flags & (F_TEXT|F_BPAD)))
79 bpad(pr);
80 if (cnt == 1 && pr->nospace) {
81 savech = *pr->nospace;
82 *pr->nospace = '\0';
83 }
84 print(pr, bp);
85 if (cnt == 1 && pr->nospace)
86 *pr->nospace = savech;
87 }
88 }
89 if (endfu) {
90 /*
91 * If eaddress not set, error or file size was multiple of
92 * blocksize, and no partial block ever found.
93 */
94 if (!eaddress) {
95 if (!address)
96 return;
97 eaddress = address;
98 }
99 for (pr = endfu->nextpr; pr; pr = pr->nextpr)
100 switch(pr->flags) {
101 case F_ADDRESS:
102 (void)printf(pr->fmt, (quad_t)eaddress);
103 break;
104 case F_TEXT:
105 (void)printf(pr->fmt);
106 break;
107 }
108 }
109 }
110
111 static inline void
112 print(pr, bp)
113 PR *pr;
114 u_char *bp;
115 {
116 double f8;
117 float f4;
118 int16_t s2;
119 int8_t s8;
120 int32_t s4;
121 u_int16_t u2;
122 u_int32_t u4;
123 u_int64_t u8;
124
125 switch(pr->flags) {
126 case F_ADDRESS:
127 (void)printf(pr->fmt, (quad_t)address);
128 break;
129 case F_BPAD:
130 (void)printf(pr->fmt, "");
131 break;
132 case F_C:
133 conv_c(pr, bp);
134 break;
135 case F_CHAR:
136 (void)printf(pr->fmt, *bp);
137 break;
138 case F_DBL:
139 switch(pr->bcnt) {
140 case 4:
141 bcopy(bp, &f4, sizeof(f4));
142 (void)printf(pr->fmt, f4);
143 break;
144 case 8:
145 bcopy(bp, &f8, sizeof(f8));
146 (void)printf(pr->fmt, f8);
147 break;
148 }
149 break;
150 case F_INT:
151 switch(pr->bcnt) {
152 case 1:
153 (void)printf(pr->fmt, (quad_t)*bp);
154 break;
155 case 2:
156 bcopy(bp, &s2, sizeof(s2));
157 (void)printf(pr->fmt, (quad_t)s2);
158 break;
159 case 4:
160 bcopy(bp, &s4, sizeof(s4));
161 (void)printf(pr->fmt, (quad_t)s4);
162 break;
163 case 8:
164 bcopy(bp, &s8, sizeof(s8));
165 (void)printf(pr->fmt, s8);
166 break;
167 }
168 break;
169 case F_P:
170 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
171 break;
172 case F_STR:
173 (void)printf(pr->fmt, (char *)bp);
174 break;
175 case F_TEXT:
176 (void)printf(pr->fmt);
177 break;
178 case F_U:
179 conv_u(pr, bp);
180 break;
181 case F_UINT:
182 switch(pr->bcnt) {
183 case 1:
184 (void)printf(pr->fmt, (u_quad_t)*bp);
185 break;
186 case 2:
187 bcopy(bp, &u2, sizeof(u2));
188 (void)printf(pr->fmt, (u_quad_t)u2);
189 break;
190 case 4:
191 bcopy(bp, &u4, sizeof(u4));
192 (void)printf(pr->fmt, (u_quad_t)u4);
193 break;
194 case 8:
195 bcopy(bp, &u8, sizeof(u8));
196 (void)printf(pr->fmt, u8);
197 break;
198 }
199 break;
200 }
201 }
202
203 void
204 bpad(pr)
205 PR *pr;
206 {
207 static char *spec = " -0+#";
208 register char *p1, *p2;
209
210 /*
211 * Remove all conversion flags; '-' is the only one valid
212 * with %s, and it's not useful here.
213 */
214 pr->flags = F_BPAD;
215 pr->cchar[0] = 's';
216 pr->cchar[1] = '\0';
217 for (p1 = pr->fmt; *p1 != '%'; ++p1);
218 for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
219 while (*p2++ = *p1++);
220 }
221
222 static char **_argv;
223
224 u_char *
225 get()
226 {
227 extern enum _vflag vflag;
228 extern int length;
229 static int ateof = 1;
230 static u_char *curp, *savp;
231 register int n;
232 int need, nread;
233 u_char *tmpp;
234
235 if (!curp) {
236 curp = emalloc(blocksize);
237 savp = emalloc(blocksize);
238 } else {
239 tmpp = curp;
240 curp = savp;
241 savp = tmpp;
242 address += blocksize;
243 }
244 for (need = blocksize, nread = 0;;) {
245 /*
246 * if read the right number of bytes, or at EOF for one file,
247 * and no other files are available, zero-pad the rest of the
248 * block and set the end flag.
249 */
250 if (!length || ateof && !next((char **)NULL)) {
251 if (need == blocksize)
252 return((u_char *)NULL);
253 if (vflag != ALL && !bcmp(curp, savp, nread)) {
254 if (vflag != DUP)
255 (void)printf("*\n");
256 return((u_char *)NULL);
257 }
258 bzero((char *)curp + nread, need);
259 eaddress = address + nread;
260 return(curp);
261 }
262 n = fread((char *)curp + nread, sizeof(u_char),
263 length == -1 ? need : MIN(length, need), stdin);
264 if (!n) {
265 if (ferror(stdin))
266 (void)fprintf(stderr, "hexdump: %s: %s\n",
267 _argv[-1], strerror(errno));
268 ateof = 1;
269 continue;
270 }
271 ateof = 0;
272 if (length != -1)
273 length -= n;
274 if (!(need -= n)) {
275 if (vflag == ALL || vflag == FIRST ||
276 bcmp(curp, savp, blocksize)) {
277 if (vflag == DUP || vflag == FIRST)
278 vflag = WAIT;
279 return(curp);
280 }
281 if (vflag == WAIT)
282 (void)printf("*\n");
283 vflag = DUP;
284 address += blocksize;
285 need = blocksize;
286 nread = 0;
287 }
288 else
289 nread += n;
290 }
291 }
292
293 extern off_t skip; /* bytes to skip */
294
295 int
296 next(argv)
297 char **argv;
298 {
299 extern int exitval;
300 static int done;
301 int statok;
302
303 if (argv) {
304 _argv = argv;
305 return(1);
306 }
307 for (;;) {
308 if (*_argv) {
309 if (!(freopen(*_argv, "r", stdin))) {
310 (void)fprintf(stderr, "hexdump: %s: %s\n",
311 *_argv, strerror(errno));
312 exitval = 1;
313 ++_argv;
314 continue;
315 }
316 statok = done = 1;
317 } else {
318 if (done++)
319 return(0);
320 statok = 0;
321 }
322 if (skip)
323 doskip(statok ? *_argv : "stdin", statok);
324 if (*_argv)
325 ++_argv;
326 if (!skip)
327 return(1);
328 }
329 /* NOTREACHED */
330 }
331
332 void
333 doskip(fname, statok)
334 char *fname;
335 int statok;
336 {
337 register int cnt;
338 struct stat sb;
339
340 if (statok) {
341 if (fstat(fileno(stdin), &sb))
342 err("%s: %s", fname, strerror(errno));
343 if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
344 address += sb.st_size;
345 skip -= sb.st_size;
346 return;
347 }
348 }
349 if (S_ISREG(sb.st_mode)) {
350 if (fseek(stdin, skip, SEEK_SET))
351 err("%s: %s", fname, strerror(errno));
352 address += skip;
353 skip = 0;
354 } else {
355 for (cnt = 0; cnt < skip; ++cnt)
356 if (getchar() == EOF)
357 break;
358 address += cnt;
359 skip -= cnt;
360 }
361 }
362
363 void *
364 emalloc(size)
365 int size;
366 {
367 void *p;
368
369 if ((p = malloc((u_int)size)) == NULL)
370 nomem();
371 bzero(p, size);
372 return(p);
373 }
374
375 void
376 nomem()
377 {
378 err("%s", strerror(errno));
379 }
380