1 /* 2 * Copyright (c) 1980, 1987, 1992, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 #ifndef lint 31 static const char copyright[] = 32 "@(#) Copyright (c) 1980, 1987, 1992, 1993\n\ 33 The Regents of the University of California. All rights reserved.\n"; 34 #endif /* not lint */ 35 36 #ifndef lint 37 #if 0 38 static char sccsid[] = "@(#)head.c 8.2 (Berkeley) 5/4/95"; 39 #endif 40 #endif /* not lint */ 41 #include <sys/cdefs.h> 42 __FBSDID("$FreeBSD$"); 43 44 #include <sys/types.h> 45 46 #include <ctype.h> 47 #include <err.h> 48 #include <inttypes.h> 49 #include <stdio.h> 50 #include <stdlib.h> 51 #include <string.h> 52 #include <unistd.h> 53 54 /* 55 * head - give the first few lines of a stream or of each of a set of files 56 * 57 * Bill Joy UCB August 24, 1977 58 */ 59 60 static void head(FILE *, int); 61 static void head_bytes(FILE *, off_t); 62 static void obsolete(char *[]); 63 static void usage(void); 64 65 int 66 main(int argc, char *argv[]) 67 { 68 int ch; 69 FILE *fp; 70 int first, linecnt = -1, eval = 0; 71 off_t bytecnt = -1; 72 char *ep; 73 74 obsolete(argv); 75 while ((ch = getopt(argc, argv, "n:c:")) != -1) 76 switch(ch) { 77 case 'c': 78 bytecnt = strtoimax(optarg, &ep, 10); 79 if (*ep || bytecnt <= 0) 80 errx(1, "illegal byte count -- %s", optarg); 81 break; 82 case 'n': 83 linecnt = strtol(optarg, &ep, 10); 84 if (*ep || linecnt <= 0) 85 errx(1, "illegal line count -- %s", optarg); 86 break; 87 case '?': 88 default: 89 usage(); 90 } 91 argc -= optind; 92 argv += optind; 93 94 if (linecnt != -1 && bytecnt != -1) 95 errx(1, "can't combine line and byte counts"); 96 if (linecnt == -1 ) 97 linecnt = 10; 98 if (*argv) { 99 for (first = 1; *argv; ++argv) { 100 if ((fp = fopen(*argv, "r")) == NULL) { 101 warn("%s", *argv); 102 eval = 1; 103 continue; 104 } 105 if (argc > 1) { 106 (void)printf("%s==> %s <==\n", 107 first ? "" : "\n", *argv); 108 first = 0; 109 } 110 if (bytecnt == -1) 111 head(fp, linecnt); 112 else 113 head_bytes(fp, bytecnt); 114 (void)fclose(fp); 115 } 116 } else if (bytecnt == -1) 117 head(stdin, linecnt); 118 else 119 head_bytes(stdin, bytecnt); 120 121 exit(eval); 122 } 123 124 static void 125 head(FILE *fp, int cnt) 126 { 127 char *cp; 128 size_t error, readlen; 129 130 while (cnt && (cp = fgetln(fp, &readlen)) != NULL) { 131 error = fwrite(cp, sizeof(char), readlen, stdout); 132 if (error != readlen) 133 err(1, "stdout"); 134 cnt--; 135 } 136 } 137 138 static void 139 head_bytes(FILE *fp, off_t cnt) 140 { 141 char buf[4096]; 142 size_t readlen; 143 144 while (cnt) { 145 if ((uintmax_t)cnt < sizeof(buf)) 146 readlen = cnt; 147 else 148 readlen = sizeof(buf); 149 readlen = fread(buf, sizeof(char), readlen, fp); 150 if (readlen == 0) 151 break; 152 if (fwrite(buf, sizeof(char), readlen, stdout) != readlen) 153 err(1, "stdout"); 154 cnt -= readlen; 155 } 156 } 157 158 static void 159 obsolete(char *argv[]) 160 { 161 char *ap; 162 163 while ((ap = *++argv)) { 164 /* Return if "--" or not "-[0-9]*". */ 165 if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1])) 166 return; 167 if ((ap = malloc(strlen(*argv) + 2)) == NULL) 168 err(1, NULL); 169 ap[0] = '-'; 170 ap[1] = 'n'; 171 (void)strcpy(ap + 2, *argv + 1); 172 *argv = ap; 173 } 174 } 175 176 static void 177 usage(void) 178 { 179 180 (void)fprintf(stderr, "usage: head [-n lines | -c bytes] [file ...]\n"); 181 exit(1); 182 } 183