head.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  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 "busybox.h"
  13. static const char head_opts[] =
  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. { NULL, 0 }
  25. };
  26. #endif
  27. static const char header_fmt_str[] = "\n==> %s <==\n";
  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 (argc > 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. #if !ENABLE_FEATURE_FANCY_HEAD
  73. count = xatoul(p);
  74. #else
  75. count = xatoul_sfx(p, head_suffixes);
  76. #endif
  77. break;
  78. default:
  79. bb_show_usage();
  80. }
  81. }
  82. argv += optind;
  83. if (!*argv) {
  84. *--argv = "-";
  85. }
  86. fmt = header_fmt_str + 1;
  87. #if ENABLE_FEATURE_FANCY_HEAD
  88. if (argc - optind <= header_threshhold) {
  89. header_threshhold = 0;
  90. }
  91. #else
  92. if (argc <= optind + 1) {
  93. fmt += 11;
  94. }
  95. /* Now define some things here to avoid #ifdefs in the code below.
  96. * These should optimize out of the if conditions below. */
  97. #define header_threshhold 1
  98. #define count_bytes 0
  99. #endif
  100. do {
  101. fp = fopen_or_warn_stdin(*argv);
  102. if (fp) {
  103. if (fp == stdin) {
  104. *argv = (char *) bb_msg_standard_input;
  105. }
  106. if (header_threshhold) {
  107. printf(fmt, *argv);
  108. }
  109. i = count;
  110. while (i && ((c = getc(fp)) != EOF)) {
  111. if (count_bytes || (c == '\n')) {
  112. --i;
  113. }
  114. putchar(c);
  115. }
  116. if (fclose_if_not_stdin(fp)) {
  117. bb_perror_msg("%s", *argv); /* Avoid multibyte problems. */
  118. retval = EXIT_FAILURE;
  119. }
  120. die_if_ferror_stdout();
  121. }
  122. fmt = header_fmt_str;
  123. } while (*++argv);
  124. fflush_stdout_and_exit(retval);
  125. }