Must distinguish between "ambiguous" and "unknown" commands.
[unix-history] / usr / src / usr.bin / strings / strings.c
index 8463eef..77c8421 100644 (file)
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.  The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)strings.c   4.2 (Berkeley) %G%";
-#endif
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif not lint
 
 
-#include <stdio.h>
+#ifndef lint
+static char sccsid[] = "@(#)strings.c  5.3 (Berkeley) %G%";
+#endif not lint
+
+#include <sys/types.h>
+#include <sys/file.h>
 #include <a.out.h>
 #include <a.out.h>
+#include <stdio.h>
 #include <ctype.h>
 #include <ctype.h>
-#include <sys/file.h>
 
 
-long   ftell();
+#define DEF_LEN                4               /* default minimum string length */
+#define EOS            (char)NULL      /* end of string */
+#define ERR            -1              /* general error */
+#define ERREXIT                1               /* error exit */
+#define NO             0               /* false/no */
+#define OK             0               /* ok exit */
+#define YES            1               /* true/yes */
 
 
-/*
- * strings
- */
+#define ISSTR(ch)      (isascii(ch) && (isprint(ch) || ch == '\t'))
 
 
-struct exec header;
+typedef struct exec    EXEC;           /* struct exec cast */
 
 
-char   *infile = "Standard input";
-int    oflg;
-int    asdata;
-long   offset;
-int    minlength = 4;
+static long    foff;                   /* offset in the file */
+static int     hcnt,                   /* head count */
+               head_len,               /* length of header */
+               read_len;               /* length to read */
+static u_char  hbfr[sizeof(EXEC)];     /* buffer for struct exec */
 
 
-main(argc, argv)
-       int argc;
-       char *argv[];
+main(argc,argv)
+int    argc;
+char   **argv;
 {
 {
-
-       argc--, argv++;
-       while (argc > 0 && argv[0][0] == '-') {
-               register int i;
-               if (argv[0][1] == 0)
-                       asdata++;
-               else for (i = 1; argv[0][i] != 0; i++) switch (argv[0][i]) {
-
-               case 'o':
-                       oflg++;
-                       break;
-
-               case 'a':
-                       asdata++;
-                       break;
-
-               default:
-                       if (!isdigit(argv[0][i])) {
-                               fprintf(stderr, "Usage: strings [ -a ] [ -o ] [ -# ] [ file ... ]\n");
-                               exit(1);
+       register int    ch,             /* character */
+                       cnt;            /* general counter */
+       register u_char *C;             /* bfr pointer */
+       EXEC    *head;                  /* exec header pointer */
+       int     minlen = DEF_LEN;       /* minimum string length */
+       short   asdata = NO,            /* look in everything */
+               oflg;                   /* print octal location */
+       u_char  *bfr;                   /* collection buffer */
+       char    *file,                  /* file name for error */
+               *malloc();
+
+       /*
+        * for backward compatibility, allow '-' to specify 'a' flag; no
+        * longer documented in the man page or usage string.
+        */
+       for (++argv;*argv && **argv ==  '-';++argv) {
+               for (cnt = 1;(*argv)[cnt];++cnt)
+                       switch ((*argv)[cnt]) {
+                               case 'a':
+                                       asdata = YES;
+                                       break;
+                               case 'o':
+                                       oflg = YES;
+                                       break;
+                               default:        /* getopt message compatible */
+                                       if (!isdigit((*argv)[cnt])) {
+                                               fprintf(stderr,"strings: illegal option -- %c\nusage: strings [-ao] [-#] [file ... ]\n",(*argv)[cnt]);
+                                               exit(ERREXIT);
+                                       }
+                                       minlen = atoi(*argv + 1);
+                                       break;
                        }
                        }
-                       minlength = argv[0][i] - '0';
-                       for (i++; isdigit(argv[0][i]); i++)
-                               minlength = minlength * 10 + argv[0][i] - '0';
-                       i--;
-                       break;
-               }
-               argc--, argv++;
+               if (cnt == 1)
+                       asdata = YES;
        }
        }
+
+       if (!(bfr = (u_char *)malloc((u_int)minlen))) {
+               fputs("strings: unable to allocate space.\n",stderr);
+               exit(ERREXIT);
+       }
+       bfr[minlen] = EOS;
+       file = "stdin";
        do {
        do {
-               if (argc > 0) {
-                       if (freopen(argv[0], "r", stdin) == NULL) {
-                               perror(argv[0]);
-                               exit(1);
+               if (*argv) {
+                       if (!freopen(*argv,"r",stdin)) {
+                               perror(*argv);
+                               exit(ERREXIT);
                        }
                        }
-                       infile = argv[0];
-                       argc--, argv++;
+                       file = *argv++;
                }
                }
-               fseek(stdin, (long) 0, L_SET);
-               if (asdata ||
-                   fread((char *)&header, sizeof header, 1, stdin) != 1 || 
-                   N_BADMAG(header)) {
-                       fseek(stdin, (long) 0, L_SET);
-                       find((long) 100000000L);
-                       continue;
+               foff = 0;
+               read_len = ERR;
+               if (asdata)
+                       head_len = 0;
+               else {
+                       head = (EXEC *)hbfr;
+                       if ((head_len = read(fileno(stdin),(char *)head,sizeof(EXEC))) == ERR) {
+                               perror(file);
+                               exit(ERREXIT);
+                       }
+                       if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
+                               foff = N_TXTOFF(*head) + head->a_text;
+                               if (fseek(stdin,foff,L_SET) == ERR) {
+                                       perror(file);
+                                       exit(ERREXIT);
+                               }
+                               read_len = head->a_data;
+                               head_len = 0;
+                       }
+                       else
+                               hcnt = 0;
                }
                }
-               fseek(stdin, (long) N_TXTOFF(header)+header.a_text, L_SET);
-               find((long) header.a_data);
-       } while (argc > 0);
-}
-
-find(cnt)
-       long cnt;
-{
-       static char buf[BUFSIZ];
-       register char *cp;
-       register int c, cc;
-
-       cp = buf, cc = 0;
-       for (; cnt != 0; cnt--) {
-               c = getc(stdin);
-               if (c == '\n' || dirt(c) || cnt == 0) {
-                       if (cp > buf && cp[-1] == '\n')
-                               --cp;
-                       *cp++ = 0;
-                       if (cp > &buf[minlength]) {
+               for (cnt = 0;(ch = getch()) != EOF;) {
+                       if (ISSTR(ch)) {
+                               if (!cnt)
+                                       C = bfr;
+                               *C++ = ch;
+                               if (++cnt < minlen)
+                                       continue;
                                if (oflg)
                                if (oflg)
-                                       printf("%7D ", ftell(stdin) - cc - 1);
-                               printf("%s\n", buf);
+                                       printf("%07ld %s",foff - minlen,bfr);
+                               else
+                                       fputs((char *)bfr,stdout);
+                               while ((ch = getch()) != EOF && ISSTR(ch))
+                                       putchar((char)ch);
+                               putchar('\n');
                        }
                        }
-                       cp = buf, cc = 0;
-               } else {
-                       if (cp < &buf[sizeof buf - 2])
-                               *cp++ = c;
-                       cc++;
+                       cnt = 0;
                }
                }
-               if (ferror(stdin) || feof(stdin))
-                       break;
-       }
+       } while (*argv);
+       exit(OK);
 }
 
 }
 
-dirt(c)
-       int c;
+/*
+ * getch --
+ *     get next character from wherever
+ */
+static
+getch()
 {
 {
-
-       switch (c) {
-
-       case '\n':
-       case '\f':
-               return (0);
-
-       case 0177:
-               return (1);
-
-       default:
-               return (c > 0200 || c < ' ');
+       ++foff;
+       if (head_len) {
+               if (hcnt < head_len)
+                       return((int)hbfr[hcnt++]);
+               head_len = 0;
        }
        }
+       if (read_len == ERR || read_len-- > 0)
+               return(getchar());
+       return(EOF);
 }
 }