1a85fe12eSEd Maste /*-
2a85fe12eSEd Maste * Copyright (c) 2007 S.Sam Arun Raj
3a85fe12eSEd Maste * All rights reserved.
4a85fe12eSEd Maste *
5a85fe12eSEd Maste * Redistribution and use in source and binary forms, with or without
6a85fe12eSEd Maste * modification, are permitted provided that the following conditions
7a85fe12eSEd Maste * are met:
8a85fe12eSEd Maste * 1. Redistributions of source code must retain the above copyright
9a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer.
10a85fe12eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright
11a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer in the
12a85fe12eSEd Maste * documentation and/or other materials provided with the distribution.
13a85fe12eSEd Maste *
14a85fe12eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15a85fe12eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16a85fe12eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17a85fe12eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18a85fe12eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19a85fe12eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20a85fe12eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21a85fe12eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22a85fe12eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23a85fe12eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24a85fe12eSEd Maste * SUCH DAMAGE.
25a85fe12eSEd Maste */
26a85fe12eSEd Maste
27a85fe12eSEd Maste #include <sys/types.h>
286d395debSMariusz Zaborski #include <sys/capsicum.h>
294f486ad6SMariusz Zaborski #include <sys/stat.h>
30a85fe12eSEd Maste
316d395debSMariusz Zaborski #include <capsicum_helpers.h>
32a85fe12eSEd Maste #include <ctype.h>
33a85fe12eSEd Maste #include <err.h>
34a85fe12eSEd Maste #include <errno.h>
35a85fe12eSEd Maste #include <fcntl.h>
36a85fe12eSEd Maste #include <getopt.h>
37a85fe12eSEd Maste #include <inttypes.h>
38a85fe12eSEd Maste #include <stdint.h>
39a85fe12eSEd Maste #include <stdio.h>
40a85fe12eSEd Maste #include <stdlib.h>
41a85fe12eSEd Maste #include <string.h>
42839529caSEd Maste #include <sysexits.h>
43a85fe12eSEd Maste #include <unistd.h>
44a85fe12eSEd Maste
45a85fe12eSEd Maste #include <libelf.h>
46a85fe12eSEd Maste #include <libelftc.h>
47a85fe12eSEd Maste #include <gelf.h>
48a85fe12eSEd Maste
496d395debSMariusz Zaborski #include <libcasper.h>
506d395debSMariusz Zaborski #include <casper/cap_fileargs.h>
516d395debSMariusz Zaborski
52a85fe12eSEd Maste #include "_elftc.h"
53a85fe12eSEd Maste
54ae500c1fSEd Maste ELFTC_VCSID("$Id: strings.c 3648 2018-11-22 23:26:43Z emaste $");
55a85fe12eSEd Maste
56a85fe12eSEd Maste enum radix_style {
57a85fe12eSEd Maste RADIX_DECIMAL,
58a85fe12eSEd Maste RADIX_HEX,
59a85fe12eSEd Maste RADIX_OCTAL
60a85fe12eSEd Maste };
61a85fe12eSEd Maste
62a85fe12eSEd Maste enum encoding_style {
63a85fe12eSEd Maste ENCODING_7BIT,
64a85fe12eSEd Maste ENCODING_8BIT,
65a85fe12eSEd Maste ENCODING_16BIT_BIG,
66a85fe12eSEd Maste ENCODING_16BIT_LITTLE,
67a85fe12eSEd Maste ENCODING_32BIT_BIG,
68a85fe12eSEd Maste ENCODING_32BIT_LITTLE
69a85fe12eSEd Maste };
70a85fe12eSEd Maste
71a85fe12eSEd Maste #define PRINTABLE(c) \
72a85fe12eSEd Maste ((c) >= 0 && (c) <= 255 && \
73a85fe12eSEd Maste ((c) == '\t' || isprint((c)) || \
74a85fe12eSEd Maste (encoding == ENCODING_8BIT && (c) > 127)))
75a85fe12eSEd Maste
76839529caSEd Maste static int encoding_size, entire_file, show_filename, show_loc;
7750f69bfbSEd Maste static enum encoding_style encoding;
7850f69bfbSEd Maste static enum radix_style radix;
79839529caSEd Maste static intmax_t min_len;
80a85fe12eSEd Maste
81a85fe12eSEd Maste static struct option strings_longopts[] = {
82a85fe12eSEd Maste { "all", no_argument, NULL, 'a'},
83a85fe12eSEd Maste { "bytes", required_argument, NULL, 'n'},
84a85fe12eSEd Maste { "encoding", required_argument, NULL, 'e'},
85a85fe12eSEd Maste { "help", no_argument, NULL, 'h'},
86a85fe12eSEd Maste { "print-file-name", no_argument, NULL, 'f'},
87a85fe12eSEd Maste { "radix", required_argument, NULL, 't'},
88a85fe12eSEd Maste { "version", no_argument, NULL, 'v'},
89a85fe12eSEd Maste { NULL, 0, NULL, 0 }
90a85fe12eSEd Maste };
91a85fe12eSEd Maste
9255d3f888SMariusz Zaborski int getcharacter(FILE *, long *);
936d395debSMariusz Zaborski int handle_file(fileargs_t *fa, const char *);
9461d994f1SMariusz Zaborski int handle_elf(const char *, FILE *);
9561d994f1SMariusz Zaborski int handle_binary(const char *, FILE *, size_t);
9661d994f1SMariusz Zaborski int find_strings(const char *, FILE *, off_t, off_t);
97a85fe12eSEd Maste void show_version(void);
98a85fe12eSEd Maste void usage(void);
99a85fe12eSEd Maste
100a85fe12eSEd Maste /*
101a85fe12eSEd Maste * strings(1) extracts text(contiguous printable characters)
102a85fe12eSEd Maste * from elf and binary files.
103a85fe12eSEd Maste */
104a85fe12eSEd Maste int
main(int argc,char ** argv)105a85fe12eSEd Maste main(int argc, char **argv)
106a85fe12eSEd Maste {
1076d395debSMariusz Zaborski fileargs_t *fa;
1086d395debSMariusz Zaborski cap_rights_t rights;
109a85fe12eSEd Maste int ch, rc;
110a85fe12eSEd Maste
111f8d647b4SEd Maste rc = 0;
112a85fe12eSEd Maste min_len = 0;
113a85fe12eSEd Maste encoding_size = 1;
114a85fe12eSEd Maste if (elf_version(EV_CURRENT) == EV_NONE)
115a85fe12eSEd Maste errx(EXIT_FAILURE, "ELF library initialization failed: %s",
116a85fe12eSEd Maste elf_errmsg(-1));
117a85fe12eSEd Maste
118a85fe12eSEd Maste while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv",
1194f486ad6SMariusz Zaborski strings_longopts, NULL)) != -1) {
120a85fe12eSEd Maste switch ((char)ch) {
121a85fe12eSEd Maste case 'a':
122a85fe12eSEd Maste entire_file = 1;
123a85fe12eSEd Maste break;
124a85fe12eSEd Maste case 'e':
125a85fe12eSEd Maste if (*optarg == 's') {
126a85fe12eSEd Maste encoding = ENCODING_7BIT;
127a85fe12eSEd Maste } else if (*optarg == 'S') {
128a85fe12eSEd Maste encoding = ENCODING_8BIT;
129a85fe12eSEd Maste } else if (*optarg == 'b') {
130a85fe12eSEd Maste encoding = ENCODING_16BIT_BIG;
131a85fe12eSEd Maste encoding_size = 2;
132a85fe12eSEd Maste } else if (*optarg == 'B') {
133a85fe12eSEd Maste encoding = ENCODING_32BIT_BIG;
134a85fe12eSEd Maste encoding_size = 4;
135a85fe12eSEd Maste } else if (*optarg == 'l') {
136a85fe12eSEd Maste encoding = ENCODING_16BIT_LITTLE;
137a85fe12eSEd Maste encoding_size = 2;
138a85fe12eSEd Maste } else if (*optarg == 'L') {
139a85fe12eSEd Maste encoding = ENCODING_32BIT_LITTLE;
140a85fe12eSEd Maste encoding_size = 4;
141a85fe12eSEd Maste } else
142a85fe12eSEd Maste usage();
143a85fe12eSEd Maste /* NOTREACHED */
144a85fe12eSEd Maste break;
145a85fe12eSEd Maste case 'f':
146a85fe12eSEd Maste show_filename = 1;
147a85fe12eSEd Maste break;
148a85fe12eSEd Maste case 'n':
149839529caSEd Maste min_len = strtoimax(optarg, (char**)NULL, 10);
150839529caSEd Maste if (min_len <= 0)
151839529caSEd Maste errx(EX_USAGE, "option -n should specify a "
152839529caSEd Maste "positive decimal integer.");
153a85fe12eSEd Maste break;
154a85fe12eSEd Maste case 'o':
155a85fe12eSEd Maste show_loc = 1;
156a85fe12eSEd Maste radix = RADIX_OCTAL;
157a85fe12eSEd Maste break;
158a85fe12eSEd Maste case 't':
159a85fe12eSEd Maste show_loc = 1;
160a85fe12eSEd Maste if (*optarg == 'd')
161a85fe12eSEd Maste radix = RADIX_DECIMAL;
162a85fe12eSEd Maste else if (*optarg == 'o')
163a85fe12eSEd Maste radix = RADIX_OCTAL;
164a85fe12eSEd Maste else if (*optarg == 'x')
165a85fe12eSEd Maste radix = RADIX_HEX;
166a85fe12eSEd Maste else
167a85fe12eSEd Maste usage();
168a85fe12eSEd Maste /* NOTREACHED */
169a85fe12eSEd Maste break;
170a85fe12eSEd Maste case 'v':
171a85fe12eSEd Maste case 'V':
172a85fe12eSEd Maste show_version();
173a85fe12eSEd Maste /* NOTREACHED */
174a85fe12eSEd Maste case '0':
175a85fe12eSEd Maste case '1':
176a85fe12eSEd Maste case '2':
177a85fe12eSEd Maste case '3':
178a85fe12eSEd Maste case '4':
179a85fe12eSEd Maste case '5':
180a85fe12eSEd Maste case '6':
181a85fe12eSEd Maste case '7':
182a85fe12eSEd Maste case '8':
183a85fe12eSEd Maste case '9':
184a85fe12eSEd Maste min_len *= 10;
185a85fe12eSEd Maste min_len += ch - '0';
186a85fe12eSEd Maste break;
187a85fe12eSEd Maste case 'h':
188a85fe12eSEd Maste case '?':
189a85fe12eSEd Maste default:
190a85fe12eSEd Maste usage();
191a85fe12eSEd Maste /* NOTREACHED */
192a85fe12eSEd Maste }
1934f486ad6SMariusz Zaborski }
194a85fe12eSEd Maste argc -= optind;
195a85fe12eSEd Maste argv += optind;
196a85fe12eSEd Maste
197*5eac9c1cSMariusz Zaborski cap_rights_init(&rights, CAP_READ, CAP_SEEK, CAP_FSTAT, CAP_FCNTL, CAP_MMAP_R);
198d76eef34SEd Maste fa = fileargs_init(argc, argv, O_RDONLY, 0, &rights, FA_OPEN);
1996d395debSMariusz Zaborski if (fa == NULL)
2006d395debSMariusz Zaborski err(1, "Unable to initialize casper fileargs");
2016d395debSMariusz Zaborski
2026d395debSMariusz Zaborski caph_cache_catpages();
2035ff84ed3SMariusz Zaborski if (caph_limit_stdio() < 0 || caph_enter_casper() < 0) {
2046d395debSMariusz Zaborski fileargs_free(fa);
2056d395debSMariusz Zaborski err(1, "Unable to enter capability mode");
2066d395debSMariusz Zaborski }
2076d395debSMariusz Zaborski
2084f486ad6SMariusz Zaborski if (min_len == 0)
209a85fe12eSEd Maste min_len = 4;
2104f486ad6SMariusz Zaborski if (*argv == NULL)
21161d994f1SMariusz Zaborski rc = find_strings("{standard input}", stdin, 0, 0);
2124f486ad6SMariusz Zaborski else while (*argv != NULL) {
2136d395debSMariusz Zaborski if (handle_file(fa, *argv) != 0)
214f8d647b4SEd Maste rc = 1;
215a85fe12eSEd Maste argv++;
216a85fe12eSEd Maste }
2176d395debSMariusz Zaborski
2186d395debSMariusz Zaborski fileargs_free(fa);
2196d395debSMariusz Zaborski
220a85fe12eSEd Maste return (rc);
221a85fe12eSEd Maste }
222a85fe12eSEd Maste
223a85fe12eSEd Maste int
handle_file(fileargs_t * fa,const char * name)2246d395debSMariusz Zaborski handle_file(fileargs_t *fa, const char *name)
225a85fe12eSEd Maste {
22661d994f1SMariusz Zaborski FILE *pfile;
22761d994f1SMariusz Zaborski int rt;
228a85fe12eSEd Maste
229a85fe12eSEd Maste if (name == NULL)
230f8d647b4SEd Maste return (1);
2316d395debSMariusz Zaborski pfile = fileargs_fopen(fa, name, "rb");
23261d994f1SMariusz Zaborski if (pfile == NULL) {
233a85fe12eSEd Maste warnx("'%s': %s", name, strerror(errno));
234f8d647b4SEd Maste return (1);
235a85fe12eSEd Maste }
236a85fe12eSEd Maste
23761d994f1SMariusz Zaborski rt = handle_elf(name, pfile);
23861d994f1SMariusz Zaborski fclose(pfile);
239a85fe12eSEd Maste return (rt);
240a85fe12eSEd Maste }
241a85fe12eSEd Maste
242a85fe12eSEd Maste /*
243a85fe12eSEd Maste * Files not understood by handle_elf, will be passed off here and will
244a85fe12eSEd Maste * treated as a binary file. This would include text file, core dumps ...
245a85fe12eSEd Maste */
246a85fe12eSEd Maste int
handle_binary(const char * name,FILE * pfile,size_t size)24761d994f1SMariusz Zaborski handle_binary(const char *name, FILE *pfile, size_t size)
248a85fe12eSEd Maste {
249a85fe12eSEd Maste
25061d994f1SMariusz Zaborski (void)fseeko(pfile, 0, SEEK_SET);
25161d994f1SMariusz Zaborski return (find_strings(name, pfile, 0, size));
252a85fe12eSEd Maste }
253a85fe12eSEd Maste
254a85fe12eSEd Maste /*
255a85fe12eSEd Maste * Will analyse a file to see if it ELF, other files including ar(1),
256a85fe12eSEd Maste * core dumps are passed off and treated as flat binary files. Unlike
257a85fe12eSEd Maste * GNU size in FreeBSD this routine will not treat ELF object from
258a85fe12eSEd Maste * different archs as flat binary files(has to overridden using -a).
259a85fe12eSEd Maste */
260a85fe12eSEd Maste int
handle_elf(const char * name,FILE * pfile)26161d994f1SMariusz Zaborski handle_elf(const char *name, FILE *pfile)
262a85fe12eSEd Maste {
26361d994f1SMariusz Zaborski struct stat buf;
264a85fe12eSEd Maste GElf_Ehdr elfhdr;
265a85fe12eSEd Maste GElf_Shdr shdr;
266a85fe12eSEd Maste Elf *elf;
267a85fe12eSEd Maste Elf_Scn *scn;
26861d994f1SMariusz Zaborski int rc, fd;
269a85fe12eSEd Maste
270f8d647b4SEd Maste rc = 0;
27161d994f1SMariusz Zaborski fd = fileno(pfile);
27261d994f1SMariusz Zaborski if (fstat(fd, &buf) < 0)
27361d994f1SMariusz Zaborski return (1);
27461d994f1SMariusz Zaborski
275b6b6f9ccSEd Maste /* If entire file is chosen, treat it as a binary file */
276a85fe12eSEd Maste if (entire_file)
27761d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size));
278a85fe12eSEd Maste
2794f486ad6SMariusz Zaborski (void)lseek(fd, 0, SEEK_SET);
280a85fe12eSEd Maste elf = elf_begin(fd, ELF_C_READ, NULL);
281a85fe12eSEd Maste if (elf_kind(elf) != ELF_K_ELF) {
282a85fe12eSEd Maste (void)elf_end(elf);
28361d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size));
284a85fe12eSEd Maste }
285a85fe12eSEd Maste
286a85fe12eSEd Maste if (gelf_getehdr(elf, &elfhdr) == NULL) {
287a85fe12eSEd Maste (void)elf_end(elf);
288a85fe12eSEd Maste warnx("%s: ELF file could not be processed", name);
289f8d647b4SEd Maste return (1);
290a85fe12eSEd Maste }
291a85fe12eSEd Maste
292a85fe12eSEd Maste if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) {
293a85fe12eSEd Maste (void)elf_end(elf);
29461d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size));
295a85fe12eSEd Maste } else {
296a85fe12eSEd Maste scn = NULL;
297a85fe12eSEd Maste while ((scn = elf_nextscn(elf, scn)) != NULL) {
298a85fe12eSEd Maste if (gelf_getshdr(scn, &shdr) == NULL)
299a85fe12eSEd Maste continue;
300a85fe12eSEd Maste if (shdr.sh_type != SHT_NOBITS &&
301a85fe12eSEd Maste (shdr.sh_flags & SHF_ALLOC) != 0) {
30261d994f1SMariusz Zaborski rc = find_strings(name, pfile, shdr.sh_offset,
303a85fe12eSEd Maste shdr.sh_size);
304a85fe12eSEd Maste }
305a85fe12eSEd Maste }
306a85fe12eSEd Maste }
307a85fe12eSEd Maste (void)elf_end(elf);
308a85fe12eSEd Maste return (rc);
309a85fe12eSEd Maste }
310a85fe12eSEd Maste
311a85fe12eSEd Maste /*
312a85fe12eSEd Maste * Retrieves a character from input stream based on the encoding
313a85fe12eSEd Maste * type requested.
314a85fe12eSEd Maste */
31555d3f888SMariusz Zaborski int
getcharacter(FILE * pfile,long * rt)31655d3f888SMariusz Zaborski getcharacter(FILE *pfile, long *rt)
317a85fe12eSEd Maste {
318cee114a8SMariusz Zaborski int i, c;
319cee114a8SMariusz Zaborski char buf[4];
320a85fe12eSEd Maste
321a85fe12eSEd Maste for(i = 0; i < encoding_size; i++) {
32261d994f1SMariusz Zaborski c = getc(pfile);
3234cb07cbaSMariusz Zaborski if (c == EOF)
32455d3f888SMariusz Zaborski return (-1);
325a85fe12eSEd Maste buf[i] = c;
326a85fe12eSEd Maste }
327a85fe12eSEd Maste
328a85fe12eSEd Maste switch (encoding) {
329a85fe12eSEd Maste case ENCODING_7BIT:
330a85fe12eSEd Maste case ENCODING_8BIT:
33155d3f888SMariusz Zaborski *rt = buf[0];
332a85fe12eSEd Maste break;
333a85fe12eSEd Maste case ENCODING_16BIT_BIG:
33455d3f888SMariusz Zaborski *rt = (buf[0] << 8) | buf[1];
335a85fe12eSEd Maste break;
336a85fe12eSEd Maste case ENCODING_16BIT_LITTLE:
33755d3f888SMariusz Zaborski *rt = buf[0] | (buf[1] << 8);
338a85fe12eSEd Maste break;
339a85fe12eSEd Maste case ENCODING_32BIT_BIG:
34055d3f888SMariusz Zaborski *rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) |
341a85fe12eSEd Maste ((long) buf[2] << 8) | buf[3];
342a85fe12eSEd Maste break;
343a85fe12eSEd Maste case ENCODING_32BIT_LITTLE:
34455d3f888SMariusz Zaborski *rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) |
345a85fe12eSEd Maste ((long) buf[3] << 24);
346a85fe12eSEd Maste break;
34755d3f888SMariusz Zaborski default:
34855d3f888SMariusz Zaborski return (-1);
349a85fe12eSEd Maste }
35055d3f888SMariusz Zaborski
35155d3f888SMariusz Zaborski return (0);
352a85fe12eSEd Maste }
353a85fe12eSEd Maste
354a85fe12eSEd Maste /*
35561d994f1SMariusz Zaborski * Input stream is read until the end of file is reached or until
356a85fe12eSEd Maste * the section size is reached in case of ELF files. Contiguous
357a85fe12eSEd Maste * characters of >= min_size(default 4) will be displayed.
358a85fe12eSEd Maste */
359a85fe12eSEd Maste int
find_strings(const char * name,FILE * pfile,off_t offset,off_t size)36061d994f1SMariusz Zaborski find_strings(const char *name, FILE *pfile, off_t offset, off_t size)
361a85fe12eSEd Maste {
362a85fe12eSEd Maste off_t cur_off, start_off;
363a85fe12eSEd Maste char *obuf;
364a85fe12eSEd Maste long c;
365a85fe12eSEd Maste int i;
366a85fe12eSEd Maste
367a85fe12eSEd Maste if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) {
3684f486ad6SMariusz Zaborski fprintf(stderr, "Unable to allocate memory: %s\n",
369a85fe12eSEd Maste strerror(errno));
370f8d647b4SEd Maste return (1);
371a85fe12eSEd Maste }
372a85fe12eSEd Maste
37361d994f1SMariusz Zaborski (void)fseeko(pfile, offset, SEEK_SET);
374a85fe12eSEd Maste cur_off = offset;
375a85fe12eSEd Maste start_off = 0;
376248b5d08SMateusz Guzik for (;;) {
377a85fe12eSEd Maste if ((offset + size) && (cur_off >= offset + size))
378a85fe12eSEd Maste break;
379a85fe12eSEd Maste start_off = cur_off;
380a85fe12eSEd Maste memset(obuf, 0, min_len + 1);
381a85fe12eSEd Maste for(i = 0; i < min_len; i++) {
38255d3f888SMariusz Zaborski if (getcharacter(pfile, &c) < 0)
383a85fe12eSEd Maste goto _exit1;
384a85fe12eSEd Maste if (PRINTABLE(c)) {
385a85fe12eSEd Maste obuf[i] = c;
386a85fe12eSEd Maste obuf[i + 1] = 0;
387a85fe12eSEd Maste cur_off += encoding_size;
388a85fe12eSEd Maste } else {
389a85fe12eSEd Maste if (encoding == ENCODING_8BIT &&
390a85fe12eSEd Maste (uint8_t)c > 127) {
391a85fe12eSEd Maste obuf[i] = c;
392a85fe12eSEd Maste obuf[i + 1] = 0;
393a85fe12eSEd Maste cur_off += encoding_size;
394a85fe12eSEd Maste continue;
395a85fe12eSEd Maste }
396a85fe12eSEd Maste cur_off += encoding_size;
397a85fe12eSEd Maste break;
398a85fe12eSEd Maste }
399a85fe12eSEd Maste }
400a85fe12eSEd Maste
401a85fe12eSEd Maste if (i >= min_len && ((cur_off <= offset + size) ||
402a85fe12eSEd Maste !(offset + size))) {
403a85fe12eSEd Maste if (show_filename)
404a85fe12eSEd Maste printf("%s: ", name);
405a85fe12eSEd Maste if (show_loc) {
406a85fe12eSEd Maste switch (radix) {
407a85fe12eSEd Maste case RADIX_DECIMAL:
4084f486ad6SMariusz Zaborski printf("%7ju ", (uintmax_t)start_off);
409a85fe12eSEd Maste break;
410a85fe12eSEd Maste case RADIX_HEX:
4114f486ad6SMariusz Zaborski printf("%7jx ", (uintmax_t)start_off);
412a85fe12eSEd Maste break;
413a85fe12eSEd Maste case RADIX_OCTAL:
4144f486ad6SMariusz Zaborski printf("%7jo ", (uintmax_t)start_off);
415a85fe12eSEd Maste break;
416a85fe12eSEd Maste }
417a85fe12eSEd Maste }
418a85fe12eSEd Maste printf("%s", obuf);
419a85fe12eSEd Maste
420248b5d08SMateusz Guzik for (;;) {
421a85fe12eSEd Maste if ((offset + size) &&
422a85fe12eSEd Maste (cur_off >= offset + size))
423a85fe12eSEd Maste break;
42455d3f888SMariusz Zaborski if (getcharacter(pfile, &c) < 0)
4251194c3cbSMariusz Zaborski break;
42655d3f888SMariusz Zaborski cur_off += encoding_size;
427a85fe12eSEd Maste if (encoding == ENCODING_8BIT &&
428a85fe12eSEd Maste (uint8_t)c > 127) {
429a85fe12eSEd Maste putchar(c);
430a85fe12eSEd Maste continue;
431a85fe12eSEd Maste }
43255d3f888SMariusz Zaborski if (!PRINTABLE(c))
43355d3f888SMariusz Zaborski break;
434a85fe12eSEd Maste putchar(c);
435a85fe12eSEd Maste }
436a85fe12eSEd Maste putchar('\n');
437a85fe12eSEd Maste }
438a85fe12eSEd Maste }
439a85fe12eSEd Maste _exit1:
440a85fe12eSEd Maste free(obuf);
441f8d647b4SEd Maste return (0);
442a85fe12eSEd Maste }
443a85fe12eSEd Maste
444a85fe12eSEd Maste #define USAGE_MESSAGE "\
445a85fe12eSEd Maste Usage: %s [options] [file...]\n\
446a85fe12eSEd Maste Print contiguous sequences of printable characters.\n\n\
447a85fe12eSEd Maste Options:\n\
448a85fe12eSEd Maste -a | --all Scan the entire file for strings.\n\
449a85fe12eSEd Maste -e ENC | --encoding=ENC Select the character encoding to use.\n\
450a85fe12eSEd Maste -f | --print-file-name Print the file name before each string.\n\
451a85fe12eSEd Maste -h | --help Print a help message and exit.\n\
452a85fe12eSEd Maste -n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\
453a85fe12eSEd Maste -o Print offsets in octal.\n\
454a85fe12eSEd Maste -t R | --radix=R Print offsets using the radix named by 'R'.\n\
455a85fe12eSEd Maste -v | --version Print a version identifier and exit.\n"
456a85fe12eSEd Maste
457a85fe12eSEd Maste void
usage(void)458a85fe12eSEd Maste usage(void)
459a85fe12eSEd Maste {
4604f486ad6SMariusz Zaborski
4614f486ad6SMariusz Zaborski fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME());
462a85fe12eSEd Maste exit(EXIT_FAILURE);
463a85fe12eSEd Maste }
464a85fe12eSEd Maste
465a85fe12eSEd Maste void
show_version(void)466a85fe12eSEd Maste show_version(void)
467a85fe12eSEd Maste {
4684f486ad6SMariusz Zaborski
4694f486ad6SMariusz Zaborski printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version());
470a85fe12eSEd Maste exit(EXIT_SUCCESS);
471a85fe12eSEd Maste }
472