2 * Copyright (c) 1989 The Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
34 #include <sys/param.h>
44 static void doskip(const char *, int);
45 static u_char *get(void);
48 #define MIN(a,b) ((a)<(b)?(a):(b))
51 enum _vflag vflag = FIRST;
53 static off_t address; /* address/offset in stream */
54 static off_t eaddress; /* end address */
57 print(PR *pr, u_char *bp) {
61 (void)printf(pr->fmt, (quad_t)address);
64 (void)printf(pr->fmt, "");
70 (void)printf(pr->fmt, *bp);
78 memmove(&fval, bp, sizeof(fval));
79 (void)printf(pr->fmt, fval);
82 memmove(&dval, bp, sizeof(dval));
83 (void)printf(pr->fmt, dval);
90 short sval; /* int16_t */
91 int ival; /* int32_t */
92 long long Lval; /* int64_t, quad_t */
96 (void)printf(pr->fmt, (quad_t)*bp);
99 memmove(&sval, bp, sizeof(sval));
100 (void)printf(pr->fmt, (quad_t)sval);
103 memmove(&ival, bp, sizeof(ival));
104 (void)printf(pr->fmt, (quad_t)ival);
107 memmove(&Lval, bp, sizeof(Lval));
108 (void)printf(pr->fmt, (quad_t)Lval);
114 (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
117 (void)printf(pr->fmt, (char *)bp);
120 (void)printf("%s", pr->fmt);
127 unsigned short sval; /* u_int16_t */
128 unsigned int ival; /* u_int32_t */
129 unsigned long long Lval;/* u_int64_t, u_quad_t */
133 (void)printf(pr->fmt, (u_quad_t)*bp);
136 memmove(&sval, bp, sizeof(sval));
137 (void)printf(pr->fmt, (u_quad_t)sval);
140 memmove(&ival, bp, sizeof(ival));
141 (void)printf(pr->fmt, (u_quad_t)ival);
144 memmove(&Lval, bp, sizeof(Lval));
145 (void)printf(pr->fmt, (u_quad_t)Lval);
153 static void bpad(PR *pr)
155 static const char *spec = " -0+#";
159 * remove all conversion flags; '-' is the only one valid
160 * with %s, and it's not useful here.
165 for (p1 = pr->fmt; *p1 != '%'; ++p1);
166 for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
167 while ((*p2++ = *p1++) != 0) ;
178 u_char savech = 0, *savebp;
180 while ((bp = get()) != NULL)
181 for (fs = fshead, savebp = bp, saveaddress = address; fs;
182 fs = fs->nextfs, bp = savebp, address = saveaddress)
183 for (fu = fs->nextfu; fu; fu = fu->nextfu) {
184 if (fu->flags&F_IGNORE)
186 for (cnt = fu->reps; cnt; --cnt)
187 for (pr = fu->nextpr; pr; address += pr->bcnt,
188 bp += pr->bcnt, pr = pr->nextpr) {
189 if (eaddress && address >= eaddress &&
190 !(pr->flags&(F_TEXT|F_BPAD)))
192 if (cnt == 1 && pr->nospace) {
193 savech = *pr->nospace;
197 if (cnt == 1 && pr->nospace)
198 *pr->nospace = savech;
203 * if eaddress not set, error or file size was multiple of
204 * blocksize, and no partial block ever found.
211 for (pr = endfu->nextpr; pr; pr = pr->nextpr)
214 (void)printf(pr->fmt, (quad_t)eaddress);
217 (void)printf("%s", pr->fmt);
228 static int ateof = 1;
229 static u_char *curp, *savp;
235 curp = emalloc(blocksize);
236 savp = emalloc(blocksize);
241 address += blocksize;
243 for (need = blocksize, nread = 0;;) {
245 * if read the right number of bytes, or at EOF for one file,
246 * and no other files are available, zero-pad the rest of the
247 * block and set the end flag.
249 if (!length || (ateof && !next(NULL))) {
250 if (need == blocksize)
252 if (!need && vflag != ALL &&
253 !memcmp(curp, savp, nread)) {
259 memset((char *)curp + nread, 0, need);
260 eaddress = address + nread;
263 n = fread((char *)curp + nread, sizeof(u_char),
264 length == -1 ? need : MIN(length, need), stdin);
267 (void)fprintf(stderr, "hexdump: %s: %s\n",
268 _argv[-1], strerror(errno));
276 if (vflag == ALL || vflag == FIRST ||
277 memcmp(curp, savp, blocksize)) {
278 if (vflag == DUP || vflag == FIRST)
285 address += blocksize;
294 int next(char **argv)
305 if (!(freopen(*_argv, "r", stdin))) {
306 (void)fprintf(stderr, "hexdump: %s: %s\n",
307 *_argv, strerror(errno));
319 doskip(statok ? *_argv : "stdin", statok);
329 doskip(const char *fname, int statok)
334 if (fstat(fileno(stdin), &sbuf)) {
335 (void)fprintf(stderr, "hexdump: %s: %s.\n",
336 fname, strerror(errno));
339 if (S_ISREG(sbuf.st_mode) && skip >= sbuf.st_size) {
340 /* If size valid and skip >= size */
341 skip -= sbuf.st_size;
342 address += sbuf.st_size;
346 /* sbuf may be undefined here - do not test it */
347 if (fseek(stdin, skip, SEEK_SET)) {
348 (void)fprintf(stderr, "hexdump: %s: %s.\n",
349 fname, strerror(errno));
360 if (!(p = malloc((u_int)sz)))
367 (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno));