home *** CD-ROM | disk | FTP | other *** search
- /*========================================================================*
- * STRINGS(8) -- Find strings in COFF files *
- * *
- * Copyright (c) 1987 *
- * Tom Reynolds *
- * Phoenix microsystems, inc. *
- * 991 Discovery Drive *
- * Huntsville, AL 35807 *
- * *
- * Permission granted to publish in source and object form. *
- * Publication must retain all copyright notices. *
- * Object-only distribution permitted only if source is also *
- * available from distributor. *
- * Fees are limited to cost-of-media charges. *
- * *
- *========================================================================*/
-
- #include <stdio.h>
- #include <filehdr.h>
- #include <scnhdr.h>
- #include <ldfcn.h>
- #include <varargs.h>
- #include <ctype.h>
-
- #define OPTIONS "an:o" /* GETOPT(3C) Option string */
-
- char *copyright =
- "Copyright (c) 1987 by Tom Reynolds, Phoenix microsystems, inc. Huntsville AL";
-
- extern char
- *optarg; /* GETOPT(3C): Current argument */
-
- extern int
- getopt(), /* GETOPT(3C): Declaration */
- optind; /* GETOPT(3C): argv[0] index */
-
- extern long
- ftell(); /* FTELL() calls this */
-
- char
- *fn, /* Current file name being processed */
- *me, /* Process name (from argv[0]) */
- *options = OPTIONS; /* Command line option string */
-
- int
- length = 4, /* Need this many to make string */
- multi = 0; /* True if more than 1 input file */
- offset = 0; /* True if file offset wanted */
-
- long
- types = STYP_DATA; /* Section types to search */
-
- LDFILE
- *ldptr; /* COFF File pointer */
-
- /*========================================================================*
- * error: Write fatal error text and exit *
- *========================================================================*/
-
- /*VARARGS*/
- void
- error( va_alist )
- va_dcl
- {
- va_list args; /* Argument list keeper */
- char *fmt; /* Printf()-like format address */
- va_start( args ); /* Init the varargs mechanism */
- fmt = va_arg( args, char * ); /* Pick off format */
- (void) fprintf( stderr, "%s: ", me );/* Write our process name */
- (void) vfprintf( stderr, fmt, args );/* Write message text */
- (void) fputc( '\n', stderr ); /* Terminate the line */
- va_end( args ); /* Clean up stack */
- exit( 1 ); /* Back to real world */
- }
- /*ARGSUSED*/
-
- /*========================================================================*
- * usage: Tell how to use us *
- *========================================================================*/
-
- void
- usage( s )
- char *s; /* Optional error text */
- {
- if( s != (char *) NULL ) (void) fprintf( stderr, "%s: %s\n", me, s );
- (void) fprintf( stderr, "usage: %s [-a] [-n #] [-o] file...\n", me );
- (void) exit( 1 );
- }
-
- /*========================================================================*
- * strings: Find and output all strings in this section of file *
- *========================================================================*/
-
- void
- strings( cnt )
- long cnt; /* Bytes in this section */
- {
- register int c; /* Character we're considering */
- char buf[ BUFSIZ+1 ]; /* Holding area for string */
- register char *bp; /* Walks down buf[] */
- register char *eob = buf+BUFSIZ; /* End of buffer */
- int n; /* Length of our string in buf[] */
- for( bp = buf; cnt != 0L; cnt-- ) {
- c = GETC( ldptr ); /* Get a character */
- if( c == -1 ) break; /* Get out if end of file */
- if( isprint( c ) ) {
- /* Found a printable character */
- if( bp != eob ) *bp++ = c;
- } else if( (c == '\0') || (c == '\n') ) {
- /* Found a proper terminator, so have string if long enough */
- n = bp - buf; /* How long is it? */
- if( n >= length ) {
- /* String passes */
- *bp = '\0'; /* End the string */
- if( multi ) (void) printf( "%s\t", fn );
- if( offset )
- (void) printf( "%#lo\t", FTELL( ldptr ) - (long) n - 1L );
- (void) printf( "%s\n", buf ); /* Show it */
- }
- bp = buf; /* Start string over again */
- } else bp = buf; /* Strings doesn't end right */
- }
- }
-
- /*========================================================================*
- * process: Find strings in a single COFF object *
- *========================================================================*/
-
- void
- process()
- {
- if( ISCOFF( TYPE( ldptr ) ) ) {
- unsigned short section; /* Which section we're working on */
- struct scnhdr hdr; /* Section header storage */
- long here; /* Progress into file so far */
- if( FSEEK( ldptr, (long) HEADER( ldptr ).f_opthdr, 0 ) == -1 )
- error( "Could not skip optional header in file \"%s\"", fn );
- here = FTELL( ldptr ) +
- (sizeof( struct scnhdr ) * HEADER( ldptr ).f_nscns);
- for( section = 1; section <= HEADER( ldptr ).f_nscns; section++ ) {
- if( ldshread( ldptr, section, &hdr ) == FAILURE )
- error( "Could not read section %d's section header in file \"%s\"",
- section, fn );
- if( FSEEK( ldptr, here, 0 ) == -1 ) {
- error( "Could not seek to data segment %d in file \"%s\"",
- section, fn );
- }
- if( hdr.s_flags & types )
- strings( hdr.s_size ); /* Find the strings */
- else if( FSEEK( ldptr, hdr.s_size, 0 ) == -1 ) {
- error( "Could not step over section %d's data area in file \"%s\"",
- section, fn );
- }
- here = FTELL( ldptr ); /* Remember data for next section */
- }
- } else {
- /* Not a COFF file, so do the best we can */
- if( FSEEK( ldptr, 0L, 0 ) == -1 )
- error( "Could not seek beginning of file \"%s\"", fn );
- strings( -1L );
- }
- }
-
- /*========================================================================*
- * main: Central Control Logic *
- *========================================================================*/
-
- int
- main( argc, argv )
- int argc; /* Number of arguments */
- char **argv; /* Command line arguments */
- {
- int c; /* Command line option character */
- int errflag = 0; /* Command line error flag */
- me = argv[ 0 ]; /* Save our process name */
- while( (c = getopt( argc, argv, options )) != EOF ) {
- switch( c ) {
- default: fprintf( stderr, "%s: No -%c yet!\n", me, c ); /*FALLTHRU*/
- case '?': errflag++; break;
- case 'a': types |= STYP_TEXT; break;
- case 'n': length = atoi( optarg ); break;
- case 'o': offset = 1; break;
- }
- }
- if( errflag > 0 ) usage( "Illegal switches" );
- if( length < 1 ) usage( "-n spec too short" );
- if( length > BUFSIZ ) usage( "-n too long" );
- switch( argc - optind ) {
- case 0: usage( "Need input filenames" ); /* No files! */
- case 1: break; /* Only one file */
- default: multi = 1; break; /* Lotsa files */
- }
- if( optind >= argc ) usage( "Need input filenames" );
- while( optind < argc ) {
- /* For every input file */
- fn = optarg = argv[ optind++ ]; /* Get another filename */
- ldptr = (LDFILE *) NULL; /* Start clean */
- do {
- if( (ldptr = ldopen( fn, ldptr )) != (LDFILE *) NULL ) {
- process();
- } else {
- fprintf( stderr, "%s: Cannot open %s\n", me, fn );
- errflag++;
- }
- } while( ldclose( ldptr ) == FAILURE );
- }
- (void) exit( errflag ? 1 : 0 );
- /* NOTREACHED */
- }
-