|
|
1.1 ! root 1: char _version[] = "Version 1.5"; ! 2: /* ! 3: * Look at a file and try to ! 4: * figure out its type. Knows about the various ! 5: * flavours of filesystem entries, object files of various ! 6: * types, C programs, input to one of the various flavours ! 7: * of text formatter, etc. ! 8: */ ! 9: #include <stdio.h> ! 10: #include <sys/coherent.h> ! 11: #include <ctype.h> ! 12: #include <sys/stat.h> ! 13: #include <sys/uproc.h> ! 14: #include <n.out.h> ! 15: #include <coff.h> ! 16: #include <canon.h> ! 17: #include <ar.h> ! 18: #include <arcoff.h> ! 19: #include <sys/core.h> ! 20: ! 21: /* UNIX archive magic numbers */ ! 22: #define COFFARMAG "!<arch>\n" ! 23: #define COFFARMAG_RAN "!<arch>\n/" ! 24: #define UARMAG 0177545 /* UNIX v7 archives */ ! 25: #define OUARMAG 0177555 /* UNIX v6 and previous archives */ ! 26: ! 27: #define TYPE_LEN 120 ! 28: ! 29: #define COMPRESSED 0x9D1F /* Output of "compress(1)" command. */ ! 30: ! 31: #define EXEC (S_IEXEC|(S_IEXEC<<3)|(S_IEXEC<<6)) ! 32: ! 33: /* ! 34: * Tar header. ! 35: */ ! 36: struct th_info { ! 37: char th_name[100], ! 38: th_mode[8], ! 39: th_uid[8], ! 40: th_gid[8], ! 41: th_size[12], ! 42: th_mtime[12], ! 43: th_check[8], ! 44: th_islink, ! 45: th_link[100], ! 46: th_pad[255]; ! 47: }; ! 48: ! 49: /* ! 50: * The first BUFSIZ bytes of the ! 51: * file in question are read into this ! 52: * union. It contains members for accessing ! 53: * the possible file structures. ! 54: */ ! 55: ! 56: union iobuf ! 57: { ! 58: char u_buf[BUFSIZ]; /* General data */ ! 59: struct ldheader u_lout; /* L.out object file header */ ! 60: struct filehdr u_coff; /* COFF object file header */ ! 61: int u_armag; /* Archive number */ ! 62: struct th_info u_tar; /* Tar header */ ! 63: struct ch_info u_core; /* Core header */ ! 64: }; ! 65: ! 66: UPROC uProc; ! 67: ! 68: union iobuf iobuf; ! 69: char *file(); ! 70: char *textclass(); ! 71: char *objclass(); ! 72: char *coffclass(); ! 73: char *dirtype(); ! 74: char *mtype(); ! 75: char *coffmtype(); ! 76: char *strcat(); ! 77: ! 78: main(argc, argv) ! 79: char *argv[]; ! 80: { ! 81: struct stat sb; ! 82: register char *p; ! 83: register int i; ! 84: register int estat; ! 85: ! 86: if (argc < 2) { ! 87: fprintf(stderr, "Usage: file name ...\n"); ! 88: exit(1); ! 89: } ! 90: estat = 0; ! 91: for (i=1; i<argc; i++) { ! 92: p = argv[i]; ! 93: if (stat(p, &sb) < 0) { ! 94: fprintf(stderr, "file: %s: not accessible\n", p); ! 95: estat = 1; ! 96: continue; ! 97: } ! 98: printf("%s: %s\n", p, file(&sb, p)); ! 99: } ! 100: exit(estat); ! 101: } ! 102: ! 103: /* ! 104: * Routine to guess filetype ! 105: */ ! 106: char * ! 107: file(sbp, fn) ! 108: struct stat *sbp; ! 109: char *fn; ! 110: { ! 111: static char buf[50]; ! 112: unsigned short magic; ! 113: register int nb; ! 114: char type[TYPE_LEN]; ! 115: register int fd = -1; ! 116: ! 117: if ((sbp->st_mode&S_IFMT) != S_IFREG) { ! 118: switch (sbp->st_mode & S_IFMT) { ! 119: case S_IFDIR: ! 120: return (dirtype(fn)); ! 121: ! 122: case S_IFBLK: ! 123: sprintf(buf, "block special file %d/%d", ! 124: major(sbp->st_rdev), minor(sbp->st_rdev)); ! 125: return (buf); ! 126: ! 127: case S_IFCHR: ! 128: sprintf(buf, "character special file %d/%d", ! 129: major(sbp->st_rdev), minor(sbp->st_rdev)); ! 130: return (buf); ! 131: ! 132: case S_IFMPB: ! 133: return ("block multiplexor file"); ! 134: ! 135: case S_IFMPC: ! 136: return ("character multiplexor file"); ! 137: ! 138: case S_IFPIP: ! 139: return ("named pipe"); ! 140: ! 141: default: ! 142: return ("invalid filetype"); ! 143: } ! 144: } ! 145: if ((fd = open(fn, 0)) < 0) ! 146: return ("unreadable"); ! 147: if ((nb = read(fd, (char *) &iobuf, sizeof(iobuf))) < 0) { ! 148: extern int errno; ! 149: printf("nb: %d, errno: %d ", nb, errno ); ! 150: close(fd); ! 151: return ("read error"); ! 152: } ! 153: ! 154: /* file of length zero? */ ! 155: if (nb == 0) { ! 156: close(fd); ! 157: return ("empty"); ! 158: } ! 159: ! 160: /* l.out executable? */ ! 161: if (nb >= sizeof(struct ldheader)) { ! 162: magic = iobuf.u_lout.l_magic; ! 163: canint(magic); ! 164: if (magic == L_MAGIC) { ! 165: canint(iobuf.u_lout.l_flag); ! 166: canint(iobuf.u_lout.l_machine); ! 167: close(fd); ! 168: return (objclass(fd, &iobuf.u_lout)); ! 169: } ! 170: } ! 171: ! 172: /* COFF executable? */ ! 173: if (nb >= sizeof(struct filehdr)) { ! 174: magic = iobuf.u_coff.f_magic; ! 175: if (ISCOFF(magic)) { ! 176: close(fd); ! 177: return (coffclass(&iobuf.u_coff)); ! 178: } ! 179: } ! 180: ! 181: /* COFF archive? */ ! 182: if (nb >= strlen(COFFARMAG_RAN)) { ! 183: if (strncmp(COFFARMAG_RAN, iobuf.u_buf, ! 184: strlen(COFFARMAG_RAN)) == 0) { ! 185: close(fd); ! 186: return("COFF archive (ranlib)"); ! 187: } ! 188: if ( strncmp(COFFARMAG, iobuf.u_buf, strlen(COFFARMAG)) == 0) { ! 189: close(fd); ! 190: return("COFF archive"); ! 191: } ! 192: } ! 193: ! 194: /* {v7 tar} archive? */ ! 195: if (nb >= sizeof(struct th_info)) { ! 196: if ( tar_path(iobuf.u_tar.th_name, 100) && ! 197: tar_oct(iobuf.u_tar.th_mode, 8) && ! 198: tar_dec(iobuf.u_tar.th_uid, 8) && ! 199: tar_dec(iobuf.u_tar.th_gid, 8) && ! 200: tar_dec(iobuf.u_tar.th_size, 12) && ! 201: tar_dec(iobuf.u_tar.th_mtime, 12) && ! 202: strlen(iobuf.u_tar.th_pad) < 8 ) { ! 203: ! 204: type[0] ='\0'; ! 205: if ( '\0' != iobuf.u_tar.th_pad[0]) { ! 206: strcpy(type, iobuf.u_tar.th_pad); ! 207: } else { ! 208: strcpy(type, "v7 tar"); ! 209: } ! 210: ! 211: strcat(type, " archive"); ! 212: close(fd); ! 213: return(type); ! 214: } /* if looks like a tar header. */ ! 215: } ! 216: ! 217: /* core file? */ ! 218: if (nb >= sizeof(struct ch_info)) { ! 219: struct ch_info * cip = & iobuf.u_core; ! 220: int offset = cip->ch_info_len + cip->ch_uproc_offset; ! 221: int lsought, readed; ! 222: ! 223: magic = cip->ch_magic; ! 224: if (magic != CORE_MAGIC) ! 225: ; /* bad magic for core file */ ! 226: else if (offset != (lsought = lseek(fd, offset, 0))) ! 227: ; /* can't seek far enough to find UPROC */ ! 228: else if (sizeof(UPROC) != ! 229: (readed = read(fd, &uProc, sizeof(UPROC)))) ! 230: ; /* can't read UPROC */ ! 231: else { ! 232: sprintf(type, "core file from \"%.10s\" uproc (v%04X)", ! 233: uProc.u_comm, uProc.u_version); ! 234: close(fd); ! 235: return(type); ! 236: } ! 237: } ! 238: ! 239: /* Archive or compress'ed file? */ ! 240: if (nb >= sizeof (short)) { ! 241: magic = iobuf.u_armag; ! 242: canint(magic); ! 243: if (magic == ARMAG) { ! 244: close(fd); ! 245: return ("l.out archive"); ! 246: } ! 247: if (magic == UARMAG) { ! 248: close(fd); ! 249: return ("seventh edition archive"); ! 250: } ! 251: if (magic == OUARMAG) { ! 252: close(fd); ! 253: return ("sixth edition archive"); ! 254: } ! 255: if (magic == COMPRESSED){ ! 256: sprintf(type, "%d bit compressed file", ! 257: (int) (0x7f & iobuf.u_buf[2])); ! 258: close(fd); ! 259: return(type); ! 260: } ! 261: } ! 262: ! 263: if (hasnonascii((unsigned char *) &iobuf, nb)) { ! 264: close(fd); ! 265: return ("binary data"); ! 266: } ! 267: if (sbp->st_mode & EXEC) { ! 268: if (strncmp(iobuf.u_buf, "#!", 2) == 0) { ! 269: sprintf(type, "%s script", ! 270: strtok(&(iobuf.u_buf[2]), " \t\n")); ! 271: close(fd); ! 272: return(type); ! 273: } else { ! 274: close(fd); ! 275: return ("commands"); ! 276: } ! 277: } ! 278: close(fd); ! 279: return textclass((unsigned char *) &iobuf, nb); ! 280: } ! 281: ! 282: /* ! 283: * Return the type of the directory. ! 284: * Currently, only "s.*" is recognised as SCCS directory. ! 285: */ ! 286: char * ! 287: dirtype(dn) ! 288: register char *dn; ! 289: { ! 290: register char *cp; ! 291: ! 292: for (cp = dn; *cp; cp++) ! 293: ; ! 294: while (cp > dn) ! 295: if (*--cp == '/') { ! 296: cp++; ! 297: break; ! 298: } ! 299: if (cp[0]=='s' && cp[1]=='.') ! 300: return ("SCCS directory"); ! 301: ! 302: if (strcmp(cp, "RCS") == 0) ! 303: return ("RCS directory"); ! 304: ! 305: return ("directory"); ! 306: } ! 307: ! 308: /* ! 309: * Return true if there ar characters ! 310: * in the buffer that do not look like good ! 311: * ascii characters. ! 312: * This routine knows that ascii is a seven ! 313: * bit code. ! 314: */ ! 315: hasnonascii(bp, nb) ! 316: register unsigned char *bp; ! 317: register nb; ! 318: { ! 319: while (nb--) { ! 320: if (!isascii(*bp)) ! 321: return (1); ! 322: if (!(isprint(*bp) || isspace(*bp) || *bp=='\b' || *bp=='\a')) ! 323: return (1); ! 324: bp++; ! 325: } ! 326: return (0); ! 327: } ! 328: ! 329: /* ! 330: * Classify the first `nb' ! 331: * bytes of a text file. ! 332: */ ! 333: char * ! 334: textclass(bp, nb) ! 335: register unsigned char *bp; ! 336: register nb; ! 337: { ! 338: register int c; ! 339: int nlf = 1; ! 340: int nlbrace; ! 341: int nrbrace; ! 342: int nsharps; ! 343: int nsemi; ! 344: int xmail; ! 345: char *sbp = bp; ! 346: ! 347: nlbrace = 0; ! 348: nrbrace = 0; ! 349: nsharps = 0; ! 350: nsemi = 0; ! 351: xmail = 0; ! 352: while (nb--) { ! 353: c = *bp++; ! 354: if (c=='.' && strncmp(bp, "globl", 5)==0) ! 355: return ("assembler"); ! 356: if (nlf) { ! 357: if (c == '.') ! 358: return ("nroff, tbl or eqn input"); ! 359: else if (c == ':') ! 360: return ("commands"); ! 361: else if (c == '#') ! 362: ++nsharps; ! 363: else if (c=='%') ! 364: if (*bp=='%' || *bp=='{' || *bp=='}') ! 365: return ("yacc or lex input"); ! 366: } ! 367: if (c == '{') ! 368: ++nlbrace; ! 369: else if (c == '}') ! 370: ++nrbrace; ! 371: if (c == '\n') { ! 372: nlf = 1; ! 373: if (bp[-2] == ';') ! 374: nsemi++; ! 375: if (((bp-sbp) % 22) == 0) { ! 376: if (bp[-2]==' ' || bp[-2]=='!') ! 377: xmail++; ! 378: } else ! 379: xmail = 0; ! 380: } else ! 381: nlf = 0; ! 382: } ! 383: if (xmail) ! 384: return ("xmail encoded text"); ! 385: if ((nsharps || nsemi) && (nlbrace || nrbrace)) ! 386: return ("C program"); ! 387: return ("probably text"); ! 388: } ! 389: ! 390: /* ! 391: * Figure out the type of an l.out ! 392: * object file. Tag it with the machine ! 393: * id if not for the machine upon which the ! 394: * command is running. ! 395: */ ! 396: char * ! 397: objclass(fd, lhp) ! 398: register struct ldheader *lhp; ! 399: { ! 400: static char type[TYPE_LEN]; ! 401: register char *mch; ! 402: struct ldsym lds; ! 403: register fsize_t stbase; ! 404: register i; ! 405: ! 406: type[0] = '\0'; ! 407: if ((lhp->l_flag&LF_32) != 0) ! 408: strcat(type, "32 bit "); ! 409: if ((lhp->l_flag&LF_SLIB) != 0) ! 410: strcat(type, "shared library "); ! 411: if ((lhp->l_flag&LF_SLREF) != 0) ! 412: strcat(type, "libref "); ! 413: if ((lhp->l_flag&LF_SHR) != 0) ! 414: strcat(type, "shared "); ! 415: if ((lhp->l_flag&LF_SEP) != 0) ! 416: strcat(type, "separate "); ! 417: if ((lhp->l_flag&LF_KER) != 0) { ! 418: register unsigned ssize; ! 419: ! 420: ssize = sizeof (lds); ! 421: if ((lhp->l_flag & LF_32) == 0) { ! 422: stbase = sizeof(*lhp) - 2*sizeof(int); ! 423: ssize -= sizeof (int); ! 424: } else { ! 425: canshort(lhp->l_tbase); ! 426: stbase = lhp->l_tbase; ! 427: } ! 428: for (i=L_SHRI; i<L_SYM; ++i) ! 429: if (i!=L_BSSI && i!=L_BSSD) { ! 430: cansize(lhp->l_ssize[i]); ! 431: stbase += lhp->l_ssize[i]; ! 432: } ! 433: lseek(fd, stbase, 0); ! 434: cansize(lhp->l_ssize[L_SYM]); ! 435: while (lhp->l_ssize[L_SYM] != 0) { ! 436: if (read(fd, &lds, ssize) != ssize) ! 437: break; ! 438: canshort(lds.ls_type); ! 439: if (strncmp(lds.ls_id, "conftab_", NCPLN) == 0 ! 440: && (lds.ls_type&LR_SEG) != L_REF) ! 441: break; ! 442: lhp->l_ssize[L_SYM] -= ssize; ! 443: } ! 444: strcat(type, lhp->l_ssize[L_SYM]==0?"kernel ":"driver "); ! 445: } ! 446: strcat(type, "executable"); ! 447: if ((lhp->l_flag&LF_NRB) == 0) ! 448: strcat(type, " with relocation"); ! 449: if ((mch = mtype(lhp->l_machine)) == NULL) ! 450: mch = "Unknown machine type"; ! 451: sprintf(type, "%s (%s)", type, mch); ! 452: return (type); ! 453: } ! 454: ! 455: /* ! 456: * Figure out the type of a coff ! 457: * object file. Tag it with the machine ! 458: * id if not for the machine upon which the ! 459: * command is running. ! 460: */ ! 461: char * ! 462: coffclass(chp) ! 463: register struct filehdr *chp; ! 464: { ! 465: static char type[TYPE_LEN]; ! 466: register char *mch; ! 467: ! 468: sprintf(type, "COFF "); ! 469: if ((chp->f_flags&F_MINMAL) != 0) ! 470: strcat(type, "minimal "); ! 471: #ifdef COFF_H_FIXED ! 472: if ((chp->f_flags&F_UPDATE) != 0) ! 473: strcat(type, "update "); ! 474: if ((chp->f_flags&F_SWABD) != 0) ! 475: strcat(type, "swapped bytes "); ! 476: if ((chp->f_flags&F_PATCH) != 0) ! 477: strcat(type, "patch "); ! 478: if ((chp->f_flags&F_NODF) != 0) ! 479: strcat(type, "no decision "); ! 480: #else /* COFF_H_FIXED */ ! 481: if ((chp->f_flags&F_AR32WR) == 0) ! 482: strcat(type, "non i80x86 byte order "); ! 483: #endif /* COFF_H_FIXED */ ! 484: if ((chp->f_flags&F_EXEC) != 0){ ! 485: if ((chp->f_flags&F_LSYMS) != 0) ! 486: strcat(type, "stripped "); ! 487: strcat(type, "executable "); ! 488: } else { ! 489: strcat(type, "object "); ! 490: if ((chp->f_flags&F_RELFLG) != 0) ! 491: strcat(type, "stripped relocation "); ! 492: if ((chp->f_flags&F_LSYMS) != 0) ! 493: strcat(type, "stripped local symbols "); ! 494: } ! 495: ! 496: if ((mch = coffmtype(chp->f_magic)) == NULL) ! 497: mch = "Unknown machine type"; ! 498: sprintf(type, "%s(%s) ", type, mch); ! 499: ! 500: return (type); ! 501: } ! 502: ! 503: ! 504: /* ! 505: * Identify a COFF executable. ! 506: */ ! 507: char * ! 508: coffmtype(magic) ! 509: unsigned short magic; ! 510: { ! 511: switch ((unsigned) magic) { ! 512: ! 513: #ifdef COFF_H_FIXED ! 514: case IAPX16: ! 515: case IAPX16TV: ! 516: case IAPX20: ! 517: case IAPX20TV: ! 518: return("iAPX"); ! 519: ! 520: case B16MAGIC: ! 521: case BTVMAGIC: ! 522: return("Intel Basic-16"); ! 523: ! 524: case X86MAGIC: ! 525: case XTVMAGIC: ! 526: return("Intel x86"); ! 527: ! 528: case I286SMAGIC: ! 529: return("Intel 286"); ! 530: ! 531: case I386MAGIC: ! 532: return("Intel 386"); ! 533: ! 534: case N3BMAGIC: ! 535: case NTVMAGIC: ! 536: return("New 3B"); ! 537: ! 538: case WE32MAGIC: ! 539: case RBOMAGIC: ! 540: case MTVMAGIC: ! 541: return("MAC-32, 3515, 3B5"); ! 542: ! 543: case VAXWRMAGIC: ! 544: case VAXROMAGIC: ! 545: return("VAX 11/780 or /750"); ! 546: ! 547: case 0401: ! 548: case 0405: ! 549: case 0407: ! 550: case 0410: ! 551: case 0411: ! 552: case 0437: ! 553: return("pdp11"); ! 554: ! 555: case MC68MAGIC: ! 556: case MC68TVMAGIC: ! 557: case M68MAGIC: ! 558: case M68TVMAGIC: ! 559: return("Motorola 680xx"); ! 560: ! 561: /* case I286LMAGIC: */ ! 562: case MC68KPGMAGIC: ! 563: return("UNIX PC or iAPX 286"); ! 564: ! 565: case U370WRMAGIC: ! 566: case U370ROMAGIC: ! 567: return("IBM 370"); ! 568: ! 569: case AMDWRMAGIC: ! 570: case AMDROMAGIC: ! 571: return("Amdahl 470/580"); ! 572: ! 573: #else /* COFF_H_FIXED */ ! 574: case C_386_MAGIC: ! 575: return("Intel 386"); ! 576: #endif /* COFF_H_FIXED */ ! 577: ! 578: default: ! 579: return(NULL); ! 580: ! 581: } ! 582: } /* coffmtype() */ ! 583: ! 584: /* ! 585: * Decide if character array 'str' of length 'len' is an acceptable tar ! 586: * octal field. Returns TRUE if it is acceptable, FALSE otherwise. ! 587: */ ! 588: int ! 589: tar_oct(str, len) ! 590: char *str; ! 591: int len; ! 592: { ! 593: for (; len > 0; --len, ++str) { ! 594: if (*str != '\0' && *str != ' ' && ! 595: !('0' <= *str && *str <= '7')) { ! 596: break; ! 597: } ! 598: } ! 599: ! 600: return(0 == len); ! 601: } /* tar_oct() */ ! 602: ! 603: /* ! 604: * Decide if character array 'str' of length 'len' is an acceptable tar ! 605: * decimal field. Returns TRUE if it is acceptable, FALSE otherwise. ! 606: */ ! 607: int ! 608: tar_dec(str, len) ! 609: char *str; ! 610: int len; ! 611: { ! 612: for (; len > 0; --len, ++str) { ! 613: if (*str != '\0' && *str != ' ' && ! 614: !isdigit(*str)) { ! 615: break; ! 616: } ! 617: } ! 618: ! 619: return(0 == len); ! 620: } /* tar_dec() */ ! 621: ! 622: /* ! 623: * Decide if character array 'str' of length 'len' is an acceptable tar ! 624: * path type field. Returns TRUE if it is acceptable, FALSE otherwise. ! 625: */ ! 626: int ! 627: tar_path(str, len) ! 628: char *str; ! 629: int len; ! 630: { ! 631: for (; len > 0; --len, ++str) { ! 632: if (*str != '\0' && *str != ' ' && ! 633: !isprint(*str)) { ! 634: break; ! 635: } ! 636: } ! 637: ! 638: return(0 == len); ! 639: } /* tar_path() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.