138855Sbostic /* 238855Sbostic * Copyright (c) 1989 The Regents of the University of California. 338855Sbostic * All rights reserved. 438855Sbostic * 542734Sbostic * %sccs.include.redist.c% 638855Sbostic */ 738855Sbostic 838855Sbostic #ifndef lint 9*60075Sbostic static char sccsid[] = "@(#)display.c 5.15 (Berkeley) 05/17/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 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 8655201Sbostic print(pr, bp) 8755201Sbostic PR *pr; 8855201Sbostic u_char *bp; 8955201Sbostic { 90*60075Sbostic double f8; 91*60075Sbostic float f4; 92*60075Sbostic int16_t s2; 93*60075Sbostic int8_t s8; 94*60075Sbostic int32_t s4; 95*60075Sbostic u_int16_t u2; 96*60075Sbostic u_int32_t u4; 97*60075Sbostic 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 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 * 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 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 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 * 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 35038855Sbostic nomem() 35138855Sbostic { 35255201Sbostic err("%s", strerror(errno)); 35338855Sbostic } 354