cat.c 5.1 KB

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