BSD 3 development
[unix-history] / usr / src / cmd / file.c
CommitLineData
39f31736
BJ
1/*
2 * determine type of file
3 */
4
5#include <sys/param.h>
6#include <sys/stat.h>
7#include <stdio.h>
8#include <ctype.h>
9int in;
10int i = 0;
11char buf[512];
12char *fort[] = {
13 "function","subroutine","common","dimension","block","integer",
14 "real","data","double",0};
15char *asc[] = {
16 "chmk","mov","tst","clr","jmp",0};
17char *c[] = {
18 "int","char","float","double","struct","extern",0};
19char *as[] = {
20 "globl","byte","align","text","data","comm",0};
21int ifile;
22
23main(argc, argv)
24char **argv;
25{
26 FILE *fl;
27 register char *p;
28 char ap[128];
29
30 if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
31 if ((fl = fopen(argv[2], "r")) == NULL) {
32 printf("Can't open %s\n", argv[2]);
33 exit(2);
34 }
35 while ((p = fgets(ap, 128, fl)) != NULL) {
36 int l = strlen(p);
37 if (l>0)
38 p[l-1] = '\0';
39 printf("%s: ", p);
40 type(p);
41 if (ifile>=0)
42 close(ifile);
43 }
44 exit(1);
45 }
46 while(argc > 1) {
47 printf("%s: ", argv[1]);
48 type(argv[1]);
49 argc--;
50 argv++;
51 if (ifile >= 0)
52 close(ifile);
53 }
54}
55
56type(file)
57char *file;
58{
59 int j,nl;
60 char ch;
61 struct stat mbuf;
62
63 ifile = -1;
64 if(stat(file, &mbuf) < 0) {
65 printf("cannot stat\n");
66 return;
67 }
68 switch (mbuf.st_mode & S_IFMT) {
69
70 case S_IFCHR:
71 printf("character");
72 goto spcl;
73
74 case S_IFDIR:
75 printf("directory\n");
76 return;
77
78 case S_IFBLK:
79 printf("block");
80
81spcl:
82 printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev));
83 return;
84 }
85
86 ifile = open(file, 0);
87 if(ifile < 0) {
88 printf("cannot open\n");
89 return;
90 }
91 in = read(ifile, buf, 512);
92 if(in == 0){
93 printf("empty\n");
94 return;
95 }
96 switch(*(int *)buf) {
97
98 case 0413:
99 printf("demand paged ");
100 case 0410:
101 printf("pure ");
102 goto exec;
103
104 case 0412:
105 printf("demand paged ");
106 goto exec;
107
108 case 0411:
109 printf("separate ");
110
111 case 0407:
112exec:
113 printf("executable");
114 if(((int *)buf)[4] != 0)
115 printf(" not stripped");
116 printf("\n");
117 goto out;
118
119 case 0177555:
120 printf("old archive\n");
121 goto out;
122
123 case 0177545:
124 printf("archive\n");
125 goto out;
126 }
127
128 i = 0;
129 if(ccom() == 0)goto notc;
130 while(buf[i] == '#'){
131 j = i;
132 while(buf[i++] != '\n'){
133 if(i - j > 255){
134 printf("data\n");
135 goto out;
136 }
137 if(i >= in)goto notc;
138 }
139 if(ccom() == 0)goto notc;
140 }
141check:
142 if(lookup(c) == 1){
143 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc;
144 printf("c program text");
145 goto outa;
146 }
147 nl = 0;
148 while(buf[i] != '('){
149 if(buf[i] <= 0)
150 goto notas;
151 if(buf[i] == ';'){
152 i++;
153 goto check;
154 }
155 if(buf[i++] == '\n')
156 if(nl++ > 6)goto notc;
157 if(i >= in)goto notc;
158 }
159 while(buf[i] != ')'){
160 if(buf[i++] == '\n')
161 if(nl++ > 6)goto notc;
162 if(i >= in)goto notc;
163 }
164 while(buf[i] != '{'){
165 if(buf[i++] == '\n')
166 if(nl++ > 6)goto notc;
167 if(i >= in)goto notc;
168 }
169 printf("c program text");
170 goto outa;
171notc:
172 i = 0;
173 while(buf[i] == 'c' || buf[i] == '#'){
174 while(buf[i++] != '\n')if(i >= in)goto notfort;
175 }
176 if(lookup(fort) == 1){
177 printf("fortran program text");
178 goto outa;
179 }
180notfort:
181 i=0;
182 if(ascom() == 0)goto notas;
183 j = i-1;
184 if(buf[i] == '.'){
185 i++;
186 if(lookup(as) == 1){
187 printf("assembler program text");
188 goto outa;
189 }
190 else if(buf[j] == '\n' && isalpha(buf[j+2])){
191 printf("roff, nroff, or eqn input text");
192 goto outa;
193 }
194 }
195 while(lookup(asc) == 0){
196 if(ascom() == 0)goto notas;
197 while(buf[i] != '\n' && buf[i++] != ':')
198 if(i >= in)goto notas;
199 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas;
200 j = i-1;
201 if(buf[i] == '.'){
202 i++;
203 if(lookup(as) == 1){
204 printf("assembler program text");
205 goto outa;
206 }
207 else if(buf[j] == '\n' && isalpha(buf[j+2])){
208 printf("roff, nroff, or eqn input text");
209 goto outa;
210 }
211 }
212 }
213 printf("assembler program text");
214 goto outa;
215notas:
216 for(i=0; i < in; i++)if(buf[i]&0200){
217 if (buf[0]=='\100' && buf[1]=='\357') {
218 printf("troff output\n");
219 goto out;
220 }
221 printf("data\n");
222 goto out;
223 }
224 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
225 printf("commands text");
226 else
227 if (english(buf, in))
228 printf("English text");
229 else
230 printf("ascii text");
231outa:
232 while(i < in)
233 if((buf[i++]&0377) > 127){
234 printf(" with garbage\n");
235 goto out;
236 }
237 /* if next few lines in then read whole file looking for nulls ...
238 while((in = read(ifile,buf,512)) > 0)
239 for(i = 0; i < in; i++)
240 if((buf[i]&0377) > 127){
241 printf(" with garbage\n");
242 goto out;
243 }
244 /*.... */
245 printf("\n");
246out:;
247}
248lookup(tab)
249char *tab[];
250{
251 char r;
252 int k,j,l;
253 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++;
254 for(j=0; tab[j] != 0; j++){
255 l=0;
256 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++);
257 if(r == '\0')
258 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t'
259 || buf[k] == '{' || buf[k] == '/'){
260 i=k;
261 return(1);
262 }
263 }
264 return(0);
265}
266ccom(){
267 char cc;
268 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0);
269 if(buf[i] == '/' && buf[i+1] == '*'){
270 i += 2;
271 while(buf[i] != '*' || buf[i+1] != '/'){
272 if(buf[i] == '\\')i += 2;
273 else i++;
274 if(i >= in)return(0);
275 }
276 if((i += 2) >= in)return(0);
277 }
278 if(buf[i] == '\n')if(ccom() == 0)return(0);
279 return(1);
280}
281ascom(){
282 while(buf[i] == '/'){
283 i++;
284 while(buf[i++] != '\n')if(i >= in)return(0);
285 while(buf[i] == '\n')if(i++ >= in)return(0);
286 }
287 return(1);
288}
289
290english (bp, n)
291char *bp;
292{
293# define NASC 128
294 int ct[NASC], j, vow, freq, rare;
295 int badpun = 0, punct = 0;
296 if (n<50) return(0); /* no point in statistics on squibs */
297 for(j=0; j<NASC; j++)
298 ct[j]=0;
299 for(j=0; j<n; j++)
300 {
301 if (bp[j]<NASC)
302 ct[bp[j]|040]++;
303 switch (bp[j])
304 {
305 case '.':
306 case ',':
307 case ')':
308 case '%':
309 case ';':
310 case ':':
311 case '?':
312 punct++;
313 if ( j < n-1 &&
314 bp[j+1] != ' ' &&
315 bp[j+1] != '\n')
316 badpun++;
317 }
318 }
319 if (badpun*5 > punct)
320 return(0);
321 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u'];
322 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n'];
323 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z'];
324 if (2*ct[';'] > ct['e']) return(0);
325 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */
326 return (vow*5 >= n-ct[' '] && freq >= 10*rare);
327}