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