xref: /original-bsd/bin/cat/cat.c (revision b218b2ee)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Kevin Fall.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #ifndef lint
22 char copyright[] =
23 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
24  All rights reserved.\n";
25 #endif /* not lint */
26 
27 #ifndef lint
28 static char sccsid[] = "@(#)cat.c	5.4 (Berkeley) 03/11/89";
29 #endif /* not lint */
30 
31 #include <stdio.h>
32 #include <ctype.h>
33 
34 int bflag, eflag, nflag, sflag, tflag, vflag;
35 int rval;
36 char *filename;
37 
38 main(argc, argv)
39 	int argc;
40 	char **argv;
41 {
42 	extern int errno, optind;
43 	register FILE *fp;
44 	int ch;
45 	char *strerror();
46 
47 	while ((ch = getopt(argc, argv, "-benstuv")) != EOF)
48 		switch (ch) {
49 		case '-':
50 			--optind;
51 			goto done;
52 		case 'b':
53 			bflag = nflag = 1;	/* -b implies -n */
54 			break;
55 		case 'e':
56 			eflag = vflag = 1;	/* -e implies -v */
57 			break;
58 		case 'n':
59 			nflag = 1;
60 			break;
61 		case 's':
62 			sflag = 1;
63 			break;
64 		case 't':
65 			tflag = vflag = 1;	/* -t implies -v */
66 			break;
67 		case 'u':
68 			setbuf(stdout, (char *)NULL);
69 			break;
70 		case 'v':
71 			vflag = 1;
72 			break;
73 		case '?':
74 			(void)fprintf(stderr,
75 			    "usage: cat [-benstuv] [-] [file ...]\n");
76 			exit(1);
77 		}
78 done:	argv += optind;
79 
80 	fp = stdin;
81 	filename = "-";
82 	do {
83 		if (*argv) {
84 			if (!strcmp(*argv, "-")) {
85 				fp = stdin;
86 				filename = "-";
87 			}
88 			else if (!(fp = fopen(filename = *argv, "r"))) {
89 				(void)fprintf(stderr,
90 				    "cat: %s: %s\n", *argv, strerror(errno));
91 				++argv;
92 				continue;
93 			}
94 			++argv;
95 		}
96 		if (bflag || eflag || nflag || sflag || tflag || vflag)
97 			process_buf(fp);
98 		else
99 			rawcat(fileno(fp));
100 		if (fp != stdin)
101 			(void)fclose(fp);
102 	} while (*argv);
103 	exit(rval);
104 }
105 
106 process_buf(fp)
107 	register FILE *fp;
108 {
109 	register int ch, gobble, line, prev;
110 
111 	line = gobble = 0;
112 	for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
113 		if (prev == '\n') {
114 			if (ch == '\n') {
115 				if (sflag) {
116 					if (gobble)
117 						continue;
118 					gobble = 1;
119 				}
120 				if (nflag && !bflag) {
121 					(void)fprintf(stdout, "%6d\t", ++line);
122 					if (ferror(stdout))
123 						break;
124 				}
125 			}
126 			else if (nflag) {
127 				(void)fprintf(stdout, "%6d\t", ++line);
128 				if (ferror(stdout))
129 					break;
130 			}
131 		}
132 		if (ch == '\n') {
133 			if (eflag)
134 				if (putc('$', stdout) == EOF)
135 					break;
136 		} else if (ch == '\t') {
137 			if (tflag) {
138 				if (putc('^', stdout) == EOF ||
139 				    putc('I', stdout) == EOF)
140 					break;
141 				continue;
142 			}
143 		} else if (vflag) {
144 			if (ch > 0177) {
145 				if (putc('M', stdout) == EOF ||
146 				    putc('-', stdout) == EOF)
147 					break;
148 				ch &= 0177;
149 			}
150 			if (iscntrl(ch)) {
151 				if (putc('^', stdout) == EOF ||
152 				    putc(ch == '\177' ? '?' :
153 				    ch | 0100, stdout) == EOF)
154 					break;
155 				continue;
156 			}
157 		}
158 		if (putc(ch, stdout) == EOF)
159 			break;
160 	}
161 	if (ferror(fp)) {
162 		(void)fprintf(stderr, "cat: %s: read error\n", filename);
163 		rval = 1;
164 	}
165 	if (ferror(stdout)) {
166 		clearerr(stdout);
167 		(void)fprintf(stderr, "cat: stdout: write error\n");
168 		rval = 1;
169 	}
170 }
171 
172 rawcat(fd)
173 	register int fd;
174 {
175 	extern int errno;
176 	static char buf[8*1024];
177 	register int nr, nw, off;
178 	char *strerror();
179 
180 	while ((nr = read(fd, buf, sizeof(buf))) > 0)
181 		for (off = 0; off < nr;) {
182 			if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
183 				perror("cat: stdout");
184 				rval = 1;
185 				return;
186 			}
187 			off += nw;
188 		}
189 	if (nr < 0) {
190 		(void)fprintf(stderr, "cat: %s: %s\n", filename,
191 		    strerror(errno));
192 		rval = 1;
193 	}
194 }
195