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/stat.h> 28a85fe12eSEd Maste #include <sys/types.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> 40*839529caSEd 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 49*839529caSEd Maste ELFTC_VCSID("$Id: strings.c 3360 2016-01-24 18:34:06Z jkoshy $"); 50a85fe12eSEd Maste 51a85fe12eSEd Maste enum return_code { 52a85fe12eSEd Maste RETURN_OK, 53a85fe12eSEd Maste RETURN_NOINPUT, 54a85fe12eSEd Maste RETURN_SOFTWARE 55a85fe12eSEd Maste }; 56a85fe12eSEd Maste 57a85fe12eSEd Maste enum radix_style { 58a85fe12eSEd Maste RADIX_DECIMAL, 59a85fe12eSEd Maste RADIX_HEX, 60a85fe12eSEd Maste RADIX_OCTAL 61a85fe12eSEd Maste }; 62a85fe12eSEd Maste 63a85fe12eSEd Maste enum encoding_style { 64a85fe12eSEd Maste ENCODING_7BIT, 65a85fe12eSEd Maste ENCODING_8BIT, 66a85fe12eSEd Maste ENCODING_16BIT_BIG, 67a85fe12eSEd Maste ENCODING_16BIT_LITTLE, 68a85fe12eSEd Maste ENCODING_32BIT_BIG, 69a85fe12eSEd Maste ENCODING_32BIT_LITTLE 70a85fe12eSEd Maste }; 71a85fe12eSEd Maste 72a85fe12eSEd Maste #define PRINTABLE(c) \ 73a85fe12eSEd Maste ((c) >= 0 && (c) <= 255 && \ 74a85fe12eSEd Maste ((c) == '\t' || isprint((c)) || \ 75a85fe12eSEd Maste (encoding == ENCODING_8BIT && (c) > 127))) 76a85fe12eSEd Maste 77*839529caSEd Maste static int encoding_size, entire_file, show_filename, show_loc; 7850f69bfbSEd Maste static enum encoding_style encoding; 7950f69bfbSEd Maste static enum radix_style radix; 80*839529caSEd Maste static intmax_t min_len; 81a85fe12eSEd Maste 82a85fe12eSEd Maste static struct option strings_longopts[] = { 83a85fe12eSEd Maste { "all", no_argument, NULL, 'a'}, 84a85fe12eSEd Maste { "bytes", required_argument, NULL, 'n'}, 85a85fe12eSEd Maste { "encoding", required_argument, NULL, 'e'}, 86a85fe12eSEd Maste { "help", no_argument, NULL, 'h'}, 87a85fe12eSEd Maste { "print-file-name", no_argument, NULL, 'f'}, 88a85fe12eSEd Maste { "radix", required_argument, NULL, 't'}, 89a85fe12eSEd Maste { "version", no_argument, NULL, 'v'}, 90a85fe12eSEd Maste { NULL, 0, NULL, 0 } 91a85fe12eSEd Maste }; 92a85fe12eSEd Maste 93a85fe12eSEd Maste long getcharacter(void); 94a85fe12eSEd Maste int handle_file(const char *); 95a85fe12eSEd Maste int handle_elf(const char *, int); 96a85fe12eSEd Maste int handle_binary(const char *, int); 97a85fe12eSEd Maste int find_strings(const char *, off_t, off_t); 98a85fe12eSEd Maste void show_version(void); 99a85fe12eSEd Maste void usage(void); 100a85fe12eSEd Maste 101a85fe12eSEd Maste /* 102a85fe12eSEd Maste * strings(1) extracts text(contiguous printable characters) 103a85fe12eSEd Maste * from elf and binary files. 104a85fe12eSEd Maste */ 105a85fe12eSEd Maste int 106a85fe12eSEd Maste main(int argc, char **argv) 107a85fe12eSEd Maste { 108a85fe12eSEd Maste int ch, rc; 109a85fe12eSEd Maste 110a85fe12eSEd Maste rc = RETURN_OK; 111a85fe12eSEd Maste min_len = 0; 112a85fe12eSEd Maste encoding_size = 1; 113a85fe12eSEd Maste if (elf_version(EV_CURRENT) == EV_NONE) 114a85fe12eSEd Maste errx(EXIT_FAILURE, "ELF library initialization failed: %s", 115a85fe12eSEd Maste elf_errmsg(-1)); 116a85fe12eSEd Maste 117a85fe12eSEd Maste while ((ch = getopt_long(argc, argv, "1234567890ae:fhn:ot:Vv", 118a85fe12eSEd Maste strings_longopts, NULL)) != -1) 119a85fe12eSEd Maste switch((char)ch) { 120a85fe12eSEd Maste case 'a': 121a85fe12eSEd Maste entire_file = 1; 122a85fe12eSEd Maste break; 123a85fe12eSEd Maste case 'e': 124a85fe12eSEd Maste if (*optarg == 's') { 125a85fe12eSEd Maste encoding = ENCODING_7BIT; 126a85fe12eSEd Maste } else if (*optarg == 'S') { 127a85fe12eSEd Maste encoding = ENCODING_8BIT; 128a85fe12eSEd Maste } else if (*optarg == 'b') { 129a85fe12eSEd Maste encoding = ENCODING_16BIT_BIG; 130a85fe12eSEd Maste encoding_size = 2; 131a85fe12eSEd Maste } else if (*optarg == 'B') { 132a85fe12eSEd Maste encoding = ENCODING_32BIT_BIG; 133a85fe12eSEd Maste encoding_size = 4; 134a85fe12eSEd Maste } else if (*optarg == 'l') { 135a85fe12eSEd Maste encoding = ENCODING_16BIT_LITTLE; 136a85fe12eSEd Maste encoding_size = 2; 137a85fe12eSEd Maste } else if (*optarg == 'L') { 138a85fe12eSEd Maste encoding = ENCODING_32BIT_LITTLE; 139a85fe12eSEd Maste encoding_size = 4; 140a85fe12eSEd Maste } else 141a85fe12eSEd Maste usage(); 142a85fe12eSEd Maste /* NOTREACHED */ 143a85fe12eSEd Maste break; 144a85fe12eSEd Maste case 'f': 145a85fe12eSEd Maste show_filename = 1; 146a85fe12eSEd Maste break; 147a85fe12eSEd Maste case 'n': 148*839529caSEd Maste min_len = strtoimax(optarg, (char**)NULL, 10); 149*839529caSEd Maste if (min_len <= 0) 150*839529caSEd Maste errx(EX_USAGE, "option -n should specify a " 151*839529caSEd Maste "positive decimal integer."); 152a85fe12eSEd Maste break; 153a85fe12eSEd Maste case 'o': 154a85fe12eSEd Maste show_loc = 1; 155a85fe12eSEd Maste radix = RADIX_OCTAL; 156a85fe12eSEd Maste break; 157a85fe12eSEd Maste case 't': 158a85fe12eSEd Maste show_loc = 1; 159a85fe12eSEd Maste if (*optarg == 'd') 160a85fe12eSEd Maste radix = RADIX_DECIMAL; 161a85fe12eSEd Maste else if (*optarg == 'o') 162a85fe12eSEd Maste radix = RADIX_OCTAL; 163a85fe12eSEd Maste else if (*optarg == 'x') 164a85fe12eSEd Maste radix = RADIX_HEX; 165a85fe12eSEd Maste else 166a85fe12eSEd Maste usage(); 167a85fe12eSEd Maste /* NOTREACHED */ 168a85fe12eSEd Maste break; 169a85fe12eSEd Maste case 'v': 170a85fe12eSEd Maste case 'V': 171a85fe12eSEd Maste show_version(); 172a85fe12eSEd Maste /* NOTREACHED */ 173a85fe12eSEd Maste case '0': 174a85fe12eSEd Maste case '1': 175a85fe12eSEd Maste case '2': 176a85fe12eSEd Maste case '3': 177a85fe12eSEd Maste case '4': 178a85fe12eSEd Maste case '5': 179a85fe12eSEd Maste case '6': 180a85fe12eSEd Maste case '7': 181a85fe12eSEd Maste case '8': 182a85fe12eSEd Maste case '9': 183a85fe12eSEd Maste min_len *= 10; 184a85fe12eSEd Maste min_len += ch - '0'; 185a85fe12eSEd Maste break; 186a85fe12eSEd Maste case 'h': 187a85fe12eSEd Maste case '?': 188a85fe12eSEd Maste default: 189a85fe12eSEd Maste usage(); 190a85fe12eSEd Maste /* NOTREACHED */ 191a85fe12eSEd Maste } 192a85fe12eSEd Maste argc -= optind; 193a85fe12eSEd Maste argv += optind; 194a85fe12eSEd Maste 195a85fe12eSEd Maste if (!min_len) 196a85fe12eSEd Maste min_len = 4; 197a85fe12eSEd Maste if (!*argv) 198a85fe12eSEd Maste rc = handle_file("{standard input}"); 199a85fe12eSEd Maste else while (*argv) { 200a85fe12eSEd Maste rc = handle_file(*argv); 201a85fe12eSEd Maste argv++; 202a85fe12eSEd Maste } 203a85fe12eSEd Maste return (rc); 204a85fe12eSEd Maste } 205a85fe12eSEd Maste 206a85fe12eSEd Maste int 207a85fe12eSEd Maste handle_file(const char *name) 208a85fe12eSEd Maste { 209a85fe12eSEd Maste int fd, rt; 210a85fe12eSEd Maste 211a85fe12eSEd Maste if (name == NULL) 212a85fe12eSEd Maste return (RETURN_NOINPUT); 213a85fe12eSEd Maste if (strcmp("{standard input}", name) != 0) { 214a85fe12eSEd Maste if (freopen(name, "rb", stdin) == NULL) { 215a85fe12eSEd Maste warnx("'%s': %s", name, strerror(errno)); 216a85fe12eSEd Maste return (RETURN_NOINPUT); 217a85fe12eSEd Maste } 218a85fe12eSEd Maste } else { 219a85fe12eSEd Maste return (find_strings(name, (off_t)0, (off_t)0)); 220a85fe12eSEd Maste } 221a85fe12eSEd Maste 222a85fe12eSEd Maste fd = fileno(stdin); 223a85fe12eSEd Maste if (fd < 0) 224a85fe12eSEd Maste return (RETURN_NOINPUT); 225a85fe12eSEd Maste rt = handle_elf(name, fd); 226a85fe12eSEd Maste return (rt); 227a85fe12eSEd Maste } 228a85fe12eSEd Maste 229a85fe12eSEd Maste /* 230a85fe12eSEd Maste * Files not understood by handle_elf, will be passed off here and will 231a85fe12eSEd Maste * treated as a binary file. This would include text file, core dumps ... 232a85fe12eSEd Maste */ 233a85fe12eSEd Maste int 234a85fe12eSEd Maste handle_binary(const char *name, int fd) 235a85fe12eSEd Maste { 236a85fe12eSEd Maste struct stat buf; 237a85fe12eSEd Maste 238a85fe12eSEd Maste memset(&buf, 0, sizeof(struct stat)); 239a85fe12eSEd Maste (void) lseek(fd, (off_t)0, SEEK_SET); 240a85fe12eSEd Maste if (!fstat(fd, &buf)) 241a85fe12eSEd Maste return (find_strings(name, (off_t)0, buf.st_size)); 242a85fe12eSEd Maste return (RETURN_SOFTWARE); 243a85fe12eSEd Maste } 244a85fe12eSEd Maste 245a85fe12eSEd Maste /* 246a85fe12eSEd Maste * Will analyse a file to see if it ELF, other files including ar(1), 247a85fe12eSEd Maste * core dumps are passed off and treated as flat binary files. Unlike 248a85fe12eSEd Maste * GNU size in FreeBSD this routine will not treat ELF object from 249a85fe12eSEd Maste * different archs as flat binary files(has to overridden using -a). 250a85fe12eSEd Maste */ 251a85fe12eSEd Maste int 252a85fe12eSEd Maste handle_elf(const char *name, int fd) 253a85fe12eSEd Maste { 254a85fe12eSEd Maste GElf_Ehdr elfhdr; 255a85fe12eSEd Maste GElf_Shdr shdr; 256a85fe12eSEd Maste Elf *elf; 257a85fe12eSEd Maste Elf_Scn *scn; 258a85fe12eSEd Maste int rc; 259a85fe12eSEd Maste 260a85fe12eSEd Maste rc = RETURN_OK; 261a85fe12eSEd Maste /* If entire file is choosen, treat it as a binary file */ 262a85fe12eSEd Maste if (entire_file) 263a85fe12eSEd Maste return (handle_binary(name, fd)); 264a85fe12eSEd Maste 265a85fe12eSEd Maste (void) lseek(fd, (off_t)0, SEEK_SET); 266a85fe12eSEd Maste elf = elf_begin(fd, ELF_C_READ, NULL); 267a85fe12eSEd Maste if (elf_kind(elf) != ELF_K_ELF) { 268a85fe12eSEd Maste (void) elf_end(elf); 269a85fe12eSEd Maste return (handle_binary(name, fd)); 270a85fe12eSEd Maste } 271a85fe12eSEd Maste 272a85fe12eSEd Maste if (gelf_getehdr(elf, &elfhdr) == NULL) { 273a85fe12eSEd Maste (void) elf_end(elf); 274a85fe12eSEd Maste warnx("%s: ELF file could not be processed", name); 275a85fe12eSEd Maste return (RETURN_SOFTWARE); 276a85fe12eSEd Maste } 277a85fe12eSEd Maste 278a85fe12eSEd Maste if (elfhdr.e_shnum == 0 && elfhdr.e_type == ET_CORE) { 279a85fe12eSEd Maste (void) elf_end(elf); 280a85fe12eSEd Maste return (handle_binary(name, fd)); 281a85fe12eSEd Maste } else { 282a85fe12eSEd Maste scn = NULL; 283a85fe12eSEd Maste while ((scn = elf_nextscn(elf, scn)) != NULL) { 284a85fe12eSEd Maste if (gelf_getshdr(scn, &shdr) == NULL) 285a85fe12eSEd Maste continue; 286a85fe12eSEd Maste if (shdr.sh_type != SHT_NOBITS && 287a85fe12eSEd Maste (shdr.sh_flags & SHF_ALLOC) != 0) { 288a85fe12eSEd Maste rc = find_strings(name, shdr.sh_offset, 289a85fe12eSEd Maste shdr.sh_size); 290a85fe12eSEd Maste } 291a85fe12eSEd Maste } 292a85fe12eSEd Maste } 293a85fe12eSEd Maste (void) elf_end(elf); 294a85fe12eSEd Maste return (rc); 295a85fe12eSEd Maste } 296a85fe12eSEd Maste 297a85fe12eSEd Maste /* 298a85fe12eSEd Maste * Retrieves a character from input stream based on the encoding 299a85fe12eSEd Maste * type requested. 300a85fe12eSEd Maste */ 301a85fe12eSEd Maste long 302a85fe12eSEd Maste getcharacter(void) 303a85fe12eSEd Maste { 304a85fe12eSEd Maste long rt; 305a85fe12eSEd Maste int i; 306a85fe12eSEd Maste char buf[4], c; 307a85fe12eSEd Maste 308a85fe12eSEd Maste rt = EOF; 309a85fe12eSEd Maste for(i = 0; i < encoding_size; i++) { 310a85fe12eSEd Maste c = getc(stdin); 311a85fe12eSEd Maste if (feof(stdin)) 312a85fe12eSEd Maste return (EOF); 313a85fe12eSEd Maste buf[i] = c; 314a85fe12eSEd Maste } 315a85fe12eSEd Maste 316a85fe12eSEd Maste switch(encoding) { 317a85fe12eSEd Maste case ENCODING_7BIT: 318a85fe12eSEd Maste case ENCODING_8BIT: 319a85fe12eSEd Maste rt = buf[0]; 320a85fe12eSEd Maste break; 321a85fe12eSEd Maste case ENCODING_16BIT_BIG: 322a85fe12eSEd Maste rt = (buf[0] << 8) | buf[1]; 323a85fe12eSEd Maste break; 324a85fe12eSEd Maste case ENCODING_16BIT_LITTLE: 325a85fe12eSEd Maste rt = buf[0] | (buf[1] << 8); 326a85fe12eSEd Maste break; 327a85fe12eSEd Maste case ENCODING_32BIT_BIG: 328a85fe12eSEd Maste rt = ((long) buf[0] << 24) | ((long) buf[1] << 16) | 329a85fe12eSEd Maste ((long) buf[2] << 8) | buf[3]; 330a85fe12eSEd Maste break; 331a85fe12eSEd Maste case ENCODING_32BIT_LITTLE: 332a85fe12eSEd Maste rt = buf[0] | ((long) buf[1] << 8) | ((long) buf[2] << 16) | 333a85fe12eSEd Maste ((long) buf[3] << 24); 334a85fe12eSEd Maste break; 335a85fe12eSEd Maste } 336a85fe12eSEd Maste return (rt); 337a85fe12eSEd Maste } 338a85fe12eSEd Maste 339a85fe12eSEd Maste /* 340a85fe12eSEd Maste * Input stream stdin is read until the end of file is reached or until 341a85fe12eSEd Maste * the section size is reached in case of ELF files. Contiguous 342a85fe12eSEd Maste * characters of >= min_size(default 4) will be displayed. 343a85fe12eSEd Maste */ 344a85fe12eSEd Maste int 345a85fe12eSEd Maste find_strings(const char *name, off_t offset, off_t size) 346a85fe12eSEd Maste { 347a85fe12eSEd Maste off_t cur_off, start_off; 348a85fe12eSEd Maste char *obuf; 349a85fe12eSEd Maste long c; 350a85fe12eSEd Maste int i; 351a85fe12eSEd Maste 352a85fe12eSEd Maste if ((obuf = (char*)calloc(1, min_len + 1)) == NULL) { 353a85fe12eSEd Maste (void) fprintf(stderr, "Unable to allocate memory: %s\n", 354a85fe12eSEd Maste strerror(errno)); 355a85fe12eSEd Maste return (RETURN_SOFTWARE); 356a85fe12eSEd Maste } 357a85fe12eSEd Maste 358a85fe12eSEd Maste (void) fseeko(stdin, offset, SEEK_SET); 359a85fe12eSEd Maste cur_off = offset; 360a85fe12eSEd Maste start_off = 0; 361a85fe12eSEd Maste while(1) { 362a85fe12eSEd Maste if ((offset + size) && (cur_off >= offset + size)) 363a85fe12eSEd Maste break; 364a85fe12eSEd Maste start_off = cur_off; 365a85fe12eSEd Maste memset(obuf, 0, min_len+1); 366a85fe12eSEd Maste for(i = 0; i < min_len; i++) { 367a85fe12eSEd Maste c = getcharacter(); 368a85fe12eSEd Maste if (c == EOF && feof(stdin)) 369a85fe12eSEd Maste goto _exit1; 370a85fe12eSEd Maste if (PRINTABLE(c)) { 371a85fe12eSEd Maste obuf[i] = c; 372a85fe12eSEd Maste obuf[i+1] = 0; 373a85fe12eSEd Maste cur_off += encoding_size; 374a85fe12eSEd Maste } else { 375a85fe12eSEd Maste if (encoding == ENCODING_8BIT && 376a85fe12eSEd Maste (uint8_t)c > 127) { 377a85fe12eSEd Maste obuf[i] = c; 378a85fe12eSEd Maste obuf[i+1] = 0; 379a85fe12eSEd Maste cur_off += encoding_size; 380a85fe12eSEd Maste continue; 381a85fe12eSEd Maste } 382a85fe12eSEd Maste cur_off += encoding_size; 383a85fe12eSEd Maste break; 384a85fe12eSEd Maste } 385a85fe12eSEd Maste } 386a85fe12eSEd Maste 387a85fe12eSEd Maste if (i >= min_len && ((cur_off <= offset + size) || 388a85fe12eSEd Maste !(offset + size))) { 389a85fe12eSEd Maste if (show_filename) 390a85fe12eSEd Maste printf ("%s: ", name); 391a85fe12eSEd Maste if (show_loc) { 392a85fe12eSEd Maste switch(radix) { 393a85fe12eSEd Maste case RADIX_DECIMAL: 394a85fe12eSEd Maste (void) printf("%7ju ", 395a85fe12eSEd Maste (uintmax_t)start_off); 396a85fe12eSEd Maste break; 397a85fe12eSEd Maste case RADIX_HEX: 398a85fe12eSEd Maste (void) printf("%7jx ", 399a85fe12eSEd Maste (uintmax_t)start_off); 400a85fe12eSEd Maste break; 401a85fe12eSEd Maste case RADIX_OCTAL: 402a85fe12eSEd Maste (void) printf("%7jo ", 403a85fe12eSEd Maste (uintmax_t)start_off); 404a85fe12eSEd Maste break; 405a85fe12eSEd Maste } 406a85fe12eSEd Maste } 407a85fe12eSEd Maste printf("%s", obuf); 408a85fe12eSEd Maste 409a85fe12eSEd Maste while(1) { 410a85fe12eSEd Maste if ((offset + size) && 411a85fe12eSEd Maste (cur_off >= offset + size)) 412a85fe12eSEd Maste break; 413a85fe12eSEd Maste c = getcharacter(); 414a85fe12eSEd Maste cur_off += encoding_size; 415a85fe12eSEd Maste if (encoding == ENCODING_8BIT && 416a85fe12eSEd Maste (uint8_t)c > 127) { 417a85fe12eSEd Maste putchar(c); 418a85fe12eSEd Maste continue; 419a85fe12eSEd Maste } 420a85fe12eSEd Maste if (!PRINTABLE(c) || c == EOF) 421a85fe12eSEd Maste break; 422a85fe12eSEd Maste putchar(c); 423a85fe12eSEd Maste } 424a85fe12eSEd Maste putchar('\n'); 425a85fe12eSEd Maste } 426a85fe12eSEd Maste } 427a85fe12eSEd Maste _exit1: 428a85fe12eSEd Maste free(obuf); 429a85fe12eSEd Maste return (RETURN_OK); 430a85fe12eSEd Maste } 431a85fe12eSEd Maste 432a85fe12eSEd Maste #define USAGE_MESSAGE "\ 433a85fe12eSEd Maste Usage: %s [options] [file...]\n\ 434a85fe12eSEd Maste Print contiguous sequences of printable characters.\n\n\ 435a85fe12eSEd Maste Options:\n\ 436a85fe12eSEd Maste -a | --all Scan the entire file for strings.\n\ 437a85fe12eSEd Maste -e ENC | --encoding=ENC Select the character encoding to use.\n\ 438a85fe12eSEd Maste -f | --print-file-name Print the file name before each string.\n\ 439a85fe12eSEd Maste -h | --help Print a help message and exit.\n\ 440a85fe12eSEd Maste -n N | --bytes=N | -N Print sequences with 'N' or more characters.\n\ 441a85fe12eSEd Maste -o Print offsets in octal.\n\ 442a85fe12eSEd Maste -t R | --radix=R Print offsets using the radix named by 'R'.\n\ 443a85fe12eSEd Maste -v | --version Print a version identifier and exit.\n" 444a85fe12eSEd Maste 445a85fe12eSEd Maste void 446a85fe12eSEd Maste usage(void) 447a85fe12eSEd Maste { 448a85fe12eSEd Maste (void) fprintf(stderr, USAGE_MESSAGE, ELFTC_GETPROGNAME()); 449a85fe12eSEd Maste exit(EXIT_FAILURE); 450a85fe12eSEd Maste } 451a85fe12eSEd Maste 452a85fe12eSEd Maste void 453a85fe12eSEd Maste show_version(void) 454a85fe12eSEd Maste { 455a85fe12eSEd Maste (void) printf("%s (%s)\n", ELFTC_GETPROGNAME(), elftc_version()); 456a85fe12eSEd Maste exit(EXIT_SUCCESS); 457a85fe12eSEd Maste } 458