head.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  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. static const char head_opts[] ALIGN1 =
  14. "n:"
  15. #if ENABLE_FEATURE_FANCY_HEAD
  16. "c:qv"
  17. #endif
  18. ;
  19. static const struct suffix_mult head_suffixes[] = {
  20. { "b", 512 },
  21. { "k", 1024 },
  22. { "m", 1024*1024 },
  23. { "", 0 }
  24. };
  25. #define header_fmt_str "\n==> %s <==\n"
  26. int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  27. int head_main(int argc, char **argv)
  28. {
  29. unsigned long count = 10;
  30. unsigned long i;
  31. #if ENABLE_FEATURE_FANCY_HEAD
  32. int count_bytes = 0;
  33. int header_threshhold = 1;
  34. #endif
  35. FILE *fp;
  36. const char *fmt;
  37. char *p;
  38. int opt;
  39. int c;
  40. int retval = EXIT_SUCCESS;
  41. #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  42. /* Allow legacy syntax of an initial numeric option without -n. */
  43. if (argv[1] && argv[1][0] == '-'
  44. && isdigit(argv[1][1])
  45. ) {
  46. --argc;
  47. ++argv;
  48. p = (*argv) + 1;
  49. goto GET_COUNT;
  50. }
  51. #endif
  52. /* No size benefit in converting this to getopt32 */
  53. while ((opt = getopt(argc, argv, head_opts)) > 0) {
  54. switch (opt) {
  55. #if ENABLE_FEATURE_FANCY_HEAD
  56. case 'q':
  57. header_threshhold = INT_MAX;
  58. break;
  59. case 'v':
  60. header_threshhold = -1;
  61. break;
  62. case 'c':
  63. count_bytes = 1;
  64. /* fall through */
  65. #endif
  66. case 'n':
  67. p = optarg;
  68. #if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  69. GET_COUNT:
  70. #endif
  71. count = xatoul_sfx(p, head_suffixes);
  72. break;
  73. default:
  74. bb_show_usage();
  75. }
  76. }
  77. argc -= optind;
  78. argv += optind;
  79. if (!*argv)
  80. *--argv = (char*)"-";
  81. fmt = header_fmt_str + 1;
  82. #if ENABLE_FEATURE_FANCY_HEAD
  83. if (argc <= header_threshhold) {
  84. header_threshhold = 0;
  85. }
  86. #else
  87. if (argc <= 1) {
  88. fmt += 11; /* "" */
  89. }
  90. /* Now define some things here to avoid #ifdefs in the code below.
  91. * These should optimize out of the if conditions below. */
  92. #define header_threshhold 1
  93. #define count_bytes 0
  94. #endif
  95. do {
  96. fp = fopen_or_warn_stdin(*argv);
  97. if (fp) {
  98. if (fp == stdin) {
  99. *argv = (char *) bb_msg_standard_input;
  100. }
  101. if (header_threshhold) {
  102. printf(fmt, *argv);
  103. }
  104. i = count;
  105. while (i && ((c = getc(fp)) != EOF)) {
  106. if (count_bytes || (c == '\n')) {
  107. --i;
  108. }
  109. putchar(c);
  110. }
  111. if (fclose_if_not_stdin(fp)) {
  112. bb_simple_perror_msg(*argv);
  113. retval = EXIT_FAILURE;
  114. }
  115. die_if_ferror_stdout();
  116. } else {
  117. retval = EXIT_FAILURE;
  118. }
  119. fmt = header_fmt_str;
  120. } while (*++argv);
  121. fflush_stdout_and_exit(retval);
  122. }