138855Sbostic /*
2*62031Sbostic * Copyright (c) 1989, 1993
3*62031Sbostic * The Regents of the University of California. All rights reserved.
438855Sbostic *
542734Sbostic * %sccs.include.redist.c%
638855Sbostic */
738855Sbostic
838855Sbostic #ifndef lint
9*62031Sbostic static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 06/06/93";
1038855Sbostic #endif /* not lint */
1138855Sbostic
1238855Sbostic #include <sys/param.h>
1338855Sbostic #include <sys/stat.h>
1455201Sbostic
1538855Sbostic #include <unistd.h>
1641450Sbostic #include <errno.h>
1738855Sbostic #include <ctype.h>
1838855Sbostic #include <stdio.h>
1947174Sbostic #include <stdlib.h>
2042056Sbostic #include <string.h>
2138855Sbostic #include "hexdump.h"
2238855Sbostic
2341453Sbostic enum _vflag vflag = FIRST;
2441453Sbostic
2538855Sbostic static off_t address; /* address/offset in stream */
2638855Sbostic static off_t eaddress; /* end address */
2738855Sbostic
2855201Sbostic static inline void print __P((PR *, u_char *));
2938860Sbostic
3055201Sbostic void
display()3138855Sbostic display()
3238855Sbostic {
3338855Sbostic extern FU *endfu;
3438855Sbostic register FS *fs;
3538855Sbostic register FU *fu;
3638855Sbostic register PR *pr;
3738855Sbostic register int cnt;
3838855Sbostic register u_char *bp;
3938855Sbostic off_t saveaddress;
4055201Sbostic u_char savech, *savebp;
4138855Sbostic
4238855Sbostic while (bp = get())
4338855Sbostic for (fs = fshead, savebp = bp, saveaddress = address; fs;
4438860Sbostic fs = fs->nextfs, bp = savebp, address = saveaddress)
4538855Sbostic for (fu = fs->nextfu; fu; fu = fu->nextfu) {
4638855Sbostic if (fu->flags&F_IGNORE)
4738855Sbostic break;
4838855Sbostic for (cnt = fu->reps; cnt; --cnt)
4938855Sbostic for (pr = fu->nextpr; pr; address += pr->bcnt,
5038855Sbostic bp += pr->bcnt, pr = pr->nextpr) {
5138861Sbostic if (eaddress && address >= eaddress &&
5255201Sbostic !(pr->flags & (F_TEXT|F_BPAD)))
5338861Sbostic bpad(pr);
5438855Sbostic if (cnt == 1 && pr->nospace) {
5538855Sbostic savech = *pr->nospace;
5638855Sbostic *pr->nospace = '\0';
5738855Sbostic }
5855201Sbostic print(pr, bp);
5938855Sbostic if (cnt == 1 && pr->nospace)
6038855Sbostic *pr->nospace = savech;
6138855Sbostic }
6238855Sbostic }
6338855Sbostic if (endfu) {
6438855Sbostic /*
6555201Sbostic * If eaddress not set, error or file size was multiple of
6639097Sbostic * blocksize, and no partial block ever found.
6738855Sbostic */
6839097Sbostic if (!eaddress) {
6939097Sbostic if (!address)
7039097Sbostic return;
7142373Sbostic eaddress = address;
7239097Sbostic }
7338855Sbostic for (pr = endfu->nextpr; pr; pr = pr->nextpr)
7438855Sbostic switch(pr->flags) {
7538855Sbostic case F_ADDRESS:
7658440Sbostic (void)printf(pr->fmt, (quad_t)eaddress);
7738855Sbostic break;
7838855Sbostic case F_TEXT:
7938855Sbostic (void)printf(pr->fmt);
8038855Sbostic break;
8138855Sbostic }
8238855Sbostic }
8338855Sbostic }
8438855Sbostic
8555201Sbostic static inline void
print(pr,bp)8655201Sbostic print(pr, bp)
8755201Sbostic PR *pr;
8855201Sbostic u_char *bp;
8955201Sbostic {
9060075Sbostic double f8;
9160075Sbostic float f4;
9260075Sbostic int16_t s2;
9360075Sbostic int8_t s8;
9460075Sbostic int32_t s4;
9560075Sbostic u_int16_t u2;
9660075Sbostic u_int32_t u4;
9760075Sbostic u_int64_t u8;
9855201Sbostic
9955201Sbostic switch(pr->flags) {
10055201Sbostic case F_ADDRESS:
10158440Sbostic (void)printf(pr->fmt, (quad_t)address);
10255201Sbostic break;
10355201Sbostic case F_BPAD:
10455201Sbostic (void)printf(pr->fmt, "");
10555201Sbostic break;
10655201Sbostic case F_C:
10755201Sbostic conv_c(pr, bp);
10855201Sbostic break;
10955201Sbostic case F_CHAR:
11055201Sbostic (void)printf(pr->fmt, *bp);
11155201Sbostic break;
11255201Sbostic case F_DBL:
11355201Sbostic switch(pr->bcnt) {
11455201Sbostic case 4:
11555201Sbostic bcopy(bp, &f4, sizeof(f4));
11655201Sbostic (void)printf(pr->fmt, f4);
11755201Sbostic break;
11855201Sbostic case 8:
11955201Sbostic bcopy(bp, &f8, sizeof(f8));
12055201Sbostic (void)printf(pr->fmt, f8);
12155201Sbostic break;
12255201Sbostic }
12355201Sbostic break;
12455201Sbostic case F_INT:
12555201Sbostic switch(pr->bcnt) {
12655201Sbostic case 1:
12755201Sbostic (void)printf(pr->fmt, (quad_t)*bp);
12855201Sbostic break;
12955201Sbostic case 2:
13055201Sbostic bcopy(bp, &s2, sizeof(s2));
13155201Sbostic (void)printf(pr->fmt, (quad_t)s2);
13255201Sbostic break;
13355201Sbostic case 4:
13455201Sbostic bcopy(bp, &s4, sizeof(s4));
13555201Sbostic (void)printf(pr->fmt, (quad_t)s4);
13655201Sbostic break;
13755201Sbostic case 8:
13855201Sbostic bcopy(bp, &s8, sizeof(s8));
13955201Sbostic (void)printf(pr->fmt, s8);
14055201Sbostic break;
14155201Sbostic }
14255201Sbostic break;
14355201Sbostic case F_P:
14455201Sbostic (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
14555201Sbostic break;
14655201Sbostic case F_STR:
14755201Sbostic (void)printf(pr->fmt, (char *)bp);
14855201Sbostic break;
14955201Sbostic case F_TEXT:
15055201Sbostic (void)printf(pr->fmt);
15155201Sbostic break;
15255201Sbostic case F_U:
15355201Sbostic conv_u(pr, bp);
15455201Sbostic break;
15555201Sbostic case F_UINT:
15655201Sbostic switch(pr->bcnt) {
15755201Sbostic case 1:
15855201Sbostic (void)printf(pr->fmt, (u_quad_t)*bp);
15955201Sbostic break;
16055201Sbostic case 2:
16155201Sbostic bcopy(bp, &u2, sizeof(u2));
16255201Sbostic (void)printf(pr->fmt, (u_quad_t)u2);
16355201Sbostic break;
16455201Sbostic case 4:
16555201Sbostic bcopy(bp, &u4, sizeof(u4));
16655201Sbostic (void)printf(pr->fmt, (u_quad_t)u4);
16755201Sbostic break;
16855201Sbostic case 8:
16955201Sbostic bcopy(bp, &u8, sizeof(u8));
17055201Sbostic (void)printf(pr->fmt, u8);
17155201Sbostic break;
17255201Sbostic }
17355201Sbostic break;
17455201Sbostic }
17555201Sbostic }
17655201Sbostic
17755201Sbostic void
bpad(pr)17838861Sbostic bpad(pr)
17938861Sbostic PR *pr;
18038861Sbostic {
18138861Sbostic static char *spec = " -0+#";
18238861Sbostic register char *p1, *p2;
18338861Sbostic
18438861Sbostic /*
18555201Sbostic * Remove all conversion flags; '-' is the only one valid
18638861Sbostic * with %s, and it's not useful here.
18738861Sbostic */
18838861Sbostic pr->flags = F_BPAD;
18955201Sbostic pr->cchar[0] = 's';
19055201Sbostic pr->cchar[1] = '\0';
19138861Sbostic for (p1 = pr->fmt; *p1 != '%'; ++p1);
19238861Sbostic for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
19338861Sbostic while (*p2++ = *p1++);
19438861Sbostic }
19538861Sbostic
19642630Sbostic static char **_argv;
19742630Sbostic
19838855Sbostic u_char *
get()19938855Sbostic get()
20038855Sbostic {
20138855Sbostic extern enum _vflag vflag;
20238855Sbostic extern int length;
20338855Sbostic static int ateof = 1;
20438855Sbostic static u_char *curp, *savp;
20538855Sbostic register int n;
20638855Sbostic int need, nread;
20738855Sbostic u_char *tmpp;
20838855Sbostic
20938855Sbostic if (!curp) {
21055201Sbostic curp = emalloc(blocksize);
21155201Sbostic savp = emalloc(blocksize);
21238855Sbostic } else {
21338855Sbostic tmpp = curp;
21438855Sbostic curp = savp;
21538855Sbostic savp = tmpp;
21652140Sbostic address += blocksize;
21738855Sbostic }
21838855Sbostic for (need = blocksize, nread = 0;;) {
21938855Sbostic /*
22038855Sbostic * if read the right number of bytes, or at EOF for one file,
22138855Sbostic * and no other files are available, zero-pad the rest of the
22238855Sbostic * block and set the end flag.
22338855Sbostic */
22438855Sbostic if (!length || ateof && !next((char **)NULL)) {
22538855Sbostic if (need == blocksize)
22638855Sbostic return((u_char *)NULL);
22738855Sbostic if (vflag != ALL && !bcmp(curp, savp, nread)) {
22838855Sbostic if (vflag != DUP)
22938855Sbostic (void)printf("*\n");
23038855Sbostic return((u_char *)NULL);
23138855Sbostic }
23238855Sbostic bzero((char *)curp + nread, need);
23338855Sbostic eaddress = address + nread;
23438855Sbostic return(curp);
23538855Sbostic }
23638855Sbostic n = fread((char *)curp + nread, sizeof(u_char),
23738855Sbostic length == -1 ? need : MIN(length, need), stdin);
23838855Sbostic if (!n) {
23942630Sbostic if (ferror(stdin))
24042630Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n",
24142630Sbostic _argv[-1], strerror(errno));
24238855Sbostic ateof = 1;
24338855Sbostic continue;
24438855Sbostic }
24538855Sbostic ateof = 0;
24638855Sbostic if (length != -1)
24738855Sbostic length -= n;
24838855Sbostic if (!(need -= n)) {
24941450Sbostic if (vflag == ALL || vflag == FIRST ||
25041450Sbostic bcmp(curp, savp, blocksize)) {
25141450Sbostic if (vflag == DUP || vflag == FIRST)
25238855Sbostic vflag = WAIT;
25338855Sbostic return(curp);
25438855Sbostic }
25538855Sbostic if (vflag == WAIT)
25638855Sbostic (void)printf("*\n");
25738855Sbostic vflag = DUP;
25852140Sbostic address += blocksize;
25938855Sbostic need = blocksize;
26038855Sbostic nread = 0;
26138855Sbostic }
26238855Sbostic else
26338855Sbostic nread += n;
26438855Sbostic }
26538855Sbostic }
26638855Sbostic
26738855Sbostic extern off_t skip; /* bytes to skip */
26838855Sbostic
26955201Sbostic int
next(argv)27038855Sbostic next(argv)
27138855Sbostic char **argv;
27238855Sbostic {
27355201Sbostic extern int exitval;
27438855Sbostic static int done;
27538855Sbostic int statok;
27638855Sbostic
27738855Sbostic if (argv) {
27838855Sbostic _argv = argv;
27938855Sbostic return(1);
28038855Sbostic }
28138855Sbostic for (;;) {
28238855Sbostic if (*_argv) {
28338855Sbostic if (!(freopen(*_argv, "r", stdin))) {
28438855Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n",
28538855Sbostic *_argv, strerror(errno));
28638855Sbostic exitval = 1;
28738855Sbostic ++_argv;
28838855Sbostic continue;
28938855Sbostic }
29038855Sbostic statok = done = 1;
29138855Sbostic } else {
29238855Sbostic if (done++)
29338855Sbostic return(0);
29438855Sbostic statok = 0;
29538855Sbostic }
29638855Sbostic if (skip)
29738855Sbostic doskip(statok ? *_argv : "stdin", statok);
29838855Sbostic if (*_argv)
29938855Sbostic ++_argv;
30038855Sbostic if (!skip)
30138855Sbostic return(1);
30238855Sbostic }
30338855Sbostic /* NOTREACHED */
30438855Sbostic }
30538855Sbostic
30655201Sbostic void
doskip(fname,statok)30738855Sbostic doskip(fname, statok)
30838855Sbostic char *fname;
30938855Sbostic int statok;
31038855Sbostic {
31152140Sbostic register int cnt;
31252140Sbostic struct stat sb;
31338855Sbostic
31438855Sbostic if (statok) {
31555201Sbostic if (fstat(fileno(stdin), &sb))
31655201Sbostic err("%s: %s", fname, strerror(errno));
31752140Sbostic if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
31852140Sbostic address += sb.st_size;
31952140Sbostic skip -= sb.st_size;
32038855Sbostic return;
32138855Sbostic }
32238855Sbostic }
32352140Sbostic if (S_ISREG(sb.st_mode)) {
32455201Sbostic if (fseek(stdin, skip, SEEK_SET))
32555201Sbostic err("%s: %s", fname, strerror(errno));
32652140Sbostic address += skip;
32752140Sbostic skip = 0;
32852140Sbostic } else {
32952140Sbostic for (cnt = 0; cnt < skip; ++cnt)
33052140Sbostic if (getchar() == EOF)
33152140Sbostic break;
33252140Sbostic address += cnt;
33352140Sbostic skip -= cnt;
33438855Sbostic }
33538855Sbostic }
33638855Sbostic
33755201Sbostic void *
emalloc(size)33838855Sbostic emalloc(size)
33938855Sbostic int size;
34038855Sbostic {
34155201Sbostic void *p;
34238855Sbostic
34355201Sbostic if ((p = malloc((u_int)size)) == NULL)
34438855Sbostic nomem();
34538855Sbostic bzero(p, size);
34638855Sbostic return(p);
34738855Sbostic }
34838855Sbostic
34955201Sbostic void
nomem()35038855Sbostic nomem()
35138855Sbostic {
35255201Sbostic err("%s", strerror(errno));
35338855Sbostic }
354