date and time created 83/02/11 15:45:08 by rrh
[unix-history] / usr / src / usr.bin / file / file.c
CommitLineData
2db3d63d 1static char sccsid[] = "@(#)file.c 4.4 (Berkeley) 4.4";
fd2fc6c6
BJ
2/*
3 * file - determine type of file
4 */
5
6#include <pagsiz.h>
7#include <sys/types.h>
8#include <stat.h>
9#include <stdio.h>
10#include <ctype.h>
75ea79ff 11#include <a.out.h>
fd2fc6c6
BJ
12int in;
13int i = 0;
14char buf[BUFSIZ];
15char *troff[] = { /* new troff intermediate lang */
16 "x","T","res","init","font","202","V0","p1",0};
17char *fort[] = {
18 "function","subroutine","common","dimension","block","integer",
19 "real","data","double",0};
20char *asc[] = {
21 "chmk","mov","tst","clr","jmp",0};
22char *c[] = {
23 "int","char","float","double","struct","extern",0};
24char *as[] = {
25 "globl","byte","align","text","data","comm",0};
26int ifile;
27
28main(argc, argv)
29char **argv;
30{
31 FILE *fl;
32 register char *p;
33 char ap[128];
34 extern char _sobuf[];
35
36 if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
37 if ((fl = fopen(argv[2], "r")) == NULL) {
38 printf("Can't open %s\n", argv[2]);
39 exit(2);
40 }
41 while ((p = fgets(ap, 128, fl)) != NULL) {
42 int l = strlen(p);
43 if (l>0)
44 p[l-1] = '\0';
45 printf("%s: ", p);
46 type(p);
47 if (ifile>=0)
48 close(ifile);
49 }
50 exit(1);
51 }
52 while(argc > 1) {
53 printf("%s: ", argv[1]);
54 type(argv[1]);
55 fflush(stdout);
56 argc--;
57 argv++;
58 if (ifile >= 0)
59 close(ifile);
60 }
61}
62
63type(file)
64char *file;
65{
66 int j,nl;
67 char ch;
68 struct stat mbuf;
69
70 ifile = -1;
2db3d63d 71 if (lstat(file, &mbuf) < 0) {
fd2fc6c6
BJ
72 printf("cannot stat\n");
73 return;
74 }
75 switch (mbuf.st_mode & S_IFMT) {
76
77 case S_IFCHR:
78 printf("character");
79 goto spcl;
80
2db3d63d
KM
81 case S_IFLNK:
82 printf("symbolic link\n");
fd2fc6c6
BJ
83 return;
84
2db3d63d
KM
85 case S_IFDIR:
86 printf("directory\n");
fd2fc6c6
BJ
87 return;
88
89 case S_IFBLK:
90 printf("block");
91
92spcl:
93 printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev));
94 return;
95 }
96
97 ifile = open(file, 0);
98 if(ifile < 0) {
99 printf("cannot open\n");
100 return;
101 }
102 in = read(ifile, buf, BUFSIZ);
103 if(in == 0){
104 printf("empty\n");
105 return;
106 }
107 switch(*(int *)buf) {
108
109 case 0413:
110 printf("demand paged ");
111
112 case 0410:
113 printf("pure ");
114 goto exec;
115
116 case 0411:
117 printf("jfr or pdp-11 unix 411 executable\n");
118 return;
119
120 case 0407:
121exec:
122 printf("executable");
123 if(((int *)buf)[4] != 0) {
124 printf(" not stripped");
125 if(oldo(buf))
126 printf(" (old format symbol table)");
127 }
128 printf("\n");
129 goto out;
130
131 case 0177555:
132 printf("very old archive\n");
133 goto out;
134
135 case 0177545:
136 printf("old archive\n");
137 goto out;
c083f459
BJ
138
139 case 070707:
140 printf("cpio data\n");
141 goto out;
fd2fc6c6
BJ
142 }
143
144 if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) {
145 printf("archive random library\n");
146 goto out;
147 }
148 if (strncmp(buf, "!<arch>\n", 8)==0) {
149 printf("archive\n");
150 goto out;
151 }
47aeb93c
BJ
152 if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */
153 lseek(ifile, -512L, 2); /* last block */
154 if (read(ifile, buf, BUFSIZ) > 0
155 && *(short int *)buf == 12138) {
156 printf("PRESS file\n");
157 goto out;
158 }
159 }
fd2fc6c6
BJ
160 i = 0;
161 if(ccom() == 0)goto notc;
162 while(buf[i] == '#'){
163 j = i;
164 while(buf[i++] != '\n'){
165 if(i - j > 255){
166 printf("data\n");
167 goto out;
168 }
169 if(i >= in)goto notc;
170 }
171 if(ccom() == 0)goto notc;
172 }
173check:
174 if(lookup(c) == 1){
175 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc;
176 printf("c program text");
177 goto outa;
178 }
179 nl = 0;
180 while(buf[i] != '('){
181 if(buf[i] <= 0)
182 goto notas;
183 if(buf[i] == ';'){
184 i++;
185 goto check;
186 }
187 if(buf[i++] == '\n')
188 if(nl++ > 6)goto notc;
189 if(i >= in)goto notc;
190 }
191 while(buf[i] != ')'){
192 if(buf[i++] == '\n')
193 if(nl++ > 6)goto notc;
194 if(i >= in)goto notc;
195 }
196 while(buf[i] != '{'){
197 if(buf[i++] == '\n')
198 if(nl++ > 6)goto notc;
199 if(i >= in)goto notc;
200 }
201 printf("c program text");
202 goto outa;
203notc:
204 i = 0;
205 while(buf[i] == 'c' || buf[i] == '#'){
206 while(buf[i++] != '\n')if(i >= in)goto notfort;
207 }
208 if(lookup(fort) == 1){
209 printf("fortran program text");
210 goto outa;
211 }
212notfort:
213 i=0;
214 if(ascom() == 0)goto notas;
215 j = i-1;
216 if(buf[i] == '.'){
217 i++;
218 if(lookup(as) == 1){
219 printf("assembler program text");
220 goto outa;
221 }
222 else if(buf[j] == '\n' && isalpha(buf[j+2])){
223 printf("roff, nroff, or eqn input text");
224 goto outa;
225 }
226 }
227 while(lookup(asc) == 0){
228 if(ascom() == 0)goto notas;
229 while(buf[i] != '\n' && buf[i++] != ':')
230 if(i >= in)goto notas;
231 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas;
232 j = i-1;
233 if(buf[i] == '.'){
234 i++;
235 if(lookup(as) == 1){
236 printf("assembler program text");
237 goto outa;
238 }
239 else if(buf[j] == '\n' && isalpha(buf[j+2])){
240 printf("roff, nroff, or eqn input text");
241 goto outa;
242 }
243 }
244 }
245 printf("assembler program text");
246 goto outa;
247notas:
248 for(i=0; i < in; i++)if(buf[i]&0200){
249 if (buf[0]=='\100' && buf[1]=='\357') {
250 printf("troff (CAT) output\n");
251 goto out;
252 }
253 printf("data\n");
254 goto out;
255 }
256 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
257 printf("commands text");
258 else if (troffint(buf, in))
259 printf("troff intermediate output text");
260 else if (english(buf, in))
261 printf("English text");
262 else
263 printf("ascii text");
264outa:
265 while(i < in)
266 if((buf[i++]&0377) > 127){
267 printf(" with garbage\n");
268 goto out;
269 }
270 /* if next few lines in then read whole file looking for nulls ...
271 while((in = read(ifile,buf,BUFSIZ)) > 0)
272 for(i = 0; i < in; i++)
273 if((buf[i]&0377) > 127){
274 printf(" with garbage\n");
275 goto out;
276 }
277 /*.... */
278 printf("\n");
279out:;
280}
281
282oldo(cp)
283char *cp;
284{
285 struct exec ex;
286 struct stat stb;
287
288 ex = *(struct exec *)cp;
289 if (fstat(ifile, &stb) < 0)
290 return(0);
291 if (N_STROFF(ex)+sizeof(off_t) > stb.st_size)
292 return (1);
293 return (0);
294}
295
296
297
298troffint(bp, n)
299char *bp;
300int n;
301{
302 int k;
303
304 i = 0;
305 for (k = 0; k < 6; k++) {
306 if (lookup(troff) == 0)
307 return(0);
308 if (lookup(troff) == 0)
309 return(0);
310 while (i < n && buf[i] != '\n')
311 i++;
312 if (i++ >= n)
313 return(0);
314 }
315 return(1);
316}
317lookup(tab)
318char *tab[];
319{
320 char r;
321 int k,j,l;
322 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++;
323 for(j=0; tab[j] != 0; j++){
324 l=0;
325 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++);
326 if(r == '\0')
327 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t'
328 || buf[k] == '{' || buf[k] == '/'){
329 i=k;
330 return(1);
331 }
332 }
333 return(0);
334}
335ccom(){
336 char cc;
337 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0);
338 if(buf[i] == '/' && buf[i+1] == '*'){
339 i += 2;
340 while(buf[i] != '*' || buf[i+1] != '/'){
341 if(buf[i] == '\\')i += 2;
342 else i++;
343 if(i >= in)return(0);
344 }
345 if((i += 2) >= in)return(0);
346 }
347 if(buf[i] == '\n')if(ccom() == 0)return(0);
348 return(1);
349}
350ascom(){
351 while(buf[i] == '/'){
352 i++;
353 while(buf[i++] != '\n')if(i >= in)return(0);
354 while(buf[i] == '\n')if(i++ >= in)return(0);
355 }
356 return(1);
357}
358
359english (bp, n)
360char *bp;
361{
362# define NASC 128
363 int ct[NASC], j, vow, freq, rare;
364 int badpun = 0, punct = 0;
365 if (n<50) return(0); /* no point in statistics on squibs */
366 for(j=0; j<NASC; j++)
367 ct[j]=0;
368 for(j=0; j<n; j++)
369 {
370 if (bp[j]<NASC)
371 ct[bp[j]|040]++;
372 switch (bp[j])
373 {
374 case '.':
375 case ',':
376 case ')':
377 case '%':
378 case ';':
379 case ':':
380 case '?':
381 punct++;
382 if ( j < n-1 &&
383 bp[j+1] != ' ' &&
384 bp[j+1] != '\n')
385 badpun++;
386 }
387 }
388 if (badpun*5 > punct)
389 return(0);
390 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u'];
391 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n'];
392 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z'];
393 if (2*ct[';'] > ct['e']) return(0);
394 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */
395 return (vow*5 >= n-ct[' '] && freq >= 10*rare);
396}