DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T s

⟦e99dee8af⟧ TextFile

    Length: 6113 (0x17e1)
    Types: TextFile
    Names: »search.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/news/misc/search/search.c« 

TextFile

/* search [options] ... [file|directory] ...

   Search saved news articles for a match, and summarize the matching
   articles.
   Options are:
	-f		show file name
	-b		show article's body
	-h		show article's header
	-a		show entire article (== -b -h)
	-k key		show header lines with this key; *suppress* matching
			header lines if combined with -h or -a
	-m [key]:[val]	process only matching articles
	-p		pipe output through pager (for each article separately)
	-e		allow editing of the file
   Directories are scanned recursively for matching files.
   If no files or directories are given, searches ~/News/save, or $SAVE if
   defined.
   If none of the parameters -f, -b, -h, -a, -k or -e are given, -k Subject
   is assumed.
*/

#include "lib/defs.h"
#include "lib/scanheaders.h"

/* Getopt globals: */
extern int optind;
extern char *optarg;

int process(); /* Forward */

/* Command line options. */

bool do_name= FALSE;
bool do_header= FALSE;
bool do_body= FALSE;
bool use_pager= FALSE;
bool edit_file= FALSE;

main(argc, argv)
	int argc;
	char **argv;
{
	int c;
	int status= 0;
	
	while ((c= getopt(argc, argv, "abefhpk:m:")) != EOF) {
		switch (c) {
		case 'f':
			do_name= TRUE;
			break;
		case 'h':
			do_header= TRUE;
			break;
		case 'k':
			set_keyword(optarg);
			break;
		case 'm':
			set_pattern(optarg);
			break;
		case 'a':
			do_header= do_body= TRUE;
			break;
		case 'b':
			do_body= TRUE;
			break;
		case 'p':
			use_pager= TRUE;
			break;
		case 'e':
			edit_file= TRUE;
			break;
		default:
			usage(argv[0]);
		}
	}
	add_defaults(); /* If no flags given */
	if (argc-optind < 1) {
		char *save= getenv("SAVE");
		if (save == NULL || *save == EOS) {
			char buf[BUFSIZ];
			save= getenv("HOME");
			if (save == NULL || *save == EOS)
				usage(argv[0]);
			sprintf(buf, "%s/News/save", save);
			save= strsave(buf);
		}
		status |= descend(save, process);
	}
	else {
		do {
			if (isdir(argv[optind]))
				status |= descend(argv[optind], process);
			else
				status |= process(argv[optind]);
		} while (++optind < argc);
	}
	exit(status);
}

/* Issue 'usage' error message and exit. */

usage(progname)
	char *progname;
{
	fprintf(stderr,
	    "usage: %s [-abefhp] [-m key:match] [-k key] ... file|dir ...\n",
	    progname);
	exit(2);
}

/* Process one file given by name. */

int
process(name)
	char *name;
{
	FILE *fp;
	int status;
	
	if ((fp= fopen(name, "r")) == NULL) {
		perror(name);
		return 1;
	}
	status= fprocess(fp, name);
	(void) fclose(fp);
	return status;
}

/* Process one file, given as a FILE pointer. */

int match(); /* Forward */
int display(); /* Forward */

bool have_pattern= FALSE;

int
fprocess(fp, name)
	FILE *fp;
	char *name;
{
	int code= have_pattern ? scanheaders(fp, name, match) : FOUND_MATCH;
	
	switch (code) {
	
	case FOUND_MATCH:
		startfile(name);
		rewind(fp);
		(void) scanheaders(fp, name, display);
		endfile(fp, name);
		/* Fall through */
	case NO_MATCH:
		return 0;
		
	case EMPTY_FILE:
		fprintf(stderr, "%s: empty file\n", name);
		break;
	
	case NO_HEADERS:
		fprintf(stderr, "%s: no headers\n", name);
		break;
	
	case BAD_HEADER:
		fprintf(stderr, "%s: bad headers\n", name);
		break;
	
	case BAD_LINE:
		fprintf(stderr, "%s: bad header line\n", name);
		break;
	
	default:
		fprintf(stderr, "%s: bad header, code %d\n", name,
		code);
		break;
	
	}
	return 1;
}

/* Set the search pattern. */

char *the_key;
int key_len;
char *the_val;
int val_len;

set_pattern(pattern)
	char *pattern;
{
	char *key= pattern;
	char *value= pattern;
	
	while (iskwchar(*value))
		++value;
	if (*value != EOS)
		*value++ = EOS;
	the_key= key;
	key_len= strlen(the_key);
	the_val= trim(value);
	val_len= strlen(the_val);
	have_pattern= key_len + val_len > 0;
}

/* See if key, value match with the given pattern. */

/*ARGSUSED*/
bool
match(key, value, file, first)
	char *key;
	char *value;
	char *file;
	bool first;
{
	return cistrncmp(the_key, key, key_len) == 0 &&
		cimatch(the_val, value, val_len);
}

/* Set the keywords to be used in displaying the header. */

#define MAXKEYWORDS 50
int nkeywords= 0;
char *keywords[MAXKEYWORDS];

set_keyword(key)
	char *key;
{
	if (nkeywords >= MAXKEYWORDS) {
		fprintf(stderr, "too many -k parameters\n");
		exit(2);
	}
	keywords[nkeywords++]= key;
}

/* Print a header line, if it matches the specifications. */

FILE *ofile= stdout;

bool
display(key, value, file, first)
	char *key;
	char *value;
	char *file;
	bool first;
{
	if (okay(key)) {
		if (first)
			fprintf(ofile, "%s: ", key);
		else
			fprintf(ofile, "\t");
		fprintf(ofile, "%s\n", trim(value));
	}
	return FALSE;
}

/* Do we want to print this key? */

bool
okay(key)
	char *key;
{
	int i;
	
	for (i= 0; i < nkeywords; ++i) {
		if (cistrncmp(key, keywords[i], strlen(keywords[i])) == 0)
			return !do_header;
	}
	return do_header;
}

startfile(file)
	char *file;
{
	if (use_pager) {
		static char *pager;
		if (pager == NULL) {
			pager= getenv("PAGER");
			if (pager == NULL || *pager == EOS)
				pager= "more";
		}
		ofile= popen(pager, "w");
	}
	if (do_name)
		fprintf(ofile, "%s\n", file);
}

endfile(fp, file)
	FILE *fp;
	char *file;
{
	if (do_header || (nkeywords + do_name) > 1)
		fprintf(ofile, "\n");
	if (do_body)
		copyrest(fp, ofile);
	if (use_pager) {
		int status= pclose(ofile);
		if (status != 0)
			fprintf("pager exit code %d\n", status);
	}
	if (edit_file) {
		static char *editor;
		char command[BUFSIZ];
		char line[10];
		char *reply;
		int status;
		
		if (editor == NULL) {
			editor= getenv("EDITOR");
			if (editor == NULL || *editor == EOS)
				editor= getenv("VISUAL");
			if (editor == NULL || *editor == EOS)
				editor= "vi";
		}
		sprintf(command, "%s %s", editor, file);
		fprintf(stderr, "Edit? [yn] ");
		safegets(line, sizeof line, stdin);
		reply= trim(line);
		if (*reply == 'n' || *reply == 'N')
			return;
		status= system(command);
		if (status != 0)
			fprintf(stderr, "editor exit code %d\n", status);
	}
}

/* Add defaults, to ensure at least some output is generated
   for every match. */

add_defaults()
{
	if (do_header + do_body + do_name + nkeywords == 0)
		set_keyword("Subject");
}