|
|
1.1 root 1: static char *sccsid = "@(#)tail.c 4.4 (Berkeley) 8/22/83";
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: arg = argv[1];
40: if(argc<=1 || *arg!='-'&&*arg!='+') {
41: arg = "-10l";
42: argc++;
43: argv--;
44: }
45: fromend = *arg=='-';
46: arg++;
47: if (isdigit(*arg)) {
48: n = 0;
49: while(isdigit(*arg))
50: n = n*10 + *arg++ - '0';
51: } else
52: n = -1;
53: if(!fromend&&n>0)
54: n--;
55: if(argc>2) {
56: close(0);
57: if(open(argv[2],0)!=0) {
58: perror(argv[2]);
59: exit(1);
60: }
61: }
62: lseek(0,(long)0,1);
63: piped = errno==ESPIPE;
64: bylines = -1; bkwds = 0;
65: while(*arg)
66: switch(*arg++) {
67:
68: case 'b':
69: n <<= 9;
70: if(bylines!=-1) goto errcom;
71: bylines=0;
72: break;
73: case 'c':
74: if(bylines!=-1) goto errcom;
75: bylines=0;
76: break;
77: case 'f':
78: follow = 1;
79: break;
80: case 'r':
81: if(n==-1) n = LBIN;
82: bkwds = 1; fromend = 1; bylines = 1;
83: break;
84: case 'l':
85: if(bylines!=-1) goto errcom;
86: bylines = 1;
87: break;
88: default:
89: goto errcom;
90: }
91: if (n==-1) n = 10;
92: if(bylines==-1) bylines = 1;
93: if(bkwds) follow=0;
94: if(fromend)
95: goto keep;
96:
97: /*seek from beginning */
98:
99: if(bylines) {
100: j = 0;
101: while(n-->0) {
102: do {
103: if(j--<=0) {
104: p = bin;
105: j = read(0,p,BUFSIZ);
106: if(j--<=0)
107: fexit();
108: }
109: } while(*p++ != '\n');
110: }
111: write(1,p,j);
112: } else if(n>0) {
113: if(!piped)
114: fstat(0,&statb);
115: if(piped||(statb.st_mode&S_IFMT)==S_IFCHR)
116: while(n>0) {
117: i = n>BUFSIZ?BUFSIZ:n;
118: i = read(0,bin,i);
119: if(i<=0)
120: fexit();
121: n -= i;
122: }
123: else
124: lseek(0,n,0);
125: }
126: copy:
127: while((i=read(0,bin,BUFSIZ))>0)
128: write(1,bin,i);
129: fexit();
130:
131: /*seek from end*/
132:
133: keep:
134: if(n <= 0)
135: fexit();
136: if(!piped) {
137: fstat(0,&statb);
138: di = !bylines&&n<LBIN?n:LBIN-1;
139: if(statb.st_size > di)
140: lseek(0,-di,2);
141: if(!bylines)
142: goto copy;
143: }
144: partial = 1;
145: for(;;) {
146: i = 0;
147: do {
148: j = read(0,&bin[i],LBIN-i);
149: if(j<=0)
150: goto brka;
151: i += j;
152: } while(i<LBIN);
153: partial = 0;
154: }
155: brka:
156: if(!bylines) {
157: k =
158: n<=i ? i-n:
159: partial ? 0:
160: n>=LBIN ? i+1:
161: i-n+LBIN;
162: k--;
163: } else {
164: if(bkwds && bin[i==0?LBIN-1:i-1]!='\n'){ /* force trailing newline */
165: bin[i]='\n';
166: if(++i>=LBIN) {i = 0; partial = 0;}
167: }
168: k = i;
169: j = 0;
170: do {
171: lastnl = k;
172: do {
173: if(--k<0) {
174: if(partial) {
175: if(bkwds) write(1,bin,lastnl+1);
176: goto brkb;
177: }
178: k = LBIN -1;
179: }
180: } while(bin[k]!='\n'&&k!=i);
181: if(bkwds && j>0){
182: if(k<lastnl) write(1,&bin[k+1],lastnl-k);
183: else {
184: write(1,&bin[k+1],LBIN-k-1);
185: write(1,bin,lastnl+1);
186: }
187: }
188: } while(j++<n&&k!=i);
189: brkb:
190: if(bkwds) exit(0);
191: if(k==i) do {
192: if(++k>=LBIN)
193: k = 0;
194: } while(bin[k]!='\n'&&k!=i);
195: }
196: if(k<i)
197: write(1,&bin[k+1],i-k-1);
198: else {
199: write(1,&bin[k+1],LBIN-k-1);
200: write(1,bin,i);
201: }
202: fexit();
203: errcom:
204: fprintf(stderr, "usage: tail [+_[n][lbc][rf]] [file]\n");
205: exit(2);
206: }
207:
208: fexit()
209: { register int n;
210: if (!follow || piped) exit(0);
211: for (;;)
212: { sleep(1);
213: while ((n = read (0, bin, BUFSIZ)) > 0)
214: write (1, bin, n);
215: }
216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.