File:  [MW Coherent from dump] / coherent / d / bin / strings.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/**
 *	strings -- prints out all the character strings in an executable file.
 *
 *	Usage: strings [-xaop] [-nnn] [file ...]
 *
 *	Options:
 *		 -x	print offset of each string in the file in hex
 *		 -a	print offset of each string in the file in ASCII
 *		 -o	print offset of each string in the file in octal
 *		 -p	mask out the parity bit
 */

#include	<sys/stat.h>
#include	<l.out.h>
#include	<stdio.h>
#include	<canon.h>
#include	<ctype.h>

/* The lamentable <rico.h>... */
#define	bool	char
#define	TRUE	(0 == 0)
#define	FALSE	(!TRUE)

int	nchars	= 4;	/* minimum character string length */

bool	flag;		/* input condition: FALSE for redirection, else TRUE */
bool	aflag;		/* option flags:	ascii line numbering */
bool	xflag;		/*			hex   line numbering */
bool	oflag;		/*			octal line numbering */

int	pbit;		/* parity bit mask */
long	addr;		/* current seek position in data space segment */
long	count;		/* size of data space segment */
char  * buff;		/* string to store beginning NCHARS
					characters in character string */
bool	printstr();
bool	lookfor();

extern	FILE	* freopen();
extern	char	* malloc();


main( argc, argv )

int	argc;
char  * argv[];

{
	char	* malloc();
	char	* s;

	while( (--argc > 0) && ((*++argv)[0] == '-') ) {

		/*
		 * Read options declared.
		 */
		for( s = argv[0] + 1 ; *s != '\0'; s++ ) {

			/*
			 * Set minimum string length for recognizing
			 * character strings.
			 */
			if( isdigit( *s ) ) {
				if( (nchars = atoi( s )) <= 0 )
					fatal( "string length must be greater than 0" );

				break;
			}

			/*
			 * Set appropriate flags or bit mask according to
			 * option declared.
			 */
			switch( *s ) {

			case 'x':
				if( aflag | oflag | xflag )
					usage();

				xflag = TRUE;
				break;

			case 'a':
				if( aflag | oflag | xflag )
					usage();

				aflag = TRUE;
				break;

			case 'o':
				if( aflag | oflag | xflag )
					usage();

				oflag = TRUE;
				break;

			case 'p':
				pbit = 0200;
				break;

			default:
				usage();
			}
		}
	}

	/*
	 * Get memory for string buffer.
	 */
	if( (buff = malloc( nchars )) == NULL )
		fatal( "not enough memory" );

	/*
	 * Set input condition:
	 *	FALSE if input is through indirection, else TRUE.
	 */
	if( argc > 0 )
		flag = TRUE;
	else {
		argc++;
		flag = FALSE;
	}

	/*
	 * Examine each file for strings of the required length.
	 */
	while( argc-- ) {

		/*
		 * Test for read permission in file.
		 */
		if( flag  &&  freopen( *argv, "r", stdin ) == NULL )
			fatal( "can't open %s", argv[0] );

		/*
		 * Test if file is an executable file.
		 */
		if( checklout( stdin ) < 0 ) {
			if( flag ) {
				fprintf( stderr, "strings: '%s' not executable\n", *argv);
				++argv;
				continue;
			}
			else {
				fprintf( stderr, "strings: not executable\n" );
				exit( 1 );
			}
		}

		/*
		 * Display file name if available.
		 */
		if( flag )
			fprintf( stderr, "%s:\n", *argv );

		/*
		 * Display all character strings in file.
		 */
		while( printstr() )
			;

		++argv;
	}

	free( buff );
	exit( 0 );
}

/**
 * bool
 * printstr()
 *
 *	Input:	None.
 *
 *	Action:	Display character strings in file.
 *
 *	Return:	FALSE on error or no character strings available,
 *		otherwise TRUE.
 *
 *	Note:	None.
 *
 */

bool
printstr()

