|
|
1.1 root 1: static char *sccsid = "@(#)tail.c 4.1 (Berkeley) 10/6/80";
2: /* tail command
3: *
4: * tail where [file]
5: * where is +_n[type]
6: * - means n lines before end
7: * + means nth line from beginning
8: * type 'b' means tail n blocks, not lines
9: * type 'c' means tail n characters
10: * Type 'r' means in lines in reverse order from end
11: * (for -r, default is entire buffer )
12: * option 'f' means loop endlessly trying to read more
13: * characters after the end of file, on the assumption
14: * that the file is growing
15: */
16:
17: #include <stdio.h>
18: #include <ctype.h>
19: #include <sys/types.h>
20: #include <sys/stat.h>
21: #include <errno.h>
22:
23: #define LBIN 4097
24: struct stat statb;
25: int follow;
26: int piped;
27: char bin[LBIN];
28: int errno;
29:
30: main(argc,argv)
31: char **argv;
32: {
33: long n,di;
34: register i,j,k;
35: char *arg;
36: int partial,bylines,bkwds,fromend,lastnl;
37: char *p;
38:
39: lseek(0,(long)0,1);
40: piped = errno==ESPIPE;
41: arg = argv[1];
42: if(argc<=1 || *arg!='-'&&*arg!='+') {
43: arg = "-10l";
44: argc++;
45: argv--;
46: }
47: fromend = *arg=='-';
48: arg++;
49: n = 0;
50: while(isdigit(*arg))
51: n = n*10 + *arg++ - '0';
52: if(!fromend&&n>0)
53: n--;
54: if(argc>2) {
55: close(0);
56: if(open(argv[2],0)!=0) {
57: perror(argv[2]);
58: exit(1);
59: }
60: }
61: bylines = -1; bkwds = 0;
62: while(*arg)
63: switch(*arg++) {
64:
65: case 'b':
66: n <<= 9;
67: if(bylines!=-1) goto errcom;
68: bylines=0;
69: break;
70: case 'c':
71: if(bylines!=-1) goto errcom;
72: bylines=0;
73: break;
74: case 'f':
75: follow = 1;
76: break;
77: case 'r':
78: if(n==0) n = LBIN;
79: bkwds = 1; fromend = 1; bylines = 1;
80: break;
81: case 'l':
82: if(bylines!=-1) goto errcom;
83: bylines = 1;
84: break;
85: default:
86: goto errcom;
87: }
88: if (n==0) n = 10;
89: if(bylines==-1) bylines = 1;
90: if(bkwds) follow=0;
91: if(fromend)
92: goto keep;
93:
94: /*seek from beginning */
95:
96: if(bylines) {
97: j = 0;
98: while(n-->0) {
99: do {
100: if(j--<=0) {
101: p = bin;
102: j = read(0,p,BUFSIZ);
103: if(j--<=0)
104: fexit();
105: }
106: } while(*p++ != '\n');
107: }
108: write(1,p,j);
109: } else if(n>0) {
110: if(!piped)
111: fstat(0,&statb);
112: if(piped||(statb.st_mode&S_IFMT)==S_IFCHR)
113: while(n>0) {
114: i = n>BUFSIZ?BUFSIZ:n;
115: i = read(0,bin,i);
116: if(i<=0)
117: fexit();
118: n -= i;
119: }
120: else
121: lseek(0,n,0);
122: }
123: copy:
124: while((i=read(0,bin,BUFSIZ))>0)
125: write(1,bin,i);
126: fexit();
127:
128: /*seek from end*/
129:
130: keep:
131: if(n <= 0)
132: fexit();
133: if(!piped) {
134: fstat(0,&statb);
135: di = !bylines&&n<LBIN?n:LBIN-1;
136: if(statb.st_size > di)
137: lseek(0,-di,2);
138: if(!bylines)
139: goto copy;
140: }
141: partial = 1;
142: for(;;) {
143: i = 0;
144: do {
145: j = read(0,&bin[i],LBIN-i);
146: if(j<=0)
147: goto brka;
148: i += j;
149: } while(i<LBIN);
150: partial = 0;
151: }
152: brka:
153: if(!bylines) {
154: k =
155: n<=i ? i-n:
156: partial ? 0:
157: n>=LBIN ? i+1:
158: i-n+LBIN;
159: k--;
160: } else {
161: if(bkwds && bin[i==0?LBIN-1:i-1]!='\n'){ /* force trailing newline */
162: bin[i]='\n';
163: if(++i>=LBIN) {i = 0; partial = 0;}
164: }
165: k = i;
166: j = 0;
167: do {
168: lastnl = k;
169: do {
170: if(--k<0) {
171: if(partial) {
172: if(bkwds) write(1,bin,lastnl+1);
173: goto brkb;
174: }
175: k = LBIN -1;
176: }
177: } while(bin[k]!='\n'&&k!=i);
178: if(bkwds && j>0){
179: if(k<lastnl) write(1,&bin[k+1],lastnl-k);
180: else {
181: write(1,&bin[k+1],LBIN-k-1);
182: write(1,bin,lastnl+1);
183: }
184: }
185: } while(j++<n&&k!=i);
186: brkb:
187: if(bkwds) exit(0);
188: if(k==i) do {
189: if(++k>=LBIN)
190: k = 0;
191: } while(bin[k]!='\n'&&k!=i);
192: }
193: if(k<i)
194: write(1,&bin[k+1],i-k-1);
195: else {
196: write(1,&bin[k+1],LBIN-k-1);
197: write(1,bin,i);
198: }
199: fexit();
200: errcom:
201: fprintf(stderr, "usage: tail [+_[n][lbc][rf]] [file]\n");
202: exit(2);
203: }
204:
205: fexit()
206: { register int n;
207: if (!follow || piped) exit(0);
208: for (;;)
209: { sleep(1);
210: while ((n = read (0, bin, BUFSIZ)) > 0)
211: write (1, bin, n);
212: }
213: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.