BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / file / file.c
index dbe5061..a14c39b 100644 (file)
@@ -1,14 +1,19 @@
-static char sccsid[] = "@(#)file.c 4.1 10/1/80";
+#ifndef lint
+static char sccsid[] = "@(#)file.c     4.17 (Berkeley) 7/1/90";
+#endif
 /*
  * file - determine type of file
  */
 
 /*
  * file - determine type of file
  */
 
-#include <pagsiz.h>
-#include <sys/types.h>
-#include <stat.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <string.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
+
+extern int     errno;
+
 int in;
 int i  = 0;
 char buf[BUFSIZ];
 int in;
 int i  = 0;
 char buf[BUFSIZ];
@@ -23,6 +28,12 @@ char *c[] = {
        "int","char","float","double","struct","extern",0};
 char *as[] = {
        "globl","byte","align","text","data","comm",0};
        "int","char","float","double","struct","extern",0};
 char *as[] = {
        "globl","byte","align","text","data","comm",0};
+char *sh[] = {
+       "fi", "elif", "esac", "done", "export",
+       "readonly", "trap", "PATH", "HOME", 0 };
+char *csh[] = {
+       "alias", "breaksw", "endsw", "foreach", "limit",  "onintr",
+       "repeat", "setenv", "source", "path", "home", 0 };
 int    ifile;
 
 main(argc, argv)
 int    ifile;
 
 main(argc, argv)
@@ -30,19 +41,22 @@ char **argv;
 {
        FILE *fl;
        register char *p;
 {
        FILE *fl;
        register char *p;
-       char ap[128];
-       extern char _sobuf[];
+       char ap[MAXPATHLEN + 1];
 
 
+       if (argc < 2) {
+               fprintf(stderr, "usage: %s file ...\n", argv[0]);
+               exit(3);
+       }
+               
        if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
                if ((fl = fopen(argv[2], "r")) == NULL) {
        if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
                if ((fl = fopen(argv[2], "r")) == NULL) {
-                       printf("Can't open %s\n", argv[2]);
+                       perror(argv[2]);
                        exit(2);
                }
                        exit(2);
                }
-               while ((p = fgets(ap, 128, fl)) != NULL) {
+               while ((p = fgets(ap, sizeof ap, fl)) != NULL) {
                        int l = strlen(p);
                        if (l>0)
                                p[l-1] = '\0';
                        int l = strlen(p);
                        if (l>0)
                                p[l-1] = '\0';
-                       printf("%s:     ", p);
                        type(p);
                        if (ifile>=0)
                                close(ifile);
                        type(p);
                        if (ifile>=0)
                                close(ifile);
@@ -50,7 +64,6 @@ char **argv;
                exit(1);
        }
        while(argc > 1) {
                exit(1);
        }
        while(argc > 1) {
-               printf("%s:     ", argv[1]);
                type(argv[1]);
                fflush(stdout);
                argc--;
                type(argv[1]);
                fflush(stdout);
                argc--;
@@ -58,6 +71,7 @@ char **argv;
                if (ifile >= 0)
                        close(ifile);
        }
                if (ifile >= 0)
                        close(ifile);
        }
+       exit(0);
 }
 
 type(file)
 }
 
 type(file)
@@ -66,41 +80,47 @@ char *file;
        int j,nl;
        char ch;
        struct stat mbuf;
        int j,nl;
        char ch;
        struct stat mbuf;
+       char slink[MAXPATHLEN + 1];
 
        ifile = -1;
 
        ifile = -1;
-       if(stat(file, &mbuf) < 0) {
-               printf("cannot stat\n");
+       if (lstat(file, &mbuf) < 0) {
+               fprintf(stderr, "file: %s: %s\n", file, strerror(errno));
                return;
        }
                return;
        }
