xref: /csrg-svn/bin/cat/cat.c (revision 40268)
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  *
837128Sbostic  * Redistribution and use in source and binary forms are permitted
937128Sbostic  * provided that the above copyright notice and this paragraph are
1037128Sbostic  * duplicated in all such forms and that any documentation,
1137128Sbostic  * advertising materials, and other materials related to such
1237128Sbostic  * distribution and use acknowledge that the software was developed
1337128Sbostic  * by the University of California, Berkeley.  The name of the
1437128Sbostic  * University may not be used to endorse or promote products derived
1537128Sbostic  * from this software without specific prior written permission.
1637128Sbostic  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1737128Sbostic  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1837128Sbostic  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1919840Sdist  */
2019840Sdist 
2114463Ssam #ifndef lint
2234079Sbostic char copyright[] =
2337128Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
2434079Sbostic  All rights reserved.\n";
2534079Sbostic #endif /* not lint */
2614463Ssam 
2734079Sbostic #ifndef lint
28*40268Sbostic static char sccsid[] = "@(#)cat.c	5.10 (Berkeley) 03/05/90";
2934079Sbostic #endif /* not lint */
3034079Sbostic 
3137178Sbostic #include <sys/param.h>
3237178Sbostic #include <sys/stat.h>
3337178Sbostic #include <sys/file.h>
34962Sbill #include <stdio.h>
3537128Sbostic #include <ctype.h>
36962Sbill 
37*40268Sbostic extern int errno;
3837179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
3937179Sbostic int rval;
4037128Sbostic char *filename;
41962Sbill 
42962Sbill main(argc, argv)
4337128Sbostic 	int argc;
4437128Sbostic 	char **argv;
45962Sbill {
46*40268Sbostic 	extern int optind;
4737179Sbostic 	int ch;
4837128Sbostic 	char *strerror();
49962Sbill 
5039713Sbostic 	while ((ch = getopt(argc, argv, "benstuv")) != EOF)
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;
7337128Sbostic 		case '?':
7437128Sbostic 			(void)fprintf(stderr,
7537179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
7637128Sbostic 			exit(1);
77962Sbill 		}
7839713Sbostic 	argv += optind;
7937128Sbostic 
8037179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
8137179Sbostic 		cook_args(argv);
8237179Sbostic 	else
8337179Sbostic 		raw_args(argv);
8437179Sbostic 	exit(rval);
8537179Sbostic }
8637179Sbostic 
8737179Sbostic cook_args(argv)
8837179Sbostic 	char **argv;
8937179Sbostic {
9037179Sbostic 	register FILE *fp;
9137179Sbostic 
9237179Sbostic 	fp = stdin;
9337179Sbostic 	filename = "-";
9437179Sbostic 	do {
9537179Sbostic 		if (*argv) {
9637179Sbostic 			if (!strcmp(*argv, "-"))
9737179Sbostic 				fp = stdin;
9837179Sbostic 			else if (!(fp = fopen(*argv, "r"))) {
9937179Sbostic 				(void)fprintf(stderr,
10037179Sbostic 				    "cat: %s: %s\n", *argv, strerror(errno));
10137179Sbostic 				rval = 1;
10237179Sbostic 				++argv;
10337179Sbostic 				continue;
10437179Sbostic 			}
10537179Sbostic 			filename = *argv++;
10637179Sbostic 		}
10737179Sbostic 		cook_buf(fp);
10837179Sbostic 		if (fp != stdin)
10937179Sbostic 			(void)fclose(fp);
11037179Sbostic 	} while (*argv);
11137179Sbostic }
11237179Sbostic 
11337179Sbostic cook_buf(fp)
11437179Sbostic 	register FILE *fp;
11537179Sbostic {
11637179Sbostic 	register int ch, gobble, line, prev;
11737179Sbostic 
11837179Sbostic 	line = gobble = 0;
11937179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
12037179Sbostic 		if (prev == '\n') {
12137179Sbostic 			if (ch == '\n') {
12237179Sbostic 				if (sflag) {
12338900Sbostic 					if (!gobble && putchar(ch) == EOF)
12438471Sbostic 						break;
12537179Sbostic 					gobble = 1;
12638471Sbostic 					continue;
12737179Sbostic 				}
12837179Sbostic 				if (nflag && !bflag) {
12937179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
13037179Sbostic 					if (ferror(stdout))
13137179Sbostic 						break;
13237179Sbostic 				}
13338471Sbostic 			} else if (nflag) {
13437179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
13537179Sbostic 				if (ferror(stdout))
13637179Sbostic 					break;
13737179Sbostic 			}
13837179Sbostic 		}
13938471Sbostic 		gobble = 0;
14037179Sbostic 		if (ch == '\n') {
14137179Sbostic 			if (eflag)
14238900Sbostic 				if (putchar('$') == EOF)
14337179Sbostic 					break;
14437179Sbostic 		} else if (ch == '\t') {
14537179Sbostic 			if (tflag) {
14638900Sbostic 				if (putchar('^') == EOF || putchar('I') == EOF)
14737179Sbostic 					break;
14837179Sbostic 				continue;
14937179Sbostic 			}
15037179Sbostic 		} else if (vflag) {
15138900Sbostic 			if (!isascii(ch)) {
15238900Sbostic 				if (putchar('M') == EOF || putchar('-') == EOF)
15337179Sbostic 					break;
15438900Sbostic 				ch = toascii(ch);
15537179Sbostic 			}
15637179Sbostic 			if (iscntrl(ch)) {
15738900Sbostic 				if (putchar('^') == EOF ||
15838900Sbostic 				    putchar(ch == '\177' ? '?' :
15938900Sbostic 				    ch | 0100) == EOF)
16037179Sbostic 					break;
16137179Sbostic 				continue;
16237179Sbostic 			}
16337179Sbostic 		}
16438900Sbostic 		if (putchar(ch) == EOF)
16537179Sbostic 			break;
16637179Sbostic 	}
16737179Sbostic 	if (ferror(fp)) {
16837179Sbostic 		(void)fprintf(stderr, "cat: %s: read error\n", filename);
16937179Sbostic 		rval = 1;
17037179Sbostic 	}
17137179Sbostic 	if (ferror(stdout)) {
17237179Sbostic 		clearerr(stdout);
17337179Sbostic 		(void)fprintf(stderr, "cat: stdout: write error\n");
17437179Sbostic 		rval = 1;
17537179Sbostic 	}
17637179Sbostic }
17737179Sbostic 
17837179Sbostic raw_args(argv)
17937179Sbostic 	char **argv;
18037179Sbostic {
18137179Sbostic 	register int fd;
18237179Sbostic 
18337178Sbostic 	fd = fileno(stdin);
18437128Sbostic 	filename = "-";
18537128Sbostic 	do {
18637128Sbostic 		if (*argv) {
18737178Sbostic 			if (!strcmp(*argv, "-"))
18837178Sbostic 				fd = fileno(stdin);
18937178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19037178Sbostic 				(void)fprintf(stderr, "cat: %s: %s\n",
19137178Sbostic 				    *argv, strerror(errno));
19237178Sbostic 				rval = 1;
19337128Sbostic 				++argv;
1944387Secc 				continue;
1954387Secc 			}
19637178Sbostic 			filename = *argv++;
197962Sbill 		}
19837179Sbostic 		rval |= raw_cat(fd);
19937178Sbostic 		if (fd != fileno(stdin))
20037178Sbostic 			(void)close(fd);
20137128Sbostic 	} while (*argv);
202962Sbill }
2031357Sbill 
20437179Sbostic raw_cat(fd)
20537128Sbostic 	register int fd;
20617947Sralph {
20737128Sbostic 	register int nr, nw, off;
20837178Sbostic 	static int bsize;
20937178Sbostic 	static char *buf;
21037178Sbostic 	struct stat sbuf;
21137178Sbostic 	char *malloc(), *strerror();
21217947Sralph 
21337178Sbostic 	if (!buf) {
21437178Sbostic 		if (fstat(fileno(stdout), &sbuf)) {
21537178Sbostic 			(void)fprintf(stderr, "cat: %s: %s\n", filename,
21637178Sbostic 			    strerror(errno));
21737178Sbostic 			return(1);
21837178Sbostic 		}
21937178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
22037178Sbostic 		if (!(buf = malloc((u_int)bsize))) {
22137179Sbostic 			(void)fprintf(stderr, "cat: %s: no memory.\n",
22237179Sbostic 			    filename);
22337178Sbostic 			return(1);
22437178Sbostic 		}
22537178Sbostic 	}
22637178Sbostic 	while ((nr = read(fd, buf, bsize)) > 0)
22737128Sbostic 		for (off = 0; off < nr;) {
22837128Sbostic 			if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
22937128Sbostic 				perror("cat: stdout");
23037178Sbostic 				return(1);
23117965Skarels 			}
23237128Sbostic 			off += nw;
23337128Sbostic 		}
23437128Sbostic 	if (nr < 0) {
23537128Sbostic 		(void)fprintf(stderr, "cat: %s: %s\n", filename,
23637128Sbostic 		    strerror(errno));
23737178Sbostic 		return(1);
23817947Sralph 	}
23937178Sbostic 	return(0);
24017947Sralph }
241