1 /*- 2 * Copyright (c) 1991 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.proprietary.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1991 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)file.c 5.1 (Berkeley) 06/17/92"; 16 #endif /* not lint */ 17 18 /* 19 * file - determine type of file 20 */ 21 22 #include <sys/param.h> 23 #include <sys/stat.h> 24 #include <string.h> 25 #include <stdio.h> 26 #include <ctype.h> 27 #include <a.out.h> 28 29 #if defined(hp300) || defined(hp800) 30 #include <hp/hpux/hpux_exec.h> 31 #endif 32 33 extern int errno; 34 int in; 35 int i = 0; 36 char buf[BUFSIZ]; 37 char *troff[] = { /* new troff intermediate lang */ 38 "x","T","res","init","font","202","V0","p1",0}; 39 char *fort[] = { 40 "function","subroutine","common","dimension","block","integer", 41 "real","data","double",0}; 42 char *asc[] = { 43 "chmk","mov","tst","clr","jmp",0}; 44 char *c[] = { 45 "int","char","float","double","struct","extern",0}; 46 char *as[] = { 47 "globl","byte","align","text","data","comm",0}; 48 char *sh[] = { 49 "fi", "elif", "esac", "done", "export", 50 "readonly", "trap", "PATH", "HOME", 0 }; 51 char *csh[] = { 52 "alias", "breaksw", "endsw", "foreach", "limit", "onintr", 53 "repeat", "setenv", "source", "path", "home", 0 }; 54 int ifile; 55 56 main(argc, argv) 57 char **argv; 58 { 59 FILE *fl; 60 register char *p; 61 char ap[MAXPATHLEN + 1]; 62 63 if (argc < 2) { 64 fprintf(stderr, "usage: %s file ...\n", argv[0]); 65 exit(3); 66 } 67 68 if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') { 69 if ((fl = fopen(argv[2], "r")) == NULL) { 70 perror(argv[2]); 71 exit(2); 72 } 73 while ((p = fgets(ap, sizeof ap, fl)) != NULL) { 74 int l = strlen(p); 75 if (l>0) 76 p[l-1] = '\0'; 77 type(p); 78 if (ifile>=0) 79 close(ifile); 80 } 81 exit(1); 82 } 83 while(argc > 1) { 84 ifile = -1; 85 type(argv[1]); 86 fflush(stdout); 87 argc--; 88 argv++; 89 if (ifile >= 0) 90 close(ifile); 91 } 92 exit(0); 93 } 94 95 type(file) 96 char *file; 97 { 98 int j,nl; 99 char ch; 100 struct stat mbuf; 101 char slink[MAXPATHLEN + 1]; 102 struct exec *hdr; 103 #if defined(hp300) || defined(hp800) 104 int ishpux300 = 0; 105 int ishpux800 = 0; 106 #endif 107 108 if (lstat(file, &mbuf) < 0) { 109 fprintf(stderr, "file: %s: %s\n", file, strerror(errno)); 110 return; 111 } 112 switch (mbuf.st_mode & S_IFMT) { 113 case S_IFLNK: 114 printf("%s:\tsymbolic link", file); 115 j = readlink(file, slink, sizeof slink - 1); 116 if (j >= 0) { 117 slink[j] = '\0'; 118 printf(" to %s", slink); 119 } 120 printf("\n"); 121 return; 122 123 case S_IFDIR: 124 printf("%s:\t", file); 125 if (mbuf.st_mode & S_ISVTX) 126 printf("append-only "); 127 printf("directory\n"); 128 return; 129 130 case S_IFCHR: 131 case S_IFBLK: 132 printf("%s:\t%s special (%d/%d)\n", file, 133 (mbuf.st_mode&S_IFMT) == S_IFCHR ? "character" : "block", 134 major(mbuf.st_rdev), minor(mbuf.st_rdev)); 135 return; 136 137 case S_IFSOCK: 138 printf("%s:\tsocket\n", file); 139 return; 140 } 141 142 ifile = open(file, 0); 143 if (ifile < 0) { 144 fprintf(stderr, "file: %s: %s\n", file, strerror(errno)); 145 return; 146 } 147 printf("%s:\t", file); 148 in = read(ifile, buf, BUFSIZ); 149 if (in == 0) { 150 printf("empty\n"); 151 return; 152 } 153 hdr = (struct exec *) buf; 154 #ifdef MID_ZERO /* if we have a_mid field */ 155 switch (hdr->a_mid) { 156 case MID_SUN010: 157 printf("SUN 68010/68020 "); 158 break; 159 case MID_SUN020: 160 printf("SUN 68020 "); 161 break; 162 case MID_HP200: 163 printf("HP200 "); 164 break; 165 case MID_HP300: 166 printf("HP300 "); 167 break; 168 #if defined(hp300) || defined(hp800) 169 case MID_HPUX: 170 if (((struct hpux_exec *)buf)->ha_version == BSDVNUM) 171 printf("BSD generated "); 172 printf("HP-UX series 200/300 "); 173 ishpux300 = 1; 174 if (hdr->a_magic == 0406) { 175 printf("relocatable object\n"); 176 return; 177 } 178 break; 179 case MID_HPUX800: 180 printf("HP-UX series 800 "); 181 ishpux800 = 1; 182 if (hdr->a_magic == 0x106) { 183 printf("relocatable object\n"); 184 return; 185 } 186 break; 187 #endif 188 #if BYTE_ORDER == BIG_ENDIAN 189 case ((OMAGIC & 0xff) << 8) | (OMAGIC >> 8): 190 case ((NMAGIC & 0xff) << 8) | (NMAGIC >> 8): 191 case ((ZMAGIC & 0xff) << 8) | (ZMAGIC >> 8): 192 printf("byte-swapped (VAX/386) "); 193 hdr->a_magic = ((hdr->a_mid & 0xff) << 8) | (hdr->a_mid >> 8); 194 break; 195 } 196 #endif 197 #endif /* MID_ZERO, a_mid */ 198 switch (hdr->a_magic) { 199 200 case 0411: 201 printf("jfr or pdp-11 unix 411 executable\n"); 202 return; 203 204 case ZMAGIC: 205 printf("demand paged "); 206 /* FALLTHROUGH */ 207 208 case NMAGIC: 209 printf("pure "); 210 /* FALLTHROUGH */ 211 212 case OMAGIC: 213 if (mbuf.st_mode & S_ISUID) 214 printf("set-uid "); 215 if (mbuf.st_mode & S_ISGID) 216 printf("set-gid "); 217 if (mbuf.st_mode & S_ISVTX) 218 printf("sticky "); 219 if ((mbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 && 220 (hdr->a_trsize || hdr->a_drsize)) { 221 printf("relocatable object\n"); 222 return; 223 } 224 printf("executable"); 225 #if defined(hp300) || defined(hp800) 226 if (ishpux300) { 227 if (((int *)buf)[9] != 0) 228 printf(" not stripped"); 229 } else if (ishpux800) { 230 if (((int *)buf)[24] != 0) 231 printf(" not stripped"); 232 } else 233 #endif 234 if (hdr->a_syms != 0) 235 printf(" not stripped"); 236 printf("\n"); 237 return; 238 } 239 240 switch (*(int *)buf) { 241 case 0177555: 242 printf("very old archive\n"); 243 return; 244 245 case 0177545: 246 printf("old archive\n"); 247 return; 248 249 case 070707: 250 printf("cpio data\n"); 251 return; 252 } 253 254 if (buf[0] == '#' && buf[1] == '!' && shellscript(buf+2, &mbuf)) 255 return; 256 if (buf[0] == '\037' && buf[1] == '\235') { 257 if (buf[2]&0x80) 258 printf("block "); 259 printf("compressed %d bit code data\n", buf[2]&0x1f); 260 return; 261 } 262 if (strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) { 263 printf("archive random library\n"); 264 return; 265 } 266 if (strncmp(buf, "!<arch>\n", 8)==0) { 267 printf("archive\n"); 268 return; 269 } 270 if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */ 271 lseek(ifile, -512L, 2); /* last block */ 272 if (read(ifile, buf, BUFSIZ) > 0 && *(short *)buf == 12138) { 273 printf("PRESS file\n"); 274 return; 275 } 276 } 277 i = 0; 278 if(ccom() == 0)goto notc; 279 while(buf[i] == '#'){ 280 j = i; 281 while(buf[i++] != '\n'){ 282 if(i - j > 255){ 283 printf("data\n"); 284 return; 285 } 286 if(i >= in)goto notc; 287 } 288 if(ccom() == 0)goto notc; 289 } 290 check: 291 if(lookup(c) == 1){ 292 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; 293 printf("c program text"); 294 goto outa; 295 } 296 nl = 0; 297 while(buf[i] != '('){ 298 if(buf[i] <= 0) 299 goto notas; 300 if(buf[i] == ';'){ 301 i++; 302 goto check; 303 } 304 if(buf[i++] == '\n') 305 if(nl++ > 6)goto notc; 306 if(i >= in)goto notc; 307 } 308 while(buf[i] != ')'){ 309 if(buf[i++] == '\n') 310 if(nl++ > 6)goto notc; 311 if(i >= in)goto notc; 312 } 313 while(buf[i] != '{'){ 314 if(buf[i++] == '\n') 315 if(nl++ > 6)goto notc; 316 if(i >= in)goto notc; 317 } 318 printf("c program text"); 319 goto outa; 320 notc: 321 i = 0; 322 while(buf[i] == 'c' || buf[i] == '#'){ 323 while(buf[i++] != '\n')if(i >= in)goto notfort; 324 } 325 if(lookup(fort) == 1){ 326 printf("fortran program text"); 327 goto outa; 328 } 329 notfort: 330 i=0; 331 if(ascom() == 0)goto notas; 332 j = i-1; 333 if(buf[i] == '.'){ 334 i++; 335 if(lookup(as) == 1){ 336 printf("assembler program text"); 337 goto outa; 338 } 339 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 340 printf("roff, nroff, or eqn input text"); 341 goto outa; 342 } 343 } 344 while(lookup(asc) == 0){ 345 if(ascom() == 0)goto notas; 346 while(buf[i] != '\n' && buf[i++] != ':') 347 if(i >= in)goto notas; 348 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; 349 j = i-1; 350 if(buf[i] == '.'){ 351 i++; 352 if(lookup(as) == 1){ 353 printf("assembler program text"); 354 goto outa; 355 } 356 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 357 printf("roff, nroff, or eqn input text"); 358 goto outa; 359 } 360 } 361 } 362 printf("assembler program text"); 363 goto outa; 364 notas: 365 for(i=0; i < in; i++)if(buf[i]&0200){ 366 if (buf[0]=='\100' && buf[1]=='\357') 367 printf("troff (CAT) output\n"); 368 else 369 printf("data\n"); 370 return; 371 } 372 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) { 373 if (mbuf.st_mode & S_ISUID) 374 printf("set-uid "); 375 if (mbuf.st_mode & S_ISGID) 376 printf("set-gid "); 377 if (mbuf.st_mode & S_ISVTX) 378 printf("sticky "); 379 if (shell(buf, in, sh)) 380 printf("shell script"); 381 else if (shell(buf, in, csh)) 382 printf("c-shell script"); 383 else 384 printf("commands text"); 385 } else if (troffint(buf, in)) 386 printf("troff intermediate output text"); 387 else if (shell(buf, in, sh)) 388 printf("shell commands"); 389 else if (shell(buf, in, csh)) 390 printf("c-shell commands"); 391 else if (english(buf, in)) 392 printf("English text"); 393 else 394 printf("ascii text"); 395 outa: 396 while(i < in) 397 if((buf[i++]&0377) > 127){ 398 printf(" with garbage\n"); 399 return; 400 } 401 /* if next few lines in then read whole file looking for nulls ... 402 while((in = read(ifile,buf,BUFSIZ)) > 0) 403 for(i = 0; i < in; i++) 404 if((buf[i]&0377) > 127){ 405 printf(" with garbage\n"); 406 return; 407 } 408 /*.... */ 409 printf("\n"); 410 } 411 412 troffint(bp, n) 413 char *bp; 414 int n; 415 { 416 int k; 417 418 i = 0; 419 for (k = 0; k < 6; k++) { 420 if (lookup(troff) == 0) 421 return(0); 422 if (lookup(troff) == 0) 423 return(0); 424 while (i < n && buf[i] != '\n') 425 i++; 426 if (i++ >= n) 427 return(0); 428 } 429 return(1); 430 } 431 lookup(tab) 432 char *tab[]; 433 { 434 char r; 435 int k,j,l; 436 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; 437 for(j=0; tab[j] != 0; j++){ 438 l=0; 439 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); 440 if(r == '\0') 441 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' 442 || buf[k] == '{' || buf[k] == '/'){ 443 i=k; 444 return(1); 445 } 446 } 447 return(0); 448 } 449 ccom(){ 450 char cc; 451 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); 452 if(buf[i] == '/' && buf[i+1] == '*'){ 453 i += 2; 454 while(buf[i] != '*' || buf[i+1] != '/'){ 455 if(buf[i] == '\\')i += 2; 456 else i++; 457 if(i >= in)return(0); 458 } 459 if((i += 2) >= in)return(0); 460 } 461 if(buf[i] == '\n')if(ccom() == 0)return(0); 462 return(1); 463 } 464 ascom(){ 465 while(buf[i] == '/'){ 466 i++; 467 while(buf[i++] != '\n')if(i >= in)return(0); 468 while(buf[i] == '\n')if(i++ >= in)return(0); 469 } 470 return(1); 471 } 472 473 english (bp, n) 474 char *bp; 475 { 476 # define NASC 128 477 int ct[NASC], j, vow, freq, rare; 478 int badpun = 0, punct = 0; 479 if (n<50) return(0); /* no point in statistics on squibs */ 480 for(j=0; j<NASC; j++) 481 ct[j]=0; 482 for(j=0; j<n; j++) 483 { 484 if ((u_char)bp[j]<NASC) 485 ct[bp[j]|040]++; 486 switch (bp[j]) 487 { 488 case '.': 489 case ',': 490 case ')': 491 case '%': 492 case ';': 493 case ':': 494 case '?': 495 punct++; 496 if ( j < n-1 && 497 bp[j+1] != ' ' && 498 bp[j+1] != '\n') 499 badpun++; 500 } 501 } 502 if (badpun*5 > punct) 503 return(0); 504 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u']; 505 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n']; 506 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z']; 507 if (2*ct[';'] > ct['e']) return(0); 508 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */ 509 return (vow*5 >= n-ct[' '] && freq >= 10*rare); 510 } 511 512 shellscript(buf, sb) 513 char buf[]; 514 struct stat *sb; 515 { 516 register char *tp; 517 char *cp, *xp, *index(); 518 519 cp = index(buf, '\n'); 520 if (cp == 0 || cp - buf > in) 521 return (0); 522 for (tp = buf; tp != cp && isspace(*tp); tp++) 523 if (!isascii(*tp)) 524 return (0); 525 for (xp = tp; tp != cp && !isspace(*tp); tp++) 526 if (!isascii(*tp)) 527 return (0); 528 if (tp == xp) 529 return (0); 530 if (sb->st_mode & S_ISUID) 531 printf("set-uid "); 532 if (sb->st_mode & S_ISGID) 533 printf("set-gid "); 534 if (strncmp(xp, "/bin/sh", tp-xp) == 0) 535 xp = "shell"; 536 else if (strncmp(xp, "/bin/csh", tp-xp) == 0) 537 xp = "c-shell"; 538 else 539 *tp = '\0'; 540 printf("executable %s script\n", xp); 541 return (1); 542 } 543 544 shell(bp, n, tab) 545 char *bp; 546 int n; 547 char *tab[]; 548 { 549 550 i = 0; 551 do { 552 if (buf[i] == '#' || buf[i] == ':') 553 while (i < n && buf[i] != '\n') 554 i++; 555 if (++i >= n) 556 break; 557 if (lookup(tab) == 1) 558 return (1); 559 } while (i < n); 560 return (0); 561 } 562