Commit | Line | Data |
---|---|---|
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 | ||
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 | |
290 |