Annotation of researchv10no/cmd/lp/file.c, revision 1.1.1.1

1.1       root        1: #include <u.h>
                      2: #include <libc.h>
                      3: #include <ctype.h>
                      4: #ifdef plan9
                      5: Dir    mbuf;
                      6: #else
                      7: #define print  printf
                      8: struct stat mbuf;
                      9: #define OREAD  0
                     10: #endif
                     11: /*
                     12:  * file - determine type of file
                     13:  */
                     14: 
                     15: uchar  buf[6000];
                     16: short  cfreq[140];
                     17: short  wfreq[50];
                     18: int    nbuf;
                     19: int    flag;
                     20: int    (*call[])(void);
                     21: 
                     22: enum
                     23: {
                     24:        Cword,
                     25:        Fword,
                     26:        Aword,
                     27:        I1,
                     28:        I2,
                     29:        I3,
                     30:        Clatin  = 128,
                     31:        Cbinary,
                     32:        Cnull,
                     33:        Ceascii,
                     34: };
                     35: struct
                     36: {
                     37:        char*   word;
                     38:        int     flag;
                     39: } dict[] =
                     40: {
                     41:        "TEXT",         Aword,
                     42:        "block",        Fword,
                     43:        "char",         Cword,
                     44:        "common",       Fword,
                     45:        "data",         Fword,
                     46:        "dimension",    Fword,
                     47:        "double",       Cword,
                     48:        "extern",       Cword,
                     49:        "fio",          I2,
                     50:        "float",        Cword,
                     51:        "function",     Fword,
                     52:        "h",            I3,
                     53:        "include",      I1,
                     54:        "int",          Cword,
                     55:        "integer",      Fword,
                     56:        "libc",         I2,
                     57:        "long",         Cword,
                     58:        "real",         Fword,
                     59:        "register",     Cword,
                     60:        "short",        Cword,
                     61:        "static",       Cword,
                     62:        "stdio",        I2,
                     63:        "struct",       Cword,
                     64:        "subroutine",   Fword,
                     65:        "u",            I2,
                     66:        "void",         Cword,
                     67: };
                     68: 
                     69: enum
                     70: {
                     71:        Short   = 1<<0,         /* size < 100 */
                     72:        Long    = 1<<1,
                     73: 
                     74:        Fascii  = 1<<2,         /* printable ascii */
                     75:        Flatin  = 1<<3,
                     76:        Fbinary = 1<<4,
                     77:        Feascii = 1<<5,         /* including extended */
                     78:        Fnull   = 1<<6,
                     79: };
                     80: 
                     81: void   type(char*, int);
                     82: long   lendian(uchar*);
                     83: 
                     84: int
                     85: main(int argc, char *argv[])
                     86: {
                     87:        int i, l;
                     88: 
                     89:        l = 0;
                     90:        for(i=1; i<argc; i++)
                     91:                if(strlen(argv[i]) > l)
                     92:                        l = strlen(argv[i]);
                     93:        for(i=1; i<argc; i++)
                     94:                type(argv[i], l);
                     95:        exit(0);
                     96: }
                     97: 
                     98: void
                     99: type(char *file, int nlen)
                    100: {
                    101:        int i, f, l, m, c;
                    102:        char *p, *ep, word[20];
                    103: 
                    104:        print("%s:%*s", file, nlen-strlen(file)+1, "");
                    105: #ifdef plan9
                    106:        if(dirstat(file, &mbuf) < 0) {
                    107:                print("cannot stat\n");
                    108:                return;
                    109:        }
                    110:        if(mbuf.mode & CHDIR) {
                    111:                print("directory\n");
                    112:                return;
                    113:        }
                    114:        if(mbuf.type != 'M') {
                    115:                print("special file #%c\n", mbuf.type);
                    116:                return;
                    117:        }
                    118: #else
                    119:        if(stat(file, &mbuf) < 0) {
                    120:                print("cannot stat\n");
                    121:                return;
                    122:        }
                    123:        switch(mbuf.st_mode&S_IFMT) {
                    124:        case S_IFDIR:
                    125:                print("directory\n");
                    126:                return;
                    127:        case S_IFCHR:
                    128:                print("character special file\n");
                    129:                return;
                    130:        case S_IFBLK:
                    131:                print("block special file\n");
                    132:                return;
                    133:        }
                    134: #endif
                    135: 
                    136:        f = open(file, OREAD);
                    137:        if(f < 0) {
                    138:                print("cannot open\n");
                    139:                return;
                    140:        }
                    141:        nbuf = read(f, buf, sizeof(buf));
                    142:        close(f);
                    143: 
                    144:        if(nbuf < 0) {
                    145:                print("cannot read\n");
                    146:                return;
                    147:        }
                    148:        if(nbuf == 0) {
                    149:                print("empty\n");
                    150:                return;
                    151:        }
                    152: 
                    153:        /*
                    154:         * build histogram table
                    155:         */
                    156:        memset(cfreq, 0, sizeof(cfreq));
                    157:        flag = 0;
                    158:        if(nbuf > 100)
                    159:                flag |= Long;
                    160:        else
                    161:                flag |= Short;
                    162: 
                    163:        for(i=0; i<nbuf; i++) {
                    164:                f = buf[i] & 0xff;
                    165:                if(f >= 128) {
                    166:                        if(f >= 128+32)
                    167:                                f = Clatin;     /* latin */
                    168:                        else
                    169:                                f = Cbinary;    /* not latin */
                    170:                } else
                    171:                if(!isprint(f) && !isspace(f))
                    172:                        if(f == 0)
                    173:                                f = Cnull;
                    174:                        else
                    175:                                f = Ceascii;
                    176:                cfreq[f]++;
                    177:        }
                    178: 
                    179:        /*
                    180:         * gross classify
                    181:         */
                    182:        if(cfreq[Cbinary])
                    183:                flag |= Fbinary;
                    184:        else
                    185:        if(cfreq[Clatin])
                    186:                flag |= Flatin;
                    187:        else
                    188:        if(cfreq[Ceascii])
                    189:                flag |= Feascii;
                    190:        else
                    191:        if(cfreq[Cnull])
                    192:                flag |= Fnull;
                    193:        else
                    194:                flag |= Fascii;
                    195: 
                    196:        if(flag & Fnull) {
                    197:                print("null\n");
                    198:                return;
                    199:        }
                    200: 
                    201:        /*
                    202:         * lookup dictionary words
                    203:         */
                    204:        memset(wfreq, 0, sizeof(wfreq));
                    205:        if(flag & Fascii) {
                    206:                ep = word+sizeof(word)-2;
                    207:                for(i=0; i<nbuf; i++) {
                    208:                        f = buf[i];
                    209:                        if(!isalpha(f))
                    210:                                continue;
                    211:                        p = word;
                    212:                        for(; i<nbuf; i++) {
                    213:                                f = buf[i];
                    214:                                if(!isalnum(f))
                    215:                                        break;
                    216:                                *p++ = f;
                    217:                                if(p >= ep)
                    218:                                        break;
                    219:                        }
                    220:                        *p = 0;
                    221:                        f = 0;
                    222:                        l = sizeof(dict)/sizeof(dict[0]);
                    223:                        for(;;) {
                    224:                                if(f >= l)
                    225:                                        break;
                    226:                                m = (f+l)/2;
                    227:                                c = strcmp(dict[m].word, word);
                    228:                                if(c == 0) {
                    229:                                        wfreq[dict[m].flag]++;
                    230:                                        break;
                    231:                                }
                    232:                                if(c < 0)
                    233:                                        f = m+1;
                    234:                                else
                    235:                                        l = m;
                    236:                        }
                    237:                }
                    238:        }
                    239: 
                    240:        /*
                    241:         * call individual classify routines
                    242:         */
                    243:        for(i=0; call[i]; i++)
                    244:                if((*call[i])())
                    245:                        return;
                    246: 
                    247:        /*
                    248:         * if all else fails,
                    249:         * print out gross classification
                    250:         */
                    251:        if(flag & Short)
                    252:                print("short ");
                    253:        if(flag & Fascii)
                    254:                print("ascii\n");
                    255:        else
                    256:        if(flag & Feascii)
                    257:                print("extended ascii\n");
                    258:        else
                    259:        if(flag & Flatin)
                    260:                print("latin ascii\n");
                    261:        else
                    262:                print("binary\n");
                    263: }
                    264: 
                    265: long
                    266: lendian(uchar *p)
                    267: {
                    268: 
                    269:        return (p[0]) |
                    270:                (p[1] << 8) |
                    271:                (p[2] << 16) |
                    272:                (p[3] << 24);
                    273: }
                    274: 
                    275: int
                    276: long0(void)
                    277: {
                    278: 
                    279:        switch((unsigned)lendian(buf)) {
                    280:        default:
                    281:                return 0;
                    282: 
                    283:        case 0413:
                    284:                print("demand paged ");
                    285: 
                    286:        case 0410:
                    287:                print("pure ");
                    288:                goto exec;
                    289: 
                    290:        case 0406:
                    291:                print("mpx 68000 ");
                    292:                goto exec;
                    293: 
                    294:        exec:
                    295:        case 0407:
                    296:                print("unix vax executable");
                    297:                if(lendian(buf+4) != 0)
                    298:                        print(" not stripped");
                    299:                print("\n");
                    300:                break;
                    301: 
                    302:        case 0411:
                    303:                print("jfr 411 executable\n");
                    304:                break;
                    305: 
                    306:        case 0177555:
                    307:                print("very old archive\n");
                    308:                break;
                    309: 
                    310:        case 0177545:
                    311:                print("old archive\n");
                    312:                break;
                    313: 
                    314:        case 0135246:           /* andrew/ehg */
                    315:                print("view2d input file\n");
                    316:                break;
                    317: 
                    318:        case 0135256:           /* andrew */
                    319:                print("apl file\n");
                    320:                break;
                    321: 
                    322:        case 0164200:           /* td */
                    323:                print("Lucasfilm picture\n");
                    324:                break;
                    325: 
                    326:        case 0600560:
                    327:                print("mux downloadable file\n");
                    328:                break;
                    329: 
                    330:        case 0x07010000:
                    331:                print("68020 plan9 executable\n");
                    332:                break;
                    333: 
                    334:        case 0x07040000:
                    335:                print("mips plan9 executable\n");
                    336:                break;
                    337: 
                    338:        case 0x97010000:
                    339:                print("hobbit plan9 executable\n");
                    340:                break;
                    341: 
                    342:        case 0xab020000:
                    343:                print("sparc plan9 executable\n");
                    344:                break;
                    345: 
                    346:        case 0xeb010000:
                    347:                print("386 plan9 executable\n");
                    348:                break;
                    349:        case 0x0b1f1bdc:
                    350:                print("daisy\n");
                    351:                break;
                    352:        case 0x64205300:
                    353:                print("S data object\n");
                    354:                break;
                    355:        }
                    356:        return 1;
                    357: }
                    358: 
                    359: int
                    360: short0(void)
                    361: {
                    362: 
                    363:        switch(lendian(buf) & 0xffff) {
                    364:        default:
                    365:                return 0;
                    366: 
                    367:        case 070707:
                    368:                print("cpio archive\n");
                    369:                break;
                    370: 
                    371:        case 0x02f7:
                    372:                print("tex dvi\n");
                    373:                break;
                    374: 
                    375:        case 0405:
                    376:        case 0407:
                    377:        case 0410:
                    378:        case 0411:
                    379:                print("pdp-11 executable\n");
                    380:                break;
                    381:        case 0x0000:
                    382:                print("bitmap\n");
                    383:                break;
                    384:        }
                    385:        return 1;
                    386: }
                    387: 
                    388: /*
                    389:  * initial words to classify file
                    390:  */
                    391: char*  iwords[] =
                    392: {
                    393:        "!<arch>\n__.SYMDEF",
                    394:                "archive random library",
                    395:        "!<arch>\n",
                    396:                "archive",
                    397:        "070707",
                    398:                "cpio archive - ascii header",
                    399:        "#FIG",
                    400:                "fig ouput",
                    401:        "#!/bin/echo",
                    402:                "cyntax object file",
                    403:        "#!/bin/rc",
                    404:                "rc executable file",
                    405:        "#!/bin/sh",
                    406:                "sh executable file",
                    407:        "%!",
                    408:                "postscript",
                    409:        "@document(",
                    410:                "imagen",
                    411:        "x T i300",
                    412:                "troff output for i300",
                    413:        "x T im300",
                    414:                "troff output for im300",
                    415:        "x T post",
                    416:                "troff output for post",
                    417:        "x T opost",
                    418:                "troff output for opost",
                    419:        "x T Latin1",
                    420:                "troff output for Latin1",
                    421:        "x T 202",
                    422:                "troff output for 202",
                    423:        "x T aps",
                    424:                "troff output for aps",
                    425:        0,0
                    426: };
                    427: 
                    428: int
                    429: istring(void)
                    430: {
                    431:        int i, n;
                    432:        char *p;
                    433: 
                    434:        for(i=0; p=iwords[i]; i+=2) {
                    435:                n = strlen(p);
                    436:                if(nbuf >= n && !strncmp((char*)buf, p, n)) {
                    437:                        print("%s\n", iwords[i+1]);
                    438:                        return 1;
                    439:                }
                    440:        }
                    441:        if(strncmp((char*)buf, "TYPE=", 5) == 0) {      /* td */
                    442:                for(i=5; i<nbuf; i++)
                    443:                        if(buf[i] == '\n')
                    444:                                break;
                    445:                print("%.*s picture\n", i-5, buf+5);
                    446:                return 1;
                    447:        }
                    448:        return 0;
                    449: }
                    450: 
                    451: /*
                    452:  * low entropy means encrypted
                    453:  */
                    454: int
                    455: ismung(void)
                    456: {
                    457:        int i, bucket[8];
                    458:        float cs;
                    459: 
                    460:        if(nbuf < 64)
                    461:                return 0;
                    462:        memset(bucket, 0, sizeof(bucket));
                    463:        for(i=0; i<64; i++)
                    464:                bucket[(buf[i]>>5)&07] += 1;
                    465: 
                    466:        cs = 0.;
                    467:        for(i=0; i<8; i++)
                    468:                cs += (bucket[i]-8)*(bucket[i]-8);
                    469:        cs /= 8.;
                    470:        if(cs <= 24.322) {
                    471:                if(buf[0]==037 && buf[1]==0235)
                    472:                        print("compressed\n");
                    473:                else
                    474:                        print("encrypted\n");
                    475:                return 1;
                    476:        }
                    477:        return 0;
                    478: }
                    479: 
                    480: /*
                    481:  * english by punctuation and frequencies
                    482:  */
                    483: int
                    484: isenglish(void)
                    485: {
                    486:        int i, vow, comm, rare, badpun, punct;
                    487:        char *p;
                    488: 
                    489:        if(!(flag & (Fascii|Feascii)))
                    490:                return 0;
                    491:        badpun = 0;
                    492:        punct = 0;
                    493:        for(i=0; i<nbuf-1; i++)
                    494:                switch(buf[i]) {
                    495:                case '.':
                    496:                case ',':
                    497:                case ')':
                    498:                case '%':
                    499:                case ';':
                    500:                case ':':
                    501:                case '?':
                    502:                        punct++;
                    503:                        if(buf[i+1] != ' ' && buf[i+1] != '\n')
                    504:                                badpun++;
                    505:                }
                    506:        if(badpun*5 > punct)
                    507:                return 0;
                    508:        if(cfreq['>']+cfreq['<']+cfreq['/'] > cfreq['e'])       /* shell file test */
                    509:                return 0;
                    510:        if(2*cfreq[';'] > cfreq['e'])
                    511:                return 0;
                    512: 
                    513:        vow = 0;
                    514:        for(p="AEIOU"; *p; p++) {
                    515:                vow += cfreq[*p];
                    516:                vow += cfreq[tolower(*p)];
                    517:        }
                    518:        comm = 0;
                    519:        for(p="ETAION"; *p; p++) {
                    520:                comm += cfreq[*p];
                    521:                comm += cfreq[tolower(*p)];
                    522:        }
                    523:        rare = 0;
                    524:        for(p="VJKQXZ"; *p; p++) {
                    525:                rare += cfreq[*p];
                    526:                rare += cfreq[tolower(*p)];
                    527:        }
                    528:        if(vow*5 >= nbuf-cfreq[' '] && comm >= 10*rare) {
                    529:                print("English text\n");
                    530:                return 1;
                    531:        }
                    532:        return 0;
                    533: }
                    534: 
                    535: int
                    536: isc(void)
                    537: {
                    538:        int n;
                    539: 
                    540:        n = wfreq[I1];
                    541:        /*
                    542:         * includes
                    543:         */
                    544:        if(n >= 2 && wfreq[I2] >= n && wfreq[I3] >= n && cfreq['.'] >= n)
                    545:                goto yes;
                    546:        /*
                    547:         * declarations
                    548:         */
                    549:        if(wfreq[Cword] >= 5 && cfreq[';'] >= 5)
                    550:                goto yes;
                    551:        /*
                    552:         * assignments
                    553:         */
                    554:        if(cfreq[';'] >= 10 && cfreq['='] >= 10)
                    555:                goto yes;
                    556:        return 0;
                    557: 
                    558: yes:
                    559:        print("c program text\n");
                    560:        return 1;
                    561: }
                    562: 
                    563: int
                    564: isas(void)
                    565: {
                    566: 
                    567:        /*
                    568:         * includes
                    569:         */
                    570:        if(wfreq[Aword] >= 2)
                    571:                goto yes;
                    572:        return 0;
                    573: 
                    574: yes:
                    575:        print("assembler program text\n");
                    576:        return 1;
                    577: }
                    578: 
                    579: int
                    580: iscint(void)
                    581: {
                    582: 
                    583:        if(buf[0] == 0x3a)                      /* as = ANAME */
                    584:        if(buf[1] == 0x11)                      /* type = D_FILE */
                    585:        if(buf[2] == 1)                         /* sym */
                    586:        if(buf[3] == '<') {                     /* name of file */
                    587:                print("mips .v intermediate\n");
                    588:                return 1;
                    589:        }
                    590: 
                    591:        if(buf[0] == 0x4d)                      /* aslo = ANAME */
                    592:        if(buf[1] == 0x01)                      /* ashi = ANAME */
                    593:        if(buf[2] == 0x32)                      /* type = D_FILE */
                    594:        if(buf[3] == 1)                         /* sym */
                    595:        if(buf[4] == '<') {                     /* name of file */
                    596:                print("68020 .2 intermediate\n");
                    597:                return 1;
                    598:        }
                    599: 
                    600:        if(buf[0] == 0x43)                      /* as = ANAME */
                    601:        if(buf[1] == 0x0d)                      /* type */
                    602:        if(buf[2] == 1)                         /* sym */
                    603:        if(buf[3] == '<') {                     /* name of file */
                    604:                print("hobbit .z intermediate\n");
                    605:                return 1;
                    606:        }
                    607: 
                    608:        if(buf[0] == 0x74)                      /* as = ANAME */
                    609:        if(buf[1] == 0x10)                      /* type */
                    610:        if(buf[2] == 1)                         /* sym */
                    611:        if(buf[3] == '<') {                     /* name of file */
                    612:                print("sparc .k intermediate\n");
                    613:                return 1;
                    614:        }
                    615: 
                    616:        if(buf[0] == 0x7e)                      /* aslo = ANAME */
                    617:        if(buf[1] == 0x00)                      /* ashi = ANAME */
                    618:        if(buf[2] == 0x45)                      /* type = D_FILE */
                    619:        if(buf[3] == 1)                         /* sym */
                    620:        if(buf[4] == '<') {                     /* name of file */
                    621:                print("386 .8 intermediate\n");
                    622:                return 1;
                    623:        }
                    624: 
                    625:        return 0;
                    626: }
                    627: 
                    628: /*
                    629:  * pick up a number with
                    630:  * syntax _*[0-9]+_
                    631:  */
                    632: #define        P9BITLEN        12
                    633: int
                    634: p9bitnum(uchar *bp)
                    635: {
                    636:        int n, c, len;
                    637: 
                    638:        len = P9BITLEN;
                    639:        while(*bp == ' ') {
                    640:                bp++;
                    641:                len--;
                    642:                if(len <= 0)
                    643:                        return -1;
                    644:        }
                    645:        n = 0;
                    646:        while(len > 1) {
                    647:                c = *bp++;
                    648:                if(!isdigit(c))
                    649:                        return -1;
                    650:                n = n*10 + c-'0';
                    651:                len--;
                    652:        }
                    653:        if(*bp != ' ')
                    654:                return -1;
                    655:        return n;
                    656: }
                    657: 
                    658: int
                    659: isp9bit(void)
                    660: {
                    661:        int ldep, lox, loy, hix, hiy;
                    662:        long len;
                    663: 
                    664:        ldep = p9bitnum(buf + 0*P9BITLEN);
                    665:        lox = p9bitnum(buf + 1*P9BITLEN);
                    666:        loy = p9bitnum(buf + 2*P9BITLEN);
                    667:        hix = p9bitnum(buf + 3*P9BITLEN);
                    668:        hiy = p9bitnum(buf + 4*P9BITLEN);
                    669: 
                    670:        if(ldep < 0 || lox < 0 || loy < 0 || hix < 0 || hiy < 0)
                    671:                return 0;
                    672: 
                    673:        len = (hix-lox) * (1<<ldep);    /* row length */
                    674:        len = (len + 7) / 8;            /* rounded to bytes */
                    675:        len *= (hiy-loy);               /* col length */
                    676:        len += 60;                      /* size of initial ascii */
                    677: 
                    678:        /*
                    679:         * for regular file length is non-zero and must match calculation above
                    680:         * for /dev/window and /dev/screen the length is always zero
                    681:         */
                    682: #ifdef plan9
                    683:        if(mbuf.length != len && mbuf.length != 0)
                    684: #else
                    685:        if(mbuf.st_size != len && mbuf.st_size != 0)
                    686: #endif 
                    687:                return 0;
                    688:        print("plan 9 bitmap\n");
                    689:        return 1;
                    690: }
                    691: 
                    692: int    (*call[])(void) =
                    693: {
                    694:        long0,          /* recognizable by first 4 bytes */
                    695:        short0,         /* recognizable by first 2 bytes */
                    696:        istring,        /* recognizable by first string */
                    697:        iscint,         /* c intermediate */
                    698:        isc,            /* c compiler key words */
                    699:        isas,           /* assembler key words */
                    700:        ismung,         /* entropy compressed/encrypted */
                    701:        isenglish,      /* char frequency English */
                    702:        isp9bit,        /* plan 9 bitmap (as from /dev/window) */
                    703:        0
                    704: };

unix.superglobalmegacorp.com

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