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