|
|
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: int eom_action ();
32: FP mhl_action ();
33:
34:
35: /* SORTM */
36: int msgsort ();
37: struct tws *getws ();
38:
39: /* */
40:
41: forkcmd (args, pgm)
42: char **args,
43: *pgm;
44: {
45: int child_id;
46: char *vec[MAXARGS];
47:
48: vec[0] = r1bindex (pgm, '/');
49: (void) copyip (args, vec + 1);
50:
51: if (fmsh) {
52: (void) m_delete (pfolder);
53: m_replace (pfolder, fmsh);
54: m_sync (mp);
55: m_update ();
56: }
57: (void) fflush (stdout);
58: switch (child_id = fork ()) {
59: case NOTOK:
60: advise ("fork", "unable to");
61: return;
62:
63: case OK:
64: closefds (3);
65: (void) signal (SIGINT, istat);
66: (void) signal (SIGQUIT, qstat);
67:
68: execvp (pgm, vec);
69: fprintf (stderr, "unable to exec ");
70: perror (cmd_name);
71: _exit (1);
72:
73: default:
74: (void) pidXwait (child_id, NULLCP);
75: break;
76: }
77: if (fmsh) { /* assume the worst case */
78: mp -> msgflags |= MODIFIED;
79: modified++;
80: }
81: }
82:
83: /* */
84:
85: static struct swit distswit[] = {
86: #define DIANSW 0
87: "annotate", 0,
88: #define DINANSW 1
89: "noannotate", 0,
90: #define DIDFSW 2
91: "draftfolder +folder", 0,
92: #define DIDMSW 3
93: "draftmessage msg", 0,
94: #define DINDFSW 4
95: "nodraftfolder", 0,
96: #define DIEDTSW 5
97: "editor editor", 0,
98: #define DINEDSW 6
99: "noedit", 0,
100: #define DIFRMSW 7
101: "form formfile", 0,
102: #define DIINSW 8
103: "inplace", 0,
104: #define DININSW 9
105: "noinplace", 0,
106: #define DIWHTSW 10
107: "whatnowproc program", 0,
108: #define DINWTSW 11
109: "nowhatnowproc", 0,
110: #define DIHELP 12
111: "help", 4,
112:
113: NULL, NULL
114: };
115:
116: /* */
117:
118: distcmd (args)
119: char **args;
120: {
121: int vecp = 1;
122: char *cp,
123: *msg = NULL,
124: buf[BUFSIZ],
125: *vec[MAXARGS];
126:
127: if (fmsh) {
128: forkcmd (args, cmd_name);
129: return;
130: }
131:
132: while (cp = *args++) {
133: if (*cp == '-')
134: switch (smatch (++cp, distswit)) {
135: case AMBIGSW:
136: ambigsw (cp, distswit);
137: return;
138: case UNKWNSW:
139: fprintf (stderr, "-%s unknown\n", cp);
140: return;
141: case DIHELP:
142: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
143: help (buf, distswit);
144: return;
145:
146: case DIANSW: /* not implemented */
147: case DINANSW:
148: case DIINSW:
149: case DININSW:
150: continue;
151:
152: case DINDFSW:
153: case DINEDSW:
154: case DINWTSW:
155: vec[vecp++] = --cp;
156: continue;
157:
158: case DIEDTSW:
159: case DIFRMSW:
160: case DIDFSW:
161: case DIDMSW:
162: case DIWHTSW:
163: vec[vecp++] = --cp;
164: if (!(cp = *args++) || *cp == '-') {
165: advise (NULLCP, "missing argument to %s", args[-2]);
166: return;
167: }
168: vec[vecp++] = cp;
169: continue;
170: }
171: if (*cp == '+' || *cp == '@') {
172: advise (NULLCP, "sorry, no folders allowed!");
173: return;
174: }
175: else
176: if (msg) {
177: advise (NULLCP, "only one message at a time!");
178: return;
179: }
180: else
181: msg = cp;
182: }
183:
184: vec[0] = cmd_name;
185: vec[vecp++] = "-file";
186: vec[vecp] = NULL;
187: if (!msg)
188: msg = "cur";
189: if (!m_convert (mp, msg))
190: return;
191: m_setseq (mp);
192:
193: if (mp -> numsel > 1) {
194: advise (NULLCP, "only one message at a time!");
195: return;
196: }
197: (void) process (mp -> hghsel, cmd_name, vecp, vec);
198: m_setcur (mp, mp -> hghsel);
199: }
200:
201: /* */
202:
203: static struct swit explswit[] = {
204: #define EXINSW 0
205: "inplace", 0,
206: #define EXNINSW 1
207: "noinplace", 0,
208: #define EXQISW 2
209: "quiet", 0,
210: #define EXNQISW 3
211: "noquiet", 0,
212: #define EXVBSW 4
213: "verbose", 0,
214: #define EXNVBSW 5
215: "noverbose", 0,
216: #define EXHELP 6
217: "help", 4,
218:
219: NULL, NULL
220: };
221:
222: /* */
223:
224: explcmd (args)
225: char **args;
226: {
227: int inplace = 0,
228: quietsw = 0,
229: verbosw = 0,
230: msgp = 0,
231: hi,
232: msgnum;
233: char *cp,
234: buf[BUFSIZ],
235: *msgs[MAXARGS];
236: struct Msg *smsgs;
237:
238: if (fmsh) {
239: forkcmd (args, cmd_name);
240: return;
241: }
242:
243: while (cp = *args++) {
244: if (*cp == '-')
245: switch (smatch (++cp, explswit)) {
246: case AMBIGSW:
247: ambigsw (cp, explswit);
248: return;
249: case UNKWNSW:
250: fprintf (stderr, "-%s unknown\n", cp);
251: return;
252: case EXHELP:
253: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
254: help (buf, explswit);
255: return;
256:
257: case EXINSW:
258: inplace++;
259: continue;
260: case EXNINSW:
261: inplace = 0;
262: continue;
263: case EXQISW:
264: quietsw++;
265: continue;
266: case EXNQISW:
267: quietsw = 0;
268: continue;
269: case EXVBSW:
270: verbosw++;
271: continue;
272: case EXNVBSW:
273: verbosw = 0;
274: continue;
275: }
276: if (*cp == '+' || *cp == '@') {
277: advise (NULLCP, "sorry, no folders allowed!");
278: return;
279: }
280: else
281: msgs[msgp++] = cp;
282: }
283:
284: if (!msgp)
285: msgs[msgp++] = "cur";
286: for (msgnum = 0; msgnum < msgp; msgnum++)
287: if (!m_convert (mp, msgs[msgnum]))
288: return;
289: m_setseq (mp);
290:
291: smsgs = (struct Msg *)
292: calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
293: if (smsgs == NULL)
294: adios (NULLCP, "unable to allocate folder storage");
295:
296: hi = mp -> hghmsg + 1;
297: interrupted = 0;
298: for (msgnum = mp -> lowsel;
299: msgnum <= mp -> hghsel && !interrupted;
300: msgnum++)
301: if (mp -> msgstats[msgnum] & SELECTED)
302: if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
303: break;
304:
305: free ((char *) smsgs);
306:
307: if (inplace)
308: m_setcur (mp, mp -> lowsel);
309: else
310: if (hi <= mp -> hghmsg)
311: m_setcur (mp, hi);
312:
313: mp -> msgflags |= MODIFIED;
314: modified++;
315: }
316:
317: /* */
318:
319: static burst (smsgs, msgnum, inplace, quietsw, verbosw)
320: struct Msg *smsgs;
321: int msgnum,
322: inplace,
323: quietsw,
324: verbosw;
325: {
326: int i,
327: j,
328: ld3,
329: wasdlm,
330: msgp;
331: long pos;
332: char c,
333: buffer[BUFSIZ];
334: register FILE *zp;
335:
336: ld3 = strlen (delim3);
337:
338: if (Msgs[msgnum].m_scanl) {
339: free (Msgs[msgnum].m_scanl);
340: Msgs[msgnum].m_scanl = NULL;
341: }
342:
343: pos = ftell (zp = msh_ready (msgnum, 1));
344: for (msgp = 1; msgp <= MAXFOLDER;) {
345: while (fgets (buffer, sizeof buffer, zp) != NULL
346: && buffer[0] == '\n'
347: && pos < Msgs[msgnum].m_stop)
348: pos += (long) strlen (buffer);
349: if (feof (zp) || pos >= Msgs[msgnum].m_stop)
350: break;
351: (void) fseek (zp, pos, 0);
352: smsgs[msgp].m_start = pos;
353:
354: for (c = NULL;
355: fgets (buffer, sizeof buffer, zp) != NULL
356: && pos < Msgs[msgnum].m_stop;
357: c = buffer[0])
358: if (strncmp (buffer, delim3, ld3) == 0
359: && peekc (zp) == '\n'
360: && (msgp == 1 || c == '\n'))
361: break;
362: else
363: pos += (long) strlen (buffer);
364:
365: wasdlm = strncmp (buffer, delim3, ld3) == 0;
366: if (smsgs[msgp].m_start != pos)
367: smsgs[msgp++].m_stop = c == '\n' && wasdlm ? pos - 1 : pos;
368: if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
369: if (wasdlm) {
370: smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
371: msgp++; /* fake "End of XXX Digest" */
372: }
373: break;
374: }
375: pos += (long) strlen (buffer);
376: }
377:
378: switch (--msgp) { /* toss "End of XXX Digest" */
379: case 0:
380: adios (NULLCP, "burst() botch -- you lose big");
381:
382: case 1:
383: if (!quietsw)
384: printf ("message %d not in digest format\n", msgnum);
385: return OK;
386:
387: default:
388: if (verbosw)
389: printf ("%d message%s exploded from digest %d\n",
390: msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum);
391: if (msgp == 2)
392: msgp++;
393: break;
394: }
395:
396: msgp--;
397: if ((i = msgp + mp -> hghmsg) > MAXFOLDER) {
398: advise (NULLCP, "more than %d messages", MAXFOLDER);
399: return NOTOK;
400: }
401: if ((mp = m_remsg (mp, 0, i)) == NULL)
402: adios (NULLCP, "unable to allocate folder storage");
403:
404: j = mp -> hghmsg;
405: mp -> hghmsg += msgp - 1;
406: mp -> nummsg += msgp - 1;
407: if (mp -> hghsel > msgnum)
408: mp -> hghsel += msgp - 1;
409:
410: if (inplace && msgp > 1)
411: for (i = mp -> hghmsg; j > msgnum; i--, j--) {
412: if (verbosw)
413: printf ("message %d becomes message %d\n", j, i);
414:
415: Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
416: Msgs[i].m_top = Msgs[j].m_top;
417: Msgs[i].m_start = Msgs[j].m_start;
418: Msgs[i].m_stop = Msgs[j].m_stop;
419: Msgs[i].m_scanl = NULL;
420: if (Msgs[j].m_scanl) {
421: free (Msgs[j].m_scanl);
422: Msgs[j].m_scanl = NULL;
423: }
424: mp -> msgstats[i] = mp -> msgstats[j];
425: }
426:
427: if (Msgs[msgnum].m_bboard_id == 0)
428: (void) readid (msgnum);
429:
430: mp -> msgstats[msgnum] &= ~SELECTED;
431: i = inplace ? msgnum + msgp - 1 : mp -> hghmsg;
432: for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) {
433: if (verbosw && i != msgnum)
434: printf ("message %d of digest %d becomes message %d\n",
435: j, msgnum, i);
436:
437: Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
438: Msgs[i].m_top = Msgs[j].m_top;
439: Msgs[i].m_start = smsgs[j].m_start;
440: Msgs[i].m_stop = smsgs[j].m_stop;
441: Msgs[i].m_scanl = NULL;
442: mp -> msgstats[i] = mp -> msgstats[msgnum];
443: }
444:
445: return OK;
446: }
447:
448: /* */
449:
450: static struct swit fileswit[] = {
451: #define FIDRFT 0
452: "draft", 0,
453: #define FILINK 1
454: "link", 0,
455: #define FINLINK 2
456: "nolink", 0,
457: #define FIPRES 3
458: "preserve", 0,
459: #define FINPRES 4
460: "nopreserve", 0,
461: #define FISRC 5
462: "src +folder", 0,
463: #define FIFILE 6
464: "file file", 0,
465: #define FIHELP 7
466: "help", 4,
467:
468: NULL, NULL
469: };
470:
471: /* */
472:
473: filecmd (args)
474: char **args;
475: {
476: int linksw = 0,
477: msgp = 0,
478: vecp = 1,
479: i,
480: msgnum;
481: char *cp,
482: buf[BUFSIZ],
483: *msgs[MAXARGS],
484: *vec[MAXARGS];
485:
486: if (fmsh) {
487: forkcmd (args, cmd_name);
488: return;
489: }
490:
491: while (cp = *args++) {
492: if (*cp == '-')
493: switch (i = smatch (++cp, fileswit)) {
494: case AMBIGSW:
495: ambigsw (cp, fileswit);
496: return;
497: case UNKWNSW:
498: fprintf (stderr, "-%s unknown\n", cp);
499: return;
500: case FIHELP:
501: (void) sprintf (buf, "%s +folder... [msgs] [switches]",
502: cmd_name);
503: help (buf, fileswit);
504: return;
505:
506: case FILINK:
507: linksw++;
508: continue;
509: case FINLINK:
510: linksw = 0;
511: continue;
512:
513: case FIPRES:
514: case FINPRES:
515: continue;
516:
517: case FISRC:
518: case FIDRFT:
519: case FIFILE:
520: advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw);
521: return;
522: }
523: if (*cp == '+' || *cp == '@')
524: vec[vecp++] = cp;
525: else
526: msgs[msgp++] = cp;
527: }
528:
529: vec[0] = cmd_name;
530: vec[vecp++] = "-file";
531: vec[vecp] = NULL;
532: if (!msgp)
533: msgs[msgp++] = "cur";
534: for (msgnum = 0; msgnum < msgp; msgnum++)
535: if (!m_convert (mp, msgs[msgnum]))
536: return;
537: m_setseq (mp);
538:
539: interrupted = 0;
540: for (msgnum = mp -> lowsel;
541: msgnum <= mp -> hghsel && !interrupted;
542: msgnum++)
543: if (mp -> msgstats[msgnum] & SELECTED)
544: if (process (msgnum, fileproc, vecp, vec)) {
545: mp -> msgstats[msgnum] &= ~SELECTED;
546: mp -> numsel--;
547: }
548:
549: if (mp -> numsel != mp -> nummsg || linksw)
550: m_setcur (mp, mp -> hghsel);
551: if (!linksw)
552: rmm ();
553: }
554:
555: /* */
556:
557: int filehak (args)
558: char **args;
559: {
560: int result,
561: vecp = 0;
562: char *cp,
563: *cwd,
564: *vec[MAXARGS];
565:
566: while (cp = *args++) {
567: if (*cp == '-')
568: switch (smatch (++cp, fileswit)) {
569: case AMBIGSW:
570: case UNKWNSW:
571: case FIHELP:
572: return NOTOK;
573:
574: case FILINK:
575: case FINLINK:
576: case FIPRES:
577: case FINPRES:
578: continue;
579:
580: case FISRC:
581: case FIDRFT:
582: case FIFILE:
583: return NOTOK;
584: }
585: if (*cp == '+' || *cp == '@')
586: vec[vecp++] = cp;
587: }
588: vec[vecp] = NULL;
589:
590: result = NOTOK;
591: cwd = NULL;
592: for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
593: if (cwd == NULL)
594: cwd = getcpy (pwd ());
595: (void) chdir (m_maildir (""));
596: cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
597: if (access (m_maildir (cp), 0) == NOTOK)
598: result = OK;
599: free (cp);
600: }
601: if (cwd)
602: (void) chdir (cwd);
603:
604: return result;
605: }
606:
607: /* */
608:
609: static struct swit foldswit[] = {
610: #define FLALSW 0
611: "all", 0,
612: #define FLFASW 1
613: "fast", 0,
614: #define FLNFASW 2
615: "nofast", 0,
616: #define FLHDSW 3
617: "header", 0,
618: #define FLNHDSW 4
619: "noheader", 0,
620: #define FLPKSW 5
621: "pack", 0,
622: #define FLNPKSW 6
623: "nopack", 0,
624: #define FLRCSW 7
625: "recurse", 0,
626: #define FLNRCSW 8
627: "norecurse", 0,
628: #define FLTLSW 9
629: "total", 0,
630: #define FLNTLSW 10
631: "nototal", 0,
632: #define FLPRSW 11
633: "print", 0,
634: #define FLPUSW 12
635: "push", 0,
636: #define FLPOSW 13
637: "pop", 0,
638: #define FLLISW 14
639: "list", 0,
640: #define FLHELP 15
641: "help", 4,
642:
643: NULL, NULL
644: };
645:
646: /* */
647:
648: foldcmd (args)
649: char **args;
650: {
651: int fastsw = 0,
652: headersw = 0,
653: packsw = 0,
654: hole,
655: msgnum;
656: char *cp,
657: *folder = NULL,
658: *msg = NULL,
659: buf[BUFSIZ],
660: **vec = args;
661:
662: if (args == NULL)
663: goto fast;
664:
665: while (cp = *args++) {
666: if (*cp == '-')
667: switch (smatch (++cp, foldswit)) {
668: case AMBIGSW:
669: ambigsw (cp, foldswit);
670: return;
671: case UNKWNSW:
672: fprintf (stderr, "-%s unknown\n", cp);
673: return;
674: case FLHELP:
675: (void) sprintf (buf, "%s [+folder] [msg] [switches]",
676: cmd_name);
677: help (buf, foldswit);
678: return;
679:
680: case FLALSW: /* not implemented */
681: case FLRCSW:
682: case FLNRCSW:
683: case FLTLSW:
684: case FLNTLSW:
685: case FLPRSW:
686: case FLPUSW:
687: case FLPOSW:
688: case FLLISW:
689: continue;
690:
691: case FLFASW:
692: fastsw++;
693: continue;
694: case FLNFASW:
695: fastsw = 0;
696: continue;
697: case FLHDSW:
698: headersw++;
699: continue;
700: case FLNHDSW:
701: headersw = 0;
702: continue;
703: case FLPKSW:
704: packsw++;
705: continue;
706: case FLNPKSW:
707: packsw = 0;
708: continue;
709: }
710: if (*cp == '+' || *cp == '@')
711: if (folder) {
712: advise (NULLCP, "only one folder at a time!\n");
713: return;
714: }
715: else
716: folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
717: : cp + 1;
718: else
719: if (msg) {
720: advise (NULLCP, "only one message at a time!\n");
721: return;
722: }
723: else
724: msg = cp;
725: }
726:
727: if (folder) {
728: if (*folder == NULL) {
729: advise (NULLCP, "null folder names are not permitted");
730: return;
731: }
732: if (fmsh) {
733: if (access (m_maildir (folder), 04) == NOTOK) {
734: advise (folder, "unable to read");
735: return;
736: }
737: }
738: else {
739: (void) strcpy (buf, folder);
740: if (expand (buf) == NOTOK)
741: return;
742: folder = buf;
743: if (access (folder, 04) == NOTOK) {
744: advise (folder, "unable to read");
745: return;
746: }
747: }
748: m_reset ();
749:
750: if (fmsh)
751: fsetup (folder);
752: else
753: setup (folder);
754: readids (0);
755: display_info (0);
756: }
757:
758: if (msg) {
759: if (!m_convert (mp, msg))
760: return;
761: m_setseq (mp);
762:
763: if (mp -> numsel > 1) {
764: advise (NULLCP, "only one message at a time!");
765: return;
766: }
767: m_setcur (mp, mp -> hghsel);
768: }
769:
770: if (packsw) {
771: if (fmsh) {
772: forkcmd (vec, cmd_name);
773: return;
774: }
775:
776: if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
777: adios (NULLCP, "unable to allocate folder storage");
778: for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
779: if (mp -> msgstats[msgnum] & EXISTS) {
780: if (msgnum != hole) {
781: Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
782: Msgs[hole].m_top = Msgs[msgnum].m_top;
783: Msgs[hole].m_start = Msgs[msgnum].m_start;
784: Msgs[hole].m_stop = Msgs[msgnum].m_stop;
785: Msgs[hole].m_scanl = NULL;
786: if (Msgs[msgnum].m_scanl) {
787: free (Msgs[msgnum].m_scanl);
788: Msgs[msgnum].m_scanl = NULL;
789: }
790: mp -> msgstats[hole] = mp -> msgstats[msgnum];
791: if (mp -> curmsg == msgnum)
792: m_setcur (mp, hole);
793: }
794: hole++;
795: }
796: if (mp -> nummsg > 0) {
797: mp -> lowmsg = 1;
798: mp -> hghmsg = hole - 1;
799: }
800: mp -> msgflags |= MODIFIED;
801: modified++;
802: }
803:
804: fast: ;
805: if (fastsw)
806: printf ("%s\n", fmsh ? fmsh : mp -> foldpath);
807: else {
808: if (headersw)
809: printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
810: DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
811: DMAXFOLDER - 2, "");
812: printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath);
813: if (mp -> hghmsg == 0)
814: printf ("has no messages%*s",
815: mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
816: else {
817: printf ("has %*d message%s (%*d-%*d)",
818: DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "",
819: DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg);
820: if (mp -> curmsg >= mp -> lowmsg
821: && mp -> curmsg <= mp -> hghmsg)
822: printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg);
823: }
824: printf (".\n");
825: }
826: }
827:
828: /* */
829:
830: static struct swit forwswit[] = {
831: #define FOANSW 0
832: "annotate", 0,
833: #define FONANSW 1
834: "noannotate", 0,
835: #define FODFSW 2
836: "draftfolder +folder", 0,
837: #define FODMSW 3
838: "draftmessage msg", 0,
839: #define FONDFSW 4
840: "nodraftfolder", 0,
841: #define FOEDTSW 5
842: "editor editor", 0,
843: #define FONEDSW 6
844: "noedit", 0,
845: #define FOFTRSW 7
846: "filter filterfile", 0,
847: #define FOFRMSW 8
848: "form formfile", 0,
849: #define FOFTSW 9
850: "format", 5,
851: #define FONFTSW 10
852: "noformat", 7,
853: #define FOINSW 11
854: "inplace", 0,
855: #define FONINSW 12
856: "noinplace", 0,
857: #define FOWHTSW 13
858: "whatnowproc program", 0,
859: #define FONWTSW 14
860: "nowhatnow", 0,
861: #define FOHELP 15
862: "help", 4,
863:
864: NULL, NULL
865: };
866:
867: /* */
868:
869: forwcmd (args)
870: char **args;
871: {
872: int msgp = 0,
873: vecp = 1,
874: msgnum;
875: char *cp,
876: *filter = NULL,
877: buf[BUFSIZ],
878: *msgs[MAXARGS],
879: *vec[MAXARGS];
880:
881: if (fmsh) {
882: forkcmd (args, cmd_name);
883: return;
884: }
885:
886: while (cp = *args++) {
887: if (*cp == '-')
888: switch (smatch (++cp, forwswit)) {
889: case AMBIGSW:
890: ambigsw (cp, forwswit);
891: return;
892: case UNKWNSW:
893: fprintf (stderr, "-%s unknown\n", cp);
894: return;
895: case FOHELP:
896: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
897: help (buf, forwswit);
898: return;
899:
900: case FOANSW: /* not implemented */
901: case FONANSW:
902: case FOINSW:
903: case FONINSW:
904: continue;
905:
906: case FONDFSW:
907: case FONEDSW:
908: case FONWTSW:
909: vec[vecp++] = --cp;
910: continue;
911:
912: case FOEDTSW:
913: case FOFRMSW:
914: case FODFSW:
915: case FODMSW:
916: case FOWHTSW:
917: vec[vecp++] = --cp;
918: if (!(cp = *args++) || *cp == '-') {
919: advise (NULLCP, "missing argument to %s", args[-2]);
920: return;
921: }
922: vec[vecp++] = cp;
923: continue;
924: case FOFTRSW:
925: if (!(filter = *args++) || *filter == '-') {
926: advise (NULLCP, "missing argument to %s", args[-2]);
927: return;
928: }
929: continue;
930: case FOFTSW:
931: if (access (filter = myfilter, 04) == NOTOK) {
932: advise (filter, "unable to read default filter file");
933: return;
934: }
935: continue;
936: case FONFTSW:
937: filter = NULL;
938: continue;
939: }
940: if (*cp == '+' || *cp == '@') {
941: advise (NULLCP, "sorry, no folders allowed!");
942: return;
943: }
944: else
945: msgs[msgp++] = cp;
946: }
947:
948: /* foil search of .mh_profile */
949: (void) sprintf (buf, "%sXXXXXX", invo_name);
950: vec[0] = mktemp (buf);
951: vec[vecp++] = "-file";
952: vec[vecp] = NULL;
953: if (!msgp)
954: msgs[msgp++] = "cur";
955: for (msgnum = 0; msgnum < msgp; msgnum++)
956: if (!m_convert (mp, msgs[msgnum]))
957: return;
958: m_setseq (mp);
959:
960: if (filter) {
961: (void) strcpy (buf, filter);
962: if (expand (buf) == NOTOK)
963: return;
964: if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) {
965: advise (filter, "unable to read");
966: free (filter);
967: return;
968: }
969: }
970: forw (cmd_name, filter, vecp, vec);
971: m_setcur (mp, mp -> hghsel);
972: if (filter)
973: free (filter);
974: }
975:
976: /* */
977:
978: static forw (proc, filter, vecp, vec)
979: int vecp;
980: char *proc,
981: *filter,
982: **vec;
983: {
984: int i,
985: child_id,
986: msgnum,
987: msgcnt;
988: char tmpfil[80],
989: *args[MAXARGS];
990: FILE *out;
991:
992: (void) strcpy (tmpfil, m_tmpfil (invo_name));
993: interrupted = 0;
994: if (filter)
995: switch (child_id = fork ()) {
996: case NOTOK:
997: advise ("fork", "unable to");
998: return;
999:
1000: case OK: /* "trust me" */
1001: if (freopen (tmpfil, "w", stdout) == NULL) {
1002: fprintf (stderr, "unable to create ");
1003: perror (tmpfil);
1004: _exit (1);
1005: }
1006: args[0] = r1bindex (mhlproc, '/');
1007: i = 1;
1008: args[i++] = "-forwall";
1009: args[i++] = "-form";
1010: args[i++] = filter;
1011: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1012: if (mp -> msgstats[msgnum] & SELECTED)
1013: args[i++] = getcpy (m_name (msgnum));
1014: args[i] = NULL;
1015: (void) mhlsbr (i, args, mhl_action);
1016: m_eomsbr ((int (*) ()) 0);
1017: (void) fclose (stdout);
1018: _exit (0);
1019:
1020: default:
1021: if (pidXwait (child_id, NULLCP))
1022: interrupted++;
1023: break;
1024: }
1025: else {
1026: if ((out = fopen (tmpfil, "w")) == NULL) {
1027: advise (tmpfil, "unable to create temporary file");
1028: return;
1029: }
1030:
1031: msgcnt = 1;
1032: for (msgnum = mp -> lowsel;
1033: msgnum <= mp -> hghsel && !interrupted;
1034: msgnum++)
1035: if (mp -> msgstats[msgnum] & SELECTED) {
1036: fprintf (out, "\n\n-------");
1037: if (msgnum == mp -> lowsel)
1038: fprintf (out, " Forwarded Message%s",
1039: mp -> numsel > 1 ? "s" : "");
1040: else
1041: fprintf (out, " Message %d", msgcnt);
1042: fprintf (out, "\n\n");
1043: copy_digest (msgnum, out);
1044: msgcnt++;
1045: }
1046:
1047: fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1048: mp -> numsel > 1 ? "s" : "");
1049: (void) fclose (out);
1050: }
1051:
1052: (void) fflush (stdout);
1053: if (!interrupted)
1054: switch (child_id = fork ()) {
1055: case NOTOK:
1056: advise ("fork", "unable to");
1057: break;
1058:
1059: case OK:
1060: closefds (3);
1061: (void) signal (SIGINT, istat);
1062: (void) signal (SIGQUIT, qstat);
1063:
1064: vec[vecp++] = tmpfil;
1065: vec[vecp] = NULL;
1066:
1067: execvp (proc, vec);
1068: fprintf (stderr, "unable to exec ");
1069: perror (proc);
1070: _exit (1);
1071:
1072: default:
1073: (void) pidXwait (child_id, NULLCP);
1074: break;
1075: }
1076:
1077: (void) unlink (tmpfil);
1078: }
1079:
1080: /* */
1081:
1082: static char *hlpmsg[] = {
1083: "The %s program emulates many of the commands found in the Rand MH",
1084: "system. Instead of operating on MH folders, commands to %s concern",
1085: "a single file.",
1086: "",
1087: "To see the list of commands available, just type a ``?'' followed by",
1088: "the RETURN key. To find out what switches each command takes, type",
1089: "the name of the command followed by ``-help''. To leave %s, use the",
1090: "``quit'' command.",
1091: "",
1092: "Although a lot of MH commands are found in %s, not all are fully",
1093: "implemented. %s will always recognize all legal switches for a",
1094: "given command though, and will let you know when you ask for an",
1095: "option that it is unable to perform.",
1096: "",
1097: "Running %s is fun, but using MH from your shell is far superior.",
1098: "After you have familiarized yourself with the MH style by using %s,",
1099: "you should try using MH from the shell. You can still use %s for",
1100: "message files that aren't in MH format, such as BBoard files.",
1101: NULL
1102: };
1103:
1104:
1105: /* ARGSUSED */
1106:
1107: helpcmd (args)
1108: char **args;
1109: {
1110: int i;
1111:
1112: for (i = 0; hlpmsg[i]; i++) {
1113: printf (hlpmsg[i], invo_name);
1114: (void) putchar ('\n');
1115: }
1116: }
1117:
1118: /* */
1119:
1120: static struct swit markswit[] = {
1121: #define MADDSW 0
1122: "add", 0,
1123: #define MDELSW 1
1124: "delete", 0,
1125: #define MLSTSW 2
1126: "list", 0,
1127: #define MSEQSW 3
1128: "sequence name", 0,
1129: #define MPUBSW 4
1130: "public", 0,
1131: #define MNPUBSW 5
1132: "nopublic", 0,
1133: #define MZERSW 6
1134: "zero", 0,
1135: #define MNZERSW 7
1136: "nozero", 0,
1137: #define MHELP 8
1138: "help", 4,
1139: #define MDBUGSW 9
1140: "debug", -5,
1141:
1142: NULL, NULL
1143: };
1144:
1145: /* */
1146:
1147: markcmd (args)
1148: char **args;
1149: {
1150: int addsw = 0,
1151: deletesw = 0,
1152: debugsw = 0,
1153: listsw = 0,
1154: zerosw = 0,
1155: seqp = 0,
1156: msgp = 0,
1157: i,
1158: msgnum;
1159: char *cp,
1160: buf[BUFSIZ],
1161: *seqs[NATTRS + 1],
1162: *msgs[MAXARGS];
1163:
1164: while (cp = *args++) {
1165: if (*cp == '-')
1166: switch (smatch (++cp, markswit)) {
1167: case AMBIGSW:
1168: ambigsw (cp, markswit);
1169: return;
1170: case UNKWNSW:
1171: fprintf (stderr, "-%s unknown\n", cp);
1172: return;
1173: case MHELP:
1174: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1175: help (buf, markswit);
1176: return;
1177:
1178: case MADDSW:
1179: addsw++;
1180: deletesw = listsw = 0;
1181: continue;
1182: case MDELSW:
1183: deletesw++;
1184: addsw = listsw = 0;
1185: continue;
1186: case MLSTSW:
1187: listsw++;
1188: addsw = deletesw = 0;
1189: continue;
1190:
1191: case MSEQSW:
1192: if (!(cp = *args++) || *cp == '-') {
1193: advise (NULLCP, "missing argument to %s", args[-2]);
1194: return;
1195: }
1196: if (seqp < NATTRS)
1197: seqs[seqp++] = cp;
1198: else {
1199: advise (NULLCP, "only %d sequences allowed!", NATTRS);
1200: return;
1201: }
1202: continue;
1203:
1204: case MPUBSW: /* not implemented */
1205: case MNPUBSW:
1206: continue;
1207:
1208: case MDBUGSW:
1209: debugsw++;
1210: continue;
1211:
1212: case MZERSW:
1213: zerosw++;
1214: continue;
1215: case MNZERSW:
1216: zerosw = 0;
1217: continue;
1218: }
1219: if (*cp == '+' || *cp == '@') {
1220: advise (NULLCP, "sorry, no folders allowed!");
1221: return;
1222: }
1223: else
1224: msgs[msgp++] = cp;
1225: }
1226:
1227: if (!addsw && !deletesw && !listsw)
1228: if (seqp)
1229: addsw++;
1230: else
1231: if (debugsw)
1232: listsw++;
1233: else {
1234: seqs[seqp++] = "unseen";
1235: deletesw++;
1236: zerosw = 0;
1237: if (!msgp)
1238: msgs[msgp++] = "all";
1239: }
1240:
1241: if (!msgp)
1242: msgs[msgp++] = listsw ? "all" :"cur";
1243: for (msgnum = 0; msgnum < msgp; msgnum++)
1244: if (!m_convert (mp, msgs[msgnum]))
1245: return;
1246:
1247: if (debugsw) {
1248: printf ("invo_name=%s mypath=%s defpath=%s\n",
1249: invo_name, mypath, defpath);
1250: printf ("ctxpath=%s context flags=%s\n",
1251: ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS));
1252: printf ("foldpath=%s flags=%s\n",
1253: mp -> foldpath,
1254: sprintb (buf, (unsigned) mp -> msgflags, FBITS));
1255: printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1256: mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg);
1257: printf ("lowsel=%d hghsel=%d numsel=%d\n",
1258: mp -> lowsel, mp -> hghsel, mp -> numsel);
1259: #ifndef MTR
1260: printf ("lowoff=%d hghoff=%d\n",
1261: mp -> lowoff, mp -> hghoff);
1262: #else MTR
1263: printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n",
1264: mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats);
1265: #endif MTR
1266: }
1267:
1268: if (seqp == 0 && (addsw || deletesw)) {
1269: advise (NULLCP, "-%s requires at least one -sequence argument",
1270: addsw ? "add" : "delete");
1271: return;
1272: }
1273: seqs[seqp] = NULL;
1274:
1275: if (addsw)
1276: for (seqp = 0; seqs[seqp]; seqp++) {
1277: if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1278: return;
1279: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1280: if (mp -> msgstats[msgnum] & SELECTED)
1281: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1282: return;
1283: }
1284:
1285: if (deletesw)
1286: for (seqp = 0; seqs[seqp]; seqp++) {
1287: if (zerosw)
1288: for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1289: if (mp -> msgstats[msgnum] & EXISTS)
1290: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1291: return;
1292: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1293: if (mp -> msgstats[msgnum] & SELECTED)
1294: if (!m_seqdel (mp, seqs[seqp], msgnum))
1295: return;
1296: }
1297:
1298: if (listsw) {
1299: int bits = FFATTRSLOT;
1300:
1301: if (seqp == 0)
1302: for (i = 0; mp -> msgattrs[i]; i++)
1303: printf ("%s%s: %s\n", mp -> msgattrs[i],
1304: mp -> attrstats & (1 << (bits + i))
1305: ? " (private)" : "",
1306: m_seq (mp, mp -> msgattrs[i]));
1307: else
1308: for (seqp = 0; seqs[seqp]; seqp++)
1309: printf ("%s%s: %s\n", seqs[seqp], m_seq (mp, seqs[seqp]));
1310:
1311: interrupted = 0;
1312: if (debugsw)
1313: for (msgnum = mp -> lowsel;
1314: msgnum <= mp -> hghsel && !interrupted;
1315: msgnum++)
1316: if (mp -> msgstats[msgnum] & SELECTED) {
1317: printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1318: DMAXFOLDER, msgnum,
1319: Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top,
1320: Msgs[msgnum].m_start, Msgs[msgnum].m_stop,
1321: sprintb (buf, (unsigned) mp -> msgstats[msgnum],
1322: m_seqbits (mp)));
1323: if (Msgs[msgnum].m_scanl)
1324: printf ("%s", Msgs[msgnum].m_scanl);
1325: }
1326: }
1327: }
1328:
1329: /* */
1330:
1331: static struct swit packswit[] = {
1332: #define PAFISW 0
1333: "file name", 0,
1334:
1335: #define PAHELP 1
1336: "help", 4,
1337:
1338: NULL, NULL
1339: };
1340:
1341: /* */
1342:
1343: packcmd (args)
1344: char **args;
1345: {
1346: int msgp = 0,
1347: md,
1348: msgnum;
1349: char *cp,
1350: *file = NULL,
1351: buf[BUFSIZ],
1352: *msgs[MAXARGS];
1353: struct stat st;
1354:
1355: if (fmsh) {
1356: forkcmd (args, cmd_name);
1357: return;
1358: }
1359:
1360: while (cp = *args++) {
1361: if (*cp == '-')
1362: switch (smatch (++cp, packswit)) {
1363: case AMBIGSW:
1364: ambigsw (cp, packswit);
1365: return;
1366: case UNKWNSW:
1367: fprintf (stderr, "-%s unknown\n", cp);
1368: return;
1369: case PAHELP:
1370: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1371: help (buf, packswit);
1372: return;
1373:
1374: case PAFISW:
1375: if (!(file = *args++) || *file == '-') {
1376: advise (NULLCP, "missing argument to %s", args[-2]);
1377: return;
1378: }
1379: continue;
1380: }
1381: if (*cp == '+' || *cp == '@') {
1382: advise (NULLCP, "sorry, no folders allowed!");
1383: return;
1384: }
1385: else
1386: msgs[msgp++] = cp;
1387: }
1388:
1389: if (!file)
1390: file = "./msgbox";
1391: file = path (file, TFILE);
1392: if (stat (file, &st) == NOTOK) {
1393: if (errno != ENOENT) {
1394: advise (file, "error on file");
1395: goto done_pack;
1396: }
1397: md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP));
1398: free (cp);
1399: if (!md)
1400: goto done_pack;
1401: }
1402:
1403: if (!msgp)
1404: msgs[msgp++] = "all";
1405: for (msgnum = 0; msgnum < msgp; msgnum++)
1406: if (!m_convert (mp, msgs[msgnum]))
1407: goto done_pack;
1408: m_setseq (mp);
1409:
1410: if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1411: advise (file, "unable to open");
1412: goto done_pack;
1413: }
1414: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1415: if (mp -> msgstats[msgnum] & SELECTED)
1416: if (pack (file, md, msgnum) == NOTOK)
1417: break;
1418: (void) mbx_close (file, md);
1419:
1420: if (mp -> hghsel != mp -> curmsg)
1421: m_setcur (mp, mp -> lowsel);
1422:
1423: done_pack: ;
1424: free (file);
1425: }
1426:
1427: /* */
1428:
1429: int pack (mailbox, md, msgnum)
1430: char *mailbox;
1431: int md,
1432: msgnum;
1433: {
1434: register FILE *zp;
1435:
1436: if (Msgs[msgnum].m_bboard_id == 0)
1437: (void) readid (msgnum);
1438:
1439: zp = msh_ready (msgnum, 1);
1440: return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1441: ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1442: }
1443:
1444: /* */
1445:
1446: int packhak (args)
1447: char **args;
1448: {
1449: int result;
1450: char *cp,
1451: *file = NULL;
1452:
1453: while (cp = *args++) {
1454: if (*cp == '-')
1455: switch (smatch (++cp, packswit)) {
1456: case AMBIGSW:
1457: case UNKWNSW:
1458: case PAHELP:
1459: return NOTOK;
1460:
1461: case PAFISW:
1462: if (!(file = *args++) || *file == '-')
1463: return NOTOK;
1464: continue;
1465: }
1466: if (*cp == '+' || *cp == '@')
1467: return NOTOK;
1468: }
1469:
1470: file = path (file ? file : "./msgbox", TFILE);
1471: result = access (file, 0) == NOTOK ? OK : NOTOK;
1472: free (file);
1473:
1474: return result;
1475: }
1476:
1477: /* */
1478:
1479: static struct swit pickswit[] = {
1480: #define PIANSW 0
1481: "and", 0,
1482: #define PIORSW 1
1483: "or", 0,
1484: #define PINTSW 2
1485: "not", 0,
1486: #define PILBSW 3
1487: "lbrace", 0,
1488: #define PIRBSW 4
1489: "rbrace", 0,
1490:
1491: #define PICCSW 5
1492: "cc pattern", 0,
1493: #define PIDASW 6
1494: "date pattern", 0,
1495: #define PIFRSW 7
1496: "from pattern", 0,
1497: #define PISESW 8
1498: "search pattern", 0,
1499: #define PISUSW 9
1500: "subject pattern", 0,
1501: #define PITOSW 10
1502: "to pattern", 0,
1503: #define PIOTSW 11
1504: "-othercomponent pattern", 15,
1505: #define PIAFSW 12
1506: "after date", 0,
1507: #define PIBFSW 13
1508: "before date", 0,
1509: #define PIDFSW 14
1510: "datefield field", 5,
1511: #define PISQSW 15
1512: "sequence name", 0,
1513: #define PIPUSW 16
1514: "public", 0,
1515: #define PINPUSW 17
1516: "nopublic", 0,
1517: #define PIZRSW 18
1518: "zero", 0,
1519: #define PINZRSW 19
1520: "nozero", 0,
1521: #define PILISW 20
1522: "list", 0,
1523: #define PINLISW 21
1524: "nolist", 0,
1525: #define PIHELP 22
1526: "help", 4,
1527:
1528: NULL, NULL
1529: };
1530:
1531: /* */
1532:
1533: pickcmd (args)
1534: char **args;
1535: {
1536: int zerosw = 1,
1537: msgp = 0,
1538: seqp = 0,
1539: vecp = 0,
1540: hi,
1541: lo,
1542: msgnum;
1543: char *cp,
1544: buf[BUFSIZ],
1545: *msgs[MAXARGS],
1546: *seqs[NATTRS],
1547: *vec[MAXARGS];
1548: register FILE *zp;
1549:
1550: while (cp = *args++) {
1551: if (*cp == '-') {
1552: if (*++cp == '-') {
1553: vec[vecp++] = --cp;
1554: goto pattern;
1555: }
1556: switch (smatch (cp, pickswit)) {
1557: case AMBIGSW:
1558: ambigsw (cp, pickswit);
1559: return;
1560: case UNKWNSW:
1561: fprintf (stderr, "-%s unknown\n", cp);
1562: return;
1563: case PIHELP:
1564: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1565: help (buf, pickswit);
1566: return;
1567:
1568: case PICCSW:
1569: case PIDASW:
1570: case PIFRSW:
1571: case PISUSW:
1572: case PITOSW:
1573: case PIDFSW:
1574: case PIAFSW:
1575: case PIBFSW:
1576: case PISESW:
1577: vec[vecp++] = --cp;
1578: pattern: ;
1579: if (!(cp = *args++)) {/* allow -xyz arguments */
1580: advise (NULLCP, "missing argument to %s", args[-2]);
1581: return;
1582: }
1583: vec[vecp++] = cp;
1584: continue;
1585: case PIOTSW:
1586: advise (NULLCP, "internal error!");
1587: return;
1588: case PIANSW:
1589: case PIORSW:
1590: case PINTSW:
1591: case PILBSW:
1592: case PIRBSW:
1593: vec[vecp++] = --cp;
1594: continue;
1595:
1596: case PISQSW:
1597: if (!(cp = *args++) || *cp == '-') {
1598: advise (NULLCP, "missing argument to %s", args[-2]);
1599: return;
1600: }
1601: if (seqp < NATTRS)
1602: seqs[seqp++] = cp;
1603: else {
1604: advise (NULLCP, "only %d sequences allowed!", NATTRS);
1605: return;
1606: }
1607: continue;
1608: case PIZRSW:
1609: zerosw++;
1610: continue;
1611: case PINZRSW:
1612: zerosw = 0;
1613: continue;
1614:
1615: case PIPUSW: /* not implemented */
1616: case PINPUSW:
1617: case PILISW:
1618: case PINLISW:
1619: continue;
1620: }
1621: }
1622: if (*cp == '+' || *cp == '@') {
1623: advise (NULLCP, "sorry, no folders allowed!");
1624: return;
1625: }
1626: else
1627: msgs[msgp++] = cp;
1628: }
1629: vec[vecp] = NULL;
1630:
1631: if (!msgp)
1632: msgs[msgp++] = "all";
1633: for (msgnum = 0; msgnum < msgp; msgnum++)
1634: if (!m_convert (mp, msgs[msgnum]))
1635: return;
1636: m_setseq (mp);
1637:
1638: interrupted = 0;
1639: if (!pcompile (vec, NULLCP))
1640: return;
1641:
1642: lo = mp -> lowsel;
1643: hi = mp -> hghsel;
1644:
1645: for (msgnum = mp -> lowsel;
1646: msgnum <= mp -> hghsel && !interrupted;
1647: msgnum++)
1648: if (mp -> msgstats[msgnum] & SELECTED) {
1649: zp = msh_ready (msgnum, 1);
1650: if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1651: fmsh ? 0L : Msgs[msgnum].m_stop)) {
1652: if (msgnum < lo)
1653: lo = msgnum;
1654: if (msgnum > hi)
1655: hi = msgnum;
1656: }
1657: else {
1658: mp -> msgstats[msgnum] &= ~SELECTED;
1659: mp -> numsel--;
1660: }
1661: }
1662:
1663: if (interrupted)
1664: return;
1665:
1666: mp -> lowsel = lo;
1667: mp -> hghsel = hi;
1668:
1669: if (mp -> numsel <= 0) {
1670: advise (NULLCP, "no messages match specification");
1671: return;
1672: }
1673:
1674: seqs[seqp] = NULL;
1675: for (seqp = 0; seqs[seqp]; seqp++) {
1676: if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1677: return;
1678: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1679: if (mp -> msgstats[msgnum] & SELECTED)
1680: if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1681: return;
1682: }
1683:
1684: printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s");
1685: }
1686:
1687: /* */
1688:
1689: static struct swit replswit[] = {
1690: #define REANSW 0
1691: "annotate", 0,
1692: #define RENANSW 1
1693: "noannotate", 0,
1694: #define RECCSW 2
1695: "cc type", 0,
1696: #define RENCCSW 3
1697: "nocc type", 0,
1698: #define REDFSW 4
1699: "draftfolder +folder", 0,
1700: #define REDMSW 5
1701: "draftmessage msg", 0,
1702: #define RENDFSW 6
1703: "nodraftfolder", 0,
1704: #define REEDTSW 7
1705: "editor editor", 0,
1706: #define RENEDSW 8
1707: "noedit", 0,
1708: #define REFCCSW 9
1709: "fcc +folder", 0,
1710: #define REFLTSW 10
1711: "filter filterfile", 0,
1712: #define REFRMSW 11
1713: "form formfile", 0,
1714: #define REFRSW 12
1715: "format", 5,
1716: #define RENFRSW 13
1717: "noformat", 7,
1718: #define REINSW 14
1719: "inplace", 0,
1720: #define RENINSW 15
1721: "noinplace", 0,
1722: #define REQUSW 16
1723: "query", 0,
1724: #define RENQUSW 17
1725: "noquery", 0,
1726: #define REWHTSW 18
1727: "whatnowproc program", 0,
1728: #define RENWTSW 19
1729: "nowhatnow", 0,
1730: #define REWIDSW 20
1731: "width columns", 0,
1732: #define REHELP 21
1733: "help", 4,
1734:
1735: NULL, NULL
1736: };
1737:
1738: /* */
1739:
1740: replcmd (args)
1741: char **args;
1742: {
1743: int vecp = 1;
1744: char *cp,
1745: *msg = NULL,
1746: buf[BUFSIZ],
1747: *vec[MAXARGS];
1748:
1749: if (fmsh) {
1750: forkcmd (args, cmd_name);
1751: return;
1752: }
1753:
1754: while (cp = *args++) {
1755: if (*cp == '-')
1756: switch (smatch (++cp, replswit)) {
1757: case AMBIGSW:
1758: ambigsw (cp, replswit);
1759: return;
1760: case UNKWNSW:
1761: fprintf (stderr, "-%s unknown\n", cp);
1762: return;
1763: case REHELP:
1764: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1765: help (buf, replswit);
1766: return;
1767:
1768: case REANSW: /* not implemented */
1769: case RENANSW:
1770: case REINSW:
1771: case RENINSW:
1772: continue;
1773:
1774: case REFRSW:
1775: case RENFRSW:
1776: case REQUSW:
1777: case RENQUSW:
1778: case RENDFSW:
1779: case RENEDSW:
1780: case RENWTSW:
1781: vec[vecp++] = --cp;
1782: continue;
1783:
1784: case RECCSW:
1785: case RENCCSW:
1786: case REEDTSW:
1787: case REFCCSW:
1788: case REFLTSW:
1789: case REFRMSW:
1790: case REWIDSW:
1791: case REDFSW:
1792: case REDMSW:
1793: case REWHTSW:
1794: vec[vecp++] = --cp;
1795: if (!(cp = *args++) || *cp == '-') {
1796: advise (NULLCP, "missing argument to %s", args[-2]);
1797: return;
1798: }
1799: vec[vecp++] = cp;
1800: continue;
1801: }
1802: if (*cp == '+' || *cp == '@') {
1803: advise (NULLCP, "sorry, no folders allowed!");
1804: return;
1805: }
1806: else
1807: if (msg) {
1808: advise (NULLCP, "only one message at a time!");
1809: return;
1810: }
1811: else
1812: msg = cp;
1813: }
1814:
1815: vec[0] = cmd_name;
1816: vec[vecp++] = "-file";
1817: vec[vecp] = NULL;
1818: if (!msg)
1819: msg = "cur";
1820: if (!m_convert (mp, msg))
1821: return;
1822: m_setseq (mp);
1823:
1824: if (mp -> numsel > 1) {
1825: advise (NULLCP, "only one message at a time!");
1826: return;
1827: }
1828: (void) process (mp -> hghsel, cmd_name, vecp, vec);
1829: m_setcur (mp, mp -> hghsel);
1830: }
1831:
1832: /* */
1833:
1834: static struct swit rmmswit[] = {
1835: #define RMHELP 0
1836: "help", 4,
1837:
1838: NULL, NULL
1839: };
1840:
1841: /* */
1842:
1843: rmmcmd (args)
1844: char **args;
1845: {
1846: int msgp = 0,
1847: msgnum;
1848: char *cp,
1849: buf[BUFSIZ],
1850: *msgs[MAXARGS];
1851:
1852: while (cp = *args++) {
1853: if (*cp == '-')
1854: switch (smatch (++cp, rmmswit)) {
1855: case AMBIGSW:
1856: ambigsw (cp, rmmswit);
1857: return;
1858: case UNKWNSW:
1859: fprintf (stderr, "-%s unknown\n", cp);
1860: return;
1861: case RMHELP:
1862: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1863: help (buf, rmmswit);
1864: return;
1865: }
1866: if (*cp == '+' || *cp == '@') {
1867: advise (NULLCP, "sorry, no folders allowed!");
1868: return;
1869: }
1870: else
1871: msgs[msgp++] = cp;
1872: }
1873:
1874: if (!msgp)
1875: msgs[msgp++] = "cur";
1876: for (msgnum = 0; msgnum < msgp; msgnum++)
1877: if (!m_convert (mp, msgs[msgnum]))
1878: return;
1879: m_setseq (mp);
1880:
1881: rmm ();
1882: }
1883:
1884: /* */
1885:
1886: static rmm () {
1887: register int msgnum,
1888: vecp;
1889: register char *cp;
1890: char buffer[BUFSIZ],
1891: *vec[MAXARGS];
1892:
1893: if (fmsh) {
1894: if (rmmproc) {
1895: if (mp -> numsel > MAXARGS - 1) {
1896: advise (NULLCP, "more than %d messages for %s exec",
1897: MAXARGS - 1, rmmproc);
1898: return;
1899: }
1900: vecp = 0;
1901: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1902: if (mp -> msgstats[msgnum] & SELECTED)
1903: vec[vecp++] = getcpy (m_name (msgnum));
1904: vec[vecp] = NULL;
1905: forkcmd (vec, rmmproc);
1906: for (vecp = 0; vec[vecp]; vecp++)
1907: free (vec[vecp]);
1908: }
1909: else
1910: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1911: if (mp -> msgstats[msgnum] & SELECTED) {
1912: (void) strcpy (buffer, m_backup (cp = m_name (msgnum)));
1913: if (rename (cp, buffer) == NOTOK)
1914: admonish (buffer, "unable to rename %s to", cp);
1915: }
1916: }
1917:
1918: for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1919: if (mp -> msgstats[msgnum] & SELECTED) {
1920: mp -> msgstats[msgnum] |= DELETED;
1921: mp -> msgstats[msgnum] &= ~EXISTS;
1922: }
1923:
1924: if ((mp -> nummsg -= mp -> numsel) <= 0) {
1925: if (fmsh)
1926: admonish (NULLCP, "no messages remaining in +%s", fmsh);
1927: else
1928: admonish (NULLCP, "no messages remaining in %s", mp -> foldpath);
1929: mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
1930: }
1931: if (mp -> lowsel == mp -> lowmsg) {
1932: for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
1933: if (mp -> msgstats[msgnum] & EXISTS)
1934: break;
1935: mp -> lowmsg = msgnum;
1936: }
1937: if (mp -> hghsel == mp -> hghmsg) {
1938: for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--)
1939: if (mp -> msgstats[msgnum] & EXISTS)
1940: break;
1941: mp -> hghmsg = msgnum;
1942: }
1943:
1944: mp -> msgflags |= MODIFIED;
1945: modified++;
1946: }
1947:
1948: /* */
1949:
1950: static struct swit scanswit[] = {
1951: #define SCCLR 0
1952: "clear", 0,
1953: #define SCNCLR 1
1954: "noclear", 0,
1955: #define SCFORM 2
1956: "form formatfile", 0,
1957: #define SCFMT 3
1958: "format string", 5,
1959: #define SCHEAD 4
1960: "header", 0,
1961: #define SCNHEAD 5
1962: "noheader", 0,
1963: #define SCWID 6
1964: "width columns", 0,
1965: #define SCHELP 7
1966: "help", 4,
1967:
1968: NULL, NULL
1969: };
1970:
1971: /* */
1972:
1973: scancmd (args)
1974: char **args;
1975: {
1976: #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
1977:
1978: int clearsw = 0,
1979: headersw = 0,
1980: width = 0,
1981: msgp = 0,
1982: msgnum,
1983: optim,
1984: state;
1985: char *cp,
1986: *form = NULL,
1987: *format = NULL,
1988: buf[BUFSIZ],
1989: *nfs,
1990: *msgs[MAXARGS];
1991: register FILE *zp;
1992: static int s_optim = 0;
1993: static char *s_form = NULL,
1994: *s_format = NULL;
1995:
1996: while (cp = *args++) {
1997: if (*cp == '-')
1998: switch (smatch (++cp, scanswit)) {
1999: case AMBIGSW:
2000: ambigsw (cp, scanswit);
2001: return;
2002: case UNKWNSW:
2003: fprintf (stderr, "-%s unknown\n", cp);
2004: return;
2005: case SCHELP:
2006: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2007: help (buf, scanswit);
2008: return;
2009:
2010: case SCCLR:
2011: clearsw++;
2012: continue;
2013: case SCNCLR:
2014: clearsw = 0;
2015: continue;
2016: case SCHEAD:
2017: headersw++;
2018: continue;
2019: case SCNHEAD:
2020: headersw = 0;
2021: continue;
2022: case SCFORM:
2023: if (!(form = *args++) || *form == '-') {
2024: advise (NULLCP, "missing argument to %s", args[-2]);
2025: return;
2026: }
2027: format = NULL;
2028: continue;
2029: case SCFMT:
2030: if (!(format = *args++) || *format == '-') {
2031: advise (NULLCP, "missing argument to %s", args[-2]);
2032: return;
2033: }
2034: form = NULL;
2035: continue;
2036: case SCWID:
2037: if (!(cp = *args++) || *cp == '-') {
2038: advise (NULLCP, "missing argument to %s", args[-2]);
2039: return;
2040: }
2041: width = atoi (cp);
2042: continue;
2043: }
2044: if (*cp == '+' || *cp == '@') {
2045: advise (NULLCP, "sorry, no folders allowed!");
2046: return;
2047: }
2048: else
2049: msgs[msgp++] = cp;
2050: }
2051:
2052: if (!msgp)
2053: msgs[msgp++] = "all";
2054: for (msgnum = 0; msgnum < msgp; msgnum++)
2055: if (!m_convert (mp, msgs[msgnum]))
2056: return;
2057: m_setseq (mp);
2058:
2059: nfs = new_fs (form, format, FORMAT);
2060: if (scanl) { /* force scansbr to (re)compile format */
2061: (void) free (scanl);
2062: scanl = NULL;
2063: }
2064:
2065: if (s_optim == 0) {
2066: s_optim = optim = 1;
2067: s_form = form ? getcpy (form) : NULL;
2068: s_format = format ? getcpy (format) : NULL;
2069: }
2070: else
2071: optim = equiv (s_form, form) && equiv (s_format, format);
2072:
2073: interrupted = 0;
2074: for (msgnum = mp -> lowsel;
2075: msgnum <= mp -> hghsel && !interrupted;
2076: msgnum++)
2077: if (mp -> msgstats[msgnum] & SELECTED) {
2078: if (optim && Msgs[msgnum].m_scanl)
2079: printf ("%s", Msgs[msgnum].m_scanl);
2080: else {
2081: zp = msh_ready (msgnum, 0);
2082: switch (state = scan (zp, msgnum, 0, nfs, width,
2083: msgnum == mp -> curmsg, headersw,
2084: fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2085: 1)) {
2086: case SCNMSG:
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 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 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 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 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.