]> diplodocus.org Git - nmh/blob - docs/historical/mh-jun-1982/progs/pick.c
Replaced use of snprintf() with memcpy()/memmove().
[nmh] / docs / historical / mh-jun-1982 / progs / pick.c
1 #ifdef COMMENT
2 Proprietary Rand Corporation, 1981.
3 Further distribution of this software
4 subject to the terms of the Rand
5 license agreement.
6 #endif
7
8 #include "../mh.h"
9 #include "../folder.h"
10 #include <stdio.h>
11 #include <signal.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 char *malloc();
15
16 #define NFOLD 20 /* Allow 20 folder specs */
17
18 extern struct swit anoyes[]; /* Std no/yes gans array */
19
20 /*
21 * pick [-src folder] [msgs] search [-scan] [-show] [file-op]
22 *
23 * search = -from \
24 * -to \
25 * -cc \
26 * -subject \ pattern
27 * -sub /
28 * -date /
29 * -search /
30 * --component /
31 *
32 * file-op = -file [-preserve] [-link] +folder ...
33 * -keep [-stay] [+folder ...]
34 */
35
36 int nvecp, foldp;
37 char **nvec;
38 struct msgs *mp;
39 char grep[256], *grepp, *folder, maildir[128];
40 int showf, scanfl, filef, keepf, linkf, noteold, prsrvf, stayf;
41 int grep_lowsel = 5000,
42 grep_hghsel = 0;
43 char *delprog;
44
45 struct st_fold folders[NFOLD];
46
47 struct swit switches[] = {
48 "cc pattern", 0, /* 0 */
49 "date pattern", 0, /* 1 */
50 "from pattern", 0, /* 2 */
51 "search pattern", 0, /* 3 */
52 "subject pattern", 0, /* 4 */
53 "to pattern", 0, /* 5 */
54 "-othercomponent pattern", 15, /* 6 */
55 "all", -3, /* 7 */
56 "file +folder ...", 0, /* 8 */
57 "nofile", 0, /* 9 */
58 "keep [+folder ...]", 0, /* 10 */
59 "nokeep", 0, /* 11 */
60 "link", 0, /* 12 */
61 "nolink", 0, /* 13 */
62 "preserve", 0, /* 14 */
63 "nopreserve", 0, /* 15 */
64 "scan", 0, /* 16 */
65 "noscan", 0, /* 17 */
66 "show", 0, /* 18 */
67 "noshow", 0, /* 19 */
68 "src +folder", 0, /* 20 */
69 "stay", 0, /* 21 */
70 "nostay", 0, /* 22 */
71 "help", 4, /* 23 */
72 0, 0
73 };
74
75 /*ARGSUSED*/
76 main(argc, argv)
77 char *argv[];
78 {
79 char *msgs[128], buf[128];
80 register int msgnum;
81 register char *cp;
82 int msgp, i;
83 char **ap;
84 char *arguments[50], **argp, **arrp;
85
86 invo_name = argv[0];
87 #ifdef NEWS
88 m_news();
89 #endif
90 nvecp = 1;
91 msgp = 0;
92 grepp = grep;
93 cp = r1bindex(argv[0], '/');
94 if((cp = m_find(cp)) != NULL) {
95 ap = brkstring(cp = getcpy(cp), " ", "\n");
96 ap = copyip(ap, arguments);
97 } else
98 ap = arguments;
99 VOID copyip(argv+1, ap);
100 argp = arguments;
101 while(cp = *argp++) {
102 if(*cp == '-') {
103 if(*++cp == '-') { /* --component */
104 toomany: if(grepp != grep) {
105 fprintf(stderr, "Only one search string.\n");
106 goto leave;
107 }
108 grepp = copy("^", grepp);
109 grepp = copy(++cp, grepp);
110 grepp = copy(":.*", grepp);
111 goto pattern;
112 }
113 switch(i = smatch(cp, switches)) {
114 case -2:ambigsw(cp, switches); /* ambiguous */
115 goto leave;
116 /* unknown */
117 case -1:fprintf(stderr, "pick: -%s unknown\n", cp);
118 goto leave;
119 /* -component */
120 case 0: case 1: case 2: case 4: case 5:
121 if(grepp != grep)
122 goto toomany;
123 grepp = copy("^", grepp);
124 arrp = brkstring(switches[i].sw, " ", NULLCP);
125 grepp = copy(*arrp, grepp);
126 grepp = copy(":.*", grepp);
127 case 3: /* -search */
128 pattern: grepp = copy(*argp++, grepp);
129 continue;
130 case 6: fprintf(stderr, "pick: can't get here\n");
131 goto leave;
132 /* -all */
133 case 7: fprintf(stderr, "\"-all\" changed to \"all\"\n");
134 goto leave;
135 case 8: filef = 1; continue; /* -file */
136 case 9: filef = 0; continue; /* -nofile */
137 case 10:keepf = 1; continue; /* -keep */
138 case 11:keepf = 0; continue; /* -nokeep */
139 case 12:linkf = 1; continue; /* -link */
140 case 13:linkf = 0; continue; /* -nolink */
141 case 14:prsrvf = 1; continue; /* -preserve */
142 case 15:prsrvf = 0; continue; /* -nopreserve */
143 case 16:scanfl = 1; continue; /* -scan */
144 case 17:scanfl = 0; continue; /* -noscan */
145 case 18:showf = 1; continue; /* -show */
146 case 19:showf = 0; continue; /* -noshow */
147 case 21:stayf = 1; continue; /* -stay */
148 case 22:stayf = 0; continue; /* -nostay */
149 case 20:if(folder) { /* -src */
150 fprintf(stderr, "Only one src folder.\n");
151 goto leave;
152 }
153 if(!(folder = *argp++) || *folder == '-') {
154 fprintf(stderr, "pick: Missing argument for %s switch\n", argp[-2]);
155 goto leave;
156 }
157 if(*folder == '+')
158 folder++;
159 folder = path(folder, TFOLDER);
160 continue;
161 /* -help */
162 case 23:help("pick [msgs] [switches]", switches);
163 goto leave;
164 }
165 } else if(*cp == '+') {
166 if(foldp < NFOLD)
167 folders[foldp++].f_name = path(cp+1, TFOLDER);
168 else {
169 fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
170 goto leave;
171 }
172 } else
173 msgs[msgp++] = cp;
174 }
175 if(!m_find("path")) free(path("./", TFOLDER));
176 if(grepp == grep) {
177 fprintf(stderr, "No search pattern specified.\n");
178 goto leave;
179 }
180 if(filef && keepf) {
181 fprintf(stderr, "-file and -keep don't go together.\n");
182 goto leave;
183 }
184 if(!scanfl && !showf && !filef)
185 keepf++; /* The default is -keep */
186 if(keepf) {
187 prsrvf++; /* -keep forces -preserve */
188 linkf++; /* and -link */
189 }
190 if(!folder)
191 folder = m_getfolder(); /* use cur folder if no -src */
192 VOID copy(m_maildir(folder), maildir);
193 if(chdir(maildir) < 0) {
194 fprintf(stderr, "Can't chdir to: ");
195 perror(maildir);
196 goto leave;
197 }
198 if(!(mp = m_gmsg(folder))) {
199 fprintf(stderr, "Can't read folder!?\n");
200 goto leave;
201 }
202 if(mp->hghmsg == 0) {
203 fprintf(stderr, "No messages in \"%s\".\n", folder);
204 goto leave;
205 }
206 if(!foldp) { /* if no +folder given... */
207 if(filef) { /* -file requires one */
208 fprintf(stderr, "-file requires at least one folder arg.\n");
209 goto leave;
210 }
211 if(keepf) { /* use default selection-list name */
212 VOID copy(listname, copy("/", copy(folder, buf)));
213 folders[foldp++].f_name = getcpy(buf);
214 noteold++; /* tell user if existing folder */
215 }
216 } else if(keepf) { /* make folders sub-folders */
217 for(msgnum = 0; msgnum < foldp; msgnum++)
218 if(*(cp = folders[msgnum].f_name) != '.' &&
219 *cp != '/') {
220 VOID copy(cp, copy("/", copy(folder, buf)));
221 folders[msgnum].f_name = getcpy(buf);
222 }
223 noteold++;
224 }
225 if(!msgp)
226 msgs[msgp++] = "first-last";
227 for(msgnum = 0; msgnum < msgp; msgnum++)
228 if(!m_convert(msgs[msgnum]))
229 goto leave;
230 if(mp->numsel == 0) {
231 fprintf(stderr, "pick: Peanut butter 'n jelly\n");/* never get here */
232 goto leave;
233 }
234 if(!compile(grep)) {
235 fprintf(stderr, "Pattern Error.\n");
236 goto leave;
237 }
238 for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
239 if(mp->msgstats[msgnum]&SELECTED)
240 grepfn(msgnum);
241 if(mp->numsel == 0) {
242 fprintf(stderr, "No messages match specification.\n");
243 goto leave;
244 }
245 mp->lowsel = grep_lowsel;
246 mp->hghsel = grep_hghsel;
247 /* all the exec's */
248 if((((delprog = m_find("delete-prog")) != NULL) &&
249 ((filef || keepf) && !linkf)) ||
250 scanfl || showf) {
251 if(mp->numsel > MAXARGS-2) {
252 fprintf(stderr, "pick: more than %d messages for %s exec\n",
253 MAXARGS-2,
254 scanfl ? "scan" : showf ? "show" : delprog);
255 goto leave;
256 }
257 nvec = (char **) malloc(MAXARGS * sizeof nvec[0]);
258 for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
259 if(mp->msgstats[msgnum]&SELECTED)
260 nvec[nvecp++] = getcpy(m_name(msgnum));
261 nvec[nvecp] = 0;
262 }
263 if(keepf || filef)
264 if(opnfolds())
265 goto leave;
266 if(!noteold || foldp > 1)
267 m_replace(pfolder, folder);
268 if(scanfl)
269 scanfn(showf|filef|keepf);
270 else {
271 printf("%d hit%s.\n", mp->numsel, mp->numsel == 1 ? "" : "s");
272 VOID fflush(stdout);
273 }
274 if(showf)
275 showfn(filef|keepf);
276 if(!(filef|keepf))
277 goto leave;
278 for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
279 if(mp->msgstats[msgnum]&SELECTED)
280 if(m_file(folder, cp = getcpy(m_name(msgnum)),
281 folders, foldp, prsrvf, 1))
282 goto leave;
283 else
284 free (cp);
285 if(!linkf)
286 remove();
287 if(noteold) {
288 struct st_fold *fptr;
289 if(!stayf && foldp == 1) {
290 m_replace(pfolder, cp = folders[0].f_name);
291 printf("[+%s now current]\n", cp); VOID fflush(stdout);
292 }
293 for(fptr = folders; fptr < &folders[foldp]; fptr++)
294 if(!fptr->f_reused) {
295 VOID chdir(m_maildir(fptr->f_name));
296 m_setcur(fptr->f_mp->curmsg);
297 }
298 }
299 leave:
300 m_update();
301 }
302
303
304 grepfn(msg)
305 {
306 if(execute(m_name(msg))) { /* a match */
307 if(msg < grep_lowsel)
308 grep_lowsel = msg;
309 if(msg > grep_hghsel)
310 grep_hghsel = msg;
311 } else {
312 mp->msgstats[msg] &= ~SELECTED; /* clear SELECTED bit */
313 mp->numsel--;
314 }
315 }
316
317
318 opnfolds()
319 {
320 register int i;
321 register char *cp, *ap;
322 char nmaildir[128];
323 struct stat stbuf;
324
325 for(i = 0; i < foldp; i++) {
326 VOID copy(m_maildir(cp = folders[i].f_name), nmaildir);
327 if(stat(nmaildir, &stbuf) < 0) {
328 if(!noteold) {
329 ap = concat("Create folder \"",
330 nmaildir, "\"? ", 0);
331 if(!gans(ap, anoyes))
332 return(1);
333 }
334 if(!makedir(nmaildir)) {
335 fprintf(stderr, "Can't create folder.\n");
336 return(1);
337 }
338 } else if(noteold) {
339 printf("[Folder %s being re-used.]\n", cp);
340 VOID fflush(stdout);
341 folders[i].f_reused++; /* Don't change cur in old fold */
342 }
343 if(chdir(nmaildir) < 0) {
344 fprintf(stderr, "Can't chdir to: ");
345 perror(nmaildir);
346 return(1);
347 }
348 if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
349 fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
350 return(1);
351 }
352 folders[i].f_mp->curmsg = 0;
353 }
354 VOID chdir(maildir); /* return to src folder */
355 return(0);
356 }
357
358
359 scanfn(forkf)
360 {
361 register int pid;
362
363 nvec[0] = r1bindex(scanproc, '/');
364 if(forkf && (pid = fork())) {
365 if(pid == -1) {
366 fprintf(stderr, "No forks!\n");
367 done(1);
368 }
369 while(wait((int *)NULL) != pid) ;
370 } else {
371 m_update();
372 VOID fflush(stdout);
373 execv(scanproc, nvec);
374 perror(scanproc);
375 done(1);
376 }
377 }
378
379
380 showfn(forkf)
381 {
382 register int pid;
383 int (*sint)(), (*sqit)();
384
385 nvec[0] = r1bindex(showproc, '/');
386 if(forkf) {
387 sint = signal(SIGINT, SIG_IGN);
388 sqit = signal(SIGQUIT, SIG_IGN);
389 }
390 if(forkf && (pid = fork())) {
391 if(pid == -1) {
392 fprintf(stderr, "No forks!\n");
393 done(1);
394 }
395 while(wait((int *)NULL) != pid) ;
396 VOID signal(SIGINT, sint);
397 VOID signal(SIGQUIT, sqit);
398 } else {
399 m_update();
400 VOID fflush(stdout);
401 putenv("mhfolder", folder);
402 execv(showproc, nvec);
403 perror(showproc);
404 done(1);
405 }
406 }
407
408
409 remove()
410 {
411 register int i;
412 register char *cp;
413
414 if(delprog != NULL) {
415 nvec[0] = r1bindex(delprog, '/');
416 m_update();
417 VOID fflush(stdout);
418 execv(delprog, nvec);
419 fprintf(stderr, "Can't exec deletion-prog--");
420 perror(delprog);
421 } else {
422 for(i= mp->lowsel; i<= mp->hghsel; i++)
423 if(mp->msgstats[i]&SELECTED)
424 if(unlink(cp = m_name(i)) == -1) {
425 fprintf(stderr, "Can't unlink %s:",folder);
426 perror(cp);
427