15d82ecf4Sdist /*
23616f2cbSbostic * Copyright (c) 1980, 1987, 1993
33616f2cbSbostic * The Regents of the University of California. All rights reserved.
4654d9ca0Sbostic *
5179c5b05Sbostic * %sccs.include.redist.c%
65d82ecf4Sdist */
75d82ecf4Sdist
8cb535708Ssam #ifndef lint
93616f2cbSbostic static char copyright[] =
103616f2cbSbostic "@(#) Copyright (c) 1980, 1987, 1993\n\
113616f2cbSbostic The Regents of the University of California. All rights reserved.\n";
12654d9ca0Sbostic #endif /* not lint */
135d82ecf4Sdist
145d82ecf4Sdist #ifndef lint
15*168d7fa9Sbostic static char sccsid[] = "@(#)strings.c 8.2 (Berkeley) 01/28/94";
16654d9ca0Sbostic #endif /* not lint */
17cb535708Ssam
18dbf62afdSbostic #include <sys/types.h>
19*168d7fa9Sbostic
20dbf62afdSbostic #include <a.out.h>
21dbf62afdSbostic #include <ctype.h>
22*168d7fa9Sbostic #include <errno.h>
23*168d7fa9Sbostic #include <fcntl.h>
24*168d7fa9Sbostic #include <stdio.h>
25afb0792fSbostic #include <stdlib.h>
26afb0792fSbostic #include <string.h>
27*168d7fa9Sbostic #include <unistd.h>
2888d53f5dSbill
29dbf62afdSbostic #define DEF_LEN 4 /* default minimum string length */
30dbf62afdSbostic #define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t'))
3188d53f5dSbill
32dbf62afdSbostic typedef struct exec EXEC; /* struct exec cast */
3388d53f5dSbill
34dbf62afdSbostic static long foff; /* offset in the file */
35dbf62afdSbostic static int hcnt, /* head count */
36dbf62afdSbostic head_len, /* length of header */
37dbf62afdSbostic read_len; /* length to read */
38dbf62afdSbostic static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */
3988d53f5dSbill
40afb0792fSbostic static void usage();
41afb0792fSbostic
main(argc,argv)4288d53f5dSbill main(argc, argv)
4388d53f5dSbill int argc;
44dbf62afdSbostic char **argv;
4588d53f5dSbill {
46654d9ca0Sbostic extern char *optarg;
47654d9ca0Sbostic extern int optind;
48654d9ca0Sbostic register int ch, cnt;
49654d9ca0Sbostic register u_char *C;
50654d9ca0Sbostic EXEC *head;
51afb0792fSbostic int exitcode, minlen;
52ffb17e88Smarc short asdata, oflg, fflg;
53654d9ca0Sbostic u_char *bfr;
54afb0792fSbostic char *file, *p;
5588d53f5dSbill
56dbf62afdSbostic /*
57dbf62afdSbostic * for backward compatibility, allow '-' to specify 'a' flag; no
58dbf62afdSbostic * longer documented in the man page or usage string.
59dbf62afdSbostic */
60afb0792fSbostic asdata = exitcode = fflg = oflg = 0;
61654d9ca0Sbostic minlen = -1;
62*168d7fa9Sbostic while ((ch = getopt(argc, argv, "-0123456789an:of")) != EOF)
63*168d7fa9Sbostic switch (ch) {
64654d9ca0Sbostic case '0': case '1': case '2': case '3': case '4':
65654d9ca0Sbostic case '5': case '6': case '7': case '8': case '9':
66654d9ca0Sbostic /*
67654d9ca0Sbostic * kludge: strings was originally designed to take
68654d9ca0Sbostic * a number after a dash.
69654d9ca0Sbostic */
70654d9ca0Sbostic if (minlen == -1) {
71654d9ca0Sbostic p = argv[optind - 1];
72654d9ca0Sbostic if (p[0] == '-' && p[1] == ch && !p[2])
73654d9ca0Sbostic minlen = atoi(++p);
74654d9ca0Sbostic else
75654d9ca0Sbostic minlen = atoi(argv[optind] + 1);
76654d9ca0Sbostic }
77654d9ca0Sbostic break;
78654d9ca0Sbostic case '-':
7988d53f5dSbill case 'a':
80654d9ca0Sbostic asdata = 1;
8188d53f5dSbill break;
82ffb17e88Smarc case 'f':
83ffb17e88Smarc fflg = 1;
84ffb17e88Smarc break;
85afb0792fSbostic case 'n':
86afb0792fSbostic minlen = atoi(optarg);
87afb0792fSbostic break;
88afb0792fSbostic case 'o':
89afb0792fSbostic oflg = 1;
90afb0792fSbostic break;
91654d9ca0Sbostic case '?':
92654d9ca0Sbostic default:
93afb0792fSbostic usage();
94dbf62afdSbostic }
95654d9ca0Sbostic argc -= optind;
96654d9ca0Sbostic argv += optind;
97654d9ca0Sbostic
98654d9ca0Sbostic if (minlen == -1)
99654d9ca0Sbostic minlen = DEF_LEN;
100*168d7fa9Sbostic else {
101*168d7fa9Sbostic (void)fprintf(stderr, "strings: length less than 1\n");
102*168d7fa9Sbostic exit (1);
103*168d7fa9Sbostic }
10488d53f5dSbill
105afb0792fSbostic if (!(bfr = malloc((u_int)minlen))) {
106afb0792fSbostic (void)fprintf(stderr, "strings: %s\n", strerror(errno));
107654d9ca0Sbostic exit(1);
10888d53f5dSbill }
109654d9ca0Sbostic bfr[minlen] = '\0';
11069dea8ddSbostic file = "stdin";
11188d53f5dSbill do {
112dbf62afdSbostic if (*argv) {
113dbf62afdSbostic file = *argv++;
114ffb17e88Smarc if (!freopen(file, "r", stdin)) {
115afb0792fSbostic (void)fprintf(stderr,
116c017df21Sbostic "strings: %s: %s\n", file, strerror(errno));
117ffb17e88Smarc exitcode = 1;
118ffb17e88Smarc goto nextfile;
119ffb17e88Smarc }
12088d53f5dSbill }
121dbf62afdSbostic foff = 0;
122ffb17e88Smarc #define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;}
123654d9ca0Sbostic read_len = -1;
124dbf62afdSbostic if (asdata)
125ffb17e88Smarc DO_EVERYTHING()
126dbf62afdSbostic else {
127dbf62afdSbostic head = (EXEC *)hbfr;
128afb0792fSbostic if ((head_len =
129afb0792fSbostic read(fileno(stdin), head, sizeof(EXEC))) == -1)
130ffb17e88Smarc DO_EVERYTHING()
131dbf62afdSbostic if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
1321cad0f35Sdonn foff = N_TXTOFF(*head);
133afb0792fSbostic if (fseek(stdin, foff, SEEK_SET) == -1)
134ffb17e88Smarc DO_EVERYTHING()
1351cad0f35Sdonn read_len = head->a_text + head->a_data;
136dbf62afdSbostic head_len = 0;
137dbf62afdSbostic }
138dbf62afdSbostic else
139dbf62afdSbostic hcnt = 0;
140dbf62afdSbostic }
141ffb17e88Smarc start:
142dbf62afdSbostic for (cnt = 0; (ch = getch()) != EOF;) {
143dbf62afdSbostic if (ISSTR(ch)) {
144dbf62afdSbostic if (!cnt)
145dbf62afdSbostic C = bfr;
146dbf62afdSbostic *C++ = ch;
147dbf62afdSbostic if (++cnt < minlen)
14888d53f5dSbill continue;
149ffb17e88Smarc if (fflg)
150ffb17e88Smarc printf("%s:", file);
15188d53f5dSbill if (oflg)
152afb0792fSbostic printf("%07ld %s",
153afb0792fSbostic foff - minlen, (char *)bfr);
154dbf62afdSbostic else
155afb0792fSbostic printf("%s", bfr);
156dbf62afdSbostic while ((ch = getch()) != EOF && ISSTR(ch))
157dbf62afdSbostic putchar((char)ch);
158dbf62afdSbostic putchar('\n');
15988d53f5dSbill }
160dbf62afdSbostic cnt = 0;
16188d53f5dSbill }
162ffb17e88Smarc nextfile: ;
163dbf62afdSbostic } while (*argv);
164ffb17e88Smarc exit(exitcode);
16588d53f5dSbill }
16688d53f5dSbill
167dbf62afdSbostic /*
168dbf62afdSbostic * getch --
169dbf62afdSbostic * get next character from wherever
170dbf62afdSbostic */
getch()171dbf62afdSbostic getch()
17288d53f5dSbill {
173dbf62afdSbostic ++foff;
174dbf62afdSbostic if (head_len) {
175dbf62afdSbostic if (hcnt < head_len)
176dbf62afdSbostic return((int)hbfr[hcnt++]);
177dbf62afdSbostic head_len = 0;
17888d53f5dSbill }
179654d9ca0Sbostic if (read_len == -1 || read_len-- > 0)
180dbf62afdSbostic return(getchar());
181dbf62afdSbostic return(EOF);
18288d53f5dSbill }
183afb0792fSbostic
184afb0792fSbostic static void
usage()185afb0792fSbostic usage()
186afb0792fSbostic {
187afb0792fSbostic (void)fprintf(stderr,
188afb0792fSbostic "usage: strings [-afo] [-n length] [file ... ]\n");
189afb0792fSbostic exit(1);
190afb0792fSbostic }
191