4.3BSD/usr/contrib/rn/artsrch.c

Compare this file to the similar file:
Show the results in this format:

/* $Header: artsrch.c,v 4.3 85/05/01 11:35:47 lwall Exp $
 *
 * $Log:	artsrch.c,v $
 * Revision 4.3  85/05/01  11:35:47  lwall
 * Baseline for release with 4.3bsd.
 * 
 */

#include "EXTERN.h"
#include "common.h"
#include "search.h"
#include "term.h"
#include "util.h"
#include "intrp.h"
#include "bits.h"
#include "kfile.h"
#include "head.h"
#include "final.h"
#include "cheat.h"
#include "ng.h"
#include "artio.h"
#include "INTERN.h"
#include "artsrch.h"

void
artsrch_init()
{
#ifdef ARTSEARCH
#ifdef ZEROGLOB
    init_compex(&sub_compex);
    init_compex(&art_compex);
#endif
#endif
}

/* search for an article containing some pattern */

#ifdef ARTSEARCH
int
art_search(patbuf,patbufsiz,get_cmd)
char *patbuf;				/* if patbuf != buf, get_cmd must */
int patbufsiz;
int get_cmd;				/*   be set to FALSE!!! */
{
    char *pattern;			/* unparsed pattern */
    register char cmdchr = *patbuf;	/* what kind of search? */
    register char *s;
    bool backward = cmdchr == '?' || cmdchr == Ctl('p');
					/* direction of search */
    COMPEX *compex;			/* which compiled expression */
    char *cmdlst = Nullch;		/* list of commands to do */
    int normal_return = SRCH_NOTFOUND;	/* assume no commands */
    bool saltaway = FALSE;		/* store in KILL file? */
    char howmuch;			/* search just the subjects */
    bool doread;			/* search read articles? */
    bool foldcase = TRUE;		/* fold upper and lower case? */

    int_count = 0;
    if (cmdchr == '/' || cmdchr == '?') {	/* normal search? */
	if (get_cmd && buf == patbuf)
	    if (!finish_command(FALSE))	/* get rest of command */
		return SRCH_ABORT;
	compex = &art_compex;
	if (patbuf[1]) {
	    howmuch = 0;
	    doread = FALSE;
	}
	else {
	    howmuch = art_howmuch;
	    doread = art_doread;
	}
	s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */
	pattern = buf;
	if (*pattern) {
	    if (*lastpat)
		free(lastpat);
	    lastpat = savestr(pattern);
	}
	if (*s) {			/* modifiers or commands? */
	    for (s++; *s && index("Kharc",*s); s++) {
		if (*s == 'h')		/* scan header */
		    howmuch = 1;
		else if (*s == 'a')	/* scan article */
		    howmuch = 2;
		else if (*s == 'r')	/* scan read articles */
		    doread = TRUE;
		else if (*s == 'K')	/* put into KILL file */
		    saltaway = TRUE;
		else if (*s == 'c')	/* make search case sensitive */
		    foldcase = FALSE;
	    }
	}
	while (isspace(*s) || *s == ':')
	    s++;
	if (*s) {
	    if (*s == 'm' || *s == 'M')
		doread = TRUE;
	    if (*s == 'k')		/* grandfather clause */
		*s = 'j';
	    cmdlst = savestr(s);
	    normal_return = SRCH_DONE;
	}
	art_howmuch = howmuch;
	art_doread = doread;
	if (srchahead)
	    srchahead = -1;
    }
    else {
	register char *h;

	howmuch = 0;			/* just search subjects */
	doread = (cmdchr == Ctl('p'));
	if (cmdchr == Ctl('n'))
	    normal_return = SRCH_SUBJDONE;
	compex = &sub_compex;
	pattern = patbuf+1;
	strcpy(pattern,": *");
	h = pattern + strlen(pattern);
	interp(h,patbufsiz - (h-patbuf),"%s");	/* fetch current subject */
	if (cmdchr == 'K') {
	    saltaway = TRUE;
	    cmdchr = 'k';
	}
	if (cmdchr == 'k') {
	    normal_return = SRCH_DONE;
	    cmdlst = savestr("j");
	    mark_as_read(art);		/* this article has this subject */
	    if (!*h) {
#ifdef VERBOSE
		IF(verbose)
		    fputs("\nCannot delete null subject.\n",stdout) FLUSH;
		ELSE
#endif
#ifdef TERSE
		    fputs("\nNull subject.\n",stdout) FLUSH;
#endif
		return SRCH_ABORT;
	    }
#ifdef VERBOSE
	    else if (verbose)
		printf("\nMarking subject \"%s\" as read.\n",h) FLUSH;
#endif
	}
	else if (!srchahead)
	    srchahead = -1;
	h[24] = '\0';		/* compensate for notesfiles */
	while (*h) {
	    if (index("/\\[.^*$'\"",*h) != Nullch)
		*h++ = '.';
	    else
		h++;
	}
#ifdef DEBUGGING
	if (debug) {
	    printf("\npattern = %s\n",pattern) FLUSH;
	}
#endif
    }
    if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) {
					/* compile regular expression */
	printf("\n%s\n",s) FLUSH;
	return SRCH_ABORT;
    }