+       printf("%s:\t", file);
        switch (mbuf.st_mode & S_IFMT) {
 
        switch (mbuf.st_mode & S_IFMT) {
 
-       case S_IFCHR:
-               printf("character");
-               goto spcl;
+       case S_IFLNK:
+               printf("symbolic link");
+               j = readlink(file, slink, sizeof slink - 1);
+               if (j >= 0) {
+                       slink[j] = '\0';
+                       printf(" to %s", slink);
+               }
+               printf("\n");
+               return;
 
        case S_IFDIR:
 
        case S_IFDIR:
+               if (mbuf.st_mode & S_ISVTX)
+                       printf("append-only ");
                printf("directory\n");
                return;
 
                printf("directory\n");
                return;
 
-       case S_IFMPC:
-               printf("char multiplexor\n");
-               return;
-
-       case S_IFMPB:
-               printf("block multiplexor\n");
-               return;
-
+       case S_IFCHR:
        case S_IFBLK:
        case S_IFBLK:
-               printf("block");
+               printf("%s special (%d/%d)\n",
+                   (mbuf.st_mode&S_IFMT) == S_IFCHR ? "character" : "block",
+                    major(mbuf.st_rdev), minor(mbuf.st_rdev));
+               return;
 
 
-spcl:
-               printf(" special (%d/%d)\n", major(mbuf.st_rdev), minor(mbuf.st_rdev));
+       case S_IFSOCK:
+               printf("socket\n");
                return;
        }
 
        ifile = open(file, 0);
        if(ifile < 0) {
                return;
        }
 
        ifile = open(file, 0);
        if(ifile < 0) {
-               printf("cannot open\n");
+               fprintf(stderr, "file: %s: %s\n", file, strerror(errno));
                return;
        }
        in = read(ifile, buf, BUFSIZ);
                return;
        }
        in = read(ifile, buf, BUFSIZ);
@@ -123,6 +143,12 @@ spcl:
 
        case 0407:
 exec:
 
        case 0407:
 exec:
+               if (mbuf.st_mode & S_ISUID)
+                       printf("set-uid ");
+               if (mbuf.st_mode & S_ISGID)
+                       printf("set-gid ");
+               if (mbuf.st_mode & S_ISVTX)
+                       printf("sticky ");
                printf("executable");
                if(((int *)buf)[4] != 0) {
                        printf(" not stripped");
                printf("executable");
                if(((int *)buf)[4] != 0) {
                        printf(" not stripped");
@@ -130,35 +156,42 @@ exec:
                                printf(" (old format symbol table)");
                }
                printf("\n");
                                printf(" (old format symbol table)");
                }
                printf("\n");
-               goto out;
+               return;
 
        case 0177555:
                printf("very old archive\n");
 
        case 0177555:
                printf("very old archive\n");
-               goto out;
+               return;
 
        case 0177545:
                printf("old archive\n");
 
        case 0177545:
                printf("old archive\n");
-               goto out;
+               return;
 
        case 070707:
                printf("cpio data\n");
 
        case 070707:
                printf("cpio data\n");
-               goto out;
+               return;
        }
 
        }
 
+       if (buf[0] == '#' && buf[1] == '!' && shellscript(buf+2, &mbuf))
+               return;
+       if (buf[0] == '\037' && buf[1] == '\235') {
+               if (buf[2]&0x80)
+                       printf("block ");
+               printf("compressed %d bit code data\n", buf[2]&0x1f);
+               return;
+       }
        if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) {
                printf("archive random library\n");
        if(strncmp(buf, "!<arch>\n__.SYMDEF", 17) == 0 ) {
                printf("archive random library\n");
-               goto out;
+               return;
        }
        if (strncmp(buf, "!<arch>\n", 8)==0) {
                printf("archive\n");
        }
        if (strncmp(buf, "!<arch>\n", 8)==0) {
                printf("archive\n");
-               goto out;
+               return;
        }
        if (mbuf.st_size % 512 == 0) {  /* it may be a PRESS file */
                lseek(ifile, -512L, 2); /* last block */
        }
        if (mbuf.st_size % 512 == 0) {  /* it may be a PRESS file */
                lseek(ifile, -512L, 2); /* last block */
-               if (read(ifile, buf, BUFSIZ) > 0
-                && *(short int *)buf == 12138) {
+               if (read(ifile, buf, BUFSIZ) > 0 && *(short *)buf == 12138) {
                        printf("PRESS file\n");
                        printf("PRESS file\n");
-                       goto out;
+                       return;
                }
        }
        i = 0;
                }
        }
        i = 0;
@@ -168,7 +201,7 @@ exec:
                while(buf[i++] != '\n'){
                        if(i - j > 255){
                                printf("data\n"); 
                while(buf[i++] != '\n'){
                        if(i - j > 255){
                                printf("data\n"); 
-                               goto out;
+                               return;
                        }
                        if(i >= in)goto notc;
                }
                        }
                        if(i >= in)goto notc;
                }
@@ -250,17 +283,31 @@ notfort:
        goto outa;
 notas:
        for(i=0; i < in; i++)if(buf[i]&0200){
        goto outa;
 notas:
        for(i=0; i < in; i++)if(buf[i]&0200){
-               if (buf[0]=='\100' && buf[1]=='\357') {
+               if (buf[0]=='\100' && buf[1]=='\357')
                        printf("troff (CAT) output\n");
                        printf("troff (CAT) output\n");
-                       goto out;
-               }
-               printf("data\n"); 
-               goto out; 
+               else
+                       printf("data\n"); 
+               return;
        }
        }
