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