[BACK]Return to display.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / hexdump

Annotation of src/usr.bin/hexdump/display.c, Revision 1.6

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