-       if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6)))
-               printf("commands text");
-       else if (troffint(buf, in))
+       if (mbuf.st_mode&((S_IEXEC)|(S_IEXEC>>3)|(S_IEXEC>>6))) {
+               if (mbuf.st_mode & S_ISUID)
+                       printf("set-uid ");
+               if (mbuf.st_mode & S_ISGID)
+                       printf("set-gid ");
+               if (mbuf.st_mode & S_ISVTX)
+                       printf("sticky ");
+               if (shell(buf, in, sh))
+                       printf("shell script");
+               else if (shell(buf, in, csh))
+                       printf("c-shell script");
+               else
+                       printf("commands text");
+       } else if (troffint(buf, in))
                printf("troff intermediate output text");
                printf("troff intermediate output text");
+       else if (shell(buf, in, sh))
+               printf("shell commands");
+       else if (shell(buf, in, csh))
+               printf("c-shell commands");
        else if (english(buf, in))
                printf("English text");
        else
        else if (english(buf, in))
                printf("English text");
        else
@@ -269,18 +316,17 @@ outa:
        while(i < in)
                if((buf[i++]&0377) > 127){
                        printf(" with garbage\n");
        while(i < in)
                if((buf[i++]&0377) > 127){
                        printf(" with garbage\n");
-                       goto out;
+                       return;
                }
        /* if next few lines in then read whole file looking for nulls ...
                while((in = read(ifile,buf,BUFSIZ)) > 0)
                        for(i = 0; i < in; i++)
                                if((buf[i]&0377) > 127){
                                        printf(" with garbage\n");
                }
        /* if next few lines in then read whole file looking for nulls ...
                while((in = read(ifile,buf,BUFSIZ)) > 0)
                        for(i = 0; i < in; i++)
                                if((buf[i]&0377) > 127){
                                        printf(" with garbage\n");
-                                       goto out;
+                                       return;
                                }
                /*.... */
        printf("\n");
                                }
                /*.... */
        printf("\n");
-out:;
 }
 
 oldo(cp)
 }
 
 oldo(cp)
@@ -371,7 +417,7 @@ char *bp;
                ct[j]=0;
        for(j=0; j<n; j++)
        {
                ct[j]=0;
        for(j=0; j<n; j++)
        {
-               if (bp[j]<NASC)
+               if ((u_char)bp[j]<NASC)
                        ct[bp[j]|040]++;
                switch (bp[j])
                {
                        ct[bp[j]|040]++;
                switch (bp[j])
                {
@@ -398,3 +444,54 @@ char *bp;
        if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */
        return (vow*5 >= n-ct[' '] && freq >= 10*rare);
 }
        if ( (ct['>']+ct['<']+ct['/'])>ct['e']) return(0); /* shell file test */
        return (vow*5 >= n-ct[' '] && freq >= 10*rare);
 }
+
+shellscript(buf, sb)
+       char buf[];
+       struct stat *sb;
+{
+       register char *tp;
+       char *cp, *xp, *index();
+
+       cp = index(buf, '\n');
+       if (cp == 0 || cp - buf > in)
+               return (0);
+       for (tp = buf; tp != cp && isspace(*tp); tp++)
+               if (!isascii(*tp))
+                       return (0);
+       for (xp = tp; tp != cp && !isspace(*tp); tp++)
+               if (!isascii(*tp))
+                       return (0);
+       if (tp == xp)
+               return (0);
+       if (sb->st_mode & S_ISUID)
+               printf("set-uid ");
+       if (sb->st_mode & S_ISGID)
+               printf("set-gid ");
+       if (strncmp(xp, "/bin/sh", tp-xp) == 0)
+               xp = "shell";
+       else if (strncmp(xp, "/bin/csh", tp-xp) == 0)
+               xp = "c-shell";
+       else
+               *tp = '\0';
+       printf("executable %s script\n", xp);
+       return (1);
+}
+
+shell(bp, n, tab)
+       char *bp;
+       int n;
+       char *tab[];
+{
+
+       i = 0;
+       do {
+               if (buf[i] == '#' || buf[i] == ':')
+                       while (i < n && buf[i] != '\n')
+                               i++;
+               if (++i >= n)
+                       break;
+               if (lookup(tab) == 1)
+                       return (1);
+       } while (i < n);
+       return (0);
+}