|
|
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: */
10: #include <sys/types.h>
11: #include <sys/stat.h>
12: #include <errno.h>
13: #include <pagsiz.h>
14: #define BUFSIZ BSIZE
15: #define LBIN 4097
16: struct stat statb;
17: char bin[LBIN];
18: int errno;
19:
20: main(argc,argv)
21: char **argv;
22: {
23: long n,di;
24: int fromend;
25: register i,j,k;
26: char *p;
27: int partial,piped,bylines;
28: char *arg;
29: lseek(0,(long)0,1);
30: piped = errno==ESPIPE;
31: arg = argv[1];
32: if(argc<=1 || *arg!='-'&&*arg!='+') {
33: arg = "-10l";
34: argc++;
35: argv--;
36: }
37: fromend = *arg=='-';
38: arg++;
39: if(!digit(*arg))
40: goto errcom;
41: n = 0;
42: while(digit(*arg))
43: n = n*10 + *arg++ - '0';
44: if(!fromend&&n>0)
45: n--;
46: if(argc>2) {
47: close(0);
48: if(open(argv[2],0)!=0) {
49: write(2,"tail: can't open ",17);
50: write(2,argv[2],strlen(argv[2]));
51: write(2,"\n",1);
52: exit(1);
53: }
54: }
55: bylines = 0;
56: switch(*arg) {
57: case 'b':
58: n <<= 9;
59: break;
60: case 'c':
61: break;
62: case '\0':
63: case 'l':
64: bylines = 1;
65: break;
66: default:
67: goto errcom;
68: }
69: if(fromend)
70: goto keep;
71:
72: /*seek from beginning */
73:
74: if(bylines) {
75: j = 0;
76: while(n-->0) {
77: do {
78: if(j--<=0) {
79: p = bin;
80: j = read(0,p,BUFSIZ);
81: if(j--<=0) exit(0);
82: }
83: } while(*p++ != '\n');
84: }
85: write(1,p,j);
86: } else if(n>0) {
87: if(!piped)
88: fstat(0,&statb);
89: if(piped||(statb.st_mode&S_IFMT)==S_IFCHR)
90: while(n>0) {
91: i = n>BUFSIZ?BUFSIZ:n;
92: i = read(0,bin,i);
93: if(i<=0) exit(0);
94: n -= i;
95: }
96: else
97: lseek(0,n,0);
98: }
99: while((i=read(0,bin,BUFSIZ))>0)
100: write(1,bin,i);
101: exit(0);
102:
103: /*seek from end*/
104:
105: keep:
106: if(n<=0) exit(0);
107: if(!piped) {
108: fstat(0,&statb);
109: di = !bylines&&n<LBIN?n:LBIN-1;
110: if(statb.st_size > di)
111: lseek(0,-di,2);
112: }
113: partial = 1;
114: for(;;) {
115: i = 0;
116: do {
117: j = read(0,&bin[i],LBIN-i);
118: if(j<=0)
119: goto brka;
120: i += j;
121: } while(i<LBIN);
122: partial = 0;
123: }
124: brka:
125: if(!bylines) {
126: k =
127: n<=i ? i-n:
128: partial ? 0:
129: n>=LBIN ? i+1:
130: i-n+LBIN;
131: k--;
132: } else {
133: k = i;
134: j = 0;
135: do {
136: do {
137: if(--k<0) {
138: if(partial)
139: goto brkb;
140: k = LBIN -1;
141: }
142: } while(bin[k]!='\n'&&k!=i);
143: } while(j++<n&&k!=i);
144: brkb:
145: if(k==i) do {
146: if(++k>=LBIN)
147: k = 0;
148: } while(bin[k]!='\n'&&k!=i);
149: }
150: if(k<i)
151: write(1,&bin[k+1],i-k-1);
152: else {
153: write(1,&bin[k+1],LBIN-k-1);
154: write(1,bin,i);
155: }
156: exit(0);
157: errcom:
158: write(2,"usage: tail +_n[lbc] [file]\n",29);
159: exit(1);
160: }
161:
162: digit(c)
163: {
164: return(c>='0'&&c<='9');
165: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.