xref: /csrg-svn/bin/cat/cat.c (revision 68970)
119840Sdist /*
263892Sbostic  * Copyright (c) 1989, 1993
363892Sbostic  *	The Regents of the University of California.  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
1263892Sbostic static char copyright[] =
1363892Sbostic "@(#) Copyright (c) 1989, 1993\n\
1463892Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1534079Sbostic #endif /* not lint */
1614463Ssam 
1734079Sbostic #ifndef lint
18*68970Sbostic static char sccsid[] = "@(#)cat.c	8.2 (Berkeley) 04/27/95";
1934079Sbostic #endif /* not lint */
2034079Sbostic 
2137178Sbostic #include <sys/param.h>
2237178Sbostic #include <sys/stat.h>
2358141Sbostic 
2458141Sbostic #include <ctype.h>
2558141Sbostic #include <err.h>
2658141Sbostic #include <errno.h>
2748953Sbostic #include <fcntl.h>
28962Sbill #include <stdio.h>
2948953Sbostic #include <stdlib.h>
3048953Sbostic #include <string.h>
3158141Sbostic #include <unistd.h>
32962Sbill 
3337179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
3437179Sbostic int rval;
3537128Sbostic char *filename;
36962Sbill 
3758141Sbostic void cook_args __P((char *argv[]));
3858141Sbostic void cook_buf __P((FILE *));
3958141Sbostic void raw_args __P((char *argv[]));
4058141Sbostic void raw_cat __P((int));
4148953Sbostic 
4258141Sbostic int
main(argc,argv)43962Sbill main(argc, argv)
4437128Sbostic 	int argc;
4558141Sbostic 	char *argv[];
46962Sbill {
4740268Sbostic 	extern int optind;
4837179Sbostic 	int ch;
49962Sbill 
50*68970Sbostic 	while ((ch = getopt(argc, argv, "benstuv")) != -1)
5137128Sbostic 		switch (ch) {
5237179Sbostic 		case 'b':
5337179Sbostic 			bflag = nflag = 1;	/* -b implies -n */
54962Sbill 			break;
5537179Sbostic 		case 'e':
5637179Sbostic 			eflag = vflag = 1;	/* -e implies -v */
5737179Sbostic 			break;
5837179Sbostic 		case 'n':
5937179Sbostic 			nflag = 1;
6037179Sbostic 			break;
6137179Sbostic 		case 's':
6237179Sbostic 			sflag = 1;
6337179Sbostic 			break;
6437179Sbostic 		case 't':
6537179Sbostic 			tflag = vflag = 1;	/* -t implies -v */
6637179Sbostic 			break;
6737179Sbostic 		case 'u':
6837179Sbostic 			setbuf(stdout, (char *)NULL);
6937179Sbostic 			break;
7037179Sbostic 		case 'v':
7137179Sbostic 			vflag = 1;
7237179Sbostic 			break;
73*68970Sbostic 		default:
7437128Sbostic 		case '?':
7537128Sbostic 			(void)fprintf(stderr,
7637179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
7737128Sbostic 			exit(1);
78962Sbill 		}
7939713Sbostic 	argv += optind;
8037128Sbostic 
8137179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
8237179Sbostic 		cook_args(argv);
8337179Sbostic 	else
8437179Sbostic 		raw_args(argv);
8549212Sbostic 	if (fclose(stdout))
8658141Sbostic 		err(1, "stdout");
8737179Sbostic 	exit(rval);
8837179Sbostic }
8937179Sbostic 
9048953Sbostic void
cook_args(argv)9137179Sbostic cook_args(argv)
9237179Sbostic 	char **argv;
9337179Sbostic {
9437179Sbostic 	register FILE *fp;
9537179Sbostic 
9637179Sbostic 	fp = stdin;
9749860Sbostic 	filename = "stdin";
9837179Sbostic 	do {
9937179Sbostic 		if (*argv) {
10037179Sbostic 			if (!strcmp(*argv, "-"))
10137179Sbostic 				fp = stdin;
10258141Sbostic 			else if ((fp = fopen(*argv, "r")) == NULL) {
10358141Sbostic 				warn("%s", *argv);
10437179Sbostic 				++argv;
10537179Sbostic 				continue;
10637179Sbostic 			}
10737179Sbostic 			filename = *argv++;
10837179Sbostic 		}
10937179Sbostic 		cook_buf(fp);
11037179Sbostic 		if (fp != stdin)
11137179Sbostic 			(void)fclose(fp);
11237179Sbostic 	} while (*argv);
11337179Sbostic }
11437179Sbostic 
11548953Sbostic void
cook_buf(fp)11637179Sbostic cook_buf(fp)
11737179Sbostic 	register FILE *fp;
11837179Sbostic {
11937179Sbostic 	register int ch, gobble, line, prev;
12037179Sbostic 
12137179Sbostic 	line = gobble = 0;
12237179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
12337179Sbostic 		if (prev == '\n') {
12437179Sbostic 			if (ch == '\n') {
12537179Sbostic 				if (sflag) {
12638900Sbostic 					if (!gobble && putchar(ch) == EOF)
12738471Sbostic 						break;
12837179Sbostic 					gobble = 1;
12938471Sbostic 					continue;
13037179Sbostic 				}
13137179Sbostic 				if (nflag && !bflag) {
13237179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
13337179Sbostic 					if (ferror(stdout))
13437179Sbostic 						break;
13537179Sbostic 				}
13638471Sbostic 			} else if (nflag) {
13737179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
13837179Sbostic 				if (ferror(stdout))
13937179Sbostic 					break;
14037179Sbostic 			}
14137179Sbostic 		}
14238471Sbostic 		gobble = 0;
14337179Sbostic 		if (ch == '\n') {
14437179Sbostic 			if (eflag)
14538900Sbostic 				if (putchar('$') == EOF)
14637179Sbostic 					break;
14737179Sbostic 		} else if (ch == '\t') {
14837179Sbostic 			if (tflag) {
14938900Sbostic 				if (putchar('^') == EOF || putchar('I') == EOF)
15037179Sbostic 					break;
15137179Sbostic 				continue;
15237179Sbostic 			}
15337179Sbostic 		} else if (vflag) {
15438900Sbostic 			if (!isascii(ch)) {
15538900Sbostic 				if (putchar('M') == EOF || putchar('-') == EOF)
15637179Sbostic 					break;
15738900Sbostic 				ch = toascii(ch);
15837179Sbostic 			}
15937179Sbostic 			if (iscntrl(ch)) {
16038900Sbostic 				if (putchar('^') == EOF ||
16138900Sbostic 				    putchar(ch == '\177' ? '?' :
16238900Sbostic 				    ch | 0100) == EOF)
16337179Sbostic 					break;
16437179Sbostic 				continue;
16537179Sbostic 			}
16637179Sbostic 		}
16738900Sbostic 		if (putchar(ch) == EOF)
16837179Sbostic 			break;
16937179Sbostic 	}
17037179Sbostic 	if (ferror(fp)) {
17158141Sbostic 		warn("%s", filename);
17248953Sbostic 		clearerr(fp);
17337179Sbostic 	}
17448953Sbostic 	if (ferror(stdout))
17558141Sbostic 		err(1, "stdout");
17637179Sbostic }
17737179Sbostic 
17848953Sbostic void
raw_args(argv)17937179Sbostic raw_args(argv)
18037179Sbostic 	char **argv;
18137179Sbostic {
18237179Sbostic 	register int fd;
18337179Sbostic 
18437178Sbostic 	fd = fileno(stdin);
18549860Sbostic 	filename = "stdin";
18637128Sbostic 	do {
18737128Sbostic 		if (*argv) {
18837178Sbostic 			if (!strcmp(*argv, "-"))
18937178Sbostic 				fd = fileno(stdin);
19037178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19158141Sbostic 				warn("%s", *argv);
19237128Sbostic 				++argv;
1934387Secc 				continue;
1944387Secc 			}
19537178Sbostic 			filename = *argv++;
196962Sbill 		}
19748953Sbostic 		raw_cat(fd);
19837178Sbostic 		if (fd != fileno(stdin))
19937178Sbostic 			(void)close(fd);
20037128Sbostic 	} while (*argv);
201962Sbill }
2021357Sbill 
20348953Sbostic void
raw_cat(rfd)20448953Sbostic raw_cat(rfd)
20548953Sbostic 	register int rfd;
20617947Sralph {
20748953Sbostic 	register int nr, nw, off, wfd;
20837178Sbostic 	static int bsize;
20937178Sbostic 	static char *buf;
21037178Sbostic 	struct stat sbuf;
21117947Sralph 
21248953Sbostic 	wfd = fileno(stdout);
21358141Sbostic 	if (buf == NULL) {
21448953Sbostic 		if (fstat(wfd, &sbuf))
21558141Sbostic 			err(1, "%s", filename);
21637178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
21758141Sbostic 		if ((buf = malloc((u_int)bsize)) == NULL)
218*68970Sbostic 			err(1, NULL);
21937178Sbostic 	}
22048953Sbostic 	while ((nr = read(rfd, buf, bsize)) > 0)
22163891Sbostic 		for (off = 0; nr; nr -= nw, off += nw)
22248953Sbostic 			if ((nw = write(wfd, buf + off, nr)) < 0)
22358141Sbostic 				err(1, "stdout");
22448953Sbostic 	if (nr < 0)
22558141Sbostic 		warn("%s", filename);
22617947Sralph }
227