home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume12 / strings.coff / strings.c < prev   
Encoding:
C/C++ Source or Header  |  1987-10-25  |  7.7 KB  |  210 lines

  1. /*========================================================================*
  2.  * STRINGS(8) -- Find strings in COFF files                               *
  3.  *                                                                        *
  4.  * Copyright (c) 1987                                                     *
  5.  * Tom Reynolds                                                           *
  6.  * Phoenix microsystems, inc.                                             *
  7.  * 991 Discovery Drive                                                    *
  8.  * Huntsville, AL 35807                                                   *
  9.  *                                                                        *
  10.  * Permission granted to publish in source and object form.               *
  11.  * Publication must retain all copyright notices.                         *
  12.  * Object-only distribution permitted only if source is also              *
  13.  * available from distributor.                                            *
  14.  * Fees are limited to cost-of-media charges.                             *
  15.  *                                                                        *
  16.  *========================================================================*/
  17.  
  18. #include <stdio.h>
  19. #include <filehdr.h>
  20. #include <scnhdr.h>
  21. #include <ldfcn.h>
  22. #include <varargs.h>
  23. #include <ctype.h>
  24.  
  25. #define OPTIONS    "an:o"            /* GETOPT(3C) Option string */
  26.  
  27. char *copyright = 
  28. "Copyright (c) 1987 by Tom Reynolds, Phoenix microsystems, inc. Huntsville AL";
  29.  
  30. extern char
  31.    *optarg;                /* GETOPT(3C): Current argument */
  32.  
  33. extern int
  34.    getopt(),                /* GETOPT(3C): Declaration */
  35.    optind;                /* GETOPT(3C): argv[0] index */
  36.  
  37. extern long 
  38.    ftell();                /* FTELL() calls this */
  39.  
  40. char
  41.    *fn,                    /* Current file name being processed */
  42.    *me,                    /* Process name (from argv[0]) */
  43.    *options = OPTIONS;            /* Command line option string */
  44.  
  45. int
  46.    length = 4,                /* Need this many to make string */
  47.    multi = 0;                /* True if more than 1 input file */
  48.    offset = 0;                /* True if file offset wanted */
  49.  
  50. long
  51.    types = STYP_DATA;            /* Section types to search */
  52.  
  53. LDFILE
  54.    *ldptr;                /* COFF File pointer */
  55.  
  56. /*========================================================================*
  57.  * error: Write fatal error text and exit                                 *
  58.  *========================================================================*/
  59.  
  60. /*VARARGS*/
  61. void
  62. error( va_alist )
  63. va_dcl
  64. {
  65.    va_list args;            /* Argument list keeper */
  66.    char *fmt;                /* Printf()-like format address */
  67.    va_start( args );            /* Init the varargs mechanism */
  68.    fmt = va_arg( args, char * );    /* Pick off format */
  69.    (void) fprintf( stderr, "%s: ", me );/* Write our process name */
  70.    (void) vfprintf( stderr, fmt, args );/* Write message text */
  71.    (void) fputc( '\n', stderr );    /* Terminate the line */
  72.    va_end( args );            /* Clean up stack */
  73.    exit( 1 );                /* Back to real world */
  74. }
  75. /*ARGSUSED*/
  76.  
  77. /*========================================================================*
  78.  * usage: Tell how to use us                                              *
  79.  *========================================================================*/
  80.  
  81. void
  82. usage( s )
  83. char *s;                /* Optional error text */
  84. {
  85.    if( s != (char *) NULL ) (void) fprintf( stderr, "%s: %s\n", me, s );
  86.    (void) fprintf( stderr, "usage: %s [-a] [-n #] [-o] file...\n", me );
  87.    (void) exit( 1 );
  88. }
  89.  
  90. /*========================================================================*
  91.  * strings: Find and output all strings in this section of file           *
  92.  *========================================================================*/
  93.  
  94. void
  95. strings( cnt )
  96. long cnt;                /* Bytes in this section */
  97. {
  98.    register int c;            /* Character we're considering */
  99.    char buf[ BUFSIZ+1 ];        /* Holding area for string */
  100.    register char *bp;            /* Walks down buf[] */
  101.    register char *eob = buf+BUFSIZ;    /* End of buffer */
  102.    int n;                /* Length of our string in buf[] */
  103.    for( bp = buf; cnt != 0L; cnt-- ) {
  104.       c = GETC( ldptr );        /* Get a character */
  105.       if( c == -1 ) break;        /* Get out if end of file */
  106.       if( isprint( c ) ) {
  107.      /* Found a printable character */
  108.      if( bp != eob ) *bp++ = c;
  109.       } else if( (c == '\0') || (c == '\n') ) {
  110.      /* Found a proper terminator, so have string if long enough */
  111.      n = bp - buf;            /* How long is it? */
  112.      if( n >= length ) {
  113.         /* String passes */
  114.         *bp = '\0';            /* End the string */
  115.         if( multi ) (void) printf( "%s\t", fn );
  116.         if( offset ) 
  117.            (void) printf( "%#lo\t", FTELL( ldptr ) - (long) n - 1L );
  118.         (void) printf( "%s\n", buf ); /* Show it */
  119.      }
  120.      bp = buf;            /* Start string over again */
  121.       } else bp = buf;            /* Strings doesn't end right */
  122.    }
  123. }
  124.  
  125. /*========================================================================*
  126.  * process: Find strings in a single COFF object                          *
  127.  *========================================================================*/
  128.  
  129. void
  130. process()
  131. {
  132.    if( ISCOFF( TYPE( ldptr ) ) ) {
  133.       unsigned short section;        /* Which section we're working on */
  134.       struct scnhdr hdr;        /* Section header storage */
  135.       long here;            /* Progress into file so far */
  136.       if( FSEEK( ldptr, (long) HEADER( ldptr ).f_opthdr, 0 ) == -1 )
  137.      error( "Could not skip optional header in file \"%s\"", fn );
  138.       here = FTELL( ldptr ) + 
  139.      (sizeof( struct scnhdr ) * HEADER( ldptr ).f_nscns);
  140.       for( section = 1; section <= HEADER( ldptr ).f_nscns; section++ ) {
  141.      if( ldshread( ldptr, section, &hdr ) == FAILURE )
  142.         error( "Could not read section %d's section header in file \"%s\"",
  143.            section, fn );
  144.      if( FSEEK( ldptr, here, 0 ) == -1 ) {
  145.         error( "Could not seek to data segment %d in file \"%s\"", 
  146.            section, fn );
  147.      }
  148.      if( hdr.s_flags & types )
  149.         strings( hdr.s_size );    /* Find the strings */
  150.      else if( FSEEK( ldptr, hdr.s_size, 0 ) == -1 ) {
  151.         error( "Could not step over section %d's data area in file \"%s\"",
  152.            section, fn );
  153.      }
  154.      here = FTELL( ldptr );        /* Remember data for next section */
  155.       }
  156.    } else {
  157.       /* Not a COFF file, so do the best we can */
  158.       if( FSEEK( ldptr, 0L, 0 ) == -1 )
  159.      error( "Could not seek beginning of file \"%s\"", fn );
  160.       strings( -1L );
  161.    }
  162. }
  163.  
  164. /*========================================================================*
  165.  * main: Central Control Logic                                            *
  166.  *========================================================================*/
  167.  
  168. int
  169. main( argc, argv )
  170. int argc;                /* Number of arguments */
  171. char **argv;                /* Command line arguments */
  172. {
  173.    int c;                /* Command line option character */
  174.    int errflag = 0;            /* Command line error flag */
  175.    me = argv[ 0 ];            /* Save our process name */
  176.    while( (c = getopt( argc, argv, options )) != EOF ) {
  177.       switch( c ) {
  178.      default:  fprintf( stderr, "%s: No -%c yet!\n", me, c ); /*FALLTHRU*/
  179.      case '?': errflag++; break;
  180.      case 'a': types |= STYP_TEXT; break;
  181.      case 'n': length = atoi( optarg ); break;
  182.      case 'o': offset = 1; break;
  183.       }
  184.    }
  185.    if( errflag >  0      ) usage( "Illegal switches" );
  186.    if( length  <  1      ) usage( "-n spec too short" );
  187.    if( length  >  BUFSIZ ) usage( "-n too long" );
  188.    switch( argc - optind ) {
  189.       case 0: usage( "Need input filenames" );        /* No files! */
  190.       case 1: break;                    /* Only one file */
  191.       default: multi = 1; break;            /* Lotsa files */
  192.    }
  193.    if( optind  >= argc   ) usage( "Need input filenames" );
  194.    while( optind < argc ) {
  195.       /* For every input file */
  196.       fn = optarg = argv[ optind++ ];    /* Get another filename */
  197.       ldptr = (LDFILE *) NULL;        /* Start clean */
  198.       do {
  199.      if( (ldptr = ldopen( fn, ldptr )) != (LDFILE *) NULL ) {
  200.         process();
  201.      } else {
  202.         fprintf( stderr, "%s: Cannot open %s\n", me, fn );
  203.         errflag++;
  204.      }
  205.       } while( ldclose( ldptr ) == FAILURE );
  206.    }
  207.    (void) exit( errflag ? 1 : 0 );
  208.    /* NOTREACHED */
  209. }
  210.