Annotation of coherent/b/bin/file.c, revision 1.1.1.1

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() */

unix.superglobalmegacorp.com

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