head.c revision 93441
159191Skris/*
259191Skris * Copyright (c) 1980, 1987, 1992, 1993
359191Skris *	The Regents of the University of California.  All rights reserved.
459191Skris *
559191Skris * Redistribution and use in source and binary forms, with or without
659191Skris * modification, are permitted provided that the following conditions
759191Skris * are met:
859191Skris * 1. Redistributions of source code must retain the above copyright
959191Skris *    notice, this list of conditions and the following disclaimer.
1059191Skris * 2. Redistributions in binary form must reproduce the above copyright
1159191Skris *    notice, this list of conditions and the following disclaimer in the
1259191Skris *    documentation and/or other materials provided with the distribution.
1359191Skris * 3. All advertising materials mentioning features or use of this software
1459191Skris *    must display the following acknowledgement:
1559191Skris *	This product includes software developed by the University of
1659191Skris *	California, Berkeley and its contributors.
1759191Skris * 4. Neither the name of the University nor the names of its contributors
1859191Skris *    may be used to endorse or promote products derived from this software
1959191Skris *    without specific prior written permission.
2059191Skris *
2159191Skris * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2259191Skris * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359191Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459191Skris * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559191Skris * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2659191Skris * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759191Skris * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859191Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959191Skris * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059191Skris * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159191Skris * SUCH DAMAGE.
3259191Skris */
3359191Skris
3459191Skris#ifndef lint
3559191Skrisstatic const char copyright[] =
3659191Skris"@(#) Copyright (c) 1980, 1987, 1992, 1993\n\
3759191Skris	The Regents of the University of California.  All rights reserved.\n";
3859191Skris#endif /* not lint */
3959191Skris
4059191Skris#ifndef lint
4159191Skris#if 0
4259191Skrisstatic char sccsid[] = "@(#)head.c	8.2 (Berkeley) 5/4/95";
4359191Skris#endif
4459191Skrisstatic const char rcsid[] =
4559191Skris  "$FreeBSD: head/usr.bin/head/head.c 93441 2002-03-30 17:17:26Z dwmalone $";
4659191Skris#endif /* not lint */
4759191Skris
4859191Skris#include <sys/types.h>
4959191Skris
5059191Skris#include <ctype.h>
5159191Skris#include <err.h>
5259191Skris#include <stdio.h>
5359191Skris#include <stdlib.h>
5459191Skris#include <string.h>
5559191Skris#include <unistd.h>
5659191Skris
5759191Skris/*
5859191Skris * head - give the first few lines of a stream or of each of a set of files
5959191Skris *
6059191Skris * Bill Joy UCB August 24, 1977
6159191Skris */
6259191Skris
6359191Skrisstatic void head(FILE *, int);
6459191Skrisstatic void head_bytes(FILE *, size_t);
6559191Skrisstatic void obsolete(char *[]);
6659191Skrisstatic void usage(void);
67100936Snectar
68109998Smarkmint
6959191Skrismain(argc, argv)
70142425Snectar	int argc;
71142425Snectar	char *argv[];
7259191Skris{
7359191Skris	int ch;
74205128Ssimon	FILE *fp;
75205128Ssimon	int first, linecnt = -1, bytecnt = -1, eval = 0;
7659191Skris	char *ep;
7759191Skris
7859191Skris	obsolete(argv);
7959191Skris	while ((ch = getopt(argc, argv, "n:c:")) != -1)
8059191Skris		switch(ch) {
8159191Skris		case 'c':
8259191Skris			bytecnt = strtol(optarg, &ep, 10);
8359191Skris			if (*ep || bytecnt <= 0)
8459191Skris				errx(1, "illegal byte count -- %s", optarg);
8559191Skris			break;
8659191Skris		case 'n':
8759191Skris			linecnt = strtol(optarg, &ep, 10);
8859191Skris			if (*ep || linecnt <= 0)
8959191Skris				errx(1, "illegal line count -- %s", optarg);
9059191Skris			break;
9159191Skris		case '?':
9259191Skris		default:
9359191Skris			usage();
9459191Skris		}
9559191Skris	argc -= optind;
9659191Skris	argv += optind;
9759191Skris
98109998Smarkm	if (linecnt != -1 && bytecnt != -1)
9959191Skris		errx(1, "can't combine line and byte counts");
10059191Skris	if (linecnt == -1 )
101238405Sjkim		linecnt = 10;
102238405Sjkim	if (*argv) {
10359191Skris		for (first = 1; *argv; ++argv) {
104238405Sjkim			if ((fp = fopen(*argv, "r")) == NULL) {
10559191Skris				warn("%s", *argv);
106109998Smarkm				eval = 1;
10759191Skris				continue;
10859191Skris			}
10959191Skris			if (argc > 1) {
11059191Skris				(void)printf("%s==> %s <==\n",
11159191Skris				    first ? "" : "\n", *argv);
11259191Skris				first = 0;
11359191Skris			}
11459191Skris			if (bytecnt == -1)
115194206Ssimon				head(fp, linecnt);
116194206Ssimon			else
117194206Ssimon				head_bytes(fp, bytecnt);
118194206Ssimon			(void)fclose(fp);
119194206Ssimon		}
120194206Ssimon	} else if (bytecnt == -1)
121194206Ssimon		head(stdin, linecnt);
122194206Ssimon	else
123194206Ssimon		head_bytes(stdin, bytecnt);
124109998Smarkm
12559191Skris	exit(eval);
12659191Skris}
12759191Skris
12859191Skrisstatic void
12959191Skrishead(fp, cnt)
13059191Skris	FILE *fp;
13159191Skris	int cnt;
13259191Skris{
13359191Skris	char *cp;
13459191Skris	size_t error, readlen;
135109998Smarkm
13659191Skris	while (cnt && (cp = fgetln(fp, &readlen)) != NULL) {
13759191Skris		error = fwrite(cp, sizeof(char), readlen, stdout);
13859191Skris		if (error != readlen)
13959191Skris			err(1, "stdout");
14059191Skris		cnt--;
14159191Skris	}
14259191Skris}
14359191Skris
14459191Skrisstatic void
145109998Smarkmhead_bytes(fp, cnt)
14659191Skris	FILE *fp;
14759191Skris	size_t cnt;
14859191Skris{
14959191Skris	char buf[4096];
15059191Skris	size_t readlen;
15159191Skris
15259191Skris	while (cnt) {
15359191Skris		if (cnt < sizeof(buf))
15459191Skris			readlen = cnt;
15559191Skris		else
156109998Smarkm			readlen = sizeof(buf);
15759191Skris		readlen = fread(buf, sizeof(char), readlen, fp);
15859191Skris		if (readlen == 0)
15959191Skris			break;
16059191Skris		if (fwrite(buf, sizeof(char), readlen, stdout) != readlen)
16159191Skris			err(1, "stdout");
16259191Skris		cnt -= readlen;
16359191Skris	}
164109998Smarkm}
165109998Smarkm
166109998Smarkmstatic void
167109998Smarkmobsolete(argv)
168109998Smarkm	char *argv[];
169142425Snectar{
170142425Snectar	char *ap;
171109998Smarkm
172109998Smarkm	while ((ap = *++argv)) {
173238405Sjkim		/* Return if "--" or not "-[0-9]*". */
174238405Sjkim		if (ap[0] != '-' || ap[1] == '-' || !isdigit(ap[1]))
175109998Smarkm			return;
176109998Smarkm		if ((ap = malloc(strlen(*argv) + 2)) == NULL)
177109998Smarkm			err(1, NULL);
178109998Smarkm		ap[0] = '-';
179109998Smarkm		ap[1] = 'n';
180142425Snectar		(void)strcpy(ap + 2, *argv + 1);
181142425Snectar		*argv = ap;
182109998Smarkm	}
183109998Smarkm}
184238405Sjkim
185109998Smarkmstatic void
186109998Smarkmusage()
187109998Smarkm{
188109998Smarkm
189109998Smarkm	(void)fprintf(stderr, "usage: head [-n lines | -c bytes] [file ...]\n");
190142425Snectar	exit(1);
191142425Snectar}
192109998Smarkm