head.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * head implementation for busybox
  4. *
  5. * Copyright (C) 2003 Manuel Novoa III <mjn3@codepoet.org>
  6. *
  7. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  8. */
  9. /* BB_AUDIT SUSv3 compliant */
  10. /* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
  11. /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
  12. #include "libbb.h"
  13. /* This is a NOEXEC applet. Be very careful! */
  14. static const char head_opts[] ALIGN1 =
  15. "n:"
  16. #if ENABLE_FEATURE_FANCY_HEAD
  17. "c:qv"
  18. #endif
  19. ;
  20. static const struct suffix_mult head_suffixes[] = {
  21. { "b", 512 },
  22. { "k", 1024 },
  23. { "m", 1024*1024 },
  24. { "", 0 }
  25. };
  26. #define header_fmt_str "\n==> %s <==\n"
  27. int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  28. int head_main(int argc, char **argv)
  29. {
  30. unsigned long count = 10;
  31. unsigned long i;
  32. #if ENABLE_FEATURE_FANCY_HEAD
  33. int count_bytes = 0;
  34. int header_threshhold = 1;
  35. #endif
  36. FILE *fp;
  37. const char *fmt;
  38. char *p;
  39. int opt;
  40. int c;
  41. int retval = EXIT_SUCCESS;
  42. #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  43. /* Allow legacy syntax of an initial numeric option without -n. */
  44. if (argv[1] && argv[1][0] == '-'
  45. && isdigit(argv[1][1])
  46. ) {
  47. --argc;
  48. ++argv;
  49. p = (*argv) + 1;
  50. goto GET_COUNT;
  51. }
  52. #endif
  53. /* No size benefit in converting this to getopt32 */
  54. while ((opt = getopt(argc, argv, head_opts)) > 0) {
  55. switch (opt) {
  56. #if ENABLE_FEATURE_FANCY_HEAD
  57. case 'q':
  58. header_threshhold = INT_MAX;
  59. break;
  60. case 'v':
  61. header_threshhold = -1;
  62. break;
  63. case 'c':
  64. count_bytes = 1;
  65. /* fall through */
  66. #endif
  67. case 'n':
  68. p = optarg;
  69. #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  70. GET_COUNT:
  71. #endif
  72. count = xatoul_sfx(p, head_suffixes);
  73. break;
  74. default:
  75. bb_show_usage();
  76. }
  77. }
  78. argc -= optind;
  79. argv += optind;
  80. if (!*argv)
  81. *--argv = (char*)"-";
  82. fmt = header_fmt_str + 1;
  83. #if ENABLE_FEATURE_FANCY_HEAD
  84. if (argc <= header_threshhold) {
  85. header_threshhold = 0;
  86. }
  87. #else
  88. if (argc <= 1) {
  89. fmt += 11; /* "" */
  90. }
  91. /* Now define some things here to avoid #ifdefs in the code below.
  92. * These should optimize out of the if conditions below. */
  93. #define header_threshhold 1
  94. #define count_bytes 0
  95. #endif
  96. do {
  97. fp = fopen_or_warn_stdin(*argv);
  98. if (fp) {
  99. if (fp == stdin) {
  100. *argv = (char *) bb_msg_standard_input;
  101. }
  102. if (header_threshhold) {
  103. printf(fmt, *argv);
  104. }
  105. i = count;
  106. while (i && ((c = getc(fp)) != EOF)) {
  107. if (count_bytes || (c == '\n')) {
  108. --i;
  109. }
  110. putchar(c);
  111. }
  112. if (fclose_if_not_stdin(fp)) {
  113. bb_simple_perror_msg(*argv);
  114. retval = EXIT_FAILURE;
  115. }
  116. die_if_ferror_stdout();
  117. } else {
  118. retval = EXIT_FAILURE;
  119. }
  120. fmt = header_fmt_str;
  121. } while (*++argv);
  122. fflush_stdout_and_exit(retval);
  123. }