Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:19

0001 /*
0002  * Copyright (c) 1989, 1993
0003  *  The Regents of the University of California.  All rights reserved.
0004  *
0005  * Redistribution and use in source and binary forms, with or without
0006  * modification, are permitted provided that the following conditions
0007  * are met:
0008  * 1. Redistributions of source code must retain the above copyright
0009  *    notice, this list of conditions and the following disclaimer.
0010  * 2. Redistributions in binary form must reproduce the above copyright
0011  *    notice, this list of conditions and the following disclaimer in the
0012  *    documentation and/or other materials provided with the distribution.
0013  * 3. All advertising materials mentioning features or use of this software
0014  *    must display the following acknowledgement:
0015  *  This product includes software developed by the University of
0016  *  California, Berkeley and its contributors.
0017  * 4. Neither the name of the University nor the names of its contributors
0018  *    may be used to endorse or promote products derived from this software
0019  *    without specific prior written permission.
0020  *
0021  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
0022  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0023  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0024  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
0025  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0026  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0027  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0028  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0029  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0030  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0031  * SUCH DAMAGE.
0032  */
0033 
0034 #ifdef HAVE_CONFIG_H
0035 #include "config.h"
0036 #endif
0037 
0038 #ifndef lint
0039 #if 0
0040 static char sccsid[] = "@(#)display.c   8.1 (Berkeley) 6/6/93";
0041 #endif
0042 #endif /* not lint */
0043 #if 0
0044 #include <sys/cdefs.h>
0045 __FBSDID("$FreeBSD: src/usr.bin/hexdump/display.c,v 1.22 2004/08/04 02:47:32 tjr Exp $");
0046 #endif
0047 
0048 #include <sys/param.h>
0049 #include <sys/stat.h>
0050 
0051 #include <stdint.h>
0052 
0053 #include <ctype.h>
0054 #include "err.h"
0055 #include <errno.h>
0056 #include <stdio.h>
0057 #include <stdlib.h>
0058 #include <string.h>
0059 #include <unistd.h>
0060 #include "hexdump.h"
0061 
0062 #define bcmp(s1,s2,sz)  memcmp(s1,s2,sz)
0063 #define bcopy(s,d,sz)   memcpy(d,s,sz)
0064 #define bzero(s,sz) memset(s,0,sz)
0065 #define index(s,c)  strchr(s,c)
0066 
0067 #if RTEMS_REMOVED
0068 enum _vflag vflag = FIRST;
0069 
0070 static off_t address;           /* address/offset in stream */
0071 static off_t eaddress;          /* end address */
0072 #endif
0073 
0074 static void print(rtems_shell_hexdump_globals*, PR *, u_char *);
0075 
0076 void
0077 display(rtems_shell_hexdump_globals* globals)
0078 {
0079     FS *fs;
0080     FU *fu;
0081     PR *pr;
0082     int cnt;
0083     u_char *bp;
0084     off_t saveaddress;
0085     u_char savech, *savebp;
0086 
0087     savech = 0;
0088     while ((bp = get(globals)))
0089         for (fs = fshead, savebp = bp, saveaddress = address; fs;
0090         fs = fs->nextfs, bp = savebp, address = saveaddress)
0091             for (fu = fs->nextfu; fu; fu = fu->nextfu) {
0092             if (fu->flags&F_IGNORE)
0093                 break;
0094             for (cnt = fu->reps; cnt; --cnt)
0095                 for (pr = fu->nextpr; pr; address += pr->bcnt,
0096                 bp += pr->bcnt, pr = pr->nextpr) {
0097                     if (eaddress && address >= eaddress &&
0098                     !(pr->flags & (F_TEXT|F_BPAD)))
0099                         bpad(pr);
0100                     if (cnt == 1 && pr->nospace) {
0101                     savech = *pr->nospace;
0102                     *pr->nospace = '\0';
0103                     }
0104                     print(globals, pr, bp);
0105                     if (cnt == 1 && pr->nospace)
0106                     *pr->nospace = savech;
0107                 }
0108             }
0109     if (endfu) {
0110         /*
0111          * If eaddress not set, error or file size was multiple of
0112          * blocksize, and no partial block ever found.
0113          */
0114         if (!eaddress) {
0115             if (!address)
0116                 return;
0117             eaddress = address;
0118         }
0119         for (pr = endfu->nextpr; pr; pr = pr->nextpr)
0120             switch(pr->flags) {
0121             case F_ADDRESS:
0122                 (void)printf(pr->fmt, (quad_t)eaddress);
0123                 break;
0124             case F_TEXT:
0125                 (void)printf("%s", pr->fmt);
0126                 break;
0127             }
0128     }
0129 }
0130 
0131 static void
0132 print(rtems_shell_hexdump_globals* globals, PR *pr, u_char *bp)
0133 {
0134     long double ldbl;
0135        double f8;
0136         float f4;
0137       int16_t s2;
0138        int8_t s8;
0139       int32_t s4;
0140     u_int16_t u2;
0141     u_int32_t u4;
0142     u_int64_t u8;
0143 
0144     switch(pr->flags) {
0145     case F_ADDRESS:
0146         (void)printf(pr->fmt, (quad_t)address);
0147         break;
0148     case F_BPAD:
0149         (void)printf(pr->fmt, "");
0150         break;
0151     case F_C:
0152         conv_c(globals, pr, bp, eaddress ? eaddress - address :
0153             blocksize - address % blocksize);
0154         break;
0155     case F_CHAR:
0156         (void)printf(pr->fmt, *bp);
0157         break;
0158     case F_DBL:
0159         switch(pr->bcnt) {
0160         case 4:
0161             bcopy(bp, &f4, sizeof(f4));
0162             (void)printf(pr->fmt, f4);
0163             break;
0164         case 8:
0165             bcopy(bp, &f8, sizeof(f8));
0166             (void)printf(pr->fmt, f8);
0167             break;
0168         default:
0169             if (pr->bcnt == sizeof(long double)) {
0170                 bcopy(bp, &ldbl, sizeof(ldbl));
0171                 (void)printf(pr->fmt, ldbl);
0172             }
0173             break;
0174         }
0175         break;
0176     case F_INT:
0177         switch(pr->bcnt) {
0178         case 1:
0179             (void)printf(pr->fmt, (quad_t)(signed char)*bp);
0180             break;
0181         case 2:
0182             bcopy(bp, &s2, sizeof(s2));
0183             (void)printf(pr->fmt, (quad_t)s2);
0184             break;
0185         case 4:
0186             bcopy(bp, &s4, sizeof(s4));
0187             (void)printf(pr->fmt, (quad_t)s4);
0188             break;
0189         case 8:
0190             bcopy(bp, &s8, sizeof(s8));
0191             (void)printf(pr->fmt, s8);
0192             break;
0193         }
0194         break;
0195     case F_P:
0196         (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
0197         break;
0198     case F_STR:
0199         (void)printf(pr->fmt, (char *)bp);
0200         break;
0201     case F_TEXT:
0202         (void)printf("%s", pr->fmt);
0203         break;
0204     case F_U:
0205         conv_u(globals, pr, bp);
0206         break;
0207     case F_UINT:
0208         switch(pr->bcnt) {
0209         case 1:
0210             (void)printf(pr->fmt, (u_quad_t)*bp);
0211             break;
0212         case 2:
0213             bcopy(bp, &u2, sizeof(u2));
0214             (void)printf(pr->fmt, (u_quad_t)u2);
0215             break;
0216         case 4:
0217             bcopy(bp, &u4, sizeof(u4));
0218             (void)printf(pr->fmt, (u_quad_t)u4);
0219             break;
0220         case 8:
0221             bcopy(bp, &u8, sizeof(u8));
0222             (void)printf(pr->fmt, u8);
0223             break;
0224         }
0225         break;
0226     }
0227 }
0228 
0229 void
0230 bpad(PR *pr)
0231 {
0232     static char const *spec = " -0+#";
0233     char *p1, *p2;
0234 
0235     /*
0236      * Remove all conversion flags; '-' is the only one valid
0237      * with %s, and it's not useful here.
0238      */
0239     pr->flags = F_BPAD;
0240     pr->cchar[0] = 's';
0241     pr->cchar[1] = '\0';
0242     for (p1 = pr->fmt; *p1 != '%'; ++p1);
0243     for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
0244     while ((*p2++ = *p1++));
0245 }
0246 
0247 static char **_argv;
0248 
0249 u_char *
0250 get(rtems_shell_hexdump_globals* globals)
0251 {
0252 #if RTEMS_REMOVED
0253     static int ateof = 1;
0254     static u_char *curp, *savp;
0255 #endif
0256     int n;
0257     int need, nread;
0258     int valid_save = 0;
0259     u_char *tmpp;
0260 
0261     if (!curp) {
0262         if ((curp = calloc(1, blocksize)) == NULL)
0263             err(exit_jump, 1, NULL);
0264         if ((savp = calloc(1, blocksize)) == NULL)
0265             err(exit_jump, 1, NULL);
0266     } else {
0267         tmpp = curp;
0268         curp = savp;
0269         savp = tmpp;
0270         address += blocksize;
0271         valid_save = 1;
0272     }
0273     for (need = blocksize, nread = 0;;) {
0274         /*
0275          * if read the right number of bytes, or at EOF for one file,
0276          * and no other files are available, zero-pad the rest of the
0277          * block and set the end flag.
0278          */
0279         if (!length || (ateof && !next(globals, (char **)NULL))) {
0280             if (odmode && address < skip)
0281                 errx(exit_jump, 1, "cannot skip past end of input");
0282             if (need == blocksize)
0283                 return((u_char *)NULL);
0284             /*
0285              * XXX bcmp() is not quite right in the presence
0286              * of multibyte characters.
0287              */
0288             if (vflag != ALL &&
0289                 valid_save &&
0290                 bcmp(curp, savp, nread) == 0) {
0291                 if (vflag != DUP)
0292                     (void)printf("*\n");
0293                 return((u_char *)NULL);
0294             }
0295             bzero((char *)curp + nread, need);
0296             eaddress = address + nread;
0297             return(curp);
0298         }
0299         n = fread((char *)curp + nread, sizeof(u_char),
0300             length == -1 ? need : MIN(length, need), hdstdin);
0301         if (!n) {
0302             if (ferror(hdstdin))
0303                 warn("%s", _argv[-1]);
0304             ateof = 1;
0305             continue;
0306         }
0307         ateof = 0;
0308         if (length != -1)
0309             length -= n;
0310         if (!(need -= n)) {
0311             /*
0312              * XXX bcmp() is not quite right in the presence
0313              * of multibyte characters.
0314              */
0315             if (vflag == ALL || vflag == FIRST ||
0316                 valid_save == 0 ||
0317                 bcmp(curp, savp, blocksize) != 0) {
0318                 if (vflag == DUP || vflag == FIRST)
0319                     vflag = WAIT;
0320                 return(curp);
0321             }
0322             if (vflag == WAIT)
0323                 (void)printf("*\n");
0324             vflag = DUP;
0325             address += blocksize;
0326             need = blocksize;
0327             nread = 0;
0328         }
0329         else
0330             nread += n;
0331     }
0332 }
0333 
0334 size_t
0335 peek(rtems_shell_hexdump_globals* globals, u_char *buf, size_t nbytes)
0336 {
0337     size_t n, nread;
0338     int c;
0339 
0340     if (length != -1 && nbytes > (unsigned int)length)
0341         nbytes = length;
0342     nread = 0;
0343     while (nread < nbytes && (c = getchar()) != EOF) {
0344         *buf++ = c;
0345         nread++;
0346     }
0347     n = nread;
0348     while (n-- > 0) {
0349         c = *--buf;
0350         ungetc(c, hdstdin);
0351     }
0352     return (nread);
0353 }
0354 
0355 int
0356 next(rtems_shell_hexdump_globals* globals, char **argv)
0357 {
0358 #if RTEMS_REMOVED
0359     static int done;
0360 #endif
0361     int statok;
0362 
0363     if (argv) {
0364         _argv = argv;
0365         return(1);
0366     }
0367     for (;;) {
0368         if (*_argv) {
0369             done = 1;
0370       if (!hdstdin) {
0371         hdstdin = malloc(sizeof(FILE));
0372         if (!hdstdin)
0373         {
0374           errno = ENOMEM;
0375           err(exit_jump, 1, "file name allocation");
0376         }
0377         memset (hdstdin, 0, sizeof(FILE));
0378       }
0379             if (!(hdstdin = freopen(*_argv, "r", hdstdin))) {
0380                 warn("%s", *_argv);
0381                 exitval = 1;
0382                 ++_argv;
0383                 continue;
0384             }
0385             statok = 1;
0386         } else {
0387       errno = ECANCELED;
0388       err(exit_jump, 1, "no file (stdin no supported)");
0389             if (done++)
0390                 return(0);
0391             statok = 0;
0392         }
0393         if (skip)
0394             doskip(globals, statok ? *_argv : "stdin", statok);
0395         if (*_argv)
0396             ++_argv;
0397         if (!skip)
0398             return(1);
0399     }
0400     /* NOTREACHED */
0401 }
0402 
0403 void
0404 doskip(rtems_shell_hexdump_globals* globals, const char *fname, int statok)
0405 {
0406     int cnt;
0407     struct stat sb;
0408 
0409     if (statok) {
0410         if (fstat(fileno(hdstdin), &sb))
0411             err(exit_jump, 1, "%s", fname);
0412     /* can seek block devices on RTEMS */
0413         if (0 && S_ISREG(sb.st_mode) && skip >= sb.st_size) {
0414             address += sb.st_size;
0415             skip -= sb.st_size;
0416             return;
0417         }
0418         if (1 || S_ISREG(sb.st_mode)) {
0419             if (fseeko(hdstdin, skip, SEEK_SET))
0420                 err(exit_jump, 1, "%s", fname);
0421             address += skip;
0422             skip = 0;
0423         } else {
0424             for (cnt = 0; cnt < skip; ++cnt)
0425                 if (getchar() == EOF)
0426                     break;
0427             address += cnt;
0428             skip -= cnt;
0429         }
0430     }
0431 }