This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / bin / cat / cat.c
CommitLineData
15637ed4
RG
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, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#ifndef lint
38char copyright[] =
39"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
40 All rights reserved.\n";
41#endif /* not lint */
42
43#ifndef lint
44static char sccsid[] = "@(#)cat.c 5.15 (Berkeley) 5/23/91";
45#endif /* not lint */
46
47#include <sys/param.h>
48#include <sys/stat.h>
49#include <fcntl.h>
50#include <errno.h>
51#include <unistd.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <ctype.h>
56
57int bflag, eflag, nflag, sflag, tflag, vflag;
58int rval;
59char *filename;
60
78ed81a3 61void cook_args __P((char **));
62void cook_buf __P((FILE *));
63void raw_args __P((char **));
64void raw_cat __P((int));
65void err __P((int, const char *, ...));
15637ed4 66
78ed81a3 67int
15637ed4
RG
68main(argc, argv)
69 int argc;
70 char **argv;
71{
72 extern int optind;
73 int ch;
74
78ed81a3 75 while ((ch = getopt(argc, argv, "benstuv")) != -1)
15637ed4
RG
76 switch (ch) {
77 case 'b':
78 bflag = nflag = 1; /* -b implies -n */
79 break;
80 case 'e':
81 eflag = vflag = 1; /* -e implies -v */
82 break;
83 case 'n':
84 nflag = 1;
85 break;
86 case 's':
87 sflag = 1;
88 break;
89 case 't':
90 tflag = vflag = 1; /* -t implies -v */
91 break;
92 case 'u':
93 setbuf(stdout, (char *)NULL);
94 break;
95 case 'v':
96 vflag = 1;
97 break;
78ed81a3 98 default:
15637ed4
RG
99 case '?':
100 (void)fprintf(stderr,
101 "usage: cat [-benstuv] [-] [file ...]\n");
102 exit(1);
103 }
104 argv += optind;
105
106 if (bflag || eflag || nflag || sflag || tflag || vflag)
107 cook_args(argv);
108 else
109 raw_args(argv);
110 if (fclose(stdout))
111 err(1, "stdout: %s", strerror(errno));
112 exit(rval);
113}
114
115void
116cook_args(argv)
117 char **argv;
118{
119 register FILE *fp;
120
121 fp = stdin;
122 filename = "stdin";
123 do {
124 if (*argv) {
125 if (!strcmp(*argv, "-"))
126 fp = stdin;
127 else if (!(fp = fopen(*argv, "r"))) {
128 err(0, "%s: %s", *argv, strerror(errno));
129 ++argv;
130 continue;
131 }
132 filename = *argv++;
133 }
134 cook_buf(fp);
135 if (fp != stdin)
136 (void)fclose(fp);
137 } while (*argv);
138}
139
140void
141cook_buf(fp)
142 register FILE *fp;
143{
144 register int ch, gobble, line, prev;
145
146 line = gobble = 0;
147 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
148 if (prev == '\n') {
149 if (ch == '\n') {
150 if (sflag) {
151 if (!gobble && putchar(ch) == EOF)
152 break;
153 gobble = 1;
154 continue;
155 }
156 if (nflag && !bflag) {
157 (void)fprintf(stdout, "%6d\t", ++line);
158 if (ferror(stdout))
159 break;
160 }
161 } else if (nflag) {
162 (void)fprintf(stdout, "%6d\t", ++line);
163 if (ferror(stdout))
164 break;
165 }
166 }
167 gobble = 0;
168 if (ch == '\n') {
169 if (eflag)
170 if (putchar('$') == EOF)
171 break;
172 } else if (ch == '\t') {
173 if (tflag) {
174 if (putchar('^') == EOF || putchar('I') == EOF)
175 break;
176 continue;
177 }
178 } else if (vflag) {
179 if (!isascii(ch)) {
180 if (putchar('M') == EOF || putchar('-') == EOF)
181 break;
182 ch = toascii(ch);
183 }
184 if (iscntrl(ch)) {
185 if (putchar('^') == EOF ||
186 putchar(ch == '\177' ? '?' :
187 ch | 0100) == EOF)
188 break;
189 continue;
190 }
191 }
192 if (putchar(ch) == EOF)
193 break;
194 }
195 if (ferror(fp)) {
78ed81a3 196 err(0, "%s: %s", filename, strerror(errno));
15637ed4
RG
197 clearerr(fp);
198 }
199 if (ferror(stdout))
200 err(1, "stdout: %s", strerror(errno));
201}
202
203void
204raw_args(argv)
205 char **argv;
206{
207 register int fd;
208
209 fd = fileno(stdin);
210 filename = "stdin";
211 do {
212 if (*argv) {
213 if (!strcmp(*argv, "-"))
214 fd = fileno(stdin);
215 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
216 err(0, "%s: %s", *argv, strerror(errno));
217 ++argv;
218 continue;
219 }
220 filename = *argv++;
221 }
222 raw_cat(fd);
223 if (fd != fileno(stdin))
224 (void)close(fd);
225 } while (*argv);
226}
227
228void
229raw_cat(rfd)
230 register int rfd;
231{
232 register int nr, nw, off, wfd;
233 static int bsize;
234 static char *buf;
235 struct stat sbuf;
236
237 wfd = fileno(stdout);
238 if (!buf) {
239 if (fstat(wfd, &sbuf))
240 err(1, "%s: %s", filename, strerror(errno));
241 bsize = MAX(sbuf.st_blksize, 1024);
242 if (!(buf = malloc((u_int)bsize)))
243 err(1, "%s", strerror(errno));
244 }
245 while ((nr = read(rfd, buf, bsize)) > 0)
246 for (off = 0; off < nr; nr -= nw, off += nw)
247 if ((nw = write(wfd, buf + off, nr)) < 0)
248 err(1, "stdout");
249 if (nr < 0)
250 err(0, "%s: %s", filename, strerror(errno));
251}
252
253#if __STDC__
254#include <stdarg.h>
255#else
256#include <varargs.h>
257#endif
258
259void
260#if __STDC__
261err(int ex, const char *fmt, ...)
262#else
263err(ex, fmt, va_alist)
264 int ex;
265 char *fmt;
266 va_dcl
267#endif
268{
269 va_list ap;
270#if __STDC__
271 va_start(ap, fmt);
272#else
273 va_start(ap);
274#endif
275 (void)fprintf(stderr, "cat: ");
276 (void)vfprintf(stderr, fmt, ap);
277 va_end(ap);
278 (void)fprintf(stderr, "\n");
279 if (ex)
280 exit(1);
281 rval = 1;
282}