1 static char sccsid[] = "@(#)file.c 4.4 (Berkeley) 4.4"; 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 (lstat(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_IFLNK: 82 printf("symbolic link\n"); 83 return; 84 85 case S_IFDIR: 86 printf("directory\n"); 87 return; 88 89 case S_IFBLK: 90 printf("block"); 91 92 spcl: 93 printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev)); 94 return; 95 } 96 97 ifile = open(file, 0); 98 if(ifile < 0) { 99 printf("cannot open\n"); 100 return; 101 } 102 in = read(ifile, buf, BUFSIZ); 103 if(in == 0){ 104 printf("empty\n"); 105 return; 106 } 107 switch(*(int *)buf) { 108 109 case 0413: 110 printf("demand paged "); 111 112 case 0410: 113 printf("pure "); 114 goto exec; 115 116 case 0411: 117 printf("jfr or pdp-11 unix 411 executable\n"); 118 return; 119 120 case 0407: 121 exec: 122 printf("executable"); 123 if(((int *)buf)[4] != 0) { 124 printf(" not stripped"); 125 if(oldo(buf)) 126 printf(" (old format symbol table)"); 127 } 128 printf("\n"); 129 goto out; 130 131 case 0177555: 132 printf("very old archive\n"); 133 goto out; 134 135 case 0177545: 136 printf("old archive\n"); 137 goto out; 138 139 case 070707: 140 printf("cpio data\n"); 141 goto out; 142 } 143 144 if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) { 145 printf("archive random library\n"); 146 goto out; 147 } 148 if (strncmp(buf, "!<arch>\n", 8)==0) { 149 printf("archive\n"); 150 goto out; 151 } 152 if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */ 153 lseek(ifile, -512L, 2); /* last block */ 154 if (read(ifile, buf, BUFSIZ) > 0 155 && *(short int *)buf == 12138) { 156 printf("PRESS file\n"); 157 goto out; 158 } 159 } 160 i = 0; 161 if(ccom() == 0)goto notc; 162 while(buf[i] == '#'){ 163 j = i; 164 while(buf[i++] != '\n'){ 165 if(i - j > 255){ 166 printf("data\n"); 167 goto out; 168 } 169 if(i >= in)goto notc; 170 } 171 if(ccom() == 0)goto notc; 172 } 173 check: 174 if(lookup(c) == 1){ 175 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; 176 printf("c program text"); 177 goto outa; 178 } 179 nl = 0; 180 while(buf[i] != '('){ 181 if(buf[i] <= 0) 182 goto notas; 183 if(buf[i] == ';'){ 184 i++; 185 goto check; 186 } 187 if(buf[i++] == '\n') 188 if(nl++ > 6)goto notc; 189 if(i >= in)goto notc; 190 } 191 while(buf[i] != ')'){ 192 if(buf[i++] == '\n') 193 if(nl++ > 6)goto notc; 194 if(i >= in)goto notc; 195 } 196 while(buf[i] != '{'){ 197 if(buf[i++] == '\n') 198 if(nl++ > 6)goto notc; 199 if(i >= in)goto notc; 200 } 201 printf("c program text"); 202 goto outa; 203 notc: 204 i = 0; 205 while(buf[i] == 'c' || buf[i] == '#'){ 206 while(buf[i++] != '\n')if(i >= in)goto notfort; 207 } 208 if(lookup(fort) == 1){ 209 printf("fortran program text"); 210 goto outa; 211 } 212 notfort: 213 i=0; 214 if(ascom() == 0)goto notas; 215 j = i-1; 216 if(buf[i] == '.'){ 217 i++; 218 if(lookup(as) == 1){ 219 printf("assembler program text"); 220 goto outa; 221 } 222 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 223 printf("roff, nroff, or eqn input text"); 224 goto outa; 225 } 226 } 227 while(lookup(asc) == 0){ 228 if(ascom() == 0)goto notas; 229 while(buf[i] != '\n' && buf[i++] != ':') 230 if(i >= in)goto notas; 231 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; 232 j = i-1; 233 if(buf[i] == '.'){ 234 i++; 235 if(lookup(as) == 1){ 236 printf("assembler program text"); 237 goto outa; 238 } 239 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 240 printf("roff, nroff, or eqn input text"); 241 goto outa; 242 } 243 } 244 } 245 printf("assembler program text"); 246 goto outa; 247 notas: 248 for(i=0; i < in; i++)if(buf[i]&0200){ 249 if (buf[0]=='\100' && buf[1]=='\357') { 250 printf("troff (CAT) output\n"); 251 goto out; 252 } 253 printf("data\n"); 254 goto out; 255 } 256 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) 257 printf("commands text"); 258 else if (troffint(buf, in)) 259 printf("troff intermediate output text"); 260 else if (english(buf, in)) 261 printf("English text"); 262 else 263 printf("ascii text"); 264 outa: 265 while(i < in) 266 if((buf[i++]&0377) > 127){ 267 printf(" with garbage\n"); 268 goto out; 269 } 270 /* if next few lines in then read whole file looking for nulls ... 271 while((in = read(ifile,buf,BUFSIZ)) > 0) 272 for(i = 0; i < in; i++) 273 if((buf[i]&0377) > 127){ 274 printf(" with garbage\n"); 275 goto out; 276 } 277 /*.... */ 278 printf("\n"); 279 out:; 280 } 281 282 oldo(cp) 283 char *cp; 284 { 285 struct exec ex; 286 struct stat stb; 287 288 ex = *(struct exec *)cp; 289 if (fstat(ifile, &stb) < 0) 290 return(0); 291 if (N_STROFF(ex)+sizeof(off_t) > stb.st_size) 292 return (1); 293 return (0); 294 } 295 296 297 298 troffint(bp, n) 299 char *bp; 300 int n; 301 { 302 int k; 303 304 i = 0; 305 for (k = 0; k < 6; k++) { 306 if (lookup(troff) == 0) 307 return(0); 308 if (lookup(troff) == 0) 309 return(0); 310 while (i < n && buf[i] != '\n') 311 i++; 312 if (i++ >= n) 313 return(0); 314 } 315 return(1); 316 } 317 lookup(tab) 318 char *tab[]; 319 { 320 char r; 321 int k,j,l; 322 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; 323 for(j=0; tab[j] != 0; j++){ 324 l=0; 325 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); 326 if(r == '\0') 327 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' 328 || buf[k] == '{' || buf[k] == '/'){ 329 i=k; 330 return(1); 331 } 332 } 333 return(0); 334 } 335 ccom(){ 336 char cc; 337 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); 338 if(buf[i] == '/' && buf[i+1] == '*'){ 339 i += 2; 340 while(buf[i] != '*' || buf[i+1] != '/'){ 341 if(buf[i] == '\\')i += 2; 342 else i++; 343 if(i >= in)return(0); 344 } 345 if((i += 2) >= in)return(0); 346 } 347 if(buf[i] == '\n')if(ccom() == 0)return(0); 348 return(1); 349 } 350 ascom(){ 351 while(buf[i] == '/'){ 352 i++; 353 while(buf[i++] != '\n')if(i >= in)return(0); 354 while(buf[i] == '\n')if(i++ >= in)return(0); 355 } 356 return(1); 357 } 358 359 english (bp, n) 360 char *bp; 361 { 362 # define NASC 128 363 int ct[NASC], j, vow, freq, rare; 364 int badpun = 0, punct = 0; 365 if (n<50) return(0); /* no point in statistics on squibs */ 366 for(j=0; j<NASC; j++) 367 ct[j]=0; 368 for(j=0; j<n; j++) 369 { 370 if (bp[j]<NASC) 371 ct[bp[j]|040]++; 372 switch (bp[j]) 373 { 374 case '.': 375 case ',': 376 case ')': 377 case '%': 378 case ';': 379 case ':': 380 case '?': 381 punct++; 382 if ( j < n-1 && 383 bp[j+1] != ' ' && 384 bp[j+1] != '\n') 385 badpun++; 386 } 387 } 388 if (badpun*5 > punct) 389 return(0); 390 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u']; 391 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n']; 392 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z']; 393 if (2*ct[';'] > ct['e']) return(0); 394 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */ 395 return (vow*5 >= n-ct[' '] && freq >= 10*rare); 396 } 397