#ifdef KILLFILES
    if (saltaway) {
	char saltbuf[LBUFLEN];

	s = saltbuf;
	sprintf(s,"/%s/",pattern);
	s += strlen(s);
	if (doread)
	    *s++ = 'r';
	if (howmuch==1)
	    *s++ = 'h';
	else if (howmuch==2)
	    *s++ = 'a';
	*s++ = ':';
	if (!cmdlst)
	    cmdlst = savestr("j");
	safecpy(s,cmdlst,LBUFLEN-(s-saltbuf));
	kf_append(saltbuf);
    }
#endif
    if (cmdlst && index(cmdlst,'='))
	normal_return = SRCH_ERROR;	/* listing subjects is an error? */
    if (get_cmd) {
	fputs("\nSearching...\n",stdout) FLUSH;
					/* give them something to read */
    }
    if (backward) {
	if (cmdlst && art < lastart)
	    art++;			/* include current article */
	if (doread)
	    check_first(absfirst);
    }
    else {
	if (art > lastart)
	    art = (doread ? absfirst : firstart) - 1;
	else if (cmdlst && art > absfirst)
	    art--;			/* include current article */
	check_first(art);
    }
    if (srchahead > 0) {
	if (!backward)
	    art = srchahead - 1;
	srchahead = -1;
    }
    assert(!cmdlst || *cmdlst);
    for (;;) {
	if (int_count) {
	    int_count = 0;
	    if (cmdlst)
		free(cmdlst);
	    return SRCH_INTR;
	}
	if (backward ?
		(--art < absfirst || (!doread && art < firstart)) :
		(++art > lastart)
	  ) {			/* out of articles? */
	    if (cmdlst)
		free(cmdlst);
	    return normal_return;
	}
	/*NOSTRICT*/
	if (doread || !was_read(art)) {
	    if (wanted(compex,art,howmuch)) {
				    /* does the shoe fit? */
		if (cmdlst) {
		    if (perform(cmdlst,TRUE)) {
			if (cmdlst)
			    free(cmdlst);
			return SRCH_INTR;
		    }
		}
		else {
		    if (cmdlst)
			free(cmdlst);
		    return SRCH_FOUND;
		}
	    }
	    else if (!cmdlst && ! (art%50)) {
		printf("...%ld",(long)art);
		fflush(stdout);
	    }
	}
    }
}

/* determine if article fits pattern */
/* returns TRUE if it exists and fits pattern, FALSE otherwise */

bool
wanted(compex, artnum, scope)
COMPEX *compex;
ART_NUM artnum;
char scope;
{
    if (!scope) {
	char subj_buf[266];
	
	strcpy(subj_buf, "Subject: ");
	strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256);
#ifdef DEBUGGING
	if (debug & DEB_SEARCH_AHEAD)
	    printf("%s\n",subj_buf) FLUSH;
#endif
	return execute(compex,subj_buf) != Nullch;
    }
#ifdef CACHESUBJ
    else
	fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */
#endif
    
    if (artopen(artnum) == Nullfp)	/* ensure that article is open */
	return FALSE;			/* if not, return NO MATCH */
    scope--;
    while (fgets(buf,LBUFLEN,artfp) != Nullch) {
					/* for each line of article */
	if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t')
					/* if headers only and out of header */
	    return FALSE;		/* say no go */
	if (execute(compex,buf) != Nullch) {
					/* does pattern matcher match? */
	    return TRUE;		/* say Eureka */
	}
    }
    return FALSE;			/* out of article, so no match */
}
#endif