1: /* 2: * Copyright (c) 1989 The Regents of the University of California. 3: * All rights reserved. 4: * 5: * Redistribution and use in source and binary forms are permitted 6: * provided that: (1) source distributions retain this entire copyright 7: * notice and comment, and (2) distributions including binaries display 8: * the following acknowledgement: ``This product includes software 9: * developed by the University of California, Berkeley and its contributors'' 10: * in the documentation or other materials provided with the distribution 11: * and in all advertising materials mentioning features or use of this 12: * software. Neither the name of the University nor the names of its 13: * contributors may be used to endorse or promote products derived 14: * from this software without specific prior written permission. 15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18: */ 19: 20: #ifndef lint 21: static char sccsid[] = "@(#)display.c 5.10 (Berkeley) 6/1/90"; 22: #endif /* not lint */ 23: 24: #include <sys/param.h> 25: #include <sys/stat.h> 26: #include <unistd.h> 27: #include <errno.h> 28: #include <ctype.h> 29: #include <stdio.h> 30: #include <string.h> 31: #include "hexdump.h" 32: 33: enum _vflag vflag = FIRST; 34: 35: static off_t address; /* address/offset in stream */ 36: static off_t eaddress; /* end address */ 37: static off_t savaddress; /* saved address/offset in stream */ 38: 39: #define PRINT { \ 40: switch(pr->flags) { \ 41: case F_ADDRESS: \ 42: (void)printf(pr->fmt, address); \ 43: break; \ 44: case F_BPAD: \ 45: (void)printf(pr->fmt, ""); \ 46: break; \ 47: case F_C: \ 48: conv_c(pr, bp); \ 49: break; \ 50: case F_CHAR: \ 51: (void)printf(pr->fmt, *bp); \ 52: break; \ 53: case F_DBL: { \ 54: double dval; \ 55: float fval; \ 56: switch(pr->bcnt) { \ 57: case 4: \ 58: bcopy((char *)bp, (char *)&fval, sizeof(fval)); \ 59: (void)printf(pr->fmt, fval); \ 60: break; \ 61: case 8: \ 62: bcopy((char *)bp, (char *)&dval, sizeof(dval)); \ 63: (void)printf(pr->fmt, dval); \ 64: break; \ 65: } \ 66: break; \ 67: } \ 68: case F_INT: { \ 69: int ival; \ 70: short sval; \ 71: switch(pr->bcnt) { \ 72: case 1: \ 73: (void)printf(pr->fmt, (int)*bp); \ 74: break; \ 75: case 2: \ 76: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 77: (void)printf(pr->fmt, (int)sval); \ 78: break; \ 79: case 4: \ 80: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 81: (void)printf(pr->fmt, ival); \ 82: break; \ 83: } \ 84: break; \ 85: } \ 86: case F_P: \ 87: (void)printf(pr->fmt, isprint(*bp) ? *bp : '.'); \ 88: break; \ 89: case F_STR: \ 90: (void)printf(pr->fmt, (char *)bp); \ 91: break; \ 92: case F_TEXT: \ 93: (void)printf(pr->fmt); \ 94: break; \ 95: case F_U: \ 96: conv_u(pr, bp); \ 97: break; \ 98: case F_UINT: { \ 99: u_int ival; \ 100: u_short sval; \ 101: switch(pr->bcnt) { \ 102: case 1: \ 103: (void)printf(pr->fmt, (u_int)*bp); \ 104: break; \ 105: case 2: \ 106: bcopy((char *)bp, (char *)&sval, sizeof(sval)); \ 107: (void)printf(pr->fmt, (u_int)sval); \ 108: break; \ 109: case 4: \ 110: bcopy((char *)bp, (char *)&ival, sizeof(ival)); \ 111: (void)printf(pr->fmt, ival); \ 112: break; \ 113: } \ 114: break; \ 115: } \ 116: } \ 117: } 118: 119: display() 120: { 121: extern FU *endfu; 122: register FS *fs; 123: register FU *fu; 124: register PR *pr; 125: register int cnt; 126: register u_char *bp; 127: off_t saveaddress; 128: u_char savech, *savebp, *get(); 129: 130: while (bp = get()) 131: for (fs = fshead, savebp = bp, saveaddress = address; fs; 132: fs = fs->nextfs, bp = savebp, address = saveaddress) 133: for (fu = fs->nextfu; fu; fu = fu->nextfu) { 134: if (fu->flags&F_IGNORE) 135: break; 136: for (cnt = fu->reps; cnt; --cnt) 137: for (pr = fu->nextpr; pr; address += pr->bcnt, 138: bp += pr->bcnt, pr = pr->nextpr) { 139: if (eaddress && address >= eaddress && 140: !(pr->flags&(F_TEXT|F_BPAD))) 141: bpad(pr); 142: if (cnt == 1 && pr->nospace) { 143: savech = *pr->nospace; 144: *pr->nospace = '\0'; 145: } 146: PRINT; 147: if (cnt == 1 && pr->nospace) 148: *pr->nospace = savech; 149: } 150: } 151: if (endfu) { 152: /* 153: * if eaddress not set, error or file size was multiple of 154: * blocksize, and no partial block ever found. 155: */ 156: if (!eaddress) { 157: if (!address) 158: return; 159: eaddress = address; 160: } 161: for (pr = endfu->nextpr; pr; pr = pr->nextpr) 162: switch(pr->flags) { 163: case F_ADDRESS: 164: (void)printf(pr->fmt, eaddress); 165: break; 166: case F_TEXT: 167: (void)printf(pr->fmt); 168: break; 169: } 170: } 171: } 172: 173: bpad(pr) 174: PR *pr; 175: { 176: static char *spec = " -0+#"; 177: register char *p1, *p2; 178: 179: /* 180: * remove all conversion flags; '-' is the only one valid 181: * with %s, and it's not useful here. 182: */ 183: pr->flags = F_BPAD; 184: *pr->cchar = 's'; 185: for (p1 = pr->fmt; *p1 != '%'; ++p1); 186: for (p2 = ++p1; *p1 && index(spec, *p1); ++p1); 187: while (*p2++ = *p1++); 188: } 189: 190: static char **_argv; 191: 192: u_char * 193: get() 194: { 195: extern enum _vflag vflag; 196: extern int length; 197: static int ateof = 1; 198: static u_char *curp, *savp; 199: register int n; 200: int need, nread; 201: u_char *tmpp; 202: 203: if (!curp) { 204: curp = (u_char *)emalloc(blocksize); 205: savp = (u_char *)emalloc(blocksize); 206: } else { 207: tmpp = curp; 208: curp = savp; 209: savp = tmpp; 210: address = savaddress += blocksize; 211: } 212: for (need = blocksize, nread = 0;;) { 213: /* 214: * if read the right number of bytes, or at EOF for one file, 215: * and no other files are available, zero-pad the rest of the 216: * block and set the end flag. 217: */ 218: if (!length || ateof && !next((char **)NULL)) { 219: if (need == blocksize) 220: return((u_char *)NULL); 221: if (vflag != ALL && !bcmp(curp, savp, nread)) { 222: if (vflag != DUP) 223: (void)printf("*\n"); 224: return((u_char *)NULL); 225: } 226: bzero((char *)curp + nread, need); 227: eaddress = address + nread; 228: return(curp); 229: } 230: n = fread((char *)curp + nread, sizeof(u_char), 231: length == -1 ? need : MIN(length, need), stdin); 232: if (!n) { 233: if (ferror(stdin)) 234: (void)fprintf(stderr, "hexdump: %s: %s\n", 235: _argv[-1], strerror(errno)); 236: ateof = 1; 237: continue; 238: } 239: ateof = 0; 240: if (length != -1) 241: length -= n; 242: if (!(need -= n)) { 243: if (vflag == ALL || vflag == FIRST || 244: bcmp(curp, savp, blocksize)) { 245: if (vflag == DUP || vflag == FIRST) 246: vflag = WAIT; 247: return(curp); 248: } 249: if (vflag == WAIT) 250: (void)printf("*\n"); 251: vflag = DUP; 252: address = savaddress += blocksize; 253: need = blocksize; 254: nread = 0; 255: } 256: else 257: nread += n; 258: } 259: } 260: 261: extern off_t skip; /* bytes to skip */ 262: 263: next(argv) 264: char **argv; 265: { 266: extern int errno, exitval; 267: static int done; 268: int statok; 269: 270: if (argv) { 271: _argv = argv; 272: return(1); 273: } 274: for (;;) { 275: if (*_argv) { 276: if (!(freopen(*_argv, "r", stdin))) { 277: (void)fprintf(stderr, "hexdump: %s: %s\n", 278: *_argv, strerror(errno)); 279: exitval = 1; 280: ++_argv; 281: continue; 282: } 283: statok = done = 1; 284: } else { 285: if (done++) 286: return(0); 287: statok = 0; 288: } 289: if (skip) 290: doskip(statok ? *_argv : "stdin", statok); 291: if (*_argv) 292: ++_argv; 293: if (!skip) 294: return(1); 295: } 296: /* NOTREACHED */ 297: } 298: 299: doskip(fname, statok) 300: char *fname; 301: int statok; 302: { 303: extern int errno; 304: struct stat sbuf; 305: 306: if (statok) { 307: if (fstat(fileno(stdin), &sbuf)) { 308: (void)fprintf(stderr, "hexdump: %s: %s.\n", 309: fname, strerror(errno)); 310: exit(1); 311: } 312: if (skip >= sbuf.st_size) { 313: skip -= sbuf.st_size; 314: address += sbuf.st_size; 315: return; 316: } 317: } 318: if (fseek(stdin, skip, SEEK_SET)) { 319: (void)fprintf(stderr, "hexdump: %s: %s.\n", 320: fname, strerror(errno)); 321: exit(1); 322: } 323: savaddress = address += skip; 324: skip = 0; 325: } 326: 327: char * 328: emalloc(size) 329: int size; 330: { 331: char *p, *malloc(); 332: 333: if (!(p = malloc((u_int)size))) 334: nomem(); 335: bzero(p, size); 336: return(p); 337: } 338: 339: nomem() 340: { 341: extern int errno; 342: 343: (void)fprintf(stderr, "hexdump: %s.\n", strerror(errno)); 344: exit(1); 345: }