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*42630Sbostic static char sccsid[] = "@(#)display.c 5.9 (Berkeley) 06/01/90"; 2038855Sbostic #endif /* not lint */ 2138855Sbostic 2238855Sbostic #include <sys/param.h> 2338855Sbostic #include <sys/stat.h> 2438855Sbostic #include <unistd.h> 2541450Sbostic #include <errno.h> 2638855Sbostic #include <ctype.h> 2738855Sbostic #include <stdio.h> 2842056Sbostic #include <string.h> 2938855Sbostic #include "hexdump.h" 3038855Sbostic 3141453Sbostic enum _vflag vflag = FIRST; 3241453Sbostic 3338855Sbostic static off_t address; /* address/offset in stream */ 3438855Sbostic static off_t eaddress; /* end address */ 3538855Sbostic static off_t savaddress; /* saved address/offset in stream */ 3638855Sbostic 3738860Sbostic #define PRINT { \ 3838860Sbostic switch(pr->flags) { \ 3938860Sbostic case F_ADDRESS: \ 4038860Sbostic (void)printf(pr->fmt, address); \ 4138860Sbostic break; \ 4238860Sbostic case F_BPAD: \ 4338860Sbostic (void)printf(pr->fmt, ""); \ 4438860Sbostic break; \ 4538860Sbostic case F_C: \ 4638860Sbostic conv_c(pr, bp); \ 4738860Sbostic break; \ 4838860Sbostic case F_CHAR: \ 4938860Sbostic (void)printf(pr->fmt, *bp); \ 5038860Sbostic break; \ 5138860Sbostic case F_DBL: { \ 5238860Sbostic double dval; \ 5338860Sbostic float fval; \ 5438860Sbostic switch(pr->bcnt) { \ 5538860Sbostic case 4: \ 5638860Sbostic bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ 5738860Sbostic (void)printf(pr->fmt, fval); \ 5838860Sbostic break; \ 5938860Sbostic case 8: \ 6038860Sbostic bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ 6138860Sbostic (void)printf(pr->fmt, dval); \ 6238860Sbostic break; \ 6338860Sbostic } \ 6438860Sbostic break; \ 6538860Sbostic } \ 6638860Sbostic case F_INT: { \ 6738860Sbostic int ival; \ 6838860Sbostic short sval; \ 6938860Sbostic switch(pr->bcnt) { \ 7038860Sbostic case 1: \ 7138860Sbostic (void)printf(pr->fmt, (int)*bp); \ 7238860Sbostic break; \ 7338860Sbostic case 2: \ 7438860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 7538860Sbostic (void)printf(pr->fmt, (int)sval); \ 7638860Sbostic break; \ 7738860Sbostic case 4: \ 7838860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 7938860Sbostic (void)printf(pr->fmt, ival); \ 8038860Sbostic break; \ 8138860Sbostic } \ 8238860Sbostic break; \ 8338860Sbostic } \ 8438860Sbostic case F_P: \ 8538860Sbostic (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ 8638860Sbostic break; \ 8738860Sbostic case F_STR: \ 8838860Sbostic (void)printf(pr->fmt, (char *)bp); \ 8938860Sbostic break; \ 9038860Sbostic case F_TEXT: \ 9138860Sbostic (void)printf(pr->fmt); \ 9238860Sbostic break; \ 9338860Sbostic case F_U: \ 9438860Sbostic conv_u(pr, bp); \ 9538860Sbostic break; \ 9638860Sbostic case F_UINT: { \ 9738860Sbostic u_int ival; \ 9838860Sbostic u_short sval; \ 9938860Sbostic switch(pr->bcnt) { \ 10038860Sbostic case 1: \ 10138860Sbostic (void)printf(pr->fmt, (u_int)*bp); \ 10238860Sbostic break; \ 10338860Sbostic case 2: \ 10438860Sbostic bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 10538860Sbostic (void)printf(pr->fmt, (u_int)sval); \ 10638860Sbostic break; \ 10738860Sbostic case 4: \ 10838860Sbostic bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 10938860Sbostic (void)printf(pr->fmt, ival); \ 11038860Sbostic break; \ 11138860Sbostic } \ 11238860Sbostic break; \ 11338860Sbostic } \ 11438860Sbostic } \ 11538860Sbostic } 11638860Sbostic 11738855Sbostic display() 11838855Sbostic { 11938855Sbostic extern FU *endfu; 12038855Sbostic register FS *fs; 12138855Sbostic register FU *fu; 12238855Sbostic register PR *pr; 12338855Sbostic register int cnt; 12438855Sbostic register u_char *bp; 12538855Sbostic off_t saveaddress; 12638855Sbostic u_char savech, *savebp, *get(); 12738855Sbostic 12838855Sbostic while (bp = get()) 12938855Sbostic for (fs = fshead, savebp = bp, saveaddress = address; fs; 13038860Sbostic fs = fs->nextfs, bp = savebp, address = saveaddress) 13138855Sbostic for (fu = fs->nextfu; fu; fu = fu->nextfu) { 13238855Sbostic if (fu->flags&F_IGNORE) 13338855Sbostic break; 13438855Sbostic for (cnt = fu->reps; cnt; --cnt) 13538855Sbostic for (pr = fu->nextpr; pr; address += pr->bcnt, 13638855Sbostic bp += pr->bcnt, pr = pr->nextpr) { 13738861Sbostic if (eaddress && address >= eaddress && 13838861Sbostic !(pr->flags&(F_TEXT|F_BPAD))) 13938861Sbostic bpad(pr); 14038855Sbostic if (cnt == 1 && pr->nospace) { 14138855Sbostic savech = *pr->nospace; 14238855Sbostic *pr->nospace = '\0'; 14338855Sbostic } 14438860Sbostic PRINT; 14538855Sbostic if (cnt == 1 && pr->nospace) 14638855Sbostic *pr->nospace = savech; 14738855Sbostic } 14838855Sbostic } 14938855Sbostic if (endfu) { 15038855Sbostic /* 15139097Sbostic * if eaddress not set, error or file size was multiple of 15239097Sbostic * blocksize, and no partial block ever found. 15338855Sbostic */ 15439097Sbostic if (!eaddress) { 15539097Sbostic if (!address) 15639097Sbostic return; 15742373Sbostic eaddress = address; 15839097Sbostic } 15938855Sbostic for (pr = endfu->nextpr; pr; pr = pr->nextpr) 16038855Sbostic switch(pr->flags) { 16138855Sbostic case F_ADDRESS: 16238855Sbostic (void)printf(pr->fmt, eaddress); 16338855Sbostic break; 16438855Sbostic case F_TEXT: 16538855Sbostic (void)printf(pr->fmt); 16638855Sbostic break; 16738855Sbostic } 16838855Sbostic } 16938855Sbostic } 17038855Sbostic 17138861Sbostic bpad(pr) 17238861Sbostic PR *pr; 17338861Sbostic { 17438861Sbostic static char *spec = " -0+#"; 17538861Sbostic register char *p1, *p2; 17638861Sbostic 17738861Sbostic /* 17838861Sbostic * remove all conversion flags; '-' is the only one valid 17938861Sbostic * with %s, and it's not useful here. 18038861Sbostic */ 18138861Sbostic pr->flags = F_BPAD; 18238861Sbostic *pr->cchar = 's'; 18338861Sbostic for (p1 = pr->fmt; *p1 != '%'; ++p1); 18438861Sbostic for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); 18538861Sbostic while (*p2++ = *p1++); 18638861Sbostic } 18738861Sbostic 188*42630Sbostic static char **_argv; 189*42630Sbostic 19038855Sbostic u_char * 19138855Sbostic get() 19238855Sbostic { 19338855Sbostic extern enum _vflag vflag; 19438855Sbostic extern int length; 19538855Sbostic static int ateof = 1; 19638855Sbostic static u_char *curp, *savp; 19738855Sbostic register int n; 19838855Sbostic int need, nread; 19938855Sbostic u_char *tmpp; 20038855Sbostic 20138855Sbostic if (!curp) { 20238855Sbostic curp = (u_char *)emalloc(blocksize); 20338855Sbostic savp = (u_char *)emalloc(blocksize); 20438855Sbostic } else { 20538855Sbostic tmpp = curp; 20638855Sbostic curp = savp; 20738855Sbostic savp = tmpp; 20838855Sbostic address = savaddress += blocksize; 20938855Sbostic } 21038855Sbostic for (need = blocksize, nread = 0;;) { 21138855Sbostic /* 21238855Sbostic * if read the right number of bytes, or at EOF for one file, 21338855Sbostic * and no other files are available, zero-pad the rest of the 21438855Sbostic * block and set the end flag. 21538855Sbostic */ 21638855Sbostic if (!length || ateof && !next((char **)NULL)) { 21738855Sbostic if (need == blocksize) 21838855Sbostic return((u_char *)NULL); 21938855Sbostic if (vflag != ALL && !bcmp(curp, savp, nread)) { 22038855Sbostic if (vflag != DUP) 22138855Sbostic (void)printf("*\n"); 22238855Sbostic return((u_char *)NULL); 22338855Sbostic } 22438855Sbostic bzero((char *)curp + nread, need); 22538855Sbostic eaddress = address + nread; 22638855Sbostic return(curp); 22738855Sbostic } 22838855Sbostic n = fread((char *)curp + nread, sizeof(u_char), 22938855Sbostic length == -1 ? need : MIN(length, need), stdin); 23038855Sbostic if (!n) { 231*42630Sbostic if (ferror(stdin)) 232*42630Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n", 233*42630Sbostic _argv[-1], strerror(errno)); 23438855Sbostic ateof = 1; 23538855Sbostic continue; 23638855Sbostic } 23738855Sbostic ateof = 0; 23838855Sbostic if (length != -1) 23938855Sbostic length -= n; 24038855Sbostic if (!(need -= n)) { 24141450Sbostic if (vflag == ALL || vflag == FIRST || 24241450Sbostic bcmp(curp, savp, blocksize)) { 24341450Sbostic if (vflag == DUP || vflag == FIRST) 24438855Sbostic vflag = WAIT; 24538855Sbostic return(curp); 24638855Sbostic } 24738855Sbostic if (vflag == WAIT) 24838855Sbostic (void)printf("*\n"); 24938855Sbostic vflag = DUP; 25038855Sbostic address = savaddress += blocksize; 25138855Sbostic need = blocksize; 25238855Sbostic nread = 0; 25338855Sbostic } 25438855Sbostic else 25538855Sbostic nread += n; 25638855Sbostic } 25738855Sbostic } 25838855Sbostic 25938855Sbostic extern off_t skip; /* bytes to skip */ 26038855Sbostic 26138855Sbostic next(argv) 26238855Sbostic char **argv; 26338855Sbostic { 26438855Sbostic extern int errno, exitval; 26538855Sbostic static int done; 26638855Sbostic int statok; 26738855Sbostic 26838855Sbostic if (argv) { 26938855Sbostic _argv = argv; 27038855Sbostic return(1); 27138855Sbostic } 27238855Sbostic for (;;) { 27338855Sbostic if (*_argv) { 27438855Sbostic if (!(freopen(*_argv, "r", stdin))) { 27538855Sbostic (void)fprintf(stderr, "hexdump: %s: %s\n", 27638855Sbostic *_argv, strerror(errno)); 27738855Sbostic exitval = 1; 27838855Sbostic ++_argv; 27938855Sbostic continue; 28038855Sbostic } 28138855Sbostic statok = done = 1; 28238855Sbostic } else { 28338855Sbostic if (done++) 28438855Sbostic return(0); 28538855Sbostic statok = 0; 28638855Sbostic } 28738855Sbostic if (skip) 28838855Sbostic doskip(statok ? *_argv : "stdin", statok); 28938855Sbostic if (*_argv) 29038855Sbostic ++_argv; 29138855Sbostic if (!skip) 29238855Sbostic return(1); 29338855Sbostic } 29438855Sbostic /* NOTREACHED */ 29538855Sbostic } 29638855Sbostic 29738855Sbostic doskip(fname, statok) 29838855Sbostic char *fname; 29938855Sbostic int statok; 30038855Sbostic { 30138855Sbostic extern int errno; 30238855Sbostic struct stat sbuf; 30338855Sbostic 30438855Sbostic if (statok) { 30538855Sbostic if (fstat(fileno(stdin), &sbuf)) { 30638855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 30738855Sbostic fname, strerror(errno)); 30838855Sbostic exit(1); 30938855Sbostic } 31038855Sbostic if (skip >= sbuf.st_size) { 31138855Sbostic skip -= sbuf.st_size; 31238855Sbostic address += sbuf.st_size; 31338855Sbostic return; 31438855Sbostic } 31538855Sbostic } 31638855Sbostic if (fseek(stdin, skip, SEEK_SET)) { 31738855Sbostic (void)fprintf(stderr, "hexdump: %s: %s.\n", 31838855Sbostic fname, strerror(errno)); 31938855Sbostic exit(1); 32038855Sbostic } 32138855Sbostic savaddress = address += skip; 32238855Sbostic skip = 0; 32338855Sbostic } 32438855Sbostic 32538855Sbostic char * 32638855Sbostic emalloc(size) 32738855Sbostic int size; 32838855Sbostic { 32938855Sbostic char *p, *malloc(); 33038855Sbostic 33138855Sbostic if (!(p = malloc((u_int)size))) 33238855Sbostic nomem(); 33338855Sbostic bzero(p, size); 33438855Sbostic return(p); 33538855Sbostic } 33638855Sbostic 33738855Sbostic nomem() 33838855Sbostic { 33941450Sbostic extern int errno; 34041450Sbostic 34141450Sbostic (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno)); 34238855Sbostic exit(1); 34338855Sbostic } 344