1 /*
2 * Copyright (c) 1980, 1987, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1980, 1987, 1993\n\
11 The Regents of the University of California. All rights reserved.\n";
12 #endif /* not lint */
13
14 #ifndef lint
15 static char sccsid[] = "@(#)strings.c 8.2 (Berkeley) 01/28/94";
16 #endif /* not lint */
17
18 #include <sys/types.h>
19
20 #include <a.out.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 #define DEF_LEN 4 /* default minimum string length */
30 #define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t'))
31
32 typedef struct exec EXEC; /* struct exec cast */
33
34 static long foff; /* offset in the file */
35 static int hcnt, /* head count */
36 head_len, /* length of header */
37 read_len; /* length to read */
38 static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */
39
40 static void usage();
41
main(argc,argv)42 main(argc, argv)
43 int argc;
44 char **argv;
45 {
46 extern char *optarg;
47 extern int optind;
48 register int ch, cnt;
49 register u_char *C;
50 EXEC *head;
51 int exitcode, minlen;
52 short asdata, oflg, fflg;
53 u_char *bfr;
54 char *file, *p;
55
56 /*
57 * for backward compatibility, allow '-' to specify 'a' flag; no
58 * longer documented in the man page or usage string.
59 */
60 asdata = exitcode = fflg = oflg = 0;
61 minlen = -1;
62 while ((ch = getopt(argc, argv, "-0123456789an:of")) != EOF)
63 switch (ch) {
64 case '0': case '1': case '2': case '3': case '4':
65 case '5': case '6': case '7': case '8': case '9':
66 /*
67 * kludge: strings was originally designed to take
68 * a number after a dash.
69 */
70 if (minlen == -1) {
71 p = argv[optind - 1];
72 if (p[0] == '-' && p[1] == ch && !p[2])
73 minlen = atoi(++p);
74 else
75 minlen = atoi(argv[optind] + 1);
76 }
77 break;
78 case '-':
79 case 'a':
80 asdata = 1;
81 break;
82 case 'f':
83 fflg = 1;
84 break;
85 case 'n':
86 minlen = atoi(optarg);
87 break;
88 case 'o':
89 oflg = 1;
90 break;
91 case '?':
92 default:
93 usage();
94 }
95 argc -= optind;
96 argv += optind;
97
98 if (minlen == -1)
99 minlen = DEF_LEN;
100 else {
101 (void)fprintf(stderr, "strings: length less than 1\n");
102 exit (1);
103 }
104
105 if (!(bfr = malloc((u_int)minlen))) {
106 (void)fprintf(stderr, "strings: %s\n", strerror(errno));
107 exit(1);
108 }
109 bfr[minlen] = '\0';
110 file = "stdin";
111 do {
112 if (*argv) {
113 file = *argv++;
114 if (!freopen(file, "r", stdin)) {
115 (void)fprintf(stderr,
116 "strings: %s: %s\n", file, strerror(errno));
117 exitcode = 1;
118 goto nextfile;
119 }
120 }
121 foff = 0;
122 #define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;}
123 read_len = -1;
124 if (asdata)
125 DO_EVERYTHING()
126 else {
127 head = (EXEC *)hbfr;
128 if ((head_len =
129 read(fileno(stdin), head, sizeof(EXEC))) == -1)
130 DO_EVERYTHING()
131 if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
132 foff = N_TXTOFF(*head);
133 if (fseek(stdin, foff, SEEK_SET) == -1)
134 DO_EVERYTHING()
135 read_len = head->a_text + head->a_data;
136 head_len = 0;
137 }
138 else
139 hcnt = 0;
140 }
141 start:
142 for (cnt = 0; (ch = getch()) != EOF;) {
143 if (ISSTR(ch)) {
144 if (!cnt)
145 C = bfr;
146 *C++ = ch;
147 if (++cnt < minlen)
148 continue;
149 if (fflg)
150 printf("%s:", file);
151 if (oflg)
152 printf("%07ld %s",
153 foff - minlen, (char *)bfr);
154 else
155 printf("%s", bfr);
156 while ((ch = getch()) != EOF && ISSTR(ch))
157 putchar((char)ch);
158 putchar('\n');
159 }
160 cnt = 0;
161 }
162 nextfile: ;
163 } while (*argv);
164 exit(exitcode);
165 }
166
167 /*
168 * getch --
169 * get next character from wherever
170 */
getch()171 getch()
172 {
173 ++foff;
174 if (head_len) {
175 if (hcnt < head_len)
176 return((int)hbfr[hcnt++]);
177 head_len = 0;
178 }
179 if (read_len == -1 || read_len-- > 0)
180 return(getchar());
181 return(EOF);
182 }
183
184 static void
usage()185 usage()
186 {
187 (void)fprintf(stderr,
188 "usage: strings [-afo] [-n length] [file ... ]\n");
189 exit(1);
190 }
191