1: /* $Header: artsrch.c,v 4.3 85/05/01 11:35:47 lwall Exp $ 2: * 3: * $Log: artsrch.c,v $ 4: * Revision 4.3 85/05/01 11:35:47 lwall 5: * Baseline for release with 4.3bsd. 6: * 7: */ 8: 9: #include "EXTERN.h" 10: #include "common.h" 11: #include "search.h" 12: #include "term.h" 13: #include "util.h" 14: #include "intrp.h" 15: #include "bits.h" 16: #include "kfile.h" 17: #include "head.h" 18: #include "final.h" 19: #include "cheat.h" 20: #include "ng.h" 21: #include "artio.h" 22: #include "INTERN.h" 23: #include "artsrch.h" 24: 25: void 26: artsrch_init() 27: { 28: #ifdef ARTSEARCH 29: #ifdef ZEROGLOB 30: init_compex(&sub_compex); 31: init_compex(&art_compex); 32: #endif 33: #endif 34: } 35: 36: /* search for an article containing some pattern */ 37: 38: #ifdef ARTSEARCH 39: int 40: art_search(patbuf,patbufsiz,get_cmd) 41: char *patbuf; /* if patbuf != buf, get_cmd must */ 42: int patbufsiz; 43: int get_cmd; /* be set to FALSE!!! */ 44: { 45: char *pattern; /* unparsed pattern */ 46: register char cmdchr = *patbuf; /* what kind of search? */ 47: register char *s; 48: bool backward = cmdchr == '?' || cmdchr == Ctl('p'); 49: /* direction of search */ 50: COMPEX *compex; /* which compiled expression */ 51: char *cmdlst = Nullch; /* list of commands to do */ 52: int normal_return = SRCH_NOTFOUND; /* assume no commands */ 53: bool saltaway = FALSE; /* store in KILL file? */ 54: char howmuch; /* search just the subjects */ 55: bool doread; /* search read articles? */ 56: bool foldcase = TRUE; /* fold upper and lower case? */ 57: 58: int_count = 0; 59: if (cmdchr == '/' || cmdchr == '?') { /* normal search? */ 60: if (get_cmd && buf == patbuf) 61: if (!finish_command(FALSE)) /* get rest of command */ 62: return SRCH_ABORT; 63: compex = &art_compex; 64: if (patbuf[1]) { 65: howmuch = 0; 66: doread = FALSE; 67: } 68: else { 69: howmuch = art_howmuch; 70: doread = art_doread; 71: } 72: s = cpytill(buf,patbuf+1,cmdchr);/* ok to cpy buf+1 to buf */ 73: pattern = buf; 74: if (*pattern) { 75: if (*lastpat) 76: free(lastpat); 77: lastpat = savestr(pattern); 78: } 79: if (*s) { /* modifiers or commands? */ 80: for (s++; *s && index("Kharc",*s); s++) { 81: if (*s == 'h') /* scan header */ 82: howmuch = 1; 83: else if (*s == 'a') /* scan article */ 84: howmuch = 2; 85: else if (*s == 'r') /* scan read articles */ 86: doread = TRUE; 87: else if (*s == 'K') /* put into KILL file */ 88: saltaway = TRUE; 89: else if (*s == 'c') /* make search case sensitive */ 90: foldcase = FALSE; 91: } 92: } 93: while (isspace(*s) || *s == ':') 94: s++; 95: if (*s) { 96: if (*s == 'm' || *s == 'M') 97: doread = TRUE; 98: if (*s == 'k') /* grandfather clause */ 99: *s = 'j'; 100: cmdlst = savestr(s); 101: normal_return = SRCH_DONE; 102: } 103: art_howmuch = howmuch; 104: art_doread = doread; 105: if (srchahead) 106: srchahead = -1; 107: } 108: else { 109: register char *h; 110: 111: howmuch = 0; /* just search subjects */ 112: doread = (cmdchr == Ctl('p')); 113: if (cmdchr == Ctl('n')) 114: normal_return = SRCH_SUBJDONE; 115: compex = &sub_compex; 116: pattern = patbuf+1; 117: strcpy(pattern,": *"); 118: h = pattern + strlen(pattern); 119: interp(h,patbufsiz - (h-patbuf),"%s"); /* fetch current subject */ 120: if (cmdchr == 'K') { 121: saltaway = TRUE; 122: cmdchr = 'k'; 123: } 124: if (cmdchr == 'k') { 125: normal_return = SRCH_DONE; 126: cmdlst = savestr("j"); 127: mark_as_read(art); /* this article has this subject */ 128: if (!*h) { 129: #ifdef VERBOSE 130: IF(verbose) 131: fputs("\nCannot delete null subject.\n",stdout) FLUSH; 132: ELSE 133: #endif 134: #ifdef TERSE 135: fputs("\nNull subject.\n",stdout) FLUSH; 136: #endif 137: return SRCH_ABORT; 138: } 139: #ifdef VERBOSE 140: else if (verbose) 141: printf("\nMarking subject \"%s\" as read.\n",h) FLUSH; 142: #endif 143: } 144: else if (!srchahead) 145: srchahead = -1; 146: h[24] = '\0'; /* compensate for notesfiles */ 147: while (*h) { 148: if (index("/\\[.^*$'\"",*h) != Nullch) 149: *h++ = '.'; 150: else 151: h++; 152: } 153: #ifdef DEBUGGING 154: if (debug) { 155: printf("\npattern = %s\n",pattern) FLUSH; 156: } 157: #endif 158: } 159: if ((s = compile(compex,pattern,TRUE,foldcase)) != Nullch) { 160: /* compile regular expression */ 161: printf("\n%s\n",s) FLUSH; 162: return SRCH_ABORT; 163: } 164: #ifdef KILLFILES 165: if (saltaway) { 166: char saltbuf[LBUFLEN]; 167: 168: s = saltbuf; 169: sprintf(s,"/%s/",pattern); 170: s += strlen(s); 171: if (doread) 172: *s++ = 'r'; 173: if (howmuch==1) 174: *s++ = 'h'; 175: else if (howmuch==2) 176: *s++ = 'a'; 177: *s++ = ':'; 178: if (!cmdlst) 179: cmdlst = savestr("j"); 180: safecpy(s,cmdlst,LBUFLEN-(s-saltbuf)); 181: kf_append(saltbuf); 182: } 183: #endif 184: if (cmdlst && index(cmdlst,'=')) 185: normal_return = SRCH_ERROR; /* listing subjects is an error? */ 186: if (get_cmd) { 187: fputs("\nSearching...\n",stdout) FLUSH; 188: /* give them something to read */ 189: } 190: if (backward) { 191: if (cmdlst && art < lastart) 192: art++; /* include current article */ 193: if (doread) 194: check_first(absfirst); 195: } 196: else { 197: if (art > lastart) 198: art = (doread ? absfirst : firstart) - 1; 199: else if (cmdlst && art > absfirst) 200: art--; /* include current article */ 201: check_first(art); 202: } 203: if (srchahead > 0) { 204: if (!backward) 205: art = srchahead - 1; 206: srchahead = -1; 207: } 208: assert(!cmdlst || *cmdlst); 209: for (;;) { 210: if (int_count) { 211: int_count = 0; 212: if (cmdlst) 213: free(cmdlst); 214: return SRCH_INTR; 215: } 216: if (backward ? 217: (--art < absfirst || (!doread && art < firstart)) : 218: (++art > lastart) 219: ) { /* out of articles? */ 220: if (cmdlst) 221: free(cmdlst); 222: return normal_return; 223: } 224: /*NOSTRICT*/ 225: if (doread || !was_read(art)) { 226: if (wanted(compex,art,howmuch)) { 227: /* does the shoe fit? */ 228: if (cmdlst) { 229: if (perform(cmdlst,TRUE)) { 230: if (cmdlst) 231: free(cmdlst); 232: return SRCH_INTR; 233: } 234: } 235: else { 236: if (cmdlst) 237: free(cmdlst); 238: return SRCH_FOUND; 239: } 240: } 241: else if (!cmdlst && ! (art%50)) { 242: printf("...%ld",(long)art); 243: fflush(stdout); 244: } 245: } 246: } 247: } 248: 249: /* determine if article fits pattern */ 250: /* returns TRUE if it exists and fits pattern, FALSE otherwise */ 251: 252: bool 253: wanted(compex, artnum, scope) 254: COMPEX *compex; 255: ART_NUM artnum; 256: char scope; 257: { 258: if (!scope) { 259: char subj_buf[266]; 260: 261: strcpy(subj_buf, "Subject: "); 262: strncpy(subj_buf+9,fetchsubj(artnum,FALSE,FALSE),256); 263: #ifdef DEBUGGING 264: if (debug & DEB_SEARCH_AHEAD) 265: printf("%s\n",subj_buf) FLUSH; 266: #endif 267: return execute(compex,subj_buf) != Nullch; 268: } 269: #ifdef CACHESUBJ 270: else 271: fetchsubj(artnum,FALSE,FALSE);/* might as well get subject handy */ 272: #endif 273: 274: if (artopen(artnum) == Nullfp) /* ensure that article is open */ 275: return FALSE; /* if not, return NO MATCH */ 276: scope--; 277: while (fgets(buf,LBUFLEN,artfp) != Nullch) { 278: /* for each line of article */ 279: if (!scope && index(buf,':') == Nullch && *buf != ' ' && *buf != '\t') 280: /* if headers only and out of header */ 281: return FALSE; /* say no go */ 282: if (execute(compex,buf) != Nullch) { 283: /* does pattern matcher match? */ 284: return TRUE; /* say Eureka */ 285: } 286: } 287: return FALSE; /* out of article, so no match */ 288: } 289: #endif