11590Srgrimes/*
21590Srgrimes * Copyright (c) 1989, 1993
31590Srgrimes *	The Regents of the University of California.  All rights reserved.
41590Srgrimes *
51590Srgrimes * Redistribution and use in source and binary forms, with or without
61590Srgrimes * modification, are permitted provided that the following conditions
71590Srgrimes * are met:
81590Srgrimes * 1. Redistributions of source code must retain the above copyright
91590Srgrimes *    notice, this list of conditions and the following disclaimer.
101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111590Srgrimes *    notice, this list of conditions and the following disclaimer in the
121590Srgrimes *    documentation and/or other materials provided with the distribution.
131590Srgrimes * 4. Neither the name of the University nor the names of its contributors
141590Srgrimes *    may be used to endorse or promote products derived from this software
151590Srgrimes *    without specific prior written permission.
161590Srgrimes *
171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201590Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271590Srgrimes * SUCH DAMAGE.
281590Srgrimes */
291590Srgrimes
301590Srgrimes#ifndef lint
3127315Scharnier#if 0
321590Srgrimesstatic char sccsid[] = "@(#)display.c	8.1 (Berkeley) 6/6/93";
3327315Scharnier#endif
341590Srgrimes#endif /* not lint */
3599112Sobrien#include <sys/cdefs.h>
3699112Sobrien__FBSDID("$FreeBSD$");
371590Srgrimes
381590Srgrimes#include <sys/param.h>
391590Srgrimes#include <sys/stat.h>
401590Srgrimes
411590Srgrimes#include <ctype.h>
4227315Scharnier#include <err.h>
431590Srgrimes#include <stdio.h>
441590Srgrimes#include <stdlib.h>
451590Srgrimes#include <string.h>
46200462Sdelphij#include <unistd.h>
471590Srgrimes#include "hexdump.h"
481590Srgrimes
491590Srgrimesenum _vflag vflag = FIRST;
501590Srgrimes
511590Srgrimesstatic off_t address;			/* address/offset in stream */
521590Srgrimesstatic off_t eaddress;			/* end address */
531590Srgrimes
54132785Skanstatic void print(PR *, u_char *);
551590Srgrimes
561590Srgrimesvoid
57102944Sdwmalonedisplay(void)
581590Srgrimes{
59102944Sdwmalone	FS *fs;
60102944Sdwmalone	FU *fu;
61102944Sdwmalone	PR *pr;
62102944Sdwmalone	int cnt;
63102944Sdwmalone	u_char *bp;
641590Srgrimes	off_t saveaddress;
651590Srgrimes	u_char savech, *savebp;
661590Srgrimes
67132541Sjohan	savech = 0;
6887203Smarkm	while ((bp = get()))
691590Srgrimes	    for (fs = fshead, savebp = bp, saveaddress = address; fs;
701590Srgrimes		fs = fs->nextfs, bp = savebp, address = saveaddress)
711590Srgrimes		    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
721590Srgrimes			if (fu->flags&F_IGNORE)
731590Srgrimes				break;
741590Srgrimes			for (cnt = fu->reps; cnt; --cnt)
751590Srgrimes			    for (pr = fu->nextpr; pr; address += pr->bcnt,
761590Srgrimes				bp += pr->bcnt, pr = pr->nextpr) {
771590Srgrimes				    if (eaddress && address >= eaddress &&
781590Srgrimes					!(pr->flags & (F_TEXT|F_BPAD)))
791590Srgrimes					    bpad(pr);
801590Srgrimes				    if (cnt == 1 && pr->nospace) {
811590Srgrimes					savech = *pr->nospace;
821590Srgrimes					*pr->nospace = '\0';
831590Srgrimes				    }
841590Srgrimes				    print(pr, bp);
851590Srgrimes				    if (cnt == 1 && pr->nospace)
861590Srgrimes					*pr->nospace = savech;
871590Srgrimes			    }
881590Srgrimes		    }
891590Srgrimes	if (endfu) {
901590Srgrimes		/*
911590Srgrimes		 * If eaddress not set, error or file size was multiple of
921590Srgrimes		 * blocksize, and no partial block ever found.
931590Srgrimes		 */
941590Srgrimes		if (!eaddress) {
951590Srgrimes			if (!address)
961590Srgrimes				return;
971590Srgrimes			eaddress = address;
981590Srgrimes		}
991590Srgrimes		for (pr = endfu->nextpr; pr; pr = pr->nextpr)
1001590Srgrimes			switch(pr->flags) {
1011590Srgrimes			case F_ADDRESS:
1021590Srgrimes				(void)printf(pr->fmt, (quad_t)eaddress);
1031590Srgrimes				break;
1041590Srgrimes			case F_TEXT:
10562892Skris				(void)printf("%s", pr->fmt);
1061590Srgrimes				break;
1071590Srgrimes			}
1081590Srgrimes	}
1091590Srgrimes}
1101590Srgrimes
111132785Skanstatic void
112102944Sdwmaloneprint(PR *pr, u_char *bp)
1131590Srgrimes{
11496792Stjr	long double ldbl;
1151590Srgrimes	   double f8;
1161590Srgrimes	    float f4;
1171590Srgrimes	  int16_t s2;
1181590Srgrimes	   int8_t s8;
1191590Srgrimes	  int32_t s4;
1201590Srgrimes	u_int16_t u2;
1211590Srgrimes	u_int32_t u4;
1221590Srgrimes	u_int64_t u8;
1231590Srgrimes
1241590Srgrimes	switch(pr->flags) {
1251590Srgrimes	case F_ADDRESS:
1261590Srgrimes		(void)printf(pr->fmt, (quad_t)address);
1271590Srgrimes		break;
1281590Srgrimes	case F_BPAD:
1291590Srgrimes		(void)printf(pr->fmt, "");
1301590Srgrimes		break;
1311590Srgrimes	case F_C:
132131954Stjr		conv_c(pr, bp, eaddress ? eaddress - address :
133131954Stjr		    blocksize - address % blocksize);
1341590Srgrimes		break;
1351590Srgrimes	case F_CHAR:
1361590Srgrimes		(void)printf(pr->fmt, *bp);
1371590Srgrimes		break;
1381590Srgrimes	case F_DBL:
1391590Srgrimes		switch(pr->bcnt) {
1401590Srgrimes		case 4:
1411590Srgrimes			bcopy(bp, &f4, sizeof(f4));
1421590Srgrimes			(void)printf(pr->fmt, f4);
1431590Srgrimes			break;
1441590Srgrimes		case 8:
1451590Srgrimes			bcopy(bp, &f8, sizeof(f8));
1461590Srgrimes			(void)printf(pr->fmt, f8);
1471590Srgrimes			break;
14896795Stjr		default:
14996795Stjr			if (pr->bcnt == sizeof(long double)) {
15096795Stjr				bcopy(bp, &ldbl, sizeof(ldbl));
15196795Stjr				(void)printf(pr->fmt, ldbl);
15296795Stjr			}
15396792Stjr			break;
1541590Srgrimes		}
1551590Srgrimes		break;
1561590Srgrimes	case F_INT:
1571590Srgrimes		switch(pr->bcnt) {
1581590Srgrimes		case 1:
15996790Stjr			(void)printf(pr->fmt, (quad_t)(signed char)*bp);
1601590Srgrimes			break;
1611590Srgrimes		case 2:
1621590Srgrimes			bcopy(bp, &s2, sizeof(s2));
1631590Srgrimes			(void)printf(pr->fmt, (quad_t)s2);
1641590Srgrimes			break;
1651590Srgrimes		case 4:
1661590Srgrimes			bcopy(bp, &s4, sizeof(s4));
1671590Srgrimes			(void)printf(pr->fmt, (quad_t)s4);
1681590Srgrimes			break;
1691590Srgrimes		case 8:
1701590Srgrimes			bcopy(bp, &s8, sizeof(s8));
1711590Srgrimes			(void)printf(pr->fmt, s8);
1721590Srgrimes			break;
1731590Srgrimes		}
1741590Srgrimes		break;
1751590Srgrimes	case F_P:
1761590Srgrimes		(void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
1771590Srgrimes		break;
1781590Srgrimes	case F_STR:
1791590Srgrimes		(void)printf(pr->fmt, (char *)bp);
1801590Srgrimes		break;
1811590Srgrimes	case F_TEXT:
18262893Skris		(void)printf("%s", pr->fmt);
1831590Srgrimes		break;
1841590Srgrimes	case F_U:
1851590Srgrimes		conv_u(pr, bp);
1861590Srgrimes		break;
1871590Srgrimes	case F_UINT:
1881590Srgrimes		switch(pr->bcnt) {
1891590Srgrimes		case 1:
1901590Srgrimes			(void)printf(pr->fmt, (u_quad_t)*bp);
1911590Srgrimes			break;
1921590Srgrimes		case 2:
1931590Srgrimes			bcopy(bp, &u2, sizeof(u2));
1941590Srgrimes			(void)printf(pr->fmt, (u_quad_t)u2);
1951590Srgrimes			break;
1961590Srgrimes		case 4:
1971590Srgrimes			bcopy(bp, &u4, sizeof(u4));
1981590Srgrimes			(void)printf(pr->fmt, (u_quad_t)u4);
1991590Srgrimes			break;
2001590Srgrimes		case 8:
2011590Srgrimes			bcopy(bp, &u8, sizeof(u8));
2021590Srgrimes			(void)printf(pr->fmt, u8);
2031590Srgrimes			break;
2041590Srgrimes		}
2051590Srgrimes		break;
2061590Srgrimes	}
2071590Srgrimes}
2081590Srgrimes
2091590Srgrimesvoid
210102944Sdwmalonebpad(PR *pr)
2111590Srgrimes{
21291838Sobrien	static char const *spec = " -0+#";
213102944Sdwmalone	char *p1, *p2;
2141590Srgrimes
2151590Srgrimes	/*
2161590Srgrimes	 * Remove all conversion flags; '-' is the only one valid
2171590Srgrimes	 * with %s, and it's not useful here.
2181590Srgrimes	 */
2191590Srgrimes	pr->flags = F_BPAD;
2201590Srgrimes	pr->cchar[0] = 's';
2211590Srgrimes	pr->cchar[1] = '\0';
2221590Srgrimes	for (p1 = pr->fmt; *p1 != '%'; ++p1);
223229403Sed	for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
22487203Smarkm	while ((*p2++ = *p1++));
2251590Srgrimes}
2261590Srgrimes
2271590Srgrimesstatic char **_argv;
2281590Srgrimes
2291590Srgrimesu_char *
230102944Sdwmaloneget(void)
2311590Srgrimes{
2321590Srgrimes	static int ateof = 1;
2331590Srgrimes	static u_char *curp, *savp;
234102944Sdwmalone	int n;
2351590Srgrimes	int need, nread;
23641724Sdillon	int valid_save = 0;
2371590Srgrimes	u_char *tmpp;
2381590Srgrimes
2391590Srgrimes	if (!curp) {
24080290Sobrien		if ((curp = calloc(1, blocksize)) == NULL)
24180290Sobrien			err(1, NULL);
24280290Sobrien		if ((savp = calloc(1, blocksize)) == NULL)
24380290Sobrien			err(1, NULL);
2441590Srgrimes	} else {
2451590Srgrimes		tmpp = curp;
2461590Srgrimes		curp = savp;
2471590Srgrimes		savp = tmpp;
2481590Srgrimes		address += blocksize;
24941724Sdillon		valid_save = 1;
2501590Srgrimes	}
2511590Srgrimes	for (need = blocksize, nread = 0;;) {
2521590Srgrimes		/*
2531590Srgrimes		 * if read the right number of bytes, or at EOF for one file,
2541590Srgrimes		 * and no other files are available, zero-pad the rest of the
2551590Srgrimes		 * block and set the end flag.
2561590Srgrimes		 */
25787203Smarkm		if (!length || (ateof && !next((char **)NULL))) {
25896795Stjr			if (odmode && address < skip)
25996795Stjr				errx(1, "cannot skip past end of input");
2601590Srgrimes			if (need == blocksize)
2611590Srgrimes				return((u_char *)NULL);
262131954Stjr			/*
263131954Stjr			 * XXX bcmp() is not quite right in the presence
264131954Stjr			 * of multibyte characters.
265131954Stjr			 */
26641724Sdillon			if (vflag != ALL &&
26741724Sdillon			    valid_save &&
26841724Sdillon			    bcmp(curp, savp, nread) == 0) {
2691590Srgrimes				if (vflag != DUP)
2701590Srgrimes					(void)printf("*\n");
2711590Srgrimes				return((u_char *)NULL);
2721590Srgrimes			}
2731590Srgrimes			bzero((char *)curp + nread, need);
2741590Srgrimes			eaddress = address + nread;
2751590Srgrimes			return(curp);
2761590Srgrimes		}
2771590Srgrimes		n = fread((char *)curp + nread, sizeof(u_char),
2781590Srgrimes		    length == -1 ? need : MIN(length, need), stdin);
2791590Srgrimes		if (!n) {
2801590Srgrimes			if (ferror(stdin))
28127315Scharnier				warn("%s", _argv[-1]);
2821590Srgrimes			ateof = 1;
2831590Srgrimes			continue;
2841590Srgrimes		}
2851590Srgrimes		ateof = 0;
2861590Srgrimes		if (length != -1)
2871590Srgrimes			length -= n;
2881590Srgrimes		if (!(need -= n)) {
289131954Stjr			/*
290131954Stjr			 * XXX bcmp() is not quite right in the presence
291131954Stjr			 * of multibyte characters.
292131954Stjr			 */
2931590Srgrimes			if (vflag == ALL || vflag == FIRST ||
29441724Sdillon			    valid_save == 0 ||
29541724Sdillon			    bcmp(curp, savp, blocksize) != 0) {
2961590Srgrimes				if (vflag == DUP || vflag == FIRST)
2971590Srgrimes					vflag = WAIT;
2981590Srgrimes				return(curp);
2991590Srgrimes			}
3001590Srgrimes			if (vflag == WAIT)
3011590Srgrimes				(void)printf("*\n");
3021590Srgrimes			vflag = DUP;
3031590Srgrimes			address += blocksize;
3041590Srgrimes			need = blocksize;
3051590Srgrimes			nread = 0;
3061590Srgrimes		}
3071590Srgrimes		else
3081590Srgrimes			nread += n;
3091590Srgrimes	}
3101590Srgrimes}
3111590Srgrimes
312131954Stjrsize_t
313131954Stjrpeek(u_char *buf, size_t nbytes)
314131954Stjr{
315131954Stjr	size_t n, nread;
316131954Stjr	int c;
317131954Stjr
318132541Sjohan	if (length != -1 && nbytes > (unsigned int)length)
319131954Stjr		nbytes = length;
320131954Stjr	nread = 0;
321131954Stjr	while (nread < nbytes && (c = getchar()) != EOF) {
322131954Stjr		*buf++ = c;
323131954Stjr		nread++;
324131954Stjr	}
325131954Stjr	n = nread;
326131954Stjr	while (n-- > 0) {
327131954Stjr		c = *--buf;
328131954Stjr		ungetc(c, stdin);
329131954Stjr	}
330131954Stjr	return (nread);
331131954Stjr}
332131954Stjr
3331590Srgrimesint
334102944Sdwmalonenext(char **argv)
3351590Srgrimes{
3361590Srgrimes	static int done;
3371590Srgrimes	int statok;
3381590Srgrimes
3391590Srgrimes	if (argv) {
3401590Srgrimes		_argv = argv;
3411590Srgrimes		return(1);
3421590Srgrimes	}
3431590Srgrimes	for (;;) {
3441590Srgrimes		if (*_argv) {
345133099Stjr			done = 1;
3461590Srgrimes			if (!(freopen(*_argv, "r", stdin))) {
34727315Scharnier				warn("%s", *_argv);
3481590Srgrimes				exitval = 1;
3491590Srgrimes				++_argv;
3501590Srgrimes				continue;
3511590Srgrimes			}
352133099Stjr			statok = 1;
3531590Srgrimes		} else {
3541590Srgrimes			if (done++)
3551590Srgrimes				return(0);
3561590Srgrimes			statok = 0;
3571590Srgrimes		}
3581590Srgrimes		if (skip)
3591590Srgrimes			doskip(statok ? *_argv : "stdin", statok);
3601590Srgrimes		if (*_argv)
3611590Srgrimes			++_argv;
3621590Srgrimes		if (!skip)
3631590Srgrimes			return(1);
3641590Srgrimes	}
3651590Srgrimes	/* NOTREACHED */
3661590Srgrimes}
3671590Srgrimes
3681590Srgrimesvoid
369102944Sdwmalonedoskip(const char *fname, int statok)
3701590Srgrimes{
371102944Sdwmalone	int cnt;
3721590Srgrimes	struct stat sb;
3731590Srgrimes
3741590Srgrimes	if (statok) {
3751590Srgrimes		if (fstat(fileno(stdin), &sb))
37627315Scharnier			err(1, "%s", fname);
3771590Srgrimes		if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
3781590Srgrimes			address += sb.st_size;
3791590Srgrimes			skip -= sb.st_size;
3801590Srgrimes			return;
3811590Srgrimes		}
3821590Srgrimes	}
383282738Sjilles	if (statok && S_ISREG(sb.st_mode)) {
38482766Sache		if (fseeko(stdin, skip, SEEK_SET))
38527315Scharnier			err(1, "%s", fname);
3861590Srgrimes		address += skip;
3871590Srgrimes		skip = 0;
3881590Srgrimes	} else {
3891590Srgrimes		for (cnt = 0; cnt < skip; ++cnt)
3901590Srgrimes			if (getchar() == EOF)
3911590Srgrimes				break;
3921590Srgrimes		address += cnt;
3931590Srgrimes		skip -= cnt;
3941590Srgrimes	}
3951590Srgrimes}
396