diff options
Diffstat (limited to 'coreutils/cat.c')
-rw-r--r-- | coreutils/cat.c | 156 |
1 files changed, 134 insertions, 22 deletions
diff --git a/coreutils/cat.c b/coreutils/cat.c index 65978887e..4d9147f8a 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c | |||
@@ -12,56 +12,168 @@ | |||
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 | ||
20 | /* BB_AUDIT SUSv3 compliant */ | 27 | /* BB_AUDIT SUSv3 compliant */ |
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: "[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" |
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: ) | ||
42 | /* | ||
43 | Longopts not implemented yet: | ||
44 | --number-nonblank number nonempty output lines, overrides -n | ||
45 | --number number all output lines | ||
46 | --show-nonprinting use ^ and M- notation, except for LFD and TAB | ||
47 | --show-all equivalent to -vet | ||
48 | Not implemented yet: | ||
49 | -E, --show-ends display $ at end of each line (-e sans -v) | ||
50 | -T, --show-tabs display TAB characters as ^I (-t sans -v) | ||
51 | -s, --squeeze-blank suppress repeated empty output lines | ||
52 | */ | ||
27 | //usage: | 53 | //usage: |
28 | //usage:#define cat_example_usage | 54 | //usage:#define cat_example_usage |
29 | //usage: "$ cat /proc/uptime\n" | 55 | //usage: "$ cat /proc/uptime\n" |
30 | //usage: "110716.72 17.67" | 56 | //usage: "110716.72 17.67" |
31 | 57 | ||
32 | #include "libbb.h" | 58 | #include "libbb.h" |
59 | #include "common_bufsiz.h" | ||
33 | 60 | ||
34 | /* This is a NOFORK applet. Be very careful! */ | 61 | #if ENABLE_FEATURE_CATV |
35 | 62 | /* | |
36 | 63 | * cat -v implementation for busybox | |
37 | int bb_cat(char **argv) | 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) | ||
38 | { | 94 | { |
39 | int fd; | ||
40 | int retval = EXIT_SUCCESS; | 95 | int retval = EXIT_SUCCESS; |
96 | int fd; | ||
41 | 97 | ||
42 | if (!*argv) | 98 | BUILD_BUG_ON(CATV_OPT_e != VISIBLE_ENDLINE); |
43 | argv = (char**) &bb_argv_dash; | 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*)"-"; | ||
44 | 110 | ||
111 | #define read_buf bb_common_bufsiz1 | ||
112 | setup_common_bufsiz(); | ||
45 | do { | 113 | do { |
46 | fd = open_or_warn_stdin(*argv); | 114 | fd = open_or_warn_stdin(*argv); |
47 | if (fd >= 0) { | 115 | if (fd < 0) { |
48 | /* This is not a xfunc - never exits */ | 116 | retval = EXIT_FAILURE; |
49 | off_t r = bb_copyfd_eof(fd, STDOUT_FILENO); | 117 | continue; |
50 | if (fd != STDIN_FILENO) | ||
51 | close(fd); | ||
52 | if (r >= 0) | ||
53 | continue; | ||
54 | } | 118 | } |
55 | retval = EXIT_FAILURE; | 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); | ||
56 | } while (*++argv); | 136 | } while (*++argv); |
57 | 137 | ||
58 | return retval; | 138 | fflush_stdout_and_exit(retval); |
59 | } | 139 | } |
140 | #endif | ||
60 | 141 | ||
61 | int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 142 | int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
62 | int cat_main(int argc UNUSED_PARAM, char **argv) | 143 | int cat_main(int argc UNUSED_PARAM, char **argv) |
63 | { | 144 | { |
64 | getopt32(argv, "u"); | 145 | struct number_state ns; |
146 | unsigned opts; | ||
147 | |||
148 | IF_FEATURE_CATV(opt_complementary = "Aetv"; /* -A == -vet */) | ||
149 | /* -u is ignored ("unbuffered") */ | ||
150 | opts = getopt32(argv, IF_FEATURE_CATV("etvA")"nbu"); | ||
65 | argv += optind; | 151 | argv += optind; |
66 | return bb_cat(argv); | 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 */ | ||
164 | return bb_cat(argv); | ||
165 | |||
166 | if (!*argv) | ||
167 | *--argv = (char*)"-"; | ||
168 | ns.width = 6; | ||
169 | ns.start = 1; | ||
170 | ns.inc = 1; | ||
171 | ns.sep = "\t"; | ||
172 | ns.empty_str = "\n"; | ||
173 | ns.all = !(opts & CAT_OPT_b); /* -n without -b */ | ||
174 | ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */ | ||
175 | do { | ||
176 | print_numbered_lines(&ns, *argv); | ||
177 | } while (*++argv); | ||
178 | fflush_stdout_and_exit(EXIT_SUCCESS); | ||
67 | } | 179 | } |