xref: /csrg-svn/usr.bin/hexdump/display.c (revision 62031)
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