libstand: gzipfs unused variable
[unleashed.git] / usr / src / cmd / strings / strings.c
blob64f5ea65883e43b6f401cb93ce50d3a6292e8d2a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T
28 * All Rights Reserved
32 * Copyright (c) 1987, 1988 Microsoft Corporation
33 * All Rights Reserved
37 * Copyright (c) 1979 Regents of the University of California
40 #pragma ident "%Z%%M% %I% %E% SMI"
42 #include <stdio.h>
43 #include "a.out.h"
44 #include <ctype.h>
45 #include <wchar.h>
46 #include <wctype.h>
47 #include <libelf.h>
48 #include <sys/elf.h>
49 #include <locale.h>
50 #include <string.h>
51 #include <stdlib.h>
52 #include <sys/types.h>
53 #include <unistd.h>
54 #include <limits.h>
55 #include <widec.h>
56 #include <gelf.h>
57 #include <errno.h>
60 #define NOTOUT 0
61 #define AOUT 1
62 #define ELF 4
64 struct aexec ahdr;
66 /* used to maintain a list of program sections to look in */
67 typedef struct sec_name {
68 char *name;
69 struct sec_name *next;
70 } sec_name_t;
73 * function prototypes
75 static void Usage();
76 static void find(long);
77 static int ismagic(int, struct aexec *, FILE *);
78 static int tryelf(FILE *);
79 static int dirt(int, int);
83 * Strings - extract strings from an object file for whatever
85 * The algorithm is to look for sequences of "non-junk" characters
86 * The variable "minlen" is the minimum length string printed.
87 * This helps get rid of garbage.
88 * Default minimum string length is 4 characters.
92 #define DEF_MIN_STRING 4
94 static int tflg;
95 static char t_format;
96 static int aflg;
97 static int minlength = 0;
98 static int isClocale = 0;
99 static char *buf = NULL;
100 static char *tbuf = NULL;
101 static size_t buf_size = 0;
102 static int rc = 0; /* exit code */
105 * Returns 0 when sections have been successfully looked through,
106 * otherwise returns 1.
108 static int
109 look_in_sections(char *file, sec_name_t *seclistptr)
111 int fd = fileno(stdin);
112 int found_sec;
113 int rc = 0;
114 Elf *elf;
115 GElf_Ehdr ehdr;
116 Elf_Scn *scn;
117 GElf_Shdr shdr;
119 (void) lseek(fd, 0L, 0);
120 elf = elf_begin(fd, ELF_C_READ, NULL);
121 if (gelf_getehdr(elf, &ehdr) == (GElf_Ehdr *)NULL) {
122 (void) fprintf(stderr, "%s: %s\n", file, elf_errmsg(-1));
123 (void) elf_end(elf);
124 return (1);
126 scn = 0;
127 while ((scn = elf_nextscn(elf, scn)) != 0) {
128 found_sec = 0;
129 if (gelf_getshdr(scn, &shdr) == (GElf_Shdr *)0) {
130 (void) fprintf(stderr, "%s: %s\n", file,
131 elf_errmsg(-1));
132 rc = 1;
133 continue;
136 if (seclistptr != NULL) {
137 char *scn_name;
139 /* Only look in the specified section(s). */
140 if ((scn_name = elf_strptr(elf, ehdr.e_shstrndx,
141 (size_t)shdr.sh_name)) == NULL) {
142 (void) fprintf(stderr, "%s: %s\n", file,
143 elf_errmsg(-1));
144 rc = 1;
145 continue;
146 } else {
147 sec_name_t *sptr;
149 for (sptr = seclistptr; sptr != NULL;
150 sptr = sptr->next) {
151 if (strcmp(scn_name, sptr->name) == 0) {
152 found_sec = 1;
153 break;
157 } else {
159 * Look through program sections that are
160 * loaded in memory.
162 if ((shdr.sh_flags & SHF_ALLOC) &&
163 (shdr.sh_type == SHT_PROGBITS)) {
164 found_sec = 1;
167 if (found_sec == 1) {
168 (void) fseek(stdin, (long)shdr.sh_offset, 0);
169 find((long)shdr.sh_size);
172 return (rc);
176 main(argc, argv)
177 int argc;
178 char *argv[];
180 int hsize;
181 int htype;
182 char *locale;
183 int opt;
184 int i;
185 sec_name_t *seclistptr = NULL;
186 sec_name_t *seclistendptr;
187 sec_name_t *sptr;
189 (void) setlocale(LC_ALL, "");
191 #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */
192 #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */
193 #endif
194 (void) textdomain(TEXT_DOMAIN);
196 locale = setlocale(LC_CTYPE, NULL);
197 if ((strcmp(locale, "C") == 0) ||
198 (strcmp(locale, "POSIX") == 0)) {
199 isClocale = 1;
202 /* check for non-standard "-" option */
203 for (i = 1; i < argc; i++) {
204 if (strcmp(argv[i], "-") == 0) {
205 aflg++;
206 while (i < argc) {
207 argv[i] = argv[i+1];
208 i++;
210 argc--;
214 /* get options */
215 while ((opt = getopt(argc, argv, "1234567890an:N:ot:")) != -1) {
216 switch (opt) {
217 case 'a':
218 aflg++;
219 break;
221 case 'n':
222 minlength = (int)strtol(optarg, (char **)NULL,
223 10);
224 break;
226 case 'N':
227 if (((sptr = malloc(sizeof (sec_name_t)))
228 == NULL) || ((sptr->name = strdup(optarg))
229 == NULL)) {
230 (void) fprintf(stderr, gettext(
231 "Cannot allocate memory: "
232 "%s\n"), strerror(errno));
233 exit(1);
235 if (seclistptr == NULL) {
236 seclistptr = sptr;
237 seclistptr->next = NULL;
238 seclistendptr = sptr;
239 } else {
240 seclistendptr->next = sptr;
241 seclistendptr = sptr;
243 break;
245 case 'o':
246 tflg++;
247 t_format = 'd';
248 break;
250 case 't':
251 tflg++;
252 t_format = *optarg;
253 if (t_format != 'd' && t_format != 'o' &&
254 t_format != 'x')
256 (void) fprintf(stderr,
257 gettext("Invalid format\n"));
258 Usage();
260 break;
261 case '0':
262 case '1':
263 case '2':
264 case '3':
265 case '4':
266 case '5':
267 case '6':
268 case '7':
269 case '8':
270 case '9':
271 minlength *= 10;
272 minlength += opt - '0';
273 break;
275 default:
276 Usage();
280 /* if min string not specified, use default */
281 if (!minlength)
282 minlength = DEF_MIN_STRING;
285 /* dynamic allocation of char buffer array */
286 buf = (char *)malloc(BUFSIZ);
287 if (buf == NULL) {
288 (void) fprintf(stderr, gettext("Cannot allocate memory: %s\n"),
289 strerror(errno));
290 exit(1);
292 buf_size = BUFSIZ;
293 tbuf = buf;
296 /* for each file operand */
297 do {
298 if (argv[optind] != NULL) {
299 if (freopen(argv[optind], "r", stdin) == NULL) {
300 perror(argv[optind]);
301 rc = 1;
302 optind++;
303 continue;
305 optind++;
306 } else
307 aflg++;
309 if (aflg)
310 htype = NOTOUT;
311 else {
312 hsize = fread((char *)&ahdr, sizeof (char),
313 sizeof (ahdr), stdin);
314 htype = ismagic(hsize, &ahdr, stdin);
316 switch (htype) {
317 case AOUT:
318 (void) fseek(stdin, (long)ADATAPOS(&ahdr), 0);
319 find((long)ahdr.xa_data);
320 continue;
322 case ELF:
324 * Will take care of COFF M32 and i386 also
325 * As well as ELF M32, i386 and Sparc (32-
326 * and 64-bit)
328 rc = look_in_sections(argv[optind - 1],
329 seclistptr);
330 continue;
332 case NOTOUT:
333 default:
334 if (!aflg)
335 (void) fseek(stdin, (long)0, 0);
336 find(LONG_MAX);
337 continue;
339 } while (argv[optind] != NULL);
341 return (rc);
344 static void
345 find(cnt)
346 long cnt;
348 int c;
349 int cc;
350 int cr;
352 cc = 0;
353 for (c = ~EOF; (cnt > 0) && (c != EOF); cnt--) {
354 c = getc(stdin);
355 if (!(cr = dirt(c, cc))) {
356 if (cc >= minlength) {
357 if (tflg) {
358 switch (t_format) {
359 case 'd':
360 (void) printf("%7ld ",
361 ftell(stdin) - cc - 1);
362 break;
364 case 'o':
365 (void) printf("%7lo ",
366 ftell(stdin) - cc - 1);
367 break;
369 case 'x':
370 (void) printf("%7lx ",
371 ftell(stdin) - cc - 1);
372 break;
376 if (cc >= buf_size)
377 buf[buf_size-1] = '\0';
378 else
379 buf[cc] = '\0';
380 (void) puts(buf);
382 cc = 0;
384 cc += cr;
388 static int
389 dirt(c, cc)
390 int c;
391 int cc;
393 char mbuf[MB_LEN_MAX + 1];
394 int len, len1, i;
395 wchar_t wc;
396 int r_val;
398 if (isascii(c)) {
399 if (isprint(c)) {
401 * If character count is greater than dynamic
402 * char buffer size, then increase char buffer size.
404 if (cc >= (buf_size-2)) {
405 if (tbuf != NULL) {
406 buf_size += BUFSIZ;
407 tbuf = (char *)realloc(buf, buf_size);
408 if (tbuf == NULL) {
409 (void) fprintf(stderr,
410 gettext("Cannot allocate memory: %s\n"),
411 strerror(errno));
412 buf_size -= BUFSIZ;
413 rc = 1;
414 return (0);
415 } else {
416 buf = tbuf;
418 } else {
419 return (0);
422 buf[cc] = c;
423 return (1);
425 return (0);
428 if (isClocale)
429 return (0);
431 r_val = 0;
432 mbuf[0] = c;
433 for (len = 1; len < (unsigned int)MB_CUR_MAX; len++) {
434 if ((signed char)
435 (mbuf[len] = getc(stdin)) == -1)
436 break;
438 mbuf[len] = 0;
440 if ((len1 = mbtowc(&wc, mbuf, len)) <= 0) {
441 len1 = 1;
442 goto _unget;
445 if (iswprint(wc)) {
446 if ((cc + len1) >= (buf_size-2)) {
447 if (tbuf != NULL) {
448 buf_size += BUFSIZ;
449 tbuf = (char *)realloc(buf, buf_size);
450 if (tbuf == NULL) {
451 (void) fprintf(stderr,
452 gettext("Cannot allocate memory: %s\n"),
453 strerror(errno));
454 buf_size -= BUFSIZ;
455 rc = 1;
456 return (0);
458 buf = tbuf;
459 } else {
460 return (0);
463 for (i = 0; i < len1; i++, cc++)
464 buf[cc] = mbuf[i];
465 r_val = len1;
468 _unget:
469 for (len--; len >= len1; len--)
470 (void) ungetc(mbuf[len], stdin);
471 return (r_val);
475 static int
476 ismagic(hsize, hdr, fp)
477 int hsize;
478 struct aexec *hdr;
479 FILE *fp;
481 switch (hdr->xa_magic) {
482 case A_MAGIC1:
483 case A_MAGIC2:
484 case A_MAGIC3:
485 case A_MAGIC4:
486 if (hsize < sizeof (struct aexec))
487 return (NOTOUT);
488 else
489 return (AOUT);
490 default:
491 break;
493 return (tryelf(fp));
497 static int
498 tryelf(fp)
499 FILE *fp;
501 int fd;
502 Elf *elf;
503 GElf_Ehdr ehdr;
505 fd = fileno(fp);
507 if ((elf_version(EV_CURRENT)) == EV_NONE) {
508 (void) fprintf(stderr, "%s\n", elf_errmsg(-1));
509 return (NOTOUT);
512 (void) lseek(fd, 0L, 0);
514 if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
515 (void) fprintf(stderr, "%s\n", elf_errmsg(-1));
516 return (NOTOUT);
519 switch (elf_kind(elf)) {
520 case ELF_K_AR:
522 * This should try to run strings on each element
523 * of the archive. For now, just search entire
524 * file (-a), as strings has always done
525 * for archives.
527 case ELF_K_NONE:
528 (void) elf_end(elf);
529 return (NOTOUT);
532 if (gelf_getehdr(elf, &ehdr) == (GElf_Ehdr *)NULL) {
533 (void) fprintf(stderr, "%s\n", elf_errmsg(-1));
534 (void) elf_end(elf);
535 return (NOTOUT);
538 if ((ehdr.e_type == ET_CORE) || (ehdr.e_type == ET_NONE)) {
539 (void) elf_end(elf);
540 return (NOTOUT);
543 (void) elf_end(elf);
545 return (ELF);
550 static void
551 Usage()
553 (void) fprintf(stderr, gettext(
554 "Usage: strings [-a | -] [-t format | -o] [-n number | -number]"
555 "\n\t[-N name] [file]...\n"));
556 exit(1);