|
|
1.1 root 1: #ifndef lint
2: static char sccsid[] = "@(#)file.c 4.15 (Berkeley) 6/1/88";
3: #endif
4: /*
5: * file - determine type of file
6: */
7:
8: #include <sys/param.h>
9: #include <sys/stat.h>
10: #include <stdio.h>
11: #include <ctype.h>
12: #include <a.out.h>
13:
14: extern int errno;
15: extern int sys_nerr;
16: extern char *sys_errlist[];
17:
18: int in;
19: int i = 0;
20: char buf[BUFSIZ];
21: char *troff[] = { /* new troff intermediate lang */
22: "x","T","res","init","font","202","V0","p1",0};
23: char *fort[] = {
24: "function","subroutine","common","dimension","block","integer",
25: "real","data","double",0};
26: char *asc[] = {
27: "chmk","mov","tst","clr","jmp",0};
28: char *c[] = {
29: "int","char","float","double","struct","extern",0};
30: char *as[] = {
31: "globl","byte","align","text","data","comm",0};
32: char *sh[] = {
33: "fi", "elif", "esac", "done", "export",
34: "readonly", "trap", "PATH", "HOME", 0 };
35: char *csh[] = {
36: "alias", "breaksw", "endsw", "foreach", "limit", "onintr",
37: "repeat", "setenv", "source", "path", "home", 0 };
38: int ifile;
39:
40: main(argc, argv)
41: char **argv;
42: {
43: FILE *fl;
44: register char *p;
45: char ap[MAXPATHLEN + 1];
46:
47: if (argc < 2) {
48: fprintf(stderr, "usage: %s file ...\n", argv[0]);
49: exit(3);
50: }
51:
52: if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
53: if ((fl = fopen(argv[2], "r")) == NULL) {
54: perror(argv[2]);
55: exit(2);
56: }
57: while ((p = fgets(ap, sizeof ap, fl)) != NULL) {
58: int l = strlen(p);
59: if (l>0)
60: p[l-1] = '\0';
61: printf("%s: ", p);
62: type(p);
63: if (ifile>=0)
64: close(ifile);
65: }
66: exit(1);
67: }
68: while(argc > 1) {
69: printf("%s: ", argv[1]);
70: type(argv[1]);
71: fflush(stdout);
72: argc--;
73: argv++;
74: if (ifile >= 0)
75: close(ifile);
76: }
77: exit(0);
78: }
79:
80: type(file)
81: char *file;
82: {
83: int j,nl;
84: char ch;
85: struct stat mbuf;
86: char slink[MAXPATHLEN + 1];
87:
88: ifile = -1;
89: if (lstat(file, &mbuf) < 0) {
90: printf("%s\n",
91: (unsigned)errno < sys_nerr? sys_errlist[errno]: "Cannot stat");
92: return;
93: }
94: switch (mbuf.st_mode & S_IFMT) {
95:
96: case S_IFLNK:
97: printf("symbolic link");
98: j = readlink(file, slink, sizeof slink - 1);
99: if (j >= 0) {
100: slink[j] = '\0';
101: printf(" to %s", slink);
102: }
103: printf("\n");
104: return;
105:
106: case S_IFDIR:
107: if (mbuf.st_mode & S_ISVTX)
108: printf("append-only ");
109: printf("directory\n");
110: return;
111:
112: case S_IFCHR:
113: case S_IFBLK:
114: printf("%s special (%d/%d)\n",
115: (mbuf.st_mode&S_IFMT) == S_IFCHR ? "character" : "block",
116: major(mbuf.st_rdev), minor(mbuf.st_rdev));
117: return;
118:
119: case S_IFSOCK:
120: printf("socket\n");
121: return;
122: }
123:
124: ifile = open(file, 0);
125: if(ifile < 0) {
126: printf("%s\n",
127: (unsigned)errno < sys_nerr? sys_errlist[errno]: "Cannot read");
128: return;
129: }
130: in = read(ifile, buf, BUFSIZ);
131: if(in == 0){
132: printf("empty\n");
133: return;
134: }
135: switch(*(int *)buf) {
136:
137: case 0413:
138: printf("demand paged ");
139:
140: case 0410:
141: printf("pure ");
142: goto exec;
143:
144: case 0411:
145: printf("jfr or pdp-11 unix 411 executable\n");
146: return;
147:
148: case 0407:
149: exec:
150: if (mbuf.st_mode & S_ISUID)
151: printf("set-uid ");
152: if (mbuf.st_mode & S_ISGID)
153: printf("set-gid ");
154: if (mbuf.st_mode & S_ISVTX)
155: printf("sticky ");
156: printf("executable");
157: if(((int *)buf)[4] != 0) {
158: printf(" not stripped");
159: if(oldo(buf))
160: printf(" (old format symbol table)");
161: }
162: printf("\n");
163: return;
164:
165: case 0177555:
166: printf("very old archive\n");
167: return;
168:
169: case 0177545:
170: printf("old archive\n");
171: return;
172:
173: case 070707:
174: printf("cpio data\n");
175: return;
176: }
177:
178: if (buf[0] == '#' && buf[1] == '!' && shellscript(buf+2, &mbuf))
179: return;
180: if (buf[0] == '\037' && buf[1] == '\235') {
181: if (buf[2]&0x80)
182: printf("block ");
183: printf("compressed %d bit code data\n", buf[2]&0x1f);
184: return;
185: }
186: if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) {
187: printf("archive random library\n");
188: return;
189: }
190: if (strncmp(buf, "!<arch>\n", 8)==0) {
191: printf("archive\n");
192: return;
193: }
194: if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */
195: lseek(ifile, -512L, 2); /* last block */
196: if (read(ifile, buf, BUFSIZ) > 0 && *(short *)buf == 12138) {
197: printf("PRESS file\n");
198: return;
199: }
200: }
201: i = 0;
202: if(ccom() == 0)goto notc;
203: while(buf[i] == '#'){
204: j = i;
205: while(buf[i++] != '\n'){
206: if(i - j > 255){
207: printf("data\n");
208: return;
209: }
210: if(i >= in)goto notc;
211: }
212: if(ccom() == 0)goto notc;
213: }
214: check:
215: if(lookup(c) == 1){
216: while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc;
217: printf("c program text");
218: goto outa;
219: }
220: nl = 0;
221: while(buf[i] != '('){
222: if(buf[i] <= 0)
223: goto notas;
224: if(buf[i] == ';'){
225: i++;
226: goto check;
227: }
228: if(buf[i++] == '\n')
229: if(nl++ > 6)goto notc;
230: if(i >= in)goto notc;
231: }
232: while(buf[i] != ')'){
233: if(buf[i++] == '\n')
234: if(nl++ > 6)goto notc;
235: if(i >= in)goto notc;
236: }
237: while(buf[i] != '{'){
238: if(buf[i++] == '\n')
239: if(nl++ > 6)goto notc;
240: if(i >= in)goto notc;
241: }
242: printf("c program text");
243: goto outa;
244: notc:
245: i = 0;
246: while(buf[i] == 'c' || buf[i] == '#'){
247: while(buf[i++] != '\n')if(i >= in)goto notfort;
248: }
249: if(lookup(fort) == 1){
250: printf("fortran program text");
251: goto outa;
252: }
253: notfort:
254: i=0;
255: if(ascom() == 0)goto notas;
256: j = i-1;
257: if(buf[i] == '.'){
258: i++;
259: if(lookup(as) == 1){
260: printf("assembler program text");
261: goto outa;
262: }
263: else if(buf[j] == '\n' && isalpha(buf[j+2])){
264: printf("roff, nroff, or eqn input text");
265: goto outa;
266: }
267: }
268: while(lookup(asc) == 0){
269: if(ascom() == 0)goto notas;
270: while(buf[i] != '\n' && buf[i++] != ':')
271: if(i >= in)goto notas;
272: while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas;
273: j = i-1;
274: if(buf[i] == '.'){
275: i++;
276: if(lookup(as) == 1){
277: printf("assembler program text");
278: goto outa;
279: }
280: else if(buf[j] == '\n' && isalpha(buf[j+2])){
281: printf("roff, nroff, or eqn input text");
282: goto outa;
283: }
284: }
285: }
286: printf("assembler program text");
287: goto outa;
288: notas:
289: for(i=0; i < in; i++)if(buf[i]&0200){
290: if (buf[0]=='\100' && buf[1]=='\357')
291: printf("troff (CAT) output\n");
292: else
293: printf("data\n");
294: return;
295: }
296: if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) {
297: if (mbuf.st_mode & S_ISUID)
298: printf("set-uid ");
299: if (mbuf.st_mode & S_ISGID)
300: printf("set-gid ");
301: if (mbuf.st_mode & S_ISVTX)
302: printf("sticky ");
303: if (shell(buf, in, sh))
304: printf("shell script");
305: else if (shell(buf, in, csh))
306: printf("c-shell script");
307: else
308: printf("commands text");
309: } else if (troffint(buf, in))
310: printf("troff intermediate output text");
311: else if (shell(buf, in, sh))
312: printf("shell commands");
313: else if (shell(buf, in, csh))
314: printf("c-shell commands");
315: else if (english(buf, in))
316: printf("English text");
317: else
318: printf("ascii text");
319: outa:
320: while(i < in)
321: if((buf[i++]&0377) > 127){
322: printf(" with garbage\n");
323: return;
324: }
325: /* if next few lines in then read whole file looking for nulls ...
326: while((in = read(ifile,buf,BUFSIZ)) > 0)
327: for(i = 0; i < in; i++)
328: if((buf[i]&0377) > 127){
329: printf(" with garbage\n");
330: return;
331: }
332: /*.... */
333: printf("\n");
334: }
335:
336: oldo(cp)
337: char *cp;
338: {
339: struct exec ex;
340: struct stat stb;
341:
342: ex = *(struct exec *)cp;
343: if (fstat(ifile, &stb) < 0)
344: return(0);
345: if (N_STROFF(ex)+sizeof(off_t) > stb.st_size)
346: return (1);
347: return (0);
348: }
349:
350:
351:
352: troffint(bp, n)
353: char *bp;
354: int n;
355: {
356: int k;
357:
358: i = 0;
359: for (k = 0; k < 6; k++) {
360: if (lookup(troff) == 0)
361: return(0);
362: if (lookup(troff) == 0)
363: return(0);
364: while (i < n && buf[i] != '\n')
365: i++;
366: if (i++ >= n)
367: return(0);
368: }
369: return(1);
370: }
371: lookup(tab)
372: char *tab[];
373: {
374: char r;
375: int k,j,l;
376: while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++;
377: for(j=0; tab[j] != 0; j++){
378: l=0;
379: for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++);
380: if(r == '\0')
381: if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t'
382: || buf[k] == '{' || buf[k] == '/'){
383: i=k;
384: return(1);
385: }
386: }
387: return(0);
388: }
389: ccom(){
390: char cc;
391: while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0);
392: if(buf[i] == '/' && buf[i+1] == '*'){
393: i += 2;
394: while(buf[i] != '*' || buf[i+1] != '/'){
395: if(buf[i] == '\\')i += 2;
396: else i++;
397: if(i >= in)return(0);
398: }
399: if((i += 2) >= in)return(0);
400: }
401: if(buf[i] == '\n')if(ccom() == 0)return(0);
402: return(1);
403: }
404: ascom(){
405: while(buf[i] == '/'){
406: i++;
407: while(buf[i++] != '\n')if(i >= in)return(0);
408: while(buf[i] == '\n')if(i++ >= in)return(0);
409: }
410: return(1);
411: }
412:
413: english (bp, n)
414: char *bp;
415: {
416: # define NASC 128
417: int ct[NASC], j, vow, freq, rare;
418: int badpun = 0, punct = 0;
419: if (n<50) return(0); /* no point in statistics on squibs */
420: for(j=0; j<NASC; j++)
421: ct[j]=0;
422: for(j=0; j<n; j++)
423: {
424: if ((u_char)bp[j]<NASC)
425: ct[bp[j]|040]++;
426: switch (bp[j])
427: {
428: case '.':
429: case ',':
430: case ')':
431: case '%':
432: case ';':
433: case ':':
434: case '?':
435: punct++;
436: if ( j < n-1 &&
437: bp[j+1] != ' ' &&
438: bp[j+1] != '\n')
439: badpun++;
440: }
441: }
442: if (badpun*5 > punct)
443: return(0);
444: vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u'];
445: freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n'];
446: rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z'];
447: if (2*ct[';'] > ct['e']) return(0);
448: if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */
449: return (vow*5 >= n-ct[' '] && freq >= 10*rare);
450: }
451:
452: shellscript(buf, sb)
453: char buf[];
454: struct stat *sb;
455: {
456: register char *tp;
457: char *cp, *xp, *index();
458:
459: cp = index(buf, '\n');
460: if (cp == 0 || cp - buf > in)
461: return (0);
462: for (tp = buf; tp != cp && isspace(*tp); tp++)
463: if (!isascii(*tp))
464: return (0);
465: for (xp = tp; tp != cp && !isspace(*tp); tp++)
466: if (!isascii(*tp))
467: return (0);
468: if (tp == xp)
469: return (0);
470: if (sb->st_mode & S_ISUID)
471: printf("set-uid ");
472: if (sb->st_mode & S_ISGID)
473: printf("set-gid ");
474: if (strncmp(xp, "/bin/sh", tp-xp) == 0)
475: xp = "shell";
476: else if (strncmp(xp, "/bin/csh", tp-xp) == 0)
477: xp = "c-shell";
478: else
479: *tp = '\0';
480: printf("executable %s script\n", xp);
481: return (1);
482: }
483:
484: shell(bp, n, tab)
485: char *bp;
486: int n;
487: char *tab[];
488: {
489:
490: i = 0;
491: do {
492: if (buf[i] == '#' || buf[i] == ':')
493: while (i < n && buf[i] != '\n')
494: i++;
495: if (++i >= n)
496: break;
497: if (lookup(tab) == 1)
498: return (1);
499: } while (i < n);
500: return (0);
501: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.