1
0
Files
irix-657m-src/eoe/cmd/strings/strings.c
2022-09-29 17:59:04 +03:00

545 lines
13 KiB
C

/*
* |-----------------------------------------------------------|
* | Copyright (c) 1991, 1990 MIPS Computer Systems, Inc. |
* | All Rights Reserved |
* |-----------------------------------------------------------|
* | Restricted Rights Legend |
* | Use, duplication, or disclosure by the Government is |
* | subject to restrictions as set forth in |
* | subparagraph (c)(1)(ii) of the Rights in Technical |
* | Data and Computer Software Clause of DFARS 252.227-7013. |
* | MIPS Computer Systems, Inc. |
* | 950 DeGuigne Avenue |
* | Sunnyvale, California 94088-3650, USA |
* |-----------------------------------------------------------|
*/
#ident "$Header: /proj/irix6.5.7m/isms/eoe/cmd/strings/RCS/strings.c,v 1.17 1999/05/11 21:26:20 olson Exp $"
/*
* Copyright (c) 1980 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
*/
#ifndef lint
char copyright[] =
"@(#) Copyright (c) 1980 Regents of the University of California.\n\
All rights reserved.\n";
#endif
#include <sys/types.h>
#include <sys/file.h>
#include <a.out.h>
#include <stdio.h>
#include <ctype.h>
#include <locale.h>
#include <widec.h>
#include <wctype.h>
#include <stdarg.h>
#include <fmtmsg.h>
#include <unistd.h>
#include <sgi_nl.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <msgs/uxsgicore.h>
#include <elf_abi.h>
#define DEF_LEN 4 /* default minimum string length */
#define EOS (char)NULL /* end of string */
#define ERR -1 /* general error */
#define ERREXIT 1 /* error exit */
#define NO 0 /* false/no */
#define OK 0 /* ok exit */
#define YES 1 /* true/yes */
#define DEBUG if (debug) printf
int debug = 0;
int _xpg = 0; /* in xpg compliant mode (strings only if end in
\0, \n, or EOF), if set. See bug 642929 */
typedef struct exec EXEC; /* struct exec cast */
extern const char * setcat(const char *);
extern int setlabel(const char *);
static wchar_t getch(void);
static long foff; /* offset in the file */
static int head_len, /* length of header */
read_len; /* length to read */
void process(void);
static u_char hbfr[FILHSZ+AOUTHSZ]; /* buffer for filehdr, aouthdr */
FILHDR *filhdr = (FILHDR *) hbfr;
AOUTHDR *aouthdr = (AOUTHDR *) &hbfr[FILHSZ];
int minlen = DEF_LEN; /* minimum string length */
short oflg; /* print location in decimal*/
/* with padding*/
/* Flags for xpg4 */
short decflg; /* print decimal location*/
short octflg; /* print octal location */
short hexflg; /* print hex location */
wchar_t ch; /* character */
int cnt; /* general counter */
wchar_t *C; /* bfr pointer */
wchar_t *bfr; /* collection buffer */
static int end;
static char cmd_label[] = "UX:strings";
/*
* some error prints
*/
static void
err_opt(int c)
{
_sgi_nl_error(SGINL_NOSYSERR, cmd_label,
gettxt(_SGI_DMMX_illoption, "illegal option -- %c"),
c);
_sgi_nl_usage(SGINL_USAGE, cmd_label,
gettxt(_SGI_DMMX_usage_strings, "strings [-ao] [-#] [file ... ]"));
}
static void
err_usage(void)
{
_sgi_nl_usage(SGINL_USAGE, cmd_label,
gettxt(_SGI_DMMX_usage_strings, "strings [-ao] [-#] [file ... ]"));
}
static void
err_nomem(void)
{
_sgi_nl_error(SGINL_NOSYSERR, cmd_label,
gettxt(_SGI_DMMX_outofmem, "Out of memory"));
}
static void
err_open(char *s)
{
_sgi_nl_error(SGINL_SYSERR, cmd_label,
gettxt(_SGI_DMMX_CannotOpen, "Cannot open %s"),
s);
}
static void
err_read(char *s)
{
_sgi_nl_error(SGINL_SYSERR, cmd_label,
gettxt(_SGI_DMMX_CannotRead, "Cannot read from %s"),
s);
}
static void
err_seek(char *s)
{
_sgi_nl_error(SGINL_SYSERR, cmd_label,
gettxt(_SGI_DMMX_CannotSeek, "%s: Cannot seek"),
s);
}
/*
* main entry
*/
main(int argc, char **argv)
{
short asdata = NO; /* look in everything */
char *file; /* file name for error */
char *strtab; /* variable for ELF Formats */
int s_num;
off_t foff; /* variable to hold shdr file offset */
int need_num = NO; /* set if next arg needs to be a num */
int need_letter = NO;
char *xpg;
/*
* intnl support
*/
(void)setlocale(LC_ALL, "");
(void)setcat("uxsgicore");
(void)setlabel(cmd_label);
xpg = getenv("_XPG");
_xpg = xpg && atoi(xpg) > 0;
/*
* for backward compatibility, allow '-' to specify 'a' flag; no
* longer documented in the man page or usage string.
*/
for (++argv; (*argv && (*argv)[0] == '-') || (need_num == YES) ||
(need_letter == YES); ++argv) {
if (need_letter == YES) {
cnt = 0;
switch ((*argv)[cnt]) {
case 'd':
decflg = YES;
break;
case 'o':
octflg = YES;
break;
case 'x':
hexflg = YES;
break;
default:
err_opt((*argv)[cnt]);
exit(ERREXIT);
break;
}
need_letter = NO;
continue;
}
if (need_num == YES) {
if (*argv) {
cnt = 0;
if (!isdigit((*argv)[cnt])) {
err_opt((*argv)[cnt]);
exit(ERREXIT);
}
minlen = atoi(*argv);
need_num = NO;
continue;
} else {
err_usage();
exit(ERREXIT);
}
}
if (strcmp(*argv, "--") == 0) {
++argv;
break;
}
for (cnt = 1;(*argv)[cnt];++cnt)
switch ((*argv)[cnt]) {
case 'a':
asdata = YES;
break;
case 'o':
oflg = YES;
break;
case 'd':
debug = YES;
break;
case 't':
need_letter = YES;
break;
case 'n':
if (((*argv)[cnt+1]) == 0) {
need_num = YES;
break;
} else if (isdigit((*argv)[cnt+1]) == 0) {
err_opt((*argv)[cnt+1]);
exit(ERREXIT);
} else {
DEBUG ("argv +2 = %s\n",*argv + 2);
minlen = strtol(*argv + 2, argv, 0);
cnt = -1;
DEBUG("minlen = %d\nargv = %s\n", minlen, *argv);
need_num = NO;
}
break;
default: /* getopt message compatible */
if (!isdigit((*argv)[cnt])) {
err_opt((*argv)[cnt]);
exit(ERREXIT);
}
minlen = atoi(*argv + 1);
break;
}
if (cnt == 1)
asdata = YES;
}
file = "stdin";
do {
if (*argv) {
if (!freopen(*argv,"r",stdin)) {
err_open(*argv);
exit(ERREXIT);
}
file = *argv++;
}
else asdata = YES;
foff = 0;
read_len = ERR;
if (asdata)
process();
else {
/* check for good header */
if ((head_len = read(fileno(stdin),(char *)filhdr,
FILHSZ)) == ERR) {
err_read(file);
exit(ERREXIT);
}
if ISCOFF(filhdr->f_magic) { /* process COFF format */
if ((head_len += read(fileno(stdin),(char *)aouthdr,
AOUTHSZ)) == ERR) {
err_read(file);
exit(ERREXIT);
}
if (head_len == FILHSZ+AOUTHSZ && !N_BADMAG(*aouthdr)){
foff = N_TXTOFF(*filhdr, *aouthdr) + aouthdr->tsize;
if (fseek64(stdin,foff,L_SET) == ERR) {
err_seek(file);
exit(ERREXIT);
}
read_len = aouthdr->dsize;
head_len = 0;
process();
} else {
if (fseek64(stdin, 0LL, 0) == ERR) {
err_seek(file);
perror(file);
exit(ERREXIT);
}
process();
}
} else {
/*
Read header and then check to see if the
file is a 32 or 64bit file.
*/
Elf32_Ehdr ehdr;
fseek64(stdin, 0LL, 0);
if ((head_len = read(fileno(stdin), &ehdr,
sizeof(ehdr))) == ERR) {
err_read(file);
exit(ERREXIT);
}
/* If it is a ELF 32bit format then process */
if (head_len == sizeof(ehdr) && IS_ELF(ehdr) &&
ehdr.e_ident[EI_CLASS] == ELFCLASS32) {
Elf32_Shdr secthdr;
foff = ehdr.e_shoff; /* section hdr tbl offset */
/* get strings table header */
fseek64(stdin, foff+(ehdr.e_shstrndx*ehdr.e_shentsize),0);
if (read(fileno(stdin), &secthdr,sizeof(secthdr)) != sizeof(secthdr)) {
err_read(file);
exit(ERREXIT);
}
/* read string table section */
strtab = malloc(secthdr.sh_size);
fseek64(stdin,secthdr.sh_offset,0);
if (read(fileno(stdin), strtab,secthdr.sh_size) != secthdr.sh_size) {
err_read(file);
exit(ERREXIT);
}
/* for each section in the section header table,
* read the section header and determine the section name.
* process .data, and .rodata sections
*/
for (s_num = 0; s_num < ehdr.e_shnum; s_num = ++s_num) {
fseek64(stdin, foff, 0);
/* read section header */
if (read(fileno(stdin),&secthdr,sizeof(secthdr)) !=
sizeof(secthdr)) {
err_read(file);
exit(1);
}
/* check name of section */
if ((strcmp(strtab+secthdr.sh_name,ELF_DATA) == 0) ||
(strcmp(strtab+secthdr.sh_name,ELF_RODATA) == 0)) {
read_len = (int)secthdr.sh_size;
head_len = 0;
if (fseek64(stdin, secthdr.sh_offset, L_SET) == ERR) {
err_seek(file);
exit(ERREXIT);
} /* if */
process(); /* process section */
} /* if */
/* update pointer to next header */
foff += ehdr.e_shentsize;
} /* for */
} else if (IS_ELF(ehdr) && ehdr.e_ident[EI_CLASS] == ELFCLASS64) {
/* Check if it is a ELF 64bit format */
Elf64_Ehdr ehdr_64;
Elf64_Shdr secthdr_64;
/* Re-read to completely fill the 64bit ELF header */
fseek64(stdin, 0LL, 0);
if ((head_len = read(fileno(stdin), &ehdr_64,
sizeof(ehdr_64))) == ERR) {
err_read(file);
exit(ERREXIT);
}
foff = ehdr_64.e_shoff; /* section hdr tbl offset */
/* get strings table header */
fseek64(stdin, foff+(ehdr_64.e_shstrndx*ehdr_64.e_shentsize),0);
if (read(fileno(stdin), &secthdr_64,sizeof(secthdr_64)) != sizeof(secthdr_64)) {
err_read(file);
exit(ERREXIT);
}
/* read string table section */
strtab = malloc(secthdr_64.sh_size);
fseek64(stdin,secthdr_64.sh_offset,0);
if (read(fileno(stdin), strtab,secthdr_64.sh_size) != secthdr_64.sh_size) {
err_read(file);
exit(ERREXIT);
}
/* for each section in the section header table,
* read the section header and determine the section name.
* process .data, and .rodata sections
*/
for (s_num = 0; s_num < ehdr_64.e_shnum; s_num = ++s_num) {
fseek64(stdin, foff, 0);
/* read section header */
if (read(fileno(stdin),&secthdr_64,sizeof(secthdr_64)) !=
sizeof(secthdr_64)) {
err_read(file);
exit(1);
}
/* check name of section */
if ((strcmp(strtab+secthdr_64.sh_name,ELF_DATA) == 0) ||
(strcmp(strtab+secthdr_64.sh_name,ELF_RODATA) == 0)) {
read_len = secthdr_64.sh_size;
head_len = 0;
if (fseek64(stdin, secthdr_64.sh_offset, L_SET) == ERR) {
err_seek(file);
exit(ERREXIT);
} /* if */
process(); /* process section */
} /* if */
/* update pointer to next header */
foff += ehdr_64.e_shentsize;
} /* for */
} else {
/* If not COFF or ELF, do whole file */
if (fseek64(stdin, 0LL, 0) == ERR) {
err_seek(file);
exit(ERREXIT);
}
process();
} /* if (IS_ELF(ehdr)) */
}
}
} while (*argv);
return(OK);
}
/*
* process --
* find strings in section
*/
void
process(void)
{
register long cnt;
size_t buf_cnt;
long foff_sv;
buf_cnt = ((LINE_MAX > (minlen+1)) ? LINE_MAX : minlen+1);
if (!(bfr = (wchar_t *)malloc((size_t)((buf_cnt)*sizeof(wchar_t))))) {
err_nomem();
exit(ERREXIT);
}
for (cnt = 0, end = 0; !end; ) {
ch = getch();
if (end)
break;
if (iswprint(ch) || ch == L'\t' || (_xpg && ch == L'\n')) {
if (!cnt) {
C = bfr;
foff_sv = foff-1;
}
if( cnt < minlen && (_xpg && (ch == L'\n' || ch == 0))){
cnt = 0;
continue;
}
*C++ = ch;
if (++cnt < minlen)
continue;
/* Satisfied min cnt */
for(;;) {
ch = getch();
if(end) /* Allow end of file to terminate minlen string */
goto output;
if (!iswprint(ch) && ch != L'\t') {
if(_xpg && ch != L'\n' && ch != 0)
break;
else
goto output;
}
if ((cnt+1) > buf_cnt){
if (!(realloc(bfr,(size_t)((buf_cnt+LINE_MAX)*
sizeof(wchar_t))))) {
err_nomem();
exit(ERREXIT);
}
buf_cnt += LINE_MAX;
}
if( ch != L'\n' ){
*C++ = ch;
++cnt;
}
if( ch == 0 || ch == L'\n' ) {
output:
*C = 0;
if (decflg)
printf("%d %S",foff_sv,bfr);
else if (hexflg)
printf("%x %S",foff_sv,bfr);
else if (octflg)
printf("%o %S",foff_sv,bfr);
else if (oflg)
printf("%07ld %S",foff_sv,bfr);
else
fputws(bfr,stdout);
putchar(L'\n');
break;
}
}
}
cnt = 0;
}
}
/*
* getch --
* get next character from wherever
*/
static wchar_t
getch(void)
{
wchar_t wc;
if (read_len != ERR && read_len-- == 0) {
end = 1;
return -1;
}
wc = getwchar();
if (feof(stdin) || ferror(stdin)) {
end = 1;
return -1;
}
foff = ftell(stdin);
return(wc);
}