xref: /csrg-svn/bin/cat/cat.c (revision 38900)
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*38900Sbostic static char sccsid[] = "@(#)cat.c	5.8 (Berkeley) 09/01/89";
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 
3737179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
3837179Sbostic int rval;
3937128Sbostic char *filename;
40962Sbill 
41962Sbill main(argc, argv)
4237128Sbostic 	int argc;
4337128Sbostic 	char **argv;
44962Sbill {
4537128Sbostic 	extern int errno, optind;
4637179Sbostic 	int ch;
4737128Sbostic 	char *strerror();
48962Sbill 
4937179Sbostic 	while ((ch = getopt(argc, argv, "-benstuv")) != EOF)
5037128Sbostic 		switch (ch) {
5137128Sbostic 		case '-':
5237128Sbostic 			--optind;
5337128Sbostic 			goto done;
5437179Sbostic 		case 'b':
5537179Sbostic 			bflag = nflag = 1;	/* -b implies -n */
56962Sbill 			break;
5737179Sbostic 		case 'e':
5837179Sbostic 			eflag = vflag = 1;	/* -e implies -v */
5937179Sbostic 			break;
6037179Sbostic 		case 'n':
6137179Sbostic 			nflag = 1;
6237179Sbostic 			break;
6337179Sbostic 		case 's':
6437179Sbostic 			sflag = 1;
6537179Sbostic 			break;
6637179Sbostic 		case 't':
6737179Sbostic 			tflag = vflag = 1;	/* -t implies -v */
6837179Sbostic 			break;
6937179Sbostic 		case 'u':
7037179Sbostic 			setbuf(stdout, (char *)NULL);
7137179Sbostic 			break;
7237179Sbostic 		case 'v':
7337179Sbostic 			vflag = 1;
7437179Sbostic 			break;
7537128Sbostic 		case '?':
7637128Sbostic 			(void)fprintf(stderr,
7737179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
7837128Sbostic 			exit(1);
79962Sbill 		}
8037128Sbostic done:	argv += optind;
8137128Sbostic 
8237179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
8337179Sbostic 		cook_args(argv);
8437179Sbostic 	else
8537179Sbostic 		raw_args(argv);
8637179Sbostic 	exit(rval);
8737179Sbostic }
8837179Sbostic 
8937179Sbostic cook_args(argv)
9037179Sbostic 	char **argv;
9137179Sbostic {
9237179Sbostic 	register FILE *fp;
9337179Sbostic 
9437179Sbostic 	fp = stdin;
9537179Sbostic 	filename = "-";
9637179Sbostic 	do {
9737179Sbostic 		if (*argv) {
9837179Sbostic 			if (!strcmp(*argv, "-"))
9937179Sbostic 				fp = stdin;
10037179Sbostic 			else if (!(fp = fopen(*argv, "r"))) {
10137179Sbostic 				(void)fprintf(stderr,
10237179Sbostic 				    "cat: %s: %s\n", *argv, strerror(errno));
10337179Sbostic 				rval = 1;
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 
11537179Sbostic cook_buf(fp)
11637179Sbostic 	register FILE *fp;
11737179Sbostic {
11837179Sbostic 	register int ch, gobble, line, prev;
11937179Sbostic 
12037179Sbostic 	line = gobble = 0;
12137179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
12237179Sbostic 		if (prev == '\n') {
12337179Sbostic 			if (ch == '\n') {
12437179Sbostic 				if (sflag) {
125*38900Sbostic 					if (!gobble && putchar(ch) == EOF)
12638471Sbostic 						break;
12737179Sbostic 					gobble = 1;
12838471Sbostic 					continue;
12937179Sbostic 				}
13037179Sbostic 				if (nflag && !bflag) {
13137179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
13237179Sbostic 					if (ferror(stdout))
13337179Sbostic 						break;
13437179Sbostic 				}
13538471Sbostic 			} else if (nflag) {
13637179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
13737179Sbostic 				if (ferror(stdout))
13837179Sbostic 					break;
13937179Sbostic 			}
14037179Sbostic 		}
14138471Sbostic 		gobble = 0;
14237179Sbostic 		if (ch == '\n') {
14337179Sbostic 			if (eflag)
144*38900Sbostic 				if (putchar('$') == EOF)
14537179Sbostic 					break;
14637179Sbostic 		} else if (ch == '\t') {
14737179Sbostic 			if (tflag) {
148*38900Sbostic 				if (putchar('^') == EOF || putchar('I') == EOF)
14937179Sbostic 					break;
15037179Sbostic 				continue;
15137179Sbostic 			}
15237179Sbostic 		} else if (vflag) {
153*38900Sbostic 			if (!isascii(ch)) {
154*38900Sbostic 				if (putchar('M') == EOF || putchar('-') == EOF)
15537179Sbostic 					break;
156*38900Sbostic 				ch = toascii(ch);
15737179Sbostic 			}
15837179Sbostic 			if (iscntrl(ch)) {
159*38900Sbostic 				if (putchar('^') == EOF ||
160*38900Sbostic 				    putchar(ch == '\177' ? '?' :
161*38900Sbostic 				    ch | 0100) == EOF)
16237179Sbostic 					break;
16337179Sbostic 				continue;
16437179Sbostic 			}
16537179Sbostic 		}
166*38900Sbostic 		if (putchar(ch) == EOF)
16737179Sbostic 			break;
16837179Sbostic 	}
16937179Sbostic 	if (ferror(fp)) {
17037179Sbostic 		(void)fprintf(stderr, "cat: %s: read error\n", filename);
17137179Sbostic 		rval = 1;
17237179Sbostic 	}
17337179Sbostic 	if (ferror(stdout)) {
17437179Sbostic 		clearerr(stdout);
17537179Sbostic 		(void)fprintf(stderr, "cat: stdout: write error\n");
17637179Sbostic 		rval = 1;
17737179Sbostic 	}
17837179Sbostic }
17937179Sbostic 
18037179Sbostic raw_args(argv)
18137179Sbostic 	char **argv;
18237179Sbostic {
18337179Sbostic 	register int fd;
18437179Sbostic 
18537178Sbostic 	fd = fileno(stdin);
18637128Sbostic 	filename = "-";
18737128Sbostic 	do {
18837128Sbostic 		if (*argv) {
18937178Sbostic 			if (!strcmp(*argv, "-"))
19037178Sbostic 				fd = fileno(stdin);
19137178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19237178Sbostic 				(void)fprintf(stderr, "cat: %s: %s\n",
19337178Sbostic 				    *argv, strerror(errno));
19437178Sbostic 				rval = 1;
19537128Sbostic 				++argv;
1964387Secc 				continue;
1974387Secc 			}
19837178Sbostic 			filename = *argv++;
199962Sbill 		}
20037179Sbostic 		rval |= raw_cat(fd);
20137178Sbostic 		if (fd != fileno(stdin))
20237178Sbostic 			(void)close(fd);
20337128Sbostic 	} while (*argv);
204962Sbill }
2051357Sbill 
20637179Sbostic raw_cat(fd)
20737128Sbostic 	register int fd;
20817947Sralph {
20937128Sbostic 	extern int errno;
21037128Sbostic 	register int nr, nw, off;
21137178Sbostic 	static int bsize;
21237178Sbostic 	static char *buf;
21337178Sbostic 	struct stat sbuf;
21437178Sbostic 	char *malloc(), *strerror();
21517947Sralph 
21637178Sbostic 	if (!buf) {
21737178Sbostic 		if (fstat(fileno(stdout), &sbuf)) {
21837178Sbostic 			(void)fprintf(stderr, "cat: %s: %s\n", filename,
21937178Sbostic 			    strerror(errno));
22037178Sbostic 			return(1);
22137178Sbostic 		}
22237178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
22337178Sbostic 		if (!(buf = malloc((u_int)bsize))) {
22437179Sbostic 			(void)fprintf(stderr, "cat: %s: no memory.\n",
22537179Sbostic 			    filename);
22637178Sbostic 			return(1);
22737178Sbostic 		}
22837178Sbostic 	}
22937178Sbostic 	while ((nr = read(fd, buf, bsize)) > 0)
23037128Sbostic 		for (off = 0; off < nr;) {
23137128Sbostic 			if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
23237128Sbostic 				perror("cat: stdout");
23337178Sbostic 				return(1);
23417965Skarels 			}
23537128Sbostic 			off += nw;
23637128Sbostic 		}
23737128Sbostic 	if (nr < 0) {
23837128Sbostic 		(void)fprintf(stderr, "cat: %s: %s\n", filename,
23937128Sbostic 		    strerror(errno));
24037178Sbostic 		return(1);
24117947Sralph 	}
24237178Sbostic 	return(0);
24317947Sralph }
244