]> diplodocus.org Git - nmh/blob - docs/historical/mh-nov-1983/cmds/pick.c
Removed --depth 1 from git clone invocation.
[nmh] / docs / historical / mh-nov-1983 / cmds / pick.c
1 #include "mh.h"
2 #include <stdio.h>
3 #include <signal.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <errno.h>
7 #include <strings.h>
8
9 #define NFOLD 20 /* Allow 20 folder specs */
10
11 char *anoyes[]; /* Std no/yes gans array */
12
13 /*
14 * pick [-src folder] [msgs] search [-scan] [-show] [file-op]
15 *
16 * search = -from \
17 * -to \
18 * -cc \
19 * -subject \ pattern
20 * -sub /
21 * -date /
22 * -search /
23 * --component /
24 *
25 * file-op = -file [-preserve] [-link] +folder ...
26 * -keep [-stay] [+folder ...]
27 */
28
29 extern int errno;
30 int nvecp, foldp;
31 char **nvec;
32 struct msgs *mp;
33 char grep[256], *grepp, *folder, maildir[128];
34 int showf, scanf, filef, keepf, linkf, noteold, prsrvf, stayf;
35 int grep_lowsel = 5000,
36 grep_hghsel = 0;
37 char *delprog;
38
39 char _sobuf[BUFSIZ];
40
41 struct st_fold {
42 char *f_name;
43 int f_reused;
44 struct msgs *f_mp;
45 } folders[NFOLD], *fptr;
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 main(argc, argv)
76 char *argv[];
77 {
78 char *msgs[128], buf[128];
79 register int msgnum;
80 register char *cp;
81 int msgp, i;
82 char **ap;
83 char *arguments[50], **argp, **arrp;
84
85 setbuf(stdout, _sobuf);
86
87 #ifdef NEWS
88 m_news();
89 #endif
90
91 nvecp = 1;
92 msgp = 0;
93 grepp = grep;
94 cp = r1bindex(argv[0], '/');
95 if((cp = m_find(cp)) != NULL) {
96 ap = brkstring(cp = getcpy(cp), " ", "\n");
97 ap = copyip(ap, arguments);
98 } else
99 ap = arguments;
100 copyip(argv+1, ap);
101 argp = arguments;
102 while(cp = *argp++) {
103 if(*cp == '-') {
104 if(*++cp == '-') { /* --component */
105 toomany: if(grepp != grep) {
106 fprintf(stderr, "Only one search string.\n");
107 goto leave;
108 }
109 grepp = copy("^", grepp);
110 grepp = copy(++cp, grepp);
111 grepp = copy(":.*", grepp);
112 goto pattern;
113 }
114 switch(i = smatch(cp, switches)) {
115 case -2:ambigsw(cp, switches); /* ambiguous */
116 goto leave;
117 /* unknown */
118 case -1:fprintf(stderr, "pick: -%s unknown\n", cp);
119 goto leave;
120 /* -component */
121 case 0: case 1: case 2: case 4: case 5:
122 if(grepp != grep)
123 goto toomany;
124 grepp = copy("^", grepp);
125 arrp = brkstring(switches[i].sw, " ", 0);
126 grepp = copy(*arrp, grepp);
127 grepp = copy(":.*", grepp);
128 case 3: /* -search */
129 pattern: grepp = copy(*argp++, grepp);
130 continue;
131 case 6: fprintf(stderr, "pick: can't get here\n");
132 goto leave;
133 /* -all */
134 case 7: fprintf(stderr, "\"-all\" changed to \"all\"\n");
135 goto leave;
136 case 8: filef = 1; continue; /* -file */
137 case 9: filef = 0; continue; /* -nofile */
138 case 10:keepf = 1; continue; /* -keep */
139 case 11:keepf = 0; continue; /* -nokeep */
140 case 12:linkf = 1; continue; /* -link */
141 case 13:linkf = 0; continue; /* -nolink */
142 case 14:prsrvf = 1; continue; /* -preserve */
143 case 15:prsrvf = 0; continue; /* -nopreserve */
144 case 16:scanf = 1; continue; /* -scan */
145 case 17:scanf = 0; continue; /* -noscan */
146 case 18:showf = 1; continue; /* -show */
147 case 19:showf = 0; continue; /* -noshow */
148 case 21:stayf = 1; continue; /* -stay */
149 case 22:stayf = 0; continue; /* -nostay */
150 case 20:if(folder) { /* -src */
151 fprintf(stderr, "Only one src folder.\n");
152 goto leave;
153 }
154 if(!(folder = *argp++) || *folder == '-') {
155 fprintf(stderr, "pick: Missing argument for %s switch\n", argp[-2]);
156 goto leave;
157 }
158 if(*folder == '+')
159 folder++;
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 = cp + 1;
168 else {
169 fprintf(stderr, "Only %d folders allowed.\n", NFOLD);
170 goto leave;
171 }
172 } else
173 msgs[msgp++] = cp;
174 }
175 if(grepp == grep) {
176 fprintf(stderr, "No search pattern specified.\n");
177 goto leave;
178 }
179 if(filef && keepf) {
180 fprintf(stderr, "-file and -keep don't go together.\n");
181 goto leave;
182 }
183 if(!scanf && !showf && !filef)
184 keepf++; /* The default is -keep */
185 if(keepf) {
186 prsrvf++; /* -keep forces -preserve */
187 linkf++; /* and -link */
188 }
189 if(!folder)
190 folder = m_getfolder(); /* use cur folder if no -src */
191 copy(m_maildir(folder), maildir);
192 if(chdir(maildir) < 0) {
193 fprintf(stderr, "Can't chdir to: ");
194 perror(maildir);
195 goto leave;
196 }
197 if(!(mp = m_gmsg(folder))) {
198 fprintf(stderr, "Can't read folder!?\n");
199 goto leave;
200 }
201 if(mp->hghmsg == 0) {
202 fprintf(stderr, "No messages in \"%s\".\n", folder);
203 goto leave;
204 }
205 if(!foldp) { /* if no +folder given... */
206 if(filef) { /* -file requires one */
207 fprintf(stderr, "-file requires at least one folder arg.\n");
208 goto leave;
209 }
210 if(keepf) { /* use default selection-list name */
211 copy(listname, copy("/", copy(folder, buf)));
212 folders[foldp++].f_name = getcpy(buf);
213 noteold++; /* tell user if existing folder */
214 }
215 } else if(keepf) { /* make folders sub-folders */
216 for(msgnum = 0; msgnum < foldp; msgnum++)
217 if(*(cp = folders[msgnum].f_name) != '.' &&
218 *cp != '/') {
219 copy(cp, copy("/", copy(folder, buf)));
220 folders[msgnum].f_name = getcpy(buf);
221 }
222 noteold++;
223 }
224 if(!msgp)
225 msgs[msgp++] = "first-last";
226 for(msgnum = 0; msgnum < msgp; msgnum++)
227 if(!m_convert(msgs[msgnum]))
228 goto leave;
229 if(mp->numsel == 0) {
230 fprintf(stderr, "pick: Peanut butter 'n jelly\n");/* never get here */
231 goto leave;
232 }
233 if(!compile(grep)) {
234 fprintf(stderr, "Pattern Error.\n");
235 goto leave;
236 }
237 for(msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
238 if(mp->msgstats[msgnum]&SELECTED)
239 grepfn(msgnum);
240 if(mp->numsel == 0) {
241 fprintf(stderr, "No messages match specification.\n");
242 goto leave;
243 }
244 mp->lowsel = grep_lowsel;
245 mp->hghsel = grep_hghsel;
246 /* all the exec's */
247 if((((delprog = m_find("delete-prog")) != NULL) &&
248 ((filef || keepf) && !linkf)) ||
249 scanf || showf) {
250 if(mp->numsel > MAXARGS-2) {
251 fprintf(stderr, "pick: more than %d messages for %s exec\n",
252 MAXARGS-2,
253 scanf ? "scan" : showf ? "show" : delprog);
254 goto leave;
255 }
256 nvec = (char **) malloc(MAXARGS * sizeof nvec[0]);
257 for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
258 if(mp->msgstats[msgnum]&SELECTED)
259 nvec[nvecp++] = getcpy(m_name(msgnum));
260 nvec[nvecp] = 0;
261 }
262 if(keepf || filef)
263 if(opnfolds())
264 goto leave;
265 if(!noteold || foldp > 1)
266 m_replace(pfolder, folder);
267 if(scanf)
268 scanfn(showf|filef|keepf);
269 else {
270 printf("%d hits.\n", mp->numsel); fflush(stdout);
271 }
272 if(showf)
273 showfn(filef|keepf);
274 if(!(filef|keepf))
275 goto leave;
276 for(msgnum= mp->lowsel; msgnum<= mp->hghsel; msgnum++)
277 if(mp->msgstats[msgnum]&SELECTED)
278 if(process(cp = getcpy(m_name(msgnum))))
279 goto leave;
280 else
281 free (cp);
282 if(!linkf)
283 remove();
284 if(noteold) {
285 if(!stayf && foldp == 1) {
286 m_replace(pfolder, cp = folders[0].f_name);
287 printf("[+%s now current]\n", cp); fflush(stdout);
288 }
289 for(fptr = folders; fptr < &folders[foldp]; fptr++)
290 if(!fptr->f_reused) {
291 chdir(m_maildir(fptr->f_name));
292 m_setcur(fptr->f_mp->curmsg);
293 }
294 }
295 leave:
296 m_update();
297 }
298
299
300 grepfn(msg)
301 {
302 if(execute(m_name(msg))) { /* a match */
303 if(msg < grep_lowsel)
304 grep_lowsel = msg;
305 if(msg > grep_hghsel)
306 grep_hghsel = msg;
307 } else {
308 mp->msgstats[msg] &= ~SELECTED; /* clear SELECTED bit */
309 mp->numsel--;
310 }
311 }
312
313
314 opnfolds()
315 {
316 register int i;
317 register char *cp, *ap;
318 char nmaildir[128];
319 struct stat stbuf;
320
321 for(i = 0; i < foldp; i++) {
322 copy(m_maildir(cp = folders[i].f_name), nmaildir);
323 if(stat(nmaildir, &stbuf) < 0) {
324 if(!noteold) {
325 ap = concat("Create folder \"",
326 nmaildir, "\"? ", 0);
327 if(!gans(ap, anoyes))
328 return(1);
329 }
330 if(!makedir(nmaildir)) {
331 fprintf(stderr, "Can't create folder.\n");
332 return(1);
333 }
334 } else if(noteold) {
335 printf("[Folder %s being re-used.]\n", cp);
336 fflush(stdout);
337 folders[i].f_reused++; /* Don't change cur in old fold */
338 }
339 if(chdir(nmaildir) < 0) {
340 fprintf(stderr, "Can't chdir to: ");
341 perror(nmaildir);
342 return(1);
343 }
344 if(!(folders[i].f_mp = m_gmsg(folders[i].f_name))) {
345 fprintf(stderr, "Can't read folder %s\n", folders[i].f_name);
346 return(1);
347 }
348 folders[i].f_mp->curmsg = 0;
349 }
350 chdir(maildir); /* return to src folder */
351 return(0);
352 }
353
354
355 scanfn(forkf)
356 {
357 register int pid, i;
358
359 nvec[0] = "mh-scan";
360 if(forkf && (pid = fork())) {
361 if(pid == -1) {
362 fprintf(stderr, "No forks!\n");
363 done(1);
364 }
365 while(wait((int *)NULL) != pid) ;
366 } else {
367 m_update();
368 fflush(stdout);
369 execv(scanproc, nvec);
370 perror(scanproc);
371 done(1);
372 }
373 }
374
375
376 showfn(forkf)
377 {
378 register int pid, i;
379 int sint, sqit;
380
381 nvec[0] = "c:mh-type";
382 if(forkf) {
383 sint = (int) signal(SIGINT, SIG_IGN);
384 sqit = (int) signal(SIGQUIT, SIG_IGN);
385 }
386 if(forkf && (pid = fork())) {
387 if(pid == -1) {
388 fprintf(stderr, "No forks!\n");
389 done(1);
390 }
391 while(wait((int *)NULL) != pid) ;
392 signal(SIGINT, sint);
393 signal(SIGQUIT, sqit);
394 } else {
395 m_update();
396 fflush(stdout);
397 execv(showproc, nvec);
398 perror(showproc);
399 done(1);
400 }
401 }
402
403
404 remove()
405 {
406 register int i, j;
407 register char *cp;
408
409 if(delprog != NULL) {
410 nvec[0] = delprog;
411 m_update();
412 fflush(stdout);
413 execv(nvec[0], nvec);
414 fprintf(stderr, "Can't exec deletion-prog--");
415 perror(delprog);
416 } else {
417 for(i= mp->lowsel; i<= mp->hghsel; i++)
418 if(mp->msgstats[i]&SELECTED)
419 if(unlink(cp = m_name(i)) == -1) {
420 fprintf(stderr, "Can't unlink %s:",folder);
421 perror(cp);
422 }
423 }
424 }
425
426 process(msg)
427 char *msg;
428 {
429 char newmsg[256], buf[BUFSIZ];
430 register int i;
431 register char *nmsg;
432 register struct st_fold *fp;
433 struct stat stbuf, stbf1;
434 int n, o, linkerr;
435
436 for(fp = folders; fp < &folders[foldp]; fp++) {
437 if(prsrvf)
438 nmsg = msg;
439 else
440 nmsg = m_name(fp->f_mp->hghmsg++ + 1);
441 copy(nmsg, copy("/", copy(m_maildir(fp->f_name), newmsg)));
442 if(link(msg, newmsg) < 0) {
443 linkerr = errno;
444 if(linkerr == EEXIST ||
445 (linkerr == EXDEV && stat(newmsg, &stbuf) != -1)) {
446 if(linkerr != EEXIST || stat(msg, &stbf1) < 0 ||
447 stat(newmsg, &stbuf) < 0 ||
448 stbf1.st_ino != stbuf.st_ino) {
449 fprintf(stderr, "Message %s:%s already exists.\n",
450 fp->f_name, msg);
451 return(1);
452 }
453 continue;
454 }
455 if(linkerr == EXDEV) {
456 if((o = open(msg, 0)) == -1) {
457 fprintf(stderr, "Can't open %s:%s.\n",
458 folder, msg);
459 return(1);
460 }
461 fstat(o, &stbuf);
462 if((n = creat(newmsg, stbuf.st_mode&0777)) == -1) {
463 fprintf(stderr, "Can't create %s:%s.\n",
464 fp->f_name, nmsg);
465 close(o);
466 return(1);
467 }
468 do
469 if((i=read(o, buf, sizeof buf)) < 0 ||
470 write(n, buf, i) == -1) {
471 fprintf(stderr, "Copy error on %s:%s to %s:%s!\n",
472 folder, msg, fp->f_name, nmsg);
473 close(o); close(n);
474 return(1);
475 }
476 while(i == sizeof buf);
477 close(n); close(o);
478 } else {
479 fprintf(stderr, "Error on link %s:%s to %s:",
480 folder, msg, fp->f_name);
481 perror(nmsg);
482 return(1);
483 }
484 }
485 if((i = atoi(nmsg)) < fp->f_mp->curmsg || !fp->f_mp->curmsg)
486 fp->f_mp->curmsg = i;
487 cont: ;
488 }
489 return(0);
490 }