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//usage:#define head_trivial_usage
  15//usage:       "[OPTIONS] [FILE]..."
  16//usage:#define head_full_usage "\n\n"
  17//usage:       "Print first 10 lines of each FILE (or stdin) to stdout.\n"
  18//usage:       "With more than one FILE, precede each with a filename header.\n"
  19//usage:     "\n        -n N[kbm]       Print first N lines"
  20//usage:        IF_FEATURE_FANCY_HEAD(
  21//usage:     "\n        -c N[kbm]       Print first N bytes"
  22//usage:     "\n        -q              Never print headers"
  23//usage:     "\n        -v              Always print headers"
  24//usage:        )
  25//usage:     "\n"
  26//usage:     "\nN may be suffixed by k (x1024), b (x512), or m (x1024^2)."
  27//usage:
  28//usage:#define head_example_usage
  29//usage:       "$ head -n 2 /etc/passwd\n"
  30//usage:       "root:x:0:0:root:/root:/bin/bash\n"
  31//usage:       "daemon:x:1:1:daemon:/usr/sbin:/bin/sh\n"
  32
  33#include "libbb.h"
  34
  35/* This is a NOEXEC applet. Be very careful! */
  36
  37static const char head_opts[] ALIGN1 =
  38        "n:"
  39#if ENABLE_FEATURE_FANCY_HEAD
  40        "c:qv"
  41#endif
  42        ;
  43
  44static const struct suffix_mult head_suffixes[] = {
  45        { "b", 512 },
  46        { "k", 1024 },
  47        { "m", 1024*1024 },
  48        { "", 0 }
  49};
  50
  51#define header_fmt_str "\n==> %s <==\n"
  52
  53int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  54int head_main(int argc, char **argv)
  55{
  56        unsigned long count = 10;
  57        unsigned long i;
  58#if ENABLE_FEATURE_FANCY_HEAD
  59        int count_bytes = 0;
  60        int header_threshhold = 1;
  61#endif
  62        FILE *fp;
  63        const char *fmt;
  64        char *p;
  65        int opt;
  66        int c;
  67        int retval = EXIT_SUCCESS;
  68
  69#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  70        /* Allow legacy syntax of an initial numeric option without -n. */
  71        if (argv[1] && argv[1][0] == '-'
  72         && isdigit(argv[1][1])
  73        ) {
  74                --argc;
  75                ++argv;
  76                p = (*argv) + 1;
  77                goto GET_COUNT;
  78        }
  79#endif
  80
  81        /* No size benefit in converting this to getopt32 */
  82        while ((opt = getopt(argc, argv, head_opts)) > 0) {
  83                switch (opt) {
  84#if ENABLE_FEATURE_FANCY_HEAD
  85                case 'q':
  86                        header_threshhold = INT_MAX;
  87                        break;
  88                case 'v':
  89                        header_threshhold = -1;
  90                        break;
  91                case 'c':
  92                        count_bytes = 1;
  93                        /* fall through */
  94#endif
  95                case 'n':
  96                        p = optarg;
  97#if ENABLE_INCLUDE_SUSv2 || ENABLE_FEATURE_FANCY_HEAD
  98 GET_COUNT:
  99#endif
 100                        count = xatoul_sfx(p, head_suffixes);
 101                        break;
 102                default:
 103                        bb_show_usage();
 104                }
 105        }
 106
 107        argc -= optind;
 108        argv += optind;
 109        if (!*argv)
 110                *--argv = (char*)"-";
 111
 112        fmt = header_fmt_str + 1;
 113#if ENABLE_FEATURE_FANCY_HEAD
 114        if (argc <= header_threshhold) {
 115                header_threshhold = 0;
 116        }
 117#else
 118        if (argc <= 1) {
 119                fmt += 11; /* "" */
 120        }
 121        /* Now define some things here to avoid #ifdefs in the code below.
 122         * These should optimize out of the if conditions below. */
 123#define header_threshhold   1
 124#define count_bytes         0
 125#endif
 126
 127        do {
 128                fp = fopen_or_warn_stdin(*argv);
 129                if (fp) {
 130                        if (fp == stdin) {
 131                                *argv = (char *) bb_msg_standard_input;
 132                        }
 133                        if (header_threshhold) {
 134                                printf(fmt, *argv);
 135                        }
 136                        i = count;
 137                        while (i && ((c = getc(fp)) != EOF)) {
 138                                if (count_bytes || (c == '\n')) {
 139                                        --i;
 140                                }
 141                                putchar(c);
 142                        }
 143                        if (fclose_if_not_stdin(fp)) {
 144                                bb_simple_perror_msg(*argv);
 145                                retval = EXIT_FAILURE;
 146                        }
 147                        die_if_ferror_stdout();
 148                } else {
 149                        retval = EXIT_FAILURE;
 150                }
 151                fmt = header_fmt_str;
 152        } while (*++argv);
 153
 154        fflush_stdout_and_exit(retval);
 155}
 156