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