new copyright notice
[unix-history] / usr / src / bin / cat / cat.c
CommitLineData
bcf1365c 1/*
0986a758
KB
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 *
27c71911 8 * %sccs.include.redist.c%
bcf1365c
DF
9 */
10
205a2d85 11#ifndef lint
d6d4c082 12char copyright[] =
0986a758 13"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
d6d4c082
KB
14 All rights reserved.\n";
15#endif /* not lint */
16
17#ifndef lint
27c71911 18static char sccsid[] = "@(#)cat.c 5.11 (Berkeley) %G%";
d6d4c082 19#endif /* not lint */
205a2d85 20
0ae48d09
KB
21#include <sys/param.h>
22#include <sys/stat.h>
23#include <sys/file.h>
efa30d97 24#include <stdio.h>
0986a758 25#include <ctype.h>
efa30d97 26
2b7b0bbf 27extern int errno;
f56eef62
KB
28int bflag, eflag, nflag, sflag, tflag, vflag;
29int rval;
0986a758 30char *filename;
efa30d97
BJ
31
32main(argc, argv)
0986a758
KB
33 int argc;
34 char **argv;
efa30d97 35{
2b7b0bbf 36 extern int optind;
f56eef62 37 int ch;
0986a758 38 char *strerror();
efa30d97 39
fc16a647 40 while ((ch = getopt(argc, argv, "benstuv")) != EOF)
0986a758 41 switch (ch) {
f56eef62
KB
42 case 'b':
43 bflag = nflag = 1; /* -b implies -n */
44 break;
45 case 'e':
46 eflag = vflag = 1; /* -e implies -v */
47 break;
48 case 'n':
49 nflag = 1;
50 break;
51 case 's':
52 sflag = 1;
53 break;
54 case 't':
55 tflag = vflag = 1; /* -t implies -v */
56 break;
57 case 'u':
58 setbuf(stdout, (char *)NULL);
59 break;
60 case 'v':
61 vflag = 1;
0986a758
KB
62 break;
63 case '?':
64 (void)fprintf(stderr,
f56eef62 65 "usage: cat [-benstuv] [-] [file ...]\n");
0986a758 66 exit(1);
72c98f6b 67 }
fc16a647 68 argv += optind;
0986a758 69
f56eef62
KB
70 if (bflag || eflag || nflag || sflag || tflag || vflag)
71 cook_args(argv);
72 else
73 raw_args(argv);
74 exit(rval);
75}
76
77cook_args(argv)
78 char **argv;
79{
80 register FILE *fp;
81
82 fp = stdin;
83 filename = "-";
84 do {
85 if (*argv) {
86 if (!strcmp(*argv, "-"))
87 fp = stdin;
88 else if (!(fp = fopen(*argv, "r"))) {
89 (void)fprintf(stderr,
90 "cat: %s: %s\n", *argv, strerror(errno));
91 rval = 1;
92 ++argv;
93 continue;
94 }
95 filename = *argv++;
96 }
97 cook_buf(fp);
98 if (fp != stdin)
99 (void)fclose(fp);
100 } while (*argv);
101}
102
103cook_buf(fp)
104 register FILE *fp;
105{
106 register int ch, gobble, line, prev;
107
108 line = gobble = 0;
109 for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) {
110 if (prev == '\n') {
111 if (ch == '\n') {
112 if (sflag) {
73e4609d 113 if (!gobble && putchar(ch) == EOF)
7d9ace85 114 break;
f56eef62 115 gobble = 1;
7d9ace85 116 continue;
f56eef62
KB
117 }
118 if (nflag && !bflag) {
119 (void)fprintf(stdout, "%6d\t", ++line);
120 if (ferror(stdout))
121 break;
122 }
7d9ace85 123 } else if (nflag) {
f56eef62
KB
124 (void)fprintf(stdout, "%6d\t", ++line);
125 if (ferror(stdout))
126 break;
127 }
128 }
7d9ace85 129 gobble = 0;
f56eef62
KB
130 if (ch == '\n') {
131 if (eflag)
73e4609d 132 if (putchar('$') == EOF)
f56eef62
KB
133 break;
134 } else if (ch == '\t') {
135 if (tflag) {
73e4609d 136 if (putchar('^') == EOF || putchar('I') == EOF)
f56eef62
KB
137 break;
138 continue;
139 }
140 } else if (vflag) {
73e4609d
KB
141 if (!isascii(ch)) {
142 if (putchar('M') == EOF || putchar('-') == EOF)
f56eef62 143 break;
73e4609d 144 ch = toascii(ch);
f56eef62
KB
145 }
146 if (iscntrl(ch)) {
73e4609d
KB
147 if (putchar('^') == EOF ||
148 putchar(ch == '\177' ? '?' :
149 ch | 0100) == EOF)
f56eef62
KB
150 break;
151 continue;
152 }
153 }
73e4609d 154 if (putchar(ch) == EOF)
f56eef62
KB
155 break;
156 }
157 if (ferror(fp)) {
158 (void)fprintf(stderr, "cat: %s: read error\n", filename);
159 rval = 1;
160 }
161 if (ferror(stdout)) {
162 clearerr(stdout);
163 (void)fprintf(stderr, "cat: stdout: write error\n");
164 rval = 1;
165 }
166}
167
168raw_args(argv)
169 char **argv;
170{
171 register int fd;
172
0ae48d09 173 fd = fileno(stdin);
0986a758
KB
174 filename = "-";
175 do {
176 if (*argv) {
0ae48d09
KB
177 if (!strcmp(*argv, "-"))
178 fd = fileno(stdin);
179 else if ((fd = open(*argv, O_RDONLY, 0)) < 0) {
180 (void)fprintf(stderr, "cat: %s: %s\n",
181 *argv, strerror(errno));
182 rval = 1;
0986a758 183 ++argv;
72c98f6b
EC
184 continue;
185 }
0ae48d09 186 filename = *argv++;
efa30d97 187 }
f56eef62 188 rval |= raw_cat(fd);
0ae48d09
KB
189 if (fd != fileno(stdin))
190 (void)close(fd);
0986a758 191 } while (*argv);
efa30d97 192}
3c67f80d 193
f56eef62 194raw_cat(fd)
0986a758 195 register int fd;
ef57e02f 196{
0986a758 197 register int nr, nw, off;
0ae48d09
KB
198 static int bsize;
199 static char *buf;
200 struct stat sbuf;
201 char *malloc(), *strerror();
ef57e02f 202
0ae48d09
KB
203 if (!buf) {
204 if (fstat(fileno(stdout), &sbuf)) {
205 (void)fprintf(stderr, "cat: %s: %s\n", filename,
206 strerror(errno));
207 return(1);
208 }
209 bsize = MAX(sbuf.st_blksize, 1024);
210 if (!(buf = malloc((u_int)bsize))) {
f56eef62
KB
211 (void)fprintf(stderr, "cat: %s: no memory.\n",
212 filename);
0ae48d09
KB
213 return(1);
214 }
215 }
216 while ((nr = read(fd, buf, bsize)) > 0)
0986a758
KB
217 for (off = 0; off < nr;) {
218 if ((nw = write(fileno(stdout), buf + off, nr)) < 0) {
219 perror("cat: stdout");
0ae48d09 220 return(1);
a58e01f9 221 }
0986a758
KB
222 off += nw;
223 }
224 if (nr < 0) {
225 (void)fprintf(stderr, "cat: %s: %s\n", filename,
226 strerror(errno));
0ae48d09 227 return(1);
a58e01f9 228 }
0ae48d09 229 return(0);
ef57e02f 230}