1 /* head.c - copy first lines from input to stdout.
2  *
3  * Copyright 2006 Timothy Elliott <tle@holymonkey.com>
4  *
5  * See http://opengroup.org/onlinepubs/9699919799/utilities/head.html
6  *
7  * Deviations from posix: -c
8 
9 USE_HEAD(NEWTOY(head, "?n(lines)#<0=10c(bytes)#<0qv[-nc]", TOYFLAG_USR|TOYFLAG_BIN))
10 
11 config HEAD
12   bool "head"
13   default y
14   help
15     usage: head [-n number] [file...]
16 
17     Copy first lines from files to stdout. If no files listed, copy from
18     stdin. Filename "-" is a synonym for stdin.
19 
20     -n	Number of lines to copy
21     -c	Number of bytes to copy
22     -q	Never print headers
23     -v	Always print headers
24 */
25 
26 #define FOR_head
27 #include "toys.h"
28 
GLOBALS(long c,n;int file_no;)29 GLOBALS(
30   long c, n;
31 
32   int file_no;
33 )
34 
35 static void do_head(int fd, char *name)
36 {
37   int i, len, lines=TT.n, bytes=TT.c;
38 
39   if ((toys.optc > 1 && !(toys.optflags & FLAG_q)) || toys.optflags & FLAG_v) {
40     // Print an extra newline for all but the first file
41     if (TT.file_no) xprintf("\n");
42     xprintf("==> %s <==\n", name);
43     xflush();
44   }
45 
46   while ((toys.optflags&FLAG_c) ? bytes : lines) {
47     len = read(fd, toybuf, sizeof(toybuf));
48     if (len<0) perror_msg_raw(name);
49     if (len<1) break;
50 
51     if (bytes) {
52       i = bytes >= len ? len : bytes;
53       bytes -= i;
54     } else for(i=0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
55 
56     xwrite(1, toybuf, i);
57   }
58 
59   TT.file_no++;
60 }
61 
head_main(void)62 void head_main(void)
63 {
64   char *arg = *toys.optargs;
65 
66   // handle old "-42" style arguments
67   if (arg && *arg == '-' && arg[1]) {
68     TT.n = atolx(arg+1);
69     toys.optc--;
70   } else arg = 0;
71   loopfiles(toys.optargs+!!arg, do_head);
72 }
73