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