1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 /* 40 * Copyright (c) 2013, Joyent, Inc. All rights reserved. 41 */ 42 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <locale.h> 48 #include <string.h> 49 #include <ctype.h> 50 51 #define DEF_LINE_COUNT 10 52 53 static void copyout(off_t, int); 54 static void Usage(); 55 56 57 /* 58 * head - give the first few lines of a stream or of each of a set of files. 59 * Optionally shows a specific number of bytes instead. 60 */ 61 int 62 main(int argc, char **argv) 63 { 64 int fileCount; 65 int around = 0; 66 int i; 67 int opt; 68 off_t linecnt = DEF_LINE_COUNT; 69 int isline = 1; 70 int error = 0; 71 int quiet = 0; 72 73 (void) setlocale(LC_ALL, ""); 74 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ 75 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ 76 #endif 77 (void) textdomain(TEXT_DOMAIN); 78 79 /* check for non-standard "-line-count" option */ 80 for (i = 1; i < argc; i++) { 81 if (strcmp(argv[i], "--") == 0) 82 break; 83 84 if ((argv[i][0] == '-') && isdigit(argv[i][1])) { 85 if (strlen(&argv[i][1]) != 86 strspn(&argv[i][1], "0123456789")) { 87 (void) fprintf(stderr, gettext( 88 "%s: Badly formed number\n"), argv[0]); 89 Usage(); 90 } 91 92 linecnt = (off_t)strtoll(&argv[i][1], (char **)NULL, 93 10); 94 while (i < argc) { 95 argv[i] = argv[i + 1]; 96 i++; 97 } 98 argc--; 99 } 100 } 101 102 /* get options */ 103 while ((opt = getopt(argc, argv, "qvn:c:")) != EOF) { 104 switch (opt) { 105 case 'n': 106 case 'c': 107 if ((strcmp(optarg, "--") == 0) || (optind > argc)) { 108 (void) fprintf(stderr, gettext( 109 "%s: Missing -%c argument\n"), argv[0], 110 optopt); 111 Usage(); 112 } 113 linecnt = (off_t)strtoll(optarg, (char **)NULL, 10); 114 if (linecnt <= 0) { 115 (void) fprintf(stderr, gettext( 116 "%s: Invalid \"-%c %s\" option\n"), 117 argv[0], optopt, optarg); 118 Usage(); 119 } 120 isline = optopt != 'c'; 121 break; 122 case 'q': 123 quiet = 1; 124 break; 125 case 'v': 126 quiet = 0; 127 break; 128 default: 129 Usage(); 130 } 131 } 132 133 fileCount = argc - optind; 134 135 do { 136 if ((argv[optind] == NULL) && around) 137 break; 138 139 if (argv[optind] != NULL) { 140 (void) close(0); 141 if (freopen(argv[optind], "r", stdin) == NULL) { 142 perror(argv[optind]); 143 error = 1; 144 optind++; 145 continue; 146 } 147 } 148 149 if (quiet == 0) { 150 if (around) 151 (void) putchar('\n'); 152 153 if (fileCount > 1) 154 (void) printf("==> %s <==\n", argv[optind]); 155 } 156 157 if (argv[optind] != NULL) 158 optind++; 159 160 copyout(linecnt, isline); 161 (void) fflush(stdout); 162 around++; 163 164 } while (argv[optind] != NULL); 165 166 return (error); 167 } 168 169 static void 170 copyout(off_t cnt, int isline) 171 { 172 char lbuf[BUFSIZ]; 173 size_t len; 174 175 while (cnt > 0 && fgets(lbuf, sizeof (lbuf), stdin) != 0) { 176 len = strlen(lbuf); 177 if (isline) { 178 (void) printf("%s", lbuf); 179 /* 180 * only count as a line if buffer read ends with newline 181 */ 182 if (len > 0) { 183 if (lbuf[len - 1] == '\n') { 184 (void) fflush(stdout); 185 cnt--; 186 } 187 } 188 } else { 189 if (len > cnt) { 190 lbuf[cnt] = '\0'; 191 len = cnt; 192 } 193 (void) printf("%s", lbuf); 194 cnt -= len; 195 (void) fflush(stdout); 196 } 197 } 198 } 199 200 static void 201 Usage() 202 { 203 (void) printf(gettext("usage: head [-q] [-v] [-n #] [-c #] [-#] " 204 "[filename...]\n")); 205 exit(1); 206 } 207