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 source tree.
   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
  16/* This is a NOEXEC applet. Be very careful! */
  17
  18static const char head_opts[] ALIGN1 =
  19        "n:"
  20#if ENABLE_FEATURE_FANCY_HEAD
  21        "c:qv"
  22#endif
  23        ;
  24
  25static const struct suffix_mult head_suffixes[] = {
  26        { "b", 512 },
  27        { "k", 1024 },
  28        { "m", 1024*1024 },
  29        { "", 0 }
  30};
  31
  32#define header_fmt_str "\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                        count = xatoul_sfx(p, head_suffixes);
  82                        break;
  83                default:
  84                        bb_show_usage();
  85                }
  86        }
  87
  88        argc -= optind;
  89        argv += optind;
  90        if (!*argv)
  91                *--argv = (char*)"-";
  92
  93        fmt = header_fmt_str + 1;
  94#if ENABLE_FEATURE_FANCY_HEAD
  95        if (argc <= header_threshhold) {
  96                header_threshhold = 0;
  97        }
  98#else
  99        if (argc <= 1) {
 100                fmt += 11; /* "" */
 101        }
 102        /* Now define some things here to avoid #ifdefs in the code below.
 103         * These should optimize out of the if conditions below. */
 104#define header_threshhold   1
 105#define count_bytes         0
 106#endif
 107
 108        do {
 109                fp = fopen_or_warn_stdin(*argv);
 110                if (fp) {
 111                        if (fp == stdin) {
 112                                *argv = (char *) bb_msg_standard_input;
 113                        }
 114                        if (header_threshhold) {
 115                                printf(fmt, *argv);
 116                        }
 117                        i = count;
 118                        while (i && ((c = getc(fp)) != EOF)) {
 119                                if (count_bytes || (c == '\n')) {
 120                                        --i;
 121                                }
 122                                putchar(c);
 123                        }
 124                        if (fclose_if_not_stdin(fp)) {
 125                                bb_simple_perror_msg(*argv);
 126                                retval = EXIT_FAILURE;
 127                        }
 128                        die_if_ferror_stdout();
 129                } else {
 130                        retval = EXIT_FAILURE;
 131                }
 132                fmt = header_fmt_str;
 133        } while (*++argv);
 134
 135        fflush_stdout_and_exit(retval);
 136}
 137