/* $Id: artsrch.c,v 3.0 1992/02/01 03:09:32 davison Trn $ */ /* This software is Copyright 1991 by Stan Barber. * * Permission is hereby granted to copy, reproduce, redistribute or otherwise * use this software as long as: there is no monetary profit gained * specifically from the use or reproduction of this software, it is not * sold, rented, traded or otherwise marketed, and this copyright notice is * included prominently in any copy made. * * The author make no claims as to the fitness or correctness of this software * for any use whatsoever, and it is provided as is. Any use of this software * is at the user's own risk. */ #include "EXTERN.h" #include "common.h" #include "search.h" #include "term.h" #include "util.h" #include "intrp.h" #include "cache.h" #include "bits.h" #include "kfile.h" #include "head.h" #include "final.h" #include "nntp.h" #include "ng.h" #include "ngdata.h" #include "ngstuff.h" #include "artio.h" #include "rthread.h" #include "rt-select.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 scope: subj/from/head/art */ bool doread; /* search read articles? */ bool foldcase = TRUE; /* fold upper and lower case? */ ART_NUM srchfirst; 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("Karchf",*s); s++) { if (*s == 'f') /* scan from line */ howmuch = 1; else if (*s == 'h') /* scan header */ howmuch = 2; else if (*s == 'a') /* scan article */ howmuch = 3; 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' || cmdchr == 'K' || cmdchr == '+' || cmdchr == ',') { if (cmdchr != 'k') saltaway = TRUE; normal_return = SRCH_DONE; if (cmdchr == '+') cmdlst = savestr("++"); else if (cmdchr == ',') cmdlst = savestr(","); mark_as_read(); /* 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; { /* compensate for notesfiles */ register int i; for (i = 24; *h && i--; h++) if (*h == '\\') h++; *h = '\0'; } #ifdef DEBUG 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]; static char *scopestr = "fha"; s = saltbuf; sprintf(s,"/%s/",pattern); s += strlen(s); if (doread) *s++ = 'r'; if (howmuch > 0) *s++ = scopestr[howmuch]; *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 (mode == 't') { if (!cmdlst) if (sel_mode == SM_ARTICLE)/* set the selector's default command */ cmdlst = savestr("+"); else cmdlst = savestr("++"); if (sel_rereading) doread = TRUE; normal_return = SRCH_DONE; } srchfirst = (doread? absfirst : (mode == 'k' && (howmuch > 1 || lastart - last_cached > 25) ? killfirst : firstart)); if (backward) { if (cmdlst && art <= lastart) art++; /* include current article */ } else { if (art > lastart) art = srchfirst-1; else if (cmdlst && art >= absfirst) art--; /* include current article */ } if (srchahead > 0) { if (!backward) art = srchahead - 1; srchahead = -1; } assert(!cmdlst || *cmdlst); perform_cnt = 0; for (;;) { /* check if we're out of articles */ if (backward? (--art < srchfirst) : (++art > lastart)) { if (cmdlst) free(cmdlst); return normal_return; } if (int_count) { int_count = 0; if (cmdlst) free(cmdlst); return SRCH_INTR; } artp = article_ptr(art); if (doread || !(artp->flags & AF_READ)) { 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_int scope; { ARTICLE *ap = find_article(artnum); if (!ap || (ap->flags & AF_MISSING)) return FALSE; if (scope <= 1) { if (!scope) { strcpy(buf,"Subject: "); strncpy(buf+9,fetchsubj(artnum,FALSE),256); #ifdef DEBUG if (debug & DEB_SEARCH_AHEAD) printf("%s\n",buf) FLUSH; #endif } else { strcpy(buf, "From: "); strncpy(buf+6,fetchfrom(artnum,FALSE),256); } return execute(compex,buf) != Nullch; } if (!parseheader(artnum)) return FALSE; /* see if it's in the header */ if (execute(compex,headbuf) != Nullch) /* does it match? */ return TRUE; /* say, "Eureka!" */ if (scope < 3) return FALSE; if (!artopen(artnum)) /* ensure we have the body */ return FALSE; /* loop through each line of the article */ while (fgets(buf,LBUFLEN,artfp) != Nullch) { if (execute(compex,buf) != Nullch) /* does it match? */ return TRUE; /* say, "Eureka!" */ } return FALSE; /* out of article, so no match */ } #endif