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.2 (Berkeley) 01/11/93"; 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 printf("HP-UX series [234]00 "); 171 ishpux300 = 1; 172 if (hdr->a_magic == 0406) { 173 printf("relocatable object\n"); 174 return; 175 } 176 break; 177 case MID_HPUX800: 178 printf("HP-UX series 800 "); 179 ishpux800 = 1; 180 if (hdr->a_magic == 0x106) { 181 printf("relocatable object\n"); 182 return; 183 } 184 break; 185 #endif 186 #if BYTE_ORDER == BIG_ENDIAN 187 case ((OMAGIC & 0xff) << 8) | (OMAGIC >> 8): 188 case ((NMAGIC & 0xff) << 8) | (NMAGIC >> 8): 189 case ((ZMAGIC & 0xff) << 8) | (ZMAGIC >> 8): 190 printf("byte-swapped (VAX/386) "); 191 hdr->a_magic = ((hdr->a_mid & 0xff) << 8) | (hdr->a_mid >> 8); 192 break; 193 } 194 #endif 195 #endif /* MID_ZERO, a_mid */ 196 switch (hdr->a_magic) { 197 198 case 0411: 199 printf("jfr or pdp-11 unix 411 executable\n"); 200 return; 201 202 case ZMAGIC: 203 printf("demand paged "); 204 /* FALLTHROUGH */ 205 206 case NMAGIC: 207 printf("pure "); 208 /* FALLTHROUGH */ 209 210 case OMAGIC: 211 if (mbuf.st_mode & S_ISUID) 212 printf("set-uid "); 213 if (mbuf.st_mode & S_ISGID) 214 printf("set-gid "); 215 if (mbuf.st_mode & S_ISVTX) 216 printf("sticky "); 217 if ((mbuf.st_mode & (S_IXUSR|S_IXGRP|S_IXOTH)) == 0 && 218 (hdr->a_trsize || hdr->a_drsize)) { 219 printf("relocatable object\n"); 220 return; 221 } 222 #if defined(hp300) 223 if (ishpux300) { 224 if (((int *)buf)[2] & 0x40000000) 225 printf("dynamically-linked "); 226 } 227 #endif 228 printf("executable"); 229 #if defined(hp300) || defined(hp800) 230 if (ishpux300) { 231 if (((int *)buf)[9] != 0) 232 printf(" not stripped"); 233 } else if (ishpux800) { 234 if (((int *)buf)[24] != 0) 235 printf(" not stripped"); 236 } else 237 #endif 238 if (hdr->a_syms != 0) 239 printf(" not stripped"); 240 printf("\n"); 241 return; 242 #if defined(hp300) 243 case 0x10e: 244 printf("shared library, version %d\n", ((short *)buf)[2]); 245 return; 246 #endif 247 } 248 249 switch (*(int *)buf) { 250 case 0177555: 251 printf("very old archive\n"); 252 return; 253 254 case 0177545: 255 printf("old archive\n"); 256 return; 257 258 case 070707: 259 printf("cpio data\n"); 260 return; 261 } 262 263 if (buf[0] == '#' && buf[1] == '!' && shellscript(buf+2, &mbuf)) 264 return; 265 if (buf[0] == '\037' && buf[1] == '\235') { 266 if (buf[2]&0x80) 267 printf("block "); 268 printf("compressed %d bit code data\n", buf[2]&0x1f); 269 return; 270 } 271 if (strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) { 272 printf("archive random library\n"); 273 return; 274 } 275 if (strncmp(buf, "!<arch>\n", 8)==0) { 276 printf("archive\n"); 277 return; 278 } 279 if (mbuf.st_size % 512 == 0) { /* it may be a PRESS file */ 280 lseek(ifile, -512L, 2); /* last block */ 281 if (read(ifile, buf, BUFSIZ) > 0 && *(short *)buf == 12138) { 282 printf("PRESS file\n"); 283 return; 284 } 285 } 286 i = 0; 287 if(ccom() == 0)goto notc; 288 while(buf[i] == '#'){ 289 j = i; 290 while(buf[i++] != '\n'){ 291 if(i - j > 255){ 292 printf("data\n"); 293 return; 294 } 295 if(i >= in)goto notc; 296 } 297 if(ccom() == 0)goto notc; 298 } 299 check: 300 if(lookup(c) == 1){ 301 while((ch = buf[i++]) != ';' && ch != '{')if(i >= in)goto notc; 302 printf("c program text"); 303 goto outa; 304 } 305 nl = 0; 306 while(buf[i] != '('){ 307 if(buf[i] <= 0) 308 goto notas; 309 if(buf[i] == ';'){ 310 i++; 311 goto check; 312 } 313 if(buf[i++] == '\n') 314 if(nl++ > 6)goto notc; 315 if(i >= in)goto notc; 316 } 317 while(buf[i] != ')'){ 318 if(buf[i++] == '\n') 319 if(nl++ > 6)goto notc; 320 if(i >= in)goto notc; 321 } 322 while(buf[i] != '{'){ 323 if(buf[i++] == '\n') 324 if(nl++ > 6)goto notc; 325 if(i >= in)goto notc; 326 } 327 printf("c program text"); 328 goto outa; 329 notc: 330 i = 0; 331 while(buf[i] == 'c' || buf[i] == '#'){ 332 while(buf[i++] != '\n')if(i >= in)goto notfort; 333 } 334 if(lookup(fort) == 1){ 335 printf("fortran program text"); 336 goto outa; 337 } 338 notfort: 339 i=0; 340 if(ascom() == 0)goto notas; 341 j = i-1; 342 if(buf[i] == '.'){ 343 i++; 344 if(lookup(as) == 1){ 345 printf("assembler program text"); 346 goto outa; 347 } 348 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 349 printf("roff, nroff, or eqn input text"); 350 goto outa; 351 } 352 } 353 while(lookup(asc) == 0){ 354 if(ascom() == 0)goto notas; 355 while(buf[i] != '\n' && buf[i++] != ':') 356 if(i >= in)goto notas; 357 while(buf[i] == '\n' || buf[i] == ' ' || buf[i] == '\t')if(i++ >= in)goto notas; 358 j = i-1; 359 if(buf[i] == '.'){ 360 i++; 361 if(lookup(as) == 1){ 362 printf("assembler program text"); 363 goto outa; 364 } 365 else if(buf[j] == '\n' && isalpha(buf[j+2])){ 366 printf("roff, nroff, or eqn input text"); 367 goto outa; 368 } 369 } 370 } 371 printf("assembler program text"); 372 goto outa; 373 notas: 374 for(i=0; i < in; i++)if(buf[i]&0200){ 375 if (buf[0]=='\100' && buf[1]=='\357') 376 printf("troff (CAT) output\n"); 377 else 378 printf("data\n"); 379 return; 380 } 381 if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) { 382 if (mbuf.st_mode & S_ISUID) 383 printf("set-uid "); 384 if (mbuf.st_mode & S_ISGID) 385 printf("set-gid "); 386 if (mbuf.st_mode & S_ISVTX) 387 printf("sticky "); 388 if (shell(buf, in, sh)) 389 printf("shell script"); 390 else if (shell(buf, in, csh)) 391 printf("c-shell script"); 392 else 393 printf("commands text"); 394 } else if (troffint(buf, in)) 395 printf("troff intermediate output text"); 396 else if (shell(buf, in, sh)) 397 printf("shell commands"); 398 else if (shell(buf, in, csh)) 399 printf("c-shell commands"); 400 else if (english(buf, in)) 401 printf("English text"); 402 else 403 printf("ascii text"); 404 outa: 405 while(i < in) 406 if((buf[i++]&0377) > 127){ 407 printf(" with garbage\n"); 408 return; 409 } 410 /* if next few lines in then read whole file looking for nulls ... 411 while((in = read(ifile,buf,BUFSIZ)) > 0) 412 for(i = 0; i < in; i++) 413 if((buf[i]&0377) > 127){ 414 printf(" with garbage\n"); 415 return; 416 } 417 /*.... */ 418 printf("\n"); 419 } 420 421 troffint(bp, n) 422 char *bp; 423 int n; 424 { 425 int k; 426 427 i = 0; 428 for (k = 0; k < 6; k++) { 429 if (lookup(troff) == 0) 430 return(0); 431 if (lookup(troff) == 0) 432 return(0); 433 while (i < n && buf[i] != '\n') 434 i++; 435 if (i++ >= n) 436 return(0); 437 } 438 return(1); 439 } 440 lookup(tab) 441 char *tab[]; 442 { 443 char r; 444 int k,j,l; 445 while(buf[i] == ' ' || buf[i] == '\t' || buf[i] == '\n')i++; 446 for(j=0; tab[j] != 0; j++){ 447 l=0; 448 for(k=i; ((r=tab[j][l++]) == buf[k] && r != '\0');k++); 449 if(r == '\0') 450 if(buf[k] == ' ' || buf[k] == '\n' || buf[k] == '\t' 451 || buf[k] == '{' || buf[k] == '/'){ 452 i=k; 453 return(1); 454 } 455 } 456 return(0); 457 } 458 ccom(){ 459 char cc; 460 while((cc = buf[i]) == ' ' || cc == '\t' || cc == '\n')if(i++ >= in)return(0); 461 if(buf[i] == '/' && buf[i+1] == '*'){ 462 i += 2; 463 while(buf[i] != '*' || buf[i+1] != '/'){ 464 if(buf[i] == '\\')i += 2; 465 else i++; 466 if(i >= in)return(0); 467 } 468 if((i += 2) >= in)return(0); 469 } 470 if(buf[i] == '\n')if(ccom() == 0)return(0); 471 return(1); 472 } 473 ascom(){ 474 while(buf[i] == '/'){ 475 i++; 476 while(buf[i++] != '\n')if(i >= in)return(0); 477 while(buf[i] == '\n')if(i++ >= in)return(0); 478 } 479 return(1); 480 } 481 482 english (bp, n) 483 char *bp; 484 { 485 # define NASC 128 486 int ct[NASC], j, vow, freq, rare; 487 int badpun = 0, punct = 0; 488 if (n<50) return(0); /* no point in statistics on squibs */ 489 for(j=0; j<NASC; j++) 490 ct[j]=0; 491 for(j=0; j<n; j++) 492 { 493 if ((u_char)bp[j]<NASC) 494 ct[bp[j]|040]++; 495 switch (bp[j]) 496 { 497 case '.': 498 case ',': 499 case ')': 500 case '%': 501 case ';': 502 case ':': 503 case '?': 504 punct++; 505 if ( j < n-1 && 506 bp[j+1] != ' ' && 507 bp[j+1] != '\n') 508 badpun++; 509 } 510 } 511 if (badpun*5 > punct) 512 return(0); 513 vow = ct['a'] + ct['e'] + ct['i'] + ct['o'] + ct['u']; 514 freq = ct['e'] + ct['t'] + ct['a'] + ct['i'] + ct['o'] + ct['n']; 515 rare = ct['v'] + ct['j'] + ct['k'] + ct['q'] + ct['x'] + ct['z']; 516 if (2*ct[';'] > ct['e']) return(0); 517 if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */ 518 return (vow*5 >= n-ct[' '] && freq >= 10*rare); 519 } 520 521 shellscript(buf, sb) 522 char buf[]; 523 struct stat *sb; 524 { 525 register char *tp; 526 char *cp, *xp, *index(); 527 528 cp = index(buf, '\n'); 529 if (cp == 0 || cp - buf > in) 530 return (0); 531 for (tp = buf; tp != cp && isspace(*tp); tp++) 532 if (!isascii(*tp)) 533 return (0); 534 for (xp = tp; tp != cp && !isspace(*tp); tp++) 535 if (!isascii(*tp)) 536 return (0); 537 if (tp == xp) 538 return (0); 539 if (sb->st_mode & S_ISUID) 540 printf("set-uid "); 541 if (sb->st_mode & S_ISGID) 542 printf("set-gid "); 543 if (strncmp(xp, "/bin/sh", tp-xp) == 0) 544 xp = "shell"; 545 else if (strncmp(xp, "/bin/csh", tp-xp) == 0) 546 xp = "c-shell"; 547 else 548 *tp = '\0'; 549 printf("executable %s script\n", xp); 550 return (1); 551 } 552 553 shell(bp, n, tab) 554 char *bp; 555 int n; 556 char *tab[]; 557 { 558 559 i = 0; 560 do { 561 if (buf[i] == '#' || buf[i] == ':') 562 while (i < n && buf[i] != '\n') 563 i++; 564 if (++i >= n) 565 break; 566 if (lookup(tab) == 1) 567 return (1); 568 } while (i < n); 569 return (0); 570 } 571