xref: /csrg-svn/bin/cat/cat.c (revision 49212)
119840Sdist /*
237128Sbostic  * Copyright (c) 1989 The Regents of the University of California.
337128Sbostic  * All rights reserved.
437128Sbostic  *
537128Sbostic  * This code is derived from software contributed to Berkeley by
637128Sbostic  * Kevin Fall.
737128Sbostic  *
842524Sbostic  * %sccs.include.redist.c%
919840Sdist  */
1019840Sdist 
1114463Ssam #ifndef lint
1234079Sbostic char copyright[] =
1337128Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
1434079Sbostic  All rights reserved.\n";
1534079Sbostic #endif /* not lint */
1614463Ssam 
1734079Sbostic #ifndef lint
18*49212Sbostic static char sccsid[] = "@(#)cat.c	5.14 (Berkeley) 05/06/91";
1934079Sbostic #endif /* not lint */
2034079Sbostic 
2137178Sbostic #include <sys/param.h>
2237178Sbostic #include <sys/stat.h>
2348953Sbostic #include <fcntl.h>
2448953Sbostic #include <errno.h>
2548953Sbostic #include <unistd.h>
26962Sbill #include <stdio.h>
2748953Sbostic #include <stdlib.h>
2848953Sbostic #include <string.h>
2937128Sbostic #include <ctype.h>
30962Sbill 
3137179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
3237179Sbostic int rval;
3337128Sbostic char *filename;
34962Sbill 
3548953Sbostic void cook_args(), cook_buf(), raw_args(), raw_cat();
3648953Sbostic void err __P((int, const char *, ...));
3748953Sbostic 
38962Sbill main(argc, argv)
3937128Sbostic 	int argc;
4037128Sbostic 	char **argv;
41962Sbill {
4240268Sbostic 	extern int optind;
4337179Sbostic 	int ch;
44962Sbill 
4539713Sbostic 	while ((ch = getopt(argc, argv, "benstuv")) != EOF)
4637128Sbostic 		switch (ch) {
4737179Sbostic 		case 'b':
4837179Sbostic 			bflag = nflag = 1;	/* -b implies -n */
49962Sbill 			break;
5037179Sbostic 		case 'e':
5137179Sbostic 			eflag = vflag = 1;	/* -e implies -v */
5237179Sbostic 			break;
5337179Sbostic 		case 'n':
5437179Sbostic 			nflag = 1;
5537179Sbostic 			break;
5637179Sbostic 		case 's':
5737179Sbostic 			sflag = 1;
5837179Sbostic 			break;
5937179Sbostic 		case 't':
6037179Sbostic 			tflag = vflag = 1;	/* -t implies -v */
6137179Sbostic 			break;
6237179Sbostic 		case 'u':
6337179Sbostic 			setbuf(stdout, (char *)NULL);
6437179Sbostic 			break;
6537179Sbostic 		case 'v':
6637179Sbostic 			vflag = 1;
6737179Sbostic 			break;
6837128Sbostic 		case '?':
6937128Sbostic 			(void)fprintf(stderr,
7037179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
7137128Sbostic 			exit(1);
72962Sbill 		}
7339713Sbostic 	argv += optind;
7437128Sbostic 
7537179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
7637179Sbostic 		cook_args(argv);
7737179Sbostic 	else
7837179Sbostic 		raw_args(argv);
79*49212Sbostic 	if (fclose(stdout))
80*49212Sbostic 		err(1, "stdout: %s", strerror(errno));
8137179Sbostic 	exit(rval);
8237179Sbostic }
8337179Sbostic 
8448953Sbostic void
8537179Sbostic cook_args(argv)
8637179Sbostic 	char **argv;
8737179Sbostic {
8837179Sbostic 	register FILE *fp;
8937179Sbostic 
9037179Sbostic 	fp = stdin;
9137179Sbostic 	filename = "-";
9237179Sbostic 	do {
9337179Sbostic 		if (*argv) {
9437179Sbostic 			if (!strcmp(*argv, "-"))
9537179Sbostic 				fp = stdin;
9637179Sbostic 			else if (!(fp = fopen(*argv, "r"))) {
9748953Sbostic 				err(0, "%s: %s", *argv, strerror(errno));
9837179Sbostic 				++argv;
9937179Sbostic 				continue;
10037179Sbostic 			}
10137179Sbostic 			filename = *argv++;
10237179Sbostic 		}
10337179Sbostic 		cook_buf(fp);
10437179Sbostic 		if (fp != stdin)
10537179Sbostic 			(void)fclose(fp);
10637179Sbostic 	} while (*argv);
10737179Sbostic }
10837179Sbostic 
10948953Sbostic void
11037179Sbostic cook_buf(fp)
11137179Sbostic 	register FILE *fp;
11237179Sbostic {
11337179Sbostic 	register int ch, gobble, line, prev;
11437179Sbostic 
11537179Sbostic 	line = gobble = 0;
11637179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
11737179Sbostic 		if (prev == '\n') {
11837179Sbostic 			if (ch == '\n') {
11937179Sbostic 				if (sflag) {
12038900Sbostic 					if (!gobble && putchar(ch) == EOF)
12138471Sbostic 						break;
12237179Sbostic 					gobble = 1;
12338471Sbostic 					continue;
12437179Sbostic 				}
12537179Sbostic 				if (nflag && !bflag) {
12637179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
12737179Sbostic 					if (ferror(stdout))
12837179Sbostic 						break;
12937179Sbostic 				}
13038471Sbostic 			} else if (nflag) {
13137179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
13237179Sbostic 				if (ferror(stdout))
13337179Sbostic 					break;
13437179Sbostic 			}
13537179Sbostic 		}
13638471Sbostic 		gobble = 0;
13737179Sbostic 		if (ch == '\n') {
13837179Sbostic 			if (eflag)
13938900Sbostic 				if (putchar('$') == EOF)
14037179Sbostic 					break;
14137179Sbostic 		} else if (ch == '\t') {
14237179Sbostic 			if (tflag) {
14338900Sbostic 				if (putchar('^') == EOF || putchar('I') == EOF)
14437179Sbostic 					break;
14537179Sbostic 				continue;
14637179Sbostic 			}
14737179Sbostic 		} else if (vflag) {
14838900Sbostic 			if (!isascii(ch)) {
14938900Sbostic 				if (putchar('M') == EOF || putchar('-') == EOF)
15037179Sbostic 					break;
15138900Sbostic 				ch = toascii(ch);
15237179Sbostic 			}
15337179Sbostic 			if (iscntrl(ch)) {
15438900Sbostic 				if (putchar('^') == EOF ||
15538900Sbostic 				    putchar(ch == '\177' ? '?' :
15638900Sbostic 				    ch | 0100) == EOF)
15737179Sbostic 					break;
15837179Sbostic 				continue;
15937179Sbostic 			}
16037179Sbostic 		}
16138900Sbostic 		if (putchar(ch) == EOF)
16237179Sbostic 			break;
16337179Sbostic 	}
16437179Sbostic 	if (ferror(fp)) {
16548953Sbostic 		err(0, "%s: %s", strerror(errno));
16648953Sbostic 		clearerr(fp);
16737179Sbostic 	}
16848953Sbostic 	if (ferror(stdout))
16948953Sbostic 		err(1, "stdout: %s", strerror(errno));
17037179Sbostic }
17137179Sbostic 
17248953Sbostic void
17337179Sbostic raw_args(argv)
17437179Sbostic 	char **argv;
17537179Sbostic {
17637179Sbostic 	register int fd;
17737179Sbostic 
17837178Sbostic 	fd = fileno(stdin);
17937128Sbostic 	filename = "-";
18037128Sbostic 	do {
18137128Sbostic 		if (*argv) {
18237178Sbostic 			if (!strcmp(*argv, "-"))
18337178Sbostic 				fd = fileno(stdin);
18437178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
18548953Sbostic 				err(0, "%s: %s", *argv, strerror(errno));
18637128Sbostic 				++argv;
1874387Secc 				continue;
1884387Secc 			}
18937178Sbostic 			filename = *argv++;
190962Sbill 		}
19148953Sbostic 		raw_cat(fd);
19237178Sbostic 		if (fd != fileno(stdin))
19337178Sbostic 			(void)close(fd);
19437128Sbostic 	} while (*argv);
195962Sbill }
1961357Sbill 
19748953Sbostic void
19848953Sbostic raw_cat(rfd)
19948953Sbostic 	register int rfd;
20017947Sralph {
20148953Sbostic 	register int nr, nw, off, wfd;
20237178Sbostic 	static int bsize;
20337178Sbostic 	static char *buf;
20437178Sbostic 	struct stat sbuf;
20517947Sralph 
20648953Sbostic 	wfd = fileno(stdout);
20737178Sbostic 	if (!buf) {
20848953Sbostic 		if (fstat(wfd, &sbuf))
20948953Sbostic 			err(1, "%s: %s", filename, strerror(errno));
21037178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
21148953Sbostic 		if (!(buf = malloc((u_int)bsize)))
21248953Sbostic 			err(1, "%s", strerror(errno));
21337178Sbostic 	}
21448953Sbostic 	while ((nr = read(rfd, buf, bsize)) > 0)
21545857Sbostic 		for (off = 0; off < nr; nr -= nw, off += nw)
21648953Sbostic 			if ((nw = write(wfd, buf + off, nr)) < 0)
21748953Sbostic 				err(1, "stdout");
21848953Sbostic 	if (nr < 0)
21948953Sbostic 		err(0, "%s: %s", filename, strerror(errno));
22017947Sralph }
22148953Sbostic 
22248953Sbostic #if __STDC__
22348953Sbostic #include <stdarg.h>
22448953Sbostic #else
22548953Sbostic #include <varargs.h>
22648953Sbostic #endif
22748953Sbostic 
22848953Sbostic void
22948953Sbostic #if __STDC__
23048953Sbostic err(int ex, const char *fmt, ...)
23148953Sbostic #else
23248953Sbostic err(ex, fmt, va_alist)
23348953Sbostic 	int ex;
23448953Sbostic 	char *fmt;
23548953Sbostic         va_dcl
23648953Sbostic #endif
23748953Sbostic {
23848953Sbostic 	va_list ap;
23948953Sbostic #if __STDC__
24048953Sbostic 	va_start(ap, fmt);
24148953Sbostic #else
24248953Sbostic 	va_start(ap);
24348953Sbostic #endif
24448953Sbostic 	(void)fprintf(stderr, "cat: ");
24548953Sbostic 	(void)vfprintf(stderr, fmt, ap);
24648953Sbostic 	va_end(ap);
24748953Sbostic 	(void)fprintf(stderr, "\n");
24848953Sbostic 	if (ex)
24948953Sbostic 		exit(1);
25048953Sbostic 	rval = 1;
25148953Sbostic }
252