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