Commit | Line | Data |
---|---|---|
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 | 12 | char 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 | |
9da2e0c8 | 18 | static char sccsid[] = "@(#)cat.c 5.17 (Berkeley) %G%"; |
d6d4c082 | 19 | #endif /* not lint */ |
205a2d85 | 20 | |
0ae48d09 KB |
21 | #include <sys/param.h> |
22 | #include <sys/stat.h> | |
9da2e0c8 KB |
23 | |
24 | #include <ctype.h> | |
25 | #include <err.h> | |
87851fcf | 26 | #include <errno.h> |
9da2e0c8 | 27 | #include <fcntl.h> |
efa30d97 | 28 | #include <stdio.h> |
87851fcf KB |
29 | #include <stdlib.h> |
30 | #include <string.h> | |
9da2e0c8 | 31 | #include <unistd.h> |
efa30d97 | 32 | |
f56eef62 KB |
33 | int bflag, eflag, nflag, sflag, tflag, vflag; |
34 | int rval; | |
0986a758 | 35 | char *filename; |
efa30d97 | 36 | |
9da2e0c8 KB |
37 | void cook_args __P((char *argv[])); |
38 | void cook_buf __P((FILE *)); | |
39 | void raw_args __P((char *argv[])); | |
40 | void raw_cat __P((int)); | |
87851fcf | 41 | |
9da2e0c8 | 42 | int |
efa30d97 | 43 | main(argc, argv) |
0986a758 | 44 | int argc; |
9da2e0c8 | 45 | char *argv[]; |
efa30d97 | 46 | { |
2b7b0bbf | 47 | extern int optind; |
f56eef62 | 48 | int ch; |
efa30d97 | 49 | |
fc16a647 | 50 | while ((ch = getopt(argc, argv, "benstuv")) != EOF) |
0986a758 | 51 | switch (ch) { |
f56eef62 KB |
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; | |
0986a758 KB |
72 | break; |
73 | case '?': | |
74 | (void)fprintf(stderr, | |
f56eef62 | 75 | "usage: cat [-benstuv] [-] [file ...]\n"); |
0986a758 | 76 | exit(1); |
72c98f6b | 77 | } |
fc16a647 | 78 | argv += optind; |
0986a758 | 79 | |
f56eef62 KB |
80 | if (bflag || eflag || nflag || sflag || tflag || vflag) |
81 | cook_args(argv); | |
82 | else | |
83 | raw_args(argv); | |
96c88030 | 84 | if (fclose(stdout)) |
9da2e0c8 | 85 | err(1, "stdout"); |
f56eef62 KB |
86 | exit(rval); |
87 | } | |
88 | ||
87851fcf | 89 | void |
f56eef62 KB |
90 | cook_args(argv) |
91 | char **argv; | |
92 | { | |
93 | register FILE *fp; | |
94 | ||
95 | fp = stdin; | |
a320e76f | 96 | filename = "stdin"; |
f56eef62 KB |
97 | do { |
98 | if (*argv) { | |
99 | if (!strcmp(*argv, "-")) | |
100 | fp = stdin; | |
9da2e0c8 KB |
101 | else if ((fp = fopen(*argv, "r")) == NULL) { |
102 | warn("%s", *argv); | |
f56eef62 KB |
103 | ++argv; |
104 | continue; | |
105 | } | |
106 | filename = *argv++; | |
107 | } | |
108 | cook_buf(fp); | |
109 | if (fp != stdin) | |
110 | (void)fclose(fp); | |
111 | } while (*argv); | |
112 | } | |
113 | ||
87851fcf | 114 | void |
f56eef62 KB |
115 | cook_buf(fp) |
116 | register FILE *fp; | |
117 | { | |
118 | register int ch, gobble, line, prev; | |
119 | ||
120 | line = gobble = 0; | |
121 | for (prev = '\n'; (ch = getc(fp)) != EOF; prev = ch) { | |
122 | if (prev == '\n') { | |
123 | if (ch == '\n') { | |
124 | if (sflag) { | |
73e4609d | 125 | if (!gobble && putchar(ch) == EOF) |
7d9ace85 | 126 | break; |
f56eef62 | 127 | gobble = 1; |
7d9ace85 | 128 | continue; |
f56eef62 KB |
129 | } |
130 | if (nflag && !bflag) { | |
131 | (void)fprintf(stdout, "%6d\t", ++line); | |
132 | if (ferror(stdout)) | |
133 | break; | |
134 | } | |
7d9ace85 | 135 | } else if (nflag) { |
f56eef62 KB |
136 | (void)fprintf(stdout, "%6d\t", ++line); |
137 | if (ferror(stdout)) | |
138 | break; | |
139 | } | |
140 | } | |
7d9ace85 | 141 | gobble = 0; |
f56eef62 KB |
142 | if (ch == '\n') { |
143 | if (eflag) | |
73e4609d | 144 | if (putchar('$') == EOF) |
f56eef62 KB |
145 | break; |
146 | } else if (ch == '\t') { | |
147 | if (tflag) { | |
73e4609d | 148 | if (putchar('^') == EOF || putchar('I') == EOF) |
f56eef62 KB |
149 | break; |
150 | continue; | |
151 | } | |
152 | } else if (vflag) { | |
73e4609d KB |
153 | if (!isascii(ch)) { |
154 | if (putchar('M') == EOF || putchar('-') == EOF) | |
f56eef62 | 155 | break; |
73e4609d | 156 | ch = toascii(ch); |
f56eef62 KB |
157 | } |
158 | if (iscntrl(ch)) { | |
73e4609d KB |
159 | if (putchar('^') == EOF || |
160 | putchar(ch == '\177' ? '?' : | |
161 | ch | 0100) == EOF) | |
f56eef62 KB |
162 | break; |
163 | continue; | |
164 | } | |
165 | } | |
73e4609d | 166 | if (putchar(ch) == EOF) |
f56eef62 KB |
167 | break; |
168 | } | |
169 | if (ferror(fp)) { | |
9da2e0c8 | 170 | warn("%s", filename); |
87851fcf | 171 | clearerr(fp); |
f56eef62 | 172 | } |
87851fcf | 173 | if (ferror(stdout)) |
9da2e0c8 | 174 | err(1, "stdout"); |
f56eef62 KB |
175 | } |
176 | ||
87851fcf | 177 | void |
f56eef62 KB |
178 | raw_args(argv) |
179 | char **argv; | |
180 | { | |
181 | register int fd; | |
182 | ||
0ae48d09 | 183 | fd = fileno(stdin); |
a320e76f | 184 | filename = "stdin"; |
0986a758 KB |
185 | do { |
186 | if (*argv) { | |
0ae48d09 KB |
187 | if (!strcmp(*argv, "-")) |
188 | fd = fileno(stdin); | |
189 | else if ((fd = open(*argv, O_RDONLY, 0)) < 0) { | |
9da2e0c8 | 190 | warn("%s", *argv); |
0986a758 | 191 | ++argv; |
72c98f6b EC |
192 | continue; |
193 | } | |
0ae48d09 | 194 | filename = *argv++; |
efa30d97 | 195 | } |
87851fcf | 196 | raw_cat(fd); |
0ae48d09 KB |
197 | if (fd != fileno(stdin)) |
198 | (void)close(fd); | |
0986a758 | 199 | } while (*argv); |
efa30d97 | 200 | } |
3c67f80d | 201 | |
87851fcf KB |
202 | void |
203 | raw_cat(rfd) | |
204 | register int rfd; | |
ef57e02f | 205 | { |
87851fcf | 206 | register int nr, nw, off, wfd; |
0ae48d09 KB |
207 | static int bsize; |
208 | static char *buf; | |
209 | struct stat sbuf; | |
ef57e02f | 210 | |
87851fcf | 211 | wfd = fileno(stdout); |
9da2e0c8 | 212 | if (buf == NULL) { |
87851fcf | 213 | if (fstat(wfd, &sbuf)) |
9da2e0c8 | 214 | err(1, "%s", filename); |
0ae48d09 | 215 | bsize = MAX(sbuf.st_blksize, 1024); |
9da2e0c8 KB |
216 | if ((buf = malloc((u_int)bsize)) == NULL) |
217 | err(1, ""); | |
0ae48d09 | 218 | } |
87851fcf | 219 | while ((nr = read(rfd, buf, bsize)) > 0) |
53ec5995 | 220 | for (off = 0; off < nr; nr -= nw, off += nw) |
87851fcf | 221 | if ((nw = write(wfd, buf + off, nr)) < 0) |
9da2e0c8 | 222 | err(1, "stdout"); |
87851fcf | 223 | if (nr < 0) |
9da2e0c8 | 224 | warn("%s", filename); |
ef57e02f | 225 | } |