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*47174Sbostic static char sccsid[] = "@(#)display.c 5.11 (Berkeley) 03/09/91"; 1038855Sbostic #endif /* not lint */ 1138855Sbostic 1238855Sbostic #include <sys/param.h> 1338855Sbostic #include <sys/stat.h> 1438855Sbostic #include <unistd.h> 1541450Sbostic #include <errno.h> 1638855Sbostic #include <ctype.h> 1738855Sbostic #include <stdio.h> 18*47174Sbostic #include <stdlib.h> 1942056Sbostic #include <string.h> 2038855Sbostic #include "hexdump.h" 2138855Sbostic 2241453Sbostic enum _vflag vflag = FIRST; 2341453Sbostic 2438855Sbostic static off_t address; /* address/offset in stream */ 2538855Sbostic static off_t eaddress; /* end address */ 2638855Sbostic static off_t savaddress; /* saved address/offset in stream */ 2738855Sbostic 2838860Sbostic #define PRINT { \ 2938860Sbostic switch(pr->flags) { \ 3038860Sbostic case F_ADDRESS: \ 3138860Sbostic (void)printf(pr->fmt, address); \ 3238860Sbostic break; \ 3338860Sbostic case F_BPAD: \ 3438860Sbostic (void)printf(pr->fmt, ""); \ 3538860Sbostic break; \ 3638860Sbostic case F_C: \ 3738860Sbostic conv_c(pr, bp); \ 3838860Sbostic break; \ 3938860Sbostic case F_CHAR: \ 4038860Sbostic (void)printf(pr->fmt, *bp); \ 4138860Sbostic break; \ 4238860Sbostic case F_DBL: { \ 4338860Sbostic double dval; \ 4438860Sbostic float fval; \ 4538860Sbostic switch(pr->bcnt) { \ 4638860Sbostic case 4: \ 4738860Sbostic bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ 4838860Sbostic (void)printf(pr->fmt, fval); \ 4938860Sbostic break; \ 5038860Sbostic case 8: \ 5138860Sbostic bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ 5238860Sbostic (void)printf(pr->fmt, dval); \ 5338860Sbostic break; \ 5438860Sbostic } \ 5538860Sbostic break; \ 5638860Sbostic } \ 5738860Sbostic case F_INT: { \ 5838860Sbostic int ival; \ 5938860Sbostic short sval; \ 6038860Sbostic switch(pr->bcnt) { \ 6138860Sbostic case 1: \ 6238860Sbostic (void)printf(pr->fmt, (int)*bp); \ 6338860Sbostic break; \ 6438860Sbostic case 2: \ 6538860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 6638860Sbostic (void)printf(pr->fmt, (int)sval); \ 6738860Sbostic break; \ 6838860Sbostic case 4: \ 6938860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 7038860Sbostic (void)printf(pr->fmt, ival); \ 7138860Sbostic break; \ 7238860Sbostic } \ 7338860Sbostic break; \ 7438860Sbostic } \ 7538860Sbostic case F_P: \ 7638860Sbostic (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ 7738860Sbostic break; \ 7838860Sbostic case F_STR: \ 7938860Sbostic (void)printf(pr->fmt, (char *)bp); \ 8038860Sbostic break; \ 8138860Sbostic case F_TEXT: \ 8238860Sbostic (void)printf(pr->fmt); \ 8338860Sbostic break; \ 8438860Sbostic case F_U: \ 8538860Sbostic conv_u(pr, bp); \ 8638860Sbostic break; \ 8738860Sbostic case F_UINT: { \ 8838860Sbostic u_int ival; \ 8938860Sbostic u_short sval; \ 9038860Sbostic switch(pr->bcnt) { \ 9138860Sbostic case 1: \ 9238860Sbostic (void)printf(pr->fmt, (u_int)*bp); \ 9338860Sbostic break; \ 9438860Sbostic case 2: \ 9538860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 9638860Sbostic (void)printf(pr->fmt, (u_int)sval); \ 9738860Sbostic break; \ 9838860Sbostic case 4: \ 9938860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 10038860Sbostic (void)printf(pr->fmt, ival); \ 10138860Sbostic break; \ 10238860Sbostic } \ 10338860Sbostic break; \ 10438860Sbostic } \ 10538860Sbostic } \ 10638860Sbostic } 10738860Sbostic 10838855Sbostic display() 10938855Sbostic { 11038855Sbostic extern FU *endfu; 11138855Sbostic register FS *fs; 11238855Sbostic register FU *fu; 11338855Sbostic register PR *pr; 11438855Sbostic register int cnt; 11538855Sbostic register u_char *bp; 11638855Sbostic off_t saveaddress; 11738855Sbostic u_char savech, *savebp, *get(); 11838855Sbostic 11938855Sbostic while (bp = get()) 12038855Sbostic for (fs = fshead, savebp = bp, saveaddress = address; fs; 12138860Sbostic fs = fs->nextfs, bp = savebp, address = saveaddress) 12238855Sbostic for (fu = fs->nextfu; fu; fu = fu->nextfu) { 12338855Sbostic if (fu->flags&F_IGNORE) 12438855Sbostic break; 12538855Sbostic for (cnt = fu->reps; cnt; --cnt) 12638855Sbostic for (pr = fu->nextpr; pr; address += pr->bcnt, 12738855Sbostic bp += pr->bcnt, pr = pr->nextpr) { 12838861Sbostic if (eaddress && address >= eaddress && 12938861Sbostic !(pr->flags&(F_TEXT|F_BPAD))) 13038861Sbostic bpad(pr); 13138855Sbostic if (cnt == 1 && pr->nospace) { 13238855Sbostic savech = *pr->nospace; 13338855Sbostic *pr->nospace = '\0'; 13438855Sbostic } 13538860Sbostic PRINT; 13638855Sbostic if (cnt == 1 && pr->nospace) 13738855Sbostic *pr->nospace = savech; 13838855Sbostic } 13938855Sbostic } 14038855Sbostic if (endfu) { 14138855Sbostic /* 14239097Sbostic * if eaddress not set, error or file size was multiple of 14339097Sbostic * blocksize, and no partial block ever found. 14438855Sbostic */ 14539097Sbostic if (!eaddress) { 14639097Sbostic if (!address) 14739097Sbostic return; 14842373Sbostic eaddress = address; 14939097Sbostic } 15038855Sbostic for (pr = endfu->nextpr; pr; pr = pr->nextpr) 15138855Sbostic switch(pr->flags) { 15238855Sbostic case F_ADDRESS: 15338855Sbostic (void)printf(pr->fmt, eaddress); 15438855Sbostic break; 15538855Sbostic case F_TEXT: 15638855Sbostic (void)printf(pr->fmt); 15738855Sbostic break; 15838855Sbostic } 15938855Sbostic } 16038855Sbostic } 16138855Sbostic 16238861Sbostic bpad(pr) 16338861Sbostic PR *pr; 16438861Sbostic { 16538861Sbostic static char *spec = " -0+#"; 16638861Sbostic register char *p1, *p2; 16738861Sbostic 16838861Sbostic /* 16938861Sbostic * remove all conversion flags; '-' is the only one valid 17038861Sbostic * with %s, and it's not useful here. 17138861Sbostic */ 17238861Sbostic pr->flags = F_BPAD; 17338861Sbostic *pr->cchar = 's'; 17438861Sbostic for (p1 = pr->fmt; *p1 != '%'; ++p1); 17538861Sbostic for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); 17638861Sbostic while (*p2++ = *p1++); 17738861Sbostic } 17838861Sbostic 17942630Sbostic static char **_argv; 18042630Sbostic 18138855Sbostic u_char * 18238855Sbostic get() 18338855Sbostic { 18438855Sbostic extern enum _vflag vflag; 18538855Sbostic extern int length; 18638855Sbostic static int ateof = 1; 18738855Sbostic static u_char *curp, *savp; 18838855Sbostic register int n; 18938855Sbostic int need, nread; 19038855Sbostic u_char *tmpp; 19138855Sbostic 19238855Sbostic if (!curp) { 19338855Sbostic curp = (u_char *)emalloc(blocksize); 19438855Sbostic savp = (u_char *)emalloc(blocksize); 19538855Sbostic } else { 19638855Sbostic tmpp = curp; 19738855Sbostic curp = savp; 19838855Sbostic savp = tmpp; 19938855Sbostic address = savaddress += blocksize; 20038855Sbostic } 20138855Sbostic for (need = blocksize, nread = 0;;) { 20238855Sbostic /* 20338855Sbostic * if read the right number of bytes, or at EOF for one file, 20438855Sbostic * and no other files are available, zero-pad the rest of the 20538855Sbostic * block and set the end flag. 20638855Sbostic */ 20738855Sbostic if (!length || ateof && !next((char **)NULL)) { 20838855Sbostic if (need == blocksize) 20938855Sbostic return((u_char *)NULL); 21038855Sbostic if (vflag != ALL && !bcmp(curp, savp, nread)) { 21138855Sbostic if (vflag != DUP) 21238855Sbostic (void)printf("*\n"); 21338855Sbostic return((u_char *)NULL); 21438855Sbostic } 21538855Sbostic bzero((char *)curp + nread, need); 21638855Sbostic eaddress = address + nread; 21738855Sbostic return(curp); 21838855Sbostic } 21938855Sbostic n = fread((char *)curp + nread, sizeof(u_char), 22038855Sbostic length == -1 ? need : MIN(length, need), stdin); 22138855Sbostic if (!n) { 22242630Sbostic if (ferror(stdin)) 22342630Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n", 22442630Sbostic _argv[-1], strerror(errno)); 22538855Sbostic ateof = 1; 22638855Sbostic continue; 22738855Sbostic } 22838855Sbostic ateof = 0; 22938855Sbostic if (length != -1) 23038855Sbostic length -= n; 23138855Sbostic if (!(need -= n)) { 23241450Sbostic if (vflag == ALL || vflag == FIRST || 23341450Sbostic bcmp(curp, savp, blocksize)) { 23441450Sbostic if (vflag == DUP || vflag == FIRST) 23538855Sbostic vflag = WAIT; 23638855Sbostic return(curp); 23738855Sbostic } 23838855Sbostic if (vflag == WAIT) 23938855Sbostic (void)printf("*\n"); 24038855Sbostic vflag = DUP; 24138855Sbostic address = savaddress += blocksize; 24238855Sbostic need = blocksize; 24338855Sbostic nread = 0; 24438855Sbostic } 24538855Sbostic else 24638855Sbostic nread += n; 24738855Sbostic } 24838855Sbostic } 24938855Sbostic 25038855Sbostic extern off_t skip; /* bytes to skip */ 25138855Sbostic 25238855Sbostic next(argv) 25338855Sbostic char **argv; 25438855Sbostic { 25538855Sbostic extern int errno, exitval; 25638855Sbostic static int done; 25738855Sbostic int statok; 25838855Sbostic 25938855Sbostic if (argv) { 26038855Sbostic _argv = argv; 26138855Sbostic return(1); 26238855Sbostic } 26338855Sbostic for (;;) { 26438855Sbostic if (*_argv) { 26538855Sbostic if (!(freopen(*_argv, "r", stdin))) { 26638855Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n", 26738855Sbostic *_argv, strerror(errno)); 26838855Sbostic exitval = 1; 26938855Sbostic ++_argv; 27038855Sbostic continue; 27138855Sbostic } 27238855Sbostic statok = done = 1; 27338855Sbostic } else { 27438855Sbostic if (done++) 27538855Sbostic return(0); 27638855Sbostic statok = 0; 27738855Sbostic } 27838855Sbostic if (skip) 27938855Sbostic doskip(statok ? *_argv : "stdin", statok); 28038855Sbostic if (*_argv) 28138855Sbostic ++_argv; 28238855Sbostic if (!skip) 28338855Sbostic return(1); 28438855Sbostic } 28538855Sbostic /* NOTREACHED */ 28638855Sbostic } 28738855Sbostic 28838855Sbostic doskip(fname, statok) 28938855Sbostic char *fname; 29038855Sbostic int statok; 29138855Sbostic { 29238855Sbostic extern int errno; 29338855Sbostic struct stat sbuf; 29438855Sbostic 29538855Sbostic if (statok) { 29638855Sbostic if (fstat(fileno(stdin), &sbuf)) { 29738855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 29838855Sbostic fname, strerror(errno)); 29938855Sbostic exit(1); 30038855Sbostic } 30138855Sbostic if (skip >= sbuf.st_size) { 30238855Sbostic skip -= sbuf.st_size; 30338855Sbostic address += sbuf.st_size; 30438855Sbostic return; 30538855Sbostic } 30638855Sbostic } 30738855Sbostic if (fseek(stdin, skip, SEEK_SET)) { 30838855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 30938855Sbostic fname, strerror(errno)); 31038855Sbostic exit(1); 31138855Sbostic } 31238855Sbostic savaddress = address += skip; 31338855Sbostic skip = 0; 31438855Sbostic } 31538855Sbostic 31638855Sbostic char * 31738855Sbostic emalloc(size) 31838855Sbostic int size; 31938855Sbostic { 320*47174Sbostic char *p; 32138855Sbostic 32238855Sbostic if (!(p = malloc((u_int)size))) 32338855Sbostic nomem(); 32438855Sbostic bzero(p, size); 32538855Sbostic return(p); 32638855Sbostic } 32738855Sbostic 32838855Sbostic nomem() 32938855Sbostic { 33041450Sbostic extern int errno; 33141450Sbostic 33241450Sbostic (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno)); 33338855Sbostic exit(1); 33438855Sbostic } 335