manual page distributed with 4.1BSD
[unix-history] / usr / src / bin / cat / cat.c
CommitLineData
205a2d85 1#ifndef lint
a58e01f9 2static char *sccsid = "@(#)cat.c 4.9 (Berkeley) %G%";
205a2d85
SL
3#endif
4
efa30d97
BJ
5/*
6 * Concatenate files.
7 */
8
9#include <stdio.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12
a58e01f9 13/* #define OPTSIZE BUFSIZ /* define this only if not 4.2 BSD or beyond */
ef57e02f
RC
14
15int bflg, eflg, nflg, sflg, tflg, uflg, vflg;
16int spaced, col, lno, inline, ibsize, obsize;
efa30d97
BJ
17
18main(argc, argv)
19char **argv;
20{
21 int fflg = 0;
22 register FILE *fi;
23 register c;
24 int dev, ino = -1;
25 struct stat statb;
ef57e02f 26 int retval = 0;
efa30d97 27
3c67f80d 28 lno = 1;
efa30d97
BJ
29 for( ; argc>1 && argv[1][0]=='-'; argc--,argv++) {
30 switch(argv[1][1]) {
31 case 0:
32 break;
33 case 'u':
34 setbuf(stdout, (char *)NULL);
ef57e02f 35 uflg++;
efa30d97 36 continue;
3c67f80d
BJ
37 case 'n':
38 nflg++;
39 continue;
40 case 'b':
41 bflg++;
42 nflg++;
43 continue;
44 case 'v':
45 vflg++;
46 continue;
47 case 's':
48 sflg++;
49 continue;
50 case 'e':
51 eflg++;
52 vflg++;
53 continue;
54 case 't':
55 tflg++;
56 vflg++;
57 continue;
efa30d97
BJ
58 }
59 break;
60 }
72c98f6b
EC
61 if (fstat(fileno(stdout), &statb) == 0) {
62 statb.st_mode &= S_IFMT;
63 if (statb.st_mode!=S_IFCHR && statb.st_mode!=S_IFBLK) {
64 dev = statb.st_dev;
65 ino = statb.st_ino;
66 }
a58e01f9 67#ifndef OPTSIZE
ef57e02f 68 obsize = statb.st_blksize;
a58e01f9 69#endif
efa30d97 70 }
ef57e02f
RC
71 else
72 obsize = 0;
efa30d97
BJ
73 if (argc < 2) {
74 argc = 2;
75 fflg++;
76 }
77 while (--argc > 0) {
78 if (fflg || (*++argv)[0]=='-' && (*argv)[1]=='\0')
79 fi = stdin;
80 else {
81 if ((fi = fopen(*argv, "r")) == NULL) {
45fb66b3 82 perror(*argv);
ef57e02f 83 retval = 1;
efa30d97
BJ
84 continue;
85 }
86 }
72c98f6b 87 if (fstat(fileno(fi), &statb) == 0) {
ec0bdac7
BJ
88 if ((statb.st_mode & S_IFMT) == S_IFREG &&
89 statb.st_dev==dev && statb.st_ino==ino) {
72c98f6b
EC
90 fprintf(stderr, "cat: input %s is output\n",
91 fflg?"-": *argv);
92 fclose(fi);
ef57e02f 93 retval = 1;
72c98f6b
EC
94 continue;
95 }
a58e01f9 96#ifndef OPTSIZE
ef57e02f 97 ibsize = statb.st_blksize;
a58e01f9 98#endif
efa30d97 99 }
ef57e02f
RC
100 else
101 ibsize = 0;
3c67f80d
BJ
102 if (nflg||sflg||vflg)
103 copyopt(fi);
ef57e02f 104 else if (uflg) {
3c67f80d
BJ
105 while ((c = getc(fi)) != EOF)
106 putchar(c);
ef57e02f 107 } else
a58e01f9 108 retval |= fastcat(fileno(fi)); /* no flags specified */
efa30d97
BJ
109 if (fi!=stdin)
110 fclose(fi);
ef57e02f
RC
111 if (ferror(stdout)) {
112 fprintf(stderr, "cat: output write error\n");
113 retval = 1;
114 break;
115 }
efa30d97 116 }
ef57e02f 117 exit(retval);
efa30d97 118}
3c67f80d
BJ
119
120copyopt(f)
121 register FILE *f;
122{
123 register int c;
124
125top:
126 c = getc(f);
127 if (c == EOF)
128 return;
129 if (c == '\n') {
130 if (inline == 0) {
131 if (sflg && spaced)
132 goto top;
133 spaced = 1;
134 }
135 if (nflg && bflg==0 && inline == 0)
136 printf("%6d\t", lno++);
137 if (eflg)
138 putchar('$');
139 putchar('\n');
140 inline = 0;
141 goto top;
142 }
143 if (nflg && inline == 0)
144 printf("%6d\t", lno++);
145 inline = 1;
146 if (vflg) {
147 if (tflg==0 && c == '\t')
148 putchar(c);
149 else {
150 if (c > 0177) {
151 printf("M-");
152 c &= 0177;
153 }
154 if (c < ' ')
155 printf("^%c", c+'@');
156 else if (c == 0177)
157 printf("^?");
158 else
159 putchar(c);
160 }
161 } else
162 putchar(c);
163 spaced = 0;
164 goto top;
165}
ef57e02f
RC
166
167fastcat(fd)
168register int fd;
169{
170 register int buffsize, n, nwritten, offset;
171 register char *buff;
172 struct stat statbuff;
173 char *malloc();
174
175#ifndef OPTSIZE
a58e01f9
MK
176 if (obsize)
177 buffsize = obsize; /* common case, use output blksize */
178 else if (ibsize)
ef57e02f
RC
179 buffsize = ibsize;
180 else
a58e01f9 181 buffsize = BUFSIZ;
ef57e02f
RC
182#else
183 buffsize = OPTSIZE;
184#endif
185
a58e01f9 186 if ((buff = malloc(buffsize)) == NULL) {
ef57e02f 187 perror("cat: no memory");
a58e01f9
MK
188 return (1);
189 }
ef57e02f
RC
190
191 /*
192 * Note that on some systems (V7), very large writes to a pipe
193 * return less than the requested size of the write.
194 * In this case, multiple writes are required.
195 */
196 while ((n = read(fd, buff, buffsize)) > 0) {
197 offset = 0;
198 do {
199 nwritten = write(fileno(stdout), &buff[offset], n);
a58e01f9 200 if (nwritten <= 0) {
ef57e02f 201 perror("cat: write error");
a58e01f9
MK
202 exit(2);
203 }
ef57e02f
RC
204 offset += nwritten;
205 } while ((n -= nwritten) > 0);
206 }
ef57e02f
RC
207
208 free(buff);
a58e01f9
MK
209 if (n < 0) {
210 perror("cat: read error");
211 return (1);
212 }
213 return (0);
ef57e02f 214}