cat.c 6.1 KB

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