BSD 4_3 release
[unix-history] / usr / src / usr.bin / file.c
index bd68e0e..94702df 100644 (file)
@@ -1,16 +1,17 @@
 #ifndef lint
 #ifndef lint
-static char sccsid[] = "@(#)file.c     4.8 (Berkeley) 8/11/83";
+static char sccsid[] = "@(#)file.c     4.12 (Berkeley) 11/17/85";
 #endif
 /*
  * file - determine type of file
  */
 
 #endif
 /*
  * file - determine type of file
  */
 
-#include <sys/types.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
 int    errno;
 #include <sys/stat.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <a.out.h>
 int    errno;
+int    sys_nerr;
 char   *sys_errlist[];
 int in;
 int i  = 0;
 char   *sys_errlist[];
 int in;
 int i  = 0;
@@ -26,6 +27,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)
@@ -33,15 +40,20 @@ char **argv;
 {
        FILE *fl;
        register char *p;
 {
        FILE *fl;
        register char *p;
-       char ap[128];
+       char ap[MAXPATHLEN + 1];
        extern char _sobuf[];
 
        extern char _sobuf[];
 
+       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) {
                        perror(argv[2]);
                        exit(2);
                }
        if (argc>1 && argv[1][0]=='-' && argv[1][1]=='f') {
                if ((fl = fopen(argv[2], "r")) == NULL) {
                        perror(argv[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';
@@ -61,6 +73,7 @@ char **argv;
                if (ifile >= 0)
                        close(ifile);
        }
                if (ifile >= 0)
                        close(ifile);
        }
+       exit(0);
 }
 
 type(file)
 }
 
 type(file)
@@ -69,37 +82,48 @@ char *file;
        int j,nl;
        char ch;
        struct stat mbuf;
        int j,nl;
        char ch;
        struct stat mbuf;
+       char slink[MAXPATHLEN + 1];
 
        ifile = -1;
        if (lstat(file, &mbuf) < 0) {
 
        ifile = -1;
        if (lstat(file, &mbuf) < 0) {
-               printf("%s\n", sys_errlist[errno]);
+               printf("%s\n",
+               (unsigned)errno < sys_nerr? sys_errlist[errno]: "Cannot stat");
                return;
        }
        switch (mbuf.st_mode & S_IFMT) {
 
                return;
        }
        switch (mbuf.st_mode & S_IFMT) {
 
-       case S_IFCHR:
-               printf("character");
-               goto spcl;
-
        case S_IFLNK:
        case S_IFLNK:
-               printf("symbolic link\n");
+               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:
                return;
 
        case S_IFDIR:
+               if (mbuf.st_mode & S_ISVTX)
+                       printf("append-only ");
                printf("directory\n");
                return;
 
                printf("directory\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");
+               printf("%s\n",
+               (unsigned)errno < sys_nerr? sys_errlist[errno]: "Cannot read");
                return;
        }
        in = read(ifile, buf, BUFSIZ);
                return;
        }
        in = read(ifile, buf, BUFSIZ);
@@ -122,6 +146,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");
@@ -129,35 +159,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;
@@ -167,7 +204,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;
                }
@@ -249,17 +286,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
@@ -268,18 +319,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)
@@ -397,3 +447,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);
+}