xref: /csrg-svn/bin/cat/cat.c (revision 37179)
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*37179Sbostic static char sccsid[] = "@(#)cat.c	5.6 (Berkeley) 03/15/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 
37*37179Sbostic int bflag, eflag, nflag, sflag, tflag, vflag;
38*37179Sbostic int rval;
3937128Sbostic char *filename;
40962Sbill 
41962Sbill main(argc, argv)
4237128Sbostic 	int argc;
4337128Sbostic 	char **argv;
44962Sbill {
4537128Sbostic 	extern int errno, optind;
46*37179Sbostic 	int ch;
4737128Sbostic 	char *strerror();
48962Sbill 
49*37179Sbostic 	while ((ch = getopt(argc, argv, "-benstuv")) != EOF)
5037128Sbostic 		switch (ch) {
5137128Sbostic 		case '-':
5237128Sbostic 			--optind;
5337128Sbostic 			goto done;
54*37179Sbostic 		case 'b':
55*37179Sbostic 			bflag = nflag = 1;	/* -b implies -n */
56962Sbill 			break;
57*37179Sbostic 		case 'e':
58*37179Sbostic 			eflag = vflag = 1;	/* -e implies -v */
59*37179Sbostic 			break;
60*37179Sbostic 		case 'n':
61*37179Sbostic 			nflag = 1;
62*37179Sbostic 			break;
63*37179Sbostic 		case 's':
64*37179Sbostic 			sflag = 1;
65*37179Sbostic 			break;
66*37179Sbostic 		case 't':
67*37179Sbostic 			tflag = vflag = 1;	/* -t implies -v */
68*37179Sbostic 			break;
69*37179Sbostic 		case 'u':
70*37179Sbostic 			setbuf(stdout, (char *)NULL);
71*37179Sbostic 			break;
72*37179Sbostic 		case 'v':
73*37179Sbostic 			vflag = 1;
74*37179Sbostic 			break;
7537128Sbostic 		case '?':
7637128Sbostic 			(void)fprintf(stderr,
77*37179Sbostic 			    "usage: cat [-benstuv] [-] [file ...]\n");
7837128Sbostic 			exit(1);
79962Sbill 		}
8037128Sbostic done:	argv += optind;
8137128Sbostic 
82*37179Sbostic 	if (bflag || eflag || nflag || sflag || tflag || vflag)
83*37179Sbostic 		cook_args(argv);
84*37179Sbostic 	else
85*37179Sbostic 		raw_args(argv);
86*37179Sbostic 	exit(rval);
87*37179Sbostic }
88*37179Sbostic 
89*37179Sbostic cook_args(argv)
90*37179Sbostic 	char **argv;
91*37179Sbostic {
92*37179Sbostic 	register FILE *fp;
93*37179Sbostic 
94*37179Sbostic 	fp = stdin;
95*37179Sbostic 	filename = "-";
96*37179Sbostic 	do {
97*37179Sbostic 		if (*argv) {
98*37179Sbostic 			if (!strcmp(*argv, "-"))
99*37179Sbostic 				fp = stdin;
100*37179Sbostic 			else if (!(fp = fopen(*argv, "r"))) {
101*37179Sbostic 				(void)fprintf(stderr,
102*37179Sbostic 				    "cat: %s: %s\n", *argv, strerror(errno));
103*37179Sbostic 				rval = 1;
104*37179Sbostic 				++argv;
105*37179Sbostic 				continue;
106*37179Sbostic 			}
107*37179Sbostic 			filename = *argv++;
108*37179Sbostic 		}
109*37179Sbostic 		cook_buf(fp);
110*37179Sbostic 		if (fp != stdin)
111*37179Sbostic 			(void)fclose(fp);
112*37179Sbostic 	} while (*argv);
113*37179Sbostic }
114*37179Sbostic 
115*37179Sbostic cook_buf(fp)
116*37179Sbostic 	register FILE *fp;
117*37179Sbostic {
118*37179Sbostic 	register int ch, gobble, line, prev;
119*37179Sbostic 
120*37179Sbostic 	line = gobble = 0;
121*37179Sbostic 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
122*37179Sbostic 		if (prev == '\n') {
123*37179Sbostic 			if (ch == '\n') {
124*37179Sbostic 				if (sflag) {
125*37179Sbostic 					if (gobble)
126*37179Sbostic 						continue;
127*37179Sbostic 					gobble = 1;
128*37179Sbostic 				}
129*37179Sbostic 				if (nflag && !bflag) {
130*37179Sbostic 					(void)fprintf(stdout, "%6d\t", ++line);
131*37179Sbostic 					if (ferror(stdout))
132*37179Sbostic 						break;
133*37179Sbostic 				}
134*37179Sbostic 			}
135*37179Sbostic 			else if (nflag) {
136*37179Sbostic 				(void)fprintf(stdout, "%6d\t", ++line);
137*37179Sbostic 				if (ferror(stdout))
138*37179Sbostic 					break;
139*37179Sbostic 			}
140*37179Sbostic 		}
141*37179Sbostic 		if (ch == '\n') {
142*37179Sbostic 			if (eflag)
143*37179Sbostic 				if (putc('$', stdout) == EOF)
144*37179Sbostic 					break;
145*37179Sbostic 		} else if (ch == '\t') {
146*37179Sbostic 			if (tflag) {
147*37179Sbostic 				if (putc('^', stdout) == EOF ||
148*37179Sbostic 				    putc('I', stdout) == EOF)
149*37179Sbostic 					break;
150*37179Sbostic 				continue;
151*37179Sbostic 			}
152*37179Sbostic 		} else if (vflag) {
153*37179Sbostic 			if (ch > 0177) {
154*37179Sbostic 				if (putc('M', stdout) == EOF ||
155*37179Sbostic 				    putc('-', stdout) == EOF)
156*37179Sbostic 					break;
157*37179Sbostic 				ch &= 0177;
158*37179Sbostic 			}
159*37179Sbostic 			if (iscntrl(ch)) {
160*37179Sbostic 				if (putc('^', stdout) == EOF ||
161*37179Sbostic 				    putc(ch == '\177' ? '?' :
162*37179Sbostic 				    ch | 0100, stdout) == EOF)
163*37179Sbostic 					break;
164*37179Sbostic 				continue;
165*37179Sbostic 			}
166*37179Sbostic 		}
167*37179Sbostic 		if (putc(ch, stdout) == EOF)
168*37179Sbostic 			break;
169*37179Sbostic 	}
170*37179Sbostic 	if (ferror(fp)) {
171*37179Sbostic 		(void)fprintf(stderr, "cat: %s: read error\n", filename);
172*37179Sbostic 		rval = 1;
173*37179Sbostic 	}
174*37179Sbostic 	if (ferror(stdout)) {
175*37179Sbostic 		clearerr(stdout);
176*37179Sbostic 		(void)fprintf(stderr, "cat: stdout: write error\n");
177*37179Sbostic 		rval = 1;
178*37179Sbostic 	}
179*37179Sbostic }
180*37179Sbostic 
181*37179Sbostic raw_args(argv)
182*37179Sbostic 	char **argv;
183*37179Sbostic {
184*37179Sbostic 	register int fd;
185*37179Sbostic 
18637178Sbostic 	fd = fileno(stdin);
18737128Sbostic 	filename = "-";
18837128Sbostic 	do {
18937128Sbostic 		if (*argv) {
19037178Sbostic 			if (!strcmp(*argv, "-"))
19137178Sbostic 				fd = fileno(stdin);
19237178Sbostic 			else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
19337178Sbostic 				(void)fprintf(stderr, "cat: %s: %s\n",
19437178Sbostic 				    *argv, strerror(errno));
19537178Sbostic 				rval = 1;
19637128Sbostic 				++argv;
1974387Secc 				continue;
1984387Secc 			}
19937178Sbostic 			filename = *argv++;
200962Sbill 		}
201*37179Sbostic 		rval |= raw_cat(fd);
20237178Sbostic 		if (fd != fileno(stdin))
20337178Sbostic 			(void)close(fd);
20437128Sbostic 	} while (*argv);
205962Sbill }
2061357Sbill 
207*37179Sbostic raw_cat(fd)
20837128Sbostic 	register int fd;
20917947Sralph {
21037128Sbostic 	extern int errno;
21137128Sbostic 	register int nr, nw, off;
21237178Sbostic 	static int bsize;
21337178Sbostic 	static char *buf;
21437178Sbostic 	struct stat sbuf;
21537178Sbostic 	char *malloc(), *strerror();
21617947Sralph 
21737178Sbostic 	if (!buf) {
21837178Sbostic 		if (fstat(fileno(stdout), &sbuf)) {
21937178Sbostic 			(void)fprintf(stderr, "cat: %s: %s\n", filename,
22037178Sbostic 			    strerror(errno));
22137178Sbostic 			return(1);
22237178Sbostic 		}
22337178Sbostic 		bsize = MAX(sbuf.st_blksize, 1024);
22437178Sbostic 		if (!(buf = malloc((u_int)bsize))) {
225*37179Sbostic 			(void)fprintf(stderr, "cat: %s: no memory.\n",
226*37179Sbostic 			    filename);
22737178Sbostic 			return(1);
22837178Sbostic 		}
22937178Sbostic 	}
23037178Sbostic 	while ((nr = read(fd, buf, bsize)) > 0)
23137128Sbostic 		for (off = 0; off < nr;) {
23237128Sbostic 			if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
23337128Sbostic 				perror("cat: stdout");
23437178Sbostic 				return(1);
23517965Skarels 			}
23637128Sbostic 			off += nw;
23737128Sbostic 		}
23837128Sbostic 	if (nr < 0) {
23937128Sbostic 		(void)fprintf(stderr, "cat: %s: %s\n", filename,
24037128Sbostic 		    strerror(errno));
24137178Sbostic 		return(1);
24217947Sralph 	}
24337178Sbostic 	return(0);
24417947Sralph }
245