[comp.os.minix] utility to find strings in a file

wheels@mks.UUCP (Gerry Wheeler) (02/07/89)

I haven't seen a version of strings for MINIX, so here is my attempt. 
It doesn't have some of the options of other versions I have seen, but
it is quite functional as is.  If someone has need of other options,
perhaps they could post their changes, or email me with a request and
I'll consider adding it. 

I've also compiled this on U**x and MS-DOS.  The only change required
for DOS was that the fopen() had to have binary mode added, so it looked
like this:

		fopen(argv[arg], "rb")

This prevents DOS from returning EOF when it reads a ^Z character.

------------------------------ cut here ------------------------------
/*
 * This is a simple version of the strings command to find and
 * display sequences of printable characters in a file. This
 * version does not have any knowledge about the format of any
 * file, so it searches the entire file.
 *
 * Written by Gerry Wheeler, February 5, 1989. Permission is
 * granted to use this source code for non-profit purposes,
 * provided this and any other acknowledgements are included.
 *
 * When compiled on MINIX ST, I found that a stack size of 5000
 * bytes was adequate. For example:
 *
 *		cc -O -o strings strings.c
 *		chmem =5000 strings
 */

#include <stdio.h>

#define DEF_LENGTH 5		/* default minimum string length */
#define MAX_LENGTH 100		/* maximum minimum string length */

#define isprintable(x)	(((x)>=' ')&&((x)<='~'))

static char* Ack = "strings, version 1.0, by Gerry Wheeler, 89/2/5";


/*
 * Find and print the strings in a file.
 */

static void strings(fp, min_length, name)
FILE *fp;
int min_length;
char *name;
{
	static char buf[MAX_LENGTH];
	int c, count;

	/*
	 * Look for a sequence of min_length printable characters.
	 * If found, print them, and then print any following printable
	 * characters.
	 */

	count = 0;
	while ((c = getc(fp)) != EOF) {
		/*
		 * If we find a printable character, add it to the
		 * buffer. Otherwise, reset the count to zero and
		 * look some more.
		 */

		if (isprintable((char)c))
			buf[count++] = (char)c;
		else
			count = 0;

		if (count >= min_length) {
			/*
			 * If we have the minimum number of printable
			 * characters, print the file name, and the
			 * characters.
			 */

			if (*name != '\0')
				printf("%s: ", name);

			for (count = 0; count < min_length; ++count)
				putchar(buf[count]);

			/*
			 * Then print any following printable characters.
			 */

			while ((c = getc(fp)) != EOF) {
				if (isprintable((char)c))
					putchar((char)c);
				else
					break;
			}

			/*
			 * Print a newline to separate sets of output.
			 */

			putchar('\n');

			count = 0;	/* reset counter for next time */
		}
	}
	fflush(stdout);		/* flush one file's output before starting another */
}


main(argc, argv)
int argc;
char *argv[];
{
	int min_length = DEF_LENGTH;	/* minimum string length */
	int arg = 1;			/* command arg being examined */

	/*
	 * See if the first argument is a string length.
	 */

	if (argc > 1 && argv[1][0] == '-') {
		/*
		 * If the hyphen is followed by a non-digit, assume they
		 * are unaware of the correct options, and give a usage
		 * message.
		 */

		if (argv[1][1] < '0' || argv[1][1] > '9') {
			fprintf(stderr, "usage: %s [-minsize] [file ...]\n", argv[0]);
			exit(1);
		}

		min_length = atoi(&argv[1][1]);

		if (min_length < 1 || min_length > MAX_LENGTH) {
			fprintf(stderr, "%s: string length must be between 1 and %d\n", argv[0], MAX_LENGTH);
			exit(1);
		}

		arg = 2;
	}

	/*
	 * If there are no more arguments, we have to use the standard
	 * input for data. Otherwise, use each of the arguments as a
	 * file name and try to open it.
	 */

	if (arg >= argc)
		strings(stdin, min_length, "");
	else {
		int shownames;

		/*
		 * If there is more than one file to show, remember
		 * that we have to show the file names.
		 */

		shownames = argc > (arg + 1);

		while (arg < argc) {
			FILE *fp;

			if ((fp = fopen(argv[arg], "r")) != NULL) {
				strings(fp, min_length, shownames ? argv[arg] : "");
				fclose(fp);
			}
			else {
				fprintf(stderr, "%s: can't open file \"%s\"\n", argv[0], argv[arg]);
				exit(1);
			}
			++arg;
		}
	}
}

-- 
     Gerry Wheeler                           Phone: (519)884-2251
Mortice Kern Systems Inc.               UUCP: uunet!watmath!mks!wheels
   35 King St. North                             BIX: join mks
Waterloo, Ontario  N2J 2W9                  CompuServe: 73260,1043