138855Sbostic /* 238855Sbostic * Copyright (c) 1989 The Regents of the University of California. 338855Sbostic * All rights reserved. 438855Sbostic * 538855Sbostic * Redistribution and use in source and binary forms are permitted 638855Sbostic * provided that the above copyright notice and this paragraph are 738855Sbostic * duplicated in all such forms and that any documentation, 838855Sbostic * advertising materials, and other materials related to such 938855Sbostic * distribution and use acknowledge that the software was developed 1038855Sbostic * by the University of California, Berkeley. The name of the 1138855Sbostic * University may not be used to endorse or promote products derived 1238855Sbostic * from this software without specific prior written permission. 1338855Sbostic * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1438855Sbostic * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1538855Sbostic * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1638855Sbostic */ 1738855Sbostic 1838855Sbostic #ifndef lint 19*39097Sbostic static char sccsid[] = "@(#)display.c 5.4 (Berkeley) 09/07/89"; 2038855Sbostic #endif /* not lint */ 2138855Sbostic 2238855Sbostic #include <sys/param.h> 2338855Sbostic #include <sys/stat.h> 2438855Sbostic #include <unistd.h> 2538855Sbostic #include <ctype.h> 2638855Sbostic #include <stdio.h> 2738855Sbostic #include <strings.h> 2838855Sbostic #include "hexdump.h" 2938855Sbostic 3038855Sbostic static off_t address; /* address/offset in stream */ 3138855Sbostic static off_t eaddress; /* end address */ 3238855Sbostic static off_t savaddress; /* saved address/offset in stream */ 3338855Sbostic 3438860Sbostic #define PRINT { \ 3538860Sbostic switch(pr->flags) { \ 3638860Sbostic case F_ADDRESS: \ 3738860Sbostic (void)printf(pr->fmt, address); \ 3838860Sbostic break; \ 3938860Sbostic case F_BPAD: \ 4038860Sbostic (void)printf(pr->fmt, ""); \ 4138860Sbostic break; \ 4238860Sbostic case F_C: \ 4338860Sbostic conv_c(pr, bp); \ 4438860Sbostic break; \ 4538860Sbostic case F_CHAR: \ 4638860Sbostic (void)printf(pr->fmt, *bp); \ 4738860Sbostic break; \ 4838860Sbostic case F_DBL: { \ 4938860Sbostic double dval; \ 5038860Sbostic float fval; \ 5138860Sbostic switch(pr->bcnt) { \ 5238860Sbostic case 4: \ 5338860Sbostic bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ 5438860Sbostic (void)printf(pr->fmt, fval); \ 5538860Sbostic break; \ 5638860Sbostic case 8: \ 5738860Sbostic bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ 5838860Sbostic (void)printf(pr->fmt, dval); \ 5938860Sbostic break; \ 6038860Sbostic } \ 6138860Sbostic break; \ 6238860Sbostic } \ 6338860Sbostic case F_INT: { \ 6438860Sbostic int ival; \ 6538860Sbostic short sval; \ 6638860Sbostic switch(pr->bcnt) { \ 6738860Sbostic case 1: \ 6838860Sbostic (void)printf(pr->fmt, (int)*bp); \ 6938860Sbostic break; \ 7038860Sbostic case 2: \ 7138860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 7238860Sbostic (void)printf(pr->fmt, (int)sval); \ 7338860Sbostic break; \ 7438860Sbostic case 4: \ 7538860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 7638860Sbostic (void)printf(pr->fmt, ival); \ 7738860Sbostic break; \ 7838860Sbostic } \ 7938860Sbostic break; \ 8038860Sbostic } \ 8138860Sbostic case F_P: \ 8238860Sbostic (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ 8338860Sbostic break; \ 8438860Sbostic case F_STR: \ 8538860Sbostic (void)printf(pr->fmt, (char *)bp); \ 8638860Sbostic break; \ 8738860Sbostic case F_TEXT: \ 8838860Sbostic (void)printf(pr->fmt); \ 8938860Sbostic break; \ 9038860Sbostic case F_U: \ 9138860Sbostic conv_u(pr, bp); \ 9238860Sbostic break; \ 9338860Sbostic case F_UINT: { \ 9438860Sbostic u_int ival; \ 9538860Sbostic u_short sval; \ 9638860Sbostic switch(pr->bcnt) { \ 9738860Sbostic case 1: \ 9838860Sbostic (void)printf(pr->fmt, (u_int)*bp); \ 9938860Sbostic break; \ 10038860Sbostic case 2: \ 10138860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 10238860Sbostic (void)printf(pr->fmt, (u_int)sval); \ 10338860Sbostic break; \ 10438860Sbostic case 4: \ 10538860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 10638860Sbostic (void)printf(pr->fmt, ival); \ 10738860Sbostic break; \ 10838860Sbostic } \ 10938860Sbostic break; \ 11038860Sbostic } \ 11138860Sbostic } \ 11238860Sbostic } 11338860Sbostic 11438855Sbostic display() 11538855Sbostic { 11638855Sbostic extern FU *endfu; 11738855Sbostic register FS *fs; 11838855Sbostic register FU *fu; 11938855Sbostic register PR *pr; 12038855Sbostic register int cnt; 12138855Sbostic register u_char *bp; 12238855Sbostic off_t saveaddress; 12338855Sbostic u_char savech, *savebp, *get(); 12438855Sbostic 12538855Sbostic while (bp = get()) 12638855Sbostic for (fs = fshead, savebp = bp, saveaddress = address; fs; 12738860Sbostic fs = fs->nextfs, bp = savebp, address = saveaddress) 12838855Sbostic for (fu = fs->nextfu; fu; fu = fu->nextfu) { 12938855Sbostic if (fu->flags&F_IGNORE) 13038855Sbostic break; 13138855Sbostic for (cnt = fu->reps; cnt; --cnt) 13238855Sbostic for (pr = fu->nextpr; pr; address += pr->bcnt, 13338855Sbostic bp += pr->bcnt, pr = pr->nextpr) { 13438861Sbostic if (eaddress && address >= eaddress && 13538861Sbostic !(pr->flags&(F_TEXT|F_BPAD))) 13638861Sbostic bpad(pr); 13738855Sbostic if (cnt == 1 && pr->nospace) { 13838855Sbostic savech = *pr->nospace; 13938855Sbostic *pr->nospace = '\0'; 14038855Sbostic } 14138860Sbostic PRINT; 14238855Sbostic if (cnt == 1 && pr->nospace) 14338855Sbostic *pr->nospace = savech; 14438855Sbostic } 14538855Sbostic } 14638855Sbostic if (endfu) { 14738855Sbostic /* 148*39097Sbostic * if eaddress not set, error or file size was multiple of 149*39097Sbostic * blocksize, and no partial block ever found. 15038855Sbostic */ 151*39097Sbostic if (!eaddress) { 152*39097Sbostic if (!address) 153*39097Sbostic return; 15438855Sbostic eaddress = address + blocksize; 155*39097Sbostic } 15638855Sbostic for (pr = endfu->nextpr; pr; pr = pr->nextpr) 15738855Sbostic switch(pr->flags) { 15838855Sbostic case F_ADDRESS: 15938855Sbostic (void)printf(pr->fmt, eaddress); 16038855Sbostic break; 16138855Sbostic case F_TEXT: 16238855Sbostic (void)printf(pr->fmt); 16338855Sbostic break; 16438855Sbostic } 16538855Sbostic } 16638855Sbostic } 16738855Sbostic 16838861Sbostic bpad(pr) 16938861Sbostic PR *pr; 17038861Sbostic { 17138861Sbostic static char *spec = " -0+#"; 17238861Sbostic register char *p1, *p2; 17338861Sbostic 17438861Sbostic /* 17538861Sbostic * remove all conversion flags; '-' is the only one valid 17638861Sbostic * with %s, and it's not useful here. 17738861Sbostic */ 17838861Sbostic pr->flags = F_BPAD; 17938861Sbostic *pr->cchar = 's'; 18038861Sbostic for (p1 = pr->fmt; *p1 != '%'; ++p1); 18138861Sbostic for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); 18238861Sbostic while (*p2++ = *p1++); 18338861Sbostic } 18438861Sbostic 18538855Sbostic u_char * 18638855Sbostic get() 18738855Sbostic { 18838855Sbostic extern enum _vflag vflag; 18938855Sbostic extern int length; 19038855Sbostic static int ateof = 1; 19138855Sbostic static u_char *curp, *savp; 19238855Sbostic register int n; 19338855Sbostic int need, nread; 19438855Sbostic u_char *tmpp; 19538855Sbostic 19638855Sbostic if (!curp) { 19738855Sbostic curp = (u_char *)emalloc(blocksize); 19838855Sbostic savp = (u_char *)emalloc(blocksize); 19938855Sbostic } else { 20038855Sbostic tmpp = curp; 20138855Sbostic curp = savp; 20238855Sbostic savp = tmpp; 20338855Sbostic address = savaddress += blocksize; 20438855Sbostic } 20538855Sbostic for (need = blocksize, nread = 0;;) { 20638855Sbostic /* 20738855Sbostic * if read the right number of bytes, or at EOF for one file, 20838855Sbostic * and no other files are available, zero-pad the rest of the 20938855Sbostic * block and set the end flag. 21038855Sbostic */ 21138855Sbostic if (!length || ateof && !next((char **)NULL)) { 21238855Sbostic if (need == blocksize) 21338855Sbostic return((u_char *)NULL); 21438855Sbostic if (vflag != ALL && !bcmp(curp, savp, nread)) { 21538855Sbostic if (vflag != DUP) 21638855Sbostic (void)printf("*\n"); 21738855Sbostic return((u_char *)NULL); 21838855Sbostic } 21938855Sbostic bzero((char *)curp + nread, need); 22038855Sbostic eaddress = address + nread; 22138855Sbostic return(curp); 22238855Sbostic } 22338855Sbostic n = fread((char *)curp + nread, sizeof(u_char), 22438855Sbostic length == -1 ? need : MIN(length, need), stdin); 22538855Sbostic if (!n) { 22638855Sbostic ateof = 1; 22738855Sbostic continue; 22838855Sbostic } 22938855Sbostic ateof = 0; 23038855Sbostic if (length != -1) 23138855Sbostic length -= n; 23238855Sbostic if (!(need -= n)) { 23338855Sbostic if (vflag == ALL || bcmp(curp, savp, blocksize)) { 23438855Sbostic if (vflag == DUP) 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 static char **_argv; 25838855Sbostic int statok; 25938855Sbostic 26038855Sbostic if (argv) { 26138855Sbostic _argv = argv; 26238855Sbostic return(1); 26338855Sbostic } 26438855Sbostic for (;;) { 26538855Sbostic if (*_argv) { 26638855Sbostic if (!(freopen(*_argv, "r", stdin))) { 26738855Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n", 26838855Sbostic *_argv, strerror(errno)); 26938855Sbostic exitval = 1; 27038855Sbostic ++_argv; 27138855Sbostic continue; 27238855Sbostic } 27338855Sbostic statok = done = 1; 27438855Sbostic } else { 27538855Sbostic if (done++) 27638855Sbostic return(0); 27738855Sbostic statok = 0; 27838855Sbostic } 27938855Sbostic if (skip) 28038855Sbostic doskip(statok ? *_argv : "stdin", statok); 28138855Sbostic if (*_argv) 28238855Sbostic ++_argv; 28338855Sbostic if (!skip) 28438855Sbostic return(1); 28538855Sbostic } 28638855Sbostic /* NOTREACHED */ 28738855Sbostic } 28838855Sbostic 28938855Sbostic doskip(fname, statok) 29038855Sbostic char *fname; 29138855Sbostic int statok; 29238855Sbostic { 29338855Sbostic extern int errno; 29438855Sbostic struct stat sbuf; 29538855Sbostic 29638855Sbostic if (statok) { 29738855Sbostic if (fstat(fileno(stdin), &sbuf)) { 29838855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 29938855Sbostic fname, strerror(errno)); 30038855Sbostic exit(1); 30138855Sbostic } 30238855Sbostic if (skip >= sbuf.st_size) { 30338855Sbostic skip -= sbuf.st_size; 30438855Sbostic address += sbuf.st_size; 30538855Sbostic return; 30638855Sbostic } 30738855Sbostic } 30838855Sbostic if (fseek(stdin, skip, SEEK_SET)) { 30938855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 31038855Sbostic fname, strerror(errno)); 31138855Sbostic exit(1); 31238855Sbostic } 31338855Sbostic savaddress = address += skip; 31438855Sbostic skip = 0; 31538855Sbostic } 31638855Sbostic 31738855Sbostic char * 31838855Sbostic emalloc(size) 31938855Sbostic int size; 32038855Sbostic { 32138855Sbostic char *p, *malloc(); 32238855Sbostic 32338855Sbostic if (!(p = malloc((u_int)size))) 32438855Sbostic nomem(); 32538855Sbostic bzero(p, size); 32638855Sbostic return(p); 32738855Sbostic } 32838855Sbostic 32938855Sbostic nomem() 33038855Sbostic { 33138855Sbostic (void)fprintf(stderr, "hexdump: out of memory.\n"); 33238855Sbostic exit(1); 33338855Sbostic } 334