|
|
1.1 root 1: /* mshcmds.c - command handlers in msh */
2:
3: #include "../h/mh.h"
4: #include "../h/dropsbr.h"
5: #include "../h/formatsbr.h"
6: #include "../h/scansbr.h"
7: #include "../zotnet/tws.h"
8: #include <stdio.h>
9: #include "../zotnet/mts.h"
10: #include <ctype.h>
11: #include <errno.h>
12: #include <setjmp.h>
13: #include <signal.h>
14: #include "../h/mshsbr.h"
15: #include <sys/types.h>
16: #include <sys/stat.h>
17:
18: /* */
19:
20: extern int errno;
21:
22: /* BURST */
23: static char delim3[] = "-------";/* from burst.c */
24:
25:
26: /* SHOW */
27: static int mhlnum;
28: static FILE *mhlfp;
29:
30: void clear_screen ();
31:
32: static void forw(), rmm(), show(), copy_message(), copy_digest();
33: static int burst(), eom_action(), ask(), msgsort(), process();
34: static FP mhl_action();
35: static struct tws *getws();
36:
37: /* */
38:
39: forkcmd (args, pgm)
40: char **args,
41: *pgm;
42: {
43: int child_id;
44: char *vec[MAXARGS];
45:
46: vec[0] = r1bindex (pgm, '/');
47: (void) copyip (args, vec + 1);
48:
49: if (fmsh) {
50: (void) m_delete (pfolder);
51: m_replace (pfolder, fmsh);
52: m_sync (mp);
53: m_update ();
54: }
55: (void) fflush (stdout);
56: switch (child_id = fork ()) {
57: case NOTOK:
58: advise ("fork", "unable to");
59: return;
60:
61: case OK:
62: closefds (3);
63: (void) signal (SIGINT, istat);
64: (void) signal (SIGQUIT, qstat);
65:
66: execvp (pgm, vec);
67: fprintf (stderr, "unable to exec ");
68: perror (cmd_name);
69: _exit (1);
70:
71: default:
72: (void) pidXwait (child_id, NULLCP);
73: break;
74: }
75: if (fmsh) { /* assume the worst case */
76: mp -> msgflags |= MODIFIED;
77: modified++;
78: }
79: }
80:
81: /* */
82:
83: static struct swit distswit[] = {
84: #define DIANSW 0
85: "annotate", 0,
86: #define DINANSW 1
87: "noannotate", 0,
88: #define DIDFSW 2
89: "draftfolder +folder", 0,
90: #define DIDMSW 3
91: "draftmessage msg", 0,
92: #define DINDFSW 4
93: "nodraftfolder", 0,
94: #define DIEDTSW 5
95: "editor editor", 0,
96: #define DINEDSW 6
97: "noedit", 0,
98: #define DIFRMSW 7
99: "form formfile", 0,
100: #define DIINSW 8
101: "inplace", 0,
102: #define DININSW 9
103: "noinplace", 0,
104: #define DIWHTSW 10
105: "whatnowproc program", 0,
106: #define DINWTSW 11
107: "nowhatnowproc", 0,
108: #define DIHELP 12
109: "help", 4,
110:
111: NULL, NULL
112: };
113:
114: /* */
115:
116: distcmd (args)
117: char **args;
118: {
119: int vecp = 1;
120: char *cp,
121: *msg = NULL,
122: buf[BUFSIZ],
123: *vec[MAXARGS];
124:
125: if (fmsh) {
126: forkcmd (args, cmd_name);
127: return;
128: }
129:
130: while (cp = *args++) {
131: if (*cp == '-')
132: switch (smatch (++cp, distswit)) {
133: case AMBIGSW:
134: ambigsw (cp, distswit);
135: return;
136: case UNKWNSW:
137: fprintf (stderr, "-%s unknown\n", cp);
138: return;
139: case DIHELP:
140: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
141: help (buf, distswit);
142: return;
143:
144: case DIANSW: /* not implemented */
145: case DINANSW:
146: case DIINSW:
147: case DININSW:
148: continue;
149:
150: case DINDFSW:
151: case DINEDSW:
152: case DINWTSW:
153: vec[vecp++] = --cp;
154: continue;
155:
156: case DIEDTSW:
157: case DIFRMSW:
158: case DIDFSW:
159: case DIDMSW:
160: case DIWHTSW:
161: vec[vecp++] = --cp;
162: if (!(cp = *args++) || *cp == '-') {
163: advise (NULLCP, "missing argument to %s", args[-2]);
164: return;
165: }
166: vec[vecp++] = cp;
167: continue;
168: }
169: if (*cp == '+' || *cp == '@') {
170: advise (NULLCP, "sorry, no folders allowed!");
171: return;
172: }
173: else
174: if (msg) {
175: advise (NULLCP, "only one message at a time!");
176: return;
177: }
178: else
179: msg = cp;
180: }
181:
182: vec[0] = cmd_name;
183: vec[vecp++] = "-file";
184: vec[vecp] = NULL;
185: if (!msg)
186: msg = "cur";
187: if (!m_convert (mp, msg))
188: return;
189: m_setseq (mp);
190:
191: if (mp -> numsel > 1) {
192: advise (NULLCP, "only one message at a time!");
193: return;
194: }
195: (void) process (mp -> hghsel, cmd_name, vecp, vec);
196: m_setcur (mp, mp -> hghsel);
197: }
198:
199: /* */
200:
201: static struct swit explswit[] = {
202: #define EXINSW 0
203: "inplace", 0,
204: #define EXNINSW 1
205: "noinplace", 0,
206: #define EXQISW 2
207: "quiet", 0,
208: #define EXNQISW 3
209: "noquiet", 0,
210: #define EXVBSW 4
211: "verbose", 0,
212: #define EXNVBSW 5
213: "noverbose", 0,
214: #define EXHELP 6
215: "help", 4,
216:
217: NULL, NULL
218: };
219:
220: /* */
221:
222: explcmd (args)
223: char **args;
224: {
225: int inplace = 0,
226: quietsw = 0,
227: verbosw = 0,
228: msgp = 0,
229: hi,
230: msgnum;
231: char *cp,
232: buf[BUFSIZ],
233: *msgs[MAXARGS];
234: struct Msg *smsgs;
235:
236: if (fmsh) {
237: forkcmd (args, cmd_name);
238: return;
239: }
240:
241: while (cp = *args++) {
242: if (*cp == '-')
243: switch (smatch (++cp, explswit)) {
244: case AMBIGSW:
245: ambigsw (cp, explswit);
246: return;
247: case UNKWNSW:
248: fprintf (stderr, "-%s unknown\n", cp);
249: return;
250: case EXHELP:
251: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
252: help (buf, explswit);
253: return;
254:
255: case EXINSW:
256: inplace++;
257: continue;
258: case EXNINSW:
259: inplace = 0;
260: continue;
261: case EXQISW:
262: quietsw++;
263: continue;
264: case EXNQISW:
265: quietsw = 0;
266: continue;
267: case EXVBSW:
268: verbosw++;
269: continue;
270: case EXNVBSW:
271: verbosw = 0;
272: continue;
273: }
274: if (*cp == '+' || *cp == '@') {
275: advise (NULLCP, "sorry, no folders allowed!");
276: return;
277: }
278: else
279: msgs[msgp++] = cp;
280: }
281:
282: if (!msgp)
283: msgs[msgp++] = "cur";
284: for (msgnum = 0; msgnum < msgp; msgnum++)
285: if (!m_convert (mp, msgs[msgnum]))
286: return;
287: m_setseq (mp);
288:
289: smsgs = (struct Msg *)
290: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
291: if (smsgs == NULL)
292: adios (NULLCP, "unable to allocate folder storage");
293:
294: hi = mp -> hghmsg + 1;
295: interrupted = 0;
296: for (msgnum = mp -> lowsel;
297: msgnum <= mp -> hghsel && !interrupted;
298: msgnum++)
299: if (mp -> msgstats[msgnum] & SELECTED)
300: if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
301: break;
302:
303: free ((char *) smsgs);
304:
305: if (inplace)
306: m_setcur (mp, mp -> lowsel);
307: else
308: if (hi <= mp -> hghmsg)
309: m_setcur (mp, hi);
310:
311: mp -> msgflags |= MODIFIED;
312: modified++;
313: }
314:
315: /* */
316:
317: static int burst (smsgs, msgnum, inplace, quietsw, verbosw)
318: struct Msg *smsgs;
319: int msgnum,
320: inplace,
321: quietsw,
322: verbosw;
323: {
324: int i,
325: j,
326: ld3,
327: wasdlm,
328: msgp;
329: long pos;
330: char c,
331: buffer[BUFSIZ];
332: register FILE *zp;
333:
334: ld3 = strlen (delim3);
335:
336: if (Msgs[msgnum].m_scanl) {
337: free (Msgs[msgnum].m_scanl);
338: Msgs[msgnum].m_scanl = NULL;
339: }
340:
341: pos = ftell (zp = msh_ready (msgnum, 1));
342: for (msgp = 1; msgp <= MAXFOLDER;) {
343: while (fgets (buffer, sizeof buffer, zp) != NULL
344: && buffer[0] == '\n'
345: && pos < Msgs[msgnum].m_stop)
346: pos += (long) strlen (buffer);
347: if (feof (zp) || pos >= Msgs[msgnum].m_stop)
348: break;
349: (void) fseek (zp, pos, 0);
350: smsgs[msgp].m_start = pos;
351:
352: for (c = NULL;
353: fgets (buffer, sizeof buffer, zp) != NULL
354: && pos < Msgs[msgnum].m_stop;
355: c = buffer[0])
356: if (strncmp (buffer, delim3, ld3) == 0
357: && peekc (zp) == '\n'
358: && (msgp == 1 || c == '\n'))
359: break;
360: else
361: pos += (long) strlen (buffer);
362:
363: wasdlm = strncmp (buffer, delim3, ld3) == 0;
364: if (smsgs[msgp].m_start != pos)
365: smsgs[msgp++].m_stop = c == '\n' && wasdlm ? pos - 1 : pos;
366: if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
367: if (wasdlm) {
368: smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
369: msgp++; /* fake "End of XXX Digest" */
370: }
371: break;
372: }
373: pos += (long) strlen (buffer);
374: }
375:
376: switch (--msgp) { /* toss "End of XXX Digest" */
377: case 0:
378: adios (NULLCP, "burst() botch -- you lose big");
379:
380: case 1:
381: if (!quietsw)
382: printf ("message %d not in digest format\n", msgnum);
383: return OK;
384:
385: default:
386: if (verbosw)
387: printf ("%d message%s exploded from digest %d\n",
388: msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum);
389: if (msgp == 2)
390: msgp++;
391: break;
392: }
393:
394: msgp--;
395: if ((i = msgp + mp -> hghmsg) > MAXFOLDER) {
396: advise (NULLCP, "more than %d messages", MAXFOLDER);
397: return NOTOK;
398: }
399: if ((mp = m_remsg (mp, 0, i)) == NULL)
400: adios (NULLCP, "unable to allocate folder storage");
401:
402: j = mp -> hghmsg;
403: mp -> hghmsg += msgp - 1;
404: mp -> nummsg += msgp - 1;
405: if (mp -> hghsel > msgnum)
406: mp -> hghsel += msgp - 1;
407:
408: if (inplace && msgp > 1)
409: for (i = mp -> hghmsg; j > msgnum; i--, j--) {
410: if (verbosw)
411: printf ("message %d becomes message %d\n", j, i);
412:
413: Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
414: Msgs[i].m_top = Msgs[j].m_top;
415: Msgs[i].m_start = Msgs[j].m_start;
416: Msgs[i].m_stop = Msgs[j].m_stop;
417: Msgs[i].m_scanl = NULL;
418: if (Msgs[j].m_scanl) {
419: free (Msgs[j].m_scanl);
420: Msgs[j].m_scanl = NULL;
421: }
422: mp -> msgstats[i] = mp -> msgstats[j];
423: }
424:
425: if (Msgs[msgnum].m_bboard_id == 0)
426: (void) readid (msgnum);
427:
428: mp -> msgstats[msgnum] &= ~SELECTED;
429: i = inplace ? msgnum + msgp - 1 : mp -> hghmsg;
430: for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) {
431: if (verbosw && i != msgnum)
432: printf ("message %d of digest %d becomes message %d\n",
433: j, msgnum, i);
434:
435: Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
436: Msgs[i].m_top = Msgs[j].m_top;
437: Msgs[i].m_start = smsgs[j].m_start;
438: Msgs[i].m_stop = smsgs[j].m_stop;
439: Msgs[i].m_scanl = NULL;
440: mp -> msgstats[i] = mp -> msgstats[msgnum];
441: }
442:
443: return OK;
444: }
445:
446: /* */
447:
448: static struct swit fileswit[] = {
449: #define FIDRFT 0
450: "draft", 0,
451: #define FILINK 1
452: "link", 0,
453: #define FINLINK 2
454: "nolink", 0,
455: #define FIPRES 3
456: "preserve", 0,
457: #define FINPRES 4
458: "nopreserve", 0,
459: #define FISRC 5
460: "src +folder", 0,
461: #define FIFILE 6
462: "file file", 0,
463: #define FIHELP 7
464: "help", 4,
465:
466: NULL, NULL
467: };
468:
469: /* */
470:
471: filecmd (args)
472: char **args;
473: {
474: int linksw = 0,
475: msgp = 0,
476: vecp = 1,
477: i,
478: msgnum;
479: char *cp,
480: buf[BUFSIZ],
481: *msgs[MAXARGS],
482: *vec[MAXARGS];
483:
484: if (fmsh) {
485: forkcmd (args, cmd_name);
486: return;
487: }
488:
489: while (cp = *args++) {
490: if (*cp == '-')
491: switch (i = smatch (++cp, fileswit)) {
492: case AMBIGSW:
493: ambigsw (cp, fileswit);
494: return;
495: case UNKWNSW:
496: fprintf (stderr, "-%s unknown\n", cp);
497: return;
498: case FIHELP:
499: (void) sprintf (buf, "%s +folder... [msgs] [switches]",
500: cmd_name);
501: help (buf, fileswit);
502: return;
503:
504: case FILINK:
505: linksw++;
506: continue;
507: case FINLINK:
508: linksw = 0;
509: continue;
510:
511: case FIPRES:
512: case FINPRES:
513: continue;
514:
515: case FISRC:
516: case FIDRFT:
517: case FIFILE:
518: advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw);
519: return;
520: }
521: if (*cp == '+' || *cp == '@')
522: vec[vecp++] = cp;
523: else
524: msgs[msgp++] = cp;
525: }
526:
527: vec[0] = cmd_name;
528: vec[vecp++] = "-file";
529: vec[vecp] = NULL;
530: if (!msgp)
531: msgs[msgp++] = "cur";
532: for (msgnum = 0; msgnum < msgp; msgnum++)
533: if (!m_convert (mp, msgs[msgnum]))
534: return;
535: m_setseq (mp);
536:
537: interrupted = 0;
538: for (msgnum = mp -> lowsel;
539: msgnum <= mp -> hghsel && !interrupted;
540: msgnum++)
541: if (mp -> msgstats[msgnum] & SELECTED)
542: if (process (msgnum, fileproc, vecp, vec)) {
543: mp -> msgstats[msgnum] &= ~SELECTED;
544: mp -> numsel--;
545: }
546:
547: if (mp -> numsel != mp -> nummsg || linksw)
548: m_setcur (mp, mp -> hghsel);
549: if (!linksw)
550: rmm ();
551: }
552:
553: /* */
554:
555: int filehak (args)
556: char **args;
557: {
558: int result,
559: vecp = 0;
560: char *cp,
561: *cwd,
562: *vec[MAXARGS];
563:
564: while (cp = *args++) {
565: if (*cp == '-')
566: switch (smatch (++cp, fileswit)) {
567: case AMBIGSW:
568: case UNKWNSW:
569: case FIHELP:
570: return NOTOK;
571:
572: case FILINK:
573: case FINLINK:
574: case FIPRES:
575: case FINPRES:
576: continue;
577:
578: case FISRC:
579: case FIDRFT:
580: case FIFILE:
581: return NOTOK;
582: }
583: if (*cp == '+' || *cp == '@')
584: vec[vecp++] = cp;
585: }
586: vec[vecp] = NULL;
587:
588: result = NOTOK;
589: cwd = NULL;
590: for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
591: if (cwd == NULL)
592: cwd = getcpy (pwd ());
593: (void) chdir (m_maildir (""));
594: cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
595: if (access (m_maildir (cp), 0) == NOTOK)
596: result = OK;
597: free (cp);
598: }
599: if (cwd)
600: (void) chdir (cwd);
601:
602: return result;
603: }
604:
605: /* */
606:
607: static struct swit foldswit[] = {
608: #define FLALSW 0
609: "all", 0,
610: #define FLFASW 1
611: "fast", 0,
612: #define FLNFASW 2
613: "nofast", 0,
614: #define FLHDSW 3
615: "header", 0,
616: #define FLNHDSW 4
617: "noheader", 0,
618: #define FLPKSW 5
619: "pack", 0,
620: #define FLNPKSW 6
621: "nopack", 0,
622: #define FLRCSW 7
623: "recurse", 0,
624: #define FLNRCSW 8
625: "norecurse", 0,
626: #define FLTLSW 9
627: "total", 0,
628: #define FLNTLSW 10
629: "nototal", 0,
630: #define FLPRSW 11
631: "print", 0,
632: #define FLPUSW 12
633: "push", 0,
634: #define FLPOSW 13
635: "pop", 0,
636: #define FLLISW 14
637: "list", 0,
638: #define FLHELP 15
639: "help", 4,
640:
641: NULL, NULL
642: };
643:
644: /* */
645:
646: foldcmd (args)
647: char **args;
648: {
649: int fastsw = 0,
650: headersw = 0,
651: packsw = 0,
652: hole,
653: msgnum;
654: char *cp,
655: *folder = NULL,
656: *msg = NULL,
657: buf[BUFSIZ],
658: **vec = args;
659:
660: if (args == NULL)
661: goto fast;
662:
663: while (cp = *args++) {
664: if (*cp == '-')
665: switch (smatch (++cp, foldswit)) {
666: case AMBIGSW:
667: ambigsw (cp, foldswit);
668: return;
669: case UNKWNSW:
670: fprintf (stderr, "-%s unknown\n", cp);
671: return;
672: case FLHELP:
673: (void) sprintf (buf, "%s [+folder] [msg] [switches]",
674: cmd_name);
675: help (buf, foldswit);
676: return;
677:
678: case FLALSW: /* not implemented */
679: case FLRCSW:
680: case FLNRCSW:
681: case FLTLSW:
682: case FLNTLSW:
683: case FLPRSW:
684: case FLPUSW:
685: case FLPOSW:
686: case FLLISW:
687: continue;
688:
689: case FLFASW:
690: fastsw++;
691: continue;
692: case FLNFASW:
693: fastsw = 0;
694: continue;
695: case FLHDSW:
696: headersw++;
697: continue;
698: case FLNHDSW:
699: headersw = 0;
700: continue;
701: case FLPKSW:
702: packsw++;
703: continue;
704: case FLNPKSW:
705: packsw = 0;
706: continue;
707: }
708: if (*cp == '+' || *cp == '@')
709: if (folder) {
710: advise (NULLCP, "only one folder at a time!\n");
711: return;
712: }
713: else
714: folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
715: : cp + 1;
716: else
717: if (msg) {
718: advise (NULLCP, "only one message at a time!\n");
719: return;
720: }
721: else
722: msg = cp;
723: }
724:
725: if (folder) {
726: if (*folder == NULL) {
727: advise (NULLCP, "null folder names are not permitted");
728: return;
729: }
730: if (fmsh) {
731: if (access (m_maildir (folder), 04) == NOTOK) {
732: advise (folder, "unable to read");
733: return;
734: }
735: }
736: else {
737: (void) strcpy (buf, folder);
738: if (expand (buf) == NOTOK)
739: return;
740: folder = buf;
741: if (access (folder, 04) == NOTOK) {
742: advise (folder, "unable to read");
743: return;
744: }
745: }
746: m_reset ();
747:
748: if (fmsh)
749: fsetup (folder);
750: else
751: setup (folder);
752: readids (0);
753: display_info (0);
754: }
755:
756: if (msg) {
757: if (!m_convert (mp, msg))
758: return;
759: m_setseq (mp);
760:
761: if (mp -> numsel > 1) {
762: advise (NULLCP, "only one message at a time!");
763: return;
764: }
765: m_setcur (mp, mp -> hghsel);
766: }
767:
768: if (packsw) {
769: if (fmsh) {
770: forkcmd (vec, cmd_name);
771: return;
772: }
773:
774: if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
775: adios (NULLCP, "unable to allocate folder storage");
776: for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
777: if (mp -> msgstats[msgnum] & EXISTS) {
778: if (msgnum != hole) {
779: Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
780: Msgs[hole].m_top = Msgs[msgnum].m_top;
781: Msgs[hole].m_start = Msgs[msgnum].m_start;
782: Msgs[hole].m_stop = Msgs[msgnum].m_stop;
783: Msgs[hole].m_scanl = NULL;
784: if (Msgs[msgnum].m_scanl) {
785: free (Msgs[msgnum].m_scanl);
786: Msgs[msgnum].m_scanl = NULL;
787: }
788: mp -> msgstats[hole] = mp -> msgstats[msgnum];
789: if (mp -> curmsg == msgnum)
790: m_setcur (mp, hole);
791: }
792: hole++;
793: }
794: if (mp -> nummsg > 0) {
795: mp -> lowmsg = 1;
796: mp -> hghmsg = hole - 1;
797: }
798: mp -> msgflags |= MODIFIED;
799: modified++;
800: }
801:
802: fast: ;
803: if (fastsw)
804: printf ("%s\n", fmsh ? fmsh : mp -> foldpath);
805: else {
806: if (headersw)
807: printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
808: DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
809: DMAXFOLDER - 2, "");
810: printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath);
811: if (mp -> hghmsg == 0)
812: printf ("has no messages%*s",
813: mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
814: else {
815: printf ("has %*d message%s (%*d-%*d)",
816: DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "",
817: DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg);
818: if (mp -> curmsg >= mp -> lowmsg
819: && mp -> curmsg <= mp -> hghmsg)
820: printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg);
821: }
822: printf (".\n");
823: }
824: }
825:
826: /* */
827:
828: static struct swit forwswit[] = {
829: #define FOANSW 0
830: "annotate", 0,
831: #define FONANSW 1
832: "noannotate", 0,
833: #define FODFSW 2
834: "draftfolder +folder", 0,
835: #define FODMSW 3
836: "draftmessage msg", 0,
837: #define FONDFSW 4
838: "nodraftfolder", 0,
839: #define FOEDTSW 5
840: "editor editor", 0,
841: #define FONEDSW 6
842: "noedit", 0,
843: #define FOFTRSW 7
844: "filter filterfile", 0,
845: #define FOFRMSW 8
846: "form formfile", 0,
847: #define FOFTSW 9
848: "format", 5,
849: #define FONFTSW 10
850: "noformat", 7,
851: #define FOINSW 11
852: "inplace", 0,
853: #define FONINSW 12
854: "noinplace", 0,
855: #define FOWHTSW 13
856: "whatnowproc program", 0,
857: #define FONWTSW 14
858: "nowhatnow", 0,
859: #define FOHELP 15
860: "help", 4,
861:
862: NULL, NULL
863: };
864:
865: /* */
866:
867: forwcmd (args)
868: char **args;
869: {
870: int msgp = 0,
871: vecp = 1,
872: msgnum;
873: char *cp,
874: *filter = NULL,
875: buf[BUFSIZ],
876: *msgs[MAXARGS],
877: *vec[MAXARGS];
878:
879: if (fmsh) {
880: forkcmd (args, cmd_name);
881: return;
882: }
883:
884: while (cp = *args++) {
885: if (*cp == '-')
886: switch (smatch (++cp, forwswit)) {
887: case AMBIGSW:
888: ambigsw (cp, forwswit);
889: return;
890: case UNKWNSW:
891: fprintf (stderr, "-%s unknown\n", cp);
892: return;
893: case FOHELP:
894: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
895: help (buf, forwswit);
896: return;
897:
898: case FOANSW: /* not implemented */
899: case FONANSW:
900: case FOINSW:
901: case FONINSW:
902: continue;
903:
904: case FONDFSW:
905: case FONEDSW:
906: case FONWTSW:
907: vec[vecp++] = --cp;
908: continue;
909:
910: case FOEDTSW:
911: case FOFRMSW:
912: case FODFSW:
913: case FODMSW:
914: case FOWHTSW:
915: vec[vecp++] = --cp;
916: if (!(cp = *args++) || *cp == '-') {
917: advise (NULLCP, "missing argument to %s", args[-2]);
918: return;
919: }
920: vec[vecp++] = cp;
921: continue;
922: case FOFTRSW:
923: if (!(filter = *args++) || *filter == '-') {
924: advise (NULLCP, "missing argument to %s", args[-2]);
925: return;
926: }
927: continue;
928: case FOFTSW:
929: if (access (filter = myfilter, 04) == NOTOK) {
930: advise (filter, "unable to read default filter file");
931: return;
932: }
933: continue;
934: case FONFTSW:
935: filter = NULL;
936: continue;
937: }
938: if (*cp == '+' || *cp == '@') {
939: advise (NULLCP, "sorry, no folders allowed!");
940: return;
941: }
942: else
943: msgs[msgp++] = cp;
944: }
945:
946: /* foil search of .mh_profile */
947: (void) sprintf (buf, "%sXXXXXX", invo_name);
948: vec[0] = mktemp (buf);
949: vec[vecp++] = "-file";
950: vec[vecp] = NULL;
951: if (!msgp)
952: msgs[msgp++] = "cur";
953: for (msgnum = 0; msgnum < msgp; msgnum++)
954: if (!m_convert (mp, msgs[msgnum]))
955: return;
956: m_setseq (mp);
957:
958: if (filter) {
959: (void) strcpy (buf, filter);
960: if (expand (buf) == NOTOK)
961: return;
962: if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) {
963: advise (filter, "unable to read");
964: free (filter);
965: return;
966: }
967: }
968: forw (cmd_name, filter, vecp, vec);
969: m_setcur (mp, mp -> hghsel);
970: if (filter)
971: free (filter);
972: }
973:
974: /* */
975:
976: static void forw (proc, filter, vecp, vec)
977: int vecp;
978: char *proc,
979: *filter,
980: **vec;
981: {
982: int i,
983: child_id,
984: msgnum,
985: msgcnt;
986: char tmpfil[80],
987: *args[MAXARGS];
988: FILE *out;
989:
990: (void) strcpy (tmpfil, m_tmpfil (invo_name));
991: interrupted = 0;
992: if (filter)
993: switch (child_id = fork ()) {
994: case NOTOK:
995: advise ("fork", "unable to");
996: return;
997:
998: case OK: /* "trust me" */
999: if (freopen (tmpfil, "w", stdout) == NULL) {
1000: fprintf (stderr, "unable to create ");
1001: perror (tmpfil);
1002: _exit (1);
1003: }
1004: args[0] = r1bindex (mhlproc, '/');
1005: i = 1;
1006: args[i++] = "-forwall";
1007: args[i++] = "-form";
1008: args[i++] = filter;
1009: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1010: if (mp -> msgstats[msgnum] & SELECTED)
1011: args[i++] = getcpy (m_name (msgnum));
1012: args[i] = NULL;
1013: (void) mhlsbr (i, args, mhl_action);
1014: m_eomsbr ((int (*) ()) 0);
1015: (void) fclose (stdout);
1016: _exit (0);
1017:
1018: default:
1019: if (pidXwait (child_id, NULLCP))
1020: interrupted++;
1021: break;
1022: }
1023: else {
1024: if ((out = fopen (tmpfil, "w")) == NULL) {
1025: advise (tmpfil, "unable to create temporary file");
1026: return;
1027: }
1028:
1029: msgcnt = 1;
1030: for (msgnum = mp -> lowsel;
1031: msgnum <= mp -> hghsel && !interrupted;
1032: msgnum++)
1033: if (mp -> msgstats[msgnum] & SELECTED) {
1034: fprintf (out, "\n\n-------");
1035: if (msgnum == mp -> lowsel)
1036: fprintf (out, " Forwarded Message%s",
1037: mp -> numsel > 1 ? "s" : "");
1038: else
1039: fprintf (out, " Message %d", msgcnt);
1040: fprintf (out, "\n\n");
1041: copy_digest (msgnum, out);
1042: msgcnt++;
1043: }
1044:
1045: fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1046: mp -> numsel > 1 ? "s" : "");
1047: (void) fclose (out);
1048: }
1049:
1050: (void) fflush (stdout);
1051: if (!interrupted)
1052: switch (child_id = fork ()) {
1053: case NOTOK:
1054: advise ("fork", "unable to");
1055: break;
1056:
1057: case OK:
1058: closefds (3);
1059: (void) signal (SIGINT, istat);
1060: (void) signal (SIGQUIT, qstat);
1061:
1062: vec[vecp++] = tmpfil;
1063: vec[vecp] = NULL;
1064:
1065: execvp (proc, vec);
1066: fprintf (stderr, "unable to exec ");
1067: perror (proc);
1068: _exit (1);
1069:
1070: default:
1071: (void) pidXwait (child_id, NULLCP);
1072: break;
1073: }
1074:
1075: (void) unlink (tmpfil);
1076: }
1077:
1078: /* */
1079:
1080: static char *hlpmsg[] = {
1081: "The %s program emulates many of the commands found in the Rand MH",
1082: "system. Instead of operating on MH folders, commands to %s concern",
1083: "a single file.",
1084: "",
1085: "To see the list of commands available, just type a ``?'' followed by",
1086: "the RETURN key. To find out what switches each command takes, type",
1087: "the name of the command followed by ``-help''. To leave %s, use the",
1088: "``quit'' command.",
1089: "",
1090: "Although a lot of MH commands are found in %s, not all are fully",
1091: "implemented. %s will always recognize all legal switches for a",
1092: "given command though, and will let you know when you ask for an",
1093: "option that it is unable to perform.",
1094: "",
1095: "Running %s is fun, but using MH from your shell is far superior.",
1096: "After you have familiarized yourself with the MH style by using %s,",
1097: "you should try using MH from the shell. You can still use %s for",
1098: "message files that aren't in MH format, such as BBoard files.",
1099: NULL
1100: };
1101:
1102:
1103: /* ARGSUSED */
1104:
1105: helpcmd (args)
1106: char **args;
1107: {
1108: int i;
1109:
1110: for (i = 0; hlpmsg[i]; i++) {
1111: printf (hlpmsg[i], invo_name);
1112: (void) putchar ('\n');
1113: }
1114: }
1115:
1116: /* */
1117:
1118: static struct swit markswit[] = {
1119: #define MADDSW 0
1120: "add", 0,
1121: #define MDELSW 1
1122: "delete", 0,
1123: #define MLSTSW 2
1124: "list", 0,
1125: #define MSEQSW 3
1126: "sequence name", 0,
1127: #define MPUBSW 4
1128: "public", 0,
1129: #define MNPUBSW 5
1130: "nopublic", 0,
1131: #define MZERSW 6
1132: "zero", 0,
1133: #define MNZERSW 7
1134: "nozero", 0,
1135: #define MHELP 8
1136: "help", 4,
1137: #define MDBUGSW 9
1138: "debug", -5,
1139:
1140: NULL, NULL
1141: };
1142:
1143: /* */
1144:
1145: markcmd (args)
1146: char **args;
1147: {
1148: int addsw = 0,
1149: deletesw = 0,
1150: debugsw = 0,
1151: listsw = 0,
1152: zerosw = 0,
1153: seqp = 0,
1154: msgp = 0,
1155: i,
1156: msgnum;
1157: char *cp,
1158: buf[BUFSIZ],
1159: *seqs[NATTRS + 1],
1160: *msgs[MAXARGS];
1161:
1162: while (cp = *args++) {
1163: if (*cp == '-')
1164: switch (smatch (++cp, markswit)) {
1165: case AMBIGSW:
1166: ambigsw (cp, markswit);
1167: return;
1168: case UNKWNSW:
1169: fprintf (stderr, "-%s unknown\n", cp);
1170: return;
1171: case MHELP:
1172: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1173: help (buf, markswit);
1174: return;
1175:
1176: case MADDSW:
1177: addsw++;
1178: deletesw = listsw = 0;
1179: continue;
1180: case MDELSW:
1181: deletesw++;
1182: addsw = listsw = 0;
1183: continue;
1184: case MLSTSW:
1185: listsw++;
1186: addsw = deletesw = 0;
1187: continue;
1188:
1189: case MSEQSW:
1190: if (!(cp = *args++) || *cp == '-') {
1191: advise (NULLCP, "missing argument to %s", args[-2]);
1192: return;
1193: }
1194: if (seqp < NATTRS)
1195: seqs[seqp++] = cp;
1196: else {
1197: advise (NULLCP, "only %d sequences allowed!", NATTRS);
1198: return;
1199: }
1200: continue;
1201:
1202: case MPUBSW: /* not implemented */
1203: case MNPUBSW:
1204: continue;
1205:
1206: case MDBUGSW:
1207: debugsw++;
1208: continue;
1209:
1210: case MZERSW:
1211: zerosw++;
1212: continue;
1213: case MNZERSW:
1214: zerosw = 0;
1215: continue;
1216: }
1217: if (*cp == '+' || *cp == '@') {
1218: advise (NULLCP, "sorry, no folders allowed!");
1219: return;
1220: }
1221: else
1222: msgs[msgp++] = cp;
1223: }
1224:
1225: if (!addsw && !deletesw && !listsw)
1226: if (seqp)
1227: addsw++;
1228: else
1229: if (debugsw)
1230: listsw++;
1231: else {
1232: seqs[seqp++] = "unseen";
1233: deletesw++;
1234: zerosw = 0;
1235: if (!msgp)
1236: msgs[msgp++] = "all";
1237: }
1238:
1239: if (!msgp)
1240: msgs[msgp++] = listsw ? "all" :"cur";
1241: for (msgnum = 0; msgnum < msgp; msgnum++)
1242: if (!m_convert (mp, msgs[msgnum]))
1243: return;
1244:
1245: if (debugsw) {
1246: printf ("invo_name=%s mypath=%s defpath=%s\n",
1247: invo_name, mypath, defpath);
1248: printf ("ctxpath=%s context flags=%s\n",
1249: ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS));
1250: printf ("foldpath=%s flags=%s\n",
1251: mp -> foldpath,
1252: sprintb (buf, (unsigned) mp -> msgflags, FBITS));
1253: printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1254: mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg);
1255: printf ("lowsel=%d hghsel=%d numsel=%d\n",
1256: mp -> lowsel, mp -> hghsel, mp -> numsel);
1257: #ifndef MTR
1258: printf ("lowoff=%d hghoff=%d\n",
1259: mp -> lowoff, mp -> hghoff);
1260: #else MTR
1261: printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n",
1262: mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats);
1263: #endif MTR
1264: }
1265:
1266: if (seqp == 0 && (addsw || deletesw)) {
1267: advise (NULLCP, "-%s requires at least one -sequence argument",
1268: addsw ? "add" : "delete");
1269: return;
1270: }
1271: seqs[seqp] = NULL;
1272:
1273: if (addsw)
1274: for (seqp = 0; seqs[seqp]; seqp++) {
1275: if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1276: return;
1277: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1278: if (mp -> msgstats[msgnum] & SELECTED)
1279: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1280: return;
1281: }
1282:
1283: if (deletesw)
1284: for (seqp = 0; seqs[seqp]; seqp++) {
1285: if (zerosw)
1286: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1287: if (mp -> msgstats[msgnum] & EXISTS)
1288: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1289: return;
1290: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1291: if (mp -> msgstats[msgnum] & SELECTED)
1292: if (!m_seqdel (mp, seqs[seqp], msgnum))
1293: return;
1294: }
1295:
1296: if (listsw) {
1297: int bits = FFATTRSLOT;
1298:
1299: if (seqp == 0)
1300: for (i = 0; mp -> msgattrs[i]; i++)
1301: printf ("%s%s: %s\n", mp -> msgattrs[i],
1302: mp -> attrstats & (1 << (bits + i))
1303: ? " (private)" : "",
1304: m_seq (mp, mp -> msgattrs[i]));
1305: else
1306: for (seqp = 0; seqs[seqp]; seqp++)
1307: printf ("%s%s: %s\n", seqs[seqp], m_seq (mp, seqs[seqp]));
1308:
1309: interrupted = 0;
1310: if (debugsw)
1311: for (msgnum = mp -> lowsel;
1312: msgnum <= mp -> hghsel && !interrupted;
1313: msgnum++)
1314: if (mp -> msgstats[msgnum] & SELECTED) {
1315: printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1316: DMAXFOLDER, msgnum,
1317: Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top,
1318: Msgs[msgnum].m_start, Msgs[msgnum].m_stop,
1319: sprintb (buf, (unsigned) mp -> msgstats[msgnum],
1320: m_seqbits (mp)));
1321: if (Msgs[msgnum].m_scanl)
1322: printf ("%s", Msgs[msgnum].m_scanl);
1323: }
1324: }
1325: }
1326:
1327: /* */
1328:
1329: static struct swit packswit[] = {
1330: #define PAFISW 0
1331: "file name", 0,
1332:
1333: #define PAHELP 1
1334: "help", 4,
1335:
1336: NULL, NULL
1337: };
1338:
1339: /* */
1340:
1341: packcmd (args)
1342: char **args;
1343: {
1344: int msgp = 0,
1345: md,
1346: msgnum;
1347: char *cp,
1348: *file = NULL,
1349: buf[BUFSIZ],
1350: *msgs[MAXARGS];
1351: struct stat st;
1352:
1353: if (fmsh) {
1354: forkcmd (args, cmd_name);
1355: return;
1356: }
1357:
1358: while (cp = *args++) {
1359: if (*cp == '-')
1360: switch (smatch (++cp, packswit)) {
1361: case AMBIGSW:
1362: ambigsw (cp, packswit);
1363: return;
1364: case UNKWNSW:
1365: fprintf (stderr, "-%s unknown\n", cp);
1366: return;
1367: case PAHELP:
1368: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1369: help (buf, packswit);
1370: return;
1371:
1372: case PAFISW:
1373: if (!(file = *args++) || *file == '-') {
1374: advise (NULLCP, "missing argument to %s", args[-2]);
1375: return;
1376: }
1377: continue;
1378: }
1379: if (*cp == '+' || *cp == '@') {
1380: advise (NULLCP, "sorry, no folders allowed!");
1381: return;
1382: }
1383: else
1384: msgs[msgp++] = cp;
1385: }
1386:
1387: if (!file)
1388: file = "./msgbox";
1389: file = path (file, TFILE);
1390: if (stat (file, &st) == NOTOK) {
1391: if (errno != ENOENT) {
1392: advise (file, "error on file");
1393: goto done_pack;
1394: }
1395: md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP));
1396: free (cp);
1397: if (!md)
1398: goto done_pack;
1399: }
1400:
1401: if (!msgp)
1402: msgs[msgp++] = "all";
1403: for (msgnum = 0; msgnum < msgp; msgnum++)
1404: if (!m_convert (mp, msgs[msgnum]))
1405: goto done_pack;
1406: m_setseq (mp);
1407:
1408: if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1409: advise (file, "unable to open");
1410: goto done_pack;
1411: }
1412: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1413: if (mp -> msgstats[msgnum] & SELECTED)
1414: if (pack (file, md, msgnum) == NOTOK)
1415: break;
1416: (void) mbx_close (file, md);
1417:
1418: if (mp -> hghsel != mp -> curmsg)
1419: m_setcur (mp, mp -> lowsel);
1420:
1421: done_pack: ;
1422: free (file);
1423: }
1424:
1425: /* */
1426:
1427: int pack (mailbox, md, msgnum)
1428: char *mailbox;
1429: int md,
1430: msgnum;
1431: {
1432: register FILE *zp;
1433:
1434: if (Msgs[msgnum].m_bboard_id == 0)
1435: (void) readid (msgnum);
1436:
1437: zp = msh_ready (msgnum, 1);
1438: return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1439: ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1440: }
1441:
1442: /* */
1443:
1444: int packhak (args)
1445: char **args;
1446: {
1447: int result;
1448: char *cp,
1449: *file = NULL;
1450:
1451: while (cp = *args++) {
1452: if (*cp == '-')
1453: switch (smatch (++cp, packswit)) {
1454: case AMBIGSW:
1455: case UNKWNSW:
1456: case PAHELP:
1457: return NOTOK;
1458:
1459: case PAFISW:
1460: if (!(file = *args++) || *file == '-')
1461: return NOTOK;
1462: continue;
1463: }
1464: if (*cp == '+' || *cp == '@')
1465: return NOTOK;
1466: }
1467:
1468: file = path (file ? file : "./msgbox", TFILE);
1469: result = access (file, 0) == NOTOK ? OK : NOTOK;
1470: free (file);
1471:
1472: return result;
1473: }
1474:
1475: /* */
1476:
1477: static struct swit pickswit[] = {
1478: #define PIANSW 0
1479: "and", 0,
1480: #define PIORSW 1
1481: "or", 0,
1482: #define PINTSW 2
1483: "not", 0,
1484: #define PILBSW 3
1485: "lbrace", 0,
1486: #define PIRBSW 4
1487: "rbrace", 0,
1488:
1489: #define PICCSW 5
1490: "cc pattern", 0,
1491: #define PIDASW 6
1492: "date pattern", 0,
1493: #define PIFRSW 7
1494: "from pattern", 0,
1495: #define PISESW 8
1496: "search pattern", 0,
1497: #define PISUSW 9
1498: "subject pattern", 0,
1499: #define PITOSW 10
1500: "to pattern", 0,
1501: #define PIOTSW 11
1502: "-othercomponent pattern", 15,
1503: #define PIAFSW 12
1504: "after date", 0,
1505: #define PIBFSW 13
1506: "before date", 0,
1507: #define PIDFSW 14
1508: "datefield field", 5,
1509: #define PISQSW 15
1510: "sequence name", 0,
1511: #define PIPUSW 16
1512: "public", 0,
1513: #define PINPUSW 17
1514: "nopublic", 0,
1515: #define PIZRSW 18
1516: "zero", 0,
1517: #define PINZRSW 19
1518: "nozero", 0,
1519: #define PILISW 20
1520: "list", 0,
1521: #define PINLISW 21
1522: "nolist", 0,
1523: #define PIHELP 22
1524: "help", 4,
1525:
1526: NULL, NULL
1527: };
1528:
1529: /* */
1530:
1531: pickcmd (args)
1532: char **args;
1533: {
1534: int zerosw = 1,
1535: msgp = 0,
1536: seqp = 0,
1537: vecp = 0,
1538: hi,
1539: lo,
1540: msgnum;
1541: char *cp,
1542: buf[BUFSIZ],
1543: *msgs[MAXARGS],
1544: *seqs[NATTRS],
1545: *vec[MAXARGS];
1546: register FILE *zp;
1547:
1548: while (cp = *args++) {
1549: if (*cp == '-') {
1550: if (*++cp == '-') {
1551: vec[vecp++] = --cp;
1552: goto pattern;
1553: }
1554: switch (smatch (cp, pickswit)) {
1555: case AMBIGSW:
1556: ambigsw (cp, pickswit);
1557: return;
1558: case UNKWNSW:
1559: fprintf (stderr, "-%s unknown\n", cp);
1560: return;
1561: case PIHELP:
1562: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1563: help (buf, pickswit);
1564: return;
1565:
1566: case PICCSW:
1567: case PIDASW:
1568: case PIFRSW:
1569: case PISUSW:
1570: case PITOSW:
1571: case PIDFSW:
1572: case PIAFSW:
1573: case PIBFSW:
1574: case PISESW:
1575: vec[vecp++] = --cp;
1576: pattern: ;
1577: if (!(cp = *args++)) {/* allow -xyz arguments */
1578: advise (NULLCP, "missing argument to %s", args[-2]);
1579: return;
1580: }
1581: vec[vecp++] = cp;
1582: continue;
1583: case PIOTSW:
1584: advise (NULLCP, "internal error!");
1585: return;
1586: case PIANSW:
1587: case PIORSW:
1588: case PINTSW:
1589: case PILBSW:
1590: case PIRBSW:
1591: vec[vecp++] = --cp;
1592: continue;
1593:
1594: case PISQSW:
1595: if (!(cp = *args++) || *cp == '-') {
1596: advise (NULLCP, "missing argument to %s", args[-2]);
1597: return;
1598: }
1599: if (seqp < NATTRS)
1600: seqs[seqp++] = cp;
1601: else {
1602: advise (NULLCP, "only %d sequences allowed!", NATTRS);
1603: return;
1604: }
1605: continue;
1606: case PIZRSW:
1607: zerosw++;
1608: continue;
1609: case PINZRSW:
1610: zerosw = 0;
1611: continue;
1612:
1613: case PIPUSW: /* not implemented */
1614: case PINPUSW:
1615: case PILISW:
1616: case PINLISW:
1617: continue;
1618: }
1619: }
1620: if (*cp == '+' || *cp == '@') {
1621: advise (NULLCP, "sorry, no folders allowed!");
1622: return;
1623: }
1624: else
1625: msgs[msgp++] = cp;
1626: }
1627: vec[vecp] = NULL;
1628:
1629: if (!msgp)
1630: msgs[msgp++] = "all";
1631: for (msgnum = 0; msgnum < msgp; msgnum++)
1632: if (!m_convert (mp, msgs[msgnum]))
1633: return;
1634: m_setseq (mp);
1635:
1636: interrupted = 0;
1637: if (!pcompile (vec, NULLCP))
1638: return;
1639:
1640: lo = mp -> lowsel;
1641: hi = mp -> hghsel;
1642:
1643: for (msgnum = mp -> lowsel;
1644: msgnum <= mp -> hghsel && !interrupted;
1645: msgnum++)
1646: if (mp -> msgstats[msgnum] & SELECTED) {
1647: zp = msh_ready (msgnum, 1);
1648: if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1649: fmsh ? 0L : Msgs[msgnum].m_stop)) {
1650: if (msgnum < lo)
1651: lo = msgnum;
1652: if (msgnum > hi)
1653: hi = msgnum;
1654: }
1655: else {
1656: mp -> msgstats[msgnum] &= ~SELECTED;
1657: mp -> numsel--;
1658: }
1659: }
1660:
1661: if (interrupted)
1662: return;
1663:
1664: mp -> lowsel = lo;
1665: mp -> hghsel = hi;
1666:
1667: if (mp -> numsel <= 0) {
1668: advise (NULLCP, "no messages match specification");
1669: return;
1670: }
1671:
1672: seqs[seqp] = NULL;
1673: for (seqp = 0; seqs[seqp]; seqp++) {
1674: if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1675: return;
1676: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1677: if (mp -> msgstats[msgnum] & SELECTED)
1678: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1679: return;
1680: }
1681:
1682: printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s");
1683: }
1684:
1685: /* */
1686:
1687: static struct swit replswit[] = {
1688: #define REANSW 0
1689: "annotate", 0,
1690: #define RENANSW 1
1691: "noannotate", 0,
1692: #define RECCSW 2
1693: "cc type", 0,
1694: #define RENCCSW 3
1695: "nocc type", 0,
1696: #define REDFSW 4
1697: "draftfolder +folder", 0,
1698: #define REDMSW 5
1699: "draftmessage msg", 0,
1700: #define RENDFSW 6
1701: "nodraftfolder", 0,
1702: #define REEDTSW 7
1703: "editor editor", 0,
1704: #define RENEDSW 8
1705: "noedit", 0,
1706: #define REFCCSW 9
1707: "fcc +folder", 0,
1708: #define REFLTSW 10
1709: "filter filterfile", 0,
1710: #define REFRMSW 11
1711: "form formfile", 0,
1712: #define REFRSW 12
1713: "format", 5,
1714: #define RENFRSW 13
1715: "noformat", 7,
1716: #define REINSW 14
1717: "inplace", 0,
1718: #define RENINSW 15
1719: "noinplace", 0,
1720: #define REQUSW 16
1721: "query", 0,
1722: #define RENQUSW 17
1723: "noquery", 0,
1724: #define REWHTSW 18
1725: "whatnowproc program", 0,
1726: #define RENWTSW 19
1727: "nowhatnow", 0,
1728: #define REWIDSW 20
1729: "width columns", 0,
1730: #define REHELP 21
1731: "help", 4,
1732:
1733: NULL, NULL
1734: };
1735:
1736: /* */
1737:
1738: replcmd (args)
1739: char **args;
1740: {
1741: int vecp = 1;
1742: char *cp,
1743: *msg = NULL,
1744: buf[BUFSIZ],
1745: *vec[MAXARGS];
1746:
1747: if (fmsh) {
1748: forkcmd (args, cmd_name);
1749: return;
1750: }
1751:
1752: while (cp = *args++) {
1753: if (*cp == '-')
1754: switch (smatch (++cp, replswit)) {
1755: case AMBIGSW:
1756: ambigsw (cp, replswit);
1757: return;
1758: case UNKWNSW:
1759: fprintf (stderr, "-%s unknown\n", cp);
1760: return;
1761: case REHELP:
1762: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1763: help (buf, replswit);
1764: return;
1765:
1766: case REANSW: /* not implemented */
1767: case RENANSW:
1768: case REINSW:
1769: case RENINSW:
1770: continue;
1771:
1772: case REFRSW:
1773: case RENFRSW:
1774: case REQUSW:
1775: case RENQUSW:
1776: case RENDFSW:
1777: case RENEDSW:
1778: case RENWTSW:
1779: vec[vecp++] = --cp;
1780: continue;
1781:
1782: case RECCSW:
1783: case RENCCSW:
1784: case REEDTSW:
1785: case REFCCSW:
1786: case REFLTSW:
1787: case REFRMSW:
1788: case REWIDSW:
1789: case REDFSW:
1790: case REDMSW:
1791: case REWHTSW:
1792: vec[vecp++] = --cp;
1793: if (!(cp = *args++) || *cp == '-') {
1794: advise (NULLCP, "missing argument to %s", args[-2]);
1795: return;
1796: }
1797: vec[vecp++] = cp;
1798: continue;
1799: }
1800: if (*cp == '+' || *cp == '@') {
1801: advise (NULLCP, "sorry, no folders allowed!");
1802: return;
1803: }
1804: else
1805: if (msg) {
1806: advise (NULLCP, "only one message at a time!");
1807: return;
1808: }
1809: else
1810: msg = cp;
1811: }
1812:
1813: vec[0] = cmd_name;
1814: vec[vecp++] = "-file";
1815: vec[vecp] = NULL;
1816: if (!msg)
1817: msg = "cur";
1818: if (!m_convert (mp, msg))
1819: return;
1820: m_setseq (mp);
1821:
1822: if (mp -> numsel > 1) {
1823: advise (NULLCP, "only one message at a time!");
1824: return;
1825: }
1826: (void) process (mp -> hghsel, cmd_name, vecp, vec);
1827: m_setcur (mp, mp -> hghsel);
1828: }
1829:
1830: /* */
1831:
1832: static struct swit rmmswit[] = {
1833: #define RMHELP 0
1834: "help", 4,
1835:
1836: NULL, NULL
1837: };
1838:
1839: /* */
1840:
1841: rmmcmd (args)
1842: char **args;
1843: {
1844: int msgp = 0,
1845: msgnum;
1846: char *cp,
1847: buf[BUFSIZ],
1848: *msgs[MAXARGS];
1849:
1850: while (cp = *args++) {
1851: if (*cp == '-')
1852: switch (smatch (++cp, rmmswit)) {
1853: case AMBIGSW:
1854: ambigsw (cp, rmmswit);
1855: return;
1856: case UNKWNSW:
1857: fprintf (stderr, "-%s unknown\n", cp);
1858: return;
1859: case RMHELP:
1860: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1861: help (buf, rmmswit);
1862: return;
1863: }
1864: if (*cp == '+' || *cp == '@') {
1865: advise (NULLCP, "sorry, no folders allowed!");
1866: return;
1867: }
1868: else
1869: msgs[msgp++] = cp;
1870: }
1871:
1872: if (!msgp)
1873: msgs[msgp++] = "cur";
1874: for (msgnum = 0; msgnum < msgp; msgnum++)
1875: if (!m_convert (mp, msgs[msgnum]))
1876: return;
1877: m_setseq (mp);
1878:
1879: rmm ();
1880: }
1881:
1882: /* */
1883:
1884: static void rmm ()
1885: {
1886: register int msgnum,
1887: vecp;
1888: register char *cp;
1889: char buffer[BUFSIZ],
1890: *vec[MAXARGS];
1891:
1892: if (fmsh) {
1893: if (rmmproc) {
1894: if (mp -> numsel > MAXARGS - 1) {
1895: advise (NULLCP, "more than %d messages for %s exec",
1896: MAXARGS - 1, rmmproc);
1897: return;
1898: }
1899: vecp = 0;
1900: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1901: if (mp -> msgstats[msgnum] & SELECTED)
1902: vec[vecp++] = getcpy (m_name (msgnum));
1903: vec[vecp] = NULL;
1904: forkcmd (vec, rmmproc);
1905: for (vecp = 0; vec[vecp]; vecp++)
1906: free (vec[vecp]);
1907: }
1908: else
1909: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1910: if (mp -> msgstats[msgnum] & SELECTED) {
1911: (void) strcpy (buffer, m_backup (cp = m_name (msgnum)));
1912: if (rename (cp, buffer) == NOTOK)
1913: admonish (buffer, "unable to rename %s to", cp);
1914: }
1915: }
1916:
1917: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1918: if (mp -> msgstats[msgnum] & SELECTED) {
1919: mp -> msgstats[msgnum] |= DELETED;
1920: mp -> msgstats[msgnum] &= ~EXISTS;
1921: }
1922:
1923: if ((mp -> nummsg -= mp -> numsel) <= 0) {
1924: if (fmsh)
1925: admonish (NULLCP, "no messages remaining in +%s", fmsh);
1926: else
1927: admonish (NULLCP, "no messages remaining in %s", mp -> foldpath);
1928: mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
1929: }
1930: if (mp -> lowsel == mp -> lowmsg) {
1931: for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
1932: if (mp -> msgstats[msgnum] & EXISTS)
1933: break;
1934: mp -> lowmsg = msgnum;
1935: }
1936: if (mp -> hghsel == mp -> hghmsg) {
1937: for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--)
1938: if (mp -> msgstats[msgnum] & EXISTS)
1939: break;
1940: mp -> hghmsg = msgnum;
1941: }
1942:
1943: mp -> msgflags |= MODIFIED;
1944: modified++;
1945: }
1946:
1947: /* */
1948:
1949: static struct swit scanswit[] = {
1950: #define SCCLR 0
1951: "clear", 0,
1952: #define SCNCLR 1
1953: "noclear", 0,
1954: #define SCFORM 2
1955: "form formatfile", 0,
1956: #define SCFMT 3
1957: "format string", 5,
1958: #define SCHEAD 4
1959: "header", 0,
1960: #define SCNHEAD 5
1961: "noheader", 0,
1962: #define SCWID 6
1963: "width columns", 0,
1964: #define SCHELP 7
1965: "help", 4,
1966:
1967: NULL, NULL
1968: };
1969:
1970: /* */
1971:
1972: scancmd (args)
1973: char **args;
1974: {
1975: #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
1976:
1977: int clearsw = 0,
1978: headersw = 0,
1979: width = 0,
1980: msgp = 0,
1981: msgnum,
1982: optim,
1983: state;
1984: char *cp,
1985: *form = NULL,
1986: *format = NULL,
1987: buf[BUFSIZ],
1988: *nfs,
1989: *msgs[MAXARGS];
1990: register FILE *zp;
1991: static int s_optim = 0;
1992: static char *s_form = NULL,
1993: *s_format = NULL;
1994:
1995: while (cp = *args++) {
1996: if (*cp == '-')
1997: switch (smatch (++cp, scanswit)) {
1998: case AMBIGSW:
1999: ambigsw (cp, scanswit);
2000: return;
2001: case UNKWNSW:
2002: fprintf (stderr, "-%s unknown\n", cp);
2003: return;
2004: case SCHELP:
2005: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2006: help (buf, scanswit);
2007: return;
2008:
2009: case SCCLR:
2010: clearsw++;
2011: continue;
2012: case SCNCLR:
2013: clearsw = 0;
2014: continue;
2015: case SCHEAD:
2016: headersw++;
2017: continue;
2018: case SCNHEAD:
2019: headersw = 0;
2020: continue;
2021: case SCFORM:
2022: if (!(form = *args++) || *form == '-') {
2023: advise (NULLCP, "missing argument to %s", args[-2]);
2024: return;
2025: }
2026: format = NULL;
2027: continue;
2028: case SCFMT:
2029: if (!(format = *args++) || *format == '-') {
2030: advise (NULLCP, "missing argument to %s", args[-2]);
2031: return;
2032: }
2033: form = NULL;
2034: continue;
2035: case SCWID:
2036: if (!(cp = *args++) || *cp == '-') {
2037: advise (NULLCP, "missing argument to %s", args[-2]);
2038: return;
2039: }
2040: width = atoi (cp);
2041: continue;
2042: }
2043: if (*cp == '+' || *cp == '@') {
2044: advise (NULLCP, "sorry, no folders allowed!");
2045: return;
2046: }
2047: else
2048: msgs[msgp++] = cp;
2049: }
2050:
2051: if (!msgp)
2052: msgs[msgp++] = "all";
2053: for (msgnum = 0; msgnum < msgp; msgnum++)
2054: if (!m_convert (mp, msgs[msgnum]))
2055: return;
2056: m_setseq (mp);
2057:
2058: nfs = new_fs (form, format, FORMAT);
2059: if (scanl) { /* force scansbr to (re)compile format */
2060: (void) free (scanl);
2061: scanl = NULL;
2062: }
2063:
2064: if (s_optim == 0) {
2065: s_optim = optim = 1;
2066: s_form = form ? getcpy (form) : NULL;
2067: s_format = format ? getcpy (format) : NULL;
2068: }
2069: else
2070: optim = equiv (s_form, form) && equiv (s_format, format);
2071:
2072: interrupted = 0;
2073: for (msgnum = mp -> lowsel;
2074: msgnum <= mp -> hghsel && !interrupted;
2075: msgnum++)
2076: if (mp -> msgstats[msgnum] & SELECTED) {
2077: if (optim && Msgs[msgnum].m_scanl)
2078: printf ("%s", Msgs[msgnum].m_scanl);
2079: else {
2080: zp = msh_ready (msgnum, 0);
2081: switch (state = scan(zp, msgnum, 0, nfs, width,
2082: msgnum == mp -> curmsg, headersw, fmsh ? 0L :
2083: (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2084: 1, 0)) {
2085: case SCNMSG:
2086: case SCNENC:
2087: case SCNERR:
2088: if (optim)
2089: Msgs[msgnum].m_scanl = getcpy (scanl);
2090: break;
2091:
2092: default:
2093: advise (NULLCP, "scan() botch (%d)", state);
2094: return;
2095:
2096: case SCNEOF:
2097: printf ("%*d empty\n", DMAXFOLDER, msgnum);
2098: break;
2099: }
2100: }
2101: headersw = 0;
2102: }
2103:
2104: if (clearsw)
2105: clear_screen ();
2106: }
2107:
2108: /* */
2109:
2110: static struct swit showswit[] = {
2111: #define SHDRAFT 0
2112: "draft", 5,
2113: #define SHFORM 1
2114: "form formfile", 4,
2115: #define SHPROG 2
2116: "moreproc program", 4,
2117: #define SHNPROG 3
2118: "nomoreproc", 3,
2119: #define SHLEN 4
2120: "length lines", 4,
2121: #define SHWID 5
2122: "width columns", 4,
2123: #define SHSHOW 6
2124: "showproc program", 4,
2125: #define SHNSHOW 7
2126: "noshowproc", 3,
2127: #define SHHEAD 8
2128: "header", 4,
2129: #define SHNHEAD 9
2130: "noheader", 3,
2131: #define SHHELP 10
2132: "help", 4,
2133:
2134: NULL, NULL
2135: };
2136:
2137: /* */
2138:
2139: showcmd (args)
2140: char **args;
2141: {
2142: int headersw = 1,
2143: nshow = 0,
2144: msgp = 0,
2145: vecp = 1,
2146: mhl = 0,
2147: seen = 0,
2148: mode = 0,
2149: i,
2150: msgnum;
2151: char *cp,
2152: *proc = showproc,
2153: buf[BUFSIZ],
2154: *msgs[MAXARGS],
2155: *vec[MAXARGS];
2156:
2157: if (uleq (cmd_name, "next"))
2158: mode = 1;
2159: else
2160: if (uleq (cmd_name, "prev"))
2161: mode = -1;
2162: while (cp = *args++) {
2163: if (*cp == '-')
2164: switch (i = smatch (++cp, showswit)) {
2165: case AMBIGSW:
2166: ambigsw (cp, showswit);
2167: return;
2168: case UNKWNSW:
2169: case SHNPROG:
2170: vec[vecp++] = --cp;
2171: continue;
2172: case SHHELP:
2173: (void) sprintf (buf,
2174: "%s %s[switches] [switches for showproc]",
2175: cmd_name, mode ? NULL : "[msgs] ");
2176: help (buf, showswit);
2177: return;
2178:
2179: case SHFORM:
2180: case SHPROG:
2181: case SHLEN:
2182: case SHWID:
2183: vec[vecp++] = --cp;
2184: if (!(cp = *args++) || *cp == '-') {
2185: advise (NULLCP, "missing argument to %s", args[-2]);
2186: return;
2187: }
2188: vec[vecp++] = cp;
2189: continue;
2190: case SHHEAD:
2191: headersw++;
2192: continue;
2193: case SHNHEAD:
2194: headersw = 0;
2195: continue;
2196: case SHSHOW:
2197: if (!(proc = *args++) || *proc == '-') {
2198: advise (NULLCP, "missing argument to %s", args[-2]);
2199: return;
2200: }
2201: nshow = 0;
2202: continue;
2203: case SHNSHOW:
2204: nshow++;
2205: continue;
2206:
2207: case SHDRAFT:
2208: advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw);
2209: return;
2210: }
2211: if (*cp == '+' || *cp == '@') {
2212: advise (NULLCP, "sorry, no folders allowed!");
2213: return;
2214: }
2215: else
2216: if (mode) {
2217: fprintf (stderr,
2218: "usage: %s [switches] [switches for showproc]\n",
2219: cmd_name);
2220: return;
2221: }
2222: else
2223: msgs[msgp++] = cp;
2224: }
2225: vec[vecp] = NULL;
2226:
2227: if (!msgp)
2228: msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2229: for (msgnum = 0; msgnum < msgp; msgnum++)
2230: if (!m_convert (mp, msgs[msgnum]))
2231: return;
2232: m_setseq (mp);
2233:
2234: if (nshow)
2235: proc = "cat";
2236: else
2237: if (strcmp (showproc, "mhl") == 0) {
2238: proc = mhlproc;
2239: mhl++;
2240: }
2241:
2242: seen = m_seqflag (mp, "unseen");
2243: vec[0] = r1bindex (proc, '/');
2244: if (mhl) {
2245: msgp = vecp;
2246: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2247: if (mp -> msgstats[msgnum] & SELECTED) {
2248: vec[vecp++] = getcpy (m_name (msgnum));
2249: if (seen)
2250: (void) m_seqdel (mp, "unseen", msgnum);
2251: }
2252: vec[vecp] = NULL;
2253: if (mp -> numsel == 1 && headersw)
2254: show (mp -> lowsel);
2255: (void) mhlsbr (vecp, vec, mhl_action);
2256: m_eomsbr ((int (*)()) 0);
2257: while (msgp < vecp)
2258: free (vec[msgp++]);
2259: }
2260: else {
2261: interrupted = 0;
2262: for (msgnum = mp -> lowsel;
2263: msgnum <= mp -> hghsel && !interrupted;
2264: msgnum++)
2265: if (mp -> msgstats[msgnum] & SELECTED) {
2266: switch (ask (msgnum)) {
2267: case NOTOK: /* QUIT */
2268: break;
2269:
2270: case OK: /* INTR */
2271: continue;
2272:
2273: default:
2274: if (mp -> numsel == 1 && headersw)
2275: show (msgnum);
2276: if (nshow)
2277: copy_message (msgnum, stdout);
2278: else
2279: (void) process (msgnum, proc, vecp, vec);
2280:
2281: if (seen)
2282: (void) m_seqdel (mp, "unseen", msgnum);
2283: continue;
2284: }
2285: break;
2286: }
2287: }
2288:
2289: m_setcur (mp, mp -> hghsel);
2290: }
2291:
2292: /* */
2293:
2294: static void show (msgnum)
2295: int msgnum;
2296: {
2297: if (Msgs[msgnum].m_bboard_id == 0)
2298: (void) readid (msgnum);
2299:
2300: printf ("(Message %d", msgnum);
2301: if (Msgs[msgnum].m_bboard_id > 0)
2302: printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2303: printf (")\n");
2304: }
2305:
2306:
2307: /* ARGSUSED */
2308:
2309: static int eom_action (c)
2310: int c;
2311: {
2312: return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2313: }
2314:
2315:
2316: static FP mhl_action (name)
2317: char *name;
2318: {
2319: int msgnum;
2320:
2321: if ((msgnum = m_atoi (name)) < mp -> lowmsg
2322: || msgnum > mp -> hghmsg
2323: || !(mp -> msgstats[msgnum] & EXISTS))
2324: return NULL;
2325: mhlnum = msgnum;
2326:
2327: mhlfp = msh_ready (msgnum, 1);
2328: if (!fmsh)
2329: m_eomsbr (eom_action);
2330:
2331: return mhlfp;
2332: }
2333:
2334:
2335: /* */
2336:
2337: static int ask (msgnum)
2338: int msgnum;
2339: {
2340: char buf[BUFSIZ];
2341:
2342: if (mp -> numsel == 1 || !interactive || redirected)
2343: return DONE;
2344:
2345: if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2346: if (mp -> lowsel != msgnum)
2347: printf ("\n\n\n");
2348: printf ("Press <return> to list \"%d\"...", msgnum);
2349: }
2350: (void) fflush (stdout);
2351: buf[0] = NULL;
2352: #ifndef BSD42
2353: (void) read (fileno (stdout), buf, sizeof buf);
2354: #else BSD42
2355: switch (setjmp (sigenv)) {
2356: case OK:
2357: should_intr = 1;
2358: (void) read (fileno (stdout), buf, sizeof buf);/* fall... */
2359:
2360: default:
2361: should_intr = 0;
2362: break;
2363: }
2364: #endif BSD42
2365: if (index (buf, '\n') == NULL)
2366: (void) putchar ('\n');
2367:
2368: if (told_to_quit) {
2369: told_to_quit = interrupted = 0;
2370: return NOTOK;
2371: }
2372: if (interrupted) {
2373: interrupted = 0;
2374: return OK;
2375: }
2376:
2377: return DONE;
2378: }
2379:
2380: /* */
2381:
2382: static struct swit sortswit[] = {
2383: #define SODATE 0
2384: "datefield field", 0,
2385: #define SOVERB 1
2386: "verbose", 0,
2387: #define SONVERB 2
2388: "noverbose", 0,
2389: #define SOHELP 3
2390: "help", 4,
2391:
2392: NULL, NULL
2393: };
2394:
2395: /* */
2396:
2397: sortcmd (args)
2398: char **args;
2399: {
2400: int msgp = 0,
2401: msgnum;
2402: char *cp,
2403: *datesw = NULL,
2404: buf[BUFSIZ],
2405: *msgs[MAXARGS];
2406: struct tws tb,
2407: *tw;
2408:
2409: if (fmsh) {
2410: forkcmd (args, cmd_name);
2411: return;
2412: }
2413:
2414: while (cp = *args++) {
2415: if (*cp == '-')
2416: switch (smatch (++cp, sortswit)) {
2417: case AMBIGSW:
2418: ambigsw (cp, sortswit);
2419: return;
2420: case UNKWNSW:
2421: fprintf (stderr, "-%s unknown\n", cp);
2422: return;
2423: case SOHELP:
2424: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2425: help (buf, sortswit);
2426: return;
2427:
2428: case SODATE:
2429: if (datesw) {
2430: advise (NULLCP, "only one date field at a time!");
2431: return;
2432: }
2433: if (!(datesw = *args++) || *datesw == '-') {
2434: advise (NULLCP, "missing argument to %s", args[-2]);
2435: return;
2436: }
2437: continue;
2438:
2439: case SOVERB: /* not implemented */
2440: case SONVERB:
2441: continue;
2442: }
2443: if (*cp == '+' || *cp == '@') {
2444: advise (NULLCP, "sorry, no folders allowed!");
2445: return;
2446: }
2447: else
2448: msgs[msgp++] = cp;
2449: }
2450:
2451: if (!msgp)
2452: msgs[msgp++] = "all";
2453: if (!datesw)
2454: datesw = "Date";
2455: for (msgnum = 0; msgnum < msgp; msgnum++)
2456: if (!m_convert (mp, msgs[msgnum]))
2457: return;
2458: m_setseq (mp);
2459:
2460: twscopy (&tb, dtwstime ());
2461:
2462: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
2463: if (Msgs[msgnum].m_scanl) {
2464: free (Msgs[msgnum].m_scanl);
2465: Msgs[msgnum].m_scanl = NULL;
2466: }
2467: if (mp -> msgstats[msgnum] & SELECTED) {
2468: if ((tw = getws (datesw, msgnum)) == NULL)
2469: tw = msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb;
2470: }
2471: else
2472: tw = &tb;
2473: twscopy (&Msgs[msgnum].m_tb, tw);
2474: Msgs[msgnum].m_stats = mp -> msgstats[msgnum];
2475: if (mp -> curmsg == msgnum)
2476: Msgs[msgnum].m_stats |= CUR;
2477: }
2478:
2479: qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1,
2480: sizeof (struct Msg), msgsort);
2481:
2482: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
2483: mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR;
2484: if (Msgs[msgnum].m_stats & CUR)
2485: m_setcur (mp, msgnum);
2486: }
2487:
2488: mp -> msgflags |= MODIFIED;
2489: modified++;
2490: }
2491:
2492: /* */
2493:
2494: static struct tws *getws (datesw, msgnum)
2495: char *datesw;
2496: int msgnum;
2497: {
2498: int state;
2499: char *bp,
2500: buf[BUFSIZ],
2501: name[NAMESZ];
2502: struct tws *tw;
2503: register FILE *zp;
2504:
2505: zp = msh_ready (msgnum, 0);
2506: for (state = FLD;;)
2507: switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2508: case FLD:
2509: case FLDEOF:
2510: case FLDPLUS:
2511: if (uleq (name, datesw)) {
2512: bp = getcpy (buf);
2513: while (state == FLDPLUS) {
2514: state = m_getfld (state, name, buf, sizeof buf, zp);
2515: bp = add (buf, bp);
2516: }
2517: if ((tw = dparsetime (bp)) == NULL)
2518: admonish (NULLCP,
2519: "unable to parse %s field in message %d",
2520: datesw, msgnum);
2521: free (bp);
2522: return tw;
2523: }
2524: while (state == FLDPLUS)
2525: state = m_getfld (state, name, buf, sizeof buf, zp);
2526: if (state != FLDEOF)
2527: continue;
2528:
2529: case BODY:
2530: case BODYEOF:
2531: case FILEEOF:
2532: admonish (NULLCP, "no %s field in message %d", datesw, msgnum);
2533: return NULL;
2534:
2535: case LENERR:
2536: case FMTERR:
2537: admonish (NULLCP, "format error in message %d", msgnum);
2538: return NULL;
2539:
2540: default:
2541: adios (NULLCP, "internal error -- you lose");
2542: }
2543: }
2544:
2545:
2546: static int msgsort (a, b)
2547: struct Msg *a,
2548: *b;
2549: {
2550: return twsort (&a -> m_tb, &b -> m_tb);
2551: }
2552:
2553: /* */
2554:
2555: static int process (msgnum, proc, vecp, vec)
2556: int msgnum,
2557: vecp;
2558: char *proc,
2559: **vec;
2560: {
2561: int child_id,
2562: status;
2563: char tmpfil[80];
2564: FILE *out;
2565:
2566: if (fmsh) {
2567: (void) strcpy (tmpfil, m_name (msgnum));
2568: (void) m_delete (pfolder);
2569: m_replace (pfolder, fmsh);
2570: m_sync (mp);
2571: m_update ();
2572: goto ready;
2573: }
2574:
2575: (void) strcpy (tmpfil, m_scratch ("", invo_name));
2576: if ((out = fopen (tmpfil, "w")) == NULL) {
2577: int olderr;
2578: extern int errno;
2579: char newfil[80];
2580:
2581: olderr = errno;
2582: (void) strcpy (newfil, m_tmpfil (invo_name));
2583: if ((out = fopen (newfil, "w")) == NULL) {
2584: errno = olderr;
2585: advise (tmpfil, "unable to create temporary file");
2586: return NOTOK;
2587: }
2588: else
2589: (void) strcpy (tmpfil, newfil);
2590: }
2591: copy_message (msgnum, out);
2592: (void) fclose (out);
2593:
2594: ready: ;
2595: (void) fflush (stdout);
2596: switch (child_id = fork ()) {
2597: case NOTOK:
2598: advise ("fork", "unable to");
2599: status = NOTOK;
2600: break;
2601:
2602: case OK:
2603: closefds (3);
2604: (void) signal (SIGINT, istat);
2605: (void) signal (SIGQUIT, qstat);
2606:
2607: vec[vecp++] = tmpfil;
2608: vec[vecp] = NULL;
2609:
2610: execvp (proc, vec);
2611: fprintf (stderr, "unable to exec ");
2612: perror (proc);
2613: _exit (1);
2614:
2615: default:
2616: status = pidXwait (child_id, NULLCP);
2617: break;
2618: }
2619:
2620: if (!fmsh)
2621: (void) unlink (tmpfil);
2622: return status;
2623: }
2624:
2625: /* */
2626:
2627: static void copy_message (msgnum, out)
2628: int msgnum;
2629: FILE * out;
2630: {
2631: long pos;
2632: static char buffer[BUFSIZ];
2633: register FILE * zp;
2634:
2635: zp = msh_ready (msgnum, 1);
2636: if (fmsh) {
2637: while (fgets (buffer, sizeof buffer, zp) != NULL) {
2638: fputs (buffer, out);
2639: if (interrupted && out == stdout)
2640: break;
2641: }
2642: }
2643: else {
2644: pos = ftell (zp);
2645: while (fgets (buffer, sizeof buffer, zp) != NULL
2646: && pos < Msgs[msgnum].m_stop) {
2647: fputs (buffer, out);
2648: pos += (long) strlen (buffer);
2649: if (interrupted && out == stdout)
2650: break;
2651: }
2652: }
2653: }
2654:
2655:
2656: static void copy_digest (msgnum, out)
2657: int msgnum;
2658: FILE * out;
2659: {
2660: char c;
2661: long pos;
2662: static char buffer[BUFSIZ];
2663: register FILE *zp;
2664:
2665: c = '\n';
2666: zp = msh_ready (msgnum, 1);
2667: if (!fmsh)
2668: pos = ftell (zp);
2669: while (fgets (buffer, sizeof buffer, zp) != NULL
2670: && !fmsh && pos < Msgs[msgnum].m_stop) {
2671: if (c == '\n' && *buffer == '-')
2672: (void) fputc (' ', out);
2673: fputs (buffer, out);
2674: c = buffer[strlen (buffer) - 1];
2675: if (!fmsh)
2676: pos += (long) strlen (buffer);
2677: if (interrupted && out == stdout)
2678: break;
2679: }
2680: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.