Initial import, 0.1 + pk 0.2.4-B1
[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
61void cook_args(), cook_buf(), raw_args(), raw_cat();
62void err __P((int, const char *, ...));
63
64main(argc, argv)
65 int argc;
66 char **argv;
67{
68 extern int optind;
69 int ch;
70
71 while ((ch = getopt(argc, argv, "benstuv")) != EOF)
72 switch (ch) {
73 case 'b':
74 bflag = nflag = 1; /* -b implies -n */
75 break;
76 case 'e':
77 eflag = vflag = 1; /* -e implies -v */
78 break;
79 case 'n':
80 nflag = 1;
81 break;
82 case 's':
83 sflag = 1;
84 break;
85 case 't':
86 tflag = vflag = 1; /* -t implies -v */
87 break;
88 case 'u':
89 setbuf(stdout, (char *)NULL);
90 break;
91 case 'v':
92 vflag = 1;
93 break;
94 case '?':
95 (void)fprintf(stderr,
96 "usage: cat [-benstuv] [-] [file ...]\n");
97 exit(1);
98 }
99 argv += optind;
100
101 if (bflag || eflag || nflag || sflag || tflag || vflag)
102 cook_args(argv);
103 else
104 raw_args(argv);
105 if (fclose(stdout))
106 err(1, "stdout: %s", strerror(errno));
107 exit(rval);
108}
109
110void
111cook_args(argv)
112 char **argv;
113{
114 register FILE *fp;
115
116 fp = stdin;
117 filename = "stdin";
118 do {
119 if (*argv) {
120 if (!strcmp(*argv, "-"))
121 fp = stdin;
122 else if (!(fp = fopen(*argv, "r"))) {
123 err(0, "%s: %s", *argv, strerror(errno));
124 ++argv;
125 continue;
126 }
127 filename = *argv++;
128 }
129 cook_buf(fp);
130 if (fp != stdin)
131 (void)fclose(fp);
132 } while (*argv);
133}
134
135void
136cook_buf(fp)
137 register FILE *fp;
138{
139 register int ch, gobble, line, prev;
140
141 line = gobble = 0;
142 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
143 if (prev == '\n') {
144 if (ch == '\n') {
145 if (sflag) {
146 if (!gobble && putchar(ch) == EOF)
147 break;
148 gobble = 1;
149 continue;
150 }
151 if (nflag && !bflag) {
152 (void)fprintf(stdout, "%6d\t", ++line);
153 if (ferror(stdout))
154 break;
155 }
156 } else if (nflag) {
157 (void)fprintf(stdout, "%6d\t", ++line);
158 if (ferror(stdout))
159 break;
160 }
161 }
162 gobble = 0;
163 if (ch == '\n') {
164 if (eflag)
165 if (putchar('$') == EOF)
166 break;
167 } else if (ch == '\t') {
168 if (tflag) {
169 if (putchar('^') == EOF || putchar('I') == EOF)
170 break;
171 continue;
172 }
173 } else if (vflag) {
174 if (!isascii(ch)) {
175 if (putchar('M') == EOF || putchar('-') == EOF)
176 break;
177 ch = toascii(ch);
178 }
179 if (iscntrl(ch)) {
180 if (putchar('^') == EOF ||
181 putchar(ch == '\177' ? '?' :
182 ch | 0100) == EOF)
183 break;
184 continue;
185 }
186 }
187 if (putchar(ch) == EOF)
188 break;
189 }
190 if (ferror(fp)) {
191 err(0, "%s: %s", strerror(errno));
192 clearerr(fp);
193 }
194 if (ferror(stdout))
195 err(1, "stdout: %s", strerror(errno));
196}
197
198void
199raw_args(argv)
200 char **argv;
201{
202 register int fd;
203
204 fd = fileno(stdin);
205 filename = "stdin";
206 do {
207 if (*argv) {
208 if (!strcmp(*argv, "-"))
209 fd = fileno(stdin);
210 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
211 err(0, "%s: %s", *argv, strerror(errno));
212 ++argv;
213 continue;
214 }
215 filename = *argv++;
216 }
217 raw_cat(fd);
218 if (fd != fileno(stdin))
219 (void)close(fd);
220 } while (*argv);
221}
222
223void
224raw_cat(rfd)
225 register int rfd;
226{
227 register int nr, nw, off, wfd;
228 static int bsize;
229 static char *buf;
230 struct stat sbuf;
231
232 wfd = fileno(stdout);
233 if (!buf) {
234 if (fstat(wfd, &sbuf))
235 err(1, "%s: %s", filename, strerror(errno));
236 bsize = MAX(sbuf.st_blksize, 1024);
237 if (!(buf = malloc((u_int)bsize)))
238 err(1, "%s", strerror(errno));
239 }
240 while ((nr = read(rfd, buf, bsize)) > 0)
241 for (off = 0; off < nr; nr -= nw, off += nw)
242 if ((nw = write(wfd, buf + off, nr)) < 0)
243 err(1, "stdout");
244 if (nr < 0)
245 err(0, "%s: %s", filename, strerror(errno));
246}
247
248#if __STDC__
249#include <stdarg.h>
250#else
251#include <varargs.h>
252#endif
253
254void
255#if __STDC__
256err(int ex, const char *fmt, ...)
257#else
258err(ex, fmt, va_alist)
259 int ex;
260 char *fmt;
261 va_dcl
262#endif
263{
264 va_list ap;
265#if __STDC__
266 va_start(ap, fmt);
267#else
268 va_start(ap);
269#endif
270 (void)fprintf(stderr, "cat: ");
271 (void)vfprintf(stderr, fmt, ap);
272 va_end(ap);
273 (void)fprintf(stderr, "\n");
274 if (ex)
275 exit(1);
276 rval = 1;
277}