Mercurial > hg > Applications > mh
comparison uip/mshcmds.c @ 0:bce86c4163a3
Initial revision
author | kono |
---|---|
date | Mon, 18 Apr 2005 23:46:02 +0900 |
parents | |
children | a6481689f99c |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:bce86c4163a3 |
---|---|
1 /* mshcmds.c - command handlers in msh */ | |
2 #ifndef lint | |
3 static char ident[] = "@(#)$Id$"; | |
4 #endif /* lint */ | |
5 | |
6 #include "../h/mh.h" | |
7 #include "../h/dropsbr.h" | |
8 #include "../h/formatsbr.h" | |
9 #include "../h/scansbr.h" | |
10 #include "../zotnet/tws.h" | |
11 #ifdef _AIX /* AIX 1.2.1 <stdio.h> declares getws() */ | |
12 #define getws _getws | |
13 #endif | |
14 #include <stdio.h> | |
15 #ifdef _AIX | |
16 #undef getws | |
17 #endif | |
18 #include "../zotnet/mts.h" | |
19 #include <ctype.h> | |
20 #include <errno.h> | |
21 #include <setjmp.h> | |
22 #include <signal.h> | |
23 #include <sys/types.h> | |
24 #include <sys/stat.h> | |
25 #include "../h/mshsbr.h" | |
26 #ifdef MIME | |
27 #include "../h/mhn.h" | |
28 #endif /* MIME */ | |
29 | |
30 /* */ | |
31 | |
32 extern int errno; | |
33 | |
34 /* BURST */ | |
35 static char delim3[] = "-------";/* from burst.c */ | |
36 | |
37 | |
38 /* SHOW */ | |
39 static int mhlnum; | |
40 static FILE *mhlfp; | |
41 | |
42 void clear_screen (); | |
43 static int eom_action (); | |
44 static FP mhl_action (); | |
45 #ifdef MIME | |
46 static int nontext(); | |
47 #endif | |
48 | |
49 | |
50 static burst(), forw(), rmm(), show(), ask(), copy_message(), copy_digest(); | |
51 static int process(); | |
52 /* SORTM */ | |
53 static int msgsort (), subsort(); | |
54 static int getws (); | |
55 static char *sosmash (); | |
56 | |
57 #if defined(NNTP) && defined(MPOP) | |
58 #undef MPOP | |
59 #endif | |
60 #ifdef MPOP | |
61 #ifdef BPOP | |
62 extern int pmsh; | |
63 extern char response[]; | |
64 #endif | |
65 #endif /* MPOP */ | |
66 | |
67 /* */ | |
68 | |
69 forkcmd (args, pgm) | |
70 char **args, | |
71 *pgm; | |
72 { | |
73 int child_id; | |
74 char *vec[MAXARGS]; | |
75 | |
76 vec[0] = r1bindex (pgm, '/'); | |
77 (void) copyip (args, vec + 1); | |
78 | |
79 if (fmsh) { | |
80 (void) m_delete (pfolder); | |
81 m_replace (pfolder, fmsh); | |
82 m_sync (mp); | |
83 m_update (); | |
84 } | |
85 (void) fflush (stdout); | |
86 switch (child_id = fork ()) { | |
87 case NOTOK: | |
88 advise ("fork", "unable to"); | |
89 return; | |
90 | |
91 case OK: | |
92 closefds (3); | |
93 (void) signal (SIGINT, istat); | |
94 (void) signal (SIGQUIT, qstat); | |
95 | |
96 execvp (pgm, vec); | |
97 fprintf (stderr, "unable to exec "); | |
98 perror (cmd_name); | |
99 _exit (1); | |
100 | |
101 default: | |
102 (void) pidXwait (child_id, NULLCP); | |
103 break; | |
104 } | |
105 if (fmsh) { /* assume the worst case */ | |
106 mp -> msgflags |= MODIFIED; | |
107 modified++; | |
108 } | |
109 } | |
110 | |
111 /* */ | |
112 | |
113 static struct swit distswit[] = { | |
114 #define DIANSW 0 | |
115 "annotate", 0, | |
116 #define DINANSW 1 | |
117 "noannotate", 0, | |
118 #define DIDFSW 2 | |
119 "draftfolder +folder", 0, | |
120 #define DIDMSW 3 | |
121 "draftmessage msg", 0, | |
122 #define DINDFSW 4 | |
123 "nodraftfolder", 0, | |
124 #define DIEDTSW 5 | |
125 "editor editor", 0, | |
126 #define DINEDSW 6 | |
127 "noedit", 0, | |
128 #define DIFRMSW 7 | |
129 "form formfile", 0, | |
130 #define DIINSW 8 | |
131 "inplace", 0, | |
132 #define DININSW 9 | |
133 "noinplace", 0, | |
134 #define DIWHTSW 10 | |
135 "whatnowproc program", 0, | |
136 #define DINWTSW 11 | |
137 "nowhatnowproc", 0, | |
138 #define DIHELP 12 | |
139 "help", 4, | |
140 | |
141 NULL, 0 | |
142 }; | |
143 | |
144 /* */ | |
145 | |
146 distcmd (args) | |
147 char **args; | |
148 { | |
149 int vecp = 1; | |
150 char *cp, | |
151 *msg = NULL, | |
152 buf[BUFSIZ], | |
153 *vec[MAXARGS]; | |
154 | |
155 if (fmsh) { | |
156 forkcmd (args, cmd_name); | |
157 return; | |
158 } | |
159 | |
160 while (cp = *args++) { | |
161 if (*cp == '-') | |
162 switch (smatch (++cp, distswit)) { | |
163 case AMBIGSW: | |
164 ambigsw (cp, distswit); | |
165 return; | |
166 case UNKWNSW: | |
167 fprintf (stderr, "-%s unknown\n", cp); | |
168 return; | |
169 case DIHELP: | |
170 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
171 help (buf, distswit); | |
172 return; | |
173 | |
174 case DIANSW: /* not implemented */ | |
175 case DINANSW: | |
176 case DIINSW: | |
177 case DININSW: | |
178 continue; | |
179 | |
180 case DINDFSW: | |
181 case DINEDSW: | |
182 case DINWTSW: | |
183 vec[vecp++] = --cp; | |
184 continue; | |
185 | |
186 case DIEDTSW: | |
187 case DIFRMSW: | |
188 case DIDFSW: | |
189 case DIDMSW: | |
190 case DIWHTSW: | |
191 vec[vecp++] = --cp; | |
192 if (!(cp = *args++) || *cp == '-') { | |
193 advise (NULLCP, "missing argument to %s", args[-2]); | |
194 return; | |
195 } | |
196 vec[vecp++] = cp; | |
197 continue; | |
198 } | |
199 if (*cp == '+' || *cp == '@') { | |
200 advise (NULLCP, "sorry, no folders allowed!"); | |
201 return; | |
202 } | |
203 else | |
204 if (msg) { | |
205 advise (NULLCP, "only one message at a time!"); | |
206 return; | |
207 } | |
208 else | |
209 msg = cp; | |
210 } | |
211 | |
212 vec[0] = cmd_name; | |
213 vec[vecp++] = "-file"; | |
214 vec[vecp] = NULL; | |
215 if (!msg) | |
216 msg = "cur"; | |
217 if (!m_convert (mp, msg)) | |
218 return; | |
219 m_setseq (mp); | |
220 | |
221 if (mp -> numsel > 1) { | |
222 advise (NULLCP, "only one message at a time!"); | |
223 return; | |
224 } | |
225 (void) process (mp -> hghsel, cmd_name, vecp, vec); | |
226 m_setcur (mp, mp -> hghsel); | |
227 } | |
228 | |
229 /* */ | |
230 | |
231 static struct swit explswit[] = { | |
232 #define EXINSW 0 | |
233 "inplace", 0, | |
234 #define EXNINSW 1 | |
235 "noinplace", 0, | |
236 #define EXQISW 2 | |
237 "quiet", 0, | |
238 #define EXNQISW 3 | |
239 "noquiet", 0, | |
240 #define EXVBSW 4 | |
241 "verbose", 0, | |
242 #define EXNVBSW 5 | |
243 "noverbose", 0, | |
244 #define EXHELP 6 | |
245 "help", 4, | |
246 | |
247 NULL, 0 | |
248 }; | |
249 | |
250 /* */ | |
251 | |
252 explcmd (args) | |
253 char **args; | |
254 { | |
255 int inplace = 0, | |
256 quietsw = 0, | |
257 verbosw = 0, | |
258 msgp = 0, | |
259 hi, | |
260 msgnum; | |
261 char *cp, | |
262 buf[BUFSIZ], | |
263 *msgs[MAXARGS]; | |
264 struct Msg *smsgs; | |
265 | |
266 if (fmsh) { | |
267 forkcmd (args, cmd_name); | |
268 return; | |
269 } | |
270 | |
271 while (cp = *args++) { | |
272 if (*cp == '-') | |
273 switch (smatch (++cp, explswit)) { | |
274 case AMBIGSW: | |
275 ambigsw (cp, explswit); | |
276 return; | |
277 case UNKWNSW: | |
278 fprintf (stderr, "-%s unknown\n", cp); | |
279 return; | |
280 case EXHELP: | |
281 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
282 help (buf, explswit); | |
283 return; | |
284 | |
285 case EXINSW: | |
286 inplace++; | |
287 continue; | |
288 case EXNINSW: | |
289 inplace = 0; | |
290 continue; | |
291 case EXQISW: | |
292 quietsw++; | |
293 continue; | |
294 case EXNQISW: | |
295 quietsw = 0; | |
296 continue; | |
297 case EXVBSW: | |
298 verbosw++; | |
299 continue; | |
300 case EXNVBSW: | |
301 verbosw = 0; | |
302 continue; | |
303 } | |
304 if (*cp == '+' || *cp == '@') { | |
305 advise (NULLCP, "sorry, no folders allowed!"); | |
306 return; | |
307 } | |
308 else | |
309 msgs[msgp++] = cp; | |
310 } | |
311 | |
312 if (!msgp) | |
313 msgs[msgp++] = "cur"; | |
314 for (msgnum = 0; msgnum < msgp; msgnum++) | |
315 if (!m_convert (mp, msgs[msgnum])) | |
316 return; | |
317 m_setseq (mp); | |
318 | |
319 smsgs = (struct Msg *) | |
320 calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs); | |
321 if (smsgs == NULL) | |
322 adios (NULLCP, "unable to allocate folder storage"); | |
323 | |
324 hi = mp -> hghmsg + 1; | |
325 interrupted = 0; | |
326 for (msgnum = mp -> lowsel; | |
327 msgnum <= mp -> hghsel && !interrupted; | |
328 msgnum++) | |
329 if (mp -> msgstats[msgnum] & SELECTED) | |
330 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK) | |
331 break; | |
332 | |
333 free ((char *) smsgs); | |
334 | |
335 if (inplace) | |
336 m_setcur (mp, mp -> lowsel); | |
337 else | |
338 if (hi <= mp -> hghmsg) | |
339 m_setcur (mp, hi); | |
340 | |
341 mp -> msgflags |= MODIFIED; | |
342 modified++; | |
343 } | |
344 | |
345 /* */ | |
346 | |
347 static burst (smsgs, msgnum, inplace, quietsw, verbosw) | |
348 struct Msg *smsgs; | |
349 int msgnum, | |
350 inplace, | |
351 quietsw, | |
352 verbosw; | |
353 { | |
354 int i, | |
355 j, | |
356 ld3, | |
357 wasdlm, | |
358 msgp; | |
359 long pos; | |
360 char c, | |
361 cc, | |
362 buffer[BUFSIZ]; | |
363 register FILE *zp; | |
364 | |
365 ld3 = strlen (delim3); | |
366 | |
367 if (Msgs[msgnum].m_scanl) { | |
368 free (Msgs[msgnum].m_scanl); | |
369 Msgs[msgnum].m_scanl = NULL; | |
370 } | |
371 | |
372 pos = ftell (zp = msh_ready (msgnum, 1)); | |
373 for (msgp = 0; msgp <= MAXFOLDER;) { | |
374 while (fgets (buffer, sizeof buffer, zp) != NULL | |
375 && buffer[0] == '\n' | |
376 && pos < Msgs[msgnum].m_stop) | |
377 pos += (long) strlen (buffer); | |
378 if (feof (zp) || pos >= Msgs[msgnum].m_stop) | |
379 break; | |
380 (void) fseek (zp, pos, 0); | |
381 smsgs[msgp].m_start = pos; | |
382 | |
383 for (c = 0; | |
384 pos < Msgs[msgnum].m_stop | |
385 && fgets (buffer, sizeof buffer, zp) != NULL; | |
386 c = buffer[0]) | |
387 if (strncmp (buffer, delim3, ld3) == 0 | |
388 && (msgp == 1 || c == '\n') | |
389 && peekc (zp) == '\n') | |
390 break; | |
391 else | |
392 pos += (long) strlen (buffer); | |
393 | |
394 wasdlm = strncmp (buffer, delim3, ld3) == 0; | |
395 if (smsgs[msgp].m_start != pos) | |
396 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos; | |
397 if (feof (zp) || pos >= Msgs[msgnum].m_stop) { | |
398 if (wasdlm) | |
399 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1); | |
400 break; | |
401 } | |
402 pos += (long) strlen (buffer); | |
403 } | |
404 | |
405 switch (msgp--) { /* toss "End of XXX Digest" */ | |
406 case 0: | |
407 adios (NULLCP, "burst() botch -- you lose big"); | |
408 | |
409 case 1: | |
410 if (!quietsw) | |
411 printf ("message %d not in digest format\n", msgnum); | |
412 return OK; | |
413 | |
414 default: | |
415 if (verbosw) | |
416 printf ("%d message%s exploded from digest %d\n", | |
417 msgp, msgp != 1 ? "s" : "", msgnum); | |
418 break; | |
419 } | |
420 | |
421 if ((i = msgp + mp -> hghmsg) > MAXFOLDER) { | |
422 advise (NULLCP, "more than %d messages", MAXFOLDER); | |
423 return NOTOK; | |
424 } | |
425 if ((mp = m_remsg (mp, 0, i)) == NULL) | |
426 adios (NULLCP, "unable to allocate folder storage"); | |
427 | |
428 j = mp -> hghmsg; | |
429 mp -> hghmsg += msgp; | |
430 mp -> nummsg += msgp; | |
431 if (mp -> hghsel > msgnum) | |
432 mp -> hghsel += msgp; | |
433 | |
434 if (inplace) | |
435 for (i = mp -> hghmsg; j > msgnum; i--, j--) { | |
436 if (verbosw) | |
437 printf ("message %d becomes message %d\n", j, i); | |
438 | |
439 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id; | |
440 Msgs[i].m_top = Msgs[j].m_top; | |
441 Msgs[i].m_start = Msgs[j].m_start; | |
442 Msgs[i].m_stop = Msgs[j].m_stop; | |
443 Msgs[i].m_scanl = NULL; | |
444 if (Msgs[j].m_scanl) { | |
445 free (Msgs[j].m_scanl); | |
446 Msgs[j].m_scanl = NULL; | |
447 } | |
448 mp -> msgstats[i] = mp -> msgstats[j]; | |
449 } | |
450 | |
451 if (Msgs[msgnum].m_bboard_id == 0) | |
452 (void) readid (msgnum); | |
453 | |
454 mp -> msgstats[msgnum] &= ~SELECTED; | |
455 i = inplace ? msgnum + msgp : mp -> hghmsg; | |
456 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) { | |
457 if (verbosw && i != msgnum) | |
458 printf ("message %d of digest %d becomes message %d\n", | |
459 j, msgnum, i); | |
460 | |
461 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id; | |
462 Msgs[i].m_top = Msgs[j].m_top; | |
463 Msgs[i].m_start = smsgs[j].m_start; | |
464 Msgs[i].m_stop = smsgs[j].m_stop; | |
465 Msgs[i].m_scanl = NULL; | |
466 mp -> msgstats[i] = mp -> msgstats[msgnum]; | |
467 } | |
468 | |
469 return OK; | |
470 } | |
471 | |
472 /* */ | |
473 | |
474 static struct swit fileswit[] = { | |
475 #define FIDRFT 0 | |
476 "draft", 0, | |
477 #define FILINK 1 | |
478 "link", 0, | |
479 #define FINLINK 2 | |
480 "nolink", 0, | |
481 #define FIPRES 3 | |
482 "preserve", 0, | |
483 #define FINPRES 4 | |
484 "nopreserve", 0, | |
485 #define FISRC 5 | |
486 "src +folder", 0, | |
487 #define FIFILE 6 | |
488 "file file", 0, | |
489 #define FIPROC 7 | |
490 "rmmproc program", 0, | |
491 #define FINPRC 8 | |
492 "normmproc", 0, | |
493 #define FIHELP 9 | |
494 "help", 4, | |
495 | |
496 NULL, 0 | |
497 }; | |
498 | |
499 /* */ | |
500 | |
501 filecmd (args) | |
502 char **args; | |
503 { | |
504 int linksw = 0, | |
505 msgp = 0, | |
506 vecp = 1, | |
507 i, | |
508 msgnum; | |
509 char *cp, | |
510 buf[BUFSIZ], | |
511 *msgs[MAXARGS], | |
512 *vec[MAXARGS]; | |
513 | |
514 if (fmsh) { | |
515 forkcmd (args, cmd_name); | |
516 return; | |
517 } | |
518 | |
519 while (cp = *args++) { | |
520 if (*cp == '-') | |
521 switch (i = smatch (++cp, fileswit)) { | |
522 case AMBIGSW: | |
523 ambigsw (cp, fileswit); | |
524 return; | |
525 case UNKWNSW: | |
526 fprintf (stderr, "-%s unknown\n", cp); | |
527 return; | |
528 case FIHELP: | |
529 (void) sprintf (buf, "%s +folder... [msgs] [switches]", | |
530 cmd_name); | |
531 help (buf, fileswit); | |
532 return; | |
533 | |
534 case FILINK: | |
535 linksw++; | |
536 continue; | |
537 case FINLINK: | |
538 linksw = 0; | |
539 continue; | |
540 | |
541 case FIPRES: | |
542 case FINPRES: | |
543 continue; | |
544 | |
545 case FISRC: | |
546 case FIDRFT: | |
547 case FIFILE: | |
548 case FIPROC: | |
549 case FINPRC: | |
550 advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw); | |
551 return; | |
552 } | |
553 if (*cp == '+' || *cp == '@') | |
554 vec[vecp++] = cp; | |
555 else | |
556 msgs[msgp++] = cp; | |
557 } | |
558 | |
559 vec[0] = cmd_name; | |
560 vec[vecp++] = "-file"; | |
561 vec[vecp] = NULL; | |
562 if (!msgp) | |
563 msgs[msgp++] = "cur"; | |
564 for (msgnum = 0; msgnum < msgp; msgnum++) | |
565 if (!m_convert (mp, msgs[msgnum])) | |
566 return; | |
567 m_setseq (mp); | |
568 | |
569 interrupted = 0; | |
570 for (msgnum = mp -> lowsel; | |
571 msgnum <= mp -> hghsel && !interrupted; | |
572 msgnum++) | |
573 if (mp -> msgstats[msgnum] & SELECTED) | |
574 if (process (msgnum, fileproc, vecp, vec)) { | |
575 mp -> msgstats[msgnum] &= ~SELECTED; | |
576 mp -> numsel--; | |
577 } | |
578 | |
579 if (mp -> numsel != mp -> nummsg || linksw) | |
580 m_setcur (mp, mp -> hghsel); | |
581 if (!linksw) | |
582 rmm (); | |
583 } | |
584 | |
585 /* */ | |
586 | |
587 int filehak (args) | |
588 char **args; | |
589 { | |
590 int result, | |
591 vecp = 0; | |
592 char *cp, | |
593 *cwd, | |
594 *vec[MAXARGS]; | |
595 | |
596 while (cp = *args++) { | |
597 if (*cp == '-') | |
598 switch (smatch (++cp, fileswit)) { | |
599 case AMBIGSW: | |
600 case UNKWNSW: | |
601 case FIHELP: | |
602 return NOTOK; | |
603 | |
604 case FILINK: | |
605 case FINLINK: | |
606 case FIPRES: | |
607 case FINPRES: | |
608 continue; | |
609 | |
610 case FISRC: | |
611 case FIDRFT: | |
612 case FIFILE: | |
613 return NOTOK; | |
614 } | |
615 if (*cp == '+' || *cp == '@') | |
616 vec[vecp++] = cp; | |
617 } | |
618 vec[vecp] = NULL; | |
619 | |
620 result = NOTOK; | |
621 cwd = NULL; | |
622 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) { | |
623 if (cwd == NULL) | |
624 cwd = getcpy (pwd ()); | |
625 (void) chdir (m_maildir ("")); | |
626 cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); | |
627 if (access (m_maildir (cp), 0) == NOTOK) | |
628 result = OK; | |
629 free (cp); | |
630 } | |
631 if (cwd) | |
632 (void) chdir (cwd); | |
633 | |
634 return result; | |
635 } | |
636 | |
637 /* */ | |
638 | |
639 static struct swit foldswit[] = { | |
640 #define FLALSW 0 | |
641 "all", 0, | |
642 #define FLFASW 1 | |
643 "fast", 0, | |
644 #define FLNFASW 2 | |
645 "nofast", 0, | |
646 #define FLHDSW 3 | |
647 "header", 0, | |
648 #define FLNHDSW 4 | |
649 "noheader", 0, | |
650 #define FLPKSW 5 | |
651 "pack", 0, | |
652 #define FLNPKSW 6 | |
653 "nopack", 0, | |
654 #define FLRCSW 7 | |
655 "recurse", 0, | |
656 #define FLNRCSW 8 | |
657 "norecurse", 0, | |
658 #define FLTLSW 9 | |
659 "total", 0, | |
660 #define FLNTLSW 10 | |
661 "nototal", 0, | |
662 #define FLPRSW 11 | |
663 "print", 0, | |
664 #define FLPUSW 12 | |
665 "push", 0, | |
666 #define FLPOSW 13 | |
667 "pop", 0, | |
668 #define FLLISW 14 | |
669 "list", 0, | |
670 #define FLHELP 15 | |
671 "help", 4, | |
672 | |
673 NULL, 0 | |
674 }; | |
675 | |
676 /* */ | |
677 | |
678 foldcmd (args) | |
679 char **args; | |
680 { | |
681 int fastsw = 0, | |
682 headersw = 0, | |
683 packsw = 0, | |
684 hole, | |
685 msgnum; | |
686 char *cp, | |
687 *folder = NULL, | |
688 *msg = NULL, | |
689 buf[BUFSIZ], | |
690 **vec = args; | |
691 | |
692 if (args == NULL) | |
693 goto fast; | |
694 | |
695 while (cp = *args++) { | |
696 if (*cp == '-') | |
697 switch (smatch (++cp, foldswit)) { | |
698 case AMBIGSW: | |
699 ambigsw (cp, foldswit); | |
700 return; | |
701 case UNKWNSW: | |
702 fprintf (stderr, "-%s unknown\n", cp); | |
703 return; | |
704 case FLHELP: | |
705 (void) sprintf (buf, "%s [+folder] [msg] [switches]", | |
706 cmd_name); | |
707 help (buf, foldswit); | |
708 return; | |
709 | |
710 case FLALSW: /* not implemented */ | |
711 case FLRCSW: | |
712 case FLNRCSW: | |
713 case FLTLSW: | |
714 case FLNTLSW: | |
715 case FLPRSW: | |
716 case FLPUSW: | |
717 case FLPOSW: | |
718 case FLLISW: | |
719 continue; | |
720 | |
721 case FLFASW: | |
722 fastsw++; | |
723 continue; | |
724 case FLNFASW: | |
725 fastsw = 0; | |
726 continue; | |
727 case FLHDSW: | |
728 headersw++; | |
729 continue; | |
730 case FLNHDSW: | |
731 headersw = 0; | |
732 continue; | |
733 case FLPKSW: | |
734 packsw++; | |
735 continue; | |
736 case FLNPKSW: | |
737 packsw = 0; | |
738 continue; | |
739 } | |
740 if (*cp == '+' || *cp == '@') | |
741 if (folder) { | |
742 advise (NULLCP, "only one folder at a time!\n"); | |
743 return; | |
744 } | |
745 else | |
746 folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF) | |
747 : cp + 1; | |
748 else | |
749 if (msg) { | |
750 advise (NULLCP, "only one message at a time!\n"); | |
751 return; | |
752 } | |
753 else | |
754 msg = cp; | |
755 } | |
756 | |
757 if (folder) { | |
758 if (*folder == 0) { | |
759 advise (NULLCP, "null folder names are not permitted"); | |
760 return; | |
761 } | |
762 if (fmsh) { | |
763 if (access (m_maildir (folder), 04) == NOTOK) { | |
764 advise (folder, "unable to read"); | |
765 return; | |
766 } | |
767 } | |
768 else { | |
769 (void) strcpy (buf, folder); | |
770 if (expand (buf) == NOTOK) | |
771 return; | |
772 folder = buf; | |
773 if (access (folder, 04) == NOTOK) { | |
774 advise (folder, "unable to read"); | |
775 return; | |
776 } | |
777 } | |
778 m_reset (); | |
779 | |
780 if (fmsh) | |
781 fsetup (folder); | |
782 else | |
783 setup (folder); | |
784 readids (0); | |
785 display_info (0); | |
786 } | |
787 | |
788 if (msg) { | |
789 if (!m_convert (mp, msg)) | |
790 return; | |
791 m_setseq (mp); | |
792 | |
793 if (mp -> numsel > 1) { | |
794 advise (NULLCP, "only one message at a time!"); | |
795 return; | |
796 } | |
797 m_setcur (mp, mp -> hghsel); | |
798 } | |
799 | |
800 if (packsw) { | |
801 if (fmsh) { | |
802 forkcmd (vec, cmd_name); | |
803 return; | |
804 } | |
805 | |
806 if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL) | |
807 adios (NULLCP, "unable to allocate folder storage"); | |
808 for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++) | |
809 if (mp -> msgstats[msgnum] & EXISTS) { | |
810 if (msgnum != hole) { | |
811 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id; | |
812 Msgs[hole].m_top = Msgs[msgnum].m_top; | |
813 Msgs[hole].m_start = Msgs[msgnum].m_start; | |
814 Msgs[hole].m_stop = Msgs[msgnum].m_stop; | |
815 Msgs[hole].m_scanl = NULL; | |
816 if (Msgs[msgnum].m_scanl) { | |
817 free (Msgs[msgnum].m_scanl); | |
818 Msgs[msgnum].m_scanl = NULL; | |
819 } | |
820 mp -> msgstats[hole] = mp -> msgstats[msgnum]; | |
821 if (mp -> curmsg == msgnum) | |
822 m_setcur (mp, hole); | |
823 } | |
824 hole++; | |
825 } | |
826 if (mp -> nummsg > 0) { | |
827 mp -> lowmsg = 1; | |
828 mp -> hghmsg = hole - 1; | |
829 } | |
830 mp -> msgflags |= MODIFIED; | |
831 modified++; | |
832 } | |
833 | |
834 fast: ; | |
835 if (fastsw) | |
836 printf ("%s\n", fmsh ? fmsh : mp -> foldpath); | |
837 else { | |
838 if (headersw) | |
839 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n", | |
840 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "", | |
841 DMAXFOLDER - 2, ""); | |
842 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath); | |
843 if (mp -> hghmsg == 0) | |
844 printf ("has no messages%*s", | |
845 mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, ""); | |
846 else { | |
847 printf ("has %*d message%s (%*d-%*d)", | |
848 DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "", | |
849 DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg); | |
850 if (mp -> curmsg >= mp -> lowmsg | |
851 && mp -> curmsg <= mp -> hghmsg) | |
852 printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg); | |
853 } | |
854 printf (".\n"); | |
855 } | |
856 } | |
857 | |
858 /* */ | |
859 | |
860 #ifndef MIME | |
861 #define MIMEminc(a) (a) | |
862 #else /* MIME */ | |
863 #define MIMEminc(a) 0 | |
864 #endif /* MIME */ | |
865 | |
866 static struct swit forwswit[] = { | |
867 #define FOANSW 0 | |
868 "annotate", 0, | |
869 #define FONANSW 1 | |
870 "noannotate", 0, | |
871 #define FODFSW 2 | |
872 "draftfolder +folder", 0, | |
873 #define FODMSW 3 | |
874 "draftmessage msg", 0, | |
875 #define FONDFSW 4 | |
876 "nodraftfolder", 0, | |
877 #define FOEDTSW 5 | |
878 "editor editor", 0, | |
879 #define FONEDSW 6 | |
880 "noedit", 0, | |
881 #define FOFTRSW 7 | |
882 "filter filterfile", 0, | |
883 #define FOFRMSW 8 | |
884 "form formfile", 0, | |
885 #define FOFTSW 9 | |
886 "format", 5, | |
887 #define FONFTSW 10 | |
888 "noformat", 7, | |
889 #define FOINSW 11 | |
890 "inplace", 0, | |
891 #define FONINSW 12 | |
892 "noinplace", 0, | |
893 #define FOMISW 13 | |
894 "mime", MIMEminc(-4), | |
895 #define FONMISW 14 | |
896 "nomime", MIMEminc(-6), | |
897 #define FOWHTSW 15 | |
898 "whatnowproc program", 0, | |
899 #define FONWTSW 16 | |
900 "nowhatnow", 0, | |
901 #define FOHELP 17 | |
902 "help", 4, | |
903 | |
904 NULL, 0 | |
905 }; | |
906 | |
907 /* */ | |
908 | |
909 forwcmd (args) | |
910 char **args; | |
911 { | |
912 int msgp = 0, | |
913 vecp = 1, | |
914 mime = 0, | |
915 msgnum; | |
916 char *cp, | |
917 *filter = NULL, | |
918 buf[BUFSIZ], | |
919 *msgs[MAXARGS], | |
920 *vec[MAXARGS]; | |
921 char *mktemp (); | |
922 | |
923 if (fmsh) { | |
924 forkcmd (args, cmd_name); | |
925 return; | |
926 } | |
927 | |
928 while (cp = *args++) { | |
929 if (*cp == '-') | |
930 switch (smatch (++cp, forwswit)) { | |
931 case AMBIGSW: | |
932 ambigsw (cp, forwswit); | |
933 return; | |
934 case UNKWNSW: | |
935 fprintf (stderr, "-%s unknown\n", cp); | |
936 return; | |
937 case FOHELP: | |
938 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
939 help (buf, forwswit); | |
940 return; | |
941 | |
942 case FOANSW: /* not implemented */ | |
943 case FONANSW: | |
944 case FOINSW: | |
945 case FONINSW: | |
946 continue; | |
947 | |
948 case FOMISW: | |
949 #ifdef MIME | |
950 mime = 1; | |
951 filter = NULL; | |
952 #endif /* MIME */ | |
953 continue; | |
954 case FONMISW: | |
955 mime = 0; | |
956 continue; | |
957 | |
958 case FONDFSW: | |
959 case FONEDSW: | |
960 case FONWTSW: | |
961 vec[vecp++] = --cp; | |
962 continue; | |
963 | |
964 case FOEDTSW: | |
965 case FOFRMSW: | |
966 case FODFSW: | |
967 case FODMSW: | |
968 case FOWHTSW: | |
969 vec[vecp++] = --cp; | |
970 if (!(cp = *args++) || *cp == '-') { | |
971 advise (NULLCP, "missing argument to %s", args[-2]); | |
972 return; | |
973 } | |
974 vec[vecp++] = cp; | |
975 continue; | |
976 case FOFTRSW: | |
977 if (!(filter = *args++) || *filter == '-') { | |
978 advise (NULLCP, "missing argument to %s", args[-2]); | |
979 return; | |
980 } | |
981 mime = 0; | |
982 continue; | |
983 case FOFTSW: | |
984 if (access (filter = myfilter, 04) == NOTOK) { | |
985 advise (filter, "unable to read default filter file"); | |
986 return; | |
987 } | |
988 continue; | |
989 case FONFTSW: | |
990 filter = NULL; | |
991 continue; | |
992 } | |
993 if (*cp == '+' || *cp == '@') { | |
994 advise (NULLCP, "sorry, no folders allowed!"); | |
995 return; | |
996 } | |
997 else | |
998 msgs[msgp++] = cp; | |
999 } | |
1000 | |
1001 /* foil search of .mh_profile */ | |
1002 (void) sprintf (buf, "%sXXXXXX", invo_name); | |
1003 vec[0] = (char *)mktemp (buf); | |
1004 vec[vecp++] = "-file"; | |
1005 vec[vecp] = NULL; | |
1006 if (!msgp) | |
1007 msgs[msgp++] = "cur"; | |
1008 for (msgnum = 0; msgnum < msgp; msgnum++) | |
1009 if (!m_convert (mp, msgs[msgnum])) | |
1010 return; | |
1011 m_setseq (mp); | |
1012 | |
1013 if (filter) { | |
1014 (void) strcpy (buf, filter); | |
1015 if (expand (buf) == NOTOK) | |
1016 return; | |
1017 if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) { | |
1018 advise (filter, "unable to read"); | |
1019 free (filter); | |
1020 return; | |
1021 } | |
1022 } | |
1023 forw (cmd_name, filter, vecp, vec, mime); | |
1024 m_setcur (mp, mp -> hghsel); | |
1025 if (filter) | |
1026 free (filter); | |
1027 } | |
1028 | |
1029 /* */ | |
1030 | |
1031 static forw (proc, filter, vecp, vec, mime) | |
1032 int vecp, | |
1033 mime; | |
1034 char *proc, | |
1035 *filter, | |
1036 **vec; | |
1037 { | |
1038 int i, | |
1039 child_id, | |
1040 msgnum, | |
1041 msgcnt; | |
1042 char tmpfil[80], | |
1043 *args[MAXARGS]; | |
1044 FILE *out; | |
1045 #ifdef MIME | |
1046 int nedit = 0; | |
1047 char *ed = NULL; | |
1048 #endif /* MIME */ | |
1049 | |
1050 (void) strcpy (tmpfil, m_tmpfil (invo_name)); | |
1051 interrupted = 0; | |
1052 if (filter) | |
1053 switch (child_id = fork ()) { | |
1054 case NOTOK: | |
1055 advise ("fork", "unable to"); | |
1056 return; | |
1057 | |
1058 case OK: /* "trust me" */ | |
1059 if (freopen (tmpfil, "w", stdout) == NULL) { | |
1060 fprintf (stderr, "unable to create "); | |
1061 perror (tmpfil); | |
1062 _exit (1); | |
1063 } | |
1064 args[0] = r1bindex (mhlproc, '/'); | |
1065 i = 1; | |
1066 args[i++] = "-forwall"; | |
1067 args[i++] = "-form"; | |
1068 args[i++] = filter; | |
1069 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
1070 if (mp -> msgstats[msgnum] & SELECTED) | |
1071 args[i++] = getcpy (m_name (msgnum)); | |
1072 args[i] = NULL; | |
1073 (void) mhlsbr (i, args, mhl_action); | |
1074 m_eomsbr ((int (*) ()) 0); | |
1075 (void) fclose (stdout); | |
1076 _exit (0); | |
1077 | |
1078 default: | |
1079 if (pidXwait (child_id, NULLCP)) | |
1080 interrupted++; | |
1081 break; | |
1082 } | |
1083 #ifdef MIME | |
1084 else if (mime) { | |
1085 int isdf = 0, | |
1086 len, | |
1087 nwhat = 0; | |
1088 #define INITIAL_PREFIX "----- =_aaaaaaaaaa" | |
1089 char *cp, | |
1090 *form = NULL, | |
1091 buffer[BUFSIZ], | |
1092 prefix[sizeof INITIAL_PREFIX]; | |
1093 FILE *zp; | |
1094 | |
1095 proc = whatnowproc; | |
1096 for (vecp = 1; cp = vec[vecp++]; ) | |
1097 if (*cp == '-') | |
1098 switch (smatch (++cp, forwswit)) { | |
1099 case FOEDTSW: | |
1100 ed = vec[vecp++]; | |
1101 nedit = 0; | |
1102 continue; | |
1103 case FONEDSW: | |
1104 nedit++; | |
1105 continue; | |
1106 | |
1107 case FOFRMSW: | |
1108 form = vec[vecp++]; | |
1109 continue; | |
1110 | |
1111 case FOWHTSW: | |
1112 proc = vec[vecp++]; | |
1113 nwhat = 0; | |
1114 continue; | |
1115 case FONWTSW: | |
1116 nwhat++; | |
1117 continue; | |
1118 | |
1119 /* ignore -draftfolder / -draftmessage / -nodraftfolder */ | |
1120 case FODFSW: | |
1121 case FODMSW: | |
1122 vecp++; | |
1123 case FONDFSW: | |
1124 continue; | |
1125 } | |
1126 (void) strcpy (tmpfil, m_draft (NULLCP, NULLCP, NOUSE, &isdf)); | |
1127 if (!ed && !(ed = m_find ("editor"))) | |
1128 ed = sysed; | |
1129 | |
1130 (void) strcpy (prefix, INITIAL_PREFIX); | |
1131 cp = index (prefix, 'a'); | |
1132 len = strlen (prefix); | |
1133 | |
1134 for (;;) { | |
1135 int hit = 0; | |
1136 long pos; | |
1137 | |
1138 for (msgnum = mp -> lowsel; | |
1139 msgnum <= mp -> hghsel && !interrupted && !hit; | |
1140 msgnum++) | |
1141 if (mp -> msgstats[msgnum] & SELECTED) { | |
1142 zp = msh_ready (msgnum, 1); | |
1143 if (!fmsh) | |
1144 pos = ftell (zp); | |
1145 while (fgets (buffer, sizeof buffer, zp) != NULL | |
1146 && !fmsh | |
1147 && pos < Msgs[msgnum].m_stop) { | |
1148 register char *pp; | |
1149 | |
1150 if (buffer[0] != '-' || buffer[1] != '-') | |
1151 continue; | |
1152 | |
1153 for (pp = buffer + strlen (buffer) - 1; | |
1154 pp >= buffer; | |
1155 pp--) | |
1156 if (!isspace (*pp)) | |
1157 break; | |
1158 *pp++ = '\0'; | |
1159 | |
1160 if (strncmp (buffer + 2, prefix, len)) | |
1161 continue; | |
1162 | |
1163 hit = 1; | |
1164 break; | |
1165 } | |
1166 } | |
1167 | |
1168 if (!hit) | |
1169 break; | |
1170 | |
1171 if (*cp < 'z') | |
1172 (*cp)++; | |
1173 else | |
1174 if (*++cp == 0) { | |
1175 advise (NULLCP, | |
1176 "unable to determine unique delimiter string?!?"); | |
1177 return; | |
1178 } | |
1179 else | |
1180 (*cp)++; | |
1181 } | |
1182 | |
1183 if ((out = fopen (tmpfil, "w")) == NULL) { | |
1184 advise (tmpfil, "unable to create temporary file"); | |
1185 return; | |
1186 } | |
1187 (void) chmod (tmpfil, m_gmprot ()); | |
1188 | |
1189 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE); | |
1190 fprintf (out, "%s: multipart/digest; boundary=\"%s\"\n", TYPE_FIELD, | |
1191 prefix); | |
1192 | |
1193 if (!(zp = fopen (libpath (form ? form : forwcomps), "r"))) { | |
1194 if (form) | |
1195 advise (form, "unable to open form file"); | |
1196 else | |
1197 advise (forwcomps, "unable to open default components file"); | |
1198 (void) fclose (out); | |
1199 (void) unlink (tmpfil); | |
1200 return; | |
1201 } | |
1202 while (fgets (buffer, sizeof buffer, zp)) | |
1203 (void) fputs (buffer, out); | |
1204 (void) fclose (zp); | |
1205 | |
1206 for (msgnum = mp -> lowsel; | |
1207 msgnum <= mp -> hghsel && !interrupted; | |
1208 msgnum++) | |
1209 if (mp -> msgstats[msgnum] & SELECTED) { | |
1210 fprintf (out, "\n--%s\n%s: message/rfc822\n\n", prefix, | |
1211 TYPE_FIELD); | |
1212 | |
1213 copy_message (msgnum, out); | |
1214 } | |
1215 fprintf (out, "\n--%s--\n", prefix); | |
1216 | |
1217 (void) fclose (out); | |
1218 if (nwhat) | |
1219 return; | |
1220 } | |
1221 #endif /* MIME */ | |
1222 else { | |
1223 if ((out = fopen (tmpfil, "w")) == NULL) { | |
1224 advise (tmpfil, "unable to create temporary file"); | |
1225 return; | |
1226 } | |
1227 | |
1228 msgcnt = 1; | |
1229 for (msgnum = mp -> lowsel; | |
1230 msgnum <= mp -> hghsel && !interrupted; | |
1231 msgnum++) | |
1232 if (mp -> msgstats[msgnum] & SELECTED) { | |
1233 fprintf (out, "\n\n-------"); | |
1234 if (msgnum == mp -> lowsel) | |
1235 fprintf (out, " Forwarded Message%s", | |
1236 mp -> numsel > 1 ? "s" : ""); | |
1237 else | |
1238 fprintf (out, " Message %d", msgcnt); | |
1239 fprintf (out, "\n\n"); | |
1240 copy_digest (msgnum, out); | |
1241 msgcnt++; | |
1242 } | |
1243 | |
1244 fprintf (out, "\n\n------- End of Forwarded Message%s\n", | |
1245 mp -> numsel > 1 ? "s" : ""); | |
1246 (void) fclose (out); | |
1247 } | |
1248 | |
1249 (void) fflush (stdout); | |
1250 if (!interrupted) | |
1251 switch (child_id = fork ()) { | |
1252 case NOTOK: | |
1253 advise ("fork", "unable to"); | |
1254 break; | |
1255 | |
1256 case OK: | |
1257 closefds (3); | |
1258 (void) signal (SIGINT, istat); | |
1259 (void) signal (SIGQUIT, qstat); | |
1260 | |
1261 #ifdef MIME | |
1262 if (mime) { | |
1263 vecp = 0; | |
1264 vec[vecp++] = r1bindex (proc, '/'); | |
1265 (void) m_putenv ("mhdraft", tmpfil); | |
1266 (void) unputenv ("mhfolder"); | |
1267 (void) unputenv ("mhaltmsg"); | |
1268 (void) m_putenv ("mhdist", "0"); | |
1269 if (nedit) | |
1270 (void) unputenv ("mheditor"); | |
1271 else | |
1272 (void) m_putenv ("mheditor", ed); | |
1273 (void) m_putenv ("mhuse", "0"); | |
1274 (void) unputenv ("mhmessages"); | |
1275 (void) unputenv ("mhannotate"); | |
1276 (void) unputenv ("mhinplace"); | |
1277 } | |
1278 else | |
1279 #endif /* MIME */ | |
1280 | |
1281 vec[vecp++] = tmpfil; | |
1282 vec[vecp] = NULL; | |
1283 | |
1284 execvp (proc, vec); | |
1285 fprintf (stderr, "unable to exec "); | |
1286 perror (proc); | |
1287 _exit (1); | |
1288 | |
1289 default: | |
1290 (void) pidXwait (child_id, NULLCP); | |
1291 break; | |
1292 } | |
1293 | |
1294 #ifdef MIME | |
1295 if (!mime) | |
1296 #endif /* MIME */ | |
1297 (void) unlink (tmpfil); | |
1298 } | |
1299 | |
1300 /* */ | |
1301 | |
1302 static char *hlpmsg[] = { | |
1303 "The %s program emulates many of the commands found in the Rand MH", | |
1304 "system. Instead of operating on MH folders, commands to %s concern", | |
1305 "a single file.", | |
1306 "", | |
1307 "To see the list of commands available, just type a ``?'' followed by", | |
1308 "the RETURN key. To find out what switches each command takes, type", | |
1309 "the name of the command followed by ``-help''. To leave %s, use the", | |
1310 "``quit'' command.", | |
1311 "", | |
1312 "Although a lot of MH commands are found in %s, not all are fully", | |
1313 "implemented. %s will always recognize all legal switches for a", | |
1314 "given command though, and will let you know when you ask for an", | |
1315 "option that it is unable to perform.", | |
1316 "", | |
1317 "Running %s is fun, but using MH from your shell is far superior.", | |
1318 "After you have familiarized yourself with the MH style by using %s,", | |
1319 "you should try using MH from the shell. You can still use %s for", | |
1320 "message files that aren't in MH format, such as BBoard files.", | |
1321 NULL | |
1322 }; | |
1323 | |
1324 | |
1325 /* ARGSUSED */ | |
1326 | |
1327 helpcmd (args) | |
1328 char **args; | |
1329 { | |
1330 int i; | |
1331 | |
1332 for (i = 0; hlpmsg[i]; i++) { | |
1333 printf (hlpmsg[i], invo_name); | |
1334 (void) putchar ('\n'); | |
1335 } | |
1336 } | |
1337 | |
1338 /* */ | |
1339 | |
1340 static struct swit markswit[] = { | |
1341 #define MADDSW 0 | |
1342 "add", 0, | |
1343 #define MDELSW 1 | |
1344 "delete", 0, | |
1345 #define MLSTSW 2 | |
1346 "list", 0, | |
1347 #define MSEQSW 3 | |
1348 "sequence name", 0, | |
1349 #define MPUBSW 4 | |
1350 "public", 0, | |
1351 #define MNPUBSW 5 | |
1352 "nopublic", 0, | |
1353 #define MZERSW 6 | |
1354 "zero", 0, | |
1355 #define MNZERSW 7 | |
1356 "nozero", 0, | |
1357 #define MHELP 8 | |
1358 "help", 4, | |
1359 #define MDBUGSW 9 | |
1360 "debug", -5, | |
1361 | |
1362 NULL, 0 | |
1363 }; | |
1364 | |
1365 /* */ | |
1366 | |
1367 markcmd (args) | |
1368 char **args; | |
1369 { | |
1370 int addsw = 0, | |
1371 deletesw = 0, | |
1372 debugsw = 0, | |
1373 listsw = 0, | |
1374 zerosw = 0, | |
1375 seqp = 0, | |
1376 msgp = 0, | |
1377 i, | |
1378 msgnum; | |
1379 char *cp, | |
1380 buf[BUFSIZ], | |
1381 *seqs[NATTRS + 1], | |
1382 *msgs[MAXARGS]; | |
1383 | |
1384 while (cp = *args++) { | |
1385 if (*cp == '-') | |
1386 switch (smatch (++cp, markswit)) { | |
1387 case AMBIGSW: | |
1388 ambigsw (cp, markswit); | |
1389 return; | |
1390 case UNKWNSW: | |
1391 fprintf (stderr, "-%s unknown\n", cp); | |
1392 return; | |
1393 case MHELP: | |
1394 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
1395 help (buf, markswit); | |
1396 return; | |
1397 | |
1398 case MADDSW: | |
1399 addsw++; | |
1400 deletesw = listsw = 0; | |
1401 continue; | |
1402 case MDELSW: | |
1403 deletesw++; | |
1404 addsw = listsw = 0; | |
1405 continue; | |
1406 case MLSTSW: | |
1407 listsw++; | |
1408 addsw = deletesw = 0; | |
1409 continue; | |
1410 | |
1411 case MSEQSW: | |
1412 if (!(cp = *args++) || *cp == '-') { | |
1413 advise (NULLCP, "missing argument to %s", args[-2]); | |
1414 return; | |
1415 } | |
1416 if (seqp < NATTRS) | |
1417 seqs[seqp++] = cp; | |
1418 else { | |
1419 advise (NULLCP, "only %d sequences allowed!", NATTRS); | |
1420 return; | |
1421 } | |
1422 continue; | |
1423 | |
1424 case MPUBSW: /* not implemented */ | |
1425 case MNPUBSW: | |
1426 continue; | |
1427 | |
1428 case MDBUGSW: | |
1429 debugsw++; | |
1430 continue; | |
1431 | |
1432 case MZERSW: | |
1433 zerosw++; | |
1434 continue; | |
1435 case MNZERSW: | |
1436 zerosw = 0; | |
1437 continue; | |
1438 } | |
1439 if (*cp == '+' || *cp == '@') { | |
1440 advise (NULLCP, "sorry, no folders allowed!"); | |
1441 return; | |
1442 } | |
1443 else | |
1444 msgs[msgp++] = cp; | |
1445 } | |
1446 | |
1447 if (!addsw && !deletesw && !listsw) | |
1448 if (seqp) | |
1449 addsw++; | |
1450 else | |
1451 if (debugsw) | |
1452 listsw++; | |
1453 else { | |
1454 seqs[seqp++] = "unseen"; | |
1455 deletesw++; | |
1456 zerosw = 0; | |
1457 if (!msgp) | |
1458 msgs[msgp++] = "all"; | |
1459 } | |
1460 | |
1461 if (!msgp) | |
1462 msgs[msgp++] = listsw ? "all" :"cur"; | |
1463 for (msgnum = 0; msgnum < msgp; msgnum++) | |
1464 if (!m_convert (mp, msgs[msgnum])) | |
1465 return; | |
1466 | |
1467 if (debugsw) { | |
1468 printf ("invo_name=%s mypath=%s defpath=%s\n", | |
1469 invo_name, mypath, defpath); | |
1470 printf ("ctxpath=%s context flags=%s\n", | |
1471 ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS)); | |
1472 printf ("foldpath=%s flags=%s\n", | |
1473 mp -> foldpath, | |
1474 sprintb (buf, (unsigned) mp -> msgflags, FBITS)); | |
1475 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n", | |
1476 mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg); | |
1477 printf ("lowsel=%d hghsel=%d numsel=%d\n", | |
1478 mp -> lowsel, mp -> hghsel, mp -> numsel); | |
1479 #ifndef MTR | |
1480 printf ("lowoff=%d hghoff=%d\n", | |
1481 mp -> lowoff, mp -> hghoff); | |
1482 #else /* MTR */ | |
1483 printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n", | |
1484 mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats); | |
1485 #endif /* MTR */ | |
1486 } | |
1487 | |
1488 if (seqp == 0 && (addsw || deletesw)) { | |
1489 advise (NULLCP, "-%s requires at least one -sequence argument", | |
1490 addsw ? "add" : "delete"); | |
1491 return; | |
1492 } | |
1493 seqs[seqp] = NULL; | |
1494 | |
1495 if (addsw) | |
1496 for (seqp = 0; seqs[seqp]; seqp++) { | |
1497 if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) | |
1498 return; | |
1499 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
1500 if (mp -> msgstats[msgnum] & SELECTED) | |
1501 if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) | |
1502 return; | |
1503 } | |
1504 | |
1505 if (deletesw) | |
1506 for (seqp = 0; seqs[seqp]; seqp++) { | |
1507 if (zerosw) | |
1508 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) | |
1509 if (mp -> msgstats[msgnum] & EXISTS) | |
1510 if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) | |
1511 return; | |
1512 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
1513 if (mp -> msgstats[msgnum] & SELECTED) | |
1514 if (!m_seqdel (mp, seqs[seqp], msgnum)) | |
1515 return; | |
1516 } | |
1517 | |
1518 if (listsw) { | |
1519 int bits = FFATTRSLOT; | |
1520 | |
1521 #define empty(s) ((s) ? (s) : "") | |
1522 if (seqp == 0) | |
1523 for (i = 0; mp -> msgattrs[i]; i++) | |
1524 printf ("%s%s: %s\n", mp -> msgattrs[i], | |
1525 mp -> attrstats & (1 << (bits + i)) | |
1526 ? " (private)" : "", | |
1527 empty(m_seq (mp, mp -> msgattrs[i]))); | |
1528 else | |
1529 for (seqp = 0; seqs[seqp]; seqp++) | |
1530 printf ("%s%s: %s\n", seqs[seqp], | |
1531 empty(m_seq (mp, seqs[seqp]))); | |
1532 #undef empty | |
1533 | |
1534 interrupted = 0; | |
1535 if (debugsw) | |
1536 for (msgnum = mp -> lowsel; | |
1537 msgnum <= mp -> hghsel && !interrupted; | |
1538 msgnum++) | |
1539 if (mp -> msgstats[msgnum] & SELECTED) { | |
1540 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n", | |
1541 DMAXFOLDER, msgnum, | |
1542 Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top, | |
1543 Msgs[msgnum].m_start, Msgs[msgnum].m_stop, | |
1544 sprintb (buf, (unsigned) mp -> msgstats[msgnum], | |
1545 m_seqbits (mp))); | |
1546 if (Msgs[msgnum].m_scanl) | |
1547 printf ("%s", Msgs[msgnum].m_scanl); | |
1548 } | |
1549 } | |
1550 } | |
1551 | |
1552 /* */ | |
1553 | |
1554 #ifdef MIME | |
1555 static struct swit mhnswit[] = { | |
1556 #define MHNAUTOSW 0 | |
1557 "auto", 0, | |
1558 #define MHNNAUTOSW 1 | |
1559 "noauto", 0, | |
1560 #define MHNDEBUGSW 2 | |
1561 "debug", -5, | |
1562 #define MHNEBCDICSW 3 | |
1563 "ebcdicsafe", 0, | |
1564 #define MHNNEBCDICSW 4 | |
1565 "noebcdicsafe", 0, | |
1566 #define MHNFORMSW 5 | |
1567 "form formfile", 4, | |
1568 #define MHNHEADSW 6 | |
1569 "headers", 0, | |
1570 #define MHNNHEADSW 7 | |
1571 "noheaders", 0, | |
1572 #define MHNLISTSW 8 | |
1573 "list", 0, | |
1574 #define MHNNLISTSW 9 | |
1575 "nolist", 0, | |
1576 #define MHNPARTSW 10 | |
1577 "part number", 0, | |
1578 #define MHNSIZESW 11 | |
1579 "realsize", 0, | |
1580 #define MHNNSIZESW 12 | |
1581 "norealsize", 0, | |
1582 #define MHNRFC934SW 13 | |
1583 "rfc934mode", 0, | |
1584 #define MHNNRFC934SW 14 | |
1585 "norfc934mode", 0, | |
1586 #define MHNSERIALSW 15 | |
1587 "serialonly", 0, | |
1588 #define MHNNSERIALSW 16 | |
1589 "noserialonly", 0, | |
1590 #define MHNSHOWSW 17 | |
1591 "show", 0, | |
1592 #define MHNNSHOWSW 18 | |
1593 "noshow", 0, | |
1594 #define MHNSTORESW 19 | |
1595 "store", 0, | |
1596 #define MHNNSTORESW 20 | |
1597 "nostore", 0, | |
1598 #define MHNTYPESW 21 | |
1599 "type content", 0, | |
1600 #define MHNVERBSW 22 | |
1601 "verbose", 0, | |
1602 #define MHNNVERBSW 23 | |
1603 "noverbose", 0, | |
1604 #define MHNHELPSW 24 | |
1605 "help", 4, | |
1606 #define MHNPROGSW 25 | |
1607 "moreproc program", -4, | |
1608 #define MHNNPROGSW 26 | |
1609 "nomoreproc", -3, | |
1610 #define MHNLENSW 27 | |
1611 "length lines", -4, | |
1612 #define MHNWIDSW 28 | |
1613 "width columns", -4, | |
1614 | |
1615 NULL, 0 | |
1616 }; | |
1617 | |
1618 /* */ | |
1619 | |
1620 mhncmd (args) | |
1621 char **args; | |
1622 { | |
1623 int msgp = 0, | |
1624 vecp = 1, | |
1625 i, | |
1626 msgnum; | |
1627 char *cp, | |
1628 buf[BUFSIZ], | |
1629 *msgs[MAXARGS], | |
1630 *vec[MAXARGS]; | |
1631 | |
1632 if (fmsh) { | |
1633 forkcmd (args, cmd_name); | |
1634 return; | |
1635 } | |
1636 | |
1637 while (cp = *args++) { | |
1638 if (*cp == '-') | |
1639 switch (smatch (++cp, mhnswit)) { | |
1640 case AMBIGSW: | |
1641 ambigsw (cp, mhnswit); | |
1642 return; | |
1643 case UNKWNSW: | |
1644 fprintf (stderr, "-%s unknown\n", cp); | |
1645 return; | |
1646 case MHNHELPSW: | |
1647 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
1648 help (buf, mhnswit); | |
1649 return; | |
1650 | |
1651 case MHNAUTOSW: | |
1652 case MHNNAUTOSW: | |
1653 case MHNDEBUGSW: | |
1654 case MHNEBCDICSW: | |
1655 case MHNNEBCDICSW: | |
1656 case MHNHEADSW: | |
1657 case MHNNHEADSW: | |
1658 case MHNLISTSW: | |
1659 case MHNNLISTSW: | |
1660 case MHNSIZESW: | |
1661 case MHNNSIZESW: | |
1662 case MHNRFC934SW: | |
1663 case MHNNRFC934SW: | |
1664 case MHNSERIALSW: | |
1665 case MHNNSERIALSW: | |
1666 case MHNSHOWSW: | |
1667 case MHNNSHOWSW: | |
1668 case MHNSTORESW: | |
1669 case MHNNSTORESW: | |
1670 case MHNVERBSW: | |
1671 case MHNNVERBSW: | |
1672 case MHNNPROGSW: | |
1673 vec[vecp++] = --cp; | |
1674 continue; | |
1675 | |
1676 case MHNFORMSW: | |
1677 case MHNPARTSW: | |
1678 case MHNTYPESW: | |
1679 case MHNPROGSW: | |
1680 case MHNLENSW: | |
1681 case MHNWIDSW: | |
1682 vec[vecp++] = --cp; | |
1683 if (!(cp = *args++) || *cp == '-') { | |
1684 advise (NULLCP, "missing argument to %s", args[-2]); | |
1685 return; | |
1686 } | |
1687 vec[vecp++] = cp; | |
1688 continue; | |
1689 } | |
1690 if (*cp == '+' || *cp == '@') { | |
1691 advise (NULLCP, "sorry, no folders allowed!"); | |
1692 return; | |
1693 } | |
1694 else | |
1695 msgs[msgp++] = cp; | |
1696 } | |
1697 | |
1698 vec[0] = cmd_name; | |
1699 vec[vecp++] = "-file"; | |
1700 vec[vecp] = NULL; | |
1701 if (!msgp) | |
1702 msgs[msgp++] = "cur"; | |
1703 for (msgnum = 0; msgnum < msgp; msgnum++) | |
1704 if (!m_convert (mp, msgs[msgnum])) | |
1705 return; | |
1706 m_setseq (mp); | |
1707 | |
1708 interrupted = 0; | |
1709 for (msgnum = mp -> lowsel; | |
1710 msgnum <= mp -> hghsel && !interrupted; | |
1711 msgnum++) | |
1712 if (mp -> msgstats[msgnum] & SELECTED) | |
1713 if (process (msgnum, cmd_name, vecp, vec)) { | |
1714 mp -> msgstats[msgnum] &= ~SELECTED; | |
1715 mp -> numsel--; | |
1716 } | |
1717 | |
1718 m_setcur (mp, mp -> hghsel); | |
1719 } | |
1720 | |
1721 /* */ | |
1722 | |
1723 #endif /* MIME */ | |
1724 static struct swit packswit[] = { | |
1725 #define PAFISW 0 | |
1726 "file name", 0, | |
1727 | |
1728 #define PAHELP 1 | |
1729 "help", 4, | |
1730 | |
1731 NULL, 0 | |
1732 }; | |
1733 | |
1734 /* */ | |
1735 | |
1736 packcmd (args) | |
1737 char **args; | |
1738 { | |
1739 int msgp = 0, | |
1740 md, | |
1741 msgnum; | |
1742 char *cp, | |
1743 *file = NULL, | |
1744 buf[BUFSIZ], | |
1745 *msgs[MAXARGS]; | |
1746 struct stat st; | |
1747 | |
1748 if (fmsh) { | |
1749 forkcmd (args, cmd_name); | |
1750 return; | |
1751 } | |
1752 | |
1753 while (cp = *args++) { | |
1754 if (*cp == '-') | |
1755 switch (smatch (++cp, packswit)) { | |
1756 case AMBIGSW: | |
1757 ambigsw (cp, packswit); | |
1758 return; | |
1759 case UNKWNSW: | |
1760 fprintf (stderr, "-%s unknown\n", cp); | |
1761 return; | |
1762 case PAHELP: | |
1763 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
1764 help (buf, packswit); | |
1765 return; | |
1766 | |
1767 case PAFISW: | |
1768 if (!(file = *args++) || *file == '-') { | |
1769 advise (NULLCP, "missing argument to %s", args[-2]); | |
1770 return; | |
1771 } | |
1772 continue; | |
1773 } | |
1774 if (*cp == '+' || *cp == '@') { | |
1775 advise (NULLCP, "sorry, no folders allowed!"); | |
1776 return; | |
1777 } | |
1778 else | |
1779 msgs[msgp++] = cp; | |
1780 } | |
1781 | |
1782 if (!file) | |
1783 file = "./msgbox"; | |
1784 file = path (file, TFILE); | |
1785 if (stat (file, &st) == NOTOK) { | |
1786 if (errno != ENOENT) { | |
1787 advise (file, "error on file"); | |
1788 goto done_pack; | |
1789 } | |
1790 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP)); | |
1791 free (cp); | |
1792 if (!md) | |
1793 goto done_pack; | |
1794 } | |
1795 | |
1796 if (!msgp) | |
1797 msgs[msgp++] = "all"; | |
1798 for (msgnum = 0; msgnum < msgp; msgnum++) | |
1799 if (!m_convert (mp, msgs[msgnum])) | |
1800 goto done_pack; | |
1801 m_setseq (mp); | |
1802 | |
1803 if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) { | |
1804 advise (file, "unable to open"); | |
1805 goto done_pack; | |
1806 } | |
1807 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
1808 if (mp -> msgstats[msgnum] & SELECTED) | |
1809 if (pack (file, md, msgnum) == NOTOK) | |
1810 break; | |
1811 (void) mbx_close (file, md); | |
1812 | |
1813 if (mp -> hghsel != mp -> curmsg) | |
1814 m_setcur (mp, mp -> lowsel); | |
1815 | |
1816 done_pack: ; | |
1817 free (file); | |
1818 } | |
1819 | |
1820 /* */ | |
1821 | |
1822 int pack (mailbox, md, msgnum) | |
1823 char *mailbox; | |
1824 int md, | |
1825 msgnum; | |
1826 { | |
1827 register FILE *zp; | |
1828 | |
1829 if (Msgs[msgnum].m_bboard_id == 0) | |
1830 (void) readid (msgnum); | |
1831 | |
1832 zp = msh_ready (msgnum, 1); | |
1833 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id, | |
1834 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1); | |
1835 } | |
1836 | |
1837 /* */ | |
1838 | |
1839 int packhak (args) | |
1840 char **args; | |
1841 { | |
1842 int result; | |
1843 char *cp, | |
1844 *file = NULL; | |
1845 | |
1846 while (cp = *args++) { | |
1847 if (*cp == '-') | |
1848 switch (smatch (++cp, packswit)) { | |
1849 case AMBIGSW: | |
1850 case UNKWNSW: | |
1851 case PAHELP: | |
1852 return NOTOK; | |
1853 | |
1854 case PAFISW: | |
1855 if (!(file = *args++) || *file == '-') | |
1856 return NOTOK; | |
1857 continue; | |
1858 } | |
1859 if (*cp == '+' || *cp == '@') | |
1860 return NOTOK; | |
1861 } | |
1862 | |
1863 file = path (file ? file : "./msgbox", TFILE); | |
1864 result = access (file, 0) == NOTOK ? OK : NOTOK; | |
1865 free (file); | |
1866 | |
1867 return result; | |
1868 } | |
1869 | |
1870 /* */ | |
1871 | |
1872 static struct swit pickswit[] = { | |
1873 #define PIANSW 0 | |
1874 "and", 0, | |
1875 #define PIORSW 1 | |
1876 "or", 0, | |
1877 #define PINTSW 2 | |
1878 "not", 0, | |
1879 #define PILBSW 3 | |
1880 "lbrace", 0, | |
1881 #define PIRBSW 4 | |
1882 "rbrace", 0, | |
1883 | |
1884 #define PICCSW 5 | |
1885 "cc pattern", 0, | |
1886 #define PIDASW 6 | |
1887 "date pattern", 0, | |
1888 #define PIFRSW 7 | |
1889 "from pattern", 0, | |
1890 #define PISESW 8 | |
1891 "search pattern", 0, | |
1892 #define PISUSW 9 | |
1893 "subject pattern", 0, | |
1894 #define PITOSW 10 | |
1895 "to pattern", 0, | |
1896 #define PIOTSW 11 | |
1897 "-othercomponent pattern", 15, | |
1898 #define PIAFSW 12 | |
1899 "after date", 0, | |
1900 #define PIBFSW 13 | |
1901 "before date", 0, | |
1902 #define PIDFSW 14 | |
1903 "datefield field", 5, | |
1904 #define PISQSW 15 | |
1905 "sequence name", 0, | |
1906 #define PIPUSW 16 | |
1907 "public", 0, | |
1908 #define PINPUSW 17 | |
1909 "nopublic", 0, | |
1910 #define PIZRSW 18 | |
1911 "zero", 0, | |
1912 #define PINZRSW 19 | |
1913 "nozero", 0, | |
1914 #define PILISW 20 | |
1915 "list", 0, | |
1916 #define PINLISW 21 | |
1917 "nolist", 0, | |
1918 #define PIHELP 22 | |
1919 "help", 4, | |
1920 | |
1921 NULL, 0 | |
1922 }; | |
1923 | |
1924 /* */ | |
1925 | |
1926 pickcmd (args) | |
1927 char **args; | |
1928 { | |
1929 int zerosw = 1, | |
1930 msgp = 0, | |
1931 seqp = 0, | |
1932 vecp = 0, | |
1933 hi, | |
1934 lo, | |
1935 msgnum; | |
1936 char *cp, | |
1937 buf[BUFSIZ], | |
1938 *msgs[MAXARGS], | |
1939 *seqs[NATTRS], | |
1940 *vec[MAXARGS]; | |
1941 register FILE *zp; | |
1942 | |
1943 while (cp = *args++) { | |
1944 if (*cp == '-') { | |
1945 if (*++cp == '-') { | |
1946 vec[vecp++] = --cp; | |
1947 goto pattern; | |
1948 } | |
1949 switch (smatch (cp, pickswit)) { | |
1950 case AMBIGSW: | |
1951 ambigsw (cp, pickswit); | |
1952 return; | |
1953 case UNKWNSW: | |
1954 fprintf (stderr, "-%s unknown\n", cp); | |
1955 return; | |
1956 case PIHELP: | |
1957 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
1958 help (buf, pickswit); | |
1959 return; | |
1960 | |
1961 case PICCSW: | |
1962 case PIDASW: | |
1963 case PIFRSW: | |
1964 case PISUSW: | |
1965 case PITOSW: | |
1966 case PIDFSW: | |
1967 case PIAFSW: | |
1968 case PIBFSW: | |
1969 case PISESW: | |
1970 vec[vecp++] = --cp; | |
1971 pattern: ; | |
1972 if (!(cp = *args++)) {/* allow -xyz arguments */ | |
1973 advise (NULLCP, "missing argument to %s", args[-2]); | |
1974 return; | |
1975 } | |
1976 vec[vecp++] = cp; | |
1977 continue; | |
1978 case PIOTSW: | |
1979 advise (NULLCP, "internal error!"); | |
1980 return; | |
1981 case PIANSW: | |
1982 case PIORSW: | |
1983 case PINTSW: | |
1984 case PILBSW: | |
1985 case PIRBSW: | |
1986 vec[vecp++] = --cp; | |
1987 continue; | |
1988 | |
1989 case PISQSW: | |
1990 if (!(cp = *args++) || *cp == '-') { | |
1991 advise (NULLCP, "missing argument to %s", args[-2]); | |
1992 return; | |
1993 } | |
1994 if (seqp < NATTRS) | |
1995 seqs[seqp++] = cp; | |
1996 else { | |
1997 advise (NULLCP, "only %d sequences allowed!", NATTRS); | |
1998 return; | |
1999 } | |
2000 continue; | |
2001 case PIZRSW: | |
2002 zerosw++; | |
2003 continue; | |
2004 case PINZRSW: | |
2005 zerosw = 0; | |
2006 continue; | |
2007 | |
2008 case PIPUSW: /* not implemented */ | |
2009 case PINPUSW: | |
2010 case PILISW: | |
2011 case PINLISW: | |
2012 continue; | |
2013 } | |
2014 } | |
2015 if (*cp == '+' || *cp == '@') { | |
2016 advise (NULLCP, "sorry, no folders allowed!"); | |
2017 return; | |
2018 } | |
2019 else | |
2020 msgs[msgp++] = cp; | |
2021 } | |
2022 vec[vecp] = NULL; | |
2023 | |
2024 if (!msgp) | |
2025 msgs[msgp++] = "all"; | |
2026 for (msgnum = 0; msgnum < msgp; msgnum++) | |
2027 if (!m_convert (mp, msgs[msgnum])) | |
2028 return; | |
2029 m_setseq (mp); | |
2030 | |
2031 interrupted = 0; | |
2032 if (!pcompile (vec, NULLCP)) | |
2033 return; | |
2034 | |
2035 lo = mp -> lowsel; | |
2036 hi = mp -> hghsel; | |
2037 | |
2038 for (msgnum = mp -> lowsel; | |
2039 msgnum <= mp -> hghsel && !interrupted; | |
2040 msgnum++) | |
2041 if (mp -> msgstats[msgnum] & SELECTED) { | |
2042 zp = msh_ready (msgnum, 1); | |
2043 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start, | |
2044 fmsh ? 0L : Msgs[msgnum].m_stop)) { | |
2045 if (msgnum < lo) | |
2046 lo = msgnum; | |
2047 if (msgnum > hi) | |
2048 hi = msgnum; | |
2049 } | |
2050 else { | |
2051 mp -> msgstats[msgnum] &= ~SELECTED; | |
2052 mp -> numsel--; | |
2053 } | |
2054 } | |
2055 | |
2056 if (interrupted) | |
2057 return; | |
2058 | |
2059 mp -> lowsel = lo; | |
2060 mp -> hghsel = hi; | |
2061 | |
2062 if (mp -> numsel <= 0) { | |
2063 advise (NULLCP, "no messages match specification"); | |
2064 return; | |
2065 } | |
2066 | |
2067 seqs[seqp] = NULL; | |
2068 for (seqp = 0; seqs[seqp]; seqp++) { | |
2069 if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) | |
2070 return; | |
2071 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2072 if (mp -> msgstats[msgnum] & SELECTED) | |
2073 if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) | |
2074 return; | |
2075 } | |
2076 | |
2077 printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s"); | |
2078 } | |
2079 | |
2080 /* */ | |
2081 | |
2082 static struct swit replswit[] = { | |
2083 #define REANSW 0 | |
2084 "annotate", 0, | |
2085 #define RENANSW 1 | |
2086 "noannotate", 0, | |
2087 #define RECCSW 2 | |
2088 "cc type", 0, | |
2089 #define RENCCSW 3 | |
2090 "nocc type", 0, | |
2091 #define REDFSW 4 | |
2092 "draftfolder +folder", 0, | |
2093 #define REDMSW 5 | |
2094 "draftmessage msg", 0, | |
2095 #define RENDFSW 6 | |
2096 "nodraftfolder", 0, | |
2097 #define REEDTSW 7 | |
2098 "editor editor", 0, | |
2099 #define RENEDSW 8 | |
2100 "noedit", 0, | |
2101 #define REFCCSW 9 | |
2102 "fcc +folder", 0, | |
2103 #define REFLTSW 10 | |
2104 "filter filterfile", 0, | |
2105 #define REFRMSW 11 | |
2106 "form formfile", 0, | |
2107 #define REINSW 12 | |
2108 "inplace", 0, | |
2109 #define RENINSW 13 | |
2110 "noinplace", 0, | |
2111 #define REQUSW 14 | |
2112 "query", 0, | |
2113 #define RENQUSW 15 | |
2114 "noquery", 0, | |
2115 #define REWHTSW 16 | |
2116 "whatnowproc program", 0, | |
2117 #define RENWTSW 17 | |
2118 "nowhatnow", 0, | |
2119 #define REWIDSW 19 | |
2120 "width columns", 0, | |
2121 #define REHELP 20 | |
2122 "help", 4, | |
2123 | |
2124 NULL, 0 | |
2125 }; | |
2126 | |
2127 /* */ | |
2128 | |
2129 replcmd (args) | |
2130 char **args; | |
2131 { | |
2132 int vecp = 1; | |
2133 char *cp, | |
2134 *msg = NULL, | |
2135 buf[BUFSIZ], | |
2136 *vec[MAXARGS]; | |
2137 | |
2138 if (fmsh) { | |
2139 forkcmd (args, cmd_name); | |
2140 return; | |
2141 } | |
2142 | |
2143 while (cp = *args++) { | |
2144 if (*cp == '-') | |
2145 switch (smatch (++cp, replswit)) { | |
2146 case AMBIGSW: | |
2147 ambigsw (cp, replswit); | |
2148 return; | |
2149 case UNKWNSW: | |
2150 fprintf (stderr, "-%s unknown\n", cp); | |
2151 return; | |
2152 case REHELP: | |
2153 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
2154 help (buf, replswit); | |
2155 return; | |
2156 | |
2157 case REANSW: /* not implemented */ | |
2158 case RENANSW: | |
2159 case REINSW: | |
2160 case RENINSW: | |
2161 continue; | |
2162 | |
2163 case REQUSW: | |
2164 case RENQUSW: | |
2165 case RENDFSW: | |
2166 case RENEDSW: | |
2167 case RENWTSW: | |
2168 vec[vecp++] = --cp; | |
2169 continue; | |
2170 | |
2171 case RECCSW: | |
2172 case RENCCSW: | |
2173 case REEDTSW: | |
2174 case REFCCSW: | |
2175 case REFLTSW: | |
2176 case REFRMSW: | |
2177 case REWIDSW: | |
2178 case REDFSW: | |
2179 case REDMSW: | |
2180 case REWHTSW: | |
2181 vec[vecp++] = --cp; | |
2182 if (!(cp = *args++) || *cp == '-') { | |
2183 advise (NULLCP, "missing argument to %s", args[-2]); | |
2184 return; | |
2185 } | |
2186 vec[vecp++] = cp; | |
2187 continue; | |
2188 } | |
2189 if (*cp == '+' || *cp == '@') { | |
2190 advise (NULLCP, "sorry, no folders allowed!"); | |
2191 return; | |
2192 } | |
2193 else | |
2194 if (msg) { | |
2195 advise (NULLCP, "only one message at a time!"); | |
2196 return; | |
2197 } | |
2198 else | |
2199 msg = cp; | |
2200 } | |
2201 | |
2202 vec[0] = cmd_name; | |
2203 vec[vecp++] = "-file"; | |
2204 vec[vecp] = NULL; | |
2205 if (!msg) | |
2206 msg = "cur"; | |
2207 if (!m_convert (mp, msg)) | |
2208 return; | |
2209 m_setseq (mp); | |
2210 | |
2211 if (mp -> numsel > 1) { | |
2212 advise (NULLCP, "only one message at a time!"); | |
2213 return; | |
2214 } | |
2215 (void) process (mp -> hghsel, cmd_name, vecp, vec); | |
2216 m_setcur (mp, mp -> hghsel); | |
2217 } | |
2218 | |
2219 /* */ | |
2220 | |
2221 static struct swit rmmswit[] = { | |
2222 #define RMHELP 0 | |
2223 "help", 4, | |
2224 | |
2225 NULL, 0 | |
2226 }; | |
2227 | |
2228 /* */ | |
2229 | |
2230 rmmcmd (args) | |
2231 char **args; | |
2232 { | |
2233 int msgp = 0, | |
2234 msgnum; | |
2235 char *cp, | |
2236 buf[BUFSIZ], | |
2237 *msgs[MAXARGS]; | |
2238 | |
2239 while (cp = *args++) { | |
2240 if (*cp == '-') | |
2241 switch (smatch (++cp, rmmswit)) { | |
2242 case AMBIGSW: | |
2243 ambigsw (cp, rmmswit); | |
2244 return; | |
2245 case UNKWNSW: | |
2246 fprintf (stderr, "-%s unknown\n", cp); | |
2247 return; | |
2248 case RMHELP: | |
2249 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
2250 help (buf, rmmswit); | |
2251 return; | |
2252 } | |
2253 if (*cp == '+' || *cp == '@') { | |
2254 advise (NULLCP, "sorry, no folders allowed!"); | |
2255 return; | |
2256 } | |
2257 else | |
2258 msgs[msgp++] = cp; | |
2259 } | |
2260 | |
2261 if (!msgp) | |
2262 msgs[msgp++] = "cur"; | |
2263 for (msgnum = 0; msgnum < msgp; msgnum++) | |
2264 if (!m_convert (mp, msgs[msgnum])) | |
2265 return; | |
2266 m_setseq (mp); | |
2267 | |
2268 rmm (); | |
2269 } | |
2270 | |
2271 /* */ | |
2272 | |
2273 #ifdef MH_PLUS | |
2274 struct msgs *opntrashf (); | |
2275 struct msgs *trash (); | |
2276 #endif /* MH_PLUS */ | |
2277 | |
2278 static rmm () { | |
2279 register int msgnum, | |
2280 vecp; | |
2281 register char *cp; | |
2282 char buffer[BUFSIZ], | |
2283 *vec[MAXARGS]; | |
2284 | |
2285 if (fmsh) { | |
2286 if (rmmproc) { | |
2287 if (mp -> numsel > MAXARGS - 1) { | |
2288 advise (NULLCP, "more than %d messages for %s exec", | |
2289 MAXARGS - 1, rmmproc); | |
2290 return; | |
2291 } | |
2292 vecp = 0; | |
2293 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2294 if (mp -> msgstats[msgnum] & SELECTED) | |
2295 vec[vecp++] = getcpy (m_name (msgnum)); | |
2296 vec[vecp] = NULL; | |
2297 forkcmd (vec, rmmproc); | |
2298 for (vecp = 0; vec[vecp]; vecp++) | |
2299 free (vec[vecp]); | |
2300 } | |
2301 else { | |
2302 #ifdef MH_PLUS | |
2303 int rmp; | |
2304 char *tfold; | |
2305 struct msgs *tmp; | |
2306 | |
2307 if ((tfold = m_find ("Trash-Folder"))) | |
2308 tmp = opntrashf (tfold, m_maildir (fmsh), &rmp); | |
2309 #endif /* MH_PLUS */ | |
2310 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2311 if (mp -> msgstats[msgnum] & SELECTED) { | |
2312 #ifdef MH_PLUS | |
2313 if (tfold) { | |
2314 tmp = trash (msgnum, tmp, rmp); | |
2315 continue; | |
2316 } | |
2317 #endif /* MH_PLUS */ | |
2318 (void) strcpy (buffer, m_backup (cp = m_name (msgnum))); | |
2319 if (rename (cp, buffer) == NOTOK) | |
2320 admonish (buffer, "unable to rename %s to", cp); | |
2321 } | |
2322 } | |
2323 } | |
2324 | |
2325 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2326 if (mp -> msgstats[msgnum] & SELECTED) { | |
2327 mp -> msgstats[msgnum] |= DELETED; | |
2328 mp -> msgstats[msgnum] &= ~EXISTS; | |
2329 #ifdef MPOP | |
2330 #ifdef BPOP | |
2331 if (pmsh && pop_dele (msgnum) != OK) | |
2332 fprintf (stderr, "%s", response); | |
2333 #endif | |
2334 #endif /* MPOP */ | |
2335 } | |
2336 | |
2337 if ((mp -> nummsg -= mp -> numsel) <= 0) { | |
2338 if (fmsh) | |
2339 admonish (NULLCP, "no messages remaining in +%s", fmsh); | |
2340 else | |
2341 admonish (NULLCP, "no messages remaining in %s", mp -> foldpath); | |
2342 mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0; | |
2343 } | |
2344 if (mp -> lowsel == mp -> lowmsg) { | |
2345 for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++) | |
2346 if (mp -> msgstats[msgnum] & EXISTS) | |
2347 break; | |
2348 mp -> lowmsg = msgnum; | |
2349 } | |
2350 if (mp -> hghsel == mp -> hghmsg) { | |
2351 for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--) | |
2352 if (mp -> msgstats[msgnum] & EXISTS) | |
2353 break; | |
2354 mp -> hghmsg = msgnum; | |
2355 } | |
2356 | |
2357 mp -> msgflags |= MODIFIED; | |
2358 modified++; | |
2359 } | |
2360 | |
2361 /* */ | |
2362 | |
2363 #ifdef MH_PLUS | |
2364 struct msgs * | |
2365 opntrashf (tfold, cwd, rmp) | |
2366 char *tfold, | |
2367 *cwd; | |
2368 int *rmp; | |
2369 { | |
2370 int len; | |
2371 char *tf, | |
2372 *cp, | |
2373 *trashdir; | |
2374 struct stat st; | |
2375 struct msgs *tmp; | |
2376 | |
2377 tf = path (*tfold == '+' || *tfold == '@' ? tfold + 1 : tfold, | |
2378 *tfold != '@' ? TFOLDER : TSUBCWF); | |
2379 if (*tfold == '@' && *(tfold + 1) != '/') { | |
2380 cp = tfold + 1; | |
2381 while (*cp) { | |
2382 if (strncmp (cp, "./", 2) == 0) | |
2383 cp += 2; | |
2384 else if (strncmp (cp, "../", 3) == 0) | |
2385 cp += 3; | |
2386 else | |
2387 break; | |
2388 } | |
2389 len = strlen(cp); | |
2390 if (strncmp(cwd + strlen(cwd) - len, cp, len) == 0) { | |
2391 trashdir = "."; | |
2392 tf = path ("./", TSUBCWF); | |
2393 } else | |
2394 trashdir = m_maildir (tf); | |
2395 } else | |
2396 trashdir = m_maildir (tf); | |
2397 if (strcmp(cwd, trashdir) == 0) | |
2398 trashdir = "."; | |
2399 *rmp = strcmp(trashdir, ".") ? 0 : 1; | |
2400 | |
2401 if (stat (trashdir, &st) == NOTOK) { | |
2402 if (errno != ENOENT) | |
2403 adios (trashdir, "error on folder"); | |
2404 cp = concat ("Create folder \"", trashdir, "\"? ", NULLCP); | |
2405 if (!getanswer (cp)) | |
2406 done (1); | |
2407 free (cp); | |
2408 if (!makedir (trashdir)) | |
2409 adios (NULLCP, "unable to create folder %s", trashdir); | |
2410 } | |
2411 if (chdir (trashdir) == NOTOK) | |
2412 adios (trashdir, "unable to change directory to"); | |
2413 if (!(tmp = m_gmsg (tf))) | |
2414 adios (NULLCP, "unable to read folder %s", tfold); | |
2415 tmp -> curmsg = 0; | |
2416 chdir (cwd); | |
2417 return tmp; | |
2418 } | |
2419 | |
2420 struct msgs * | |
2421 trash (msgnum, tmp, rmp) | |
2422 struct msgs *tmp; | |
2423 int msgnum, | |
2424 rmp; | |
2425 { | |
2426 int newnum; | |
2427 char *msg, | |
2428 newmsg[BUFSIZ]; | |
2429 | |
2430 if (rmp) { | |
2431 msg = m_name (msgnum); | |
2432 if (unlink (msg) == NOTOK) | |
2433 admonish (msg, "unable to unlink"); | |
2434 return tmp; | |
2435 } | |
2436 | |
2437 if (tmp -> hghmsg >= tmp -> hghoff) | |
2438 if (!(tmp = m_remsg (tmp, 0, tmp -> hghoff + MAXFOLDER))) | |
2439 adios (NULLCP, "unable to allocate folder storage"); | |
2440 | |
2441 newnum = ++tmp -> hghmsg; | |
2442 tmp -> nummsg++; | |
2443 tmp -> msgstats[newnum] |= EXISTS | SELECTED; | |
2444 if (tmp -> lowmsg == 0) | |
2445 tmp -> lowmsg = newnum; | |
2446 if (tmp -> lowsel == 0 || newnum < tmp -> lowsel) | |
2447 tmp -> lowsel = newnum; | |
2448 if (newnum > tmp -> hghsel) | |
2449 tmp -> hghsel = newnum; | |
2450 | |
2451 (void) sprintf (newmsg, "%s/%s", tmp -> foldpath, m_name (newnum)); | |
2452 msg = m_name (msgnum); | |
2453 if (rename (msg, newmsg) == NOTOK) { | |
2454 int in, out; | |
2455 struct stat st; | |
2456 if (stat (newmsg, &st) != NOTOK) { | |
2457 admonish (newmsg, "unable to rename %s to", msg); | |
2458 return tmp; | |
2459 } | |
2460 if ((in = open(msg, 0)) == NOTOK) { | |
2461 admonish (msg, "unable to open message"); | |
2462 return tmp; | |
2463 } | |
2464 (void) fstat (in, &st); | |
2465 if ((out = creat (newmsg, (int) st.st_mode & 0777)) == NOTOK) { | |
2466 admonish (newmsg, "unable to create"); | |
2467 (void) close (in); | |
2468 return tmp; | |
2469 } | |
2470 cpydata (in, out, msg, newmsg); | |
2471 (void) close (in); | |
2472 (void) close (out); | |
2473 if (unlink (msg) == NOTOK) | |
2474 admonish (msg, "unable to unlink"); | |
2475 } | |
2476 return tmp; | |
2477 } | |
2478 #endif /* MH_PLUS */ | |
2479 | |
2480 | |
2481 /* */ | |
2482 | |
2483 static struct swit scanswit[] = { | |
2484 #define SCCLR 0 | |
2485 "clear", 0, | |
2486 #define SCNCLR 1 | |
2487 "noclear", 0, | |
2488 #define SCFORM 2 | |
2489 "form formatfile", 0, | |
2490 #define SCFMT 3 | |
2491 "format string", 5, | |
2492 #define SCHEAD 4 | |
2493 "header", 0, | |
2494 #define SCNHEAD 5 | |
2495 "noheader", 0, | |
2496 #define SCWID 6 | |
2497 "width columns", 0, | |
2498 #define SCHELP 7 | |
2499 "help", 4, | |
2500 | |
2501 NULL, 0 | |
2502 }; | |
2503 | |
2504 /* */ | |
2505 | |
2506 scancmd (args) | |
2507 char **args; | |
2508 { | |
2509 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b) | |
2510 | |
2511 int clearsw = 0, | |
2512 headersw = 0, | |
2513 width = 0, | |
2514 msgp = 0, | |
2515 msgnum, | |
2516 optim, | |
2517 state; | |
2518 char *cp, | |
2519 *form = NULL, | |
2520 *format = NULL, | |
2521 buf[BUFSIZ], | |
2522 *nfs, | |
2523 *msgs[MAXARGS]; | |
2524 register FILE *zp; | |
2525 #ifdef MPOP | |
2526 #ifdef BPOP | |
2527 static int p_optim = 0; | |
2528 #endif | |
2529 #endif /* MPOP */ | |
2530 static int s_optim = 0; | |
2531 static char *s_form = NULL, | |
2532 *s_format = NULL; | |
2533 | |
2534 while (cp = *args++) { | |
2535 if (*cp == '-') | |
2536 switch (smatch (++cp, scanswit)) { | |
2537 case AMBIGSW: | |
2538 ambigsw (cp, scanswit); | |
2539 return; | |
2540 case UNKWNSW: | |
2541 fprintf (stderr, "-%s unknown\n", cp); | |
2542 return; | |
2543 case SCHELP: | |
2544 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
2545 help (buf, scanswit); | |
2546 return; | |
2547 | |
2548 case SCCLR: | |
2549 clearsw++; | |
2550 continue; | |
2551 case SCNCLR: | |
2552 clearsw = 0; | |
2553 continue; | |
2554 case SCHEAD: | |
2555 headersw++; | |
2556 continue; | |
2557 case SCNHEAD: | |
2558 headersw = 0; | |
2559 continue; | |
2560 case SCFORM: | |
2561 if (!(form = *args++) || *form == '-') { | |
2562 advise (NULLCP, "missing argument to %s", args[-2]); | |
2563 return; | |
2564 } | |
2565 format = NULL; | |
2566 continue; | |
2567 case SCFMT: | |
2568 if (!(format = *args++) || *format == '-') { | |
2569 advise (NULLCP, "missing argument to %s", args[-2]); | |
2570 return; | |
2571 } | |
2572 form = NULL; | |
2573 continue; | |
2574 case SCWID: | |
2575 if (!(cp = *args++) || *cp == '-') { | |
2576 advise (NULLCP, "missing argument to %s", args[-2]); | |
2577 return; | |
2578 } | |
2579 width = atoi (cp); | |
2580 continue; | |
2581 } | |
2582 if (*cp == '+' || *cp == '@') { | |
2583 advise (NULLCP, "sorry, no folders allowed!"); | |
2584 return; | |
2585 } | |
2586 else | |
2587 msgs[msgp++] = cp; | |
2588 } | |
2589 | |
2590 if (!msgp) | |
2591 msgs[msgp++] = "all"; | |
2592 for (msgnum = 0; msgnum < msgp; msgnum++) | |
2593 if (!m_convert (mp, msgs[msgnum])) | |
2594 return; | |
2595 m_setseq (mp); | |
2596 | |
2597 nfs = new_fs (form, format, FORMAT); | |
2598 if (scanl) { /* force scansbr to (re)compile format */ | |
2599 (void) free (scanl); | |
2600 scanl = NULL; | |
2601 } | |
2602 | |
2603 if (s_optim == 0) { | |
2604 s_optim = optim = 1; | |
2605 s_form = form ? getcpy (form) : NULL; | |
2606 s_format = format ? getcpy (format) : NULL; | |
2607 | |
2608 #ifdef MPOP | |
2609 #ifdef BPOP | |
2610 if (pmsh) { | |
2611 int i; | |
2612 char *dp, | |
2613 *ep, | |
2614 *fp; | |
2615 | |
2616 if (width == 0) | |
2617 width = sc_width (); | |
2618 | |
2619 for (dp = nfs, i = 0; *dp; dp++, i++) | |
2620 if (*dp == '\\' || *dp == '"' || *dp == '\n') | |
2621 i++; | |
2622 i++; | |
2623 if ((ep = malloc ((unsigned) i)) == NULL) | |
2624 adios (NULLCP, "out of memory"); | |
2625 for (dp = nfs, fp = ep; *dp; dp++) { | |
2626 if (*dp == '\n') { | |
2627 *fp++ = '\\', *fp++ = 'n'; | |
2628 continue; | |
2629 } | |
2630 if (*dp == '"' || *dp == '\\') | |
2631 *fp++ = '\\'; | |
2632 *fp++ = *dp; | |
2633 } | |
2634 *fp = '\0'; | |
2635 | |
2636 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK) | |
2637 p_optim = 1; | |
2638 | |
2639 free (ep); | |
2640 } | |
2641 #endif | |
2642 #endif /* MPOP */ | |
2643 } | |
2644 else | |
2645 optim = equiv (s_form, form) && equiv (s_format, format); | |
2646 | |
2647 #ifdef MPOP | |
2648 #ifdef BPOP | |
2649 if (p_optim && optim) { | |
2650 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) | |
2651 if (!(mp -> msgstats[msgnum] & SELECTED) || Msgs[msgnum].m_scanl) | |
2652 break; | |
2653 if (msgnum > mp -> hghmsg && pop_command ("LIST") == OK) { | |
2654 fprintf (stderr, "Stand-by..."); | |
2655 fflush (stderr); | |
2656 | |
2657 for (;;) { | |
2658 int size; | |
2659 | |
2660 switch (pop_multiline ()) { | |
2661 case NOTOK: | |
2662 fprintf (stderr, "%s", response); | |
2663 /* and fall... */ | |
2664 case DONE: | |
2665 fprintf (stderr,"\n"); | |
2666 break; | |
2667 | |
2668 case OK: | |
2669 if (sscanf (response, "%d %d", &msgnum, &size) == 2 | |
2670 && mp -> lowmsg <= msgnum | |
2671 && msgnum <= mp -> hghmsg | |
2672 && (cp = index (response, '#')) | |
2673 && *++cp) | |
2674 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP); | |
2675 continue; | |
2676 } | |
2677 break; | |
2678 } | |
2679 } | |
2680 } | |
2681 #endif | |
2682 #endif /* MPOP */ | |
2683 | |
2684 interrupted = 0; | |
2685 for (msgnum = mp -> lowsel; | |
2686 msgnum <= mp -> hghsel && !interrupted; | |
2687 msgnum++) | |
2688 if (mp -> msgstats[msgnum] & SELECTED) { | |
2689 if (optim && Msgs[msgnum].m_scanl) | |
2690 printf ("%s", Msgs[msgnum].m_scanl); | |
2691 else { | |
2692 #ifdef MPOP | |
2693 #ifdef BPOP | |
2694 if (p_optim | |
2695 && optim | |
2696 && (mp -> msgstats[msgnum] & VIRTUAL) | |
2697 && pop_command ("LIST %d", msgnum) == OK | |
2698 && (cp = index (response, '#')) | |
2699 && *++cp) { | |
2700 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP); | |
2701 printf ("%s", Msgs[msgnum].m_scanl); | |
2702 continue; | |
2703 } | |
2704 #endif | |
2705 #endif /* MPOP */ | |
2706 | |
2707 zp = msh_ready (msgnum, 0); | |
2708 switch (state = scan (zp, msgnum, 0, nfs, width, | |
2709 msgnum == mp -> curmsg, | |
2710 mp -> msgstats[msgnum] & UNSEEN, /* ?? */ | |
2711 headersw, fmsh ? fmsh : mp -> foldpath, | |
2712 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start), | |
2713 1)) { | |
2714 case SCNMSG: | |
2715 case SCNENC: | |
2716 case SCNERR: | |
2717 if (optim) | |
2718 Msgs[msgnum].m_scanl = getcpy (scanl); | |
2719 break; | |
2720 | |
2721 default: | |
2722 advise (NULLCP, "scan() botch (%d)", state); | |
2723 return; | |
2724 | |
2725 case SCNEOF: | |
2726 printf ("%*d empty\n", DMAXFOLDER, msgnum); | |
2727 break; | |
2728 } | |
2729 } | |
2730 headersw = 0; | |
2731 } | |
2732 | |
2733 if (clearsw) | |
2734 clear_screen (); | |
2735 } | |
2736 | |
2737 /* */ | |
2738 | |
2739 static struct swit showswit[] = { | |
2740 #define SHDRAFT 0 | |
2741 "draft", 5, | |
2742 #define SHFORM 1 | |
2743 "form formfile", 4, | |
2744 #define SHPROG 2 | |
2745 "moreproc program", 4, | |
2746 #define SHNPROG 3 | |
2747 "nomoreproc", 3, | |
2748 #define SHLEN 4 | |
2749 "length lines", 4, | |
2750 #define SHWID 5 | |
2751 "width columns", 4, | |
2752 #define SHSHOW 6 | |
2753 "showproc program", 4, | |
2754 #define SHNSHOW 7 | |
2755 "noshowproc", 3, | |
2756 #define SHHEAD 8 | |
2757 "header", 4, | |
2758 #define SHNHEAD 9 | |
2759 "noheader", 3, | |
2760 #define SHHELP 10 | |
2761 "help", 4, | |
2762 | |
2763 NULL, 0 | |
2764 }; | |
2765 | |
2766 /* */ | |
2767 | |
2768 showcmd (args) | |
2769 char **args; | |
2770 { | |
2771 int headersw = 1, | |
2772 nshow = 0, | |
2773 msgp = 0, | |
2774 vecp = 1, | |
2775 mhl = 0, | |
2776 seen = 0, | |
2777 mode = 0, | |
2778 i, | |
2779 msgnum; | |
2780 char *cp, | |
2781 *proc = showproc, | |
2782 buf[BUFSIZ], | |
2783 *msgs[MAXARGS], | |
2784 *vec[MAXARGS]; | |
2785 | |
2786 if (uleq (cmd_name, "next")) | |
2787 mode = 1; | |
2788 else | |
2789 if (uleq (cmd_name, "prev")) | |
2790 mode = -1; | |
2791 while (cp = *args++) { | |
2792 if (*cp == '-') | |
2793 switch (i = smatch (++cp, showswit)) { | |
2794 case AMBIGSW: | |
2795 ambigsw (cp, showswit); | |
2796 return; | |
2797 case UNKWNSW: | |
2798 case SHNPROG: | |
2799 vec[vecp++] = --cp; | |
2800 continue; | |
2801 case SHHELP: | |
2802 (void) sprintf (buf, | |
2803 "%s %s[switches] [switches for showproc]", | |
2804 cmd_name, mode ? NULL : "[msgs] "); | |
2805 help (buf, showswit); | |
2806 return; | |
2807 | |
2808 case SHFORM: | |
2809 case SHPROG: | |
2810 case SHLEN: | |
2811 case SHWID: | |
2812 vec[vecp++] = --cp; | |
2813 if (!(cp = *args++) || *cp == '-') { | |
2814 advise (NULLCP, "missing argument to %s", args[-2]); | |
2815 return; | |
2816 } | |
2817 vec[vecp++] = cp; | |
2818 continue; | |
2819 case SHHEAD: | |
2820 headersw++; | |
2821 continue; | |
2822 case SHNHEAD: | |
2823 headersw = 0; | |
2824 continue; | |
2825 case SHSHOW: | |
2826 if (!(proc = *args++) || *proc == '-') { | |
2827 advise (NULLCP, "missing argument to %s", args[-2]); | |
2828 return; | |
2829 } | |
2830 nshow = 0; | |
2831 continue; | |
2832 case SHNSHOW: | |
2833 nshow++; | |
2834 continue; | |
2835 | |
2836 case SHDRAFT: | |
2837 advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw); | |
2838 return; | |
2839 } | |
2840 if (*cp == '+' || *cp == '@') { | |
2841 advise (NULLCP, "sorry, no folders allowed!"); | |
2842 return; | |
2843 } | |
2844 else | |
2845 if (mode) { | |
2846 fprintf (stderr, | |
2847 "usage: %s [switches] [switches for showproc]\n", | |
2848 cmd_name); | |
2849 return; | |
2850 } | |
2851 else | |
2852 msgs[msgp++] = cp; | |
2853 } | |
2854 vec[vecp] = NULL; | |
2855 | |
2856 if (!msgp) | |
2857 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur"; | |
2858 for (msgnum = 0; msgnum < msgp; msgnum++) | |
2859 if (!m_convert (mp, msgs[msgnum])) | |
2860 return; | |
2861 m_setseq (mp); | |
2862 | |
2863 #ifdef MIME | |
2864 if (!nshow && !getenv ("NOMHNPROC")) | |
2865 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2866 if ((mp -> msgstats[msgnum] & SELECTED) && nontext (msgnum)) { | |
2867 proc = (cp = m_find ("mhnproc")) ? cp : "mhn"; | |
2868 vec[vecp++] = "-show"; | |
2869 vec[vecp++] = "-file"; | |
2870 vec[vecp] = NULL; | |
2871 goto finish; | |
2872 } | |
2873 #endif /* MIME */ | |
2874 | |
2875 if (nshow) | |
2876 proc = "cat"; | |
2877 else | |
2878 if (strcmp (showproc, "mhl") == 0) { | |
2879 proc = mhlproc; | |
2880 mhl++; | |
2881 } | |
2882 | |
2883 finish: ; | |
2884 seen = m_seqflag (mp, "unseen"); | |
2885 vec[0] = r1bindex (proc, '/'); | |
2886 if (mhl) { | |
2887 msgp = vecp; | |
2888 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) | |
2889 if (mp -> msgstats[msgnum] & SELECTED) { | |
2890 vec[vecp++] = getcpy (m_name (msgnum)); | |
2891 if (seen) | |
2892 (void) m_seqdel (mp, "unseen", msgnum); | |
2893 } | |
2894 vec[vecp] = NULL; | |
2895 if (mp -> numsel == 1 && headersw) | |
2896 show (mp -> lowsel); | |
2897 (void) mhlsbr (vecp, vec, mhl_action); | |
2898 if (!fmsh) | |
2899 m_eomsbr ((int (*)()) 0); | |
2900 while (msgp < vecp) | |
2901 free (vec[msgp++]); | |
2902 } | |
2903 else { | |
2904 interrupted = 0; | |
2905 for (msgnum = mp -> lowsel; | |
2906 msgnum <= mp -> hghsel && !interrupted; | |
2907 msgnum++) | |
2908 if (mp -> msgstats[msgnum] & SELECTED) { | |
2909 switch (ask (msgnum)) { | |
2910 case NOTOK: /* QUIT */ | |
2911 break; | |
2912 | |
2913 case OK: /* INTR */ | |
2914 continue; | |
2915 | |
2916 default: | |
2917 if (mp -> numsel == 1 && headersw) | |
2918 show (msgnum); | |
2919 if (nshow) | |
2920 copy_message (msgnum, stdout); | |
2921 else | |
2922 (void) process (msgnum, proc, vecp, vec); | |
2923 | |
2924 if (seen) | |
2925 (void) m_seqdel (mp, "unseen", msgnum); | |
2926 continue; | |
2927 } | |
2928 break; | |
2929 } | |
2930 } | |
2931 | |
2932 m_setcur (mp, mp -> hghsel); | |
2933 } | |
2934 | |
2935 /* */ | |
2936 | |
2937 static show (msgnum) | |
2938 int msgnum; | |
2939 { | |
2940 if (Msgs[msgnum].m_bboard_id == 0) | |
2941 (void) readid (msgnum); | |
2942 | |
2943 printf ("(Message %d", msgnum); | |
2944 if (Msgs[msgnum].m_bboard_id > 0) | |
2945 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id); | |
2946 printf (")\n"); | |
2947 } | |
2948 | |
2949 | |
2950 /* ARGSUSED */ | |
2951 | |
2952 static int eom_action (c) | |
2953 int c; | |
2954 { | |
2955 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop); | |
2956 } | |
2957 | |
2958 | |
2959 static FP mhl_action (name) | |
2960 char *name; | |
2961 { | |
2962 int msgnum; | |
2963 | |
2964 if ((msgnum = m_atoi (name)) < mp -> lowmsg | |
2965 || msgnum > mp -> hghmsg | |
2966 || !(mp -> msgstats[msgnum] & EXISTS)) | |
2967 return NULL; | |
2968 mhlnum = msgnum; | |
2969 | |
2970 mhlfp = msh_ready (msgnum, 1); | |
2971 if (!fmsh) | |
2972 m_eomsbr (eom_action); | |
2973 | |
2974 return mhlfp; | |
2975 } | |
2976 | |
2977 | |
2978 /* */ | |
2979 | |
2980 static ask (msgnum) | |
2981 int msgnum; | |
2982 { | |
2983 char buf[BUFSIZ]; | |
2984 | |
2985 if (mp -> numsel == 1 || !interactive || redirected) | |
2986 return DONE; | |
2987 | |
2988 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) { | |
2989 if (mp -> lowsel != msgnum) | |
2990 printf ("\n\n\n"); | |
2991 printf ("Press <return> to list \"%d\"...", msgnum); | |
2992 } | |
2993 (void) fflush (stdout); | |
2994 buf[0] = 0; | |
2995 #if !defined(BSD42) && !defined(SVR4) | |
2996 (void) read (fileno (stdout), buf, sizeof buf); | |
2997 #else /* BSD42 || SVR4 */ | |
2998 switch (setjmp (sigenv)) { | |
2999 case OK: | |
3000 should_intr = 1; | |
3001 (void) read (fileno (stdout), buf, sizeof buf);/* fall... */ | |
3002 | |
3003 default: | |
3004 should_intr = 0; | |
3005 break; | |
3006 } | |
3007 #endif /* BSD42 || SVR4 */ | |
3008 if (index (buf, '\n') == NULL) | |
3009 (void) putchar ('\n'); | |
3010 | |
3011 if (told_to_quit) { | |
3012 told_to_quit = interrupted = 0; | |
3013 return NOTOK; | |
3014 } | |
3015 if (interrupted) { | |
3016 interrupted = 0; | |
3017 return OK; | |
3018 } | |
3019 | |
3020 return DONE; | |
3021 } | |
3022 | |
3023 /* */ | |
3024 | |
3025 #ifdef MIME | |
3026 #include "../h/mhn.h" | |
3027 | |
3028 | |
3029 static int nontext (msgnum) | |
3030 int msgnum; | |
3031 { | |
3032 int result, | |
3033 state; | |
3034 register char *bp, | |
3035 *dp; | |
3036 char *chset, | |
3037 *cp, | |
3038 buf[BUFSIZ], | |
3039 name[NAMESZ]; | |
3040 FILE *fp; | |
3041 | |
3042 if (Msgs[msgnum].m_flags & MHNCHK) | |
3043 return (Msgs[msgnum].m_flags & MHNYES); | |
3044 Msgs[msgnum].m_flags |= MHNCHK; | |
3045 | |
3046 fp = msh_ready (msgnum, 1); | |
3047 | |
3048 if (!(chset = getenv ("MM_CHARSET"))) | |
3049 #ifdef JAPAN | |
3050 chset = "iso-2022-jp"; | |
3051 #else | |
3052 chset = "us-ascii"; | |
3053 #endif /* JAPAN */ | |
3054 | |
3055 for (state = FLD;;) | |
3056 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) { | |
3057 case FLD: | |
3058 case FLDPLUS: | |
3059 case FLDEOF: | |
3060 if (uleq (name, TYPE_FIELD)) { | |
3061 int passno; | |
3062 char c; | |
3063 | |
3064 cp = add (buf, NULLCP); | |
3065 while (state == FLDPLUS) { | |
3066 state = m_getfld (state, name, buf, sizeof buf, fp); | |
3067 cp = add (buf, cp); | |
3068 } | |
3069 bp = cp; | |
3070 passno = 1; | |
3071 | |
3072 again: ; | |
3073 for (; isspace (*bp); bp++) | |
3074 continue; | |
3075 if (*bp == '(') { | |
3076 int i; | |
3077 | |
3078 for (bp++, i = 0;;) { | |
3079 switch (*bp++) { | |
3080 case '\0': | |
3081 invalid: ; | |
3082 result = 0; | |
3083 goto out; | |
3084 case '\\': | |
3085 if (*bp++ == '\0') | |
3086 goto invalid; | |
3087 continue; | |
3088 case '(': | |
3089 i++; | |
3090 /* and fall... */ | |
3091 default: | |
3092 continue; | |
3093 case ')': | |
3094 if (--i < 0) | |
3095 break; | |
3096 continue; | |
3097 } | |
3098 break; | |
3099 } | |
3100 for (; isspace (*bp); bp++) | |
3101 continue; | |
3102 } | |
3103 if (passno == 2) { | |
3104 if (*bp != '/') | |
3105 goto invalid; | |
3106 bp++; | |
3107 passno = 3; | |
3108 goto again; | |
3109 } | |
3110 else if (passno == 4) { | |
3111 if (*bp != ';') | |
3112 goto invalid; | |
3113 bp++; | |
3114 passno = 5; | |
3115 goto again; | |
3116 } | |
3117 for (dp = bp; istoken (*dp); dp++) | |
3118 continue; | |
3119 c = *dp, *dp = '\0'; | |
3120 if (*bp == '\0') | |
3121 goto invalid; | |
3122 if (passno == 3) { | |
3123 if (result = !uleq (bp, "plain")) | |
3124 goto out; | |
3125 *dp = c; | |
3126 bp = dp; | |
3127 passno = 4; | |
3128 goto again; | |
3129 } | |
3130 if (passno > 1) { | |
3131 if (result = !uprf (bp, "charset")) | |
3132 goto invalid; | |
3133 *dp = c; | |
3134 while (isspace (*dp)) | |
3135 dp++; | |
3136 if (*dp++ != '=') | |
3137 goto invalid; | |
3138 while (isspace (*dp)) | |
3139 dp++; | |
3140 if (*dp == '"') { | |
3141 if (bp = index (++dp, '"')) | |
3142 *bp = '\0'; | |
3143 } | |
3144 else | |
3145 for (bp = dp; *bp; bp++) | |
3146 if (!istoken (*bp)) { | |
3147 *bp = '\0'; | |
3148 break; | |
3149 } | |
3150 if ((result = !uleq (dp, chset)) | |
3151 && uleq (dp, "us-ascii") | |
3152 #ifdef JAPAN | |
3153 && (uleq (chset, "iso-2022-jp") | |
3154 || uleq (chset, "euc-jp") | |
3155 || uleq (chset, "shift_jis") | |
3156 || (uprf (chset, "iso-8859-") | |
3157 && m_atoi (chset+9) >= 1))) | |
3158 #else /* JAPAN */ | |
3159 /* && uleq (chset, "iso-8859-1")) */ | |
3160 && uprf (chset, "iso-8859-") | |
3161 && m_atoi (chset+9) >= 1) | |
3162 #endif /* JAPAN */ | |
3163 result = 0; | |
3164 } | |
3165 else | |
3166 if (!(result = !uleq (bp, "text"))) { | |
3167 *dp = c; | |
3168 bp = dp; | |
3169 passno = 2; | |
3170 goto again; | |
3171 } | |
3172 | |
3173 out: ; | |
3174 free (cp); | |
3175 | |
3176 if (result) { | |
3177 Msgs[msgnum].m_flags |= MHNYES; | |
3178 return result; | |
3179 } | |
3180 break; | |
3181 } | |
3182 if (uleq (name, ENCODING_FIELD)) { | |
3183 cp = add (buf, NULLCP); | |
3184 while (state == FLDPLUS) { | |
3185 state = m_getfld (state, name, buf, sizeof buf, fp); | |
3186 cp = add (buf, cp); | |
3187 } | |
3188 for (bp = cp; isspace (*bp); bp++) | |
3189 continue; | |
3190 for (dp = bp; istoken (*dp); dp++) | |
3191 continue; | |
3192 *dp = '\0'; | |
3193 result = !uleq (bp, "7bit") | |
3194 && !uleq (bp, "8bit") | |
3195 && !uleq (bp, "binary"); | |
3196 | |
3197 free (cp); | |
3198 if (result) { | |
3199 Msgs[msgnum].m_flags |= MHNYES; | |
3200 return result; | |
3201 } | |
3202 break; | |
3203 } | |
3204 while (state == FLDPLUS) | |
3205 state = m_getfld (state, name, buf, sizeof buf, fp); | |
3206 break; | |
3207 | |
3208 default: | |
3209 return 0; | |
3210 } | |
3211 } | |
3212 #endif /* MIME */ | |
3213 | |
3214 /* */ | |
3215 | |
3216 static struct swit sortswit[] = { | |
3217 #define SODATE 0 | |
3218 "datefield field", 0, | |
3219 #define SOSUBJ 1 | |
3220 "textfield field", 0, | |
3221 #define SONSUBJ 2 | |
3222 "notextfield", 0, | |
3223 #define SOLIMT 3 | |
3224 "limit days", 0, | |
3225 #define SONLIMT 4 | |
3226 "nolimit", 0, | |
3227 #define SOVERB 5 | |
3228 "verbose", 0, | |
3229 #define SONVERB 6 | |
3230 "noverbose", 0, | |
3231 #define SOHELP 7 | |
3232 "help", 4, | |
3233 | |
3234 NULL, 0 | |
3235 }; | |
3236 | |
3237 /* */ | |
3238 | |
3239 sortcmd (args) | |
3240 char **args; | |
3241 { | |
3242 int msgp = 0, | |
3243 msgnum; | |
3244 char *cp, | |
3245 *datesw = NULL, | |
3246 *subjsw = NULL, | |
3247 buf[BUFSIZ], | |
3248 *msgs[MAXARGS]; | |
3249 struct tws tb, | |
3250 *tw; | |
3251 | |
3252 if (fmsh) { | |
3253 forkcmd (args, cmd_name); | |
3254 return; | |
3255 } | |
3256 | |
3257 while (cp = *args++) { | |
3258 if (*cp == '-') | |
3259 switch (smatch (++cp, sortswit)) { | |
3260 case AMBIGSW: | |
3261 ambigsw (cp, sortswit); | |
3262 return; | |
3263 case UNKWNSW: | |
3264 fprintf (stderr, "-%s unknown\n", cp); | |
3265 return; | |
3266 case SOHELP: | |
3267 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); | |
3268 help (buf, sortswit); | |
3269 return; | |
3270 | |
3271 case SODATE: | |
3272 if (datesw) { | |
3273 advise (NULLCP, "only one date field at a time!"); | |
3274 return; | |
3275 } | |
3276 if (!(datesw = *args++) || *datesw == '-') { | |
3277 advise (NULLCP, "missing argument to %s", args[-2]); | |
3278 return; | |
3279 } | |
3280 continue; | |
3281 | |
3282 case SOSUBJ: | |
3283 if (subjsw) { | |
3284 advise (NULLCP, "only one text field at a time!"); | |
3285 return; | |
3286 } | |
3287 if (!(subjsw = *args++) || *subjsw == '-') { | |
3288 advise (NULLCP, "missing argument to %s", args[-2]); | |
3289 return; | |
3290 } | |
3291 continue; | |
3292 case SONSUBJ: | |
3293 subjsw = (char *)0; | |
3294 continue; | |
3295 | |
3296 case SOLIMT: /* too hard */ | |
3297 if (!(cp = *args++) || *cp == '-') { | |
3298 advise (NULLCP, "missing argument to %s", args[-2]); | |
3299 return; | |
3300 } | |
3301 case SONLIMT: | |
3302 case SOVERB: /* not implemented */ | |
3303 case SONVERB: | |
3304 continue; | |
3305 } | |
3306 if (*cp == '+' || *cp == '@') { | |
3307 advise (NULLCP, "sorry, no folders allowed!"); | |
3308 return; | |
3309 } | |
3310 else | |
3311 msgs[msgp++] = cp; | |
3312 } | |
3313 | |
3314 if (!msgp) | |
3315 msgs[msgp++] = "all"; | |
3316 if (!datesw) | |
3317 datesw = "Date"; | |
3318 for (msgnum = 0; msgnum < msgp; msgnum++) | |
3319 if (!m_convert (mp, msgs[msgnum])) | |
3320 return; | |
3321 m_setseq (mp); | |
3322 | |
3323 twscopy (&tb, dtwstime ()); | |
3324 | |
3325 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { | |
3326 if (Msgs[msgnum].m_scanl) { | |
3327 free (Msgs[msgnum].m_scanl); | |
3328 Msgs[msgnum].m_scanl = NULL; | |
3329 } | |
3330 if (mp -> msgstats[msgnum] & SELECTED) { | |
3331 if (getws (datesw, subjsw, msgnum, &Msgs[msgnum])) | |
3332 twscopy (&Msgs[msgnum].m_tb, | |
3333 msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb); | |
3334 } | |
3335 else /* m_scaln is already NULL */ | |
3336 twscopy (&Msgs[msgnum].m_tb, &tb); | |
3337 Msgs[msgnum].m_stats = mp -> msgstats[msgnum]; | |
3338 if (mp -> curmsg == msgnum) | |
3339 Msgs[msgnum].m_stats |= CUR; | |
3340 } | |
3341 | |
3342 qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1, | |
3343 sizeof (struct Msg), | |
3344 subjsw ? subsort : msgsort); | |
3345 | |
3346 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { | |
3347 if (subjsw && Msgs[msgnum].m_scanl) { | |
3348 free (Msgs[msgnum].m_scanl); /* from subjsort */ | |
3349 Msgs[msgnum].m_scanl = NULL; | |
3350 } | |
3351 mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR; | |
3352 if (Msgs[msgnum].m_stats & CUR) | |
3353 m_setcur (mp, msgnum); | |
3354 } | |
3355 | |
3356 mp -> msgflags |= MODIFIED; | |
3357 modified++; | |
3358 } | |
3359 | |
3360 /* */ | |
3361 | |
3362 /* | |
3363 * getws - parse message, and get date and subject if needed. We'll use | |
3364 * the msgp->m_tb tws struct for the date, and overload the msgp->m_scanl | |
3365 * field with our subject string. | |
3366 */ | |
3367 static int getws (datesw, subjsw, msgnum, msgp) | |
3368 char *datesw, | |
3369 *subjsw; | |
3370 int msgnum; | |
3371 struct Msg *msgp; | |
3372 { | |
3373 int state, | |
3374 gotdate = 0; | |
3375 char *bp, | |
3376 buf[BUFSIZ], | |
3377 name[NAMESZ]; | |
3378 struct tws *tw = (struct tws *)0; | |
3379 register FILE *zp; | |
3380 | |
3381 zp = msh_ready (msgnum, 0); | |
3382 for (state = FLD;;) { | |
3383 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) { | |
3384 case FLD: | |
3385 case FLDEOF: | |
3386 case FLDPLUS: | |
3387 if (uleq (name, datesw)) { | |
3388 bp = getcpy (buf); | |
3389 while (state == FLDPLUS) { | |
3390 state = m_getfld (state, name, buf, sizeof buf, zp); | |
3391 bp = add (buf, bp); | |
3392 } | |
3393 if ((tw = dparsetime (bp)) == NULL) | |
3394 admonish (NULLCP, | |
3395 "unable to parse %s field in message %d", | |
3396 datesw, msgnum); | |
3397 else | |
3398 twscopy (&(msgp->m_tb), tw); | |
3399 free (bp); | |
3400 if (!subjsw) /* not using this, or already done */ | |
3401 break; /* all done! */ | |
3402 gotdate++; | |
3403 } | |
3404 else if (subjsw && uleq(name, subjsw)) { | |
3405 bp = getcpy (buf); | |
3406 while (state == FLDPLUS) { | |
3407 state = m_getfld (state, name, buf, sizeof buf, zp); | |
3408 bp = add (buf, bp); | |
3409 } | |
3410 msgp->m_scanl = sosmash(subjsw, bp); | |
3411 if (gotdate) | |
3412 break; /* date done so we're done */ | |
3413 else | |
3414 subjsw = (char *)0;/* subject done, need date */ | |
3415 } else { | |
3416 while (state == FLDPLUS) /* flush this one */ | |
3417 state = m_getfld (state, name, buf, sizeof buf, zp); | |
3418 } | |
3419 continue; | |
3420 | |
3421 case BODY: | |
3422 case BODYEOF: | |
3423 case FILEEOF: | |
3424 break; | |
3425 | |
3426 case LENERR: | |
3427 case FMTERR: | |
3428 admonish (NULLCP, "format error in message %d", msgnum); | |
3429 if (msgp->m_scanl) { /* this might need free'd */ | |
3430 free (msgp->m_scanl); /* probably can't use subj anyway */ | |
3431 msgp->m_scanl = NULL; | |
3432 } | |
3433 return NOTOK; | |
3434 | |
3435 default: | |
3436 adios (NULLCP, "internal error -- you lose"); | |
3437 } | |
3438 break; | |
3439 } | |
3440 if (tw) | |
3441 return OK; /* not an error if subj not found */ | |
3442 | |
3443 admonish (NULLCP, "no %s field in message %d", datesw, msgnum); | |
3444 return NOTOK; /* NOTOK means use some other date */ | |
3445 } | |
3446 | |
3447 /* sort routines */ | |
3448 | |
3449 static int msgsort (a, b) | |
3450 struct Msg *a, | |
3451 *b; | |
3452 { | |
3453 return twsort (&a -> m_tb, &b -> m_tb); | |
3454 } | |
3455 | |
3456 static int subsort (a, b) | |
3457 struct Msg *a, | |
3458 *b; | |
3459 { | |
3460 register int i; | |
3461 | |
3462 if (a->m_scanl && b->m_scanl) | |
3463 if (i = strcmp (a->m_scanl, b->m_scanl)) | |
3464 return (i); | |
3465 | |
3466 return twsort (&a -> m_tb, &b -> m_tb); | |
3467 } | |
3468 | |
3469 /* | |
3470 * try to make the subject "canonical": delete leading "re:", everything | |
3471 * but letters & smash letters to lower case. | |
3472 */ | |
3473 static char * | |
3474 sosmash (subj, s) | |
3475 char *subj; | |
3476 register char *s; | |
3477 { | |
3478 register char *cp, | |
3479 *dp, | |
3480 c; | |
3481 if (s) { | |
3482 cp = s; | |
3483 dp = s; /* dst pointer */ | |
3484 if (uleq (subj, "subject")) | |
3485 while (c = *cp) { | |
3486 if (! isspace(c)) { | |
3487 if(uprf(cp, "re:")) | |
3488 cp += 2; | |
3489 else { | |
3490 if (isalnum(c)) | |
3491 *dp++ = isupper(c) ? tolower(c) : c; | |
3492 break; | |
3493 } | |
3494 } | |
3495 cp++; | |
3496 } | |
3497 while (c = *cp++) { | |
3498 if (isalnum(c)) | |
3499 *dp++ = isupper(c) ? tolower(c) : c; | |
3500 | |
3501 } | |
3502 *dp = '\0'; | |
3503 } | |
3504 return s; | |
3505 } | |
3506 | |
3507 /* */ | |
3508 | |
3509 static int process (msgnum, proc, vecp, vec) | |
3510 int msgnum, | |
3511 vecp; | |
3512 char *proc, | |
3513 **vec; | |
3514 { | |
3515 int child_id, | |
3516 status; | |
3517 char tmpfil[80]; | |
3518 FILE *out; | |
3519 | |
3520 if (fmsh) { | |
3521 (void) strcpy (tmpfil, m_name (msgnum)); | |
3522 (void) m_delete (pfolder); | |
3523 m_replace (pfolder, fmsh); | |
3524 m_sync (mp); | |
3525 m_update (); | |
3526 goto ready; | |
3527 } | |
3528 | |
3529 (void) strcpy (tmpfil, m_scratch ("", invo_name)); | |
3530 if ((out = fopen (tmpfil, "w")) == NULL) { | |
3531 int olderr; | |
3532 extern int errno; | |
3533 char newfil[80]; | |
3534 | |
3535 olderr = errno; | |
3536 (void) strcpy (newfil, m_tmpfil (invo_name)); | |
3537 if ((out = fopen (newfil, "w")) == NULL) { | |
3538 errno = olderr; | |
3539 advise (tmpfil, "unable to create temporary file"); | |
3540 return NOTOK; | |
3541 } | |
3542 else | |
3543 (void) strcpy (tmpfil, newfil); | |
3544 } | |
3545 copy_message (msgnum, out); | |
3546 (void) fclose (out); | |
3547 | |
3548 ready: ; | |
3549 (void) fflush (stdout); | |
3550 switch (child_id = fork ()) { | |
3551 case NOTOK: | |
3552 advise ("fork", "unable to"); | |
3553 status = NOTOK; | |
3554 break; | |
3555 | |
3556 case OK: | |
3557 closefds (3); | |
3558 (void) signal (SIGINT, istat); | |
3559 (void) signal (SIGQUIT, qstat); | |
3560 | |
3561 vec[vecp++] = tmpfil; | |
3562 vec[vecp] = NULL; | |
3563 | |
3564 execvp (proc, vec); | |
3565 fprintf (stderr, "unable to exec "); | |
3566 perror (proc); | |
3567 _exit (1); | |
3568 | |
3569 default: | |
3570 status = pidXwait (child_id, NULLCP); | |
3571 break; | |
3572 } | |
3573 | |
3574 if (!fmsh) | |
3575 (void) unlink (tmpfil); | |
3576 return status; | |
3577 } | |
3578 | |
3579 /* */ | |
3580 | |
3581 static copy_message (msgnum, out) | |
3582 int msgnum; | |
3583 FILE * out; | |
3584 { | |
3585 long pos; | |
3586 static char buffer[BUFSIZ]; | |
3587 register FILE * zp; | |
3588 | |
3589 zp = msh_ready (msgnum, 1); | |
3590 if (fmsh) { | |
3591 while (fgets (buffer, sizeof buffer, zp) != NULL) { | |
3592 fputs (buffer, out); | |
3593 if (interrupted && out == stdout) | |
3594 break; | |
3595 } | |
3596 } | |
3597 else { | |
3598 pos = ftell (zp); | |
3599 while (fgets (buffer, sizeof buffer, zp) != NULL | |
3600 && pos < Msgs[msgnum].m_stop) { | |
3601 fputs (buffer, out); | |
3602 pos += (long) strlen (buffer); | |
3603 if (interrupted && out == stdout) | |
3604 break; | |
3605 } | |
3606 } | |
3607 } | |
3608 | |
3609 | |
3610 static copy_digest (msgnum, out) | |
3611 int msgnum; | |
3612 FILE * out; | |
3613 { | |
3614 char c; | |
3615 long pos; | |
3616 static char buffer[BUFSIZ]; | |
3617 register FILE *zp; | |
3618 | |
3619 c = '\n'; | |
3620 zp = msh_ready (msgnum, 1); | |
3621 if (!fmsh) | |
3622 pos = ftell (zp); | |
3623 while (fgets (buffer, sizeof buffer, zp) != NULL | |
3624 && !fmsh && pos < Msgs[msgnum].m_stop) { | |
3625 if (c == '\n' && *buffer == '-') | |
3626 (void) fputc (' ', out); | |
3627 fputs (buffer, out); | |
3628 c = buffer[strlen (buffer) - 1]; | |
3629 if (!fmsh) | |
3630 pos += (long) strlen (buffer); | |
3631 if (interrupted && out == stdout) | |
3632 break; | |
3633 } | |
3634 } |