Annotation of src/usr.bin/strings/strings.c, Revision 1.13
1.13 ! ray 1: /* $OpenBSD: strings.c,v 1.12 2003/10/02 05:10:03 mickey Exp $ */
1.1 deraadt 2: /* $NetBSD: strings.c,v 1.7 1995/02/15 15:49:19 jtc Exp $ */
3:
4: /*
5: * Copyright (c) 1980, 1987, 1993
6: * The Regents of the University of California. All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
1.10 millert 16: * 3. Neither the name of the University nor the names of its contributors
1.1 deraadt 17: * may be used to endorse or promote products derived from this software
18: * without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: #ifndef lint
34: static char copyright[] =
35: "@(#) Copyright (c) 1980, 1987, 1993\n\
36: The Regents of the University of California. All rights reserved.\n";
37: #endif /* not lint */
38:
39: #ifndef lint
40: #if 0
41: static char sccsid[] = "@(#)strings.c 8.2 (Berkeley) 1/28/94";
42: #endif
1.13 ! ray 43: static char rcsid[] = "$OpenBSD: strings.c,v 1.12 2003/10/02 05:10:03 mickey Exp $";
1.1 deraadt 44: #endif /* not lint */
45:
46: #include <sys/types.h>
47:
48: #include <a.out.h>
49: #include <ctype.h>
50: #include <errno.h>
51: #include <fcntl.h>
52: #include <stdio.h>
53: #include <stdlib.h>
54: #include <string.h>
55: #include <locale.h>
56: #include <unistd.h>
1.12 mickey 57: #include <err.h>
1.1 deraadt 58:
59: #define FORMAT_DEC "%07ld "
60: #define FORMAT_OCT "%07lo "
61: #define FORMAT_HEX "%07lx "
62:
63: #define DEF_LEN 4 /* default minimum string length */
64: #define ISSTR(ch) (isascii(ch) && (isprint(ch) || ch == '\t'))
65:
66: typedef struct exec EXEC; /* struct exec cast */
67:
68: static long foff; /* offset in the file */
69: static int hcnt, /* head count */
70: head_len, /* length of header */
71: read_len; /* length to read */
72: static u_char hbfr[sizeof(EXEC)]; /* buffer for struct exec */
73:
1.7 millert 74: static void usage(void);
75: int getch(void);
1.1 deraadt 76:
1.4 deraadt 77: int
1.11 deraadt 78: main(int argc, char *argv[])
1.1 deraadt 79: {
80: extern char *optarg;
81: extern int optind;
1.6 mpech 82: int ch, cnt;
83: u_char *C;
1.1 deraadt 84: EXEC *head;
1.5 provos 85: int exitcode, minlen, maxlen, bfrlen;
1.1 deraadt 86: short asdata, fflg;
87: u_char *bfr;
88: char *file, *p;
89: char *offset_format;
90:
91: setlocale(LC_ALL, "");
92:
93: /*
94: * for backward compatibility, allow '-' to specify 'a' flag; no
95: * longer documented in the man page or usage string.
96: */
97: asdata = exitcode = fflg = 0;
98: offset_format = NULL;
99: minlen = -1;
1.5 provos 100: maxlen = -1;
1.9 millert 101: while ((ch = getopt(argc, argv, "0123456789an:m:oft:-")) != -1)
1.1 deraadt 102: switch((char)ch) {
103: case '0': case '1': case '2': case '3': case '4':
104: case '5': case '6': case '7': case '8': case '9':
105: /*
106: * kludge: strings was originally designed to take
107: * a number after a dash.
108: */
109: if (minlen == -1) {
110: p = argv[optind - 1];
111: if (p[0] == '-' && p[1] == ch && !p[2])
112: minlen = atoi(++p);
113: else
114: minlen = atoi(argv[optind] + 1);
115: }
116: break;
117: case '-':
118: case 'a':
119: asdata = 1;
120: break;
121: case 'f':
122: fflg = 1;
123: break;
124: case 'n':
125: minlen = atoi(optarg);
126: break;
1.5 provos 127: case 'm':
128: maxlen = atoi(optarg);
129: break;
1.1 deraadt 130: case 'o':
131: offset_format = FORMAT_OCT;
132: break;
133: case 't':
134: switch (*optarg) {
135: case 'o':
136: offset_format = FORMAT_OCT;
137: break;
138: case 'd':
139: offset_format = FORMAT_DEC;
140: break;
141: case 'x':
142: offset_format = FORMAT_HEX;
143: break;
144: default:
145: usage();
146: /* NOTREACHED */
147: }
148: break;
149: case '?':
150: default:
151: usage();
152: }
153: argc -= optind;
154: argv += optind;
155:
156: if (minlen == -1)
157: minlen = DEF_LEN;
1.12 mickey 158: else if (minlen < 1)
159: errx(1, "length less than 1");
160: if (maxlen != -1 && maxlen < minlen)
161: errx(1, "max length less than min");
1.5 provos 162: bfrlen = maxlen == -1 ? minlen : maxlen;
163: bfr = malloc(bfrlen + 1);
1.12 mickey 164: if (!bfr)
165: err(1, "malloc");
1.5 provos 166: bfr[bfrlen] = '\0';
1.1 deraadt 167: file = "stdin";
168: do {
169: if (*argv) {
170: file = *argv++;
171: if (!freopen(file, "r", stdin)) {
1.12 mickey 172: warn("%s", file);
1.1 deraadt 173: exitcode = 1;
174: goto nextfile;
175: }
176: }
177: foff = 0;
178: #define DO_EVERYTHING() {read_len = -1; head_len = 0; goto start;}
179: read_len = -1;
180: if (asdata)
181: DO_EVERYTHING()
182: else {
183: head = (EXEC *)hbfr;
184: if ((head_len =
185: read(fileno(stdin), head, sizeof(EXEC))) == -1)
186: DO_EVERYTHING()
187: if (head_len == sizeof(EXEC) && !N_BADMAG(*head)) {
188: foff = N_TXTOFF(*head);
189: if (fseek(stdin, foff, SEEK_SET) == -1)
190: DO_EVERYTHING()
191: read_len = head->a_text + head->a_data;
192: head_len = 0;
193: }
194: else
195: hcnt = 0;
196: }
197: start:
1.13 ! ray 198: for (cnt = 0, C = bfr; (ch = getch()) != EOF;) {
1.1 deraadt 199: if (ISSTR(ch)) {
200: *C++ = ch;
201: if (++cnt < minlen)
202: continue;
1.5 provos 203: if (maxlen != -1) {
204: while ((ch = getch()) != EOF &&
205: ISSTR(ch) && cnt++ < maxlen)
206: *C++ = ch;
207: if (ch == EOF ||
208: (ch != 0 && ch != '\n')) {
209: /* get all of too big string */
210: while ((ch = getch()) != EOF &&
211: ISSTR(ch))
212: ;
213: ungetc(ch, stdin);
214: goto out;
215: }
216: *C = 0;
217: }
1.1 deraadt 218:
219: if (fflg)
220: printf("%s:", file);
221:
222: if (offset_format)
223: printf(offset_format, foff - minlen);
224:
225: printf("%s", bfr);
1.5 provos 226:
227: if (maxlen == -1)
228: while ((ch = getch()) != EOF &&
229: ISSTR(ch))
230: putchar((char)ch);
1.1 deraadt 231: putchar('\n');
1.5 provos 232: out:
1.8 millert 233: ;
1.1 deraadt 234: }
235: cnt = 0;
1.13 ! ray 236: C = bfr;
1.1 deraadt 237: }
238: nextfile: ;
239: } while (*argv);
240: exit(exitcode);
241: }
242:
243: /*
244: * getch --
245: * get next character from wherever
246: */
1.4 deraadt 247: int
1.11 deraadt 248: getch(void)
1.1 deraadt 249: {
250: ++foff;
251: if (head_len) {
252: if (hcnt < head_len)
253: return((int)hbfr[hcnt++]);
254: head_len = 0;
255: }
256: if (read_len == -1 || read_len-- > 0)
257: return(getchar());
258: return(EOF);
259: }
260:
261: static void
1.11 deraadt 262: usage(void)
1.1 deraadt 263: {
264: (void)fprintf(stderr,
265: "usage: strings [-afo] [-n length] [-t {o,d,x}] [file ... ]\n");
266: exit(1);
267: }