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