{
	char	c;
	char  * p;
	char  * q;

	p = buff;
	q = p + nchars;

 	/*
	 * Check if character strings are available in file.
	 */
	if( ! lookfor() )
		return( FALSE );

	/*
	 * Display line number according to the format option specified.
	 * Ignore if no format option is set.
	 */
	if( aflag )
		printf( "%-6D: ", addr-nchars );

	else if( oflag )
		printf( "0%-6O: ", addr-nchars );

	else if( xflag )
		printf( "0x%-6X: ", addr-nchars );

	/*
	 * Display printable characters found.
	 */
	do {
		putchar( *p++ );
	} while( p < q );

	/*
	 * Display remaining printable characters in file.
	 */
	for ( ;; ) {
		if( --count <= 0L )
			return( FALSE );

		++addr;
		c = getchar();

		if( c == EOF )
			return( FALSE );

		if( ! (isascii( (c) & ~pbit ) &&  isprint( (c) & ~pbit )) )
			break;

		putchar( c );
	}

	putchar( '\n' );
	return( TRUE );
}

/**
 * bool
 * lookfor()
 *
 *	Input:	None.
 *
 *	Action:	Look for the first character string in file.
 *
 *	Return: TRUE if a character string is found, else FALSE.
 *
 *	Note:	None.
 *
 */

bool
lookfor()

{
	char	c;
	char  * p;
	char  * q;

	q = buff + nchars;

	for( ;; ) {

		/*
		 * Seek in data space segment of file until a printable
		 * character is encountered.
		 */
		do {
			if( --count <= 0L )
				return( FALSE );

			++addr;
			c = getchar();

			if( c == EOF )
				return( FALSE );

		} while( ! (isascii( (c) & ~pbit ) && isprint( (c) & ~pbit )) );

		p = buff;

		/*
		 * Check for valid character string.
		 */
		do {
			*p++ = c;

			if( p >= q )
				return( TRUE );

			if( --count <= 0L )
				return( FALSE );

			++addr;
			c = getchar();

			if( c == EOF )
				return( FALSE );

		} while( isascii( (c) & ~pbit ) && isprint( (c) & ~pbit ) );
	}
}


/**
 * int
 * checklout( f )
 *
 * register FILE * f;
 *
 *	Input:	f	- file pointer to stdin.
 *
 *	Action:	Check if executable (l.out) file.
 *
 *	Return: Returns -1 on error or file is not executable, otherwise 0.
 *
 *	Note:	None.
 *
 */

int
checklout( f )

register FILE	* f;

{
	register int	  i;		/* counter variable */
	int		  ret = -1;	/* returning error value */
	struct	 stat	  s;		/* file attributes */
	struct	 ldheader l;		/* file header information */

	if( fstat( fileno( f ), &s ) == -1 )
		return( ret );

	/*
	 * File type check. Return unless regular file.
	 */
	if( (s.st_mode & S_IFMT) != S_IFREG )
		return( ret );

	/*
	 * Get file header information.
	 */
	if( fread( &l, sizeof( l ), 1, f ) != 1 ) {
		rewind( f );
		return( ret );
	}

	rewind( f );

	if( l.l_magic != L_MAGIC )
		return( ret );

	/*
	 * Correct canonical effect on file format information.
	 */
	for( i = 0 ; i < NLSEG ; ++i )
		canlong(l.l_ssize[i]);

	/*
	 * Get seek position to the beginning memory location of the
	 * data space segment in the executable file.
	 */
	fseek( f, (long)sizeof(l) + l.l_ssize[L_SHRI] + l.l_ssize[L_PRVI], 0 );
	addr = ftell( f );

	/*
	 * Get size of data space segment of file.
	 */
	count = l.l_ssize[L_SHRD] + l.l_ssize[L_PRVD];

	if( count == 0L ) {
		fatal( "zero-length data segments" );
		/* NOTREACHED */
	}

	++count;
	return( 0 );
}

/**
 * void
 * fatal( arg0 )
 *
 * char	* arg0;
 *
 *	Input:	arg0	- pointer to string containing the error message.
 *
 *	Action:	Display fatal error message and exit.
 *
 *	Return:	Never return, always exit.
 *
 *	Note:	None.
 *
 */

fatal( arg0 )

char	* arg0;

{
	fflush( stdout );
	fprintf( stderr, "strings: %r\n", &arg0 );
	exit( 1 );
}

/**
 * void
 * usage()
 *
 *	Input:	None.
 *
 *	Action:	Display command usage format.
 *
 *	Return:	Never return, always exit.
 *
 *	Note:	None.
 *
 */

usage()

{
	fprintf( stderr, "Usage: strings [-xaop] [-nnn] [file ...]\n" );
	exit( 1 );
}

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.