hexdump: add hd alias, add -R option
authorDenis Vlasenko <vda.linux@googlemail.com>
Sun, 18 Nov 2007 05:36:50 +0000 (05:36 -0000)
committerDenis Vlasenko <vda.linux@googlemail.com>
Sun, 18 Nov 2007 05:36:50 +0000 (05:36 -0000)
include/applets.h
include/usage.h
util-linux/Config.in
util-linux/hexdump.c

index 587ccbf..f188232 100644 (file)
@@ -171,6 +171,7 @@ USE_GREP(APPLET(grep, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_GUNZIP(APPLET(gunzip, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_GZIP(APPLET(gzip, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_HALT(APPLET(halt, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_HD(APPLET_ODDNAME(hd, hexdump, _BB_DIR_USR_BIN, _BB_SUID_NEVER, hd))
 USE_HDPARM(APPLET(hdparm, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_HEAD(APPLET(head, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 USE_HEXDUMP(APPLET_NOEXEC(hexdump, hexdump, _BB_DIR_USR_BIN, _BB_SUID_NEVER, hexdump))
index 592316a..d0eecdb 100644 (file)
        "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n"
 
 #define hexdump_trivial_usage \
-       "[-[bcCdefnosvx]] [OPTION] FILE"
+       "[-bcCdefnosvx" USE_FEATURE_HEXDUMP_REVERSE("R") "] FILE..."
 #define hexdump_full_usage \
        "Display file(s) or standard input in a user specified format" \
-       "\n\nOptions:\n" \
-       "       -b              One-byte octal display\n" \
-       "       -c              One-byte character display\n" \
-       "       -C              Canonical hex+ASCII, 16 bytes per line\n" \
-       "       -d              Two-byte decimal display\n" \
-       "       -e FORMAT STRING\n" \
-       "       -f FORMAT FILE\n" \
-       "       -n LENGTH       Interpret only LENGTH bytes of input\n" \
-       "       -o              Two-byte octal display\n" \
-       "       -s OFFSET       Skip OFFSET bytes\n" \
-       "       -v              Display all input data\n" \
-       "       -x              Two-byte hexadecimal display"
+       "\n\nOptions:" \
+     "\n       -b              One-byte octal display" \
+     "\n       -c              One-byte character display" \
+     "\n       -C              Canonical hex+ASCII, 16 bytes per line" \
+     "\n       -d              Two-byte decimal display" \
+     "\n       -e FORMAT STRING" \
+     "\n       -f FORMAT FILE" \
+     "\n       -n LENGTH       Interpret only LENGTH bytes of input" \
+     "\n       -o              Two-byte octal display" \
+     "\n       -s OFFSET       Skip OFFSET bytes" \
+     "\n       -v              Display all input data" \
+     "\n       -x              Two-byte hexadecimal display" \
+       USE_FEATURE_HEXDUMP_REVERSE( \
+     "\n       -R              Reverse of 'hexdump -Cv'") \
+
+#define hd_trivial_usage \
+       "FILE..."
+#define hd_full_usage \
+       "hd is an alias for hexdump -C"
 
 #define hostid_trivial_usage \
        ""
index 107382f..8b0bbd6 100644 (file)
@@ -210,6 +210,22 @@ config HEXDUMP
          The hexdump utility is used to display binary data in a readable
          way that is comparable to the output from most hex editors.
 
+config HD
+       bool "hd"
+       default n
+       help
+         hd is an alias to hexdump -C.
+
+config FEATURE_HEXDUMP_REVERSE
+       bool "Support -R, reverse of 'hexdump -Cv'"
+       default n
+       depends on HEXDUMP
+       help
+         The hexdump utility is used to display binary data in an ascii
+         readable way. This option creates binary data from an ascii input.
+         NB: this option is non-standard. It's unwise to use it in scripts
+         aimed to be portable.
+
 config HWCLOCK
        bool "hwclock"
        default n
index e6820ae..6708670 100644 (file)
@@ -45,7 +45,7 @@ static const char *const add_strings[] = {
 
 static const char add_first[] ALIGN1 = "\"%07.7_Ax\n\"";
 
-static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v";
+static const char hexdump_opts[] ALIGN1 = "bcdoxCe:f:n:s:v" USE_FEATURE_HEXDUMP_REVERSE("R");
 
 static const struct suffix_mult suffixes[] = {
        { "b", 512 },
@@ -59,10 +59,21 @@ int hexdump_main(int argc, char **argv)
 {
        const char *p;
        int ch;
+#if ENABLE_FEATURE_HEXDUMP_REVERSE
+       FILE *fp;
+       smallint rdump = 0;
+#endif
 
        bb_dump_vflag = FIRST;
        bb_dump_length = -1;
 
+       if (ENABLE_HD && !applet_name[2]) { /* we are "hd" */
+               ch = 'C';
+               goto hd_applet;
+       }
+
+       /* We cannot use getopt32: in hexdump options are cumulative.
+        * E.g. hexdump -C -C file should dump each line twice */
        while ((ch = getopt(argc, argv, hexdump_opts)) > 0) {
                p = strchr(hexdump_opts, ch);
                if (!p)
@@ -70,28 +81,34 @@ int hexdump_main(int argc, char **argv)
                if ((p - hexdump_opts) < 5) {
                        bb_dump_add(add_first);
                        bb_dump_add(add_strings[(int)(p - hexdump_opts)]);
-               } else if (ch == 'C') {
+               }
+               /* Save a little bit of space below by omitting the 'else's. */
+               if (ch == 'C') {
+ hd_applet:
                        bb_dump_add("\"%08.8_Ax\n\"");
                        bb_dump_add("\"%08.8_ax  \" 8/1 \"%02x \" \"  \" 8/1 \"%02x \" ");
                        bb_dump_add("\"  |\" 16/1 \"%_p\" \"|\\n\"");
-               } else {
-                       /* Save a little bit of space below by omitting the 'else's. */
-                       if (ch == 'e') {
-                               bb_dump_add(optarg);
-                       } /* else */
-                       if (ch == 'f') {
-                               bb_dump_addfile(optarg);
-                       } /* else */
-                       if (ch == 'n') {
-                               bb_dump_length = xatoi_u(optarg);
-                       } /* else */
-                       if (ch == 's') {
-                               bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes);
-                       } /* else */
-                       if (ch == 'v') {
-                               bb_dump_vflag = ALL;
-                       }
                }
+               if (ch == 'e') {
+                       bb_dump_add(optarg);
+               } /* else */
+               if (ch == 'f') {
+                       bb_dump_addfile(optarg);
+               } /* else */
+               if (ch == 'n') {
+                       bb_dump_length = xatoi_u(optarg);
+               } /* else */
+               if (ch == 's') {
+                       bb_dump_skip = xatoul_range_sfx(optarg, 0, LONG_MAX, suffixes);
+               } /* else */
+               if (ch == 'v') {
+                       bb_dump_vflag = ALL;
+               }
+#if ENABLE_FEATURE_HEXDUMP_REVERSE
+               if (ch == 'R') {
+                       rdump = 1;
+               }
+#endif
        }
 
        if (!bb_dump_fshead) {
@@ -101,5 +118,40 @@ int hexdump_main(int argc, char **argv)
 
        argv += optind;
 
+#if !ENABLE_FEATURE_HEXDUMP_REVERSE
        return bb_dump_dump(argv);
+#else
+       if (!rdump) {
+               return bb_dump_dump(argv);
+       }
+
+       /* -R: reverse of 'hexdump -Cv' */
+       fp = stdin;
+       if (!*argv) {
+               argv--;
+               goto jump_in;
+       }
+
+       do {
+               char *buf;
+               fp = xfopen(*argv, "r");
+ jump_in:
+               while ((buf = xmalloc_getline(fp)) != NULL) {
+                       p = buf;
+                       while (1) {
+                               /* skip address or previous byte */
+                               while (isxdigit(*p)) p++;
+                               while (*p == ' ') p++;
+                               /* '|' char will break the line */
+                               if (!isxdigit(*p) || sscanf(p, "%x ", &ch) != 1)
+                                       break;
+                               putchar(ch);
+                       }
+                       free(buf);
+               }
+               fclose(fp);
+       } while (*++argv);
+
+       fflush_stdout_and_exit(EXIT_SUCCESS);
+#endif
 }