19b50d902SRodney W. Grimes /* 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 49b50d902SRodney W. Grimes * Copyright (c) 1980, 1987, 1992, 1993 59b50d902SRodney W. Grimes * The Regents of the University of California. All rights reserved. 69b50d902SRodney W. Grimes * 79b50d902SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 89b50d902SRodney W. Grimes * modification, are permitted provided that the following conditions 99b50d902SRodney W. Grimes * are met: 109b50d902SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 119b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 129b50d902SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 139b50d902SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 149b50d902SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 169b50d902SRodney W. Grimes * may be used to endorse or promote products derived from this software 179b50d902SRodney W. Grimes * without specific prior written permission. 189b50d902SRodney W. Grimes * 199b50d902SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 209b50d902SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 219b50d902SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 229b50d902SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 239b50d902SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 249b50d902SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 259b50d902SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 269b50d902SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 279b50d902SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 289b50d902SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 299b50d902SRodney W. Grimes * SUCH DAMAGE. 309b50d902SRodney W. Grimes */ 319b50d902SRodney W. Grimes 329b50d902SRodney W. Grimes #ifndef lint 33c8510085SPhilippe Charnier static const char copyright[] = 349b50d902SRodney W. Grimes "@(#) Copyright (c) 1980, 1987, 1992, 1993\n\ 359b50d902SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 369b50d902SRodney W. Grimes #endif /* not lint */ 379b50d902SRodney W. Grimes 389b50d902SRodney W. Grimes #ifndef lint 39c8510085SPhilippe Charnier #if 0 40df3f5d9dSPeter Wemm static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95"; 41c8510085SPhilippe Charnier #endif 429b50d902SRodney W. Grimes #endif /* not lint */ 43e026a48cSDavid E. O'Brien #include <sys/cdefs.h> 44e026a48cSDavid E. O'Brien __FBSDID("$FreeBSD$"); 459b50d902SRodney W. Grimes 463824f650SMariusz Zaborski #include <sys/capsicum.h> 479b50d902SRodney W. Grimes #include <sys/types.h> 48df3f5d9dSPeter Wemm 493824f650SMariusz Zaborski #include <capsicum_helpers.h> 50df3f5d9dSPeter Wemm #include <ctype.h> 51c8510085SPhilippe Charnier #include <err.h> 523824f650SMariusz Zaborski #include <errno.h> 5379490b93SKyle Evans #include <getopt.h> 546e8298dbSBrooks Davis #include <inttypes.h> 55df3f5d9dSPeter Wemm #include <stdio.h> 569b50d902SRodney W. Grimes #include <stdlib.h> 579b50d902SRodney W. Grimes #include <string.h> 58df3f5d9dSPeter Wemm #include <unistd.h> 599b50d902SRodney W. Grimes 60643ac419SXin LI #include <libutil.h> 61643ac419SXin LI 623824f650SMariusz Zaborski #include <libcasper.h> 633824f650SMariusz Zaborski #include <casper/cap_fileargs.h> 643824f650SMariusz Zaborski 659b50d902SRodney W. Grimes /* 669b50d902SRodney W. Grimes * head - give the first few lines of a stream or of each of a set of files 679b50d902SRodney W. Grimes * 689b50d902SRodney W. Grimes * Bill Joy UCB August 24, 1977 699b50d902SRodney W. Grimes */ 709b50d902SRodney W. Grimes 71643ac419SXin LI static void head(FILE *, intmax_t); 726e8298dbSBrooks Davis static void head_bytes(FILE *, off_t); 734001504dSDavid Malone static void obsolete(char *[]); 74a1b6427aSAlfonso Gregory static void usage(void) __dead2; 759b50d902SRodney W. Grimes 7679490b93SKyle Evans static const struct option long_opts[] = 7779490b93SKyle Evans { 7879490b93SKyle Evans {"bytes", required_argument, NULL, 'c'}, 7979490b93SKyle Evans {"lines", required_argument, NULL, 'n'}, 80643ac419SXin LI {"quiet", no_argument, NULL, 'q'}, 81643ac419SXin LI {"silent", no_argument, NULL, 'q'}, 82643ac419SXin LI {"verbose", no_argument, NULL, 'v'}, 8379490b93SKyle Evans {NULL, no_argument, NULL, 0} 8479490b93SKyle Evans }; 8579490b93SKyle Evans 869b50d902SRodney W. Grimes int 871abf87a8SMark Murray main(int argc, char *argv[]) 889b50d902SRodney W. Grimes { 899b50d902SRodney W. Grimes FILE *fp; 90509111afSMariusz Zaborski off_t bytecnt; 91643ac419SXin LI intmax_t linecnt; 92643ac419SXin LI int ch, first, eval; 933824f650SMariusz Zaborski fileargs_t *fa; 943824f650SMariusz Zaborski cap_rights_t rights; 95643ac419SXin LI int qflag = 0; 96643ac419SXin LI int vflag = 0; 97509111afSMariusz Zaborski 98509111afSMariusz Zaborski linecnt = -1; 99509111afSMariusz Zaborski eval = 0; 100509111afSMariusz Zaborski bytecnt = -1; 1019b50d902SRodney W. Grimes 1029b50d902SRodney W. Grimes obsolete(argv); 103643ac419SXin LI while ((ch = getopt_long(argc, argv, "+n:c:qv", long_opts, NULL)) != -1) { 1049b50d902SRodney W. Grimes switch(ch) { 105ef0e2ea4SAlexander Langer case 'c': 106643ac419SXin LI if (expand_number(optarg, &bytecnt) || bytecnt <= 0) 107c8510085SPhilippe Charnier errx(1, "illegal byte count -- %s", optarg); 108ef0e2ea4SAlexander Langer break; 1099b50d902SRodney W. Grimes case 'n': 110643ac419SXin LI if (expand_number(optarg, &linecnt) || linecnt <= 0) 111c8510085SPhilippe Charnier errx(1, "illegal line count -- %s", optarg); 1129b50d902SRodney W. Grimes break; 113643ac419SXin LI case 'q': 114643ac419SXin LI qflag = 1; 115643ac419SXin LI vflag = 0; 116643ac419SXin LI break; 117643ac419SXin LI case 'v': 118643ac419SXin LI qflag = 0; 119643ac419SXin LI vflag = 1; 120643ac419SXin LI break; 1219b50d902SRodney W. Grimes case '?': 1229b50d902SRodney W. Grimes default: 1239b50d902SRodney W. Grimes usage(); 124509111afSMariusz Zaborski /* NOTREACHED */ 125509111afSMariusz Zaborski } 1269b50d902SRodney W. Grimes } 1279b50d902SRodney W. Grimes argc -= optind; 1289b50d902SRodney W. Grimes argv += optind; 1299b50d902SRodney W. Grimes 1303824f650SMariusz Zaborski fa = fileargs_init(argc, argv, O_RDONLY, 0, 131d76eef34SEd Maste cap_rights_init(&rights, CAP_READ, CAP_FSTAT, CAP_FCNTL), FA_OPEN); 1323824f650SMariusz Zaborski if (fa == NULL) 1337ef518c0SMark Johnston err(1, "unable to init casper"); 1343824f650SMariusz Zaborski 1353824f650SMariusz Zaborski caph_cache_catpages(); 1363824f650SMariusz Zaborski if (caph_limit_stdio() < 0 || caph_enter_casper() < 0) 1373824f650SMariusz Zaborski err(1, "unable to enter capability mode"); 1383824f650SMariusz Zaborski 139ef0e2ea4SAlexander Langer if (linecnt != -1 && bytecnt != -1) 140c8510085SPhilippe Charnier errx(1, "can't combine line and byte counts"); 141ef0e2ea4SAlexander Langer if (linecnt == -1) 142ef0e2ea4SAlexander Langer linecnt = 10; 143509111afSMariusz Zaborski if (*argv != NULL) { 144509111afSMariusz Zaborski for (first = 1; *argv != NULL; ++argv) { 1453824f650SMariusz Zaborski if ((fp = fileargs_fopen(fa, *argv, "r")) == NULL) { 146c8510085SPhilippe Charnier warn("%s", *argv); 14773f3d053SPhilippe Charnier eval = 1; 1489b50d902SRodney W. Grimes continue; 1499b50d902SRodney W. Grimes } 150643ac419SXin LI if (vflag || (qflag == 0 && argc > 1)) { 1519b50d902SRodney W. Grimes (void)printf("%s==> %s <==\n", 1529b50d902SRodney W. Grimes first ? "" : "\n", *argv); 1539b50d902SRodney W. Grimes first = 0; 1549b50d902SRodney W. Grimes } 155ef0e2ea4SAlexander Langer if (bytecnt == -1) 1569b50d902SRodney W. Grimes head(fp, linecnt); 157ef0e2ea4SAlexander Langer else 158ef0e2ea4SAlexander Langer head_bytes(fp, bytecnt); 1599b50d902SRodney W. Grimes (void)fclose(fp); 1609b50d902SRodney W. Grimes } 161c16b5e4fSAlfred Perlstein } else if (bytecnt == -1) 1629b50d902SRodney W. Grimes head(stdin, linecnt); 163ef0e2ea4SAlexander Langer else 164ef0e2ea4SAlexander Langer head_bytes(stdin, bytecnt); 165ef0e2ea4SAlexander Langer 1663824f650SMariusz Zaborski fileargs_free(fa); 1679b50d902SRodney W. Grimes exit(eval); 1689b50d902SRodney W. Grimes } 1699b50d902SRodney W. Grimes 1704001504dSDavid Malone static void 171643ac419SXin LI head(FILE *fp, intmax_t cnt) 1729b50d902SRodney W. Grimes { 173c7a2aa5dSAlfred Perlstein char *cp; 1744001504dSDavid Malone size_t error, readlen; 1759b50d902SRodney W. Grimes 176509111afSMariusz Zaborski while (cnt != 0 && (cp = fgetln(fp, &readlen)) != NULL) { 177c7a2aa5dSAlfred Perlstein error = fwrite(cp, sizeof(char), readlen, stdout); 178c7a2aa5dSAlfred Perlstein if (error != readlen) 179c8510085SPhilippe Charnier err(1, "stdout"); 1808e502f11SJoerg Wunsch cnt--; 1819b50d902SRodney W. Grimes } 1829b50d902SRodney W. Grimes } 1839b50d902SRodney W. Grimes 1844001504dSDavid Malone static void 1856e8298dbSBrooks Davis head_bytes(FILE *fp, off_t cnt) 186ef0e2ea4SAlexander Langer { 187ef0e2ea4SAlexander Langer char buf[4096]; 1884001504dSDavid Malone size_t readlen; 189ef0e2ea4SAlexander Langer 190ef0e2ea4SAlexander Langer while (cnt) { 1916137b0bdSBrooks Davis if ((uintmax_t)cnt < sizeof(buf)) 192ef0e2ea4SAlexander Langer readlen = cnt; 193ef0e2ea4SAlexander Langer else 194ef0e2ea4SAlexander Langer readlen = sizeof(buf); 195ef0e2ea4SAlexander Langer readlen = fread(buf, sizeof(char), readlen, fp); 196710668caSDag-Erling Smørgrav if (readlen == 0) 197ef0e2ea4SAlexander Langer break; 198ef0e2ea4SAlexander Langer if (fwrite(buf, sizeof(char), readlen, stdout) != readlen) 199c8510085SPhilippe Charnier err(1, "stdout"); 200ef0e2ea4SAlexander Langer cnt -= readlen; 201ef0e2ea4SAlexander Langer } 202ef0e2ea4SAlexander Langer } 203ef0e2ea4SAlexander Langer 2044001504dSDavid Malone static void 2051abf87a8SMark Murray obsolete(char *argv[]) 2069b50d902SRodney W. Grimes { 2079b50d902SRodney W. Grimes char *ap; 2089b50d902SRodney W. Grimes 209ef0e2ea4SAlexander Langer while ((ap = *++argv)) { 2109b50d902SRodney W. Grimes /* Return if "--" or not "-[0-9]*". */ 2119b50d902SRodney W. Grimes if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1])) 2129b50d902SRodney W. Grimes return; 2139b50d902SRodney W. Grimes if ((ap = malloc(strlen(*argv) + 2)) == NULL) 214c8510085SPhilippe Charnier err(1, NULL); 2159b50d902SRodney W. Grimes ap[0] = '-'; 2169b50d902SRodney W. Grimes ap[1] = 'n'; 2179b50d902SRodney W. Grimes (void)strcpy(ap + 2, *argv + 1); 2189b50d902SRodney W. Grimes *argv = ap; 2199b50d902SRodney W. Grimes } 2209b50d902SRodney W. Grimes } 2219b50d902SRodney W. Grimes 2224001504dSDavid Malone static void 2231abf87a8SMark Murray usage(void) 2249b50d902SRodney W. Grimes { 225c16b5e4fSAlfred Perlstein 226ecca80bdSDavid Malone (void)fprintf(stderr, "usage: head [-n lines | -c bytes] [file ...]\n"); 2279b50d902SRodney W. Grimes exit(1); 2289b50d902SRodney W. Grimes } 229