BSD 4_3 development
[unix-history] / usr / contrib / rn / artsrch.c
CommitLineData
9c4b96b4
C
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
25void
26artsrch_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
39int
40art_search(patbuf,patbufsiz,get_cmd)
41char *patbuf; /* if patbuf != buf, get_cmd must */
42int patbufsiz;
43int 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
252bool
253wanted(compex, artnum, scope)
254COMPEX *compex;
255ART_NUM artnum;
256char 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
290