11590Srgrimes/* 21590Srgrimes * Copyright (c) 1980, 1987, 1992, 1993 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 301590Srgrimes#ifndef lint 3127314Scharnierstatic const char copyright[] = 321590Srgrimes"@(#) Copyright (c) 1980, 1987, 1992, 1993\n\ 331590Srgrimes The Regents of the University of California. All rights reserved.\n"; 341590Srgrimes#endif /* not lint */ 351590Srgrimes 361590Srgrimes#ifndef lint 3727314Scharnier#if 0 3823693Speterstatic char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95"; 3927314Scharnier#endif 401590Srgrimes#endif /* not lint */ 4199112Sobrien#include <sys/cdefs.h> 4299112Sobrien__FBSDID("$FreeBSD: stable/11/usr.bin/head/head.c 332482 2018-04-13 17:57:00Z kevans $"); 431590Srgrimes 441590Srgrimes#include <sys/types.h> 4523693Speter 4623693Speter#include <ctype.h> 4727314Scharnier#include <err.h> 48332482Skevans#include <getopt.h> 49165940Sbrooks#include <inttypes.h> 5023693Speter#include <stdio.h> 511590Srgrimes#include <stdlib.h> 521590Srgrimes#include <string.h> 5323693Speter#include <unistd.h> 541590Srgrimes 551590Srgrimes/* 561590Srgrimes * head - give the first few lines of a stream or of each of a set of files 571590Srgrimes * 581590Srgrimes * Bill Joy UCB August 24, 1977 591590Srgrimes */ 601590Srgrimes 6193441Sdwmalonestatic void head(FILE *, int); 62165940Sbrooksstatic void head_bytes(FILE *, off_t); 6393441Sdwmalonestatic void obsolete(char *[]); 6493441Sdwmalonestatic void usage(void); 651590Srgrimes 66332482Skevansstatic const struct option long_opts[] = 67332482Skevans{ 68332482Skevans {"bytes", required_argument, NULL, 'c'}, 69332482Skevans {"lines", required_argument, NULL, 'n'}, 70332482Skevans {NULL, no_argument, NULL, 0} 71332482Skevans}; 72332482Skevans 731590Srgrimesint 7495652Smarkmmain(int argc, char *argv[]) 751590Srgrimes{ 7693441Sdwmalone int ch; 771590Srgrimes FILE *fp; 78165940Sbrooks int first, linecnt = -1, eval = 0; 79165940Sbrooks off_t bytecnt = -1; 801590Srgrimes char *ep; 811590Srgrimes 821590Srgrimes obsolete(argv); 83332482Skevans while ((ch = getopt_long(argc, argv, "+n:c:", long_opts, NULL)) != -1) 841590Srgrimes switch(ch) { 8524665Salex case 'c': 86165940Sbrooks bytecnt = strtoimax(optarg, &ep, 10); 8724665Salex if (*ep || bytecnt <= 0) 8827314Scharnier errx(1, "illegal byte count -- %s", optarg); 8924665Salex break; 901590Srgrimes case 'n': 911590Srgrimes linecnt = strtol(optarg, &ep, 10); 921590Srgrimes if (*ep || linecnt <= 0) 9327314Scharnier errx(1, "illegal line count -- %s", optarg); 941590Srgrimes break; 951590Srgrimes case '?': 961590Srgrimes default: 971590Srgrimes usage(); 981590Srgrimes } 991590Srgrimes argc -= optind; 1001590Srgrimes argv += optind; 1011590Srgrimes 10224665Salex if (linecnt != -1 && bytecnt != -1) 10327314Scharnier errx(1, "can't combine line and byte counts"); 10424665Salex if (linecnt == -1 ) 10524665Salex linecnt = 10; 10624665Salex if (*argv) { 1071590Srgrimes for (first = 1; *argv; ++argv) { 1081590Srgrimes if ((fp = fopen(*argv, "r")) == NULL) { 10927314Scharnier warn("%s", *argv); 11027328Scharnier eval = 1; 1111590Srgrimes continue; 1121590Srgrimes } 1131590Srgrimes if (argc > 1) { 1141590Srgrimes (void)printf("%s==> %s <==\n", 1151590Srgrimes first ? "" : "\n", *argv); 1161590Srgrimes first = 0; 1171590Srgrimes } 11824665Salex if (bytecnt == -1) 11924665Salex head(fp, linecnt); 12024665Salex else 12124665Salex head_bytes(fp, bytecnt); 1221590Srgrimes (void)fclose(fp); 1231590Srgrimes } 12485859Salfred } else if (bytecnt == -1) 12524665Salex head(stdin, linecnt); 1261590Srgrimes else 12724665Salex head_bytes(stdin, bytecnt); 12824665Salex 1291590Srgrimes exit(eval); 1301590Srgrimes} 1311590Srgrimes 13293441Sdwmalonestatic void 13395652Smarkmhead(FILE *fp, int cnt) 1341590Srgrimes{ 13585861Salfred char *cp; 13693441Sdwmalone size_t error, readlen; 1371590Srgrimes 13885861Salfred while (cnt && (cp = fgetln(fp, &readlen)) != NULL) { 13985861Salfred error = fwrite(cp, sizeof(char), readlen, stdout); 14085861Salfred if (error != readlen) 14185861Salfred err(1, "stdout"); 14285861Salfred cnt--; 14385861Salfred } 1441590Srgrimes} 1451590Srgrimes 14693441Sdwmalonestatic void 147165940Sbrookshead_bytes(FILE *fp, off_t cnt) 14824665Salex{ 14924665Salex char buf[4096]; 15093441Sdwmalone size_t readlen; 15124665Salex 15224665Salex while (cnt) { 153165955Sbrooks if ((uintmax_t)cnt < sizeof(buf)) 15424665Salex readlen = cnt; 15524665Salex else 15624665Salex readlen = sizeof(buf); 15724665Salex readlen = fread(buf, sizeof(char), readlen, fp); 15840114Sdes if (readlen == 0) 15924665Salex break; 16024665Salex if (fwrite(buf, sizeof(char), readlen, stdout) != readlen) 16127314Scharnier err(1, "stdout"); 16224665Salex cnt -= readlen; 16324665Salex } 16424665Salex} 16524665Salex 16693441Sdwmalonestatic void 16795652Smarkmobsolete(char *argv[]) 1681590Srgrimes{ 1691590Srgrimes char *ap; 1701590Srgrimes 17124665Salex while ((ap = *++argv)) { 1721590Srgrimes /* Return if "--" or not "-[0-9]*". */ 1731590Srgrimes if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1])) 1741590Srgrimes return; 1751590Srgrimes if ((ap = malloc(strlen(*argv) + 2)) == NULL) 17627314Scharnier err(1, NULL); 1771590Srgrimes ap[0] = '-'; 1781590Srgrimes ap[1] = 'n'; 1791590Srgrimes (void)strcpy(ap + 2, *argv + 1); 1801590Srgrimes *argv = ap; 1811590Srgrimes } 1821590Srgrimes} 1831590Srgrimes 18493441Sdwmalonestatic void 18595652Smarkmusage(void) 1861590Srgrimes{ 18785859Salfred 18889767Sdwmalone (void)fprintf(stderr, "usage: head [-n lines | -c bytes] [file ...]\n"); 1891590Srgrimes exit(1); 1901590Srgrimes} 191