blob: 4d9147f8abcd2f6071b348a1896eadfe43466272 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersencc8ed391999-10-05 16:24:54 +00002/*
Manuel Novoa III cad53642003-03-19 09:13:01 +00003 * cat implementation for busybox
Eric Andersencc8ed391999-10-05 16:24:54 +00004 *
Manuel Novoa III cad53642003-03-19 09:13:01 +00005 * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
Eric Andersencc8ed391999-10-05 16:24:54 +00006 *
Denys Vlasenko0ef64bd2010-08-16 20:14:46 +02007 * Licensed under GPLv2, see file LICENSE in this source tree.
Eric Andersencc8ed391999-10-05 16:24:54 +00008 */
Denys Vlasenkoe4070cb2010-06-04 19:59:49 +02009//config:config CAT
10//config: bool "cat"
Denys Vlasenko2f32bf82010-06-06 04:14:28 +020011//config: default y
Denys Vlasenkoe4070cb2010-06-04 19:59:49 +020012//config: help
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.
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020015//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
Denys Vlasenkoe4070cb2010-06-04 19:59:49 +020022
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020023//applet:IF_CAT(APPLET(cat, BB_DIR_BIN, BB_SUID_DROP))
Denys Vlasenkoaf3f4202016-11-23 14:46:56 +010024
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020025//kbuild:lib-$(CONFIG_CAT) += cat.o
Denys Vlasenkoaf3f4202016-11-23 14:46:56 +010026
27/* BB_AUDIT SUSv3 compliant */
28/* http://www.opengroup.org/onlinepubs/007904975/utilities/cat.html */
29
Pere Orga34425382011-03-31 14:43:25 +020030//usage:#define cat_trivial_usage
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020031//usage: "[-nb"IF_FEATURE_CATV("vteA")"] [FILE]..."
Pere Orga34425382011-03-31 14:43:25 +020032//usage:#define cat_full_usage "\n\n"
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020033//usage: "Print FILEs to stdout\n"
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020034//usage: "\n -n Number output lines"
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020035//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: )
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020042/*
43 Longopts not implemented yet:
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020044 --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
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020048 Not implemented yet:
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020049 -E, --show-ends display $ at end of each line (-e sans -v)
50 -T, --show-tabs display TAB characters as ^I (-t sans -v)
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020051 -s, --squeeze-blank suppress repeated empty output lines
Denys Vlasenkod88f94a2017-04-05 18:17:17 +020052*/
Pere Orga34425382011-03-31 14:43:25 +020053//usage:
54//usage:#define cat_example_usage
55//usage: "$ cat /proc/uptime\n"
56//usage: "110716.72 17.67"
57
Denis Vlasenkob6adbf12007-05-26 19:00:18 +000058#include "libbb.h"
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020059#include "common_bufsiz.h"
Eric Andersencc8ed391999-10-05 16:24:54 +000060
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +020061#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)
93static int catv(unsigned opts, char **argv)
94{
95 int retval = EXIT_SUCCESS;
96 int fd;
97
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
Denis Vlasenko99912ca2007-04-10 15:43:37 +0000141
Denis Vlasenko9b49a5e2007-10-11 10:05:36 +0000142int cat_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
Denis Vlasenkoa60f84e2008-07-05 09:18:54 +0000143int cat_main(int argc UNUSED_PARAM, char **argv)
Denis Vlasenkobf66fbc2006-12-21 13:23:14 +0000144{
Denys Vlasenkod88f94a2017-04-05 18:17:17 +0200145 struct number_state ns;
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +0200146 unsigned opts;
Denys Vlasenkod88f94a2017-04-05 18:17:17 +0200147
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +0200148 IF_FEATURE_CATV(opt_complementary = "Aetv"; /* -A == -vet */)
149 /* -u is ignored ("unbuffered") */
150 opts = getopt32(argv, IF_FEATURE_CATV("etvA")"nbu");
Denis Vlasenkobf66fbc2006-12-21 13:23:14 +0000151 argv += optind;
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +0200152
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 */
Denys Vlasenkod88f94a2017-04-05 18:17:17 +0200164 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";
Denys Vlasenkoe31ca2e2017-04-12 17:17:29 +0200173 ns.all = !(opts & CAT_OPT_b); /* -n without -b */
174 ns.nonempty = (opts & CAT_OPT_b); /* -b (with or without -n) */
Denys Vlasenkod88f94a2017-04-05 18:17:17 +0200175 do {
176 print_numbered_lines(&ns, *argv);
177 } while (*++argv);
178 fflush_stdout_and_exit(EXIT_SUCCESS);
Denis Vlasenkobf66fbc2006-12-21 13:23:14 +0000179}