386BSD 0.1 development
[unix-history] / usr / src / usr.bin / strings / strings.c
CommitLineData
d8c2a3f5
WJ
1/*
2 * Copyright (c) 1980, 1987 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifndef lint
35char copyright[] =
36"@(#) Copyright (c) 1980, 1987 The Regents of the University of California.\n\
37 All rights reserved.\n";
38#endif /* not lint */
39
40#ifndef lint
41static char sccsid[] = "@(#)strings.c 5.10 (Berkeley) 5/23/91";
42#endif /* not lint */
43
44#include <sys/types.h>
45#include <fcntl.h>
46#include <errno.h>
47#include <a.out.h>
48#include <unistd.h>
49#include <stdio.h>
50#include <ctype.h>
51#include <stdlib.h>
52#include <string.h>
53
54#define DEF_LEN 4 /* default minimum string length */
55#define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t'))
56
57typedef struct exec EXEC; /* struct exec cast */
58
59static long foff; /* offset in the file */
60static int hcnt, /* head count */
61 head_len, /* length of header */
62 read_len; /* length to read */
63static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */
64
65static void usage();
66
67main(argc, argv)
68 int argc;
69 char **argv;
70{
71 extern char *optarg;
72 extern int optind;
73 register int ch, cnt;
74 register u_char *C;
75 EXEC *head;
76 int exitcode, minlen;
77 short asdata, oflg, fflg;
78 u_char *bfr;
79 char *file, *p;
80
81 /*
82 * for backward compatibility, allow '-' to specify 'a' flag; no
83 * longer documented in the man page or usage string.
84 */
85 asdata = exitcode = fflg = oflg = 0;
86 minlen = -1;
87 while ((ch = getopt(argc, argv, "-0123456789anof")) != EOF)
88 switch((char)ch) {
89 case '0': case '1': case '2': case '3': case '4':
90 case '5': case '6': case '7': case '8': case '9':
91 /*
92 * kludge: strings was originally designed to take
93 * a number after a dash.
94 */
95 if (minlen == -1) {
96 p = argv[optind - 1];
97 if (p[0] == '-' && p[1] == ch && !p[2])
98 minlen = atoi(++p);
99 else
100 minlen = atoi(argv[optind] + 1);
101 }
102 break;
103 case '-':
104 case 'a':
105 asdata = 1;
106 break;
107 case 'f':
108 fflg = 1;
109 break;
110 case 'n':
111 minlen = atoi(optarg);
112 break;
113 case 'o':
114 oflg = 1;
115 break;
116 case '?':
117 default:
118 usage();
119 }
120 argc -= optind;
121 argv += optind;
122
123 if (minlen == -1)
124 minlen = DEF_LEN;
125
126 if (!(bfr = malloc((u_int)minlen))) {
127 (void)fprintf(stderr, "strings: %s\n", strerror(errno));
128 exit(1);
129 }
130 bfr[minlen] = '\0';
131 file = "stdin";
132 do {
133 if (*argv) {
134 file = *argv++;
135 if (!freopen(file, "r", stdin)) {
136 (void)fprintf(stderr,
137 "strings: %s: %s\n", file, strerror(errno));
138 exitcode = 1;
139 goto nextfile;
140 }
141 }
142 foff = 0;
143#define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;}
144 read_len = -1;
145 if (asdata)
146 DO_EVERYTHING()
147 else {
148 head = (EXEC *)hbfr;
149 if ((head_len =
150 read(fileno(stdin), head, sizeof(EXEC))) == -1)
151 DO_EVERYTHING()
152 if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
153 foff = N_TXTOFF(*head);
154 if (fseek(stdin, foff, SEEK_SET) == -1)
155 DO_EVERYTHING()
156 read_len = head->a_text + head->a_data;
157 head_len = 0;
158 }
159 else
160 hcnt = 0;
161 }
162start:
163 for (cnt = 0; (ch = getch()) != EOF;) {
164 if (ISSTR(ch)) {
165 if (!cnt)
166 C = bfr;
167 *C++ = ch;
168 if (++cnt < minlen)
169 continue;
170 if (fflg)
171 printf("%s:", file);
172 if (oflg)
173 printf("%07ld %s",
174 foff - minlen, (char *)bfr);
175 else
176 printf("%s", bfr);
177 while ((ch = getch()) != EOF && ISSTR(ch))
178 putchar((char)ch);
179 putchar('\n');
180 }
181 cnt = 0;
182 }
183nextfile: ;
184 } while (*argv);
185 exit(exitcode);
186}
187
188/*
189 * getch --
190 * get next character from wherever
191 */
192getch()
193{
194 ++foff;
195 if (head_len) {
196 if (hcnt < head_len)
197 return((int)hbfr[hcnt++]);
198 head_len = 0;
199 }
200 if (read_len == -1 || read_len-- > 0)
201 return(getchar());
202 return(EOF);
203}
204
205static void
206usage()
207{
208 (void)fprintf(stderr,
209 "usage: strings [-afo] [-n length] [file ... ]\n");
210 exit(1);
211}