]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/mshcmds.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / mshcmds.c
1 /* mshcmds.c - command handlers in msh */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: mshcmds.c,v 1.32 1995/12/11 18:19:26 jromine Exp $";
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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 /* \f */
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
922 if (fmsh) {
923 forkcmd (args, cmd_name);
924 return;
925 }
926
927 while (cp = *args++) {
928 if (*cp == '-')
929 switch (smatch (++cp, forwswit)) {
930 case AMBIGSW:
931 ambigsw (cp, forwswit);
932 return;
933 case UNKWNSW:
934 fprintf (stderr, "-%s unknown\n", cp);
935 return;
936 case FOHELP:
937 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
938 help (buf, forwswit);
939 return;
940
941 case FOANSW: /* not implemented */
942 case FONANSW:
943 case FOINSW:
944 case FONINSW:
945 continue;
946
947 case FOMISW:
948 #ifdef MIME
949 mime = 1;
950 filter = NULL;
951 #endif /* MIME */
952 continue;
953 case FONMISW:
954 mime = 0;
955 continue;
956
957 case FONDFSW:
958 case FONEDSW:
959 case FONWTSW:
960 vec[vecp++] = --cp;
961 continue;
962
963 case FOEDTSW:
964 case FOFRMSW:
965 case FODFSW:
966 case FODMSW:
967 case FOWHTSW:
968 vec[vecp++] = --cp;
969 if (!(cp = *args++) || *cp == '-') {
970 advise (NULLCP, "missing argument to %s", args[-2]);
971 return;
972 }
973 vec[vecp++] = cp;
974 continue;
975 case FOFTRSW:
976 if (!(filter = *args++) || *filter == '-') {
977 advise (NULLCP, "missing argument to %s", args[-2]);
978 return;
979 }
980 mime = 0;
981 continue;
982 case FOFTSW:
983 if (access (filter = myfilter, 04) == NOTOK) {
984 advise (filter, "unable to read default filter file");
985 return;
986 }
987 continue;
988 case FONFTSW:
989 filter = NULL;
990 continue;
991 }
992 if (*cp == '+' || *cp == '@') {
993 advise (NULLCP, "sorry, no folders allowed!");
994 return;
995 }
996 else
997 msgs[msgp++] = cp;
998 }
999
1000 /* foil search of .mh_profile */
1001 (void) sprintf (buf, "%sXXXXXX", invo_name);
1002 vec[0] = (char *)mktemp (buf);
1003 vec[vecp++] = "-file";
1004 vec[vecp] = NULL;
1005 if (!msgp)
1006 msgs[msgp++] = "cur";
1007 for (msgnum = 0; msgnum < msgp; msgnum++)
1008 if (!m_convert (mp, msgs[msgnum]))
1009 return;
1010 m_setseq (mp);
1011
1012 if (filter) {
1013 (void) strcpy (buf, filter);
1014 if (expand (buf) == NOTOK)
1015 return;
1016 if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) {
1017 advise (filter, "unable to read");
1018 free (filter);
1019 return;
1020 }
1021 }
1022 forw (cmd_name, filter, vecp, vec, mime);
1023 m_setcur (mp, mp -> hghsel);
1024 if (filter)
1025 free (filter);
1026 }
1027
1028 /* \f */
1029
1030 static forw (proc, filter, vecp, vec, mime)
1031 int vecp,
1032 mime;
1033 char *proc,
1034 *filter,
1035 **vec;
1036 {
1037 int i,
1038 child_id,
1039 msgnum,
1040 msgcnt;
1041 char tmpfil[80],
1042 *args[MAXARGS];
1043 FILE *out;
1044 #ifdef MIME
1045 int nedit = 0;
1046 char *ed = NULL;
1047 #endif /* MIME */
1048
1049 (void) strcpy (tmpfil, m_tmpfil (invo_name));
1050 interrupted = 0;
1051 if (filter)
1052 switch (child_id = fork ()) {
1053 case NOTOK:
1054 advise ("fork", "unable to");
1055 return;
1056
1057 case OK: /* "trust me" */
1058 if (freopen (tmpfil, "w", stdout) == NULL) {
1059 fprintf (stderr, "unable to create ");
1060 perror (tmpfil);
1061 _exit (1);
1062 }
1063 args[0] = r1bindex (mhlproc, '/');
1064 i = 1;
1065 args[i++] = "-forwall";
1066 args[i++] = "-form";
1067 args[i++] = filter;
1068 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1069 if (mp -> msgstats[msgnum] & SELECTED)
1070 args[i++] = getcpy (m_name (msgnum));
1071 args[i] = NULL;
1072 (void) mhlsbr (i, args, mhl_action);
1073 m_eomsbr ((int (*) ()) 0);
1074 (void) fclose (stdout);
1075 _exit (0);
1076
1077 default:
1078 if (pidXwait (child_id, NULLCP))
1079 interrupted++;
1080 break;
1081 }
1082 #ifdef MIME
1083 else if (mime) {
1084 int isdf = 0,
1085 len,
1086 nwhat = 0;
1087 #define INITIAL_PREFIX "----- =_aaaaaaaaaa"
1088 char *cp,
1089 *form = NULL,
1090 buffer[BUFSIZ],
1091 prefix[sizeof INITIAL_PREFIX];
1092 FILE *zp;
1093
1094 proc = whatnowproc;
1095 for (vecp = 1; cp = vec[vecp++]; )
1096 if (*cp == '-')
1097 switch (smatch (++cp, forwswit)) {
1098 case FOEDTSW:
1099 ed = vec[vecp++];
1100 nedit = 0;
1101 continue;
1102 case FONEDSW:
1103 nedit++;
1104 continue;
1105
1106 case FOFRMSW:
1107 form = vec[vecp++];
1108 continue;
1109
1110 case FOWHTSW:
1111 proc = vec[vecp++];
1112 nwhat = 0;
1113 continue;
1114 case FONWTSW:
1115 nwhat++;
1116 continue;
1117
1118 /* ignore -draftfolder / -draftmessage / -nodraftfolder */
1119 case FODFSW:
1120 case FODMSW:
1121 vecp++;
1122 case FONDFSW:
1123 continue;
1124 }
1125 (void) strcpy (tmpfil, m_draft (NULLCP, NULLCP, NOUSE, &isdf));
1126 if (!ed && !(ed = m_find ("editor")))
1127 ed = sysed;
1128
1129 (void) strcpy (prefix, INITIAL_PREFIX);
1130 cp = index (prefix, 'a');
1131 len = strlen (prefix);
1132
1133 for (;;) {
1134 int hit = 0;
1135 long pos;
1136
1137 for (msgnum = mp -> lowsel;
1138 msgnum <= mp -> hghsel && !interrupted && !hit;
1139 msgnum++)
1140 if (mp -> msgstats[msgnum] & SELECTED) {
1141 zp = msh_ready (msgnum, 1);
1142 if (!fmsh)
1143 pos = ftell (zp);
1144 while (fgets (buffer, sizeof buffer, zp) != NULL
1145 && !fmsh
1146 && pos < Msgs[msgnum].m_stop) {
1147 register char *pp;
1148
1149 if (buffer[0] != '-' || buffer[1] != '-')
1150 continue;
1151
1152 for (pp = buffer + strlen (buffer) - 1;
1153 pp >= buffer;
1154 pp--)
1155 if (!isspace (*pp))
1156 break;
1157 *pp++ = '\0';
1158
1159 if (strncmp (buffer + 2, prefix, len))
1160 continue;
1161
1162 hit = 1;
1163 break;
1164 }
1165 }
1166
1167 if (!hit)
1168 break;
1169
1170 if (*cp < 'z')
1171 (*cp)++;
1172 else
1173 if (*++cp == 0) {
1174 advise (NULLCP,
1175 "unable to determine unique delimiter string?!?");
1176 return;
1177 }
1178 else
1179 (*cp)++;
1180 }
1181
1182 if ((out = fopen (tmpfil, "w")) == NULL) {
1183 advise (tmpfil, "unable to create temporary file");
1184 return;
1185 }
1186 (void) chmod (tmpfil, m_gmprot ());
1187
1188 fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
1189 fprintf (out, "%s: multipart/digest; boundary=\"%s\"\n", TYPE_FIELD,
1190 prefix);
1191
1192 if (!(zp = fopen (libpath (form ? form : forwcomps), "r"))) {
1193 if (form)
1194 advise (form, "unable to open form file");
1195 else
1196 advise (forwcomps, "unable to open default components file");
1197 (void) fclose (out);
1198 (void) unlink (tmpfil);
1199 return;
1200 }
1201 while (fgets (buffer, sizeof buffer, zp))
1202 (void) fputs (buffer, out);
1203 (void) fclose (zp);
1204
1205 for (msgnum = mp -> lowsel;
1206 msgnum <= mp -> hghsel && !interrupted;
1207 msgnum++)
1208 if (mp -> msgstats[msgnum] & SELECTED) {
1209 fprintf (out, "\n--%s\n%s: message/rfc822\n\n", prefix,
1210 TYPE_FIELD);
1211
1212 copy_message (msgnum, out);
1213 }
1214 fprintf (out, "\n--%s--\n", prefix);
1215
1216 (void) fclose (out);
1217 if (nwhat)
1218 return;
1219 }
1220 #endif /* MIME */
1221 else {
1222 if ((out = fopen (tmpfil, "w")) == NULL) {
1223 advise (tmpfil, "unable to create temporary file");
1224 return;
1225 }
1226
1227 msgcnt = 1;
1228 for (msgnum = mp -> lowsel;
1229 msgnum <= mp -> hghsel && !interrupted;
1230 msgnum++)
1231 if (mp -> msgstats[msgnum] & SELECTED) {
1232 fprintf (out, "\n\n-------");
1233 if (msgnum == mp -> lowsel)
1234 fprintf (out, " Forwarded Message%s",
1235 mp -> numsel > 1 ? "s" : "");
1236 else
1237 fprintf (out, " Message %d", msgcnt);
1238 fprintf (out, "\n\n");
1239 copy_digest (msgnum, out);
1240 msgcnt++;
1241 }
1242
1243 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1244 mp -> numsel > 1 ? "s" : "");
1245 (void) fclose (out);
1246 }
1247
1248 (void) fflush (stdout);
1249 if (!interrupted)
1250 switch (child_id = fork ()) {
1251 case NOTOK:
1252 advise ("fork", "unable to");
1253 break;
1254
1255 case OK:
1256 closefds (3);
1257 (void) signal (SIGINT, istat);
1258 (void) signal (SIGQUIT, qstat);
1259
1260 #ifdef MIME
1261 if (mime) {
1262 vecp = 0;
1263 vec[vecp++] = r1bindex (proc, '/');
1264 (void) m_putenv ("mhdraft", tmpfil);
1265 (void) unputenv ("mhfolder");
1266 (void) unputenv ("mhaltmsg");
1267 (void) m_putenv ("mhdist", "0");
1268 if (nedit)
1269 (void) unputenv ("mheditor");
1270 else
1271 (void) m_putenv ("mheditor", ed);
1272 (void) m_putenv ("mhuse", "0");
1273 (void) unputenv ("mhmessages");
1274 (void) unputenv ("mhannotate");
1275 (void) unputenv ("mhinplace");
1276 }
1277 else
1278 #endif /* MIME */
1279
1280 vec[vecp++] = tmpfil;
1281 vec[vecp] = NULL;
1282
1283 execvp (proc, vec);
1284 fprintf (stderr, "unable to exec ");
1285 perror (proc);
1286 _exit (1);
1287
1288 default:
1289 (void) pidXwait (child_id, NULLCP);
1290 break;
1291 }
1292
1293 #ifdef MIME
1294 if (!mime)
1295 #endif /* MIME */
1296 (void) unlink (tmpfil);
1297 }
1298
1299 /* \f */
1300
1301 static char *hlpmsg[] = {
1302 "The %s program emulates many of the commands found in the Rand MH",
1303 "system. Instead of operating on MH folders, commands to %s concern",
1304 "a single file.",
1305 "",
1306 "To see the list of commands available, just type a ``?'' followed by",
1307 "the RETURN key. To find out what switches each command takes, type",
1308 "the name of the command followed by ``-help''. To leave %s, use the",
1309 "``quit'' command.",
1310 "",
1311 "Although a lot of MH commands are found in %s, not all are fully",
1312 "implemented. %s will always recognize all legal switches for a",
1313 "given command though, and will let you know when you ask for an",
1314 "option that it is unable to perform.",
1315 "",
1316 "Running %s is fun, but using MH from your shell is far superior.",
1317 "After you have familiarized yourself with the MH style by using %s,",
1318 "you should try using MH from the shell. You can still use %s for",
1319 "message files that aren't in MH format, such as BBoard files.",
1320 NULL
1321 };
1322
1323
1324 /* ARGSUSED */
1325
1326 helpcmd (args)
1327 char **args;
1328 {
1329 int i;
1330
1331 for (i = 0; hlpmsg[i]; i++) {
1332 printf (hlpmsg[i], invo_name);
1333 (void) putchar ('\n');
1334 }
1335 }
1336
1337 /* \f */
1338
1339 static struct swit markswit[] = {
1340 #define MADDSW 0
1341 "add", 0,
1342 #define MDELSW 1
1343 "delete", 0,
1344 #define MLSTSW 2
1345 "list", 0,
1346 #define MSEQSW 3
1347 "sequence name", 0,
1348 #define MPUBSW 4
1349 "public", 0,
1350 #define MNPUBSW 5
1351 "nopublic", 0,
1352 #define MZERSW 6
1353 "zero", 0,
1354 #define MNZERSW 7
1355 "nozero", 0,
1356 #define MHELP 8
1357 "help", 4,
1358 #define MDBUGSW 9
1359 "debug", -5,
1360
1361 NULL, 0
1362 };
1363
1364 /* \f */
1365
1366 markcmd (args)
1367 char **args;
1368 {
1369 int addsw = 0,
1370 deletesw = 0,
1371 debugsw = 0,
1372 listsw = 0,
1373 zerosw = 0,
1374 seqp = 0,
1375 msgp = 0,
1376 i,
1377 msgnum;
1378 char *cp,
1379 buf[BUFSIZ],
1380 *seqs[NATTRS + 1],
1381 *msgs[MAXARGS];
1382
1383 while (cp = *args++) {
1384 if (*cp == '-')
1385 switch (smatch (++cp, markswit)) {
1386 case AMBIGSW:
1387 ambigsw (cp, markswit);
1388 return;
1389 case UNKWNSW:
1390 fprintf (stderr, "-%s unknown\n", cp);
1391 return;
1392 case MHELP:
1393 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1394 help (buf, markswit);
1395 return;
1396
1397 case MADDSW:
1398 addsw++;
1399 deletesw = listsw = 0;
1400 continue;
1401 case MDELSW:
1402 deletesw++;
1403 addsw = listsw = 0;
1404 continue;
1405 case MLSTSW:
1406 listsw++;
1407 addsw = deletesw = 0;
1408 continue;
1409
1410 case MSEQSW:
1411 if (!(cp = *args++) || *cp == '-') {
1412 advise (NULLCP, "missing argument to %s", args[-2]);
1413 return;
1414 }
1415 if (seqp < NATTRS)
1416 seqs[seqp++] = cp;
1417 else {
1418 advise (NULLCP, "only %d sequences allowed!", NATTRS);
1419 return;
1420 }
1421 continue;
1422
1423 case MPUBSW: /* not implemented */
1424 case MNPUBSW:
1425 continue;
1426
1427 case MDBUGSW:
1428 debugsw++;
1429 continue;
1430
1431 case MZERSW:
1432 zerosw++;
1433 continue;
1434 case MNZERSW:
1435 zerosw = 0;
1436 continue;
1437 }
1438 if (*cp == '+' || *cp == '@') {
1439 advise (NULLCP, "sorry, no folders allowed!");
1440 return;
1441 }
1442 else
1443 msgs[msgp++] = cp;
1444 }
1445
1446 if (!addsw && !deletesw && !listsw)
1447 if (seqp)
1448 addsw++;
1449 else
1450 if (debugsw)
1451 listsw++;
1452 else {
1453 seqs[seqp++] = "unseen";
1454 deletesw++;
1455 zerosw = 0;
1456 if (!msgp)
1457 msgs[msgp++] = "all";
1458 }
1459
1460 if (!msgp)
1461 msgs[msgp++] = listsw ? "all" :"cur";
1462 for (msgnum = 0; msgnum < msgp; msgnum++)
1463 if (!m_convert (mp, msgs[msgnum]))
1464 return;
1465
1466 if (debugsw) {
1467 printf ("invo_name=%s mypath=%s defpath=%s\n",
1468 invo_name, mypath, defpath);
1469 printf ("ctxpath=%s context flags=%s\n",
1470 ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS));
1471 printf ("foldpath=%s flags=%s\n",
1472 mp -> foldpath,
1473 sprintb (buf, (unsigned) mp -> msgflags, FBITS));
1474 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1475 mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg);
1476 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1477 mp -> lowsel, mp -> hghsel, mp -> numsel);
1478 #ifndef MTR
1479 printf ("lowoff=%d hghoff=%d\n",
1480 mp -> lowoff, mp -> hghoff);
1481 #else /* MTR */
1482 printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n",
1483 mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats);
1484 #endif /* MTR */
1485 }
1486
1487 if (seqp == 0 && (addsw || deletesw)) {
1488 advise (NULLCP, "-%s requires at least one -sequence argument",
1489 addsw ? "add" : "delete");
1490 return;
1491 }
1492 seqs[seqp] = NULL;
1493
1494 if (addsw)
1495 for (seqp = 0; seqs[seqp]; seqp++) {
1496 if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1497 return;
1498 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1499 if (mp -> msgstats[msgnum] & SELECTED)
1500 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1501 return;
1502 }
1503
1504 if (deletesw)
1505 for (seqp = 0; seqs[seqp]; seqp++) {
1506 if (zerosw)
1507 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1508 if (mp -> msgstats[msgnum] & EXISTS)
1509 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1510 return;
1511 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1512 if (mp -> msgstats[msgnum] & SELECTED)
1513 if (!m_seqdel (mp, seqs[seqp], msgnum))
1514 return;
1515 }
1516
1517 if (listsw) {
1518 int bits = FFATTRSLOT;
1519
1520 #define empty(s) ((s) ? (s) : "")
1521 if (seqp == 0)
1522 for (i = 0; mp -> msgattrs[i]; i++)
1523 printf ("%s%s: %s\n", mp -> msgattrs[i],
1524 mp -> attrstats & (1 << (bits + i))
1525 ? " (private)" : "",
1526 empty(m_seq (mp, mp -> msgattrs[i])));
1527 else
1528 for (seqp = 0; seqs[seqp]; seqp++)
1529 printf ("%s%s: %s\n", seqs[seqp],
1530 empty(m_seq (mp, seqs[seqp])));
1531 #undef empty
1532
1533 interrupted = 0;
1534 if (debugsw)
1535 for (msgnum = mp -> lowsel;
1536 msgnum <= mp -> hghsel && !interrupted;
1537 msgnum++)
1538 if (mp -> msgstats[msgnum] & SELECTED) {
1539 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1540 DMAXFOLDER, msgnum,
1541 Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top,
1542 Msgs[msgnum].m_start, Msgs[msgnum].m_stop,
1543 sprintb (buf, (unsigned) mp -> msgstats[msgnum],
1544 m_seqbits (mp)));
1545 if (Msgs[msgnum].m_scanl)
1546 printf ("%s", Msgs[msgnum].m_scanl);
1547 }
1548 }
1549 }
1550
1551 /* \f */
1552
1553 #ifdef MIME
1554 static struct swit mhnswit[] = {
1555 #define MHNAUTOSW 0
1556 "auto", 0,
1557 #define MHNNAUTOSW 1
1558 "noauto", 0,
1559 #define MHNDEBUGSW 2
1560 "debug", -5,
1561 #define MHNEBCDICSW 3
1562 "ebcdicsafe", 0,
1563 #define MHNNEBCDICSW 4
1564 "noebcdicsafe", 0,
1565 #define MHNFORMSW 5
1566 "form formfile", 4,
1567 #define MHNHEADSW 6
1568 "headers", 0,
1569 #define MHNNHEADSW 7
1570 "noheaders", 0,
1571 #define MHNLISTSW 8
1572 "list", 0,
1573 #define MHNNLISTSW 9
1574 "nolist", 0,
1575 #define MHNPARTSW 10
1576 "part number", 0,
1577 #define MHNSIZESW 11
1578 "realsize", 0,
1579 #define MHNNSIZESW 12
1580 "norealsize", 0,
1581 #define MHNRFC934SW 13
1582 "rfc934mode", 0,
1583 #define MHNNRFC934SW 14
1584 "norfc934mode", 0,
1585 #define MHNSERIALSW 15
1586 "serialonly", 0,
1587 #define MHNNSERIALSW 16
1588 "noserialonly", 0,
1589 #define MHNSHOWSW 17
1590 "show", 0,
1591 #define MHNNSHOWSW 18
1592 "noshow", 0,
1593 #define MHNSTORESW 19
1594 "store", 0,
1595 #define MHNNSTORESW 20
1596 "nostore", 0,
1597 #define MHNTYPESW 21
1598 "type content", 0,
1599 #define MHNVERBSW 22
1600 "verbose", 0,
1601 #define MHNNVERBSW 23
1602 "noverbose", 0,
1603 #define MHNHELPSW 24
1604 "help", 4,
1605 #define MHNPROGSW 25
1606 "moreproc program", -4,
1607 #define MHNNPROGSW 26
1608 "nomoreproc", -3,
1609 #define MHNLENSW 27
1610 "length lines", -4,
1611 #define MHNWIDSW 28
1612 "width columns", -4,
1613
1614 NULL, 0
1615 };
1616
1617 /* \f */
1618
1619 mhncmd (args)
1620 char **args;
1621 {
1622 int msgp = 0,
1623 vecp = 1,
1624 i,
1625 msgnum;
1626 char *cp,
1627 buf[BUFSIZ],
1628 *msgs[MAXARGS],
1629 *vec[MAXARGS];
1630
1631 if (fmsh) {
1632 forkcmd (args, cmd_name);
1633 return;
1634 }
1635
1636 while (cp = *args++) {
1637 if (*cp == '-')
1638 switch (smatch (++cp, mhnswit)) {
1639 case AMBIGSW:
1640 ambigsw (cp, mhnswit);
1641 return;
1642 case UNKWNSW:
1643 fprintf (stderr, "-%s unknown\n", cp);
1644 return;
1645 case MHNHELPSW:
1646 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1647 help (buf, mhnswit);
1648 return;
1649
1650 case MHNAUTOSW:
1651 case MHNNAUTOSW:
1652 case MHNDEBUGSW:
1653 case MHNEBCDICSW:
1654 case MHNNEBCDICSW:
1655 case MHNHEADSW:
1656 case MHNNHEADSW:
1657 case MHNLISTSW:
1658 case MHNNLISTSW:
1659 case MHNSIZESW:
1660 case MHNNSIZESW:
1661 case MHNRFC934SW:
1662 case MHNNRFC934SW:
1663 case MHNSERIALSW:
1664 case MHNNSERIALSW:
1665 case MHNSHOWSW:
1666 case MHNNSHOWSW:
1667 case MHNSTORESW:
1668 case MHNNSTORESW:
1669 case MHNVERBSW:
1670 case MHNNVERBSW:
1671 case MHNNPROGSW:
1672 vec[vecp++] = --cp;
1673 continue;
1674
1675 case MHNFORMSW:
1676 case MHNPARTSW:
1677 case MHNTYPESW:
1678 case MHNPROGSW:
1679 case MHNLENSW:
1680 case MHNWIDSW:
1681 vec[vecp++] = --cp;
1682 if (!(cp = *args++) || *cp == '-') {
1683 advise (NULLCP, "missing argument to %s", args[-2]);
1684 return;
1685 }
1686 vec[vecp++] = cp;
1687 continue;
1688 }
1689 if (*cp == '+' || *cp == '@') {
1690 advise (NULLCP, "sorry, no folders allowed!");
1691 return;
1692 }
1693 else
1694 msgs[msgp++] = cp;
1695 }
1696
1697 vec[0] = cmd_name;
1698 vec[vecp++] = "-file";
1699 vec[vecp] = NULL;
1700 if (!msgp)
1701 msgs[msgp++] = "cur";
1702 for (msgnum = 0; msgnum < msgp; msgnum++)
1703 if (!m_convert (mp, msgs[msgnum]))
1704 return;
1705 m_setseq (mp);
1706
1707 interrupted = 0;
1708 for (msgnum = mp -> lowsel;
1709 msgnum <= mp -> hghsel && !interrupted;
1710 msgnum++)
1711 if (mp -> msgstats[msgnum] & SELECTED)
1712 if (process (msgnum, cmd_name, vecp, vec)) {
1713 mp -> msgstats[msgnum] &= ~SELECTED;
1714 mp -> numsel--;
1715 }
1716
1717 m_setcur (mp, mp -> hghsel);
1718 }
1719
1720 /* \f */
1721
1722 #endif /* MIME */
1723 static struct swit packswit[] = {
1724 #define PAFISW 0
1725 "file name", 0,
1726
1727 #define PAHELP 1
1728 "help", 4,
1729
1730 NULL, 0
1731 };
1732
1733 /* \f */
1734
1735 packcmd (args)
1736 char **args;
1737 {
1738 int msgp = 0,
1739 md,
1740 msgnum;
1741 char *cp,
1742 *file = NULL,
1743 buf[BUFSIZ],
1744 *msgs[MAXARGS];
1745 struct stat st;
1746
1747 if (fmsh) {
1748 forkcmd (args, cmd_name);
1749 return;
1750 }
1751
1752 while (cp = *args++) {
1753 if (*cp == '-')
1754 switch (smatch (++cp, packswit)) {
1755 case AMBIGSW:
1756 ambigsw (cp, packswit);
1757 return;
1758 case UNKWNSW:
1759 fprintf (stderr, "-%s unknown\n", cp);
1760 return;
1761 case PAHELP:
1762 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1763 help (buf, packswit);
1764 return;
1765
1766 case PAFISW:
1767 if (!(file = *args++) || *file == '-') {
1768 advise (NULLCP, "missing argument to %s", args[-2]);
1769 return;
1770 }
1771 continue;
1772 }
1773 if (*cp == '+' || *cp == '@') {
1774 advise (NULLCP, "sorry, no folders allowed!");
1775 return;
1776 }
1777 else
1778 msgs[msgp++] = cp;
1779 }
1780
1781 if (!file)
1782 file = "./msgbox";
1783 file = path (file, TFILE);
1784 if (stat (file, &st) == NOTOK) {
1785 if (errno != ENOENT) {
1786 advise (file, "error on file");
1787 goto done_pack;
1788 }
1789 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP));
1790 free (cp);
1791 if (!md)
1792 goto done_pack;
1793 }
1794
1795 if (!msgp)
1796 msgs[msgp++] = "all";
1797 for (msgnum = 0; msgnum < msgp; msgnum++)
1798 if (!m_convert (mp, msgs[msgnum]))
1799 goto done_pack;
1800 m_setseq (mp);
1801
1802 if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1803 advise (file, "unable to open");
1804 goto done_pack;
1805 }
1806 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1807 if (mp -> msgstats[msgnum] & SELECTED)
1808 if (pack (file, md, msgnum) == NOTOK)
1809 break;
1810 (void) mbx_close (file, md);
1811
1812 if (mp -> hghsel != mp -> curmsg)
1813 m_setcur (mp, mp -> lowsel);
1814
1815 done_pack: ;
1816 free (file);
1817 }
1818
1819 /* \f */
1820
1821 int pack (mailbox, md, msgnum)
1822 char *mailbox;
1823 int md,
1824 msgnum;
1825 {
1826 register FILE *zp;
1827
1828 if (Msgs[msgnum].m_bboard_id == 0)
1829 (void) readid (msgnum);
1830
1831 zp = msh_ready (msgnum, 1);
1832 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1833 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1834 }
1835
1836 /* \f */
1837
1838 int packhak (args)
1839 char **args;
1840 {
1841 int result;
1842 char *cp,
1843 *file = NULL;
1844
1845 while (cp = *args++) {
1846 if (*cp == '-')
1847 switch (smatch (++cp, packswit)) {
1848 case AMBIGSW:
1849 case UNKWNSW:
1850 case PAHELP:
1851 return NOTOK;
1852
1853 case PAFISW:
1854 if (!(file = *args++) || *file == '-')
1855 return NOTOK;
1856 continue;
1857 }
1858 if (*cp == '+' || *cp == '@')
1859 return NOTOK;
1860 }
1861
1862 file = path (file ? file : "./msgbox", TFILE);
1863 result = access (file, 0) == NOTOK ? OK : NOTOK;
1864 free (file);
1865
1866 return result;
1867 }
1868
1869 /* \f */
1870
1871 static struct swit pickswit[] = {
1872 #define PIANSW 0
1873 "and", 0,
1874 #define PIORSW 1
1875 "or", 0,
1876 #define PINTSW 2
1877 "not", 0,
1878 #define PILBSW 3
1879 "lbrace", 0,
1880 #define PIRBSW 4
1881 "rbrace", 0,
1882
1883 #define PICCSW 5
1884 "cc pattern", 0,
1885 #define PIDASW 6
1886 "date pattern", 0,
1887 #define PIFRSW 7
1888 "from pattern", 0,
1889 #define PISESW 8
1890 "search pattern", 0,
1891 #define PISUSW 9
1892 "subject pattern", 0,
1893 #define PITOSW 10
1894 "to pattern", 0,
1895 #define PIOTSW 11
1896 "-othercomponent pattern", 15,
1897 #define PIAFSW 12
1898 "after date", 0,
1899 #define PIBFSW 13
1900 "before date", 0,
1901 #define PIDFSW 14
1902 "datefield field", 5,
1903 #define PISQSW 15
1904 "sequence name", 0,
1905 #define PIPUSW 16
1906 "public", 0,
1907 #define PINPUSW 17
1908 "nopublic", 0,
1909 #define PIZRSW 18
1910 "zero", 0,
1911 #define PINZRSW 19
1912 "nozero", 0,
1913 #define PILISW 20
1914 "list", 0,
1915 #define PINLISW 21
1916 "nolist", 0,
1917 #define PIHELP 22
1918 "help", 4,
1919
1920 NULL, 0
1921 };
1922
1923 /* \f */
1924
1925 pickcmd (args)
1926 char **args;
1927 {
1928 int zerosw = 1,
1929 msgp = 0,
1930 seqp = 0,
1931 vecp = 0,
1932 hi,
1933 lo,
1934 msgnum;
1935 char *cp,
1936 buf[BUFSIZ],
1937 *msgs[MAXARGS],
1938 *seqs[NATTRS],
1939 *vec[MAXARGS];
1940 register FILE *zp;
1941
1942 while (cp = *args++) {
1943 if (*cp == '-') {
1944 if (*++cp == '-') {
1945 vec[vecp++] = --cp;
1946 goto pattern;
1947 }
1948 switch (smatch (cp, pickswit)) {
1949 case AMBIGSW:
1950 ambigsw (cp, pickswit);
1951 return;
1952 case UNKWNSW:
1953 fprintf (stderr, "-%s unknown\n", cp);
1954 return;
1955 case PIHELP:
1956 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1957 help (buf, pickswit);
1958 return;
1959
1960 case PICCSW:
1961 case PIDASW:
1962 case PIFRSW:
1963 case PISUSW:
1964 case PITOSW:
1965 case PIDFSW:
1966 case PIAFSW:
1967 case PIBFSW:
1968 case PISESW:
1969 vec[vecp++] = --cp;
1970 pattern: ;
1971 if (!(cp = *args++)) {/* allow -xyz arguments */
1972 advise (NULLCP, "missing argument to %s", args[-2]);
1973 return;
1974 }
1975 vec[vecp++] = cp;
1976 continue;
1977 case PIOTSW:
1978 advise (NULLCP, "internal error!");
1979 return;
1980 case PIANSW:
1981 case PIORSW:
1982 case PINTSW:
1983 case PILBSW:
1984 case PIRBSW:
1985 vec[vecp++] = --cp;
1986 continue;
1987
1988 case PISQSW:
1989 if (!(cp = *args++) || *cp == '-') {
1990 advise (NULLCP, "missing argument to %s", args[-2]);
1991 return;
1992 }
1993 if (seqp < NATTRS)
1994 seqs[seqp++] = cp;
1995 else {
1996 advise (NULLCP, "only %d sequences allowed!", NATTRS);
1997 return;
1998 }
1999 continue;
2000 case PIZRSW:
2001 zerosw++;
2002 continue;
2003 case PINZRSW:
2004 zerosw = 0;
2005 continue;
2006
2007 case PIPUSW: /* not implemented */
2008 case PINPUSW:
2009 case PILISW:
2010 case PINLISW:
2011 continue;
2012 }
2013 }
2014 if (*cp == '+' || *cp == '@') {
2015 advise (NULLCP, "sorry, no folders allowed!");
2016 return;
2017 }
2018 else
2019 msgs[msgp++] = cp;
2020 }
2021 vec[vecp] = NULL;
2022
2023 if (!msgp)
2024 msgs[msgp++] = "all";
2025 for (msgnum = 0; msgnum < msgp; msgnum++)
2026 if (!m_convert (mp, msgs[msgnum]))
2027 return;
2028 m_setseq (mp);
2029
2030 interrupted = 0;
2031 if (!pcompile (vec, NULLCP))
2032 return;
2033
2034 lo = mp -> lowsel;
2035 hi = mp -> hghsel;
2036
2037 for (msgnum = mp -> lowsel;
2038 msgnum <= mp -> hghsel && !interrupted;
2039 msgnum++)
2040 if (mp -> msgstats[msgnum] & SELECTED) {
2041 zp = msh_ready (msgnum, 1);
2042 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
2043 fmsh ? 0L : Msgs[msgnum].m_stop)) {
2044 if (msgnum < lo)
2045 lo = msgnum;
2046 if (msgnum > hi)
2047 hi = msgnum;
2048 }
2049 else {
2050 mp -> msgstats[msgnum] &= ~SELECTED;
2051 mp -> numsel--;
2052 }
2053 }
2054
2055 if (interrupted)
2056 return;
2057
2058 mp -> lowsel = lo;
2059 mp -> hghsel = hi;
2060
2061 if (mp -> numsel <= 0) {
2062 advise (NULLCP, "no messages match specification");
2063 return;
2064 }
2065
2066 seqs[seqp] = NULL;
2067 for (seqp = 0; seqs[seqp]; seqp++) {
2068 if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
2069 return;
2070 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2071 if (mp -> msgstats[msgnum] & SELECTED)
2072 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
2073 return;
2074 }
2075
2076 printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s");
2077 }
2078
2079 /* \f */
2080
2081 static struct swit replswit[] = {
2082 #define REANSW 0
2083 "annotate", 0,
2084 #define RENANSW 1
2085 "noannotate", 0,
2086 #define RECCSW 2
2087 "cc type", 0,
2088 #define RENCCSW 3
2089 "nocc type", 0,
2090 #define REDFSW 4
2091 "draftfolder +folder", 0,
2092 #define REDMSW 5
2093 "draftmessage msg", 0,
2094 #define RENDFSW 6
2095 "nodraftfolder", 0,
2096 #define REEDTSW 7
2097 "editor editor", 0,
2098 #define RENEDSW 8
2099 "noedit", 0,
2100 #define REFCCSW 9
2101 "fcc +folder", 0,
2102 #define REFLTSW 10
2103 "filter filterfile", 0,
2104 #define REFRMSW 11
2105 "form formfile", 0,
2106 #define REINSW 12
2107 "inplace", 0,
2108 #define RENINSW 13
2109 "noinplace", 0,
2110 #define REQUSW 14
2111 "query", 0,
2112 #define RENQUSW 15
2113 "noquery", 0,
2114 #define REWHTSW 16
2115 "whatnowproc program", 0,
2116 #define RENWTSW 17
2117 "nowhatnow", 0,
2118 #define REWIDSW 19
2119 "width columns", 0,
2120 #define REHELP 20
2121 "help", 4,
2122
2123 NULL, 0
2124 };
2125
2126 /* \f */
2127
2128 replcmd (args)
2129 char **args;
2130 {
2131 int vecp = 1;
2132 char *cp,
2133 *msg = NULL,
2134 buf[BUFSIZ],
2135 *vec[MAXARGS];
2136
2137 if (fmsh) {
2138 forkcmd (args, cmd_name);
2139 return;
2140 }
2141
2142 while (cp = *args++) {
2143 if (*cp == '-')
2144 switch (smatch (++cp, replswit)) {
2145 case AMBIGSW:
2146 ambigsw (cp, replswit);
2147 return;
2148 case UNKWNSW:
2149 fprintf (stderr, "-%s unknown\n", cp);
2150 return;
2151 case REHELP:
2152 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2153 help (buf, replswit);
2154 return;
2155
2156 case REANSW: /* not implemented */
2157 case RENANSW:
2158 case REINSW:
2159 case RENINSW:
2160 continue;
2161
2162 case REQUSW:
2163 case RENQUSW:
2164 case RENDFSW:
2165 case RENEDSW:
2166 case RENWTSW:
2167 vec[vecp++] = --cp;
2168 continue;
2169
2170 case RECCSW:
2171 case RENCCSW:
2172 case REEDTSW:
2173 case REFCCSW:
2174 case REFLTSW:
2175 case REFRMSW:
2176 case REWIDSW:
2177 case REDFSW:
2178 case REDMSW:
2179 case REWHTSW:
2180 vec[vecp++] = --cp;
2181 if (!(cp = *args++) || *cp == '-') {
2182 advise (NULLCP, "missing argument to %s", args[-2]);
2183 return;
2184 }
2185 vec[vecp++] = cp;
2186 continue;
2187 }
2188 if (*cp == '+' || *cp == '@') {
2189 advise (NULLCP, "sorry, no folders allowed!");
2190 return;
2191 }
2192 else
2193 if (msg) {
2194 advise (NULLCP, "only one message at a time!");
2195 return;
2196 }
2197 else
2198 msg = cp;
2199 }
2200
2201 vec[0] = cmd_name;
2202 vec[vecp++] = "-file";
2203 vec[vecp] = NULL;
2204 if (!msg)
2205 msg = "cur";
2206 if (!m_convert (mp, msg))
2207 return;
2208 m_setseq (mp);
2209
2210 if (mp -> numsel > 1) {
2211 advise (NULLCP, "only one message at a time!");
2212 return;
2213 }
2214 (void) process (mp -> hghsel, cmd_name, vecp, vec);
2215 m_setcur (mp, mp -> hghsel);
2216 }
2217
2218 /* \f */
2219
2220 static struct swit rmmswit[] = {
2221 #define RMHELP 0
2222 "help", 4,
2223
2224 NULL, 0
2225 };
2226
2227 /* \f */
2228
2229 rmmcmd (args)
2230 char **args;
2231 {
2232 int msgp = 0,
2233 msgnum;
2234 char *cp,
2235 buf[BUFSIZ],
2236 *msgs[MAXARGS];
2237
2238 while (cp = *args++) {
2239 if (*cp == '-')
2240 switch (smatch (++cp, rmmswit)) {
2241 case AMBIGSW:
2242 ambigsw (cp, rmmswit);
2243 return;
2244 case UNKWNSW:
2245 fprintf (stderr, "-%s unknown\n", cp);
2246 return;
2247 case RMHELP:
2248 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2249 help (buf, rmmswit);
2250 return;
2251 }
2252 if (*cp == '+' || *cp == '@') {
2253 advise (NULLCP, "sorry, no folders allowed!");
2254 return;
2255 }
2256 else
2257 msgs[msgp++] = cp;
2258 }
2259
2260 if (!msgp)
2261 msgs[msgp++] = "cur";
2262 for (msgnum = 0; msgnum < msgp; msgnum++)
2263 if (!m_convert (mp, msgs[msgnum]))
2264 return;
2265 m_setseq (mp);
2266
2267 rmm ();
2268 }
2269
2270 /* \f */
2271
2272 static rmm () {
2273 register int msgnum,
2274 vecp;
2275 register char *cp;
2276 char buffer[BUFSIZ],
2277 *vec[MAXARGS];
2278
2279 if (fmsh) {
2280 if (rmmproc) {
2281 if (mp -> numsel > MAXARGS - 1) {
2282 advise (NULLCP, "more than %d messages for %s exec",
2283 MAXARGS - 1, rmmproc);
2284 return;
2285 }
2286 vecp = 0;
2287 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2288 if (mp -> msgstats[msgnum] & SELECTED)
2289 vec[vecp++] = getcpy (m_name (msgnum));
2290 vec[vecp] = NULL;
2291 forkcmd (vec, rmmproc);
2292 for (vecp = 0; vec[vecp]; vecp++)
2293 free (vec[vecp]);
2294 }
2295 else
2296 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2297 if (mp -> msgstats[msgnum] & SELECTED) {
2298 (void) strcpy (buffer, m_backup (cp = m_name (msgnum)));
2299 if (rename (cp, buffer) == NOTOK)
2300 admonish (buffer, "unable to rename %s to", cp);
2301 }
2302 }
2303
2304 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2305 if (mp -> msgstats[msgnum] & SELECTED) {
2306 mp -> msgstats[msgnum] |= DELETED;
2307 mp -> msgstats[msgnum] &= ~EXISTS;
2308 #ifdef MPOP
2309 #ifdef BPOP
2310 if (pmsh && pop_dele (msgnum) != OK)
2311 fprintf (stderr, "%s", response);
2312 #endif
2313 #endif /* MPOP */
2314 }
2315
2316 if ((mp -> nummsg -= mp -> numsel) <= 0) {
2317 if (fmsh)
2318 admonish (NULLCP, "no messages remaining in +%s", fmsh);
2319 else
2320 admonish (NULLCP, "no messages remaining in %s", mp -> foldpath);
2321 mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
2322 }
2323 if (mp -> lowsel == mp -> lowmsg) {
2324 for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
2325 if (mp -> msgstats[msgnum] & EXISTS)
2326 break;
2327 mp -> lowmsg = msgnum;
2328 }
2329 if (mp -> hghsel == mp -> hghmsg) {
2330 for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--)
2331 if (mp -> msgstats[msgnum] & EXISTS)
2332 break;
2333 mp -> hghmsg = msgnum;
2334 }
2335
2336 mp -> msgflags |= MODIFIED;
2337 modified++;
2338 }
2339
2340 /* \f */
2341
2342 static struct swit scanswit[] = {
2343 #define SCCLR 0
2344 "clear", 0,
2345 #define SCNCLR 1
2346 "noclear", 0,
2347 #define SCFORM 2
2348 "form formatfile", 0,
2349 #define SCFMT 3
2350 "format string", 5,
2351 #define SCHEAD 4
2352 "header", 0,
2353 #define SCNHEAD 5
2354 "noheader", 0,
2355 #define SCWID 6
2356 "width columns", 0,
2357 #define SCHELP 7
2358 "help", 4,
2359
2360 NULL, 0
2361 };
2362
2363 /* \f */
2364
2365 scancmd (args)
2366 char **args;
2367 {
2368 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2369
2370 int clearsw = 0,
2371 headersw = 0,
2372 width = 0,
2373 msgp = 0,
2374 msgnum,
2375 optim,
2376 state;
2377 char *cp,
2378 *form = NULL,
2379 *format = NULL,
2380 buf[BUFSIZ],
2381 *nfs,
2382 *msgs[MAXARGS];
2383 register FILE *zp;
2384 #ifdef MPOP
2385 #ifdef BPOP
2386 static int p_optim = 0;
2387 #endif
2388 #endif /* MPOP */
2389 static int s_optim = 0;
2390 static char *s_form = NULL,
2391 *s_format = NULL;
2392
2393 while (cp = *args++) {
2394 if (*cp == '-')
2395 switch (smatch (++cp, scanswit)) {
2396 case AMBIGSW:
2397 ambigsw (cp, scanswit);
2398 return;
2399 case UNKWNSW:
2400 fprintf (stderr, "-%s unknown\n", cp);
2401 return;
2402 case SCHELP:
2403 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2404 help (buf, scanswit);
2405 return;
2406
2407 case SCCLR:
2408 clearsw++;
2409 continue;
2410 case SCNCLR:
2411 clearsw = 0;
2412 continue;
2413 case SCHEAD:
2414 headersw++;
2415 continue;
2416 case SCNHEAD:
2417 headersw = 0;
2418 continue;
2419 case SCFORM:
2420 if (!(form = *args++) || *form == '-') {
2421 advise (NULLCP, "missing argument to %s", args[-2]);
2422 return;
2423 }
2424 format = NULL;
2425 continue;
2426 case SCFMT:
2427 if (!(format = *args++) || *format == '-') {
2428 advise (NULLCP, "missing argument to %s", args[-2]);
2429 return;
2430 }
2431 form = NULL;
2432 continue;
2433 case SCWID:
2434 if (!(cp = *args++) || *cp == '-') {
2435 advise (NULLCP, "missing argument to %s", args[-2]);
2436 return;
2437 }
2438 width = atoi (cp);
2439 continue;
2440 }
2441 if (*cp == '+' || *cp == '@') {
2442 advise (NULLCP, "sorry, no folders allowed!");
2443 return;
2444 }
2445 else
2446 msgs[msgp++] = cp;
2447 }
2448
2449 if (!msgp)
2450 msgs[msgp++] = "all";
2451 for (msgnum = 0; msgnum < msgp; msgnum++)
2452 if (!m_convert (mp, msgs[msgnum]))
2453 return;
2454 m_setseq (mp);
2455
2456 nfs = new_fs (form, format, FORMAT);
2457 if (scanl) { /* force scansbr to (re)compile format */
2458 (void) free (scanl);
2459 scanl = NULL;
2460 }
2461
2462 if (s_optim == 0) {
2463 s_optim = optim = 1;
2464 s_form = form ? getcpy (form) : NULL;
2465 s_format = format ? getcpy (format) : NULL;
2466
2467 #ifdef MPOP
2468 #ifdef BPOP
2469 if (pmsh) {
2470 int i;
2471 char *dp,
2472 *ep,
2473 *fp;
2474
2475 if (width == 0)
2476 width = sc_width ();
2477
2478 for (dp = nfs, i = 0; *dp; dp++, i++)
2479 if (*dp == '\\' || *dp == '"' || *dp == '\n')
2480 i++;
2481 i++;
2482 if ((ep = malloc ((unsigned) i)) == NULL)
2483 adios (NULLCP, "out of memory");
2484 for (dp = nfs, fp = ep; *dp; dp++) {
2485 if (*dp == '\n') {
2486 *fp++ = '\\', *fp++ = 'n';
2487 continue;
2488 }
2489 if (*dp == '"' || *dp == '\\')
2490 *fp++ = '\\';
2491 *fp++ = *dp;
2492 }
2493 *fp = NULL;
2494
2495 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
2496 p_optim = 1;
2497
2498 free (ep);
2499 }
2500 #endif
2501 #endif /* MPOP */
2502 }
2503 else
2504 optim = equiv (s_form, form) && equiv (s_format, format);
2505
2506 #ifdef MPOP
2507 #ifdef BPOP
2508 if (p_optim && optim) {
2509 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
2510 if (!(mp -> msgstats[msgnum] & SELECTED) || Msgs[msgnum].m_scanl)
2511 break;
2512 if (msgnum > mp -> hghmsg && pop_command ("LIST") == OK) {
2513 fprintf (stderr, "Stand-by...");
2514 fflush (stderr);
2515
2516 for (;;) {
2517 int size;
2518
2519 switch (pop_multiline ()) {
2520 case NOTOK:
2521 fprintf (stderr, "%s", response);
2522 /* and fall... */
2523 case DONE:
2524 fprintf (stderr,"\n");
2525 break;
2526
2527 case OK:
2528 if (sscanf (response, "%d %d", &msgnum, &size) == 2
2529 && mp -> lowmsg <= msgnum
2530 && msgnum <= mp -> hghmsg
2531 && (cp = index (response, '#'))
2532 && *++cp)
2533 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
2534 continue;
2535 }
2536 break;
2537 }
2538 }
2539 }
2540 #endif
2541 #endif /* MPOP */
2542
2543 interrupted = 0;
2544 for (msgnum = mp -> lowsel;
2545 msgnum <= mp -> hghsel && !interrupted;
2546 msgnum++)
2547 if (mp -> msgstats[msgnum] & SELECTED) {
2548 if (optim && Msgs[msgnum].m_scanl)
2549 printf ("%s", Msgs[msgnum].m_scanl);
2550 else {
2551 #ifdef MPOP
2552 #ifdef BPOP
2553 if (p_optim
2554 && optim
2555 && (mp -> msgstats[msgnum] & VIRTUAL)
2556 && pop_command ("LIST %d", msgnum) == OK
2557 && (cp = index (response, '#'))
2558 && *++cp) {
2559 Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
2560 printf ("%s", Msgs[msgnum].m_scanl);
2561 continue;
2562 }
2563 #endif
2564 #endif /* MPOP */
2565
2566 zp = msh_ready (msgnum, 0);
2567 switch (state = scan (zp, msgnum, 0, nfs, width,
2568 msgnum == mp -> curmsg,
2569 mp -> msgstats[msgnum] & UNSEEN, /* ?? */
2570 headersw, fmsh ? fmsh : mp -> foldpath,
2571 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2572 1)) {
2573 case SCNMSG:
2574 case SCNENC:
2575 case SCNERR:
2576 if (optim)
2577 Msgs[msgnum].m_scanl = getcpy (scanl);
2578 break;
2579
2580 default:
2581 advise (NULLCP, "scan() botch (%d)", state);
2582 return;
2583
2584 case SCNEOF:
2585 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2586 break;
2587 }
2588 }
2589 headersw = 0;
2590 }
2591
2592 if (clearsw)
2593 clear_screen ();
2594 }
2595
2596 /* \f */
2597
2598 static struct swit showswit[] = {
2599 #define SHDRAFT 0
2600 "draft", 5,
2601 #define SHFORM 1
2602 "form formfile", 4,
2603 #define SHPROG 2
2604 "moreproc program", 4,
2605 #define SHNPROG 3
2606 "nomoreproc", 3,
2607 #define SHLEN 4
2608 "length lines", 4,
2609 #define SHWID 5
2610 "width columns", 4,
2611 #define SHSHOW 6
2612 "showproc program", 4,
2613 #define SHNSHOW 7
2614 "noshowproc", 3,
2615 #define SHHEAD 8
2616 "header", 4,
2617 #define SHNHEAD 9
2618 "noheader", 3,
2619 #define SHHELP 10
2620 "help", 4,
2621
2622 NULL, 0
2623 };
2624
2625 /* \f */
2626
2627 showcmd (args)
2628 char **args;
2629 {
2630 int headersw = 1,
2631 nshow = 0,
2632 msgp = 0,
2633 vecp = 1,
2634 mhl = 0,
2635 seen = 0,
2636 mode = 0,
2637 i,
2638 msgnum;
2639 char *cp,
2640 *proc = showproc,
2641 buf[BUFSIZ],
2642 *msgs[MAXARGS],
2643 *vec[MAXARGS];
2644
2645 if (uleq (cmd_name, "next"))
2646 mode = 1;
2647 else
2648 if (uleq (cmd_name, "prev"))
2649 mode = -1;
2650 while (cp = *args++) {
2651 if (*cp == '-')
2652 switch (i = smatch (++cp, showswit)) {
2653 case AMBIGSW:
2654 ambigsw (cp, showswit);
2655 return;
2656 case UNKWNSW:
2657 case SHNPROG:
2658 vec[vecp++] = --cp;
2659 continue;
2660 case SHHELP:
2661 (void) sprintf (buf,
2662 "%s %s[switches] [switches for showproc]",
2663 cmd_name, mode ? NULL : "[msgs] ");
2664 help (buf, showswit);
2665 return;
2666
2667 case SHFORM:
2668 case SHPROG:
2669 case SHLEN:
2670 case SHWID:
2671 vec[vecp++] = --cp;
2672 if (!(cp = *args++) || *cp == '-') {
2673 advise (NULLCP, "missing argument to %s", args[-2]);
2674 return;
2675 }
2676 vec[vecp++] = cp;
2677 continue;
2678 case SHHEAD:
2679 headersw++;
2680 continue;
2681 case SHNHEAD:
2682 headersw = 0;
2683 continue;
2684 case SHSHOW:
2685 if (!(proc = *args++) || *proc == '-') {
2686 advise (NULLCP, "missing argument to %s", args[-2]);
2687 return;
2688 }
2689 nshow = 0;
2690 continue;
2691 case SHNSHOW:
2692 nshow++;
2693 continue;
2694
2695 case SHDRAFT:
2696 advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw);
2697 return;
2698 }
2699 if (*cp == '+' || *cp == '@') {
2700 advise (NULLCP, "sorry, no folders allowed!");
2701 return;
2702 }
2703 else
2704 if (mode) {
2705 fprintf (stderr,
2706 "usage: %s [switches] [switches for showproc]\n",
2707 cmd_name);
2708 return;
2709 }
2710 else
2711 msgs[msgp++] = cp;
2712 }
2713 vec[vecp] = NULL;
2714
2715 if (!msgp)
2716 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2717 for (msgnum = 0; msgnum < msgp; msgnum++)
2718 if (!m_convert (mp, msgs[msgnum]))
2719 return;
2720 m_setseq (mp);
2721
2722 #ifdef MIME
2723 if (!nshow && !getenv ("NOMHNPROC"))
2724 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2725 if ((mp -> msgstats[msgnum] & SELECTED) && nontext (msgnum)) {
2726 proc = (cp = m_find ("mhnproc")) ? cp : "mhn";
2727 vec[vecp++] = "-show";
2728 vec[vecp++] = "-file";
2729 vec[vecp] = NULL;
2730 goto finish;
2731 }
2732 #endif /* MIME */
2733
2734 if (nshow)
2735 proc = "cat";
2736 else
2737 if (strcmp (showproc, "mhl") == 0) {
2738 proc = mhlproc;
2739 mhl++;
2740 }
2741
2742 finish: ;
2743 seen = m_seqflag (mp, "unseen");
2744 vec[0] = r1bindex (proc, '/');
2745 if (mhl) {
2746 msgp = vecp;
2747 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2748 if (mp -> msgstats[msgnum] & SELECTED) {
2749 vec[vecp++] = getcpy (m_name (msgnum));
2750 if (seen)
2751 (void) m_seqdel (mp, "unseen", msgnum);
2752 }
2753 vec[vecp] = NULL;
2754 if (mp -> numsel == 1 && headersw)
2755 show (mp -> lowsel);
2756 (void) mhlsbr (vecp, vec, mhl_action);
2757 m_eomsbr ((int (*)()) 0);
2758 while (msgp < vecp)
2759 free (vec[msgp++]);
2760 }
2761 else {
2762 interrupted = 0;
2763 for (msgnum = mp -> lowsel;
2764 msgnum <= mp -> hghsel && !interrupted;
2765 msgnum++)
2766 if (mp -> msgstats[msgnum] & SELECTED) {
2767 switch (ask (msgnum)) {
2768 case NOTOK: /* QUIT */
2769 break;
2770
2771 case OK: /* INTR */
2772 continue;
2773
2774 default:
2775 if (mp -> numsel == 1 && headersw)
2776 show (msgnum);
2777 if (nshow)
2778 copy_message (msgnum, stdout);
2779 else
2780 (void) process (msgnum, proc, vecp, vec);
2781
2782 if (seen)
2783 (void) m_seqdel (mp, "unseen", msgnum);
2784 continue;
2785 }
2786 break;
2787 }
2788 }
2789
2790 m_setcur (mp, mp -> hghsel);
2791 }
2792
2793 /* \f */
2794
2795 static show (msgnum)
2796 int msgnum;
2797 {
2798 if (Msgs[msgnum].m_bboard_id == 0)
2799 (void) readid (msgnum);
2800
2801 printf ("(Message %d", msgnum);
2802 if (Msgs[msgnum].m_bboard_id > 0)
2803 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2804 printf (")\n");
2805 }
2806
2807
2808 /* ARGSUSED */
2809
2810 static int eom_action (c)
2811 int c;
2812 {
2813 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2814 }
2815
2816
2817 static FP mhl_action (name)
2818 char *name;
2819 {
2820 int msgnum;
2821
2822 if ((msgnum = m_atoi (name)) < mp -> lowmsg
2823 || msgnum > mp -> hghmsg
2824 || !(mp -> msgstats[msgnum] & EXISTS))
2825 return NULL;
2826 mhlnum = msgnum;
2827
2828 mhlfp = msh_ready (msgnum, 1);
2829 if (!fmsh)
2830 m_eomsbr (eom_action);
2831
2832 return mhlfp;
2833 }
2834
2835
2836 /* \f */
2837
2838 static ask (msgnum)
2839 int msgnum;
2840 {
2841 char buf[BUFSIZ];
2842
2843 if (mp -> numsel == 1 || !interactive || redirected)
2844 return DONE;
2845
2846 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2847 if (mp -> lowsel != msgnum)
2848 printf ("\n\n\n");
2849 printf ("Press <return> to list \"%d\"...", msgnum);
2850 }
2851 (void) fflush (stdout);
2852 buf[0] = 0;
2853 #ifndef BSD42
2854 (void) read (fileno (stdout), buf, sizeof buf);
2855 #else /* BSD42 */
2856 switch (setjmp (sigenv)) {
2857 case OK:
2858 should_intr = 1;
2859 (void) read (fileno (stdout), buf, sizeof buf);/* fall... */
2860
2861 default:
2862 should_intr = 0;
2863 break;
2864 }
2865 #endif /* BSD42 */
2866 if (index (buf, '\n') == NULL)
2867 (void) putchar ('\n');
2868
2869 if (told_to_quit) {
2870 told_to_quit = interrupted = 0;
2871 return NOTOK;
2872 }
2873 if (interrupted) {
2874 interrupted = 0;
2875 return OK;
2876 }
2877
2878 return DONE;
2879 }
2880
2881 /* \f */
2882
2883 #ifdef MIME
2884 #include "../h/mhn.h"
2885
2886
2887 static int nontext (msgnum)
2888 int msgnum;
2889 {
2890 int result,
2891 state;
2892 register char *bp,
2893 *dp;
2894 char *chset,
2895 *cp,
2896 buf[BUFSIZ],
2897 name[NAMESZ];
2898 FILE *fp;
2899
2900 if (Msgs[msgnum].m_flags & MHNCHK)
2901 return (Msgs[msgnum].m_flags & MHNYES);
2902 Msgs[msgnum].m_flags |= MHNCHK;
2903
2904 fp = msh_ready (msgnum, 1);
2905
2906 if (!(chset = getenv ("MM_CHARSET")))
2907 chset = "us-ascii";
2908
2909 for (state = FLD;;)
2910 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2911 case FLD:
2912 case FLDPLUS:
2913 case FLDEOF:
2914 if (uleq (name, TYPE_FIELD)) {
2915 int passno;
2916 char c;
2917
2918 cp = add (buf, NULLCP);
2919 while (state == FLDPLUS) {
2920 state = m_getfld (state, name, buf, sizeof buf, fp);
2921 cp = add (buf, cp);
2922 }
2923 bp = cp;
2924 passno = 1;
2925
2926 again: ;
2927 for (; isspace (*bp); bp++)
2928 continue;
2929 if (*bp == '(') {
2930 int i;
2931
2932 for (bp++, i = 0;;) {
2933 switch (*bp++) {
2934 case '\0':
2935 invalid: ;
2936 result = 0;
2937 goto out;
2938 case '\\':
2939 if (*bp++ == '\0')
2940 goto invalid;
2941 continue;
2942 case '(':
2943 i++;
2944 /* and fall... */
2945 default:
2946 continue;
2947 case ')':
2948 if (--i < 0)
2949 break;
2950 continue;
2951 }
2952 break;
2953 }
2954 }
2955 if (passno == 2) {
2956 if (*bp != '/')
2957 goto invalid;
2958 bp++;
2959 passno = 3;
2960 goto again;
2961 }
2962 for (dp = bp; istoken (*dp); dp++)
2963 continue;
2964 c = *dp, *dp = NULL;
2965 if (*bp == NULL)
2966 goto invalid;
2967 if (passno > 1) {
2968 if (result = !uleq (bp, "plain"))
2969 goto out;
2970 *dp = c;
2971 for (dp++; isspace (*dp); dp++)
2972 continue;
2973 if (result = !uprf (dp, "charset"))
2974 goto invalid;
2975 dp += sizeof "charset" - 1;
2976 while (isspace (*dp))
2977 dp++;
2978 if (*dp++ != '=')
2979 goto invalid;
2980 while (isspace (*dp))
2981 dp++;
2982 if (*dp == '"') {
2983 if (bp = index (++dp, '"'))
2984 *bp = NULL;
2985 }
2986 else
2987 for (bp = dp; *bp; bp++)
2988 if (isspace (*bp)) {
2989 *bp = NULL;
2990 break;
2991 }
2992 if ((result = !uleq (dp, chset))
2993 && uleq (dp, "us-ascii")
2994 && uleq (chset, "iso-8859-1"))
2995 result = 0;
2996 }
2997 else
2998 if (!(result = !uleq (bp, "text"))) {
2999 *dp = c;
3000 bp = dp;
3001 passno = 2;
3002 goto again;
3003 }
3004
3005 out: ;
3006 free (cp);
3007
3008 if (result) {
3009 Msgs[msgnum].m_flags |= MHNYES;
3010 return result;
3011 }
3012 break;
3013 }
3014 if (uleq (name, ENCODING_FIELD)) {
3015 cp = add (buf, NULLCP);
3016 while (state == FLDPLUS) {
3017 state = m_getfld (state, name, buf, sizeof buf, fp);
3018 cp = add (buf, cp);
3019 }
3020 for (bp = cp; isspace (*bp); bp++)
3021 continue;
3022 for (dp = bp; istoken (*dp); dp++)
3023 continue;
3024 *dp = NULL;
3025 result = !uleq (bp, "7bit")
3026 && !uleq (bp, "8bit")
3027 && !uleq (bp, "binary");
3028
3029 free (cp);
3030 if (result) {
3031 Msgs[msgnum].m_flags |= MHNYES;
3032 return result;
3033 }
3034 break;
3035 }
3036 while (state == FLDPLUS)
3037 state = m_getfld (state, name, buf, sizeof buf, fp);
3038 break;
3039
3040 default:
3041 return 0;
3042 }
3043 }
3044 #endif /* MIME */
3045
3046 /* \f */
3047
3048 static struct swit sortswit[] = {
3049 #define SODATE 0
3050 "datefield field", 0,
3051 #define SOSUBJ 1
3052 "textfield field", 0,
3053 #define SONSUBJ 2
3054 "notextfield", 0,
3055 #define SOLIMT 3
3056 "limit days", 0,
3057 #define SONLIMT 4
3058 "nolimit", 0,
3059 #define SOVERB 5
3060 "verbose", 0,
3061 #define SONVERB 6
3062 "noverbose", 0,
3063 #define SOHELP 7
3064 "help", 4,
3065
3066 NULL, 0
3067 };
3068
3069 /* \f */
3070
3071 sortcmd (args)
3072 char **args;
3073 {
3074 int msgp = 0,
3075 msgnum;
3076 char *cp,
3077 *datesw = NULL,
3078 *subjsw = NULL,
3079 buf[BUFSIZ],
3080 *msgs[MAXARGS];
3081 struct tws tb,
3082 *tw;
3083
3084 if (fmsh) {
3085 forkcmd (args, cmd_name);
3086 return;
3087 }
3088
3089 while (cp = *args++) {
3090 if (*cp == '-')
3091 switch (smatch (++cp, sortswit)) {
3092 case AMBIGSW:
3093 ambigsw (cp, sortswit);
3094 return;
3095 case UNKWNSW:
3096 fprintf (stderr, "-%s unknown\n", cp);
3097 return;
3098 case SOHELP:
3099 (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
3100 help (buf, sortswit);
3101 return;
3102
3103 case SODATE:
3104 if (datesw) {
3105 advise (NULLCP, "only one date field at a time!");
3106 return;
3107 }
3108 if (!(datesw = *args++) || *datesw == '-') {
3109 advise (NULLCP, "missing argument to %s", args[-2]);
3110 return;
3111 }
3112 continue;
3113
3114 case SOSUBJ:
3115 if (subjsw) {
3116 advise (NULLCP, "only one text field at a time!");
3117 return;
3118 }
3119 if (!(subjsw = *args++) || *subjsw == '-') {
3120 advise (NULLCP, "missing argument to %s", args[-2]);
3121 return;
3122 }
3123 continue;
3124 case SONSUBJ:
3125 subjsw = (char *)0;
3126 continue;
3127
3128 case SOLIMT: /* too hard */
3129 if (!(cp = *args++) || *cp == '-') {
3130 advise (NULLCP, "missing argument to %s", args[-2]);
3131 return;
3132 }
3133 case SONLIMT:
3134 case SOVERB: /* not implemented */
3135 case SONVERB:
3136 continue;
3137 }
3138 if (*cp == '+' || *cp == '@') {
3139 advise (NULLCP, "sorry, no folders allowed!");
3140 return;
3141 }
3142 else
3143 msgs[msgp++] = cp;
3144 }
3145
3146 if (!msgp)
3147 msgs[msgp++] = "all";
3148 if (!datesw)
3149 datesw = "Date";
3150 for (msgnum = 0; msgnum < msgp; msgnum++)
3151 if (!m_convert (mp, msgs[msgnum]))
3152 return;
3153 m_setseq (mp);
3154
3155 twscopy (&tb, dtwstime ());
3156
3157 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
3158 if (Msgs[msgnum].m_scanl) {
3159 free (Msgs[msgnum].m_scanl);
3160 Msgs[msgnum].m_scanl = NULL;
3161 }
3162 if (mp -> msgstats[msgnum] & SELECTED) {
3163 if (getws (datesw, subjsw, msgnum, &Msgs[msgnum]))
3164 twscopy (&Msgs[msgnum].m_tb,
3165 msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
3166 }
3167 else /* m_scaln is already NULL */
3168 twscopy (&Msgs[msgnum].m_tb, &tb);
3169 Msgs[msgnum].m_stats = mp -> msgstats[msgnum];
3170 if (mp -> curmsg == msgnum)
3171 Msgs[msgnum].m_stats |= CUR;
3172 }
3173
3174 qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1,
3175 sizeof (struct Msg),
3176 subjsw ? subsort : msgsort);
3177
3178 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
3179 if (subjsw && Msgs[msgnum].m_scanl) {
3180 free (Msgs[msgnum].m_scanl); /* from subjsort */
3181 Msgs[msgnum].m_scanl = NULL;
3182 }
3183 mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR;
3184 if (Msgs[msgnum].m_stats & CUR)
3185 m_setcur (mp, msgnum);
3186 }
3187
3188 mp -> msgflags |= MODIFIED;
3189 modified++;
3190 }
3191
3192 /* \f */
3193
3194 /*
3195 * getws - parse message, and get date and subject if needed. We'll use
3196 * the msgp->m_tb tws struct for the date, and overload the msgp->m_scanl
3197 * field with our subject string.
3198 */
3199 static int getws (datesw, subjsw, msgnum, msgp)
3200 char *datesw,
3201 *subjsw;
3202 int msgnum;
3203 struct Msg *msgp;
3204 {
3205 int state,
3206 gotdate = 0;
3207 char *bp,
3208 buf[BUFSIZ],
3209 name[NAMESZ];
3210 struct tws *tw = (struct tws *)0;
3211 register FILE *zp;
3212
3213 zp = msh_ready (msgnum, 0);
3214 for (state = FLD;;) {
3215 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
3216 case FLD:
3217 case FLDEOF:
3218 case FLDPLUS:
3219 if (uleq (name, datesw)) {
3220 bp = getcpy (buf);
3221 while (state == FLDPLUS) {
3222 state = m_getfld (state, name, buf, sizeof buf, zp);
3223 bp = add (buf, bp);
3224 }
3225 if ((tw = dparsetime (bp)) == NULL)
3226 admonish (NULLCP,
3227 "unable to parse %s field in message %d",
3228 datesw, msgnum);
3229 else
3230 twscopy (&(msgp->m_tb), tw);
3231 free (bp);
3232 if (!subjsw) /* not using this, or already done */
3233 break; /* all done! */
3234 gotdate++;
3235 }
3236 else if (subjsw && uleq(name, subjsw)) {
3237 bp = getcpy (buf);
3238 while (state == FLDPLUS) {
3239 state = m_getfld (state, name, buf, sizeof buf, zp);
3240 bp = add (buf, bp);
3241 }
3242 msgp->m_scanl = sosmash(subjsw, bp);
3243 if (gotdate)
3244 break; /* date done so we're done */
3245 else
3246 subjsw = (char *)0;/* subject done, need date */
3247 } else {
3248 while (state == FLDPLUS) /* flush this one */
3249 state = m_getfld (state, name, buf, sizeof buf, zp);
3250 }
3251 continue;
3252
3253 case BODY:
3254 case BODYEOF:
3255 case FILEEOF:
3256 break;
3257
3258 case LENERR:
3259 case FMTERR:
3260 admonish (NULLCP, "format error in message %d", msgnum);
3261 if (msgp->m_scanl) { /* this might need free'd */
3262 free (msgp->m_scanl); /* probably can't use subj anyway */
3263 msgp->m_scanl = NULL;
3264 }
3265 return NOTOK;
3266
3267 default:
3268 adios (NULLCP, "internal error -- you lose");
3269 }
3270 break;
3271 }
3272 if (tw)
3273 return OK; /* not an error if subj not found */
3274
3275 admonish (NULLCP, "no %s field in message %d", datesw, msgnum);
3276 return NOTOK; /* NOTOK means use some other date */
3277 }
3278
3279 /* sort routines */
3280
3281 static int msgsort (a, b)
3282 struct Msg *a,
3283 *b;
3284 {
3285 return twsort (&a -> m_tb, &b -> m_tb);
3286 }
3287
3288 static int subsort (a, b)
3289 struct Msg *a,
3290 *b;
3291 {
3292 register int i;
3293
3294 if (a->m_scanl && b->m_scanl)
3295 if (i = strcmp (a->m_scanl, b->m_scanl))
3296 return (i);
3297
3298 return twsort (&a -> m_tb, &b -> m_tb);
3299 }
3300
3301 /*
3302 * try to make the subject "canonical": delete leading "re:", everything
3303 * but letters & smash letters to lower case.
3304 */
3305 static char *
3306 sosmash (subj, s)
3307 char *subj;
3308 register char *s;
3309 {
3310 register char *cp,
3311 *dp,
3312 c;
3313 if (s) {
3314 cp = s;
3315 dp = s; /* dst pointer */
3316 if (uleq (subj, "subject"))
3317 while (c = *cp) {
3318 if (! isspace(c)) {
3319 if(uprf(cp, "re:"))
3320 cp += 2;
3321 else {
3322 if (isalnum(c))
3323 *dp++ = isupper(c) ? tolower(c) : c;
3324 break;
3325 }
3326 }
3327 cp++;
3328 }
3329 while (c = *cp++) {
3330 if (isalnum(c))
3331 *dp++ = isupper(c) ? tolower(c) : c;
3332
3333 }
3334 *dp = '\0';
3335 }
3336 return s;
3337 }
3338
3339 /* \f */
3340
3341 static int process (msgnum, proc, vecp, vec)
3342 int msgnum,
3343 vecp;
3344 char *proc,
3345 **vec;
3346 {
3347 int child_id,
3348 status;
3349 char tmpfil[80];
3350 FILE *out;
3351
3352 if (fmsh) {
3353 (void) strcpy (tmpfil, m_name (msgnum));
3354 (void) m_delete (pfolder);
3355 m_replace (pfolder, fmsh);
3356 m_sync (mp);
3357 m_update ();
3358 goto ready;
3359 }
3360
3361 (void) strcpy (tmpfil, m_scratch ("", invo_name));
3362 if ((out = fopen (tmpfil, "w")) == NULL) {
3363 int olderr;
3364 extern int errno;
3365 char newfil[80];
3366
3367 olderr = errno;
3368 (void) strcpy (newfil, m_tmpfil (invo_name));
3369 if ((out = fopen (newfil, "w")) == NULL) {
3370 errno = olderr;
3371 advise (tmpfil, "unable to create temporary file");
3372 return NOTOK;
3373 }
3374 else
3375 (void) strcpy (tmpfil, newfil);
3376 }
3377 copy_message (msgnum, out);
3378 (void) fclose (out);
3379
3380 ready: ;
3381 (void) fflush (stdout);
3382 switch (child_id = fork ()) {
3383 case NOTOK:
3384 advise ("fork", "unable to");
3385 status = NOTOK;
3386 break;
3387
3388 case OK:
3389 closefds (3);
3390 (void) signal (SIGINT, istat);
3391 (void) signal (SIGQUIT, qstat);
3392
3393 vec[vecp++] = tmpfil;
3394 vec[vecp] = NULL;
3395
3396 execvp (proc, vec);
3397 fprintf (stderr, "unable to exec ");
3398 perror (proc);
3399 _exit (1);
3400
3401 default:
3402 status = pidXwait (child_id, NULLCP);
3403 break;
3404 }
3405
3406 if (!fmsh)
3407 (void) unlink (tmpfil);
3408 return status;
3409 }
3410
3411 /* \f */
3412
3413 static copy_message (msgnum, out)
3414 int msgnum;
3415 FILE * out;
3416 {
3417 long pos;
3418 static char buffer[BUFSIZ];
3419 register FILE * zp;
3420
3421 zp = msh_ready (msgnum, 1);
3422 if (fmsh) {
3423 while (fgets (buffer, sizeof buffer, zp) != NULL) {
3424 fputs (buffer, out);
3425 if (interrupted && out == stdout)
3426 break;
3427 }
3428 }
3429 else {
3430 pos = ftell (zp);
3431 while (fgets (buffer, sizeof buffer, zp) != NULL
3432 && pos < Msgs[msgnum].m_stop) {
3433 fputs (buffer, out);
3434 pos += (long) strlen (buffer);
3435 if (interrupted && out == stdout)
3436 break;
3437 }
3438 }
3439 }
3440
3441
3442 static copy_digest (msgnum, out)
3443 int msgnum;
3444 FILE * out;
3445 {
3446 char c;
3447 long pos;
3448 static char buffer[BUFSIZ];
3449 register FILE *zp;
3450
3451 c = '\n';
3452 zp = msh_ready (msgnum, 1);
3453 if (!fmsh)
3454 pos = ftell (zp);
3455 while (fgets (buffer, sizeof buffer, zp) != NULL
3456 && !fmsh && pos < Msgs[msgnum].m_stop) {
3457 if (c == '\n' && *buffer == '-')
3458 (void) fputc (' ', out);
3459 fputs (buffer, out);
3460 c = buffer[strlen (buffer) - 1];
3461 if (!fmsh)
3462 pos += (long) strlen (buffer);
3463 if (interrupted && out == stdout)
3464 break;
3465 }
3466 }