Annotation of coherent/d/bin/file.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.