koreth@panarthea.ebay.sun.com (Steven Grimm) (10/11/89)
Submitted-by: uunet!unido!infbs!tubsibr!hafer (Udo Hafermann) Posting-number: Volume 2, Issue 89 Archive-name: strings [This arrived packaged with the "yaff" program. -sg] #!/bin/sh # shar: Shell Archiver (v1.22) # # Run the following text with /bin/sh to create: # DEBUG.H # GETOPT.C # GETOPT.H # MAKEFILE # STRINGS.C # STRINGS.MAN # sed 's/^X//' << 'SHAR_EOF' > DEBUG.H && X/* X * debug.h - debugging macros X * X */ X X/* X * dd(value, format) creates a printf-statement which dumps X * the given value in the specified format. X */ X X#if NDEBUG X#define DD(value, format) X#else X#define DD(value, format) printf("[" __FILE__ "(%d): " #value "=" #format "]\n", __LINE__, value); X#endif X X/* End of debug.h */ SHAR_EOF chmod 0600 DEBUG.H || echo "restore of DEBUG.H fails" sed 's/^X//' << 'SHAR_EOF' > GETOPT.C && X/* X** Return options and their values from the command line. X** X** This comes from the AT&T public-domain getopt published in mod.sources. X*/ X X/* adapted for MWC by hafer@infbs X*/ X X#include <stdio.h> X X#define TYPE int X X#define ERR(s, c) if(opterr){fprintf(stderr, "%s%s%c\n", argv[0], s, c);} X Xextern int strcmp(); Xextern char *index(); X X/* external vars */ X Xint opterr = 1; /* if reset to 0, getopt is silent on errors */ Xint optind = 1; /* argument number of current option */ Xint optopt; /* current option character */ Xchar *optarg; /* pointer to extra argument of current option */ X Xint Xgetopt(argc, argv, opts) Xint argc; Xchar **argv, *opts; X{ X static int sp = 1; X register int c; X register char *cp; X X if(sp == 1) X if(optind >= argc || X argv[optind][0] != '-' || argv[optind][1] == '\0') X return(EOF); X else if(strcmp(argv[optind], "--") == 0) { X optind++; X X } X optopt = c = argv[optind][sp]; X if(c == ':' || (cp=index(opts, c)) == NULL) { X ERR(": illegal option -- ", c) X if(argv[optind][++sp] == '\0') { X optind++; X sp = 1; X } X return('?'); X } X if(*++cp == ':') { X if(argv[optind][sp+1] != '\0') X optarg = &argv[optind++][sp+1]; X else if(++optind >= argc) { X ERR(": option requires an argument -- ", c) X sp = 1; X return('?'); X } else X optarg = argv[optind++]; X sp = 1; X } else { X if(argv[optind][++sp] == '\0') { X sp = 1; X optind++; X } X optarg = NULL; X } X return(c); X} X X SHAR_EOF chmod 0600 GETOPT.C || echo "restore of GETOPT.C fails" sed 's/^X//' << 'SHAR_EOF' > GETOPT.H && X X/* X * getopt.h - declarations for using getopt (needs <stdio.h>) X */ X Xextern int opterr; /* if reset to 0, getopt is silent on errors */ Xextern int optind; /* argument number following current option */ Xextern int optopt; /* current option character */ Xextern char *optarg;/* pointer to extra argument of current option */ X Xextern int getopt(/* int argc, char **argv, char *opts */); X /* for each call, returns next option letter or EOF. */ X /* opts is a list of permissible option letters, where a letter X may be followed by a colon to indicate an expected parameter */ SHAR_EOF chmod 0600 GETOPT.H || echo "restore of GETOPT.H fails" sed 's/^X//' << 'SHAR_EOF' > MAKEFILE && X XPROGRAM= strings.ttp XOBJ= strings.o getopt.o X XCFLAGS=-DNDEBUG XLDFLAGS = -s X X$(PROGRAM): $(OBJ) X cc -o $(PROGRAM) $(OBJ) X Xstrings.o: strings.c debug.h getopt.h X Xgetopt.o: getopt.c getopt.h X X X SHAR_EOF chmod 0600 MAKEFILE || echo "restore of MAKEFILE fails" sed 's/^X//' << 'SHAR_EOF' > STRINGS.C && X X/* X * strings.c - extract strings from binary file X * hafer@infbs 06-AUG-89 X */ X X#include <stdio.h> X#include "debug.h" X#include "getopt.h" X Xextern char *index(); X X#define BUFLEN 1024 X#define MINDEFAULT 4 X Xtypedef struct { X int magic; X long text; X long data; X long bss; X long symtab; X long reserved1, reserved2; X int flags; X} header; X Xstatic char buffer[BUFLEN]; Xstatic int bufcnt, X aflag, X lflag, X pflag, X nflag, X vflag, X minlen = MINDEFAULT; Xstatic char *options = "adoxlnuvm:c:", X *whoami = "strings", X *format = "%8ld ", X extrachars[BUFLEN], X *umlaute = "\204\224\201\216\231\232\236", /* "" */ X *filename; Xstatic long pos, X length, X offset; X Xstatic void addchar(ch) Xint ch; X{ X /* adds a char to buffer */ X if (bufcnt < BUFLEN-1) { X buffer[bufcnt++] = ch; X } X} X Xstatic void printbuf() X{ X /* prints buffer */ X buffer[bufcnt] = '\0'; X if (bufcnt >= minlen) { X if (pflag) X printf (format, pos+offset); X if (lflag) X printf ("%s\n", buffer); X else X printf ("\"%s\"\n", buffer); X } X bufcnt = 0; X} X Xstatic void usage() X{ X fprintf (stderr, "Usage: %s [-%s] <filename>\n", whoami, options); X exit (-1); X} X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X int ch; X FILE *fp; X header h; X X if (*argv[0]) X whoami = argv[0]; X opterr = 0; X while (EOF != getopt(argc, argv, options)) { X if (optopt == 'a') { X aflag = -1; X } else if (optopt == 'l') { X lflag = -1; X } else if (optopt == 'x') { X pflag = -1; X format = "%8lx "; X } else if (optopt == 'o') { X pflag = -1; X format = "%8lo "; X } else if (optopt == 'd') { X pflag = -1; X } else if (optopt == 'n') { X nflag = -1; X } else if (optopt == 'v') { X vflag = -1; X } else if (optopt == 'c') { X strcat (extrachars, optarg); X } else if (optopt == 'u') { X strcat (extrachars, umlaute); X } else if (optopt == 'm') { X minlen = atoi (optarg); X if (minlen == 0) X minlen = MINDEFAULT; X } else { X usage(); X } X } X /* check whether there is exactly one argument left: */ X if (argc-optind != 1) { X usage(); X } X filename = argv[optind]; X if (!(fp = fopen(filename, "rb"))) { X fprintf (stderr, "%s: cannot open file '%s'\n", X whoami, filename); X exit (-33); X } X X if (aflag) { X offset = 0; X length = -1; X } else { X if (!fread(&h, sizeof(h), 1, fp) || h.magic != 0x601a) { X fprintf (stderr, "%s: unknown format: '%s'\n", X whoami, filename); X exit (-1); X } X if (vflag) { X printf (" text data bss symtab\n"); X printf (format, h.text); X printf (format, h.data); X printf (format, h.bss); X printf (format, h.symtab); X printf ("\n"); X } X offset = sizeof(h) + h.text; X length = h.data; XDD(offset, %ld) XDD(length, %ld) X fseek (fp, offset, 0); X } X X /* off we go: */ X for (pos; pos != length; pos++) { X ch = getc(fp); X if (feof(fp)) { X /* this shouldn't happen if the header is valid... */ X fclose (fp); X exit(0); X } else if (ch == '\0' || X (nflag && (ch == '\n' || ch == '\r'))) { X printbuf(); X } else if (ch == '"' || ch == '\\') { X if (lflag) { X addchar(ch); X } else { X addchar('\\'); X addchar(ch); X } X } else if (ch>=' ' && ch<127) { X addchar(ch); X } else if (ch=='\n' || ch=='\t') { X if (lflag) { X addchar(ch); X } else { X addchar('\\'); X addchar((ch=='\n' ? 'n' : 't')); X } X } else if (*extrachars && index(extrachars, ch)) { X addchar(ch); X } else { X bufcnt = 0; X } X } X exit(0); X} SHAR_EOF chmod 0600 STRINGS.C || echo "restore of STRINGS.C fails" sed 's/^X//' << 'SHAR_EOF' > STRINGS.MAN && XSTRINGS(1) USER COMMANDS X X XNAME X strings - extract strings from binary file X XSYNOPSIS X strings [-adoxnv] [-m <number>] [-c chars] filename X XDESCRIPTION X Extracts and prints sequences of printable characters, terminated by X a _z_e_r_o _b_y_t_e, from the _d_a_t_a segment of the specified file, which is X assumed to be a GEMDOS executable. X Strings are listed in C-format, i.e. as they would be accepted X as string constants in C. Strings shorter than 4 characters are X ignored. Printable characters are '\t', '\n', and ASCII 32 to 126. X X Options: X X -a All: Search the _c_o_m_p_l_e_t_e file (regardless of its format). X -d _D_e_c_i_m_a_l: Precede each string with its _p_o_s_i_t_i_o_n in the file. X -o _O_c_t_a_l: Same as -d, only in octal. X -x _H_e_x_a_d_e_c_i_m_a_l: Same as -d, only in hex. X -l Literal: Print strings _l_i_t_e_r_a_l_l_y (i.e., not in C-format). X -n Newline: Accept '\n' and '\r' as string _t_e_r_m_i_n_a_t_o_r_s. X -m <no> _M_i_n_i_m_u_m length: Ignore strings shorter than <no> characters. X -c <ch> _C_h_a_r_a_c_t_e_r_s: Regard the specified chars as _p_r_i_n_t_a_b_l_e. X -u _U_m_l_a_u_t_s: Regard "umlaut" characters as printable (""). X -v _V_e_r_b_o_s_e: List the segment sizes. X XRESTRICTIONS X Printing of strings is limited to the internal buffer size of 1024 X characters. X XBUGS X When printing in C-format, characters greater than 126 are not X escaped by '\\ddd' (only with -c or -u options). X XAUTHOR X hafer@infbs.uucp August 1989 X SHAR_EOF chmod 0600 STRINGS.MAN || echo "restore of STRINGS.MAN fails" exit 0