head.c 2.8 KB

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