1*84d9c625SLionel Sambuc /* $NetBSD: display.c,v 1.22 2013/10/18 20:19:03 christos Exp $ */
21e33498fSThomas Cort
31e33498fSThomas Cort /*
41e33498fSThomas Cort * Copyright (c) 1989, 1993
51e33498fSThomas Cort * The Regents of the University of California. All rights reserved.
61e33498fSThomas Cort *
71e33498fSThomas Cort * Redistribution and use in source and binary forms, with or without
81e33498fSThomas Cort * modification, are permitted provided that the following conditions
91e33498fSThomas Cort * are met:
101e33498fSThomas Cort * 1. Redistributions of source code must retain the above copyright
111e33498fSThomas Cort * notice, this list of conditions and the following disclaimer.
121e33498fSThomas Cort * 2. Redistributions in binary form must reproduce the above copyright
131e33498fSThomas Cort * notice, this list of conditions and the following disclaimer in the
141e33498fSThomas Cort * documentation and/or other materials provided with the distribution.
151e33498fSThomas Cort * 3. Neither the name of the University nor the names of its contributors
161e33498fSThomas Cort * may be used to endorse or promote products derived from this software
171e33498fSThomas Cort * without specific prior written permission.
181e33498fSThomas Cort *
191e33498fSThomas Cort * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
201e33498fSThomas Cort * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
211e33498fSThomas Cort * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
221e33498fSThomas Cort * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
231e33498fSThomas Cort * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
241e33498fSThomas Cort * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
251e33498fSThomas Cort * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
261e33498fSThomas Cort * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
271e33498fSThomas Cort * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
281e33498fSThomas Cort * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
291e33498fSThomas Cort * SUCH DAMAGE.
301e33498fSThomas Cort */
311e33498fSThomas Cort
321e33498fSThomas Cort #if HAVE_NBTOOL_CONFIG_H
331e33498fSThomas Cort #include "nbtool_config.h"
341e33498fSThomas Cort #endif
351e33498fSThomas Cort
361e33498fSThomas Cort #include <sys/cdefs.h>
371e33498fSThomas Cort #if !defined(lint)
381e33498fSThomas Cort #if 0
391e33498fSThomas Cort static char sccsid[] = "@(#)display.c 8.1 (Berkeley) 6/6/93";
401e33498fSThomas Cort #else
41*84d9c625SLionel Sambuc __RCSID("$NetBSD: display.c,v 1.22 2013/10/18 20:19:03 christos Exp $");
421e33498fSThomas Cort #endif
431e33498fSThomas Cort #endif /* not lint */
441e33498fSThomas Cort
451e33498fSThomas Cort #include <sys/param.h>
461e33498fSThomas Cort #include <sys/stat.h>
471e33498fSThomas Cort
481e33498fSThomas Cort #include <ctype.h>
491e33498fSThomas Cort #include <err.h>
501e33498fSThomas Cort #include <errno.h>
511e33498fSThomas Cort #include <inttypes.h>
521e33498fSThomas Cort #include <stdio.h>
531e33498fSThomas Cort #include <stdlib.h>
541e33498fSThomas Cort #include <string.h>
551e33498fSThomas Cort #include <unistd.h>
561e33498fSThomas Cort #include <util.h>
571e33498fSThomas Cort
581e33498fSThomas Cort #include "hexdump.h"
591e33498fSThomas Cort
601e33498fSThomas Cort enum _vflag vflag = FIRST;
611e33498fSThomas Cort
621e33498fSThomas Cort static off_t address; /* address/offset in stream */
631e33498fSThomas Cort static off_t eaddress; /* end address */
641e33498fSThomas Cort
651e33498fSThomas Cort static inline void print(PR *, u_char *);
661e33498fSThomas Cort
671e33498fSThomas Cort void
display(void)681e33498fSThomas Cort display(void)
691e33498fSThomas Cort {
701e33498fSThomas Cort FS *fs;
711e33498fSThomas Cort FU *fu;
721e33498fSThomas Cort PR *pr;
731e33498fSThomas Cort int cnt;
741e33498fSThomas Cort u_char *bp;
751e33498fSThomas Cort off_t saveaddress;
761e33498fSThomas Cort u_char savech, *savebp;
771e33498fSThomas Cort
781e33498fSThomas Cort savech = 0;
791e33498fSThomas Cort while ((bp = get()) != NULL)
801e33498fSThomas Cort for (fs = fshead, savebp = bp, saveaddress = address; fs;
811e33498fSThomas Cort fs = fs->nextfs, bp = savebp, address = saveaddress)
821e33498fSThomas Cort for (fu = fs->nextfu; fu; fu = fu->nextfu) {
831e33498fSThomas Cort if (fu->flags&F_IGNORE)
841e33498fSThomas Cort break;
851e33498fSThomas Cort for (cnt = fu->reps; cnt; --cnt)
861e33498fSThomas Cort for (pr = fu->nextpr; pr; address += pr->bcnt,
871e33498fSThomas Cort bp += pr->bcnt, pr = pr->nextpr) {
881e33498fSThomas Cort if (eaddress && address >= eaddress &&
891e33498fSThomas Cort !(pr->flags & (F_TEXT|F_BPAD)))
901e33498fSThomas Cort bpad(pr);
911e33498fSThomas Cort if (cnt == 1 && pr->nospace) {
921e33498fSThomas Cort savech = *pr->nospace;
931e33498fSThomas Cort *pr->nospace = '\0';
941e33498fSThomas Cort }
951e33498fSThomas Cort print(pr, bp);
961e33498fSThomas Cort if (cnt == 1 && pr->nospace)
971e33498fSThomas Cort *pr->nospace = savech;
981e33498fSThomas Cort }
991e33498fSThomas Cort }
1001e33498fSThomas Cort if (endfu) {
1011e33498fSThomas Cort /*
1021e33498fSThomas Cort * If eaddress not set, error or file size was multiple of
1031e33498fSThomas Cort * blocksize, and no partial block ever found.
1041e33498fSThomas Cort */
1051e33498fSThomas Cort if (!eaddress) {
1061e33498fSThomas Cort if (!address)
1071e33498fSThomas Cort return;
1081e33498fSThomas Cort eaddress = address;
1091e33498fSThomas Cort }
1101e33498fSThomas Cort for (pr = endfu->nextpr; pr; pr = pr->nextpr)
1111e33498fSThomas Cort switch(pr->flags) {
1121e33498fSThomas Cort case F_ADDRESS:
1131e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)eaddress);
1141e33498fSThomas Cort break;
1151e33498fSThomas Cort case F_TEXT:
1161e33498fSThomas Cort (void)printf("%s", pr->fmt);
1171e33498fSThomas Cort break;
1181e33498fSThomas Cort }
1191e33498fSThomas Cort }
1201e33498fSThomas Cort }
1211e33498fSThomas Cort
1221e33498fSThomas Cort static inline void
print(PR * pr,u_char * bp)1231e33498fSThomas Cort print(PR *pr, u_char *bp)
1241e33498fSThomas Cort {
1251e33498fSThomas Cort double f8;
1261e33498fSThomas Cort float f4;
1271e33498fSThomas Cort int16_t s2;
1281e33498fSThomas Cort int32_t s4;
1291e33498fSThomas Cort int64_t s8;
1301e33498fSThomas Cort uint16_t u2;
1311e33498fSThomas Cort uint32_t u4;
1321e33498fSThomas Cort uint64_t u8;
1331e33498fSThomas Cort
1341e33498fSThomas Cort switch(pr->flags) {
1351e33498fSThomas Cort case F_ADDRESS:
1361e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)address);
1371e33498fSThomas Cort break;
1381e33498fSThomas Cort case F_BPAD:
1391e33498fSThomas Cort (void)printf(pr->fmt, "");
1401e33498fSThomas Cort break;
1411e33498fSThomas Cort case F_C:
1421e33498fSThomas Cort conv_c(pr, bp);
1431e33498fSThomas Cort break;
1441e33498fSThomas Cort case F_CHAR:
1451e33498fSThomas Cort (void)printf(pr->fmt, *bp);
1461e33498fSThomas Cort break;
1471e33498fSThomas Cort case F_DBL:
1481e33498fSThomas Cort switch(pr->bcnt) {
1491e33498fSThomas Cort case 4:
1501e33498fSThomas Cort memmove(&f4, bp, sizeof(f4));
1511e33498fSThomas Cort (void)printf(pr->fmt, f4);
1521e33498fSThomas Cort break;
1531e33498fSThomas Cort case 8:
1541e33498fSThomas Cort memmove(&f8, bp, sizeof(f8));
1551e33498fSThomas Cort (void)printf(pr->fmt, f8);
1561e33498fSThomas Cort break;
1571e33498fSThomas Cort }
1581e33498fSThomas Cort break;
1591e33498fSThomas Cort case F_INT:
1601e33498fSThomas Cort switch(pr->bcnt) {
1611e33498fSThomas Cort case 1:
1621e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)*bp);
1631e33498fSThomas Cort break;
1641e33498fSThomas Cort case 2:
1651e33498fSThomas Cort memmove(&s2, bp, sizeof(s2));
1661e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)s2);
1671e33498fSThomas Cort break;
1681e33498fSThomas Cort case 4:
1691e33498fSThomas Cort memmove(&s4, bp, sizeof(s4));
1701e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)s4);
1711e33498fSThomas Cort break;
1721e33498fSThomas Cort case 8:
1731e33498fSThomas Cort memmove(&s8, bp, sizeof(s8));
1741e33498fSThomas Cort (void)printf(pr->fmt, (int64_t)s8);
1751e33498fSThomas Cort break;
1761e33498fSThomas Cort }
1771e33498fSThomas Cort break;
1781e33498fSThomas Cort case F_P:
1791e33498fSThomas Cort (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
1801e33498fSThomas Cort break;
1811e33498fSThomas Cort case F_STR:
1821e33498fSThomas Cort (void)printf(pr->fmt, (char *)bp);
1831e33498fSThomas Cort break;
1841e33498fSThomas Cort case F_TEXT:
1851e33498fSThomas Cort (void)printf("%s", pr->fmt);
1861e33498fSThomas Cort break;
1871e33498fSThomas Cort case F_U:
1881e33498fSThomas Cort conv_u(pr, bp);
1891e33498fSThomas Cort break;
1901e33498fSThomas Cort case F_UINT:
1911e33498fSThomas Cort switch(pr->bcnt) {
1921e33498fSThomas Cort case 1:
1931e33498fSThomas Cort (void)printf(pr->fmt, (uint64_t)*bp);
1941e33498fSThomas Cort break;
1951e33498fSThomas Cort case 2:
1961e33498fSThomas Cort memmove(&u2, bp, sizeof(u2));
1971e33498fSThomas Cort (void)printf(pr->fmt, (uint64_t)u2);
1981e33498fSThomas Cort break;
1991e33498fSThomas Cort case 4:
2001e33498fSThomas Cort memmove(&u4, bp, sizeof(u4));
2011e33498fSThomas Cort (void)printf(pr->fmt, (uint64_t)u4);
2021e33498fSThomas Cort break;
2031e33498fSThomas Cort case 8:
2041e33498fSThomas Cort memmove(&u8, bp, sizeof(u8));
2051e33498fSThomas Cort (void)printf(pr->fmt, (uint64_t)u8);
2061e33498fSThomas Cort break;
2071e33498fSThomas Cort }
2081e33498fSThomas Cort break;
2091e33498fSThomas Cort }
2101e33498fSThomas Cort }
2111e33498fSThomas Cort
2121e33498fSThomas Cort void
bpad(PR * pr)2131e33498fSThomas Cort bpad(PR *pr)
2141e33498fSThomas Cort {
2151e33498fSThomas Cort static const char *spec = " -0+#";
2161e33498fSThomas Cort char *p1, *p2;
2171e33498fSThomas Cort
2181e33498fSThomas Cort /*
2191e33498fSThomas Cort * Remove all conversion flags; '-' is the only one valid
2201e33498fSThomas Cort * with %s, and it's not useful here.
2211e33498fSThomas Cort */
2221e33498fSThomas Cort pr->flags = F_BPAD;
2231e33498fSThomas Cort pr->cchar[0] = 's';
2241e33498fSThomas Cort pr->cchar[1] = '\0';
2251e33498fSThomas Cort for (p1 = pr->fmt; *p1 != '%'; ++p1);
2261e33498fSThomas Cort for (p2 = ++p1; *p1 && strchr(spec, *p1); ++p1);
2271e33498fSThomas Cort while ((*p2++ = *p1++) != '\0');
2281e33498fSThomas Cort }
2291e33498fSThomas Cort
2301e33498fSThomas Cort static char **_argv;
2311e33498fSThomas Cort
2321e33498fSThomas Cort u_char *
get(void)2331e33498fSThomas Cort get(void)
2341e33498fSThomas Cort {
2351e33498fSThomas Cort static int ateof = 1;
2361e33498fSThomas Cort static u_char *curp, *savp;
2371e33498fSThomas Cort int n;
2381e33498fSThomas Cort int need, nread;
2391e33498fSThomas Cort u_char *tmpp;
2401e33498fSThomas Cort
2411e33498fSThomas Cort if (!curp) {
2421e33498fSThomas Cort curp = ecalloc(blocksize, 1);
2431e33498fSThomas Cort savp = ecalloc(blocksize, 1);
2441e33498fSThomas Cort } else {
2451e33498fSThomas Cort tmpp = curp;
2461e33498fSThomas Cort curp = savp;
2471e33498fSThomas Cort savp = tmpp;
2481e33498fSThomas Cort address += blocksize;
2491e33498fSThomas Cort }
2501e33498fSThomas Cort for (need = blocksize, nread = 0;;) {
2511e33498fSThomas Cort /*
2521e33498fSThomas Cort * if read the right number of bytes, or at EOF for one file,
2531e33498fSThomas Cort * and no other files are available, zero-pad the rest of the
2541e33498fSThomas Cort * block and set the end flag.
2551e33498fSThomas Cort */
2561e33498fSThomas Cort if (!length || (ateof && !next(NULL))) {
2571e33498fSThomas Cort if (need == blocksize)
2581e33498fSThomas Cort return(NULL);
2591e33498fSThomas Cort if (!need && vflag != ALL &&
2601e33498fSThomas Cort !memcmp(curp, savp, nread)) {
2611e33498fSThomas Cort if (vflag != DUP)
2621e33498fSThomas Cort (void)printf("*\n");
2631e33498fSThomas Cort return(NULL);
2641e33498fSThomas Cort }
2651e33498fSThomas Cort memset((char *)curp + nread, 0, need);
2661e33498fSThomas Cort eaddress = address + nread;
2671e33498fSThomas Cort return(curp);
2681e33498fSThomas Cort }
2691e33498fSThomas Cort n = fread((char *)curp + nread, sizeof(u_char),
2701e33498fSThomas Cort length == -1 ? need : MIN(length, need), stdin);
2711e33498fSThomas Cort if (!n) {
2721e33498fSThomas Cort if (ferror(stdin))
2731e33498fSThomas Cort warn("%s", _argv[-1]);
2741e33498fSThomas Cort ateof = 1;
2751e33498fSThomas Cort continue;
2761e33498fSThomas Cort }
2771e33498fSThomas Cort ateof = 0;
2781e33498fSThomas Cort if (length != -1)
2791e33498fSThomas Cort length -= n;
2801e33498fSThomas Cort if (!(need -= n)) {
2811e33498fSThomas Cort if (vflag == ALL || vflag == FIRST ||
2821e33498fSThomas Cort memcmp(curp, savp, blocksize)) {
2831e33498fSThomas Cort if (vflag == DUP || vflag == FIRST)
2841e33498fSThomas Cort vflag = WAIT;
2851e33498fSThomas Cort return(curp);
2861e33498fSThomas Cort }
2871e33498fSThomas Cort if (vflag == WAIT)
2881e33498fSThomas Cort (void)printf("*\n");
2891e33498fSThomas Cort vflag = DUP;
2901e33498fSThomas Cort address += blocksize;
2911e33498fSThomas Cort need = blocksize;
2921e33498fSThomas Cort nread = 0;
2931e33498fSThomas Cort }
2941e33498fSThomas Cort else
2951e33498fSThomas Cort nread += n;
2961e33498fSThomas Cort }
2971e33498fSThomas Cort }
2981e33498fSThomas Cort
2991e33498fSThomas Cort int
next(char ** argv)3001e33498fSThomas Cort next(char **argv)
3011e33498fSThomas Cort {
3021e33498fSThomas Cort static int done;
3031e33498fSThomas Cort int statok;
3041e33498fSThomas Cort
3051e33498fSThomas Cort if (argv) {
3061e33498fSThomas Cort _argv = argv;
3071e33498fSThomas Cort return(1);
3081e33498fSThomas Cort }
3091e33498fSThomas Cort for (;;) {
3101e33498fSThomas Cort if (*_argv) {
3111e33498fSThomas Cort if (!(freopen(*_argv, "r", stdin))) {
3121e33498fSThomas Cort warn("%s", *_argv);
3131e33498fSThomas Cort exitval = 1;
3141e33498fSThomas Cort ++_argv;
3151e33498fSThomas Cort continue;
3161e33498fSThomas Cort }
3171e33498fSThomas Cort statok = done = 1;
3181e33498fSThomas Cort } else {
3191e33498fSThomas Cort if (done++)
3201e33498fSThomas Cort return(0);
3211e33498fSThomas Cort statok = 0;
3221e33498fSThomas Cort }
3231e33498fSThomas Cort if (skip)
3241e33498fSThomas Cort doskip(statok ? *_argv : "stdin", statok);
3251e33498fSThomas Cort if (*_argv)
3261e33498fSThomas Cort ++_argv;
3271e33498fSThomas Cort if (!skip)
3281e33498fSThomas Cort return(1);
3291e33498fSThomas Cort }
3301e33498fSThomas Cort /* NOTREACHED */
3311e33498fSThomas Cort }
3321e33498fSThomas Cort
3331e33498fSThomas Cort void
doskip(const char * fname,int statok)3341e33498fSThomas Cort doskip(const char *fname, int statok)
3351e33498fSThomas Cort {
3361e33498fSThomas Cort int cnt;
3371e33498fSThomas Cort struct stat sb;
3381e33498fSThomas Cort
3391e33498fSThomas Cort if (statok) {
3401e33498fSThomas Cort if (fstat(fileno(stdin), &sb))
3411e33498fSThomas Cort err(1, "fstat %s", fname);
3421e33498fSThomas Cort if (S_ISREG(sb.st_mode) && skip >= sb.st_size) {
3431e33498fSThomas Cort address += sb.st_size;
3441e33498fSThomas Cort skip -= sb.st_size;
3451e33498fSThomas Cort return;
3461e33498fSThomas Cort }
347*84d9c625SLionel Sambuc } else
348*84d9c625SLionel Sambuc sb.st_mode = S_IFIFO;
349*84d9c625SLionel Sambuc
3501e33498fSThomas Cort if (S_ISREG(sb.st_mode)) {
3511e33498fSThomas Cort if (fseek(stdin, skip, SEEK_SET))
3521e33498fSThomas Cort err(1, "fseek %s", fname);
3531e33498fSThomas Cort address += skip;
3541e33498fSThomas Cort skip = 0;
3551e33498fSThomas Cort } else {
3561e33498fSThomas Cort for (cnt = 0; cnt < skip; ++cnt)
3571e33498fSThomas Cort if (getchar() == EOF)
3581e33498fSThomas Cort break;
3591e33498fSThomas Cort address += cnt;
3601e33498fSThomas Cort skip -= cnt;
3611e33498fSThomas Cort }
3621e33498fSThomas Cort }
363