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> 284f486ad6SMariusz Zaborski #include <sys/stat.h> 29a85fe12eSEd Maste 30a85fe12eSEd Maste #include <ctype.h> 31a85fe12eSEd Maste #include <err.h> 32a85fe12eSEd Maste #include <errno.h> 33a85fe12eSEd Maste #include <fcntl.h> 34a85fe12eSEd Maste #include <getopt.h> 35a85fe12eSEd Maste #include <inttypes.h> 36a85fe12eSEd Maste #include <stdint.h> 37a85fe12eSEd Maste #include <stdio.h> 38a85fe12eSEd Maste #include <stdlib.h> 39a85fe12eSEd Maste #include <string.h> 40839529caSEd Maste #include <sysexits.h> 41a85fe12eSEd Maste #include <unistd.h> 42a85fe12eSEd Maste 43a85fe12eSEd Maste #include <libelf.h> 44a85fe12eSEd Maste #include <libelftc.h> 45a85fe12eSEd Maste #include <gelf.h> 46a85fe12eSEd Maste 47a85fe12eSEd Maste #include "_elftc.h" 48a85fe12eSEd Maste 49ae500c1fSEd Maste ELFTC_VCSID("$Id: strings.c 3648 2018-11-22 23:26:43Z emaste $"); 50a85fe12eSEd Maste 51a85fe12eSEd Maste enum radix_style { 52a85fe12eSEd Maste RADIX_DECIMAL, 53a85fe12eSEd Maste RADIX_HEX, 54a85fe12eSEd Maste RADIX_OCTAL 55a85fe12eSEd Maste }; 56a85fe12eSEd Maste 57a85fe12eSEd Maste enum encoding_style { 58a85fe12eSEd Maste ENCODING_7BIT, 59a85fe12eSEd Maste ENCODING_8BIT, 60a85fe12eSEd Maste ENCODING_16BIT_BIG, 61a85fe12eSEd Maste ENCODING_16BIT_LITTLE, 62a85fe12eSEd Maste ENCODING_32BIT_BIG, 63a85fe12eSEd Maste ENCODING_32BIT_LITTLE 64a85fe12eSEd Maste }; 65a85fe12eSEd Maste 66a85fe12eSEd Maste #define PRINTABLE(c) \ 67a85fe12eSEd Maste ((c) >= 0 && (c) <= 255 && \ 68a85fe12eSEd Maste ((c) == '\t' || isprint((c)) || \ 69a85fe12eSEd Maste (encoding == ENCODING_8BIT && (c) > 127))) 70a85fe12eSEd Maste 71839529caSEd Maste static int encoding_size, entire_file, show_filename, show_loc; 7250f69bfbSEd Maste static enum encoding_style encoding; 7350f69bfbSEd Maste static enum radix_style radix; 74839529caSEd Maste static intmax_t min_len; 75a85fe12eSEd Maste 76a85fe12eSEd Maste static struct option strings_longopts[] = { 77a85fe12eSEd Maste { "all", no_argument, NULL, 'a'}, 78a85fe12eSEd Maste { "bytes", required_argument, NULL, 'n'}, 79a85fe12eSEd Maste { "encoding", required_argument, NULL, 'e'}, 80a85fe12eSEd Maste { "help", no_argument, NULL, 'h'}, 81a85fe12eSEd Maste { "print-file-name", no_argument, NULL, 'f'}, 82a85fe12eSEd Maste { "radix", required_argument, NULL, 't'}, 83a85fe12eSEd Maste { "version", no_argument, NULL, 'v'}, 84a85fe12eSEd Maste { NULL, 0, NULL, 0 } 85a85fe12eSEd Maste }; 86a85fe12eSEd Maste 8761d994f1SMariusz Zaborski long getcharacter(FILE *); 88a85fe12eSEd Maste int handle_file(const char *); 8961d994f1SMariusz Zaborski int handle_elf(const char *, FILE *); 9061d994f1SMariusz Zaborski int handle_binary(const char *, FILE *, size_t); 9161d994f1SMariusz Zaborski int find_strings(const char *, FILE *, off_t, off_t); 92a85fe12eSEd Maste void show_version(void); 93a85fe12eSEd Maste void usage(void); 94a85fe12eSEd Maste 95a85fe12eSEd Maste /* 96a85fe12eSEd Maste * strings(1) extracts text(contiguous printable characters) 97a85fe12eSEd Maste * from elf and binary files. 98a85fe12eSEd Maste */ 99a85fe12eSEd Maste int 100a85fe12eSEd Maste main(int argc, char **argv) 101a85fe12eSEd Maste { 102a85fe12eSEd Maste int ch, rc; 103a85fe12eSEd Maste 104f8d647b4SEd Maste rc = 0; 105a85fe12eSEd Maste min_len = 0; 106a85fe12eSEd Maste encoding_size = 1; 107a85fe12eSEd Maste if (elf_version(EV_CURRENT) == EV_NONE) 108a85fe12eSEd Maste errx(EXIT_FAILURE, "ELF library initialization failed: %s", 109a85fe12eSEd Maste elf_errmsg(-1)); 110a85fe12eSEd Maste 111a85fe12eSEd Maste while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv", 1124f486ad6SMariusz Zaborski strings_longopts, NULL)) != -1) { 113a85fe12eSEd Maste switch ((char)ch) { 114a85fe12eSEd Maste case 'a': 115a85fe12eSEd Maste entire_file = 1; 116a85fe12eSEd Maste break; 117a85fe12eSEd Maste case 'e': 118a85fe12eSEd Maste if (*optarg == 's') { 119a85fe12eSEd Maste encoding = ENCODING_7BIT; 120a85fe12eSEd Maste } else if (*optarg == 'S') { 121a85fe12eSEd Maste encoding = ENCODING_8BIT; 122a85fe12eSEd Maste } else if (*optarg == 'b') { 123a85fe12eSEd Maste encoding = ENCODING_16BIT_BIG; 124a85fe12eSEd Maste encoding_size = 2; 125a85fe12eSEd Maste } else if (*optarg == 'B') { 126a85fe12eSEd Maste encoding = ENCODING_32BIT_BIG; 127a85fe12eSEd Maste encoding_size = 4; 128a85fe12eSEd Maste } else if (*optarg == 'l') { 129a85fe12eSEd Maste encoding = ENCODING_16BIT_LITTLE; 130a85fe12eSEd Maste encoding_size = 2; 131a85fe12eSEd Maste } else if (*optarg == 'L') { 132a85fe12eSEd Maste encoding = ENCODING_32BIT_LITTLE; 133a85fe12eSEd Maste encoding_size = 4; 134a85fe12eSEd Maste } else 135a85fe12eSEd Maste usage(); 136a85fe12eSEd Maste /* NOTREACHED */ 137a85fe12eSEd Maste break; 138a85fe12eSEd Maste case 'f': 139a85fe12eSEd Maste show_filename = 1; 140a85fe12eSEd Maste break; 141a85fe12eSEd Maste case 'n': 142839529caSEd Maste min_len = strtoimax(optarg, (char**)NULL, 10); 143839529caSEd Maste if (min_len <= 0) 144839529caSEd Maste errx(EX_USAGE, "option -n should specify a " 145839529caSEd Maste "positive decimal integer."); 146a85fe12eSEd Maste break; 147a85fe12eSEd Maste case 'o': 148a85fe12eSEd Maste show_loc = 1; 149a85fe12eSEd Maste radix = RADIX_OCTAL; 150a85fe12eSEd Maste break; 151a85fe12eSEd Maste case 't': 152a85fe12eSEd Maste show_loc = 1; 153a85fe12eSEd Maste if (*optarg == 'd') 154a85fe12eSEd Maste radix = RADIX_DECIMAL; 155a85fe12eSEd Maste else if (*optarg == 'o') 156a85fe12eSEd Maste radix = RADIX_OCTAL; 157a85fe12eSEd Maste else if (*optarg == 'x') 158a85fe12eSEd Maste radix = RADIX_HEX; 159a85fe12eSEd Maste else 160a85fe12eSEd Maste usage(); 161a85fe12eSEd Maste /* NOTREACHED */ 162a85fe12eSEd Maste break; 163a85fe12eSEd Maste case 'v': 164a85fe12eSEd Maste case 'V': 165a85fe12eSEd Maste show_version(); 166a85fe12eSEd Maste /* NOTREACHED */ 167a85fe12eSEd Maste case '0': 168a85fe12eSEd Maste case '1': 169a85fe12eSEd Maste case '2': 170a85fe12eSEd Maste case '3': 171a85fe12eSEd Maste case '4': 172a85fe12eSEd Maste case '5': 173a85fe12eSEd Maste case '6': 174a85fe12eSEd Maste case '7': 175a85fe12eSEd Maste case '8': 176a85fe12eSEd Maste case '9': 177a85fe12eSEd Maste min_len *= 10; 178a85fe12eSEd Maste min_len += ch - '0'; 179a85fe12eSEd Maste break; 180a85fe12eSEd Maste case 'h': 181a85fe12eSEd Maste case '?': 182a85fe12eSEd Maste default: 183a85fe12eSEd Maste usage(); 184a85fe12eSEd Maste /* NOTREACHED */ 185a85fe12eSEd Maste } 1864f486ad6SMariusz Zaborski } 187a85fe12eSEd Maste argc -= optind; 188a85fe12eSEd Maste argv += optind; 189a85fe12eSEd Maste 1904f486ad6SMariusz Zaborski if (min_len == 0) 191a85fe12eSEd Maste min_len = 4; 1924f486ad6SMariusz Zaborski if (*argv == NULL) 19361d994f1SMariusz Zaborski rc = find_strings("{standard input}", stdin, 0, 0); 1944f486ad6SMariusz Zaborski else while (*argv != NULL) { 195f8d647b4SEd Maste if (handle_file(*argv) != 0) 196f8d647b4SEd Maste rc = 1; 197a85fe12eSEd Maste argv++; 198a85fe12eSEd Maste } 199a85fe12eSEd Maste return (rc); 200a85fe12eSEd Maste } 201a85fe12eSEd Maste 202a85fe12eSEd Maste int 203a85fe12eSEd Maste handle_file(const char *name) 204a85fe12eSEd Maste { 20561d994f1SMariusz Zaborski FILE *pfile; 20661d994f1SMariusz Zaborski int rt; 207a85fe12eSEd Maste 208a85fe12eSEd Maste if (name == NULL) 209f8d647b4SEd Maste return (1); 21061d994f1SMariusz Zaborski pfile = fopen(name, "rb"); 21161d994f1SMariusz Zaborski if (pfile == NULL) { 212a85fe12eSEd Maste warnx("'%s': %s", name, strerror(errno)); 213f8d647b4SEd Maste return (1); 214a85fe12eSEd Maste } 215a85fe12eSEd Maste 21661d994f1SMariusz Zaborski rt = handle_elf(name, pfile); 21761d994f1SMariusz Zaborski fclose(pfile); 218a85fe12eSEd Maste return (rt); 219a85fe12eSEd Maste } 220a85fe12eSEd Maste 221a85fe12eSEd Maste /* 222a85fe12eSEd Maste * Files not understood by handle_elf, will be passed off here and will 223a85fe12eSEd Maste * treated as a binary file. This would include text file, core dumps ... 224a85fe12eSEd Maste */ 225a85fe12eSEd Maste int 22661d994f1SMariusz Zaborski handle_binary(const char *name, FILE *pfile, size_t size) 227a85fe12eSEd Maste { 228a85fe12eSEd Maste 22961d994f1SMariusz Zaborski (void)fseeko(pfile, 0, SEEK_SET); 23061d994f1SMariusz Zaborski return (find_strings(name, pfile, 0, size)); 231a85fe12eSEd Maste } 232a85fe12eSEd Maste 233a85fe12eSEd Maste /* 234a85fe12eSEd Maste * Will analyse a file to see if it ELF, other files including ar(1), 235a85fe12eSEd Maste * core dumps are passed off and treated as flat binary files. Unlike 236a85fe12eSEd Maste * GNU size in FreeBSD this routine will not treat ELF object from 237a85fe12eSEd Maste * different archs as flat binary files(has to overridden using -a). 238a85fe12eSEd Maste */ 239a85fe12eSEd Maste int 24061d994f1SMariusz Zaborski handle_elf(const char *name, FILE *pfile) 241a85fe12eSEd Maste { 24261d994f1SMariusz Zaborski struct stat buf; 243a85fe12eSEd Maste GElf_Ehdr elfhdr; 244a85fe12eSEd Maste GElf_Shdr shdr; 245a85fe12eSEd Maste Elf *elf; 246a85fe12eSEd Maste Elf_Scn *scn; 24761d994f1SMariusz Zaborski int rc, fd; 248a85fe12eSEd Maste 249f8d647b4SEd Maste rc = 0; 25061d994f1SMariusz Zaborski fd = fileno(pfile); 25161d994f1SMariusz Zaborski if (fstat(fd, &buf) < 0) 25261d994f1SMariusz Zaborski return (1); 25361d994f1SMariusz Zaborski 254b6b6f9ccSEd Maste /* If entire file is chosen, treat it as a binary file */ 255a85fe12eSEd Maste if (entire_file) 25661d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size)); 257a85fe12eSEd Maste 2584f486ad6SMariusz Zaborski (void)lseek(fd, 0, SEEK_SET); 259a85fe12eSEd Maste elf = elf_begin(fd, ELF_C_READ, NULL); 260a85fe12eSEd Maste if (elf_kind(elf) != ELF_K_ELF) { 261a85fe12eSEd Maste (void)elf_end(elf); 26261d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size)); 263a85fe12eSEd Maste } 264a85fe12eSEd Maste 265a85fe12eSEd Maste if (gelf_getehdr(elf, &elfhdr) == NULL) { 266a85fe12eSEd Maste (void)elf_end(elf); 267a85fe12eSEd Maste warnx("%s: ELF file could not be processed", name); 268f8d647b4SEd Maste return (1); 269a85fe12eSEd Maste } 270a85fe12eSEd Maste 271a85fe12eSEd Maste if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { 272a85fe12eSEd Maste (void)elf_end(elf); 27361d994f1SMariusz Zaborski return (handle_binary(name, pfile, buf.st_size)); 274a85fe12eSEd Maste } else { 275a85fe12eSEd Maste scn = NULL; 276a85fe12eSEd Maste while ((scn = elf_nextscn(elf, scn)) != NULL) { 277a85fe12eSEd Maste if (gelf_getshdr(scn, &shdr) == NULL) 278a85fe12eSEd Maste continue; 279a85fe12eSEd Maste if (shdr.sh_type != SHT_NOBITS && 280a85fe12eSEd Maste (shdr.sh_flags & SHF_ALLOC) != 0) { 28161d994f1SMariusz Zaborski rc = find_strings(name, pfile, shdr.sh_offset, 282a85fe12eSEd Maste shdr.sh_size); 283a85fe12eSEd Maste } 284a85fe12eSEd Maste } 285a85fe12eSEd Maste } 286a85fe12eSEd Maste (void)elf_end(elf); 287a85fe12eSEd Maste return (rc); 288a85fe12eSEd Maste } 289a85fe12eSEd Maste 290a85fe12eSEd Maste /* 291a85fe12eSEd Maste * Retrieves a character from input stream based on the encoding 292a85fe12eSEd Maste * type requested. 293a85fe12eSEd Maste */ 294a85fe12eSEd Maste long 29561d994f1SMariusz Zaborski getcharacter(FILE *pfile) 296a85fe12eSEd Maste { 297a85fe12eSEd Maste long rt; 298*cee114a8SMariusz Zaborski int i, c; 299*cee114a8SMariusz Zaborski char buf[4]; 300a85fe12eSEd Maste 301a85fe12eSEd Maste for(i = 0; i < encoding_size; i++) { 30261d994f1SMariusz Zaborski c = getc(pfile); 3034cb07cbaSMariusz Zaborski if (c == EOF) 304a85fe12eSEd Maste return (EOF); 305a85fe12eSEd Maste buf[i] = c; 306a85fe12eSEd Maste } 307a85fe12eSEd Maste 30861d994f1SMariusz Zaborski rt = EOF; 309a85fe12eSEd Maste switch (encoding) { 310a85fe12eSEd Maste case ENCODING_7BIT: 311a85fe12eSEd Maste case ENCODING_8BIT: 312a85fe12eSEd Maste rt = buf[0]; 313a85fe12eSEd Maste break; 314a85fe12eSEd Maste case ENCODING_16BIT_BIG: 315a85fe12eSEd Maste rt = (buf[0] << 8) | buf[1]; 316a85fe12eSEd Maste break; 317a85fe12eSEd Maste case ENCODING_16BIT_LITTLE: 318a85fe12eSEd Maste rt = buf[0] | (buf[1] << 8); 319a85fe12eSEd Maste break; 320a85fe12eSEd Maste case ENCODING_32BIT_BIG: 321a85fe12eSEd Maste rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) | 322a85fe12eSEd Maste ((long) buf[2] << 8) | buf[3]; 323a85fe12eSEd Maste break; 324a85fe12eSEd Maste case ENCODING_32BIT_LITTLE: 325a85fe12eSEd Maste rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) | 326a85fe12eSEd Maste ((long) buf[3] << 24); 327a85fe12eSEd Maste break; 328a85fe12eSEd Maste } 329a85fe12eSEd Maste return (rt); 330a85fe12eSEd Maste } 331a85fe12eSEd Maste 332a85fe12eSEd Maste /* 33361d994f1SMariusz Zaborski * Input stream is read until the end of file is reached or until 334a85fe12eSEd Maste * the section size is reached in case of ELF files. Contiguous 335a85fe12eSEd Maste * characters of >= min_size(default 4) will be displayed. 336a85fe12eSEd Maste */ 337a85fe12eSEd Maste int 33861d994f1SMariusz Zaborski find_strings(const char *name, FILE *pfile, off_t offset, off_t size) 339a85fe12eSEd Maste { 340a85fe12eSEd Maste off_t cur_off, start_off; 341a85fe12eSEd Maste char *obuf; 342a85fe12eSEd Maste long c; 343a85fe12eSEd Maste int i; 344a85fe12eSEd Maste 345a85fe12eSEd Maste if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) { 3464f486ad6SMariusz Zaborski fprintf(stderr, "Unable to allocate memory: %s\n", 347a85fe12eSEd Maste strerror(errno)); 348f8d647b4SEd Maste return (1); 349a85fe12eSEd Maste } 350a85fe12eSEd Maste 35161d994f1SMariusz Zaborski (void)fseeko(pfile, offset, SEEK_SET); 352a85fe12eSEd Maste cur_off = offset; 353a85fe12eSEd Maste start_off = 0; 354248b5d08SMateusz Guzik for (;;) { 355a85fe12eSEd Maste if ((offset + size) && (cur_off >= offset + size)) 356a85fe12eSEd Maste break; 357a85fe12eSEd Maste start_off = cur_off; 358a85fe12eSEd Maste memset(obuf, 0, min_len + 1); 359a85fe12eSEd Maste for(i = 0; i < min_len; i++) { 36061d994f1SMariusz Zaborski c = getcharacter(pfile); 3614cb07cbaSMariusz Zaborski if (c == EOF) 362a85fe12eSEd Maste goto _exit1; 363a85fe12eSEd Maste if (PRINTABLE(c)) { 364a85fe12eSEd Maste obuf[i] = c; 365a85fe12eSEd Maste obuf[i + 1] = 0; 366a85fe12eSEd Maste cur_off += encoding_size; 367a85fe12eSEd Maste } else { 368a85fe12eSEd Maste if (encoding == ENCODING_8BIT && 369a85fe12eSEd Maste (uint8_t)c > 127) { 370a85fe12eSEd Maste obuf[i] = c; 371a85fe12eSEd Maste obuf[i + 1] = 0; 372a85fe12eSEd Maste cur_off += encoding_size; 373a85fe12eSEd Maste continue; 374a85fe12eSEd Maste } 375a85fe12eSEd Maste cur_off += encoding_size; 376a85fe12eSEd Maste break; 377a85fe12eSEd Maste } 378a85fe12eSEd Maste } 379a85fe12eSEd Maste 380a85fe12eSEd Maste if (i >= min_len && ((cur_off <= offset + size) || 381a85fe12eSEd Maste !(offset + size))) { 382a85fe12eSEd Maste if (show_filename) 383a85fe12eSEd Maste printf("%s: ", name); 384a85fe12eSEd Maste if (show_loc) { 385a85fe12eSEd Maste switch (radix) { 386a85fe12eSEd Maste case RADIX_DECIMAL: 3874f486ad6SMariusz Zaborski printf("%7ju ", (uintmax_t)start_off); 388a85fe12eSEd Maste break; 389a85fe12eSEd Maste case RADIX_HEX: 3904f486ad6SMariusz Zaborski printf("%7jx ", (uintmax_t)start_off); 391a85fe12eSEd Maste break; 392a85fe12eSEd Maste case RADIX_OCTAL: 3934f486ad6SMariusz Zaborski printf("%7jo ", (uintmax_t)start_off); 394a85fe12eSEd Maste break; 395a85fe12eSEd Maste } 396a85fe12eSEd Maste } 397a85fe12eSEd Maste printf("%s", obuf); 398a85fe12eSEd Maste 399248b5d08SMateusz Guzik for (;;) { 400a85fe12eSEd Maste if ((offset + size) && 401a85fe12eSEd Maste (cur_off >= offset + size)) 402a85fe12eSEd Maste break; 40361d994f1SMariusz Zaborski c = getcharacter(pfile); 404a85fe12eSEd Maste cur_off += encoding_size; 405a85fe12eSEd Maste if (encoding == ENCODING_8BIT && 406a85fe12eSEd Maste (uint8_t)c > 127) { 407a85fe12eSEd Maste putchar(c); 408a85fe12eSEd Maste continue; 409a85fe12eSEd Maste } 410a85fe12eSEd Maste if (!PRINTABLE(c) || c == EOF) 411a85fe12eSEd Maste break; 412a85fe12eSEd Maste putchar(c); 413a85fe12eSEd Maste } 414a85fe12eSEd Maste putchar('\n'); 415a85fe12eSEd Maste } 416a85fe12eSEd Maste } 417a85fe12eSEd Maste _exit1: 418a85fe12eSEd Maste free(obuf); 419f8d647b4SEd Maste return (0); 420a85fe12eSEd Maste } 421a85fe12eSEd Maste 422a85fe12eSEd Maste #define USAGE_MESSAGE "\ 423a85fe12eSEd Maste Usage: %s [options] [file...]\n\ 424a85fe12eSEd Maste Print contiguous sequences of printable characters.\n\n\ 425a85fe12eSEd Maste Options:\n\ 426a85fe12eSEd Maste -a | --all Scan the entire file for strings.\n\ 427a85fe12eSEd Maste -e ENC | --encoding=ENC Select the character encoding to use.\n\ 428a85fe12eSEd Maste -f | --print-file-name Print the file name before each string.\n\ 429a85fe12eSEd Maste -h | --help Print a help message and exit.\n\ 430a85fe12eSEd Maste -n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\ 431a85fe12eSEd Maste -o Print offsets in octal.\n\ 432a85fe12eSEd Maste -t R | --radix=R Print offsets using the radix named by 'R'.\n\ 433a85fe12eSEd Maste -v | --version Print a version identifier and exit.\n" 434a85fe12eSEd Maste 435a85fe12eSEd Maste void 436a85fe12eSEd Maste usage(void) 437a85fe12eSEd Maste { 4384f486ad6SMariusz Zaborski 4394f486ad6SMariusz Zaborski fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 440a85fe12eSEd Maste exit(EXIT_FAILURE); 441a85fe12eSEd Maste } 442a85fe12eSEd Maste 443a85fe12eSEd Maste void 444a85fe12eSEd Maste show_version(void) 445a85fe12eSEd Maste { 4464f486ad6SMariusz Zaborski 4474f486ad6SMariusz Zaborski printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 448a85fe12eSEd Maste exit(EXIT_SUCCESS); 449a85fe12eSEd Maste } 450