aboutsummaryrefslogtreecommitdiff
path: root/coreutils/cat.c
diff options
context:
space:
mode:
Diffstat (limited to 'coreutils/cat.c')
-rw-r--r--coreutils/cat.c156
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
37int 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)
93static 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
61int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 142int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
62int cat_main(int argc UNUSED_PARAM, char **argv) 143int 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}