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