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