1 /* $OpenBSD: head.c,v 1.24 2022/02/07 17:19:57 cheloha Exp $ */ 2 3 /* 4 * Copyright (c) 1980, 1987 Regents of the University of California. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of the University nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <ctype.h> 35 #include <limits.h> 36 #include <err.h> 37 #include <errno.h> 38 #include <unistd.h> 39 40 int head_file(const char *, long, int); 41 static void usage(void); 42 43 /* 44 * head - give the first few lines of a stream or of each of a set of files 45 * 46 * Bill Joy UCB August 24, 1977 47 */ 48 49 int 50 main(int argc, char *argv[]) 51 { 52 const char *errstr; 53 int ch; 54 long linecnt = 10; 55 int status = 0; 56 57 if (pledge("stdio rpath", NULL) == -1) 58 err(1, "pledge"); 59 60 /* handle obsolete -number syntax */ 61 if (argc > 1 && argv[1][0] == '-' && 62 isdigit((unsigned char)argv[1][1])) { 63 linecnt = strtonum(argv[1] + 1, 1, LONG_MAX, &errstr); 64 if (errstr != NULL) 65 errx(1, "count is %s: %s", errstr, argv[1] + 1); 66 argc--; 67 argv++; 68 } 69 70 while ((ch = getopt(argc, argv, "n:")) != -1) { 71 switch (ch) { 72 case 'n': 73 linecnt = strtonum(optarg, 1, LONG_MAX, &errstr); 74 if (errstr != NULL) 75 errx(1, "count is %s: %s", errstr, optarg); 76 break; 77 default: 78 usage(); 79 } 80 } 81 argc -= optind, argv += optind; 82 83 if (argc == 0) { 84 if (pledge("stdio", NULL) == -1) 85 err(1, "pledge"); 86 87 status = head_file(NULL, linecnt, 0); 88 } else { 89 for (; *argv != NULL; argv++) 90 status |= head_file(*argv, linecnt, argc > 1); 91 } 92 93 return status; 94 } 95 96 int 97 head_file(const char *path, long count, int need_header) 98 { 99 const char *name; 100 FILE *fp; 101 int ch, status = 0; 102 static int first = 1; 103 104 if (path != NULL) { 105 name = path; 106 fp = fopen(name, "r"); 107 if (fp == NULL) { 108 warn("%s", name); 109 return 1; 110 } 111 if (need_header) { 112 printf("%s==> %s <==\n", first ? "" : "\n", name); 113 if (ferror(stdout)) 114 err(1, "stdout"); 115 first = 0; 116 } 117 } else { 118 name = "stdin"; 119 fp = stdin; 120 } 121 122 while ((ch = getc(fp)) != EOF) { 123 if (putchar(ch) == EOF) 124 err(1, "stdout"); 125 if (ch == '\n' && --count == 0) 126 break; 127 } 128 if (ferror(fp)) { 129 warn("%s", name); 130 status = 1; 131 } 132 133 fclose(fp); 134 135 return status; 136 } 137 138 139 static void 140 usage(void) 141 { 142 fputs("usage: head [-count | -n count] [file ...]\n", stderr); 143 exit(1); 144 } 145