diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-12 17:17:29 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-04-12 17:17:29 +0200 |
commit | e31ca2e9b206a05263708a3c10fbaec920920ba8 (patch) | |
tree | 060741e2cfcae4bea4fae834423a95fe001e8c67 /coreutils/cat.c | |
parent | d9eb40c18519d10aac3b3d008aa7e338ae830b72 (diff) | |
download | busybox-w32-e31ca2e9b206a05263708a3c10fbaec920920ba8.tar.gz busybox-w32-e31ca2e9b206a05263708a3c10fbaec920920ba8.tar.bz2 busybox-w32-e31ca2e9b206a05263708a3c10fbaec920920ba8.zip |
catv: convert this bbox-specific applet into "cat -v"
function old new delta
cat_main 150 320 +170
packed_usage 31511 31552 +41
applet_install_loc 190 189 -1
applet_main 1516 1512 -4
applet_names 2618 2613 -5
catv_main 227 - -227
------------------------------------------------------------------------------
(add/remove: 0/2 grow/shrink: 2/3 up/down: 211/-237) Total: -26 bytes
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'coreutils/cat.c')
-rw-r--r-- | coreutils/cat.c | 140 |
1 files changed, 122 insertions, 18 deletions
diff --git a/coreutils/cat.c b/coreutils/cat.c index 96970b19d..4d9147f8a 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c | |||
@@ -12,8 +12,15 @@ | |||
12 | //config: help | 12 | //config: help |
13 | //config: cat is used to concatenate files and print them to the standard | 13 | //config: cat is used to concatenate files and print them to the standard |
14 | //config: output. Enable this option if you wish to enable the 'cat' utility. | 14 | //config: output. Enable this option if you wish to enable the 'cat' utility. |
15 | //config: | ||
16 | //config:config FEATURE_CATV | ||
17 | //config: bool "cat -v[etA]" | ||
18 | //config: default y | ||
19 | //config: depends on CAT | ||
20 | //config: help | ||
21 | //config: Display nonprinting characters as escape sequences | ||
15 | 22 | ||
16 | //applet:IF_CAT(APPLET_NOFORK(cat, cat, BB_DIR_BIN, BB_SUID_DROP, cat)) | 23 | //applet:IF_CAT(APPLET(cat, BB_DIR_BIN, BB_SUID_DROP)) |
17 | 24 | ||
18 | //kbuild:lib-$(CONFIG_CAT) += cat.o | 25 | //kbuild:lib-$(CONFIG_CAT) += cat.o |
19 | 26 | ||
@@ -21,22 +28,27 @@ | |||
21 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */ | 28 | /* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */ |
22 | 29 | ||
23 | //usage:#define cat_trivial_usage | 30 | //usage:#define cat_trivial_usage |
24 | //usage: "[-n] [FILE]..." | 31 | //usage: "[-nb"IF_FEATURE_CATV("vteA")"] [FILE]..." |
25 | //usage:#define cat_full_usage "\n\n" | 32 | //usage:#define cat_full_usage "\n\n" |
26 | //usage: "Concatenate FILEs and print them to stdout" | 33 | //usage: "Print FILEs to stdout\n" |
27 | //usage: "\n -n Number output lines" | 34 | //usage: "\n -n Number output lines" |
35 | //usage: "\n -b Number nonempty lines" | ||
36 | //usage: IF_FEATURE_CATV( | ||
37 | //usage: "\n -v Show nonprinting characters as ^x or M-x" | ||
38 | //usage: "\n -t ...and tabs as ^I" | ||
39 | //usage: "\n -e ...and end lines with $" | ||
40 | //usage: "\n -A Same as -vte" | ||
41 | //usage: ) | ||
28 | /* | 42 | /* |
29 | Longopts not implemented yet: | 43 | Longopts not implemented yet: |
30 | --number-nonblank number nonempty output lines, overrides -n | 44 | --number-nonblank number nonempty output lines, overrides -n |
31 | --number number all output lines | 45 | --number number all output lines |
46 | --show-nonprinting use ^ and M- notation, except for LFD and TAB | ||
47 | --show-all equivalent to -vet | ||
32 | Not implemented yet: | 48 | Not implemented yet: |
33 | -A, --show-all equivalent to -vET | 49 | -E, --show-ends display $ at end of each line (-e sans -v) |
34 | -e equivalent to -vE | 50 | -T, --show-tabs display TAB characters as ^I (-t sans -v) |
35 | -E, --show-ends display $ at end of each line | ||
36 | -s, --squeeze-blank suppress repeated empty output lines | 51 | -s, --squeeze-blank suppress repeated empty output lines |
37 | -t equivalent to -vT | ||
38 | -T, --show-tabs display TAB characters as ^I | ||
39 | -v, --show-nonprinting use ^ and M- notation, except for LFD and TAB | ||
40 | */ | 52 | */ |
41 | //usage: | 53 | //usage: |
42 | //usage:#define cat_example_usage | 54 | //usage:#define cat_example_usage |
@@ -44,19 +56,111 @@ | |||
44 | //usage: "110716.72 17.67" | 56 | //usage: "110716.72 17.67" |
45 | 57 | ||
46 | #include "libbb.h" | 58 | #include "libbb.h" |
59 | #include "common_bufsiz.h" | ||
60 | |||
61 | #if ENABLE_FEATURE_CATV | ||
62 | /* | ||
63 | * cat -v implementation for busybox | ||
64 | * | ||
65 | * Copyright (C) 2006 Rob Landley <rob@landley.net> | ||
66 | * | ||
67 | * Licensed under GPLv2 or later, see file LICENSE in this source tree. | ||
68 | */ | ||
69 | /* Rob had "cat -v" implemented as a separate applet, catv. | ||
70 | * See "cat -v considered harmful" at | ||
71 | * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz | ||
72 | * From USENIX Summer Conference Proceedings, 1983 | ||
73 | * """ | ||
74 | * The talk reviews reasons for UNIX's popularity and shows, using UCB cat | ||
75 | * as a primary example, how UNIX has grown fat. cat isn't for printing | ||
76 | * files with line numbers, it isn't for compressing multiple blank lines, | ||
77 | * it's not for looking at non-printing ASCII characters, it's for | ||
78 | * concatenating files. | ||
79 | * We are reminded that ls isn't the place for code to break a single column | ||
80 | * into multiple ones, and that mailnews shouldn't have its own more | ||
81 | * processing or joke encryption code. | ||
82 | * """ | ||
83 | * | ||
84 | * I agree with the argument. Unfortunately, this ship has sailed (1983...). | ||
85 | * There are dozens of Linux distros and each of them has "cat" which supports -v. | ||
86 | * It's unrealistic for us to "reeducate" them to use our, incompatible way | ||
87 | * to achieve "cat -v" effect. The actuall effect would be "users pissed off | ||
88 | * by gratuitous incompatibility". | ||
89 | */ | ||
90 | #define CATV_OPT_e (1<<0) | ||
91 | #define CATV_OPT_t (1<<1) | ||
92 | #define CATV_OPT_v (1<<2) | ||
93 | static int catv(unsigned opts, char **argv) | ||
94 | { | ||
95 | int retval = EXIT_SUCCESS; | ||
96 | int fd; | ||
47 | 97 | ||
48 | /* This is a NOFORK applet. Be very careful! */ | 98 | BUILD_BUG_ON(CATV_OPT_e != VISIBLE_ENDLINE); |
99 | BUILD_BUG_ON(CATV_OPT_t != VISIBLE_SHOW_TABS); | ||
100 | #if 0 /* These consts match, we can just pass "opts" to visible() */ | ||
101 | if (opts & CATV_OPT_e) | ||
102 | flags |= VISIBLE_ENDLINE; | ||
103 | if (opts & CATV_OPT_t) | ||
104 | flags |= VISIBLE_SHOW_TABS; | ||
105 | #endif | ||
106 | |||
107 | /* Read from stdin if there's nothing else to do. */ | ||
108 | if (!argv[0]) | ||
109 | *--argv = (char*)"-"; | ||
110 | |||
111 | #define read_buf bb_common_bufsiz1 | ||
112 | setup_common_bufsiz(); | ||
113 | do { | ||
114 | fd = open_or_warn_stdin(*argv); | ||
115 | if (fd < 0) { | ||
116 | retval = EXIT_FAILURE; | ||
117 | continue; | ||
118 | } | ||
119 | for (;;) { | ||
120 | int i, res; | ||
121 | |||
122 | res = read(fd, read_buf, COMMON_BUFSIZE); | ||
123 | if (res < 0) | ||
124 | retval = EXIT_FAILURE; | ||
125 | if (res <= 0) | ||
126 | break; | ||
127 | for (i = 0; i < res; i++) { | ||
128 | unsigned char c = read_buf[i]; | ||
129 | char buf[sizeof("M-^c")]; | ||
130 | visible(c, buf, opts); | ||
131 | fputs(buf, stdout); | ||
132 | } | ||
133 | } | ||
134 | if (ENABLE_FEATURE_CLEAN_UP && fd) | ||
135 | close(fd); | ||
136 | } while (*++argv); | ||
137 | |||
138 | fflush_stdout_and_exit(retval); | ||
139 | } | ||
140 | #endif | ||
49 | 141 | ||
50 | int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 142 | int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
51 | int cat_main(int argc UNUSED_PARAM, char **argv) | 143 | int cat_main(int argc UNUSED_PARAM, char **argv) |
52 | { | 144 | { |
53 | struct number_state ns; | 145 | struct number_state ns; |
54 | unsigned opt; | 146 | unsigned opts; |
55 | 147 | ||
56 | /* -u is ignored */ | 148 | IF_FEATURE_CATV(opt_complementary = "Aetv"; /* -A == -vet */) |
57 | opt = getopt32(argv, "nbu"); | 149 | /* -u is ignored ("unbuffered") */ |
150 | opts = getopt32(argv, IF_FEATURE_CATV("etvA")"nbu"); | ||
58 | argv += optind; | 151 | argv += optind; |
59 | if (!(opt & 3)) /* no -n or -b */ | 152 | |
153 | #if ENABLE_FEATURE_CATV | ||
154 | if (opts & 7) | ||
155 | return catv(opts, argv); | ||
156 | //BUG: -v,-e,-t,-A ignore -nb | ||
157 | opts >>= 4; | ||
158 | #endif | ||
159 | |||
160 | #define CAT_OPT_n (1<<0) | ||
161 | #define CAT_OPT_b (1<<1) | ||
162 | #define CAT_OPT_u (1<<2) | ||
163 | if (!(opts & (CAT_OPT_n|CAT_OPT_b))) /* no -n or -b */ | ||
60 | return bb_cat(argv); | 164 | return bb_cat(argv); |
61 | 165 | ||
62 | if (!*argv) | 166 | if (!*argv) |
@@ -66,8 +170,8 @@ int cat_main(int argc UNUSED_PARAM, char **argv) | |||
66 | ns.inc = 1; | 170 | ns.inc = 1; |
67 | ns.sep = "\t"; | 171 | ns.sep = "\t"; |
68 | ns.empty_str = "\n"; | 172 | ns.empty_str = "\n"; |
69 | ns.all = !(opt & 2); /* -n without -b */ | 173 | ns.all = !(opts & CAT_OPT_b); /* -n without -b */ |
70 | ns.nonempty = (opt & 2); /* -b (with or without -n) */ | 174 | ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */ |
71 | do { | 175 | do { |
72 | print_numbered_lines(&ns, *argv); | 176 | print_numbered_lines(&ns, *argv); |
73 | } while (*++argv); | 177 | } while (*++argv); |