xref: /csrg-svn/bin/cat/cat.c (revision 45857)
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*45857Sbostic static char sccsid[] = "@(#)cat.c	5.12 (Berkeley) 12/29/90";
1934079Sbostic #endif /* not lint */
2034079Sbostic 
2137178Sbostic #include <sys/param.h>
2237178Sbostic #include <sys/stat.h>
2337178Sbostic #include <sys/file.h>
24962Sbill #include <stdio.h>
2537128Sbostic #include <ctype.h>
26962Sbill 
2740268Sbostic extern int errno;
2837179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
2937179Sbostic int rval;
3037128Sbostic char *filename;
31962Sbill 
32962Sbill main(argc, argv)
3337128Sbostic 	int argc;
3437128Sbostic 	char **argv;
35962Sbill {
3640268Sbostic 	extern int optind;
3737179Sbostic 	int ch;
3837128Sbostic 	char *strerror();
39962Sbill 
4039713Sbostic 	while ((ch = getopt(argc, argv, "benstuv")) != EOF)
4137128Sbostic 		switch (ch) {
4237179Sbostic 		case 'b':
4337179Sbostic 			bflag = nflag = 1;	/* -b implies -n */
44962Sbill 			break;
4537179Sbostic 		case 'e':
4637179Sbostic 			eflag = vflag = 1;	/* -e implies -v */
4737179Sbostic 			break;
4837179Sbostic 		case 'n':
4937179Sbostic 			nflag = 1;
5037179Sbostic 			break;
5137179Sbostic 		case 's':
5237179Sbostic 			sflag = 1;
5337179Sbostic 			break;
5437179Sbostic 		case 't':
5537179Sbostic 			tflag = vflag = 1;	/* -t implies -v */
5637179Sbostic 			break;
5737179Sbostic 		case 'u':
5837179Sbostic 			setbuf(stdout, (char *)NULL);
5937179Sbostic 			break;
6037179Sbostic 		case 'v':
6137179Sbostic 			vflag = 1;
6237179Sbostic 			break;
6337128Sbostic 		case '?':
6437128Sbostic 			(void)fprintf(stderr,
6537179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
6637128Sbostic 			exit(1);
67962Sbill 		}
6839713Sbostic 	argv += optind;
6937128Sbostic 
7037179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
7137179Sbostic 		cook_args(argv);
7237179Sbostic 	else
7337179Sbostic 		raw_args(argv);
7437179Sbostic 	exit(rval);
7537179Sbostic }
7637179Sbostic 
7737179Sbostic cook_args(argv)
7837179Sbostic 	char **argv;
7937179Sbostic {
8037179Sbostic 	register FILE *fp;
8137179Sbostic 
8237179Sbostic 	fp = stdin;
8337179Sbostic 	filename = "-";
8437179Sbostic 	do {
8537179Sbostic 		if (*argv) {
8637179Sbostic 			if (!strcmp(*argv, "-"))
8737179Sbostic 				fp = stdin;
8837179Sbostic 			else if (!(fp = fopen(*argv, "r"))) {
8937179Sbostic 				(void)fprintf(stderr,
9037179Sbostic 				    "cat: %s: %s\n", *argv, strerror(errno));
9137179Sbostic 				rval = 1;
9237179Sbostic 				++argv;
9337179Sbostic 				continue;
9437179Sbostic 			}
9537179Sbostic 			filename = *argv++;
9637179Sbostic 		}
9737179Sbostic 		cook_buf(fp);
9837179Sbostic 		if (fp != stdin)
9937179Sbostic 			(void)fclose(fp);
10037179Sbostic 	} while (*argv);
10137179Sbostic }
10237179Sbostic 
10337179Sbostic cook_buf(fp)
10437179Sbostic 	register FILE *fp;
10537179Sbostic {
10637179Sbostic 	register int ch, gobble, line, prev;
10737179Sbostic 
10837179Sbostic 	line = gobble = 0;
10937179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
11037179Sbostic 		if (prev == '\n') {
11137179Sbostic 			if (ch == '\n') {
11237179Sbostic 				if (sflag) {
11338900Sbostic 					if (!gobble && putchar(ch) == EOF)
11438471Sbostic 						break;
11537179Sbostic 					gobble = 1;
11638471Sbostic 					continue;
11737179Sbostic 				}
11837179Sbostic 				if (nflag && !bflag) {
11937179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
12037179Sbostic 					if (ferror(stdout))
12137179Sbostic 						break;
12237179Sbostic 				}
12338471Sbostic 			} else if (nflag) {
12437179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
12537179Sbostic 				if (ferror(stdout))
12637179Sbostic 					break;
12737179Sbostic 			}
12837179Sbostic 		}
12938471Sbostic 		gobble = 0;
13037179Sbostic 		if (ch == '\n') {
13137179Sbostic 			if (eflag)
13238900Sbostic 				if (putchar('$') == EOF)
13337179Sbostic 					break;
13437179Sbostic 		} else if (ch == '\t') {
13537179Sbostic 			if (tflag) {
13638900Sbostic 				if (putchar('^') == EOF || putchar('I') == EOF)
13737179Sbostic 					break;
13837179Sbostic 				continue;
13937179Sbostic 			}
14037179Sbostic 		} else if (vflag) {
14138900Sbostic 			if (!isascii(ch)) {
14238900Sbostic 				if (putchar('M') == EOF || putchar('-') == EOF)
14337179Sbostic 					break;
14438900Sbostic 				ch = toascii(ch);
14537179Sbostic 			}
14637179Sbostic 			if (iscntrl(ch)) {
14738900Sbostic 				if (putchar('^') == EOF ||
14838900Sbostic 				    putchar(ch == '\177' ? '?' :
14938900Sbostic 				    ch | 0100) == EOF)
15037179Sbostic 					break;
15137179Sbostic 				continue;
15237179Sbostic 			}
15337179Sbostic 		}
15438900Sbostic 		if (putchar(ch) == EOF)
15537179Sbostic 			break;
15637179Sbostic 	}
15737179Sbostic 	if (ferror(fp)) {
15837179Sbostic 		(void)fprintf(stderr, "cat: %s: read error\n", filename);
15937179Sbostic 		rval = 1;
16037179Sbostic 	}
16137179Sbostic 	if (ferror(stdout)) {
16237179Sbostic 		clearerr(stdout);
16337179Sbostic 		(void)fprintf(stderr, "cat: stdout: write error\n");
16437179Sbostic 		rval = 1;
16537179Sbostic 	}
16637179Sbostic }
16737179Sbostic 
16837179Sbostic raw_args(argv)
16937179Sbostic 	char **argv;
17037179Sbostic {
17137179Sbostic 	register int fd;
17237179Sbostic 
17337178Sbostic 	fd = fileno(stdin);
17437128Sbostic 	filename = "-";
17537128Sbostic 	do {
17637128Sbostic 		if (*argv) {
17737178Sbostic 			if (!strcmp(*argv, "-"))
17837178Sbostic 				fd = fileno(stdin);
17937178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
18037178Sbostic 				(void)fprintf(stderr, "cat: %s: %s\n",
18137178Sbostic 				    *argv, strerror(errno));
18237178Sbostic 				rval = 1;
18337128Sbostic 				++argv;
1844387Secc 				continue;
1854387Secc 			}
18637178Sbostic 			filename = *argv++;
187962Sbill 		}
18837179Sbostic 		rval |= raw_cat(fd);
18937178Sbostic 		if (fd != fileno(stdin))
19037178Sbostic 			(void)close(fd);
19137128Sbostic 	} while (*argv);
192962Sbill }
1931357Sbill 
19437179Sbostic raw_cat(fd)
19537128Sbostic 	register int fd;
19617947Sralph {
19737128Sbostic 	register int nr, nw, off;
19837178Sbostic 	static int bsize;
19937178Sbostic 	static char *buf;
20037178Sbostic 	struct stat sbuf;
20137178Sbostic 	char *malloc(), *strerror();
20217947Sralph 
20337178Sbostic 	if (!buf) {
20437178Sbostic 		if (fstat(fileno(stdout), &sbuf)) {
20537178Sbostic 			(void)fprintf(stderr, "cat: %s: %s\n", filename,
20637178Sbostic 			    strerror(errno));
20737178Sbostic 			return(1);
20837178Sbostic 		}
20937178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
21037178Sbostic 		if (!(buf = malloc((u_int)bsize))) {
21137179Sbostic 			(void)fprintf(stderr, "cat: %s: no memory.\n",
21237179Sbostic 			    filename);
21337178Sbostic 			return(1);
21437178Sbostic 		}
21537178Sbostic 	}
21637178Sbostic 	while ((nr = read(fd, buf, bsize)) > 0)
217*45857Sbostic 		for (off = 0; off < nr; nr -= nw, off += nw)
21837128Sbostic 			if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
21937128Sbostic 				perror("cat: stdout");
22037178Sbostic 				return(1);
22117965Skarels 			}
22237128Sbostic 	if (nr < 0) {
22337128Sbostic 		(void)fprintf(stderr, "cat: %s: %s\n", filename,
22437128Sbostic 		    strerror(errno));
22537178Sbostic 		return(1);
22617947Sralph 	}
22737178Sbostic 	return(0);
22817947Sralph }
229