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

4.104.115
Last change on this file since c648ca5 was c648ca5, checked in by Ralf Corsepius <ralf.corsepius@…>, on 03/26/10 at 17:42:24

Add HAVE_STRINGS_H for better POSIX compliance.

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