|
|
1.1 ! root 1: /** ! 2: * strings -- prints out all the character strings in an executable file. ! 3: * ! 4: * Usage: strings [-xaop] [-nnn] [file ...] ! 5: * ! 6: * Options: ! 7: * -x print offset of each string in the file in hex ! 8: * -a print offset of each string in the file in ASCII ! 9: * -o print offset of each string in the file in octal ! 10: * -p mask out the parity bit ! 11: */ ! 12: ! 13: #include <sys/stat.h> ! 14: #include <l.out.h> ! 15: #include <stdio.h> ! 16: #include <canon.h> ! 17: #include <ctype.h> ! 18: ! 19: /* The lamentable <rico.h>... */ ! 20: #define bool char ! 21: #define TRUE (0 == 0) ! 22: #define FALSE (!TRUE) ! 23: ! 24: int nchars = 4; /* minimum character string length */ ! 25: ! 26: bool flag; /* input condition: FALSE for redirection, else TRUE */ ! 27: bool aflag; /* option flags: ascii line numbering */ ! 28: bool xflag; /* hex line numbering */ ! 29: bool oflag; /* octal line numbering */ ! 30: ! 31: int pbit; /* parity bit mask */ ! 32: long addr; /* current seek position in data space segment */ ! 33: long count; /* size of data space segment */ ! 34: char * buff; /* string to store beginning NCHARS ! 35: characters in character string */ ! 36: bool printstr(); ! 37: bool lookfor(); ! 38: ! 39: extern FILE * freopen(); ! 40: extern char * malloc(); ! 41: ! 42: ! 43: main( argc, argv ) ! 44: ! 45: int argc; ! 46: char * argv[]; ! 47: ! 48: { ! 49: char * malloc(); ! 50: char * s; ! 51: ! 52: while( (--argc > 0) && ((*++argv)[0] == '-') ) { ! 53: ! 54: /* ! 55: * Read options declared. ! 56: */ ! 57: for( s = argv[0] + 1 ; *s != '\0'; s++ ) { ! 58: ! 59: /* ! 60: * Set minimum string length for recognizing ! 61: * character strings. ! 62: */ ! 63: if( isdigit( *s ) ) { ! 64: if( (nchars = atoi( s )) <= 0 ) ! 65: fatal( "string length must be greater than 0" ); ! 66: ! 67: break; ! 68: } ! 69: ! 70: /* ! 71: * Set appropriate flags or bit mask according to ! 72: * option declared. ! 73: */ ! 74: switch( *s ) { ! 75: ! 76: case 'x': ! 77: if( aflag | oflag | xflag ) ! 78: usage(); ! 79: ! 80: xflag = TRUE; ! 81: break; ! 82: ! 83: case 'a': ! 84: if( aflag | oflag | xflag ) ! 85: usage(); ! 86: ! 87: aflag = TRUE; ! 88: break; ! 89: ! 90: case 'o': ! 91: if( aflag | oflag | xflag ) ! 92: usage(); ! 93: ! 94: oflag = TRUE; ! 95: break; ! 96: ! 97: case 'p': ! 98: pbit = 0200; ! 99: break; ! 100: ! 101: default: ! 102: usage(); ! 103: } ! 104: } ! 105: } ! 106: ! 107: /* ! 108: * Get memory for string buffer. ! 109: */ ! 110: if( (buff = malloc( nchars )) == NULL ) ! 111: fatal( "not enough memory" ); ! 112: ! 113: /* ! 114: * Set input condition: ! 115: * FALSE if input is through indirection, else TRUE. ! 116: */ ! 117: if( argc > 0 ) ! 118: flag = TRUE; ! 119: else { ! 120: argc++; ! 121: flag = FALSE; ! 122: } ! 123: ! 124: /* ! 125: * Examine each file for strings of the required length. ! 126: */ ! 127: while( argc-- ) { ! 128: ! 129: /* ! 130: * Test for read permission in file. ! 131: */ ! 132: if( flag && freopen( *argv, "r", stdin ) == NULL ) ! 133: fatal( "can't open %s", argv[0] ); ! 134: ! 135: /* ! 136: * Test if file is an executable file. ! 137: */ ! 138: if( checklout( stdin ) < 0 ) { ! 139: if( flag ) { ! 140: fprintf( stderr, "strings: '%s' not executable\n", *argv); ! 141: ++argv; ! 142: continue; ! 143: } ! 144: else { ! 145: fprintf( stderr, "strings: not executable\n" ); ! 146: exit( 1 ); ! 147: } ! 148: } ! 149: ! 150: /* ! 151: * Display file name if available. ! 152: */ ! 153: if( flag ) ! 154: fprintf( stderr, "%s:\n", *argv ); ! 155: ! 156: /* ! 157: * Display all character strings in file. ! 158: */ ! 159: while( printstr() ) ! 160: ; ! 161: ! 162: ++argv; ! 163: } ! 164: ! 165: free( buff ); ! 166: exit( 0 ); ! 167: } ! 168: ! 169: /** ! 170: * bool ! 171: * printstr() ! 172: * ! 173: * Input: None. ! 174: * ! 175: * Action: Display character strings in file. ! 176: * ! 177: * Return: FALSE on error or no character strings available, ! 178: * otherwise TRUE. ! 179: * ! 180: * Note: None. ! 181: * ! 182: */ ! 183: ! 184: bool ! 185: printstr() ! 186: ! 187: { ! 188: char c; ! 189: char * p; ! 190: char * q; ! 191: ! 192: p = buff; ! 193: q = p + nchars; ! 194: ! 195: /* ! 196: * Check if character strings are available in file. ! 197: */ ! 198: if( ! lookfor() ) ! 199: return( FALSE ); ! 200: ! 201: /* ! 202: * Display line number according to the format option specified. ! 203: * Ignore if no format option is set. ! 204: */ ! 205: if( aflag ) ! 206: printf( "%-6D: ", addr-nchars ); ! 207: ! 208: else if( oflag ) ! 209: printf( "0%-6O: ", addr-nchars ); ! 210: ! 211: else if( xflag ) ! 212: printf( "0x%-6X: ", addr-nchars ); ! 213: ! 214: /* ! 215: * Display printable characters found. ! 216: */ ! 217: do { ! 218: putchar( *p++ ); ! 219: } while( p < q ); ! 220: ! 221: /* ! 222: * Display remaining printable characters in file. ! 223: */ ! 224: for ( ;; ) { ! 225: if( --count <= 0L ) ! 226: return( FALSE ); ! 227: ! 228: ++addr; ! 229: c = getchar(); ! 230: ! 231: if( c == EOF ) ! 232: return( FALSE ); ! 233: ! 234: if( ! (isascii( (c) & ~pbit ) && isprint( (c) & ~pbit )) ) ! 235: break; ! 236: ! 237: putchar( c ); ! 238: } ! 239: ! 240: putchar( '\n' ); ! 241: return( TRUE ); ! 242: } ! 243: ! 244: /** ! 245: * bool ! 246: * lookfor() ! 247: * ! 248: * Input: None. ! 249: * ! 250: * Action: Look for the first character string in file. ! 251: * ! 252: * Return: TRUE if a character string is found, else FALSE. ! 253: * ! 254: * Note: None. ! 255: * ! 256: */ ! 257: ! 258: bool ! 259: lookfor() ! 260: ! 261: { ! 262: char c; ! 263: char * p; ! 264: char * q; ! 265: ! 266: q = buff + nchars; ! 267: ! 268: for( ;; ) { ! 269: ! 270: /* ! 271: * Seek in data space segment of file until a printable ! 272: * character is encountered. ! 273: */ ! 274: do { ! 275: if( --count <= 0L ) ! 276: return( FALSE ); ! 277: ! 278: ++addr; ! 279: c = getchar(); ! 280: ! 281: if( c == EOF ) ! 282: return( FALSE ); ! 283: ! 284: } while( ! (isascii( (c) & ~pbit ) && isprint( (c) & ~pbit )) ); ! 285: ! 286: p = buff; ! 287: ! 288: /* ! 289: * Check for valid character string. ! 290: */ ! 291: do { ! 292: *p++ = c; ! 293: ! 294: if( p >= q ) ! 295: return( TRUE ); ! 296: ! 297: if( --count <= 0L ) ! 298: return( FALSE ); ! 299: ! 300: ++addr; ! 301: c = getchar(); ! 302: ! 303: if( c == EOF ) ! 304: return( FALSE ); ! 305: ! 306: } while( isascii( (c) & ~pbit ) && isprint( (c) & ~pbit ) ); ! 307: } ! 308: } ! 309: ! 310: ! 311: /** ! 312: * int ! 313: * checklout( f ) ! 314: * ! 315: * register FILE * f; ! 316: * ! 317: * Input: f - file pointer to stdin. ! 318: * ! 319: * Action: Check if executable (l.out) file. ! 320: * ! 321: * Return: Returns -1 on error or file is not executable, otherwise 0. ! 322: * ! 323: * Note: None. ! 324: * ! 325: */ ! 326: ! 327: int ! 328: checklout( f ) ! 329: ! 330: register FILE * f; ! 331: ! 332: { ! 333: register int i; /* counter variable */ ! 334: int ret = -1; /* returning error value */ ! 335: struct stat s; /* file attributes */ ! 336: struct ldheader l; /* file header information */ ! 337: ! 338: if( fstat( fileno( f ), &s ) == -1 ) ! 339: return( ret ); ! 340: ! 341: /* ! 342: * File type check. Return unless regular file. ! 343: */ ! 344: if( (s.st_mode & S_IFMT) != S_IFREG ) ! 345: return( ret ); ! 346: ! 347: /* ! 348: * Get file header information. ! 349: */ ! 350: if( fread( &l, sizeof( l ), 1, f ) != 1 ) { ! 351: rewind( f ); ! 352: return( ret ); ! 353: } ! 354: ! 355: rewind( f ); ! 356: ! 357: if( l.l_magic != L_MAGIC ) ! 358: return( ret ); ! 359: ! 360: /* ! 361: * Correct canonical effect on file format information. ! 362: */ ! 363: for( i = 0 ; i < NLSEG ; ++i ) ! 364: canlong(l.l_ssize[i]); ! 365: ! 366: /* ! 367: * Get seek position to the beginning memory location of the ! 368: * data space segment in the executable file. ! 369: */ ! 370: fseek( f, (long)sizeof(l) + l.l_ssize[L_SHRI] + l.l_ssize[L_PRVI], 0 ); ! 371: addr = ftell( f ); ! 372: ! 373: /* ! 374: * Get size of data space segment of file. ! 375: */ ! 376: count = l.l_ssize[L_SHRD] + l.l_ssize[L_PRVD]; ! 377: ! 378: if( count == 0L ) { ! 379: fatal( "zero-length data segments" ); ! 380: /* NOTREACHED */ ! 381: } ! 382: ! 383: ++count; ! 384: return( 0 ); ! 385: } ! 386: ! 387: /** ! 388: * void ! 389: * fatal( arg0 ) ! 390: * ! 391: * char * arg0; ! 392: * ! 393: * Input: arg0 - pointer to string containing the error message. ! 394: * ! 395: * Action: Display fatal error message and exit. ! 396: * ! 397: * Return: Never return, always exit. ! 398: * ! 399: * Note: None. ! 400: * ! 401: */ ! 402: ! 403: fatal( arg0 ) ! 404: ! 405: char * arg0; ! 406: ! 407: { ! 408: fflush( stdout ); ! 409: fprintf( stderr, "strings: %r\n", &arg0 ); ! 410: exit( 1 ); ! 411: } ! 412: ! 413: /** ! 414: * void ! 415: * usage() ! 416: * ! 417: * Input: None. ! 418: * ! 419: * Action: Display command usage format. ! 420: * ! 421: * Return: Never return, always exit. ! 422: * ! 423: * Note: None. ! 424: * ! 425: */ ! 426: ! 427: usage() ! 428: ! 429: { ! 430: fprintf( stderr, "Usage: strings [-xaop] [-nnn] [file ...]\n" ); ! 431: exit( 1 ); ! 432: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.