blah, forgot to save last time to fix whitespacing
[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  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20  *
21  */
22
23 /* BB_AUDIT SUSv3 compliant */
24 /* BB_AUDIT GNU compatible -c, -q, and -v options in 'fancy' configuration. */
25 /* http://www.opengroup.org/onlinepubs/007904975/utilities/head.html */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <limits.h>
30 #include <ctype.h>
31 #include <unistd.h>
32 #include "busybox.h"
33
34 static const char head_opts[] =
35         "n:"
36 #ifdef CONFIG_FEATURE_FANCY_HEAD
37         "c:qv"
38 #endif
39         ;
40
41 static const char header_fmt_str[] = "\n==> %s <==\n";
42
43 int head_main(int argc, char **argv)
44 {
45         unsigned long count = 10;
46         unsigned long i;
47 #ifdef CONFIG_FEATURE_FANCY_HEAD
48         int count_bytes = 0;
49         int header_threshhold = 1;
50 #endif
51
52         FILE *fp;
53         const char *fmt;
54         char *p;
55         int opt;
56         int c;
57         int retval = EXIT_SUCCESS;
58
59         /* Allow legacy syntax of an initial numeric option without -n. */
60         if ((argc > 1) && (argv[1][0] == '-')
61                 /* && (isdigit)(argv[1][1]) */
62                 && (((unsigned int)(argv[1][1] - '0')) <= 9)
63         ) {
64                 --argc;
65                 ++argv;
66                 p = (*argv) + 1;
67                 goto GET_COUNT;
68         }
69
70         while ((opt = getopt(argc, argv, head_opts)) > 0) {
71                 switch(opt) {
72 #ifdef CONFIG_FEATURE_FANCY_HEAD
73                         case 'q':
74                                 header_threshhold = INT_MAX;
75                                 break;
76                         case 'v':
77                                 header_threshhold = -1;
78                                 break;
79                         case 'c':
80                                 count_bytes = 1;
81                                 /* fall through */
82 #endif
83                         case 'n':
84                                 p = optarg;
85                         GET_COUNT:
86                                 count = bb_xgetularg10(p);
87                                 break;
88                         default:
89                                 bb_show_usage();
90                 }
91         }
92
93         argv += optind;
94         if (!*argv) {
95                 *--argv = "-";
96         }
97
98         fmt = header_fmt_str + 1;
99 #ifdef CONFIG_FEATURE_FANCY_HEAD
100         if (argc - optind <= header_threshhold) {
101                 header_threshhold = 0;
102         }
103 #else
104         if (argc <= optind + 1) {
105                 fmt += 11;
106         }
107         /* Now define some things here to avoid #ifdefs in the code below.
108          * These should optimize out of the if conditions below. */
109 #define header_threshhold   1
110 #define count_bytes         0
111 #endif
112
113         do {
114                 if ((fp = bb_wfopen_input(*argv)) != NULL) {
115                         if (fp == stdin) {
116                                 *argv = (char *) bb_msg_standard_input;
117                         }
118                         if (header_threshhold) {
119                                 bb_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 (bb_fclose_nonstdin(fp)) {
129                                 bb_perror_msg("%s", *argv);     /* Avoid multibyte problems. */
130                                 retval = EXIT_FAILURE;
131                         }
132                         bb_xferror_stdout();
133                 }
134                 fmt = header_fmt_str;
135         } while (*++argv);
136
137         bb_fflush_stdout_and_exit(retval);
138 }