source: rtems/cpukit/libmisc/shell/hexdump-display.c @ 6cdaa85

5
Last change on this file since 6cdaa85 was 6cdaa85, checked in by Sebastian Huber <sebastian.huber@…>, on Oct 4, 2018 at 6:16:45 PM

shell: Use #include "..." for local header files

Update #3375.

  • Property mode set to 100644
File size: 9.8 KB
Line 
1/*
2 * Copyright (c) 1989, 1993
3 *      The Regents of the University of California.  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#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)display.c   8.1 (Berkeley) 6/6/93";
41#endif
42#endif /* not lint */
43#if 0
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: src/usr.bin/hexdump/display.c,v 1.22 2004/08/04 02:47:32 tjr Exp $");
46#endif
47
48#include <sys/param.h>
49#include <sys/stat.h>
50
51#include <stdint.h>
52
53#include <ctype.h>
54#include "err.h"
55#include <errno.h>
56#include <stdio.h>
57#include <stdlib.h>
58#include <string.h>
59#include <unistd.h>
60#include "hexdump.h"
61
62#define bcmp(s1,s2,sz)  memcmp(s1,s2,sz)
63#define bcopy(s,d,sz)   memcpy(d,s,sz)
64#define bzero(s,sz)     memset(s,0,sz)
65#define index(s,c)      strchr(s,c)
66
67#if RTEMS_REMOVED
68enum _vflag vflag = FIRST;
69
70static off_t address;                   /* address/offset in stream */
71static off_t eaddress;                  /* end address */
72#endif
73
74static void print(rtems_shell_hexdump_globals*, PR *, u_char *);
75
76void
77display(rtems_shell_hexdump_globals* globals)
78{
79        FS *fs;
80        FU *fu;
81        PR *pr;
82        int cnt;
83        u_char *bp;
84        off_t saveaddress;
85        u_char savech, *savebp;
86
87        savech = 0;
88        while ((bp = get(globals)))
89                for (fs = fshead, savebp = bp, saveaddress = address; fs;
90                fs = fs->nextfs, bp = savebp, address = saveaddress)
91                    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
92                        if (fu->flags&F_IGNORE)
93                                break;
94                        for (cnt = fu->reps; cnt; --cnt)
95                            for (pr = fu->nextpr; pr; address += pr->bcnt,
96                                bp += pr->bcnt, pr = pr->nextpr) {
97                                    if (eaddress && address >= eaddress &&
98                                        !(pr->flags & (F_TEXT|F_BPAD)))
99                                            bpad(pr);
100                                    if (cnt == 1 && pr->nospace) {
101                                        savech = *pr->nospace;
102                                        *pr->nospace = '\0';
103                                    }
104                                    print(globals, pr, bp);
105                                    if (cnt == 1 && pr->nospace)
106                                        *pr->nospace = savech;
107                            }
108                    }
109        if (endfu) {
110                /*
111                 * If eaddress not set, error or file size was multiple of
112                 * blocksize, and no partial block ever found.
113                 */
114                if (!eaddress) {
115                        if (!address)
116                                return;
117                        eaddress = address;
118                }
119                for (pr = endfu->nextpr; pr; pr = pr->nextpr)
120                        switch(pr->flags) {
121                        case F_ADDRESS:
122                                (void)printf(pr->fmt, (quad_t)eaddress);
123                                break;
124                        case F_TEXT:
125                                (void)printf("%s", pr->fmt);
126                                break;
127                        }
128        }
129}
130
131static void
132print(rtems_shell_hexdump_globals* globals, PR *pr, u_char *bp)
133{
134        long double ldbl;
135           double f8;
136            float f4;
137          int16_t s2;
138           int8_t s8;
139          int32_t s4;
140        u_int16_t u2;
141        u_int32_t u4;
142        u_int64_t u8;
143
144        switch(pr->flags) {
145        case F_ADDRESS:
146                (void)printf(pr->fmt, (quad_t)address);
147                break;
148        case F_BPAD:
149                (void)printf(pr->fmt, "");
150                break;
151        case F_C:
152                conv_c(globals, pr, bp, eaddress ? eaddress - address :
153                    blocksize - address % blocksize);
154                break;
155        case F_CHAR:
156                (void)printf(pr->fmt, *bp);
157                break;
158        case F_DBL:
159                switch(pr->bcnt) {
160                case 4:
161                        bcopy(bp, &f4, sizeof(f4));
162                        (void)printf(pr->fmt, f4);
163                        break;
164                case 8:
165                        bcopy(bp, &f8, sizeof(f8));
166                        (void)printf(pr->fmt, f8);
167                        break;
168                default:
169                        if (pr->bcnt == sizeof(long double)) {
170                                bcopy(bp, &ldbl, sizeof(ldbl));
171                                (void)printf(pr->fmt, ldbl);
172                        }
173                        break;
174                }
175                break;
176        case F_INT:
177                switch(pr->bcnt) {
178                case 1:
179                        (void)printf(pr->fmt, (quad_t)(signed char)*bp);
180                        break;
181                case 2:
182                        bcopy(bp, &s2, sizeof(s2));
183                        (void)printf(pr->fmt, (quad_t)s2);
184                        break;
185                case 4:
186                        bcopy(bp, &s4, sizeof(s4));
187                        (void)printf(pr->fmt, (quad_t)s4);
188                        break;
189                case 8:
190                        bcopy(bp, &s8, sizeof(s8));
191                        (void)printf(pr->fmt, s8);
192                        break;
193                }
194                break;
195        case F_P:
196                (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
197                break;
198        case F_STR:
199                (void)printf(pr->fmt, (char *)bp);
200                break;
201        case F_TEXT:
202                (void)printf("%s", pr->fmt);
203                break;
204        case F_U:
205                conv_u(globals, pr, bp);
206                break;
207        case F_UINT:
208                switch(pr->bcnt) {
209                case 1:
210                        (void)printf(pr->fmt, (u_quad_t)*bp);
211                        break;
212                case 2:
213                        bcopy(bp, &u2, sizeof(u2));
214                        (void)printf(pr->fmt, (u_quad_t)u2);
215                        break;
216                case 4:
217                        bcopy(bp, &u4, sizeof(u4));
218                        (void)printf(pr->fmt, (u_quad_t)u4);
219                        break;
220                case 8:
221                        bcopy(bp, &u8, sizeof(u8));
222                        (void)printf(pr->fmt, u8);
223                        break;
224                }
225                break;
226        }
227}
228
229void
230bpad(PR *pr)
231{
232        static char const *spec = " -0+#";
233        char *p1, *p2;
234
235        /*
236         * Remove all conversion flags; '-' is the only one valid
237         * with %s, and it's not useful here.
238         */
239        pr->flags = F_BPAD;
240        pr->cchar[0] = 's';
241        pr->cchar[1] = '\0';
242        for (p1 = pr->fmt; *p1 != '%'; ++p1);
243        for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
244        while ((*p2++ = *p1++));
245}
246
247static char **_argv;
248
249u_char *
250get(rtems_shell_hexdump_globals* globals)
251{
252#if RTEMS_REMOVED
253        static int ateof = 1;
254        static u_char *curp, *savp;
255#endif
256        int n;
257        int need, nread;
258        int valid_save = 0;
259        u_char *tmpp;
260
261        if (!curp) {
262                if ((curp = calloc(1, blocksize)) == NULL)
263                        err(exit_jump, 1, NULL);
264                if ((savp = calloc(1, blocksize)) == NULL)
265                        err(exit_jump, 1, NULL);
266        } else {
267                tmpp = curp;
268                curp = savp;
269                savp = tmpp;
270                address += blocksize;
271                valid_save = 1;
272        }
273        for (need = blocksize, nread = 0;;) {
274                /*
275                 * if read the right number of bytes, or at EOF for one file,
276                 * and no other files are available, zero-pad the rest of the
277                 * block and set the end flag.
278                 */
279                if (!length || (ateof && !next(globals, (char **)NULL))) {
280                        if (odmode && address < skip)
281                                errx(exit_jump, 1, "cannot skip past end of input");
282                        if (need == blocksize)
283                                return((u_char *)NULL);
284                        /*
285                         * XXX bcmp() is not quite right in the presence
286                         * of multibyte characters.
287                         */
288                        if (vflag != ALL &&
289                            valid_save &&
290                            bcmp(curp, savp, nread) == 0) {
291                                if (vflag != DUP)
292                                        (void)printf("*\n");
293                                return((u_char *)NULL);
294                        }
295                        bzero((char *)curp + nread, need);
296                        eaddress = address + nread;
297                        return(curp);
298                }
299                n = fread((char *)curp + nread, sizeof(u_char),
300                    length == -1 ? need : MIN(length, need), hdstdin);
301                if (!n) {
302                        if (ferror(hdstdin))
303                                warn("%s", _argv[-1]);
304                        ateof = 1;
305                        continue;
306                }
307                ateof = 0;
308                if (length != -1)
309                        length -= n;
310                if (!(need -= n)) {
311                        /*
312                         * XXX bcmp() is not quite right in the presence
313                         * of multibyte characters.
314                         */
315                        if (vflag == ALL || vflag == FIRST ||
316                            valid_save == 0 ||
317                            bcmp(curp, savp, blocksize) != 0) {
318                                if (vflag == DUP || vflag == FIRST)
319                                        vflag = WAIT;
320                                return(curp);
321                        }
322                        if (vflag == WAIT)
323                                (void)printf("*\n");
324                        vflag = DUP;
325                        address += blocksize;
326                        need = blocksize;
327                        nread = 0;
328                }
329                else
330                        nread += n;
331        }
332}
333
334size_t
335peek(rtems_shell_hexdump_globals* globals, u_char *buf, size_t nbytes)
336{
337        size_t n, nread;
338        int c;
339
340        if (length != -1 && nbytes > (unsigned int)length)
341                nbytes = length;
342        nread = 0;
343        while (nread < nbytes && (c = getchar()) != EOF) {
344                *buf++ = c;
345                nread++;
346        }
347        n = nread;
348        while (n-- > 0) {
349                c = *--buf;
350                ungetc(c, hdstdin);
351        }
352        return (nread);
353}
354
355int
356next(rtems_shell_hexdump_globals* globals, char **argv)
357{
358#if RTEMS_REMOVED
359        static int done;
360#endif
361        int statok;
362
363        if (argv) {
364                _argv = argv;
365                return(1);
366        }
367        for (;;) {
368                if (*_argv) {
369                        done = 1;
370      if (!hdstdin) {
371        hdstdin = malloc(sizeof(FILE));
372        if (!hdstdin)
373        {
374          errno = ENOMEM;
375          err(exit_jump, 1, "file name allocation");
376        }
377        memset (hdstdin, 0, sizeof(FILE));
378      }
379                        if (!(hdstdin = freopen(*_argv, "r", hdstdin))) {
380                                warn("%s", *_argv);
381                                exitval = 1;
382                                ++_argv;
383                                continue;
384                        }
385                        statok = 1;
386                } else {
387      errno = ECANCELED;
388      err(exit_jump, 1, "no file (stdin no supported)");
389                        if (done++)
390                                return(0);
391                        statok = 0;
392                }
393                if (skip)
394                        doskip(globals, statok ? *_argv : "stdin", statok);
395                if (*_argv)
396                        ++_argv;
397                if (!skip)
398                        return(1);
399        }
400        /* NOTREACHED */
401}
402
403void
404doskip(rtems_shell_hexdump_globals* globals, const char *fname, int statok)
405{
406        int cnt;
407        struct stat sb;
408
409        if (statok) {
410                if (fstat(fileno(hdstdin), &sb))
411                        err(exit_jump, 1, "%s", fname);
412    /* can seek block devices on RTEMS */
413                if (0 && S_ISREG(sb.st_mode) && skip >= sb.st_size) {
414                        address += sb.st_size;
415                        skip -= sb.st_size;
416                        return;
417                }
418                if (1 || S_ISREG(sb.st_mode)) {
419                        if (fseeko(hdstdin, skip, SEEK_SET))
420                                err(exit_jump, 1, "%s", fname);
421                        address += skip;
422                        skip = 0;
423                } else {
424                        for (cnt = 0; cnt < skip; ++cnt)
425                                if (getchar() == EOF)
426                                        break;
427                        address += cnt;
428                        skip -= cnt;
429                }
430        }
431}
Note: See TracBrowser for help on using the repository browser.