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