busybox/coreutils/head.c
<<
>>
Prefs
   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) MAIN_EXTERNALLY_VISIBLE;
  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        FILE *fp;
  44        const char *fmt;
  45        char *p;
  46        int opt;
  47        int c;
  48        int retval = EXIT_SUCCESS;
  49
  50#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  51        /* Allow legacy syntax of an initial numeric option without -n. */
  52        if (argv[1] && argv[1][0] == '-'
  53         && isdigit(argv[1][1])
  54        ) {
  55                --argc;
  56                ++argv;
  57                p = (*argv) + 1;
  58                goto GET_COUNT;
  59        }
  60#endif
  61
  62        /* No size benefit in converting this to getopt32 */
  63        while ((opt = getopt(argc, argv, head_opts)) > 0) {
  64                switch (opt) {
  65#if ENABLE_FEATURE_FANCY_HEAD
  66                case 'q':
  67                        header_threshhold = INT_MAX;
  68                        break;
  69                case 'v':
  70                        header_threshhold = -1;
  71                        break;
  72                case 'c':
  73                        count_bytes = 1;
  74                        /* fall through */
  75#endif
  76                case 'n':
  77                        p = optarg;
  78#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  79 GET_COUNT:
  80#endif
  81#if !ENABLE_FEATURE_FANCY_HEAD
  82                        count = xatoul(p);
  83#else
  84                        count = xatoul_sfx(p, head_suffixes);
  85#endif
  86                        break;
  87                default:
  88                        bb_show_usage();
  89                }
  90        }
  91
  92        argc -= optind;
  93        argv += optind;
  94        if (!*argv)
  95                *--argv = (char*)"-";
  96
  97        fmt = header_fmt_str + 1;
  98#if ENABLE_FEATURE_FANCY_HEAD
  99        if (argc <= header_threshhold) {
 100                header_threshhold = 0;
 101        }
 102#else
 103        if (argc <= 1) {
 104                fmt += 11; /* "" */
 105        }
 106        /* Now define some things here to avoid #ifdefs in the code below.
 107         * These should optimize out of the if conditions below. */
 108#define header_threshhold   1
 109#define count_bytes         0
 110#endif
 111
 112        do {
 113                fp = fopen_or_warn_stdin(*argv);
 114                if (fp) {
 115                        if (fp == stdin) {
 116                                *argv = (char *) bb_msg_standard_input;
 117                        }
 118                        if (header_threshhold) {
 119                                printf(fmt, *argv);
 120                        }
 121                        i = count;
 122                        while (i && ((c = getc(fp)) != EOF)) {
 123                                if (count_bytes || (c == '\n')) {
 124                                        --i;
 125                                }
 126                                putchar(c);
 127                        }
 128                        if (fclose_if_not_stdin(fp)) {
 129                                bb_simple_perror_msg(*argv);
 130                                retval = EXIT_FAILURE;
 131                        }
 132                        die_if_ferror_stdout();
 133                } else {
 134                        retval = EXIT_FAILURE;
 135                }
 136                fmt = header_fmt_str;
 137        } while (*++argv);
 138
 139        fflush_stdout_and_exit(retval);
 140}
 141