catv: convert this bbox-specific applet into "cat -v"
No binary (build failed)
—
(log yok)
| @@ -12,8 +12,15 @@ | |
| //config: help | |
| //config: cat is used to concatenate files and print them to the standard | |
| //config: output. Enable this option if you wish to enable the 'cat' utility. | |
| + | //config: |
| + | //config:config FEATURE_CATV |
| + | //config: bool "cat -v[etA]" |
| + | //config: default y |
| + | //config: depends on CAT |
| + | //config: help |
| + | //config: Display nonprinting characters as escape sequences |
| - | //applet:IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) |
| + | //applet:IF_CAT(APPLET(cat, BB_DIR_BIN, BB_SUID_DROP)) |
| //kbuild:lib-$(CONFIG_CAT) += cat.o | |
| @@ -21,22 +28,27 @@ | |
| /* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */ | |
| //usage:#define cat_trivial_usage | |
| - | //usage: "[-n] [FILE]..." |
| + | //usage: "[-nb"IF_FEATURE_CATV("vteA")"] [FILE]..." |
| //usage:#define cat_full_usage "\n\n" | |
| - | //usage: "Concatenate FILEs and print them to stdout" |
| + | //usage: "Print FILEs to stdout\n" |
| //usage: "\n -n Number output lines" | |
| + | //usage: "\n -b Number nonempty lines" |
| + | //usage: IF_FEATURE_CATV( |
| + | //usage: "\n -v Show nonprinting characters as ^x or M-x" |
| + | //usage: "\n -t ...and tabs as ^I" |
| + | //usage: "\n -e ...and end lines with $" |
| + | //usage: "\n -A Same as -vte" |
| + | //usage: ) |
| /* | |
| Longopts not implemented yet: | |
| - | --number-nonblank number nonempty output lines, overrides -n |
| - | --number number all output lines |
| + | --number-nonblank number nonempty output lines, overrides -n |
| + | --number number all output lines |
| + | --show-nonprinting use ^ and M- notation, except for LFD and TAB |
| + | --show-all equivalent to -vet |
| Not implemented yet: | |
| - | -A, --show-all equivalent to -vET |
| - | -e equivalent to -vE |
| - | -E, --show-ends display $ at end of each line |
| + | -E, --show-ends display $ at end of each line (-e sans -v) |
| + | -T, --show-tabs display TAB characters as ^I (-t sans -v) |
| -s, --squeeze-blank suppress repeated empty output lines | |
| - | -t equivalent to -vT |
| - | -T, --show-tabs display TAB characters as ^I |
| - | -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB |
| */ | |
| //usage: | |
| //usage:#define cat_example_usage | |
| @@ -44,19 +56,111 @@ | |
| //usage: "110716.72 17.67" | |
| #include "libbb.h" | |
| + | #include "common_bufsiz.h" |
| + | |
| + | #if ENABLE_FEATURE_CATV |
| + | /* |
| + | * cat -v implementation for busybox |
| + | * |
| + | * Copyright (C) 2006 Rob Landley <[email protected]> |
| + | * |
| + | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| + | */ |
| + | /* Rob had "cat -v" implemented as a separate applet, catv. |
| + | * See "cat -v considered harmful" at |
| + | * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz |
| + | * From USENIX Summer Conference Proceedings, 1983 |
| + | * """ |
| + | * The talk reviews reasons for UNIX's popularity and shows, using UCB cat |
| + | * as a primary example, how UNIX has grown fat. cat isn't for printing |
| + | * files with line numbers, it isn't for compressing multiple blank lines, |
| + | * it's not for looking at non-printing ASCII characters, it's for |
| + | * concatenating files. |
| + | * We are reminded that ls isn't the place for code to break a single column |
| + | * into multiple ones, and that mailnews shouldn't have its own more |
| + | * processing or joke encryption code. |
| + | * """ |
| + | * |
| + | * I agree with the argument. Unfortunately, this ship has sailed (1983...). |
| + | * There are dozens of Linux distros and each of them has "cat" which supports -v. |
| + | * It's unrealistic for us to "reeducate" them to use our, incompatible way |
| + | * to achieve "cat -v" effect. The actuall effect would be "users pissed off |
| + | * by gratuitous incompatibility". |
| + | */ |
| + | #define CATV_OPT_e (1<<0) |
| + | #define CATV_OPT_t (1<<1) |
| + | #define CATV_OPT_v (1<<2) |
| + | static int catv(unsigned opts, char **argv) |
| + | { |
| + | int retval = EXIT_SUCCESS; |
| + | int fd; |
| - | /* This is a NOFORK applet. Be very careful! */ |
| + | BUILD_BUG_ON(CATV_OPT_e != VISIBLE_ENDLINE); |
| + | BUILD_BUG_ON(CATV_OPT_t != VISIBLE_SHOW_TABS); |
| + | #if 0 /* These consts match, we can just pass "opts" to visible() */ |
| + | if (opts & CATV_OPT_e) |
| + | flags |= VISIBLE_ENDLINE; |
| + | if (opts & CATV_OPT_t) |
| + | flags |= VISIBLE_SHOW_TABS; |
| + | #endif |
| + | |
| + | /* Read from stdin if there's nothing else to do. */ |
| + | if (!argv[0]) |
| + | *--argv = (char*)"-"; |
| + | |
| + | #define read_buf bb_common_bufsiz1 |
| + | setup_common_bufsiz(); |
| + | do { |
| + | fd = open_or_warn_stdin(*argv); |
| + | if (fd < 0) { |
| + | retval = EXIT_FAILURE; |
| + | continue; |
| + | } |
| + | for (;;) { |
| + | int i, res; |
| + | |
| + | res = read(fd, read_buf, COMMON_BUFSIZE); |
| + | if (res < 0) |
| + | retval = EXIT_FAILURE; |
| + | if (res <= 0) |
| + | break; |
| + | for (i = 0; i < res; i++) { |
| + | unsigned char c = read_buf[i]; |
| + | char buf[sizeof("M-^c")]; |
| + | visible(c, buf, opts); |
| + | fputs(buf, stdout); |
| + | } |
| + | } |
| + | if (ENABLE_FEATURE_CLEAN_UP && fd) |
| + | close(fd); |
| + | } while (*++argv); |
| + | |
| + | fflush_stdout_and_exit(retval); |
| + | } |
| + | #endif |
| int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |
| int cat_main(int argc UNUSED_PARAM, char **argv) | |
| { | |
| struct number_state ns; | |
| - | unsigned opt; |
| + | unsigned opts; |
| - | /* -u is ignored */ |
| - | opt = getopt32(argv, "nbu"); |
| + | IF_FEATURE_CATV(opt_complementary = "Aetv"; /* -A == -vet */) |
| + | /* -u is ignored ("unbuffered") */ |
| + | opts = getopt32(argv, IF_FEATURE_CATV("etvA")"nbu"); |
| argv += optind; | |
| - | if (!(opt & 3)) /* no -n or -b */ |
| + | |
| + | #if ENABLE_FEATURE_CATV |
| + | if (opts & 7) |
| + | return catv(opts, argv); |
| + | //BUG: -v,-e,-t,-A ignore -nb |
| + | opts >>= 4; |
| + | #endif |
| + | |
| + | #define CAT_OPT_n (1<<0) |
| + | #define CAT_OPT_b (1<<1) |
| + | #define CAT_OPT_u (1<<2) |
| + | if (!(opts & (CAT_OPT_n|CAT_OPT_b))) /* no -n or -b */ |
| return bb_cat(argv); | |
| if (!*argv) | |
| @@ -66,8 +170,8 @@ int cat_main(int argc UNUSED_PARAM, char **argv) | |
| ns.inc = 1; | |
| ns.sep = "\t"; | |
| ns.empty_str = "\n"; | |
| - | ns.all = !(opt & 2); /* -n without -b */ |
| - | ns.nonempty = (opt & 2); /* -b (with or without -n) */ |
| + | ns.all = !(opts & CAT_OPT_b); /* -n without -b */ |
| + | ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */ |
| do { | |
| print_numbered_lines(&ns, *argv); | |
| } while (*++argv); | |
| @@ -1,96 +0,0 @@ | |
| - | /* vi: set sw=4 ts=4: */ |
| - | /* |
| - | * cat -v implementation for busybox |
| - | * |
| - | * Copyright (C) 2006 Rob Landley <[email protected]> |
| - | * |
| - | * Licensed under GPLv2 or later, see file LICENSE in this source tree. |
| - | */ |
| - | |
| - | /* See "Cat -v considered harmful" at |
| - | * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz */ |
| - | |
| - | //config:config CATV |
| - | //config: bool "catv" |
| - | //config: default y |
| - | //config: help |
| - | //config: Display nonprinting characters as escape sequences (like some |
| - | //config: implementations' cat -v option). |
| - | |
| - | //applet:IF_CATV(APPLET(catv, BB_DIR_BIN, BB_SUID_DROP)) |
| - | |
| - | //kbuild:lib-$(CONFIG_CATV) += catv.o |
| - | |
| - | //usage:#define catv_trivial_usage |
| - | //usage: "[-etv] [FILE]..." |
| - | //usage:#define catv_full_usage "\n\n" |
| - | //usage: "Display nonprinting characters as ^x or M-x\n" |
| - | //usage: "\n -e End each line with $" |
| - | //usage: "\n -t Show tabs as ^I" |
| - | //usage: "\n -v Don't use ^x or M-x escapes" |
| - | |
| - | #include "libbb.h" |
| - | #include "common_bufsiz.h" |
| - | |
| - | #define CATV_OPT_e (1<<0) |
| - | #define CATV_OPT_t (1<<1) |
| - | #define CATV_OPT_v (1<<2) |
| - | struct BUG_const_mismatch { |
| - | char BUG_const_mismatch[ |
| - | CATV_OPT_e == VISIBLE_ENDLINE && CATV_OPT_t == VISIBLE_SHOW_TABS |
| - | ? 1 : -1 |
| - | ]; |
| - | }; |
| - | |
| - | int catv_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| - | int catv_main(int argc UNUSED_PARAM, char **argv) |
| - | { |
| - | int retval = EXIT_SUCCESS; |
| - | int fd; |
| - | unsigned opts; |
| - | opts = getopt32(argv, "etv"); |
| - | argv += optind; |
| - | #if 0 /* These consts match, we can just pass "opts" to visible() */ |
| - | if (opts & CATV_OPT_e) |
| - | flags |= VISIBLE_ENDLINE; |
| - | if (opts & CATV_OPT_t) |
| - | flags |= VISIBLE_SHOW_TABS; |
| - | #endif |
| - | |
| - | /* Read from stdin if there's nothing else to do. */ |
| - | if (!argv[0]) |
| - | *--argv = (char*)"-"; |
| - | |
| - | #define read_buf bb_common_bufsiz1 |
| - | setup_common_bufsiz(); |
| - | do { |
| - | fd = open_or_warn_stdin(*argv); |
| - | if (fd < 0) { |
| - | retval = EXIT_FAILURE; |
| - | continue; |
| - | } |
| - | for (;;) { |
| - | int i, res; |
| - | |
| - | res = read(fd, read_buf, COMMON_BUFSIZE); |
| - | if (res < 0) |
| - | retval = EXIT_FAILURE; |
| - | if (res <= 0) |
| - | break; |
| - | for (i = 0; i < res; i++) { |
| - | unsigned char c = read_buf[i]; |
| - | if (opts & CATV_OPT_v) { |
| - | putchar(c); |
| - | } else { |
| - | char buf[sizeof("M-^c")]; |
| - | visible(c, buf, opts); |
| - | fputs(buf, stdout); |
| - | } |
| - | } |
| - | } |
| - | if (ENABLE_FEATURE_CLEAN_UP && fd) |
| - | close(fd); |
| - | } while (*++argv); |
| - | |
| - | fflush_stdout_and_exit(retval); |
| - | } |