source: branches/stable/mindi-busybox/libbb/dump.c @ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 13 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 18.9 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Support code for the hexdump and od applets,
4 * based on code from util-linux v 2.11l
5 *
6 * Copyright (c) 1989
7 *  The Regents of the University of California.  All rights reserved.
8 *
9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
10 *
11 * Original copyright notice is retained at the end of this file.
12 */
13
14#include "libbb.h"
15#include "dump.h"
16
17enum _vflag bb_dump_vflag = FIRST;
18FS *bb_dump_fshead;             /* head of format strings */
19static FU *endfu;
20static char **_argv;
21static off_t savaddress;    /* saved address/offset in stream */
22static off_t eaddress;  /* end address */
23static off_t address;   /* address/offset in stream */
24off_t bb_dump_skip;             /* bytes to skip */
25static int exitval;         /* final exit value */
26int bb_dump_blocksize;          /* data block size */
27int bb_dump_length = -1;        /* max bytes to read */
28
29static const char index_str[] ALIGN1 = ".#-+ 0123456789";
30
31static const char size_conv_str[] ALIGN1 =
32"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
33
34static const char lcc[] ALIGN1 = "diouxX";
35
36int bb_dump_size(FS * fs)
37{
38    FU *fu;
39    int bcnt, cur_size;
40    char *fmt;
41    const char *p;
42    int prec;
43
44    /* figure out the data block bb_dump_size needed for each format unit */
45    for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
46        if (fu->bcnt) {
47            cur_size += fu->bcnt * fu->reps;
48            continue;
49        }
50        for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
51            if (*fmt != '%')
52                continue;
53            /*
54             * bb_dump_skip any special chars -- save precision in
55             * case it's a %s format.
56             */
57            while (strchr(index_str + 1, *++fmt));
58            if (*fmt == '.' && isdigit(*++fmt)) {
59                prec = atoi(fmt);
60                while (isdigit(*++fmt));
61            }
62            if (!(p = strchr(size_conv_str + 12, *fmt))) {
63                if (*fmt == 's') {
64                    bcnt += prec;
65                } else if (*fmt == '_') {
66                    ++fmt;
67                    if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
68                        bcnt += 1;
69                    }
70                }
71            } else {
72                bcnt += size_conv_str[p - (size_conv_str + 12)];
73            }
74        }
75        cur_size += bcnt * fu->reps;
76    }
77    return cur_size;
78}
79
80static void rewrite(FS * fs)
81{
82    enum { NOTOKAY, USEBCNT, USEPREC } sokay;
83    PR *pr, **nextpr = NULL;
84    FU *fu;
85    char *p1, *p2, *p3;
86    char savech, *fmtp;
87    const char *byte_count_str;
88    int nconv, prec = 0;
89
90    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
91        /*
92         * break each format unit into print units; each
93         * conversion character gets its own.
94         */
95        for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
96            /* NOSTRICT */
97            /* DBU:[dvae@cray.com] calloc so that forward ptrs start out NULL*/
98            pr = xzalloc(sizeof(PR));
99            if (!fu->nextpr)
100                fu->nextpr = pr;
101            /* ignore nextpr -- its unused inside the loop and is
102             * uninitialized 1st time thru.
103             */
104
105            /* bb_dump_skip preceding text and up to the next % sign */
106            for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
107
108            /* only text in the string */
109            if (!*p1) {
110                pr->fmt = fmtp;
111                pr->flags = F_TEXT;
112                break;
113            }
114
115            /*
116             * get precision for %s -- if have a byte count, don't
117             * need it.
118             */
119            if (fu->bcnt) {
120                sokay = USEBCNT;
121                /* bb_dump_skip to conversion character */
122                for (++p1; strchr(index_str, *p1); ++p1);
123            } else {
124                /* bb_dump_skip any special chars, field width */
125                while (strchr(index_str + 1, *++p1));
126                if (*p1 == '.' && isdigit(*++p1)) {
127                    sokay = USEPREC;
128                    prec = atoi(p1);
129                    while (isdigit(*++p1));
130                } else
131                    sokay = NOTOKAY;
132            }
133
134            p2 = p1 + 1;    /* set end pointer */
135
136            /*
137             * figure out the byte count for each conversion;
138             * rewrite the format as necessary, set up blank-
139             * pbb_dump_adding for end of data.
140             */
141
142            if (*p1 == 'c') {
143                pr->flags = F_CHAR;
144            DO_BYTE_COUNT_1:
145                byte_count_str = "\001";
146            DO_BYTE_COUNT:
147                if (fu->bcnt) {
148                    do {
149                        if (fu->bcnt == *byte_count_str) {
150                            break;
151                        }
152                    } while (*++byte_count_str);
153                }
154                /* Unlike the original, output the remainder of the format string. */
155                if (!*byte_count_str) {
156                    bb_error_msg_and_die("bad byte count for conversion character %s", p1);
157                }
158                pr->bcnt = *byte_count_str;
159            } else if (*p1 == 'l') {
160                ++p2;
161                ++p1;
162            DO_INT_CONV:
163                {
164                    const char *e;
165                    if (!(e = strchr(lcc, *p1))) {
166                        goto DO_BAD_CONV_CHAR;
167                    }
168                    pr->flags = F_INT;
169                    if (e > lcc + 1) {
170                        pr->flags = F_UINT;
171                    }
172                    byte_count_str = "\004\002\001";
173                    goto DO_BYTE_COUNT;
174                }
175                /* NOTREACHED */
176            } else if (strchr(lcc, *p1)) {
177                goto DO_INT_CONV;
178            } else if (strchr("eEfgG", *p1)) {
179                pr->flags = F_DBL;
180                byte_count_str = "\010\004";
181                goto DO_BYTE_COUNT;
182            } else if (*p1 == 's') {
183                pr->flags = F_STR;
184                if (sokay == USEBCNT) {
185                    pr->bcnt = fu->bcnt;
186                } else if (sokay == USEPREC) {
187                    pr->bcnt = prec;
188                } else {    /* NOTOKAY */
189                    bb_error_msg_and_die("%%s requires a precision or a byte count");
190                }
191            } else if (*p1 == '_') {
192                ++p2;
193                switch (p1[1]) {
194                case 'A':
195                    endfu = fu;
196                    fu->flags |= F_IGNORE;
197                    /* FALLTHROUGH */
198                case 'a':
199                    pr->flags = F_ADDRESS;
200                    ++p2;
201                    if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
202                        goto DO_BAD_CONV_CHAR;
203                    }
204                    *p1 = p1[2];
205                    break;
206                case 'c':
207                    pr->flags = F_C;
208                    /* *p1 = 'c';   set in conv_c */
209                    goto DO_BYTE_COUNT_1;
210                case 'p':
211                    pr->flags = F_P;
212                    *p1 = 'c';
213                    goto DO_BYTE_COUNT_1;
214                case 'u':
215                    pr->flags = F_U;
216                    /* *p1 = 'c';   set in conv_u */
217                    goto DO_BYTE_COUNT_1;
218                default:
219                    goto DO_BAD_CONV_CHAR;
220                }
221            } else {
222            DO_BAD_CONV_CHAR:
223                bb_error_msg_and_die("bad conversion character %%%s", p1);
224            }
225
226            /*
227             * copy to PR format string, set conversion character
228             * pointer, update original.
229             */
230            savech = *p2;
231            p1[1] = '\0';
232            pr->fmt = xstrdup(fmtp);
233            *p2 = savech;
234            pr->cchar = pr->fmt + (p1 - fmtp);
235
236            /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost.
237             * Skip subsequent text and up to the next % sign and tack the
238             * additional text onto fmt: eg. if fmt is "%x is a HEX number",
239             * we lose the " is a HEX number" part of fmt.
240             */
241            for (p3 = p2; *p3 && *p3 != '%'; p3++);
242            if (p3 > p2)
243            {
244                savech = *p3;
245                *p3 = '\0';
246                pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt)+(p3-p2)+1);
247                strcat(pr->fmt, p2);
248                *p3 = savech;
249                p2 = p3;
250            }
251
252            fmtp = p2;
253
254            /* only one conversion character if byte count */
255            if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) {
256                bb_error_msg_and_die("byte count with multiple conversion characters");
257            }
258        }
259        /*
260         * if format unit byte count not specified, figure it out
261         * so can adjust rep count later.
262         */
263        if (!fu->bcnt)
264            for (pr = fu->nextpr; pr; pr = pr->nextpr)
265                fu->bcnt += pr->bcnt;
266    }
267    /*
268     * if the format string interprets any data at all, and it's
269     * not the same as the bb_dump_blocksize, and its last format unit
270     * interprets any data at all, and has no iteration count,
271     * repeat it as necessary.
272     *
273     * if, rep count is greater than 1, no trailing whitespace
274     * gets output from the last iteration of the format unit.
275     */
276    for (fu = fs->nextfu;; fu = fu->nextfu) {
277        if (!fu->nextfu && fs->bcnt < bb_dump_blocksize &&
278            !(fu->flags & F_SETREP) && fu->bcnt)
279            fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt;
280        if (fu->reps > 1) {
281            for (pr = fu->nextpr;; pr = pr->nextpr)
282                if (!pr->nextpr)
283                    break;
284            for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
285                p2 = isspace(*p1) ? p1 : NULL;
286            if (p2)
287                pr->nospace = p2;
288        }
289        if (!fu->nextfu)
290            break;
291    }
292}
293
294static void do_skip(const char *fname, int statok)
295{
296    struct stat sbuf;
297
298    if (statok) {
299        if (fstat(STDIN_FILENO, &sbuf)) {
300            bb_perror_msg_and_die("%s", fname);
301        }
302        if ((!(S_ISCHR(sbuf.st_mode) ||
303               S_ISBLK(sbuf.st_mode) ||
304               S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) {
305            /* If bb_dump_size valid and bb_dump_skip >= size */
306            bb_dump_skip -= sbuf.st_size;
307            address += sbuf.st_size;
308            return;
309        }
310    }
311    if (fseek(stdin, bb_dump_skip, SEEK_SET)) {
312        bb_perror_msg_and_die("%s", fname);
313    }
314    savaddress = address += bb_dump_skip;
315    bb_dump_skip = 0;
316}
317
318static int next(char **argv)
319{
320    static smallint done;
321
322    int statok;
323
324    if (argv) {
325        _argv = argv;
326        return 1;
327    }
328    for (;;) {
329        if (*_argv) {
330            if (!(freopen(*_argv, "r", stdin))) {
331                bb_perror_msg("%s", *_argv);
332                exitval = 1;
333                ++_argv;
334                continue;
335            }
336            done = statok = 1;
337        } else {
338            if (done)
339                return 0;
340            done = 1;
341            statok = 0;
342        }
343        if (bb_dump_skip)
344            do_skip(statok ? *_argv : "stdin", statok);
345        if (*_argv)
346            ++_argv;
347        if (!bb_dump_skip)
348            return 1;
349    }
350    /* NOTREACHED */
351}
352
353static unsigned char *get(void)
354{
355    static smallint ateof = 1;
356    static unsigned char *curp = NULL, *savp; /*DBU:[dave@cray.com]initialize curp */
357
358    int n;
359    int need, nread;
360    unsigned char *tmpp;
361
362    if (!curp) {
363        address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/
364        curp = xmalloc(bb_dump_blocksize);
365        savp = xmalloc(bb_dump_blocksize);
366    } else {
367        tmpp = curp;
368        curp = savp;
369        savp = tmpp;
370        address = savaddress += bb_dump_blocksize;
371    }
372    for (need = bb_dump_blocksize, nread = 0;;) {
373        /*
374         * if read the right number of bytes, or at EOF for one file,
375         * and no other files are available, zero-pad the rest of the
376         * block and set the end flag.
377         */
378        if (!bb_dump_length || (ateof && !next((char **) NULL))) {
379            if (need == bb_dump_blocksize) {
380                return NULL;
381            }
382            if (bb_dump_vflag != ALL && !memcmp(curp, savp, nread)) {
383                if (bb_dump_vflag != DUP) {
384                    puts("*");
385                }
386                return NULL;
387            }
388            memset((char *) curp + nread, 0, need);
389            eaddress = address + nread;
390            return curp;
391        }
392        n = fread((char *) curp + nread, sizeof(unsigned char),
393                  bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin);
394        if (!n) {
395            if (ferror(stdin)) {
396                bb_perror_msg("%s", _argv[-1]);
397            }
398            ateof = 1;
399            continue;
400        }
401        ateof = 0;
402        if (bb_dump_length != -1) {
403            bb_dump_length -= n;
404        }
405        need -= n;
406        if (!need) {
407            if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST
408                || memcmp(curp, savp, bb_dump_blocksize)) {
409                if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) {
410                    bb_dump_vflag = WAIT;
411                }
412                return curp;
413            }
414            if (bb_dump_vflag == WAIT) {
415                puts("*");
416            }
417            bb_dump_vflag = DUP;
418            address = savaddress += bb_dump_blocksize;
419            need = bb_dump_blocksize;
420            nread = 0;
421        } else {
422            nread += n;
423        }
424    }
425}
426
427static void bpad(PR * pr)
428{
429    char *p1, *p2;
430
431    /*
432     * remove all conversion flags; '-' is the only one valid
433     * with %s, and it's not useful here.
434     */
435    pr->flags = F_BPAD;
436    *pr->cchar = 's';
437    for (p1 = pr->fmt; *p1 != '%'; ++p1);
438    for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1)
439        if (pr->nospace) pr->nospace--;
440    while ((*p2++ = *p1++) != 0);
441}
442
443static const char conv_str[] ALIGN1 =
444    "\0\\0\0"
445    "\007\\a\0"             /* \a */
446    "\b\\b\0"
447    "\f\\b\0"
448    "\n\\n\0"
449    "\r\\r\0"
450    "\t\\t\0"
451    "\v\\v\0"
452    ;
453
454
455static void conv_c(PR * pr, unsigned char * p)
456{
457    const char *str = conv_str;
458    char buf[10];
459
460    do {
461        if (*p == *str) {
462            ++str;
463            goto strpr;
464        }
465        str += 4;
466    } while (*str);
467
468    if (isprint(*p)) {
469        *pr->cchar = 'c';
470        (void) printf(pr->fmt, *p);
471    } else {
472        sprintf(buf, "%03o", (int) *p);
473        str = buf;
474      strpr:
475        *pr->cchar = 's';
476        printf(pr->fmt, str);
477    }
478}
479
480static void conv_u(PR * pr, unsigned char * p)
481{
482    static const char list[] ALIGN1 =
483        "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
484        "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
485        "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
486        "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
487
488    /* od used nl, not lf */
489    if (*p <= 0x1f) {
490        *pr->cchar = 's';
491        printf(pr->fmt, list + (4 * (int)*p));
492    } else if (*p == 0x7f) {
493        *pr->cchar = 's';
494        printf(pr->fmt, "del");
495    } else if (isprint(*p)) {
496        *pr->cchar = 'c';
497        printf(pr->fmt, *p);
498    } else {
499        *pr->cchar = 'x';
500        printf(pr->fmt, (int) *p);
501    }
502}
503
504static void display(void)
505{
506/*  extern FU *endfu; */
507    FS *fs;
508    FU *fu;
509    PR *pr;
510    int cnt;
511    unsigned char *bp;
512
513    off_t saveaddress;
514    unsigned char savech = 0, *savebp;
515
516    while ((bp = get()) != NULL) {
517        for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs;
518             fs = fs->nextfs, bp = savebp, address = saveaddress) {
519            for (fu = fs->nextfu; fu; fu = fu->nextfu) {
520                if (fu->flags & F_IGNORE) {
521                    break;
522                }
523                for (cnt = fu->reps; cnt; --cnt) {
524                    for (pr = fu->nextpr; pr; address += pr->bcnt,
525                         bp += pr->bcnt, pr = pr->nextpr) {
526                        if (eaddress && address >= eaddress &&
527                            !(pr->flags & (F_TEXT | F_BPAD))) {
528                            bpad(pr);
529                        }
530                        if (cnt == 1 && pr->nospace) {
531                            savech = *pr->nospace;
532                            *pr->nospace = '\0';
533                        }
534/*                      PRINT; */
535                        switch (pr->flags) {
536                        case F_ADDRESS:
537                            printf(pr->fmt, (unsigned int) address);
538                            break;
539                        case F_BPAD:
540                            printf(pr->fmt, "");
541                            break;
542                        case F_C:
543                            conv_c(pr, bp);
544                            break;
545                        case F_CHAR:
546                            printf(pr->fmt, *bp);
547                            break;
548                        case F_DBL:{
549                            double dval;
550                            float fval;
551
552                            switch (pr->bcnt) {
553                            case 4:
554                                memmove((char *) &fval, (char *) bp,
555                                      sizeof(fval));
556                                printf(pr->fmt, fval);
557                                break;
558                            case 8:
559                                memmove((char *) &dval, (char *) bp,
560                                      sizeof(dval));
561                                printf(pr->fmt, dval);
562                                break;
563                            }
564                            break;
565                        }
566                        case F_INT:{
567                            int ival;
568                            short sval;
569
570                            switch (pr->bcnt) {
571                            case 1:
572                                printf(pr->fmt, (int) *bp);
573                                break;
574                            case 2:
575                                memmove((char *) &sval, (char *) bp,
576                                      sizeof(sval));
577                                printf(pr->fmt, (int) sval);
578                                break;
579                            case 4:
580                                memmove((char *) &ival, (char *) bp,
581                                      sizeof(ival));
582                                printf(pr->fmt, ival);
583                                break;
584                            }
585                            break;
586                        }
587                        case F_P:
588                            printf(pr->fmt, isprint(*bp) ? *bp : '.');
589                            break;
590                        case F_STR:
591                            printf(pr->fmt, (char *) bp);
592                            break;
593                        case F_TEXT:
594                            printf(pr->fmt);
595                            break;
596                        case F_U:
597                            conv_u(pr, bp);
598                            break;
599                        case F_UINT:{
600                            unsigned int ival;
601                            unsigned short sval;
602
603                            switch (pr->bcnt) {
604                            case 1:
605                                printf(pr->fmt, (unsigned int) * bp);
606                                break;
607                            case 2:
608                                memmove((char *) &sval, (char *) bp,
609                                      sizeof(sval));
610                                printf(pr->fmt, (unsigned int) sval);
611                                break;
612                            case 4:
613                                memmove((char *) &ival, (char *) bp,
614                                      sizeof(ival));
615                                printf(pr->fmt, ival);
616                                break;
617                            }
618                            break;
619                        }
620                        }
621                        if (cnt == 1 && pr->nospace) {
622                            *pr->nospace = savech;
623                        }
624                    }
625                }
626            }
627        }
628    }
629    if (endfu) {
630        /*
631         * if eaddress not set, error or file bb_dump_size was multiple of
632         * bb_dump_blocksize, and no partial block ever found.
633         */
634        if (!eaddress) {
635            if (!address) {
636                return;
637            }
638            eaddress = address;
639        }
640        for (pr = endfu->nextpr; pr; pr = pr->nextpr) {
641            switch (pr->flags) {
642            case F_ADDRESS:
643                (void) printf(pr->fmt, (unsigned int) eaddress);
644                break;
645            case F_TEXT:
646                (void) printf(pr->fmt);
647                break;
648            }
649        }
650    }
651}
652
653int bb_dump_dump(char **argv)
654{
655    FS *tfs;
656
657    /* figure out the data block bb_dump_size */
658    for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
659        tfs->bcnt = bb_dump_size(tfs);
660        if (bb_dump_blocksize < tfs->bcnt) {
661            bb_dump_blocksize = tfs->bcnt;
662        }
663    }
664    /* rewrite the rules, do syntax checking */
665    for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
666        rewrite(tfs);
667    }
668
669    next(argv);
670    display();
671
672    return exitval;
673}
674
675void bb_dump_add(const char *fmt)
676{
677    const char *p;
678    char *p1;
679    char *p2;
680    static FS **nextfs;
681    FS *tfs;
682    FU *tfu, **nextfu;
683    const char *savep;
684
685    /* start new linked list of format units */
686    tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */
687    if (!bb_dump_fshead) {
688        bb_dump_fshead = tfs;
689    } else {
690        *nextfs = tfs;
691    }
692    nextfs = &tfs->nextfs;
693    nextfu = &tfs->nextfu;
694
695    /* take the format string and break it up into format units */
696    for (p = fmt;;) {
697        /* bb_dump_skip leading white space */
698        p = skip_whitespace(p);
699        if (!*p) {
700            break;
701        }
702
703        /* allocate a new format unit and link it in */
704        /* NOSTRICT */
705        /* DBU:[dave@cray.com] calloc so that forward pointers start out NULL */
706        tfu = xzalloc(sizeof(FU));
707        *nextfu = tfu;
708        nextfu = &tfu->nextfu;
709        tfu->reps = 1;
710
711        /* if leading digit, repetition count */
712        if (isdigit(*p)) {
713            for (savep = p; isdigit(*p); ++p);
714            if (!isspace(*p) && *p != '/') {
715                bb_error_msg_and_die("bad format {%s}", fmt);
716            }
717            /* may overwrite either white space or slash */
718            tfu->reps = atoi(savep);
719            tfu->flags = F_SETREP;
720            /* bb_dump_skip trailing white space */
721            p = skip_whitespace(++p);
722        }
723
724        /* bb_dump_skip slash and trailing white space */
725        if (*p == '/') {
726            p = skip_whitespace(++p);
727        }
728
729        /* byte count */
730        if (isdigit(*p)) {
731// TODO: use bb_strtou
732            savep = p;
733            do p++; while (isdigit(*p));
734            if (!isspace(*p)) {
735                bb_error_msg_and_die("bad format {%s}", fmt);
736            }
737            tfu->bcnt = atoi(savep);
738            /* bb_dump_skip trailing white space */
739            p = skip_whitespace(++p);
740        }
741
742        /* format */
743        if (*p != '"') {
744            bb_error_msg_and_die("bad format {%s}", fmt);
745        }
746        for (savep = ++p; *p != '"';) {
747            if (*p++ == 0) {
748                bb_error_msg_and_die("bad format {%s}", fmt);
749            }
750        }
751        tfu->fmt = xmalloc(p - savep + 1);
752        strncpy(tfu->fmt, savep, p - savep);
753        tfu->fmt[p - savep] = '\0';
754/*      escape(tfu->fmt); */
755
756        p1 = tfu->fmt;
757
758        /* alphabetic escape sequences have to be done in place */
759        for (p2 = p1;; ++p1, ++p2) {
760            if (!*p1) {
761                *p2 = *p1;
762                break;
763            }
764            if (*p1 == '\\') {
765                const char *cs = conv_str + 4;
766                ++p1;
767                *p2 = *p1;
768                do {
769                    if (*p1 == cs[2]) {
770                        *p2 = cs[0];
771                        break;
772                    }
773                    cs += 4;
774                } while (*cs);
775            }
776        }
777
778        p++;
779    }
780}
781
782/*
783 * Copyright (c) 1989 The Regents of the University of California.
784 * All rights reserved.
785 *
786 * Redistribution and use in source and binary forms, with or without
787 * modification, are permitted provided that the following conditions
788 * are met:
789 * 1. Redistributions of source code must retain the above copyright
790 *    notice, this list of conditions and the following disclaimer.
791 * 2. Redistributions in binary form must reproduce the above copyright
792 *    notice, this list of conditions and the following disclaimer in the
793 *    documentation and/or other materials provided with the distribution.
794 * 3. Neither the name of the University nor the names of its contributors
795 *    may be used to endorse or promote products derived from this software
796 *    without specific prior written permission.
797 *
798 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
799 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
800 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
801 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
802 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
803 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
804 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
805 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
806 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
807 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
808 * SUCH DAMAGE.
809 */
Note: See TracBrowser for help on using the repository browser.