ls: fix bits for -T, -w and --color; make -n imply -l; fix comments
[oweals/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 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
18 static const char head_opts[] ALIGN1 =
19         "n:"
20 #if ENABLE_FEATURE_FANCY_HEAD
21         "c:qv"
22 #endif
23         ;
24
25 static 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
34 int head_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
35 int 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 }