1 static char sccsid[] = "@(#)file.c 4.3 (Berkeley) 4.3"; 2 /* 3 * file - determine type of file 4 */ 5 6 #include <pagsiz.h> 7 #include <sys/types.h> 8 #include <stat.h> 9 #include <stdio.h> 10 #include <ctype.h> 11 #include <a.out.h> 12 int in; 13 int i = 0; 14 char buf[BUFSIZ]; 15 char *troff[] = { /* new troff intermediate lang */ 16 "x","T","res","init","font","202","V0","p1",0}; 17 char *fort[] = { 18 "function","subroutine","common","dimension","block","integer", 19 "real","data","double",0}; 20 char *asc[] = { 21 "chmk","mov","tst","clr","jmp",0}; 22 char *c[] = { 23 "int","char","float","double","struct","extern",0}; 24 char *as[] = { 25 "globl","byte","align","text","data","comm",0}; 26 int ifile; 27 28 main(argc, argv) 29 char **argv; 30 { 31 FILE *fl; 32 register char *p; 33 char ap[128]; 34 extern char _sobuf[]; 35 36 if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') { 37 if ((fl = fopen(argv[2], "r")) == NULL) { 38 printf("Can't open %s\n", argv[2]); 39 exit(2); 40 } 41 while ((p = fgets(ap, 128, fl)) != NULL) { 42 int l = strlen(p); 43 if (l>0) 44 p[l-1] = '\0'; 45 printf("%s: ", p); 46 type(p); 47 if (ifile>=0) 48 close(ifile); 49 } 50 exit(1); 51 } 52 while(argc > 1) { 53 printf("%s: ", argv[1]); 54 type(argv[1]); 55 fflush(stdout); 56 argc--; 57 argv++; 58 if (ifile >= 0) 59 close(ifile); 60 } 61 } 62 63 type(file) 64 char *file; 65 { 66 int j,nl; 67 char ch; 68 struct stat mbuf; 69 70 ifile = -1; 71 if(stat(file, &mbuf) < 0) { 72 printf("cannot stat\n"); 73 return; 74 } 75 switch (mbuf.st_mode & S_IFMT) { 76 77 case S_IFCHR: 78 printf("character"); 79 goto spcl; 80 81 case S_IFDIR: 82 printf("directory\n"); 83 return; 84 85 case S_IFMPC: 86 printf("char multiplexor\n"); 87 return; 88 89 case S_IFMPB: 90 printf("block multiplexor\n"); 91 return; 92 93 case S_IFBLK: 94 printf("block"); 95 96 spcl: 97 printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev)); 98 return; 99 } 100 101 ifile = open(file, 0); 102 if(ifile < 0) { 103 printf("cannot open\n"); 104 return; 105 } 106 in = read(ifile, buf, BUFSIZ); 107 if(in == 0){ 108 printf("empty\n"); 109 return; 110 } 111 switch(*(int *)buf) { 112 113 case 0413: 114 printf("demand paged "); 115 116 case 0410: 117 printf("pure "); 118 goto exec; 119 120 case 0411: 121 printf("jfr or pdp-11 unix 411 executable\n"); 122 return; 123 124 case 0407: 125 exec: 126 printf("executable"); 127 if(((int *)buf)[4] != 0) { 128 printf(" not stripped"); 129 if(oldo(buf)) 130 printf(" (old format symbol table)"); 131 } 132 printf("\n"); 133 goto out; 134 135 case 0177555: 136 printf("very old archive\n"); 137 goto out; 138 139 case 0177545: 140 printf("old archive\n"); 141 goto out; 142 143 case 070707: 144 printf("cpio data\n"); 145 goto out; 146 } 147 148 if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) { 149 printf("archive random library\n"); 150 goto out; 151 } 152 if (strncmp(buf, "!<arch>\n", 8)==0) { 153 printf("archive\n"); 154 goto out; 155 } 156 if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */ 157 lseek(ifile, -512L, 2); /* last block */ 158 if (read(ifile, buf, BUFSIZ) > 0 159 && *(short int *)buf == 12138) { 160 printf("PRESS file\n"); 161 goto out; 162 } 163 } 164 i = 0; 165 if(ccom() == 0)goto notc; 166 while(buf[i] == '#'){ 167 j = i; 168 while(buf[i++] != '\n'){ 169 if(i - j > 255){ 170 printf("data\n"); 171 goto out; 172 } 173 if(i >= in)goto notc; 174 } 175 if(ccom() == 0)goto notc; 176 } 177 check: 178 if(lookup(c) == 1){ 179 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; 180 printf("c program text"); 181 goto outa; 182 } 183 nl = 0; 184 while(buf[i] != '('){ 185 if(buf[i] <= 0) 186 goto notas; 187 if(buf[i] == ';'){ 188 i++; 189 goto check; 190 } 191 if(buf[i++] == '\n') 192 if(nl++ > 6)goto notc; 193 if(i >= in)goto notc; 194 } 195 while(buf[i] != ')'){ 196 if(buf[i++] == '\n') 197 if(nl++ > 6)goto notc; 198 if(i >= in)goto notc; 199 } 200 while(buf[i] != '{'){ 201 if(buf[i++] == '\n') 202 if(nl++ > 6)goto notc; 203 if(i >= in)goto notc; 204 } 205 printf("c program text"); 206 goto outa; 207 notc: 208 i = 0; 209 while(buf[i] == 'c' || buf[i] == '#'){ 210 while(buf[i++] != '\n')if(i >= in)goto notfort; 211 } 212 if(lookup(fort) == 1){ 213 printf("fortran program text"); 214 goto outa; 215 } 216 notfort: 217 i=0; 218 if(ascom() == 0)goto notas; 219 j = i-1; 220 if(buf[i] == '.'){ 221 i++; 222 if(lookup(as) == 1){ 223 printf("assembler program text"); 224 goto outa; 225 } 226 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 227 printf("roff, nroff, or eqn input text"); 228 goto outa; 229 } 230 } 231 while(lookup(asc) == 0){ 232 if(ascom() == 0)goto notas; 233 while(buf[i] != '\n' && buf[i++] != ':') 234 if(i >= in)goto notas; 235 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; 236 j = i-1; 237 if(buf[i] == '.'){ 238 i++; 239 if(lookup(as) == 1){ 240 printf("assembler program text"); 241 goto outa; 242 } 243 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 244 printf("roff, nroff, or eqn input text"); 245 goto outa; 246 } 247 } 248 } 249 printf("assembler program text"); 250 goto outa; 251 notas: 252 for(i=0; i < in; i++)if(buf[i]&0200){ 253 if (buf[0]=='\100' && buf[1]=='\357') { 254 printf("troff (CAT) output\n"); 255 goto out; 256 } 257 printf("data\n"); 258 goto out; 259 } 260 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) 261 printf("commands text"); 262 else if (troffint(buf, in)) 263 printf("troff intermediate output text"); 264 else if (english(buf, in)) 265 printf("English text"); 266 else 267 printf("ascii text"); 268 outa: 269 while(i < in) 270 if((buf[i++]&0377) > 127){ 271 printf(" with garbage\n"); 272 goto out; 273 } 274 /* if next few lines in then read whole file looking for nulls ... 275 while((in = read(ifile,buf,BUFSIZ)) > 0) 276 for(i = 0; i < in; i++) 277 if((buf[i]&0377) > 127){ 278 printf(" with garbage\n"); 279 goto out; 280 } 281 /*.... */ 282 printf("\n"); 283 out:; 284 } 285 286 oldo(cp) 287 char *cp; 288 { 289 struct exec ex; 290 struct stat stb; 291 292 ex = *(struct exec *)cp; 293 if (fstat(ifile, &stb) < 0) 294 return(0); 295 if (N_STROFF(ex)+sizeof(off_t) > stb.st_size) 296 return (1); 297 return (0); 298 } 299 300 301 302 troffint(bp, n) 303 char *bp; 304 int n; 305 { 306 int k; 307 308 i = 0; 309 for (k = 0; k < 6; k++) { 310 if (lookup(troff) == 0) 311 return(0); 312 if (lookup(troff) == 0) 313 return(0); 314 while (i < n && buf[i] != '\n') 315 i++; 316 if (i++ >= n) 317 return(0); 318 } 319 return(1); 320 } 321 lookup(tab) 322 char *tab[]; 323 { 324 char r; 325 int k,j,l; 326 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; 327 for(j=0; tab[j] != 0; j++){ 328 l=0; 329 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); 330 if(r == '\0') 331 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' 332 || buf[k] == '{' || buf[k] == '/'){ 333 i=k; 334 return(1); 335 } 336 } 337 return(0); 338 } 339 ccom(){ 340 char cc; 341 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); 342 if(buf[i] == '/' && buf[i+1] == '*'){ 343 i += 2; 344 while(buf[i] != '*' || buf[i+1] != '/'){ 345 if(buf[i] == '\\')i += 2; 346 else i++; 347 if(i >= in)return(0); 348 } 349 if((i += 2) >= in)return(0); 350 } 351 if(buf[i] == '\n')if(ccom() == 0)return(0); 352 return(1); 353 } 354 ascom(){ 355 while(buf[i] == '/'){ 356 i++; 357 while(buf[i++] != '\n')if(i >= in)return(0); 358 while(buf[i] == '\n')if(i++ >= in)return(0); 359 } 360 return(1); 361 } 362 363 english (bp, n) 364 char *bp; 365 { 366 # define NASC 128 367 int ct[NASC], j, vow, freq, rare; 368 int badpun = 0, punct = 0; 369 if (n<50) return(0); /* no point in statistics on squibs */ 370 for(j=0; j<NASC; j++) 371 ct[j]=0; 372 for(j=0; j<n; j++) 373 { 374 if (bp[j]<NASC) 375 ct[bp[j]|040]++; 376 switch (bp[j]) 377 { 378 case '.': 379 case ',': 380 case ')': 381 case '%': 382 case ';': 383 case ':': 384 case '?': 385 punct++; 386 if ( j < n-1 && 387 bp[j+1] != ' ' && 388 bp[j+1] != '\n') 389 badpun++; 390 } 391 } 392 if (badpun*5 > punct) 393 return(0); 394 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u']; 395 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n']; 396 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z']; 397 if (2*ct[';'] > ct['e']) return(0); 398 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */ 399 return (vow*5 >= n-ct[' '] && freq >= 10*rare); 400 } 401