1*12673Ssam #ifndef lint 2*12673Ssam static char sccsid[] = "@(#)file.c 4.6 (Berkeley) 4.6"; 3*12673Ssam #endif 4613Sbill /* 5613Sbill * file - determine type of file 6613Sbill */ 7613Sbill 8613Sbill #include <sys/types.h> 9613Sbill #include <stat.h> 10613Sbill #include <stdio.h> 11613Sbill #include <ctype.h> 12904Sbill #include <a.out.h> 1312101Smckusick int errno; 1412101Smckusick char *sys_errlist[]; 15613Sbill int in; 16613Sbill int i = 0; 17613Sbill char buf[BUFSIZ]; 18613Sbill char *troff[] = { /* new troff intermediate lang */ 19613Sbill "x","T","res","init","font","202","V0","p1",0}; 20613Sbill char *fort[] = { 21613Sbill "function","subroutine","common","dimension","block","integer", 22613Sbill "real","data","double",0}; 23613Sbill char *asc[] = { 24613Sbill "chmk","mov","tst","clr","jmp",0}; 25613Sbill char *c[] = { 26613Sbill "int","char","float","double","struct","extern",0}; 27613Sbill char *as[] = { 28613Sbill "globl","byte","align","text","data","comm",0}; 29613Sbill int ifile; 30613Sbill 31613Sbill main(argc, argv) 32613Sbill char **argv; 33613Sbill { 34613Sbill FILE *fl; 35613Sbill register char *p; 36613Sbill char ap[128]; 37613Sbill extern char _sobuf[]; 38613Sbill 39613Sbill if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') { 40613Sbill if ((fl = fopen(argv[2], "r")) == NULL) { 4112101Smckusick perror(argv[2]); 42613Sbill exit(2); 43613Sbill } 44613Sbill while ((p = fgets(ap, 128, fl)) != NULL) { 45613Sbill int l = strlen(p); 46613Sbill if (l>0) 47613Sbill p[l-1] = '\0'; 48613Sbill printf("%s: ", p); 49613Sbill type(p); 50613Sbill if (ifile>=0) 51613Sbill close(ifile); 52613Sbill } 53613Sbill exit(1); 54613Sbill } 55613Sbill while(argc > 1) { 56613Sbill printf("%s: ", argv[1]); 57613Sbill type(argv[1]); 58613Sbill fflush(stdout); 59613Sbill argc--; 60613Sbill argv++; 61613Sbill if (ifile >= 0) 62613Sbill close(ifile); 63613Sbill } 64613Sbill } 65613Sbill 66613Sbill type(file) 67613Sbill char *file; 68613Sbill { 69613Sbill int j,nl; 70613Sbill char ch; 71613Sbill struct stat mbuf; 72613Sbill 73613Sbill ifile = -1; 746719Smckusick if (lstat(file, &mbuf) < 0) { 7512101Smckusick printf("%s\n", sys_errlist[errno]); 76613Sbill return; 77613Sbill } 78613Sbill switch (mbuf.st_mode & S_IFMT) { 79613Sbill 80613Sbill case S_IFCHR: 81613Sbill printf("character"); 82613Sbill goto spcl; 83613Sbill 846719Smckusick case S_IFLNK: 856719Smckusick printf("symbolic link\n"); 866719Smckusick return; 876719Smckusick 88613Sbill case S_IFDIR: 89613Sbill printf("directory\n"); 90613Sbill return; 91613Sbill 92613Sbill case S_IFBLK: 93613Sbill printf("block"); 94613Sbill 95613Sbill spcl: 96613Sbill printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev)); 97613Sbill return; 98613Sbill } 99613Sbill 100613Sbill ifile = open(file, 0); 101613Sbill if(ifile < 0) { 102613Sbill printf("cannot open\n"); 103613Sbill return; 104613Sbill } 105613Sbill in = read(ifile, buf, BUFSIZ); 106613Sbill if(in == 0){ 107613Sbill printf("empty\n"); 108613Sbill return; 109613Sbill } 110613Sbill switch(*(int *)buf) { 111613Sbill 112613Sbill case 0413: 113613Sbill printf("demand paged "); 114613Sbill 115613Sbill case 0410: 116613Sbill printf("pure "); 117613Sbill goto exec; 118613Sbill 119613Sbill case 0411: 120613Sbill printf("jfr or pdp-11 unix 411 executable\n"); 121613Sbill return; 122613Sbill 123613Sbill case 0407: 124613Sbill exec: 125613Sbill printf("executable"); 126613Sbill if(((int *)buf)[4] != 0) { 127613Sbill printf(" not stripped"); 128613Sbill if(oldo(buf)) 129613Sbill printf(" (old format symbol table)"); 130613Sbill } 131613Sbill printf("\n"); 132613Sbill goto out; 133613Sbill 134613Sbill case 0177555: 135613Sbill printf("very old archive\n"); 136613Sbill goto out; 137613Sbill 138613Sbill case 0177545: 139613Sbill printf("old archive\n"); 140613Sbill goto out; 141897Sbill 142897Sbill case 070707: 143897Sbill printf("cpio data\n"); 144897Sbill goto out; 145613Sbill } 146613Sbill 147613Sbill if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) { 148613Sbill printf("archive random library\n"); 149613Sbill goto out; 150613Sbill } 151613Sbill if (strncmp(buf, "!<arch>\n", 8)==0) { 152613Sbill printf("archive\n"); 153613Sbill goto out; 154613Sbill } 1555900Sroot if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */ 1565900Sroot lseek(ifile, -512L, 2); /* last block */ 1575900Sroot if (read(ifile, buf, BUFSIZ) > 0 1585900Sroot && *(short int *)buf == 12138) { 1595900Sroot printf("PRESS file\n"); 1605900Sroot goto out; 1615900Sroot } 1625900Sroot } 163613Sbill i = 0; 164613Sbill if(ccom() == 0)goto notc; 165613Sbill while(buf[i] == '#'){ 166613Sbill j = i; 167613Sbill while(buf[i++] != '\n'){ 168613Sbill if(i - j > 255){ 169613Sbill printf("data\n"); 170613Sbill goto out; 171613Sbill } 172613Sbill if(i >= in)goto notc; 173613Sbill } 174613Sbill if(ccom() == 0)goto notc; 175613Sbill } 176613Sbill check: 177613Sbill if(lookup(c) == 1){ 178613Sbill while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; 179613Sbill printf("c program text"); 180613Sbill goto outa; 181613Sbill } 182613Sbill nl = 0; 183613Sbill while(buf[i] != '('){ 184613Sbill if(buf[i] <= 0) 185613Sbill goto notas; 186613Sbill if(buf[i] == ';'){ 187613Sbill i++; 188613Sbill goto check; 189613Sbill } 190613Sbill if(buf[i++] == '\n') 191613Sbill if(nl++ > 6)goto notc; 192613Sbill if(i >= in)goto notc; 193613Sbill } 194613Sbill while(buf[i] != ')'){ 195613Sbill if(buf[i++] == '\n') 196613Sbill if(nl++ > 6)goto notc; 197613Sbill if(i >= in)goto notc; 198613Sbill } 199613Sbill while(buf[i] != '{'){ 200613Sbill if(buf[i++] == '\n') 201613Sbill if(nl++ > 6)goto notc; 202613Sbill if(i >= in)goto notc; 203613Sbill } 204613Sbill printf("c program text"); 205613Sbill goto outa; 206613Sbill notc: 207613Sbill i = 0; 208613Sbill while(buf[i] == 'c' || buf[i] == '#'){ 209613Sbill while(buf[i++] != '\n')if(i >= in)goto notfort; 210613Sbill } 211613Sbill if(lookup(fort) == 1){ 212613Sbill printf("fortran program text"); 213613Sbill goto outa; 214613Sbill } 215613Sbill notfort: 216613Sbill i=0; 217613Sbill if(ascom() == 0)goto notas; 218613Sbill j = i-1; 219613Sbill if(buf[i] == '.'){ 220613Sbill i++; 221613Sbill if(lookup(as) == 1){ 222613Sbill printf("assembler program text"); 223613Sbill goto outa; 224613Sbill } 225613Sbill else if(buf[j] == '\n' && isalpha(buf[j+2])){ 226613Sbill printf("roff, nroff, or eqn input text"); 227613Sbill goto outa; 228613Sbill } 229613Sbill } 230613Sbill while(lookup(asc) == 0){ 231613Sbill if(ascom() == 0)goto notas; 232613Sbill while(buf[i] != '\n' && buf[i++] != ':') 233613Sbill if(i >= in)goto notas; 234613Sbill while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; 235613Sbill j = i-1; 236613Sbill if(buf[i] == '.'){ 237613Sbill i++; 238613Sbill if(lookup(as) == 1){ 239613Sbill printf("assembler program text"); 240613Sbill goto outa; 241613Sbill } 242613Sbill else if(buf[j] == '\n' && isalpha(buf[j+2])){ 243613Sbill printf("roff, nroff, or eqn input text"); 244613Sbill goto outa; 245613Sbill } 246613Sbill } 247613Sbill } 248613Sbill printf("assembler program text"); 249613Sbill goto outa; 250613Sbill notas: 251613Sbill for(i=0; i < in; i++)if(buf[i]&0200){ 252613Sbill if (buf[0]=='\100' && buf[1]=='\357') { 253613Sbill printf("troff (CAT) output\n"); 254613Sbill goto out; 255613Sbill } 256613Sbill printf("data\n"); 257613Sbill goto out; 258613Sbill } 259613Sbill if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) 260613Sbill printf("commands text"); 261613Sbill else if (troffint(buf, in)) 262613Sbill printf("troff intermediate output text"); 263613Sbill else if (english(buf, in)) 264613Sbill printf("English text"); 265613Sbill else 266613Sbill printf("ascii text"); 267613Sbill outa: 268613Sbill while(i < in) 269613Sbill if((buf[i++]&0377) > 127){ 270613Sbill printf(" with garbage\n"); 271613Sbill goto out; 272613Sbill } 273613Sbill /* if next few lines in then read whole file looking for nulls ... 274613Sbill while((in = read(ifile,buf,BUFSIZ)) > 0) 275613Sbill for(i = 0; i < in; i++) 276613Sbill if((buf[i]&0377) > 127){ 277613Sbill printf(" with garbage\n"); 278613Sbill goto out; 279613Sbill } 280613Sbill /*.... */ 281613Sbill printf("\n"); 282613Sbill out:; 283613Sbill } 284613Sbill 285613Sbill oldo(cp) 286613Sbill char *cp; 287613Sbill { 288613Sbill struct exec ex; 289613Sbill struct stat stb; 290613Sbill 291613Sbill ex = *(struct exec *)cp; 292613Sbill if (fstat(ifile, &stb) < 0) 293613Sbill return(0); 294613Sbill if (N_STROFF(ex)+sizeof(off_t) > stb.st_size) 295613Sbill return (1); 296613Sbill return (0); 297613Sbill } 298613Sbill 299613Sbill 300613Sbill 301613Sbill troffint(bp, n) 302613Sbill char *bp; 303613Sbill int n; 304613Sbill { 305613Sbill int k; 306613Sbill 307613Sbill i = 0; 308613Sbill for (k = 0; k < 6; k++) { 309613Sbill if (lookup(troff) == 0) 310613Sbill return(0); 311613Sbill if (lookup(troff) == 0) 312613Sbill return(0); 313613Sbill while (i < n && buf[i] != '\n') 314613Sbill i++; 315613Sbill if (i++ >= n) 316613Sbill return(0); 317613Sbill } 318613Sbill return(1); 319613Sbill } 320613Sbill lookup(tab) 321613Sbill char *tab[]; 322613Sbill { 323613Sbill char r; 324613Sbill int k,j,l; 325613Sbill while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; 326613Sbill for(j=0; tab[j] != 0; j++){ 327613Sbill l=0; 328613Sbill for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); 329613Sbill if(r == '\0') 330613Sbill if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' 331613Sbill || buf[k] == '{' || buf[k] == '/'){ 332613Sbill i=k; 333613Sbill return(1); 334613Sbill } 335613Sbill } 336613Sbill return(0); 337613Sbill } 338613Sbill ccom(){ 339613Sbill char cc; 340613Sbill while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); 341613Sbill if(buf[i] == '/' && buf[i+1] == '*'){ 342613Sbill i += 2; 343613Sbill while(buf[i] != '*' || buf[i+1] != '/'){ 344613Sbill if(buf[i] == '\\')i += 2; 345613Sbill else i++; 346613Sbill if(i >= in)return(0); 347613Sbill } 348613Sbill if((i += 2) >= in)return(0); 349613Sbill } 350613Sbill if(buf[i] == '\n')if(ccom() == 0)return(0); 351613Sbill return(1); 352613Sbill } 353613Sbill ascom(){ 354613Sbill while(buf[i] == '/'){ 355613Sbill i++; 356613Sbill while(buf[i++] != '\n')if(i >= in)return(0); 357613Sbill while(buf[i] == '\n')if(i++ >= in)return(0); 358613Sbill } 359613Sbill return(1); 360613Sbill } 361613Sbill 362613Sbill english (bp, n) 363613Sbill char *bp; 364613Sbill { 365613Sbill # define NASC 128 366613Sbill int ct[NASC], j, vow, freq, rare; 367613Sbill int badpun = 0, punct = 0; 368613Sbill if (n<50) return(0); /* no point in statistics on squibs */ 369613Sbill for(j=0; j<NASC; j++) 370613Sbill ct[j]=0; 371613Sbill for(j=0; j<n; j++) 372613Sbill { 373613Sbill if (bp[j]<NASC) 374613Sbill ct[bp[j]|040]++; 375613Sbill switch (bp[j]) 376613Sbill { 377613Sbill case '.': 378613Sbill case ',': 379613Sbill case ')': 380613Sbill case '%': 381613Sbill case ';': 382613Sbill case ':': 383613Sbill case '?': 384613Sbill punct++; 385613Sbill if ( j < n-1 && 386613Sbill bp[j+1] != ' ' && 387613Sbill bp[j+1] != '\n') 388613Sbill badpun++; 389613Sbill } 390613Sbill } 391613Sbill if (badpun*5 > punct) 392613Sbill return(0); 393613Sbill vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u']; 394613Sbill freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n']; 395613Sbill rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z']; 396613Sbill if (2*ct[';'] > ct['e']) return(0); 397613Sbill if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */ 398613Sbill return (vow*5 >= n-ct[' '] && freq >= 10*rare); 399613Sbill } 400