1 /* head.c - copy first lines from input to stdout.
2 *
3 * Copyright 2006 Timothy Elliott <[email protected]>
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|TOYFLAG_LINEBUF))
10
11 config HEAD
12 bool "head"
13 default y
14 help
15 usage: head [-cn NUM] [-qv] [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 long i = 0, len = 0, lines = TT.n, bytes = TT.c;
38
39 if ((toys.optc > 1 && !FLAG(q)) || 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 }
44
45 while (FLAG(c) ? bytes : lines) {
46 len = read(fd, toybuf, sizeof(toybuf));
47 if (len<0) perror_msg_raw(name);
48 if (len<1) break;
49
50 if (bytes) {
51 i = bytes >= len ? len : bytes;
52 bytes -= i;
53 } else for(i = 0; i<len;) if (toybuf[i++] == '\n' && !--lines) break;
54
55 xwrite(1, toybuf, i);
56 }
57
58 // attempt to unget extra data
59 if (len>i) lseek(fd, i-len, SEEK_CUR);
60
61 TT.file_no++;
62 }
63
head_main(void)64 void head_main(void)
65 {
66 char *arg = *toys.optargs;
67
68 // handle old "-42" style arguments
69 if (arg && *arg == '-' && arg[1]) {
70 TT.n = atolx(arg+1);
71 toys.optc--;
72 } else arg = 0;
73 loopfiles(toys.optargs+!!arg, do_head);
74 }
75