(add_tabstop): Give correct size when reallocating tab_list buffer.
[platform/upstream/coreutils.git] / src / head.c
1 /* head -- output first part of file(s)
2    Copyright (C) 1989, 1990, 1991, 1995 Free Software Foundation, Inc.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software
16    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
17
18 /* Options: (see usage)
19    Reads from standard input if no files are given or when a filename of
20    ``-'' is encountered.
21    By default, filename headers are printed only if more than one file
22    is given.
23    By default, prints the first 10 lines (head -n 10).
24
25    David MacKenzie <djm@gnu.ai.mit.edu> */
26
27 #include <config.h>
28
29 #include <stdio.h>
30 #include <getopt.h>
31 #include <sys/types.h>
32 #include "system.h"
33 #include "version.h"
34 #include "error.h"
35
36 /* Number of lines/chars/blocks to head. */
37 #define DEFAULT_NUMBER 10
38
39 /* Size of atomic reads. */
40 #define BUFSIZE (512 * 8)
41
42 /* Number of bytes per item we are printing.
43    If 0, head in lines. */
44 static int unit_size;
45
46 /* If nonzero, print filename headers. */
47 static int print_headers;
48
49 /* When to print the filename banners. */
50 enum header_mode
51 {
52   multiple_files, always, never
53 };
54
55 int safe_read ();
56
57 static int head ();
58 static int head_bytes ();
59 static int head_file ();
60 static int head_lines ();
61 static long atou ();
62 static void parse_unit ();
63 static void usage ();
64 static void write_header ();
65
66 /* The name this program was run with. */
67 char *program_name;
68
69 /* Have we ever read standard input?  */
70 static int have_read_stdin;
71
72 /* If non-zero, display usage information and exit.  */
73 static int show_help;
74
75 /* If non-zero, print the version on standard output then exit.  */
76 static int show_version;
77
78 static struct option const long_options[] =
79 {
80   {"bytes", required_argument, NULL, 'c'},
81   {"lines", required_argument, NULL, 'n'},
82   {"quiet", no_argument, NULL, 'q'},
83   {"silent", no_argument, NULL, 'q'},
84   {"verbose", no_argument, NULL, 'v'},
85   {"help", no_argument, &show_help, 1},
86   {"version", no_argument, &show_version, 1},
87   {NULL, 0, NULL, 0}
88 };
89
90 void
91 main (argc, argv)
92      int argc;
93      char **argv;
94 {
95   enum header_mode header_mode = multiple_files;
96   int exit_status = 0;
97   long number = -1;             /* Number of items to print (-1 if undef.). */
98   int c;                        /* Option character. */
99
100   program_name = argv[0];
101   have_read_stdin = 0;
102   unit_size = 0;
103   print_headers = 0;
104
105   if (argc > 1 && argv[1][0] == '-' && ISDIGIT (argv[1][1]))
106     {
107       /* Old option syntax; a dash, one or more digits, and one or
108          more option letters.  Move past the number. */
109       for (number = 0, ++argv[1]; ISDIGIT (*argv[1]); ++argv[1])
110         number = number * 10 + *argv[1] - '0';
111       /* Parse any appended option letters. */
112       while (*argv[1])
113         {
114           switch (*argv[1])
115             {
116             case 'b':
117               unit_size = 512;
118               break;
119
120             case 'c':
121               unit_size = 1;
122               break;
123
124             case 'k':
125               unit_size = 1024;
126               break;
127
128             case 'l':
129               unit_size = 0;
130               break;
131
132             case 'm':
133               unit_size = 1048576;
134               break;
135
136             case 'q':
137               header_mode = never;
138               break;
139
140             case 'v':
141               header_mode = always;
142               break;
143
144             default:
145               error (0, 0, "unrecognized option `-%c'", *argv[1]);
146               usage (1);
147             }
148           ++argv[1];
149         }
150       /* Make the options we just parsed invisible to getopt. */
151       argv[1] = argv[0];
152       argv++;
153       argc--;
154     }
155
156   while ((c = getopt_long (argc, argv, "c:n:qv", long_options, (int *) 0))
157          != EOF)
158     {
159       switch (c)
160         {
161         case 0:
162           break;
163
164         case 'c':
165           unit_size = 1;
166           parse_unit (optarg);
167           goto getnum;
168         case 'n':
169           unit_size = 0;
170         getnum:
171           number = atou (optarg);
172           if (number == -1)
173             error (1, 0, "invalid number `%s'", optarg);
174           break;
175
176         case 'q':
177           header_mode = never;
178           break;
179
180         case 'v':
181           header_mode = always;
182           break;
183
184         default:
185           usage (1);
186         }
187     }
188
189   if (show_version)
190     {
191       printf ("head - %s\n", version_string);
192       exit (0);
193     }
194
195   if (show_help)
196     usage (0);
197
198   if (number == -1)
199     number = DEFAULT_NUMBER;
200
201   if (unit_size > 1)
202     number *= unit_size;
203
204   if (header_mode == always
205       || (header_mode == multiple_files && optind < argc - 1))
206     print_headers = 1;
207
208   if (optind == argc)
209     exit_status |= head_file ("-", number);
210
211   for (; optind < argc; ++optind)
212     exit_status |= head_file (argv[optind], number);
213
214   if (have_read_stdin && close (0) < 0)
215     error (1, errno, "-");
216   if (fclose (stdout) == EOF)
217     error (1, errno, "write error");
218
219   exit (exit_status);
220 }
221
222 static int
223 head_file (filename, number)
224      char *filename;
225      long number;
226 {
227   int fd;
228
229   if (!strcmp (filename, "-"))
230     {
231       have_read_stdin = 1;
232       filename = "standard input";
233       if (print_headers)
234         write_header (filename);
235       return head (filename, 0, number);
236     }
237   else
238     {
239       fd = open (filename, O_RDONLY);
240       if (fd >= 0)
241         {
242           int errors;
243
244           if (print_headers)
245             write_header (filename);
246           errors = head (filename, fd, number);
247           if (close (fd) == 0)
248             return errors;
249         }
250       error (0, errno, "%s", filename);
251       return 1;
252     }
253 }
254
255 static void
256 write_header (filename)
257      char *filename;
258 {
259   static int first_file = 1;
260
261   printf ("%s==> %s <==\n", (first_file ? "" : "\n"), filename);
262   first_file = 0;
263 }
264
265 static int
266 head (filename, fd, number)
267      char *filename;
268      int fd;
269      long number;
270 {
271   if (unit_size)
272     return head_bytes (filename, fd, number);
273   else
274     return head_lines (filename, fd, number);
275 }
276
277 static int
278 head_bytes (filename, fd, bytes_to_write)
279      char *filename;
280      int fd;
281      long bytes_to_write;
282 {
283   char buffer[BUFSIZE];
284   int bytes_read;
285
286   while (bytes_to_write)
287     {
288       bytes_read = safe_read (fd, buffer, BUFSIZE);
289       if (bytes_read < 0)
290         {
291           error (0, errno, "%s", filename);
292           return 1;
293         }
294       if (bytes_read == 0)
295         break;
296       if (bytes_read > bytes_to_write)
297         bytes_read = bytes_to_write;
298       if (fwrite (buffer, 1, bytes_read, stdout) == 0)
299         error (1, errno, "write error");
300       bytes_to_write -= bytes_read;
301     }
302   return 0;
303 }
304
305 static int
306 head_lines (filename, fd, lines_to_write)
307      char *filename;
308      int fd;
309      long lines_to_write;
310 {
311   char buffer[BUFSIZE];
312   int bytes_read;
313   int bytes_to_write;
314
315   while (lines_to_write)
316     {
317       bytes_read = safe_read (fd, buffer, BUFSIZE);
318       if (bytes_read < 0)
319         {
320           error (0, errno, "%s", filename);
321           return 1;
322         }
323       if (bytes_read == 0)
324         break;
325       bytes_to_write = 0;
326       while (bytes_to_write < bytes_read)
327         if (buffer[bytes_to_write++] == '\n' && --lines_to_write == 0)
328           break;
329       if (fwrite (buffer, 1, bytes_to_write, stdout) == 0)
330         error (1, errno, "write error");
331     }
332   return 0;
333 }
334
335 static void
336 parse_unit (str)
337      char *str;
338 {
339   int arglen = strlen (str);
340
341   if (arglen == 0)
342     return;
343
344   switch (str[arglen - 1])
345     {
346     case 'b':
347       unit_size = 512;
348       str[arglen - 1] = '\0';
349       break;
350     case 'k':
351       unit_size = 1024;
352       str[arglen - 1] = '\0';
353       break;
354     case 'm':
355       unit_size = 1048576;
356       str[arglen - 1] = '\0';
357       break;
358     }
359 }
360
361 /* Convert STR, a string of ASCII digits, into an unsigned integer.
362    Return -1 if STR does not represent a valid unsigned integer. */
363
364 static long
365 atou (str)
366      char *str;
367 {
368   int value;
369
370   for (value = 0; ISDIGIT (*str); ++str)
371     value = value * 10 + *str - '0';
372   return *str ? -1 : value;
373 }
374
375 static void
376 usage (status)
377      int status;
378 {
379   if (status != 0)
380     fprintf (stderr, "Try `%s --help' for more information.\n",
381              program_name);
382   else
383     {
384       printf ("\
385 Usage: %s [OPTION]... [FILE]...\n\
386 ",
387               program_name);
388       printf ("\
389 \n\
390   -c, --bytes=SIZE         print first SIZE bytes\n\
391   -n, --lines=NUMBER   print first NUMBER lines instead of first 10\n\
392   -q, --quiet, --silent    never print headers giving file names\n\
393   -v, --verbose            always print headers giving file names\n\
394       --help               display this help and exit\n\
395       --version            output version information and exit\n\
396 \n\
397 SIZE may have a multiplier suffix: b for 512, k for 1K, m for 1 Meg.\n\
398 If -VALUE is used as first OPTION, read -c VALUE when one of\n\
399 multipliers bkm follows concatenated, else read -n VALUE.  With no\n\
400 FILE, or when FILE is -, read standard input.\n\
401 ");
402     }
403   exit (status);
404 }