Bell 32V development
[unix-history] / usr / src / cmd / tail.c
CommitLineData
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
14struct stat statb;
15char bin[LBIN];
16int errno;
17
18main(argc,argv)
19char **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
103keep:
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 }
122brka:
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);
142brkb:
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);
155errcom:
156 write(2,"usage: tail +\b_n[lbc] [file]\n",29);
157 exit(1);
158}
159
160digit(c)
161{
162 return(c>='0'&&c<='9');
163}