busybox/coreutils/od.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * od implementation for busybox
   4 * Based on code from util-linux v 2.11l
   5 *
   6 * Copyright (c) 1990
   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
  15#include "libbb.h"
  16#if ENABLE_DESKTOP
  17/* This one provides -t (busybox's own build script needs it) */
  18#include "od_bloaty.c"
  19#else
  20
  21#include "dump.h"
  22
  23static void
  24odoffset(dumper_t *dumper, int argc, char ***argvp)
  25{
  26        char *num, *p;
  27        int base;
  28        char *end;
  29
  30        /*
  31         * The offset syntax of od(1) was genuinely bizarre.  First, if
  32         * it started with a plus it had to be an offset.  Otherwise, if
  33         * there were at least two arguments, a number or lower-case 'x'
  34         * followed by a number makes it an offset.  By default it was
  35         * octal; if it started with 'x' or '0x' it was hex.  If it ended
  36         * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
  37         * multiplied the number by 512 or 1024 byte units.  There was
  38         * no way to assign a block count to a hex offset.
  39         *
  40         * We assumes it's a file if the offset is bad.
  41         */
  42        p = **argvp;
  43
  44        if (!p) {
  45                /* hey someone is probably piping to us ... */
  46                return;
  47        }
  48
  49        if ((*p != '+')
  50                && (argc < 2
  51                        || (!isdigit(p[0])
  52                                && ((p[0] != 'x') || !isxdigit(p[1])))))
  53                return;
  54
  55        base = 0;
  56        /*
  57         * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
  58         * set base.
  59         */
  60        if (p[0] == '+')
  61                ++p;
  62        if (p[0] == 'x' && isxdigit(p[1])) {
  63                ++p;
  64                base = 16;
  65        } else if (p[0] == '0' && p[1] == 'x') {
  66                p += 2;
  67                base = 16;
  68        }
  69
  70        /* skip over the number */
  71        if (base == 16)
  72                for (num = p; isxdigit(*p); ++p)
  73                        continue;
  74        else
  75                for (num = p; isdigit(*p); ++p)
  76                        continue;
  77
  78        /* check for no number */
  79        if (num == p)
  80                return;
  81
  82        /* if terminates with a '.', base is decimal */
  83        if (*p == '.') {
  84                if (base)
  85                        return;
  86                base = 10;
  87        }
  88
  89        dumper->dump_skip = strtol(num, &end, base ? base : 8);
  90
  91        /* if end isn't the same as p, we got a non-octal digit */
  92        if (end != p)
  93                dumper->dump_skip = 0;
  94        else {
  95                if (*p) {
  96                        if (*p == 'b') {
  97                                dumper->dump_skip *= 512;
  98                                ++p;
  99                        } else if (*p == 'B') {
 100                                dumper->dump_skip *= 1024;
 101                                ++p;
 102                        }
 103                }
 104                if (*p)
 105                        dumper->dump_skip = 0;
 106                else {
 107                        ++*argvp;
 108                        /*
 109                         * If the offset uses a non-octal base, the base of
 110                         * the offset is changed as well.  This isn't pretty,
 111                         * but it's easy.
 112                         */
 113#define TYPE_OFFSET     7
 114                        {
 115                                char x_or_d;
 116                                if (base == 16) {
 117                                        x_or_d = 'x';
 118                                        goto DO_X_OR_D;
 119                                }
 120                                if (base == 10) {
 121                                        x_or_d = 'd';
 122 DO_X_OR_D:
 123                                        dumper->fshead->nextfu->fmt[TYPE_OFFSET]
 124                                                = dumper->fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
 125                                                = x_or_d;
 126                                }
 127                        }
 128                }
 129        }
 130}
 131
 132static const char *const add_strings[] = {
 133        "16/1 \"%3_u \" \"\\n\"",                               /* a */
 134        "8/2 \" %06o \" \"\\n\"",                               /* B, o */
 135        "16/1 \"%03o \" \"\\n\"",                               /* b */
 136        "16/1 \"%3_c \" \"\\n\"",                               /* c */
 137        "8/2 \"  %05u \" \"\\n\"",                              /* d */
 138        "4/4 \"     %010u \" \"\\n\"",                  /* D */
 139        "2/8 \"          %21.14e \" \"\\n\"",   /* e (undocumented in od), F */
 140        "4/4 \" %14.7e \" \"\\n\"",                             /* f */
 141        "4/4 \"       %08x \" \"\\n\"",                 /* H, X */
 142        "8/2 \"   %04x \" \"\\n\"",                             /* h, x */
 143        "4/4 \"    %11d \" \"\\n\"",                    /* I, L, l */
 144        "8/2 \" %6d \" \"\\n\"",                                /* i */
 145        "4/4 \"    %011o \" \"\\n\"",                   /* O */
 146};
 147
 148static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
 149
 150static const char od_o2si[] ALIGN1 = {
 151        0, 1, 2, 3, 5,
 152        4, 6, 6, 7, 8,
 153        9, 0xa, 0xb, 0xa, 0xa,
 154        0xb, 1, 8, 9,
 155};
 156
 157int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 158int od_main(int argc, char **argv)
 159{
 160        int ch;
 161        int first = 1;
 162        char *p;
 163        dumper_t *dumper = alloc_dumper();
 164
 165        while ((ch = getopt(argc, argv, od_opts)) > 0) {
 166                if (ch == 'v') {
 167                        dumper->dump_vflag = ALL;
 168                } else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
 169                        if (first) {
 170                                first = 0;
 171                                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 172                                bb_dump_add(dumper, "\"%07.7_ao  \"");
 173                        } else {
 174                                bb_dump_add(dumper, "\"         \"");
 175                        }
 176                        bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]);
 177                } else {        /* P, p, s, w, or other unhandled */
 178                        bb_show_usage();
 179                }
 180        }
 181        if (!dumper->fshead) {
 182                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 183                bb_dump_add(dumper, "\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
 184        }
 185
 186        argc -= optind;
 187        argv += optind;
 188
 189        odoffset(dumper, argc, &argv);
 190
 191        return bb_dump_dump(dumper, argv);
 192}
 193#endif /* ENABLE_DESKTOP */
 194
 195/*-
 196 * Copyright (c) 1990 The Regents of the University of California.
 197 * All rights reserved.
 198 *
 199 * Redistribution and use in source and binary forms, with or without
 200 * modification, are permitted provided that the following conditions
 201 * are met:
 202 * 1. Redistributions of source code must retain the above copyright
 203 *    notice, this list of conditions and the following disclaimer.
 204 * 2. Redistributions in binary form must reproduce the above copyright
 205 *    notice, this list of conditions and the following disclaimer in the
 206 *    documentation and/or other materials provided with the distribution.
 207 * 3. Neither the name of the University nor the names of its contributors
 208 *    may be used to endorse or promote products derived from this software
 209 *    without specific prior written permission.
 210 *
 211 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 212 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 213 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 214 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 215 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 216 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 217 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 218 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 219 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 220 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 221 * SUCH DAMAGE.
 222 */
 223