1 /* vi: set sw=4 ts=4: */
3 * cat implementation for busybox
5 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
7 * Licensed under GPLv2, see file LICENSE in this source tree.
10 //config: bool "cat (5.8 kb)"
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.
16 //config:config FEATURE_CATN
17 //config: bool "Enable -n and -b options"
19 //config: depends on CAT
21 //config: -n numbers all output lines while -b numbers nonempty output lines.
23 //config:config FEATURE_CATV
24 //config: bool "cat -v[etA]"
26 //config: depends on CAT
28 //config: Display nonprinting characters as escape sequences
30 //applet:IF_CAT(APPLET(cat, BB_DIR_BIN, BB_SUID_DROP))
32 //kbuild:lib-$(CONFIG_CAT) += cat.o
34 /* BB_AUDIT SUSv3 compliant */
35 /* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
37 //usage:#if ENABLE_FEATURE_CATN || ENABLE_FEATURE_CATV
38 //usage:#define cat_trivial_usage
39 //usage: "[-" IF_FEATURE_CATN("nb") IF_FEATURE_CATV("vteA") "] [FILE]..."
41 //usage:#define cat_trivial_usage
44 //usage:#define cat_full_usage "\n\n"
45 //usage: "Print FILEs to stdout\n"
46 //usage: IF_FEATURE_CATN(
47 //usage: "\n -n Number output lines"
48 //usage: "\n -b Number nonempty lines"
50 //usage: IF_FEATURE_CATV(
51 //usage: "\n -v Show nonprinting characters as ^x or M-x"
52 //usage: "\n -t ...and tabs as ^I"
53 //usage: "\n -e ...and end lines with $"
54 //usage: "\n -A Same as -vte"
57 Longopts not implemented yet:
58 --number-nonblank number nonempty output lines, overrides -n
59 --number number all output lines
60 --show-nonprinting use ^ and M- notation, except for LFD and TAB
61 --show-all equivalent to -vet
63 -E, --show-ends display $ at end of each line (-e sans -v)
64 -T, --show-tabs display TAB characters as ^I (-t sans -v)
65 -s, --squeeze-blank suppress repeated empty output lines
68 //usage:#define cat_example_usage
69 //usage: "$ cat /proc/uptime\n"
70 //usage: "110716.72 17.67"
73 #include "common_bufsiz.h"
75 #if ENABLE_FEATURE_CATV
77 * cat -v implementation for busybox
79 * Copyright (C) 2006 Rob Landley <rob@landley.net>
81 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
83 /* Rob had "cat -v" implemented as a separate applet, catv.
84 * See "cat -v considered harmful" at
85 * http://cm.bell-labs.com/cm/cs/doc/84/kp.ps.gz
86 * From USENIX Summer Conference Proceedings, 1983
88 * The talk reviews reasons for UNIX's popularity and shows, using UCB cat
89 * as a primary example, how UNIX has grown fat. cat isn't for printing
90 * files with line numbers, it isn't for compressing multiple blank lines,
91 * it's not for looking at non-printing ASCII characters, it's for
92 * concatenating files.
93 * We are reminded that ls isn't the place for code to break a single column
94 * into multiple ones, and that mailnews shouldn't have its own more
95 * processing or joke encryption code.
98 * I agree with the argument. Unfortunately, this ship has sailed (1983...).
99 * There are dozens of Linux distros and each of them has "cat" which supports -v.
100 * It's unrealistic for us to "reeducate" them to use our, incompatible way
101 * to achieve "cat -v" effect. The actual effect would be "users pissed off
102 * by gratuitous incompatibility".
104 #define CAT_OPT_e (1<<0)
105 #define CAT_OPT_t (1<<1)
106 #define CAT_OPT_v (1<<2)
107 /* -A occupies bit (1<<3) */
108 #define CAT_OPT_n ((1<<4) * ENABLE_FEATURE_CATN)
109 #define CAT_OPT_b ((1<<5) * ENABLE_FEATURE_CATN)
110 static int catv(unsigned opts
, char **argv
)
112 int retval
= EXIT_SUCCESS
;
114 #if ENABLE_FEATURE_CATN
115 bool eol_seen
= (opts
& (CAT_OPT_n
|CAT_OPT_b
));
116 unsigned eol_char
= (eol_seen
? '\n' : 0x100);
117 unsigned skip_num_on
= (opts
& CAT_OPT_b
) ? '\n' : 0x100;
121 BUILD_BUG_ON(CAT_OPT_e
!= VISIBLE_ENDLINE
);
122 BUILD_BUG_ON(CAT_OPT_t
!= VISIBLE_SHOW_TABS
);
123 #if 0 /* These consts match, we can just pass "opts" to visible() */
124 if (opts
& CAT_OPT_e
)
125 flags
|= VISIBLE_ENDLINE
;
126 if (opts
& CAT_OPT_t
)
127 flags
|= VISIBLE_SHOW_TABS
;
130 #define read_buf bb_common_bufsiz1
131 setup_common_bufsiz();
133 fd
= open_or_warn_stdin(*argv
);
135 retval
= EXIT_FAILURE
;
141 res
= read(fd
, read_buf
, COMMON_BUFSIZE
);
143 retval
= EXIT_FAILURE
;
146 for (i
= 0; i
< res
; i
++) {
147 unsigned char c
= read_buf
[i
];
148 char buf
[sizeof("M-^c")];
149 #if ENABLE_FEATURE_CATN
150 if (eol_seen
&& c
!= skip_num_on
)
151 printf("%6u ", ++lineno
);
152 eol_seen
= (c
== eol_char
);
154 visible(c
, buf
, opts
);
158 if (ENABLE_FEATURE_CLEAN_UP
&& fd
)
162 fflush_stdout_and_exit(retval
);
168 int cat_main(int argc
, char **argv
) MAIN_EXTERNALLY_VISIBLE
;
169 int cat_main(int argc UNUSED_PARAM
, char **argv
)
171 #if ENABLE_FEATURE_CATV || ENABLE_FEATURE_CATN
176 getopt32(argv
, IF_FEATURE_CATV("^")
177 /* -u is ignored ("unbuffered") */
178 IF_FEATURE_CATV("etvA")IF_FEATURE_CATN("nb")"u"
179 IF_FEATURE_CATV("\0" "Aetv" /* -A == -vet */)
183 /* Read from stdin if there's nothing else to do. */
185 *--argv
= (char*)"-";
187 #if ENABLE_FEATURE_CATV
189 return catv(opts
, argv
);
193 #if ENABLE_FEATURE_CATN
194 # define CAT_OPT_n (1<<0)
195 # define CAT_OPT_b (1<<1)
196 if (opts
& (CAT_OPT_n
|CAT_OPT_b
)) { /* -n or -b */
197 struct number_state ns
;
205 ns
.all
= !(opts
& CAT_OPT_b
); /* -n without -b */
206 ns
.nonempty
= (opts
& CAT_OPT_b
); /* -b (with or without -n) */
207 exitcode
= EXIT_SUCCESS
;
209 exitcode
|= print_numbered_lines(&ns
, *argv
);
211 fflush_stdout_and_exit(exitcode
);