Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / uip / RCS / mshcmds.c,v
1 head    1.32;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.32
9 date    95.12.11.18.19.26;      author jromine; state Exp;
10 branches;
11 next    1.31;
12
13 1.31
14 date    95.12.07.18.20.22;      author jromine; state Exp;
15 branches;
16 next    1.30;
17
18 1.30
19 date    95.12.06.23.44.31;      author jromine; state Exp;
20 branches;
21 next    1.29;
22
23 1.29
24 date    94.04.21.18.20.50;      author jromine; state Exp;
25 branches;
26 next    1.28;
27
28 1.28
29 date    93.12.01.03.50.31;      author jromine; state Exp;
30 branches;
31 next    1.27;
32
33 1.27
34 date    93.10.26.20.09.54;      author jromine; state Exp;
35 branches;
36 next    1.26;
37
38 1.26
39 date    93.08.27.23.23.26;      author jromine; state Exp;
40 branches;
41 next    1.25;
42
43 1.25
44 date    92.12.15.00.20.22;      author jromine; state Exp;
45 branches;
46 next    1.24;
47
48 1.24
49 date    92.11.24.18.26.05;      author jromine; state Exp;
50 branches;
51 next    1.23;
52
53 1.23
54 date    92.11.04.00.53.32;      author jromine; state Exp;
55 branches;
56 next    1.22;
57
58 1.22
59 date    92.10.29.03.49.31;      author jromine; state Exp;
60 branches;
61 next    1.21;
62
63 1.21
64 date    92.10.26.22.21.33;      author jromine; state Exp;
65 branches;
66 next    1.20;
67
68 1.20
69 date    92.10.17.00.24.25;      author jromine; state Exp;
70 branches;
71 next    1.19;
72
73 1.19
74 date    92.10.17.00.19.58;      author jromine; state Exp;
75 branches;
76 next    1.18;
77
78 1.18
79 date    92.10.16.22.34.17;      author jromine; state Exp;
80 branches;
81 next    1.17;
82
83 1.17
84 date    92.10.16.21.50.20;      author jromine; state Exp;
85 branches;
86 next    1.16;
87
88 1.16
89 date    92.10.16.21.47.40;      author jromine; state Exp;
90 branches;
91 next    1.15;
92
93 1.15
94 date    92.10.16.21.37.18;      author jromine; state Exp;
95 branches;
96 next    1.14;
97
98 1.14
99 date    92.10.16.16.51.55;      author jromine; state Exp;
100 branches;
101 next    1.13;
102
103 1.13
104 date    92.05.19.21.03.35;      author jromine; state Exp;
105 branches;
106 next    1.12;
107
108 1.12
109 date    92.03.03.17.09.57;      author jromine; state Exp;
110 branches;
111 next    1.11;
112
113 1.11
114 date    92.02.08.00.10.26;      author jromine; state Exp;
115 branches;
116 next    1.10;
117
118 1.10
119 date    92.02.05.07.26.30;      author jromine; state Exp;
120 branches;
121 next    1.9;
122
123 1.9
124 date    92.01.31.22.19.11;      author jromine; state Exp;
125 branches;
126 next    1.8;
127
128 1.8
129 date    92.01.31.16.33.46;      author jromine; state Exp;
130 branches;
131 next    1.7;
132
133 1.7
134 date    92.01.23.22.58.03;      author jromine; state Exp;
135 branches;
136 next    1.6;
137
138 1.6
139 date    91.01.14.16.48.39;      author mh;      state Exp;
140 branches;
141 next    1.5;
142
143 1.5
144 date    90.04.05.15.01.41;      author sources; state Exp;
145 branches;
146 next    1.4;
147
148 1.4
149 date    90.03.23.14.14.55;      author sources; state Exp;
150 branches;
151 next    1.3;
152
153 1.3
154 date    90.03.22.16.59.48;      author sources; state Exp;
155 branches;
156 next    1.2;
157
158 1.2
159 date    90.02.06.13.23.35;      author sources; state Exp;
160 branches;
161 next    1.1;
162
163 1.1
164 date    90.02.06.13.23.00;      author sources; state Exp;
165 branches;
166 next    ;
167
168
169 desc
170 @@
171
172
173 1.32
174 log
175 @fix merge error (mtr fixes)
176 @
177 text
178 @/* mshcmds.c - command handlers in msh */
179 #ifndef lint
180 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.31 1995/12/07 18:20:22 jromine Exp jromine $";
181 #endif  /* lint */
182
183 #include "../h/mh.h"
184 #include "../h/dropsbr.h"
185 #include "../h/formatsbr.h"
186 #include "../h/scansbr.h"
187 #include "../zotnet/tws.h"
188 #ifdef  _AIX            /* AIX 1.2.1 <stdio.h> declares getws() */
189 #define getws _getws
190 #endif
191 #include <stdio.h>
192 #ifdef  _AIX
193 #undef getws
194 #endif
195 #include "../zotnet/mts.h"
196 #include <ctype.h>
197 #include <errno.h>
198 #include <setjmp.h>
199 #include <signal.h>
200 #include <sys/types.h>
201 #include <sys/stat.h>
202 #include "../h/mshsbr.h"
203 #ifdef  MIME
204 #include "../h/mhn.h"
205 #endif  /* MIME */
206
207 /* \f */
208
209 extern int errno;
210
211                                 /* BURST */
212 static char delim3[] = "-------";/* from burst.c */
213
214
215                                 /* SHOW */
216 static int  mhlnum;
217 static FILE *mhlfp;
218
219 void clear_screen ();
220 static int     eom_action ();
221 static FP       mhl_action ();
222 #ifdef  MIME
223 static int     nontext();
224 #endif
225
226
227 static burst(), forw(), rmm(), show(), ask(), copy_message(), copy_digest();
228 static int      process();
229                                 /* SORTM */
230 static int      msgsort (), subsort();
231 static int      getws ();
232 static char    *sosmash ();
233
234 #if     defined(NNTP) && defined(MPOP)
235 #undef  MPOP
236 #endif
237 #ifdef  MPOP
238 #ifdef  BPOP
239 extern  int     pmsh;
240 extern  char    response[];
241 #endif
242 #endif /* MPOP */
243
244 /* \f */
245
246 forkcmd (args, pgm)
247 char  **args,
248        *pgm;
249 {
250     int     child_id;
251     char   *vec[MAXARGS];
252
253     vec[0] = r1bindex (pgm, '/');
254     (void) copyip (args, vec + 1);
255
256     if (fmsh) {
257         (void) m_delete (pfolder);
258         m_replace (pfolder, fmsh);
259         m_sync (mp);
260         m_update ();
261     }
262     (void) fflush (stdout);
263     switch (child_id = fork ()) {
264         case NOTOK: 
265             advise ("fork", "unable to");
266             return;
267
268         case OK: 
269             closefds (3);
270             (void) signal (SIGINT, istat);
271             (void) signal (SIGQUIT, qstat);
272
273             execvp (pgm, vec);
274             fprintf (stderr, "unable to exec ");
275             perror (cmd_name);
276             _exit (1);
277
278         default: 
279             (void) pidXwait (child_id, NULLCP);
280             break;
281     }
282     if (fmsh) {                 /* assume the worst case */
283         mp -> msgflags |= MODIFIED;
284         modified++;
285     }
286 }
287
288 /* \f */
289
290 static struct swit distswit[] = {
291 #define DIANSW  0
292     "annotate", 0,
293 #define DINANSW 1
294     "noannotate", 0,
295 #define DIDFSW  2
296     "draftfolder +folder", 0,
297 #define DIDMSW  3
298     "draftmessage msg", 0,
299 #define DINDFSW 4
300     "nodraftfolder", 0,
301 #define DIEDTSW 5
302     "editor editor", 0,
303 #define DINEDSW 6
304     "noedit", 0,
305 #define DIFRMSW 7
306     "form formfile", 0,
307 #define DIINSW  8
308     "inplace", 0,
309 #define DININSW 9
310     "noinplace", 0,
311 #define DIWHTSW 10
312     "whatnowproc program", 0,
313 #define DINWTSW 11
314     "nowhatnowproc", 0,
315 #define DIHELP  12
316     "help", 4,
317
318     NULL, 0
319 };
320
321 /* \f */
322
323 distcmd (args)
324 char  **args;
325 {
326     int     vecp = 1;
327     char   *cp,
328            *msg = NULL,
329             buf[BUFSIZ],
330            *vec[MAXARGS];
331
332     if (fmsh) {
333         forkcmd (args, cmd_name);
334         return;
335     }
336
337     while (cp = *args++) {
338         if (*cp == '-')
339             switch (smatch (++cp, distswit)) {
340                 case AMBIGSW: 
341                     ambigsw (cp, distswit);
342                     return;
343                 case UNKWNSW: 
344                     fprintf (stderr, "-%s unknown\n", cp);
345                     return;
346                 case DIHELP: 
347                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
348                     help (buf, distswit);
349                     return;
350
351                 case DIANSW:    /* not implemented */
352                 case DINANSW: 
353                 case DIINSW: 
354                 case DININSW: 
355                     continue;
356
357                 case DINDFSW:
358                 case DINEDSW:
359                 case DINWTSW:
360                     vec[vecp++] = --cp;
361                     continue;
362
363                 case DIEDTSW: 
364                 case DIFRMSW: 
365                 case DIDFSW:
366                 case DIDMSW:
367                 case DIWHTSW:
368                     vec[vecp++] = --cp;
369                     if (!(cp = *args++) || *cp == '-') {
370                         advise (NULLCP, "missing argument to %s", args[-2]);
371                         return;
372                     }
373                     vec[vecp++] = cp;
374                     continue;
375             }
376         if (*cp == '+' || *cp == '@@') {
377             advise (NULLCP, "sorry, no folders allowed!");
378             return;
379         }
380         else
381             if (msg) {
382                 advise (NULLCP, "only one message at a time!");
383                 return;
384             }
385             else
386                 msg = cp;
387     }
388
389     vec[0] = cmd_name;
390     vec[vecp++] = "-file";
391     vec[vecp] = NULL;
392     if (!msg)
393         msg = "cur";
394     if (!m_convert (mp, msg))
395         return;
396     m_setseq (mp);
397
398     if (mp -> numsel > 1) {
399         advise (NULLCP, "only one message at a time!");
400         return;
401     }
402     (void) process (mp -> hghsel, cmd_name, vecp, vec);
403     m_setcur (mp, mp -> hghsel);
404 }
405
406 /* \f */
407
408 static struct swit explswit[] = {
409 #define EXINSW  0
410     "inplace", 0,
411 #define EXNINSW 1
412     "noinplace", 0,
413 #define EXQISW  2
414     "quiet", 0,
415 #define EXNQISW 3
416     "noquiet", 0,
417 #define EXVBSW  4
418     "verbose", 0,
419 #define EXNVBSW 5
420     "noverbose", 0,
421 #define EXHELP  6
422     "help", 4,
423
424     NULL, 0
425 };
426
427 /* \f */
428
429 explcmd (args)
430 char  **args;
431 {
432     int     inplace = 0,
433             quietsw = 0,
434             verbosw = 0,
435             msgp = 0,
436             hi,
437             msgnum;
438     char   *cp,
439             buf[BUFSIZ],
440            *msgs[MAXARGS];
441     struct Msg *smsgs;
442
443     if (fmsh) {
444         forkcmd (args, cmd_name);
445         return;
446     }
447
448     while (cp = *args++) {
449         if (*cp == '-')
450             switch (smatch (++cp, explswit)) {
451                 case AMBIGSW: 
452                     ambigsw (cp, explswit);
453                     return;
454                 case UNKWNSW: 
455                     fprintf (stderr, "-%s unknown\n", cp);
456                     return;
457                 case EXHELP: 
458                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
459                     help (buf, explswit);
460                     return;
461
462                 case EXINSW: 
463                     inplace++;
464                     continue;
465                 case EXNINSW: 
466                     inplace = 0;
467                     continue;
468                 case EXQISW: 
469                     quietsw++;
470                     continue;
471                 case EXNQISW: 
472                     quietsw = 0;
473                     continue;
474                 case EXVBSW: 
475                     verbosw++;
476                     continue;
477                 case EXNVBSW: 
478                     verbosw = 0;
479                     continue;
480             }
481         if (*cp == '+' || *cp == '@@') {
482             advise (NULLCP, "sorry, no folders allowed!");
483             return;
484         }
485         else
486             msgs[msgp++] = cp;
487     }
488
489     if (!msgp)
490         msgs[msgp++] = "cur";
491     for (msgnum = 0; msgnum < msgp; msgnum++)
492         if (!m_convert (mp, msgs[msgnum]))
493             return;
494     m_setseq (mp);
495
496     smsgs = (struct Msg *)
497                 calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs);
498     if (smsgs == NULL)
499         adios (NULLCP, "unable to allocate folder storage");
500
501     hi = mp -> hghmsg + 1;
502     interrupted = 0;
503     for (msgnum = mp -> lowsel;
504             msgnum <= mp -> hghsel && !interrupted;
505             msgnum++)
506         if (mp -> msgstats[msgnum] & SELECTED)
507             if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
508                 break;
509
510     free ((char *) smsgs);
511
512     if (inplace)
513         m_setcur (mp, mp -> lowsel);
514     else
515         if (hi <= mp -> hghmsg)
516             m_setcur (mp, hi);
517
518     mp -> msgflags |= MODIFIED;
519     modified++;
520 }
521
522 /* \f */
523
524 static  burst (smsgs, msgnum, inplace, quietsw, verbosw)
525 struct Msg *smsgs;
526 int     msgnum,
527         inplace,
528         quietsw,
529         verbosw;
530 {
531     int     i,
532             j,
533             ld3,
534             wasdlm,
535             msgp;
536     long    pos;
537     char    c,
538             cc,
539             buffer[BUFSIZ];
540     register FILE *zp;
541
542     ld3 = strlen (delim3);
543
544     if (Msgs[msgnum].m_scanl) {
545         free (Msgs[msgnum].m_scanl);
546         Msgs[msgnum].m_scanl = NULL;
547     }
548
549     pos = ftell (zp = msh_ready (msgnum, 1));
550     for (msgp = 0; msgp <= MAXFOLDER;) {
551         while (fgets (buffer, sizeof buffer, zp) != NULL
552                 && buffer[0] == '\n'
553                 && pos < Msgs[msgnum].m_stop)
554             pos += (long) strlen (buffer);
555         if (feof (zp) || pos >= Msgs[msgnum].m_stop)
556             break;
557         (void) fseek (zp, pos, 0);
558         smsgs[msgp].m_start = pos;
559
560         for (c = 0;
561                 pos < Msgs[msgnum].m_stop
562                 && fgets (buffer, sizeof buffer, zp) != NULL;
563                 c = buffer[0])
564             if (strncmp (buffer, delim3, ld3) == 0
565                     && (msgp == 1 || c == '\n')
566                     && peekc (zp) == '\n')
567                 break;
568             else
569                 pos += (long) strlen (buffer);
570
571         wasdlm = strncmp (buffer, delim3, ld3) == 0;
572         if (smsgs[msgp].m_start != pos)
573             smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
574         if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
575             if (wasdlm)
576                 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
577             break;
578         }
579         pos += (long) strlen (buffer);
580     }
581
582     switch (msgp--) {           /* toss "End of XXX Digest" */
583         case 0: 
584             adios (NULLCP, "burst() botch -- you lose big");
585
586         case 1: 
587             if (!quietsw)
588                 printf ("message %d not in digest format\n", msgnum);
589             return OK;
590
591         default: 
592             if (verbosw)
593                 printf ("%d message%s exploded from digest %d\n",
594                         msgp, msgp != 1 ? "s" : "", msgnum);
595             break;
596     }
597
598     if ((i = msgp + mp -> hghmsg) > MAXFOLDER) {
599         advise (NULLCP, "more than %d messages", MAXFOLDER);
600         return NOTOK;
601     }
602     if ((mp = m_remsg (mp, 0, i)) == NULL)
603         adios (NULLCP, "unable to allocate folder storage");
604
605     j = mp -> hghmsg;
606     mp -> hghmsg += msgp;
607     mp -> nummsg += msgp;
608     if (mp -> hghsel > msgnum)
609         mp -> hghsel += msgp;
610
611     if (inplace)
612         for (i = mp -> hghmsg; j > msgnum; i--, j--) {
613             if (verbosw)
614                 printf ("message %d becomes message %d\n", j, i);
615
616             Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
617             Msgs[i].m_top = Msgs[j].m_top;
618             Msgs[i].m_start = Msgs[j].m_start;
619             Msgs[i].m_stop = Msgs[j].m_stop;
620             Msgs[i].m_scanl = NULL;
621             if (Msgs[j].m_scanl) {
622                 free (Msgs[j].m_scanl);
623                 Msgs[j].m_scanl = NULL;
624             }
625             mp -> msgstats[i] = mp -> msgstats[j];
626         }
627
628     if (Msgs[msgnum].m_bboard_id == 0)
629         (void) readid (msgnum);
630
631     mp -> msgstats[msgnum] &= ~SELECTED;
632     i = inplace ? msgnum + msgp : mp -> hghmsg;
633     for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
634         if (verbosw && i != msgnum)
635             printf ("message %d of digest %d becomes message %d\n",
636                     j, msgnum, i);
637
638         Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
639         Msgs[i].m_top = Msgs[j].m_top;
640         Msgs[i].m_start = smsgs[j].m_start;
641         Msgs[i].m_stop = smsgs[j].m_stop;
642         Msgs[i].m_scanl = NULL;
643         mp -> msgstats[i] = mp -> msgstats[msgnum];
644     }
645
646     return OK;
647 }
648
649 /* \f */
650
651 static struct swit fileswit[] = {
652 #define FIDRFT  0
653     "draft", 0,
654 #define FILINK  1
655     "link", 0,
656 #define FINLINK 2
657     "nolink", 0,
658 #define FIPRES  3
659     "preserve", 0,
660 #define FINPRES 4
661     "nopreserve", 0,
662 #define FISRC   5
663     "src +folder", 0,
664 #define FIFILE  6
665     "file file", 0,
666 #define FIPROC  7
667     "rmmproc program", 0,
668 #define FINPRC  8
669     "normmproc", 0,
670 #define FIHELP  9
671     "help", 4,
672
673     NULL, 0
674 };
675
676 /* \f */
677
678 filecmd (args)
679 char  **args;
680 {
681     int     linksw = 0,
682             msgp = 0,
683             vecp = 1,
684             i,
685             msgnum;
686     char   *cp,
687             buf[BUFSIZ],
688            *msgs[MAXARGS],
689            *vec[MAXARGS];
690
691     if (fmsh) {
692         forkcmd (args, cmd_name);
693         return;
694     }
695
696     while (cp = *args++) {
697         if (*cp == '-')
698             switch (i = smatch (++cp, fileswit)) {
699                 case AMBIGSW: 
700                     ambigsw (cp, fileswit);
701                     return;
702                 case UNKWNSW: 
703                     fprintf (stderr, "-%s unknown\n", cp);
704                     return;
705                 case FIHELP: 
706                     (void) sprintf (buf, "%s +folder... [msgs] [switches]",
707                             cmd_name);
708                     help (buf, fileswit);
709                     return;
710
711                 case FILINK:
712                     linksw++;
713                     continue;
714                 case FINLINK: 
715                     linksw = 0;
716                     continue;
717
718                 case FIPRES: 
719                 case FINPRES: 
720                     continue;
721
722                 case FISRC: 
723                 case FIDRFT:
724                 case FIFILE: 
725                 case FIPROC:
726                 case FINPRC:
727                     advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw);
728                     return;
729             }
730         if (*cp == '+' || *cp == '@@')
731             vec[vecp++] = cp;
732         else
733             msgs[msgp++] = cp;
734     }
735
736     vec[0] = cmd_name;
737     vec[vecp++] = "-file";
738     vec[vecp] = NULL;
739     if (!msgp)
740         msgs[msgp++] = "cur";
741     for (msgnum = 0; msgnum < msgp; msgnum++)
742         if (!m_convert (mp, msgs[msgnum]))
743             return;
744     m_setseq (mp);
745
746     interrupted = 0;
747     for (msgnum = mp -> lowsel;
748             msgnum <= mp -> hghsel && !interrupted;
749             msgnum++)
750         if (mp -> msgstats[msgnum] & SELECTED)
751             if (process (msgnum, fileproc, vecp, vec)) {
752                 mp -> msgstats[msgnum] &= ~SELECTED;
753                 mp -> numsel--;
754             }
755
756     if (mp -> numsel != mp -> nummsg || linksw)
757         m_setcur (mp, mp -> hghsel);
758     if (!linksw)
759         rmm ();
760 }
761
762 /* \f */
763
764 int     filehak (args)
765 char  **args;
766 {
767     int     result,
768             vecp = 0;
769     char   *cp,
770            *cwd,
771            *vec[MAXARGS];
772
773     while (cp = *args++) {
774         if (*cp == '-')
775             switch (smatch (++cp, fileswit)) {
776                 case AMBIGSW: 
777                 case UNKWNSW: 
778                 case FIHELP: 
779                     return NOTOK;
780
781                 case FILINK:
782                 case FINLINK: 
783                 case FIPRES: 
784                 case FINPRES: 
785                     continue;
786
787                 case FISRC: 
788                 case FIDRFT:
789                 case FIFILE: 
790                     return NOTOK;
791             }
792         if (*cp == '+' || *cp == '@@')
793             vec[vecp++] = cp;
794     }
795     vec[vecp] = NULL;
796
797     result = NOTOK;
798     cwd = NULL;
799     for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
800         if (cwd == NULL)
801             cwd = getcpy (pwd ());
802         (void) chdir (m_maildir (""));
803         cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
804         if (access (m_maildir (cp), 0) == NOTOK)
805             result = OK;
806         free (cp);
807     }
808     if (cwd)
809         (void) chdir (cwd);
810
811     return result;
812 }
813
814 /* \f */
815
816 static struct swit foldswit[] = {
817 #define FLALSW  0
818     "all", 0,
819 #define FLFASW  1
820     "fast", 0,
821 #define FLNFASW 2
822     "nofast", 0,
823 #define FLHDSW  3
824     "header", 0,
825 #define FLNHDSW 4
826     "noheader", 0,
827 #define FLPKSW  5
828     "pack", 0,
829 #define FLNPKSW 6
830     "nopack", 0,
831 #define FLRCSW  7
832     "recurse", 0,
833 #define FLNRCSW 8
834     "norecurse", 0,
835 #define FLTLSW  9
836     "total", 0,
837 #define FLNTLSW 10
838     "nototal", 0,
839 #define FLPRSW  11
840     "print", 0,
841 #define FLPUSW  12
842     "push", 0,
843 #define FLPOSW  13
844     "pop", 0,
845 #define FLLISW  14
846     "list", 0,
847 #define FLHELP  15
848     "help", 4,
849
850     NULL, 0
851 };
852
853 /* \f */
854
855 foldcmd (args)
856 char  **args;
857 {
858     int     fastsw = 0,
859             headersw = 0,
860             packsw = 0,
861             hole,
862             msgnum;
863     char   *cp,
864            *folder = NULL,
865            *msg = NULL,
866             buf[BUFSIZ],
867           **vec = args;
868
869     if (args == NULL)
870         goto fast;
871
872     while (cp = *args++) {
873         if (*cp == '-')
874             switch (smatch (++cp, foldswit)) {
875                 case AMBIGSW: 
876                     ambigsw (cp, foldswit);
877                     return;
878                 case UNKWNSW: 
879                     fprintf (stderr, "-%s unknown\n", cp);
880                     return;
881                 case FLHELP: 
882                     (void) sprintf (buf, "%s [+folder] [msg] [switches]",
883                             cmd_name);
884                     help (buf, foldswit);
885                     return;
886
887                 case FLALSW:    /* not implemented */
888                 case FLRCSW: 
889                 case FLNRCSW: 
890                 case FLTLSW: 
891                 case FLNTLSW: 
892                 case FLPRSW:
893                 case FLPUSW:
894                 case FLPOSW:
895                 case FLLISW:
896                     continue;
897
898                 case FLFASW: 
899                     fastsw++;
900                     continue;
901                 case FLNFASW: 
902                     fastsw = 0;
903                     continue;
904                 case FLHDSW: 
905                     headersw++;
906                     continue;
907                 case FLNHDSW: 
908                     headersw = 0;
909                     continue;
910                 case FLPKSW: 
911                     packsw++;
912                     continue;
913                 case FLNPKSW: 
914                     packsw = 0;
915                     continue;
916             }
917         if (*cp == '+' || *cp == '@@')
918             if (folder) {
919                 advise (NULLCP, "only one folder at a time!\n");
920                 return;
921             }
922             else
923                 folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
924                             : cp + 1;
925         else
926             if (msg) {
927                 advise (NULLCP, "only one message at a time!\n");
928                 return;
929             }
930             else
931                 msg = cp;
932     }
933
934     if (folder) {
935         if (*folder == 0) {
936             advise (NULLCP, "null folder names are not permitted");
937             return;
938         }
939         if (fmsh) {
940             if (access (m_maildir (folder), 04) == NOTOK) {
941                 advise (folder, "unable to read");
942                 return;
943             }
944         }
945         else {
946             (void) strcpy (buf, folder);
947             if (expand (buf) == NOTOK)
948                 return;
949             folder = buf;
950             if (access (folder, 04) == NOTOK) {
951                 advise (folder, "unable to read");
952                 return;
953             }
954         }
955         m_reset ();
956
957         if (fmsh)
958             fsetup (folder);
959         else
960             setup (folder);
961         readids (0);
962         display_info (0);
963     }
964
965     if (msg) {
966         if (!m_convert (mp, msg))
967             return;
968         m_setseq (mp);
969
970         if (mp -> numsel > 1) {
971             advise (NULLCP, "only one message at a time!");
972             return;
973         }
974         m_setcur (mp, mp -> hghsel);
975     }
976
977     if (packsw) {
978         if (fmsh) {
979             forkcmd (vec, cmd_name);
980             return;
981         }
982
983         if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL)
984             adios (NULLCP, "unable to allocate folder storage");
985         for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++)
986             if (mp -> msgstats[msgnum] & EXISTS) {
987                 if (msgnum != hole) {
988                     Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
989                     Msgs[hole].m_top = Msgs[msgnum].m_top;
990                     Msgs[hole].m_start = Msgs[msgnum].m_start;
991                     Msgs[hole].m_stop = Msgs[msgnum].m_stop;
992                     Msgs[hole].m_scanl = NULL;
993                     if (Msgs[msgnum].m_scanl) {
994                         free (Msgs[msgnum].m_scanl);
995                         Msgs[msgnum].m_scanl = NULL;
996                     }
997                     mp -> msgstats[hole] = mp -> msgstats[msgnum];
998                     if (mp -> curmsg == msgnum)
999                         m_setcur (mp, hole);
1000                 }
1001                 hole++;
1002             }
1003         if (mp -> nummsg > 0) {
1004             mp -> lowmsg = 1;
1005             mp -> hghmsg = hole - 1;
1006         }
1007         mp -> msgflags |= MODIFIED;
1008         modified++;
1009     }
1010
1011 fast: ;
1012     if (fastsw)
1013         printf ("%s\n", fmsh ? fmsh : mp -> foldpath);
1014     else {
1015         if (headersw)
1016             printf ("\t\tFolder  %*s# of messages (%*srange%*s); cur%*smsg\n",
1017                 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
1018                 DMAXFOLDER - 2, "");
1019         printf (args ? "%22s  " : "%s ", fmsh ? fmsh : mp -> foldpath);
1020         if (mp -> hghmsg == 0)
1021             printf ("has   no messages%*s",
1022                     mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
1023         else {
1024             printf ("has %*d message%s (%*d-%*d)",
1025                     DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "",
1026                     DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg);
1027             if (mp -> curmsg >= mp -> lowmsg
1028                     && mp -> curmsg <= mp -> hghmsg)
1029                 printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg);
1030         }
1031         printf (".\n");
1032     }
1033 }
1034
1035 /* \f */
1036
1037 #ifndef MIME
1038 #define MIMEminc(a)     (a)
1039 #else   /* MIME */
1040 #define MIMEminc(a)     0
1041 #endif  /* MIME */
1042
1043 static struct swit forwswit[] = {
1044 #define FOANSW  0
1045     "annotate", 0,
1046 #define FONANSW 1
1047     "noannotate", 0,
1048 #define FODFSW  2
1049     "draftfolder +folder", 0,
1050 #define FODMSW  3
1051     "draftmessage msg", 0,
1052 #define FONDFSW 4
1053     "nodraftfolder", 0,
1054 #define FOEDTSW 5
1055     "editor editor", 0,
1056 #define FONEDSW 6
1057     "noedit", 0,
1058 #define FOFTRSW 7
1059     "filter filterfile", 0,
1060 #define FOFRMSW 8
1061     "form formfile", 0,
1062 #define FOFTSW  9
1063     "format", 5,
1064 #define FONFTSW 10
1065     "noformat", 7,
1066 #define FOINSW  11
1067     "inplace", 0,
1068 #define FONINSW 12
1069     "noinplace", 0,
1070 #define FOMISW  13
1071     "mime", MIMEminc(-4),
1072 #define FONMISW 14
1073     "nomime", MIMEminc(-6),
1074 #define FOWHTSW 15
1075     "whatnowproc program", 0,
1076 #define FONWTSW 16
1077     "nowhatnow", 0,
1078 #define FOHELP  17
1079     "help", 4,
1080
1081     NULL, 0
1082 };
1083
1084 /* \f */
1085
1086 forwcmd (args)
1087 char  **args;
1088 {
1089     int     msgp = 0,
1090             vecp = 1,
1091             mime = 0,
1092             msgnum;
1093     char   *cp,
1094            *filter = NULL,
1095             buf[BUFSIZ],
1096            *msgs[MAXARGS],
1097            *vec[MAXARGS];
1098
1099     if (fmsh) {
1100         forkcmd (args, cmd_name);
1101         return;
1102     }
1103
1104     while (cp = *args++) {
1105         if (*cp == '-')
1106             switch (smatch (++cp, forwswit)) {
1107                 case AMBIGSW: 
1108                     ambigsw (cp, forwswit);
1109                     return;
1110                 case UNKWNSW: 
1111                     fprintf (stderr, "-%s unknown\n", cp);
1112                     return;
1113                 case FOHELP: 
1114                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1115                     help (buf, forwswit);
1116                     return;
1117
1118                 case FOANSW:    /* not implemented */
1119                 case FONANSW: 
1120                 case FOINSW: 
1121                 case FONINSW: 
1122                     continue;
1123
1124                 case FOMISW:
1125 #ifdef  MIME
1126                     mime = 1;
1127                     filter = NULL;
1128 #endif  /* MIME */
1129                     continue;
1130                 case FONMISW:
1131                     mime = 0;
1132                     continue;
1133
1134                 case FONDFSW:
1135                 case FONEDSW:
1136                 case FONWTSW:
1137                     vec[vecp++] = --cp;
1138                     continue;
1139
1140                 case FOEDTSW: 
1141                 case FOFRMSW: 
1142                 case FODFSW:
1143                 case FODMSW:
1144                 case FOWHTSW:
1145                     vec[vecp++] = --cp;
1146                     if (!(cp = *args++) || *cp == '-') {
1147                         advise (NULLCP, "missing argument to %s", args[-2]);
1148                         return;
1149                     }
1150                     vec[vecp++] = cp;
1151                     continue;
1152                 case FOFTRSW: 
1153                     if (!(filter = *args++) || *filter == '-') {
1154                         advise (NULLCP, "missing argument to %s", args[-2]);
1155                         return;
1156                     }
1157                     mime = 0;
1158                     continue;
1159                 case FOFTSW: 
1160                     if (access (filter = myfilter, 04) == NOTOK) {
1161                         advise (filter, "unable to read default filter file");
1162                         return;
1163                     }
1164                     continue;
1165                 case FONFTSW: 
1166                     filter = NULL;
1167                     continue;
1168             }
1169         if (*cp == '+' || *cp == '@@') {
1170             advise (NULLCP, "sorry, no folders allowed!");
1171             return;
1172         }
1173         else
1174             msgs[msgp++] = cp;
1175     }
1176
1177                                         /* foil search of .mh_profile */
1178     (void) sprintf (buf, "%sXXXXXX", invo_name);
1179     vec[0] = (char *)mktemp (buf);
1180     vec[vecp++] = "-file";
1181     vec[vecp] = NULL;
1182     if (!msgp)
1183         msgs[msgp++] = "cur";
1184     for (msgnum = 0; msgnum < msgp; msgnum++)
1185         if (!m_convert (mp, msgs[msgnum]))
1186             return;
1187     m_setseq (mp);
1188
1189     if (filter) {
1190         (void) strcpy (buf, filter);
1191         if (expand (buf) == NOTOK)
1192             return;
1193         if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) {
1194             advise (filter, "unable to read");
1195             free (filter);
1196             return;
1197         }
1198     }
1199     forw (cmd_name, filter, vecp, vec, mime);
1200     m_setcur (mp, mp -> hghsel);
1201     if (filter)
1202         free (filter);
1203 }
1204
1205 /* \f */
1206
1207 static  forw (proc, filter, vecp, vec, mime)
1208 int     vecp,
1209         mime;
1210 char   *proc,
1211        *filter,
1212       **vec;
1213 {
1214     int     i,
1215             child_id,
1216             msgnum,
1217             msgcnt;
1218     char    tmpfil[80],
1219            *args[MAXARGS];
1220     FILE   *out;
1221 #ifdef  MIME
1222     int     nedit = 0;
1223     char   *ed = NULL;
1224 #endif  /* MIME */
1225
1226     (void) strcpy (tmpfil, m_tmpfil (invo_name));
1227     interrupted = 0;
1228     if (filter)
1229         switch (child_id = fork ()) {
1230             case NOTOK: 
1231                 advise ("fork", "unable to");
1232                 return;
1233
1234             case OK:            /* "trust me" */
1235                 if (freopen (tmpfil, "w", stdout) == NULL) {
1236                     fprintf (stderr, "unable to create ");
1237                     perror (tmpfil);
1238                     _exit (1);
1239                 }
1240                 args[0] = r1bindex (mhlproc, '/');
1241                 i = 1;
1242                 args[i++] = "-forwall";
1243                 args[i++] = "-form";
1244                 args[i++] = filter;
1245                 for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1246                     if (mp -> msgstats[msgnum] & SELECTED)
1247                         args[i++] = getcpy (m_name (msgnum));
1248                 args[i] = NULL;
1249                 (void) mhlsbr (i, args, mhl_action);
1250                 m_eomsbr ((int (*) ()) 0);
1251                 (void) fclose (stdout);
1252                 _exit (0);
1253
1254             default: 
1255                 if (pidXwait (child_id, NULLCP))
1256                     interrupted++;
1257                 break;
1258         }
1259 #ifdef  MIME
1260     else if (mime) {
1261         int     isdf = 0,
1262                 len,
1263                 nwhat = 0;
1264 #define INITIAL_PREFIX  "----- =_aaaaaaaaaa"
1265         char   *cp,
1266                *form = NULL,
1267                 buffer[BUFSIZ],
1268                 prefix[sizeof INITIAL_PREFIX];
1269         FILE   *zp;
1270
1271         proc = whatnowproc;
1272         for (vecp = 1; cp = vec[vecp++]; )
1273             if (*cp == '-')
1274                 switch (smatch (++cp, forwswit)) {
1275                     case FOEDTSW:
1276                         ed = vec[vecp++];
1277                         nedit = 0;
1278                         continue;
1279                     case FONEDSW:
1280                         nedit++;
1281                         continue;
1282
1283                     case FOFRMSW:
1284                         form = vec[vecp++];
1285                         continue;
1286                         
1287                     case FOWHTSW:
1288                         proc = vec[vecp++];
1289                         nwhat = 0;
1290                         continue;
1291                     case FONWTSW:
1292                         nwhat++;
1293                         continue;
1294
1295 /* ignore -draftfolder / -draftmessage / -nodraftfolder */
1296                     case FODFSW:
1297                     case FODMSW:
1298                         vecp++;
1299                     case FONDFSW:
1300                         continue;
1301                 }
1302         (void) strcpy (tmpfil, m_draft (NULLCP, NULLCP, NOUSE, &isdf));
1303         if (!ed && !(ed = m_find ("editor")))
1304             ed = sysed;
1305
1306         (void) strcpy (prefix, INITIAL_PREFIX);
1307         cp = index (prefix, 'a');
1308         len = strlen (prefix);
1309
1310         for (;;) {
1311             int    hit = 0;
1312             long    pos;
1313             
1314             for (msgnum = mp -> lowsel;
1315                      msgnum <= mp -> hghsel && !interrupted && !hit;
1316                      msgnum++)
1317                 if (mp -> msgstats[msgnum] & SELECTED) {
1318                     zp = msh_ready (msgnum, 1);
1319                     if (!fmsh)
1320                         pos = ftell (zp);
1321                     while (fgets (buffer, sizeof buffer, zp) != NULL
1322                                && !fmsh
1323                                && pos < Msgs[msgnum].m_stop) {
1324                         register char   *pp;
1325
1326                         if (buffer[0] != '-' || buffer[1] != '-')
1327                             continue;
1328
1329                         for (pp = buffer + strlen (buffer) - 1;
1330                                  pp >= buffer;
1331                                  pp--)
1332                             if (!isspace (*pp))
1333                                 break;
1334                         *pp++ = '\0';
1335
1336                         if (strncmp (buffer + 2, prefix, len))
1337                             continue;
1338
1339                         hit = 1;
1340                         break;
1341                     }
1342                 }
1343
1344             if (!hit)
1345                 break;
1346
1347             if (*cp < 'z')
1348                 (*cp)++;
1349             else
1350                 if (*++cp == 0) {
1351                     advise (NULLCP,
1352                             "unable to determine unique delimiter string?!?");
1353                     return;
1354                 }
1355                 else
1356                     (*cp)++;
1357         }
1358
1359         if ((out = fopen (tmpfil, "w")) == NULL) {
1360             advise (tmpfil, "unable to create temporary file");
1361             return;
1362         }
1363         (void) chmod (tmpfil, m_gmprot ());
1364
1365         fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
1366         fprintf (out, "%s: multipart/digest; boundary=\"%s\"\n", TYPE_FIELD,
1367                  prefix);
1368
1369         if (!(zp = fopen (libpath (form ? form : forwcomps), "r"))) {
1370             if (form)
1371                 advise (form, "unable to open form file");
1372             else
1373                 advise (forwcomps, "unable to open default components file");
1374             (void) fclose (out);
1375             (void) unlink (tmpfil);
1376             return;
1377         }
1378         while (fgets (buffer, sizeof buffer, zp))
1379             (void) fputs (buffer, out);
1380         (void) fclose (zp);
1381
1382         for (msgnum = mp -> lowsel;
1383                  msgnum <= mp -> hghsel && !interrupted;
1384                  msgnum++)
1385             if (mp -> msgstats[msgnum] & SELECTED) {
1386                 fprintf (out, "\n--%s\n%s: message/rfc822\n\n", prefix,
1387                          TYPE_FIELD);
1388
1389                 copy_message (msgnum, out);
1390             }
1391         fprintf (out, "\n--%s--\n", prefix);
1392
1393         (void) fclose (out);
1394         if (nwhat)
1395             return;
1396     }
1397 #endif  /* MIME */
1398     else {
1399         if ((out = fopen (tmpfil, "w")) == NULL) {
1400             advise (tmpfil, "unable to create temporary file");
1401             return;
1402         }
1403
1404         msgcnt = 1;
1405         for (msgnum = mp -> lowsel;
1406                 msgnum <= mp -> hghsel && !interrupted;
1407                 msgnum++)
1408             if (mp -> msgstats[msgnum] & SELECTED) {
1409                 fprintf (out, "\n\n-------");
1410                 if (msgnum == mp -> lowsel)
1411                     fprintf (out, " Forwarded Message%s",
1412                             mp -> numsel > 1 ? "s" : "");
1413                 else
1414                     fprintf (out, " Message %d", msgcnt);
1415                 fprintf (out, "\n\n");
1416                 copy_digest (msgnum, out);
1417                 msgcnt++;
1418             }
1419
1420         fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1421                 mp -> numsel > 1 ? "s" : "");
1422         (void) fclose (out);
1423     }
1424
1425     (void) fflush (stdout);
1426     if (!interrupted)
1427         switch (child_id = fork ()) {
1428             case NOTOK: 
1429                 advise ("fork", "unable to");
1430                 break;
1431
1432             case OK: 
1433                 closefds (3);
1434                 (void) signal (SIGINT, istat);
1435                 (void) signal (SIGQUIT, qstat);
1436
1437 #ifdef  MIME
1438                 if (mime) {
1439                     vecp = 0;
1440                     vec[vecp++] = r1bindex (proc, '/');
1441                     (void) m_putenv ("mhdraft", tmpfil);
1442                     (void) unputenv ("mhfolder");
1443                     (void) unputenv ("mhaltmsg");
1444                     (void) m_putenv ("mhdist", "0");
1445                     if (nedit)
1446                         (void) unputenv ("mheditor");
1447                     else
1448                         (void) m_putenv ("mheditor", ed);
1449                     (void) m_putenv ("mhuse", "0");
1450                     (void) unputenv ("mhmessages");
1451                     (void) unputenv ("mhannotate");
1452                     (void) unputenv ("mhinplace");
1453                 }
1454                 else
1455 #endif  /* MIME */
1456
1457                 vec[vecp++] = tmpfil;
1458                 vec[vecp] = NULL;
1459
1460                 execvp (proc, vec);
1461                 fprintf (stderr, "unable to exec ");
1462                 perror (proc);
1463                 _exit (1);
1464
1465             default: 
1466                 (void) pidXwait (child_id, NULLCP);
1467                 break;
1468         }
1469
1470 #ifdef  MIME
1471     if (!mime)
1472 #endif  /* MIME */
1473     (void) unlink (tmpfil);
1474 }
1475
1476 /* \f */
1477
1478 static char *hlpmsg[] = {
1479     "The %s program emulates many of the commands found in the Rand MH",
1480     "system.  Instead of operating on MH folders, commands to %s concern",
1481     "a single file.",
1482     "",
1483     "To see the list of commands available, just type a ``?'' followed by",
1484     "the RETURN key.  To find out what switches each command takes, type",
1485     "the name of the command followed by ``-help''.  To leave %s, use the",
1486     "``quit'' command.",
1487     "",
1488     "Although a lot of MH commands are found in %s, not all are fully",
1489     "implemented.  %s will always recognize all legal switches for a",
1490     "given command though, and will let you know when you ask for an",
1491     "option that it is unable to perform.",
1492     "",
1493     "Running %s is fun, but using MH from your shell is far superior.",
1494     "After you have familiarized yourself with the MH style by using %s,",
1495     "you should try using MH from the shell.  You can still use %s for",
1496     "message files that aren't in MH format, such as BBoard files.",
1497     NULL
1498 };
1499
1500
1501 /* ARGSUSED */
1502
1503 helpcmd (args)
1504 char  **args;
1505 {
1506     int     i;
1507
1508     for (i = 0; hlpmsg[i]; i++) {
1509         printf (hlpmsg[i], invo_name);
1510         (void) putchar ('\n');
1511     }
1512 }
1513
1514 /* \f */
1515
1516 static struct swit markswit[] = {
1517 #define MADDSW  0
1518     "add", 0,
1519 #define MDELSW  1
1520     "delete", 0,
1521 #define MLSTSW  2
1522     "list", 0,
1523 #define MSEQSW  3
1524     "sequence name", 0,
1525 #define MPUBSW  4
1526     "public", 0,
1527 #define MNPUBSW 5
1528     "nopublic", 0,
1529 #define MZERSW  6
1530     "zero", 0,
1531 #define MNZERSW 7
1532     "nozero", 0,
1533 #define MHELP   8
1534     "help", 4,
1535 #define MDBUGSW 9
1536     "debug", -5,
1537
1538     NULL, 0
1539 };
1540
1541 /* \f */
1542
1543 markcmd (args)
1544 char  **args;
1545 {
1546     int     addsw = 0,
1547             deletesw = 0,
1548             debugsw = 0,
1549             listsw = 0,
1550             zerosw = 0,
1551             seqp = 0,
1552             msgp = 0,
1553             i,
1554             msgnum;
1555     char   *cp,
1556             buf[BUFSIZ],
1557            *seqs[NATTRS + 1],
1558            *msgs[MAXARGS];
1559
1560     while (cp = *args++) {
1561         if (*cp == '-')
1562             switch (smatch (++cp, markswit)) {
1563                 case AMBIGSW: 
1564                     ambigsw (cp, markswit);
1565                     return;
1566                 case UNKWNSW: 
1567                     fprintf (stderr, "-%s unknown\n", cp);
1568                     return;
1569                 case MHELP: 
1570                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1571                     help (buf, markswit);
1572                     return;
1573
1574                 case MADDSW: 
1575                     addsw++;
1576                     deletesw = listsw = 0;
1577                     continue;
1578                 case MDELSW: 
1579                     deletesw++;
1580                     addsw = listsw = 0;
1581                     continue;
1582                 case MLSTSW: 
1583                     listsw++;
1584                     addsw = deletesw = 0;
1585                     continue;
1586
1587                 case MSEQSW: 
1588                     if (!(cp = *args++) || *cp == '-') {
1589                         advise (NULLCP, "missing argument to %s", args[-2]);
1590                         return;
1591                     }
1592                     if (seqp < NATTRS)
1593                         seqs[seqp++] = cp;
1594                     else {
1595                         advise (NULLCP, "only %d sequences allowed!", NATTRS);
1596                         return;
1597                     }
1598                     continue;
1599
1600                 case MPUBSW:    /* not implemented */
1601                 case MNPUBSW: 
1602                     continue;
1603
1604                 case MDBUGSW: 
1605                     debugsw++;
1606                     continue;
1607
1608                 case MZERSW: 
1609                     zerosw++;
1610                     continue;
1611                 case MNZERSW: 
1612                     zerosw = 0;
1613                     continue;
1614             }
1615         if (*cp == '+' || *cp == '@@') {
1616             advise (NULLCP, "sorry, no folders allowed!");
1617             return;
1618         }
1619         else
1620             msgs[msgp++] = cp;
1621     }
1622
1623     if (!addsw && !deletesw && !listsw)
1624         if (seqp)
1625             addsw++;
1626         else
1627             if (debugsw)
1628                 listsw++;
1629             else {
1630                 seqs[seqp++] = "unseen";
1631                 deletesw++;
1632                 zerosw = 0;
1633                 if (!msgp)
1634                     msgs[msgp++] = "all";
1635             }
1636
1637     if (!msgp)
1638         msgs[msgp++] = listsw ? "all" :"cur";
1639     for (msgnum = 0; msgnum < msgp; msgnum++)
1640         if (!m_convert (mp, msgs[msgnum]))
1641             return;
1642
1643     if (debugsw) {
1644         printf ("invo_name=%s mypath=%s defpath=%s\n",
1645                 invo_name, mypath, defpath);
1646         printf ("ctxpath=%s context flags=%s\n",
1647                 ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS));
1648         printf ("foldpath=%s flags=%s\n",
1649                 mp -> foldpath,
1650                 sprintb (buf, (unsigned) mp -> msgflags, FBITS));
1651         printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1652                 mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg);
1653         printf ("lowsel=%d hghsel=%d numsel=%d\n",
1654                 mp -> lowsel, mp -> hghsel, mp -> numsel);
1655 #ifndef MTR
1656         printf ("lowoff=%d hghoff=%d\n",
1657                 mp -> lowoff, mp -> hghoff);
1658 #else   /* MTR */
1659         printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n",
1660                 mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats);
1661 #endif  /* MTR */
1662     }
1663
1664     if (seqp == 0 && (addsw || deletesw)) {
1665         advise (NULLCP, "-%s requires at least one -sequence argument",
1666                 addsw ? "add" : "delete");
1667         return;
1668     }
1669     seqs[seqp] = NULL;
1670
1671     if (addsw)
1672         for (seqp = 0; seqs[seqp]; seqp++) {
1673             if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
1674                 return;
1675             for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1676                 if (mp -> msgstats[msgnum] & SELECTED)
1677                     if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1678                         return;
1679         }
1680
1681     if (deletesw)
1682         for (seqp = 0; seqs[seqp]; seqp++) {
1683             if (zerosw)
1684                 for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
1685                     if (mp -> msgstats[msgnum] & EXISTS)
1686                         if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
1687                             return;
1688             for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1689                 if (mp -> msgstats[msgnum] & SELECTED)
1690                     if (!m_seqdel (mp, seqs[seqp], msgnum))
1691                         return;
1692         }
1693
1694     if (listsw) {
1695         int     bits = FFATTRSLOT;
1696
1697 #define empty(s)        ((s) ? (s) : "")
1698         if (seqp == 0)
1699             for (i = 0; mp -> msgattrs[i]; i++)
1700                 printf ("%s%s: %s\n", mp -> msgattrs[i],
1701                         mp -> attrstats & (1 << (bits + i))
1702                         ? " (private)" : "",
1703                         empty(m_seq (mp, mp -> msgattrs[i])));
1704         else
1705             for (seqp = 0; seqs[seqp]; seqp++)
1706                 printf ("%s%s: %s\n", seqs[seqp],
1707                         empty(m_seq (mp, seqs[seqp])));
1708 #undef  empty
1709
1710         interrupted = 0;
1711         if (debugsw)
1712             for (msgnum = mp -> lowsel;
1713                     msgnum <= mp -> hghsel && !interrupted;
1714                     msgnum++)
1715                 if (mp -> msgstats[msgnum] & SELECTED) {
1716                     printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1717                             DMAXFOLDER, msgnum,
1718                             Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top,
1719                             Msgs[msgnum].m_start, Msgs[msgnum].m_stop,
1720                             sprintb (buf, (unsigned) mp -> msgstats[msgnum],
1721                                 m_seqbits (mp)));
1722                     if (Msgs[msgnum].m_scanl)
1723                         printf ("%s", Msgs[msgnum].m_scanl);
1724                 }                           
1725     }
1726 }
1727
1728 /* \f */
1729
1730 #ifdef MIME
1731 static struct swit mhnswit[] = {
1732 #define MHNAUTOSW         0
1733     "auto", 0,
1734 #define MHNNAUTOSW        1
1735     "noauto", 0,
1736 #define MHNDEBUGSW        2
1737     "debug", -5,
1738 #define MHNEBCDICSW      3
1739     "ebcdicsafe", 0,
1740 #define MHNNEBCDICSW     4
1741     "noebcdicsafe", 0,
1742 #define MHNFORMSW         5
1743     "form formfile", 4,
1744 #define MHNHEADSW         6
1745     "headers", 0,
1746 #define MHNNHEADSW        7
1747     "noheaders", 0,
1748 #define MHNLISTSW         8
1749     "list", 0,
1750 #define MHNNLISTSW        9
1751     "nolist", 0,
1752 #define MHNPARTSW        10
1753     "part number", 0,
1754 #define MHNSIZESW        11
1755     "realsize", 0,
1756 #define MHNNSIZESW       12
1757     "norealsize", 0,
1758 #define MHNRFC934SW      13
1759     "rfc934mode", 0,
1760 #define MHNNRFC934SW     14
1761     "norfc934mode", 0,
1762 #define MHNSERIALSW      15
1763     "serialonly", 0,
1764 #define MHNNSERIALSW     16
1765     "noserialonly", 0,
1766 #define MHNSHOWSW        17
1767     "show", 0,
1768 #define MHNNSHOWSW       18
1769     "noshow", 0,
1770 #define MHNSTORESW       19
1771     "store", 0,
1772 #define MHNNSTORESW      20
1773     "nostore", 0,
1774 #define MHNTYPESW        21
1775     "type content", 0,
1776 #define MHNVERBSW        22
1777     "verbose", 0,
1778 #define MHNNVERBSW       23
1779     "noverbose", 0,
1780 #define MHNHELPSW        24
1781     "help", 4,
1782 #define MHNPROGSW        25
1783     "moreproc program", -4,
1784 #define MHNNPROGSW       26
1785     "nomoreproc", -3,
1786 #define MHNLENSW         27
1787     "length lines", -4,
1788 #define MHNWIDSW         28
1789     "width columns", -4,
1790
1791     NULL, 0
1792 };
1793
1794 /* \f */
1795
1796 mhncmd (args)
1797 char  **args;
1798 {
1799     int     msgp = 0,
1800             vecp = 1,
1801             i,
1802             msgnum;
1803     char   *cp,
1804             buf[BUFSIZ],
1805            *msgs[MAXARGS],
1806            *vec[MAXARGS];
1807
1808     if (fmsh) {
1809         forkcmd (args, cmd_name);
1810         return;
1811     }
1812
1813     while (cp = *args++) {
1814         if (*cp == '-')
1815             switch (smatch (++cp, mhnswit)) {
1816                 case AMBIGSW: 
1817                     ambigsw (cp, mhnswit);
1818                     return;
1819                 case UNKWNSW: 
1820                     fprintf (stderr, "-%s unknown\n", cp);
1821                     return;
1822                 case MHNHELPSW:
1823                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1824                     help (buf, mhnswit);
1825                     return;
1826
1827                 case MHNAUTOSW:
1828                 case MHNNAUTOSW:
1829                 case MHNDEBUGSW:
1830                 case MHNEBCDICSW:
1831                 case MHNNEBCDICSW:
1832                 case MHNHEADSW:
1833                 case MHNNHEADSW:
1834                 case MHNLISTSW:
1835                 case MHNNLISTSW:
1836                 case MHNSIZESW:
1837                 case MHNNSIZESW:
1838                 case MHNRFC934SW:
1839                 case MHNNRFC934SW:
1840                 case MHNSERIALSW:
1841                 case MHNNSERIALSW:
1842                 case MHNSHOWSW:
1843                 case MHNNSHOWSW:
1844                 case MHNSTORESW:
1845                 case MHNNSTORESW:
1846                 case MHNVERBSW:
1847                 case MHNNVERBSW:
1848                 case MHNNPROGSW:
1849                     vec[vecp++] = --cp;
1850                     continue;
1851
1852                 case MHNFORMSW:
1853                 case MHNPARTSW:
1854                 case MHNTYPESW:
1855                 case MHNPROGSW:
1856                 case MHNLENSW:
1857                 case MHNWIDSW:
1858                     vec[vecp++] = --cp;
1859                     if (!(cp = *args++) || *cp == '-') {
1860                         advise (NULLCP, "missing argument to %s", args[-2]);
1861                         return;
1862                     }
1863                     vec[vecp++] = cp;
1864                     continue;
1865             }
1866         if (*cp == '+' || *cp == '@@') {
1867             advise (NULLCP, "sorry, no folders allowed!");
1868             return;
1869         }
1870         else
1871             msgs[msgp++] = cp;
1872     }
1873
1874     vec[0] = cmd_name;
1875     vec[vecp++] = "-file";
1876     vec[vecp] = NULL;
1877     if (!msgp)
1878         msgs[msgp++] = "cur";
1879     for (msgnum = 0; msgnum < msgp; msgnum++)
1880         if (!m_convert (mp, msgs[msgnum]))
1881             return;
1882     m_setseq (mp);
1883
1884     interrupted = 0;
1885     for (msgnum = mp -> lowsel;
1886             msgnum <= mp -> hghsel && !interrupted;
1887             msgnum++)
1888         if (mp -> msgstats[msgnum] & SELECTED)
1889             if (process (msgnum, cmd_name, vecp, vec)) {
1890                 mp -> msgstats[msgnum] &= ~SELECTED;
1891                 mp -> numsel--;
1892             }
1893
1894     m_setcur (mp, mp -> hghsel);
1895 }
1896
1897 /* \f */
1898
1899 #endif /* MIME */
1900 static struct swit packswit[] = {
1901 #define PAFISW  0
1902     "file name", 0,
1903
1904 #define PAHELP  1
1905     "help", 4,
1906
1907     NULL, 0
1908 };
1909
1910 /* \f */
1911
1912 packcmd (args)
1913 char  **args;
1914 {
1915     int     msgp = 0,
1916             md,
1917             msgnum;
1918     char   *cp,
1919            *file = NULL,
1920             buf[BUFSIZ],
1921            *msgs[MAXARGS];
1922     struct stat st;
1923
1924     if (fmsh) {
1925         forkcmd (args, cmd_name);
1926         return;
1927     }
1928
1929     while (cp = *args++) {
1930         if (*cp == '-')
1931             switch (smatch (++cp, packswit)) {
1932                 case AMBIGSW: 
1933                     ambigsw (cp, packswit);
1934                     return;
1935                 case UNKWNSW: 
1936                     fprintf (stderr, "-%s unknown\n", cp);
1937                     return;
1938                 case PAHELP: 
1939                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
1940                     help (buf, packswit);
1941                     return;
1942
1943                 case PAFISW: 
1944                     if (!(file = *args++) || *file == '-') {
1945                         advise (NULLCP, "missing argument to %s", args[-2]);
1946                         return;
1947                     }
1948                     continue;
1949             }
1950         if (*cp == '+' || *cp == '@@') {
1951             advise (NULLCP, "sorry, no folders allowed!");
1952             return;
1953         }
1954         else
1955             msgs[msgp++] = cp;
1956     }
1957
1958     if (!file)
1959         file = "./msgbox";
1960     file = path (file, TFILE);
1961     if (stat (file, &st) == NOTOK) {
1962         if (errno != ENOENT) {
1963             advise (file, "error on file");
1964             goto done_pack;
1965         }
1966         md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP));
1967         free (cp);
1968         if (!md)
1969             goto done_pack;
1970     }
1971
1972     if (!msgp)
1973         msgs[msgp++] = "all";
1974     for (msgnum = 0; msgnum < msgp; msgnum++)
1975         if (!m_convert (mp, msgs[msgnum]))
1976             goto done_pack;
1977     m_setseq (mp);
1978
1979     if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1980         advise (file, "unable to open");
1981         goto done_pack;
1982     }
1983     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
1984         if (mp -> msgstats[msgnum] & SELECTED)
1985             if (pack (file, md, msgnum) == NOTOK)
1986                 break;
1987     (void) mbx_close (file, md);
1988
1989     if (mp -> hghsel != mp -> curmsg)
1990         m_setcur (mp, mp -> lowsel);
1991
1992 done_pack: ;
1993     free (file);
1994 }
1995
1996 /* \f */
1997
1998 int     pack (mailbox, md, msgnum)
1999 char   *mailbox;
2000 int     md,
2001         msgnum;
2002 {
2003     register FILE *zp;
2004
2005     if (Msgs[msgnum].m_bboard_id == 0)
2006         (void) readid (msgnum);
2007
2008     zp = msh_ready (msgnum, 1);
2009     return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
2010             0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
2011 }
2012
2013 /* \f */
2014
2015 int     packhak (args)
2016 char  **args;
2017 {
2018     int     result;
2019     char   *cp,
2020            *file = NULL;
2021
2022     while (cp = *args++) {
2023         if (*cp == '-')
2024             switch (smatch (++cp, packswit)) {
2025                 case AMBIGSW: 
2026                 case UNKWNSW: 
2027                 case PAHELP: 
2028                     return NOTOK;
2029
2030                 case PAFISW: 
2031                     if (!(file = *args++) || *file == '-') 
2032                         return NOTOK;
2033                     continue;
2034             }
2035         if (*cp == '+' || *cp == '@@')
2036             return NOTOK;
2037     }
2038
2039     file = path (file ? file : "./msgbox", TFILE);
2040     result = access (file, 0) == NOTOK ? OK : NOTOK;
2041     free (file);
2042
2043     return result;
2044 }
2045
2046 /* \f */
2047
2048 static struct swit pickswit[] = {
2049 #define PIANSW  0
2050     "and", 0,
2051 #define PIORSW  1
2052     "or", 0,
2053 #define PINTSW  2
2054     "not", 0,
2055 #define PILBSW  3
2056     "lbrace", 0,
2057 #define PIRBSW  4
2058     "rbrace", 0,
2059
2060 #define PICCSW  5
2061     "cc  pattern", 0,
2062 #define PIDASW  6
2063     "date  pattern", 0,
2064 #define PIFRSW  7
2065     "from  pattern", 0,
2066 #define PISESW  8
2067     "search  pattern", 0,
2068 #define PISUSW  9
2069     "subject  pattern", 0,
2070 #define PITOSW  10
2071     "to  pattern", 0,
2072 #define PIOTSW  11
2073     "-othercomponent  pattern", 15,
2074 #define PIAFSW  12
2075     "after date", 0,
2076 #define PIBFSW  13
2077     "before date", 0,
2078 #define PIDFSW  14
2079     "datefield field", 5,
2080 #define PISQSW  15
2081     "sequence name", 0,
2082 #define PIPUSW  16
2083     "public", 0,
2084 #define PINPUSW 17
2085     "nopublic", 0,
2086 #define PIZRSW  18
2087     "zero", 0,
2088 #define PINZRSW 19
2089     "nozero", 0,
2090 #define PILISW  20
2091     "list", 0,
2092 #define PINLISW 21
2093     "nolist", 0,
2094 #define PIHELP  22
2095     "help", 4,
2096
2097     NULL, 0
2098 };
2099
2100 /* \f */
2101
2102 pickcmd (args)
2103 char  **args;
2104 {
2105     int     zerosw = 1,
2106             msgp = 0,
2107             seqp = 0,
2108             vecp = 0,
2109             hi,
2110             lo,
2111             msgnum;
2112     char   *cp,
2113             buf[BUFSIZ],
2114            *msgs[MAXARGS],
2115            *seqs[NATTRS],
2116            *vec[MAXARGS];
2117     register FILE *zp;
2118
2119     while (cp = *args++) {
2120         if (*cp == '-') {
2121             if (*++cp == '-') {
2122                 vec[vecp++] = --cp;
2123                 goto pattern;
2124             }
2125             switch (smatch (cp, pickswit)) {
2126                 case AMBIGSW: 
2127                     ambigsw (cp, pickswit);
2128                     return;
2129                 case UNKWNSW: 
2130                     fprintf (stderr, "-%s unknown\n", cp);
2131                     return;
2132                 case PIHELP: 
2133                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2134                     help (buf, pickswit);
2135                     return;
2136
2137                 case PICCSW: 
2138                 case PIDASW: 
2139                 case PIFRSW: 
2140                 case PISUSW: 
2141                 case PITOSW: 
2142                 case PIDFSW: 
2143                 case PIAFSW: 
2144                 case PIBFSW: 
2145                 case PISESW: 
2146                     vec[vecp++] = --cp;
2147 pattern: ;
2148                     if (!(cp = *args++)) {/* allow -xyz arguments */
2149                         advise (NULLCP, "missing argument to %s", args[-2]);
2150                         return;
2151                     }
2152                     vec[vecp++] = cp;
2153                     continue;
2154                 case PIOTSW: 
2155                     advise (NULLCP, "internal error!");
2156                     return;
2157                 case PIANSW: 
2158                 case PIORSW: 
2159                 case PINTSW: 
2160                 case PILBSW: 
2161                 case PIRBSW: 
2162                     vec[vecp++] = --cp;
2163                     continue;
2164
2165                 case PISQSW: 
2166                     if (!(cp = *args++) || *cp == '-') {
2167                         advise (NULLCP, "missing argument to %s", args[-2]);
2168                         return;
2169                     }
2170                     if (seqp < NATTRS)
2171                         seqs[seqp++] = cp;
2172                     else {
2173                         advise (NULLCP, "only %d sequences allowed!", NATTRS);
2174                         return;
2175                     }
2176                     continue;
2177                 case PIZRSW: 
2178                     zerosw++;
2179                     continue;
2180                 case PINZRSW: 
2181                     zerosw = 0;
2182                     continue;
2183
2184                 case PIPUSW:    /* not implemented */
2185                 case PINPUSW: 
2186                 case PILISW: 
2187                 case PINLISW: 
2188                     continue;
2189             }
2190         }
2191         if (*cp == '+' || *cp == '@@') {
2192             advise (NULLCP, "sorry, no folders allowed!");
2193             return;
2194         }
2195         else
2196             msgs[msgp++] = cp;
2197     }
2198     vec[vecp] = NULL;
2199
2200     if (!msgp)
2201         msgs[msgp++] = "all";
2202     for (msgnum = 0; msgnum < msgp; msgnum++)
2203         if (!m_convert (mp, msgs[msgnum]))
2204             return;
2205     m_setseq (mp);
2206
2207     interrupted = 0;
2208     if (!pcompile (vec, NULLCP))
2209         return;
2210
2211     lo = mp -> lowsel;
2212     hi = mp -> hghsel;
2213
2214     for (msgnum = mp -> lowsel;
2215             msgnum <= mp -> hghsel && !interrupted;
2216             msgnum++)
2217         if (mp -> msgstats[msgnum] & SELECTED) {
2218             zp = msh_ready (msgnum, 1);
2219             if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
2220                         fmsh ? 0L : Msgs[msgnum].m_stop)) {
2221                 if (msgnum < lo)
2222                     lo = msgnum;
2223                 if (msgnum > hi)
2224                     hi = msgnum;
2225             }
2226             else {
2227                 mp -> msgstats[msgnum] &= ~SELECTED;
2228                 mp -> numsel--;
2229             }
2230         }
2231
2232     if (interrupted)
2233         return;
2234
2235     mp -> lowsel = lo;
2236     mp -> hghsel = hi;
2237
2238     if (mp -> numsel <= 0) {
2239         advise (NULLCP, "no messages match specification");
2240         return;
2241     }
2242
2243     seqs[seqp] = NULL;
2244     for (seqp = 0; seqs[seqp]; seqp++) {
2245         if (zerosw && !m_seqnew (mp, seqs[seqp], 0))
2246             return;
2247         for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2248             if (mp -> msgstats[msgnum] & SELECTED)
2249                 if (!m_seqadd (mp, seqs[seqp], msgnum, 0))
2250                     return;
2251     }
2252
2253     printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s");
2254 }
2255
2256 /* \f */
2257
2258 static struct swit replswit[] = {
2259 #define REANSW  0
2260     "annotate", 0,
2261 #define RENANSW 1
2262     "noannotate", 0,
2263 #define RECCSW  2
2264     "cc type", 0,
2265 #define RENCCSW 3
2266     "nocc type", 0,
2267 #define REDFSW  4
2268     "draftfolder +folder", 0,
2269 #define REDMSW  5
2270     "draftmessage msg", 0,
2271 #define RENDFSW 6
2272     "nodraftfolder", 0,
2273 #define REEDTSW 7
2274     "editor editor", 0,
2275 #define RENEDSW 8
2276     "noedit", 0,
2277 #define REFCCSW 9
2278     "fcc +folder", 0,
2279 #define REFLTSW 10
2280     "filter filterfile", 0,
2281 #define REFRMSW 11
2282     "form formfile", 0,
2283 #define REINSW  12
2284     "inplace", 0,
2285 #define RENINSW 13
2286     "noinplace", 0,
2287 #define REQUSW  14
2288     "query", 0,
2289 #define RENQUSW 15
2290     "noquery", 0,
2291 #define REWHTSW 16
2292     "whatnowproc program", 0,
2293 #define RENWTSW 17
2294     "nowhatnow", 0,
2295 #define REWIDSW 19
2296     "width columns", 0,
2297 #define REHELP  20
2298     "help", 4,
2299
2300     NULL, 0
2301 };
2302
2303 /* \f */
2304
2305 replcmd (args)
2306 char  **args;
2307 {
2308     int     vecp = 1;
2309     char   *cp,
2310            *msg = NULL,
2311             buf[BUFSIZ],
2312            *vec[MAXARGS];
2313
2314     if (fmsh) {
2315         forkcmd (args, cmd_name);
2316         return;
2317     }
2318
2319     while (cp = *args++) {
2320         if (*cp == '-')
2321             switch (smatch (++cp, replswit)) {
2322                 case AMBIGSW: 
2323                     ambigsw (cp, replswit);
2324                     return;
2325                 case UNKWNSW: 
2326                     fprintf (stderr, "-%s unknown\n", cp);
2327                     return;
2328                 case REHELP: 
2329                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2330                     help (buf, replswit);
2331                     return;
2332
2333                 case REANSW:    /* not implemented */
2334                 case RENANSW: 
2335                 case REINSW: 
2336                 case RENINSW: 
2337                     continue;
2338
2339                 case REQUSW:
2340                 case RENQUSW:
2341                 case RENDFSW:
2342                 case RENEDSW:
2343                 case RENWTSW:
2344                     vec[vecp++] = --cp;
2345                     continue;
2346
2347                 case RECCSW: 
2348                 case RENCCSW: 
2349                 case REEDTSW: 
2350                 case REFCCSW: 
2351                 case REFLTSW:
2352                 case REFRMSW: 
2353                 case REWIDSW: 
2354                 case REDFSW:
2355                 case REDMSW:
2356                 case REWHTSW:
2357                     vec[vecp++] = --cp;
2358                     if (!(cp = *args++) || *cp == '-') {
2359                         advise (NULLCP, "missing argument to %s", args[-2]);
2360                         return;
2361                     }
2362                     vec[vecp++] = cp;
2363                     continue;
2364             }
2365         if (*cp == '+' || *cp == '@@') {
2366             advise (NULLCP, "sorry, no folders allowed!");
2367             return;
2368         }
2369         else
2370             if (msg) {
2371                 advise (NULLCP, "only one message at a time!");
2372                 return;
2373             }
2374             else
2375                 msg = cp;
2376     }
2377
2378     vec[0] = cmd_name;
2379     vec[vecp++] = "-file";
2380     vec[vecp] = NULL;
2381     if (!msg)
2382         msg = "cur";
2383     if (!m_convert (mp, msg))
2384         return;
2385     m_setseq (mp);
2386
2387     if (mp -> numsel > 1) {
2388         advise (NULLCP, "only one message at a time!");
2389         return;
2390     }
2391     (void) process (mp -> hghsel, cmd_name, vecp, vec);
2392     m_setcur (mp, mp -> hghsel);
2393 }
2394
2395 /* \f */
2396
2397 static struct swit rmmswit[] = {
2398 #define RMHELP  0
2399     "help", 4,
2400
2401     NULL, 0
2402 };
2403
2404 /* \f */
2405
2406 rmmcmd (args)
2407 char  **args;
2408 {
2409     int     msgp = 0,
2410             msgnum;
2411     char   *cp,
2412             buf[BUFSIZ],
2413            *msgs[MAXARGS];
2414
2415     while (cp = *args++) {
2416         if (*cp == '-')
2417             switch (smatch (++cp, rmmswit)) {
2418                 case AMBIGSW: 
2419                     ambigsw (cp, rmmswit);
2420                     return;
2421                 case UNKWNSW: 
2422                     fprintf (stderr, "-%s unknown\n", cp);
2423                     return;
2424                 case RMHELP: 
2425                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2426                     help (buf, rmmswit);
2427                     return;
2428             }
2429         if (*cp == '+' || *cp == '@@') {
2430             advise (NULLCP, "sorry, no folders allowed!");
2431             return;
2432         }
2433         else
2434             msgs[msgp++] = cp;
2435     }
2436
2437     if (!msgp)
2438         msgs[msgp++] = "cur";
2439     for (msgnum = 0; msgnum < msgp; msgnum++)
2440         if (!m_convert (mp, msgs[msgnum]))
2441             return;
2442     m_setseq (mp);
2443
2444     rmm ();
2445 }
2446
2447 /* \f */
2448
2449 static  rmm () {
2450     register int    msgnum,
2451                     vecp;
2452     register char  *cp;
2453     char    buffer[BUFSIZ],
2454            *vec[MAXARGS];
2455
2456     if (fmsh) {
2457         if (rmmproc) {
2458             if (mp -> numsel > MAXARGS - 1) {
2459                 advise (NULLCP, "more than %d messages for %s exec",
2460                         MAXARGS - 1, rmmproc);
2461                 return;
2462             }
2463             vecp = 0;
2464             for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2465                 if (mp -> msgstats[msgnum] & SELECTED)
2466                     vec[vecp++] = getcpy (m_name (msgnum));
2467             vec[vecp] = NULL;
2468             forkcmd (vec, rmmproc);
2469             for (vecp = 0; vec[vecp]; vecp++)
2470                 free (vec[vecp]);
2471         }
2472         else
2473             for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2474                 if (mp -> msgstats[msgnum] & SELECTED) {
2475                     (void) strcpy (buffer, m_backup (cp = m_name (msgnum)));
2476                     if (rename (cp, buffer) == NOTOK)
2477                         admonish (buffer, "unable to rename %s to", cp);
2478                 }
2479     }
2480
2481     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2482         if (mp -> msgstats[msgnum] & SELECTED) {
2483             mp -> msgstats[msgnum] |= DELETED;
2484             mp -> msgstats[msgnum] &= ~EXISTS;
2485 #ifdef  MPOP
2486 #ifdef  BPOP
2487             if (pmsh && pop_dele (msgnum) != OK)
2488                 fprintf (stderr, "%s", response);
2489 #endif
2490 #endif /* MPOP */
2491         }
2492
2493     if ((mp -> nummsg -= mp -> numsel) <= 0) {
2494         if (fmsh)
2495             admonish (NULLCP, "no messages remaining in +%s", fmsh);
2496         else
2497             admonish (NULLCP, "no messages remaining in %s", mp -> foldpath);
2498         mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0;
2499     }
2500     if (mp -> lowsel == mp -> lowmsg) {
2501         for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++)
2502             if (mp -> msgstats[msgnum] & EXISTS)
2503                 break;
2504         mp -> lowmsg = msgnum;
2505     }
2506     if (mp -> hghsel == mp -> hghmsg) {
2507         for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--)
2508             if (mp -> msgstats[msgnum] & EXISTS)
2509                 break;
2510         mp -> hghmsg = msgnum;
2511     }
2512
2513     mp -> msgflags |= MODIFIED;
2514     modified++;
2515 }
2516
2517 /* \f */
2518
2519 static struct swit scanswit[] = {
2520 #define SCCLR   0
2521     "clear", 0,
2522 #define SCNCLR  1
2523     "noclear", 0,
2524 #define SCFORM  2
2525     "form formatfile", 0,
2526 #define SCFMT   3
2527     "format string", 5,
2528 #define SCHEAD  4
2529     "header", 0,
2530 #define SCNHEAD 5
2531     "noheader", 0,
2532 #define SCWID   6
2533     "width columns", 0,
2534 #define SCHELP  7
2535     "help", 4,
2536
2537     NULL, 0
2538 };
2539
2540 /* \f */
2541
2542 scancmd (args)
2543 char  **args;
2544 {
2545 #define equiv(a,b)      (a ? b && !strcmp (a, b) : !b)
2546
2547     int     clearsw = 0,
2548             headersw = 0,
2549             width = 0,
2550             msgp = 0,
2551             msgnum,
2552             optim,
2553             state;
2554     char   *cp,
2555            *form = NULL,
2556            *format = NULL,
2557             buf[BUFSIZ],
2558            *nfs,
2559            *msgs[MAXARGS];
2560     register FILE *zp;
2561 #ifdef  MPOP
2562 #ifdef  BPOP
2563     static int p_optim = 0;
2564 #endif
2565 #endif /* MPOP */
2566     static int s_optim = 0;
2567     static char *s_form = NULL,
2568                 *s_format = NULL;
2569
2570     while (cp = *args++) {
2571         if (*cp == '-')
2572             switch (smatch (++cp, scanswit)) {
2573                 case AMBIGSW: 
2574                     ambigsw (cp, scanswit);
2575                     return;
2576                 case UNKWNSW: 
2577                     fprintf (stderr, "-%s unknown\n", cp);
2578                     return;
2579                 case SCHELP: 
2580                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
2581                     help (buf, scanswit);
2582                     return;
2583
2584                 case SCCLR: 
2585                     clearsw++;
2586                     continue;
2587                 case SCNCLR: 
2588                     clearsw = 0;
2589                     continue;
2590                 case SCHEAD: 
2591                     headersw++;
2592                     continue;
2593                 case SCNHEAD: 
2594                     headersw = 0;
2595                     continue;
2596                 case SCFORM: 
2597                     if (!(form = *args++) || *form == '-') {
2598                         advise (NULLCP, "missing argument to %s", args[-2]);
2599                         return;
2600                     }
2601                     format = NULL;
2602                     continue;
2603                 case SCFMT: 
2604                     if (!(format = *args++) || *format == '-') {
2605                         advise (NULLCP, "missing argument to %s", args[-2]);
2606                         return;
2607                     }
2608                     form = NULL;
2609                     continue;
2610                 case SCWID: 
2611                     if (!(cp = *args++) || *cp == '-') {
2612                         advise (NULLCP, "missing argument to %s", args[-2]);
2613                         return;
2614                     }
2615                     width = atoi (cp);
2616                     continue;
2617             }
2618         if (*cp == '+' || *cp == '@@') {
2619             advise (NULLCP, "sorry, no folders allowed!");
2620             return;
2621         }
2622         else
2623             msgs[msgp++] = cp;
2624     }
2625
2626     if (!msgp)
2627         msgs[msgp++] = "all";
2628     for (msgnum = 0; msgnum < msgp; msgnum++)
2629         if (!m_convert (mp, msgs[msgnum]))
2630             return;
2631     m_setseq (mp);
2632
2633     nfs = new_fs (form, format, FORMAT);
2634     if (scanl) {                /* force scansbr to (re)compile format */
2635         (void) free (scanl);
2636         scanl = NULL;
2637     }
2638
2639     if (s_optim == 0) {
2640         s_optim = optim = 1;
2641         s_form = form ? getcpy (form) : NULL;
2642         s_format = format ? getcpy (format) : NULL;
2643
2644 #ifdef  MPOP
2645 #ifdef  BPOP
2646         if (pmsh) {
2647             int     i;
2648             char   *dp,
2649                    *ep,
2650                    *fp;
2651
2652             if (width == 0)
2653                 width = sc_width ();
2654
2655             for (dp = nfs, i = 0; *dp; dp++, i++)
2656                 if (*dp == '\\' || *dp == '"' || *dp == '\n')
2657                     i++;
2658             i++;
2659             if ((ep = malloc ((unsigned) i)) == NULL)
2660                 adios (NULLCP, "out of memory");
2661             for (dp = nfs, fp = ep; *dp; dp++) {
2662                 if (*dp == '\n') {
2663                     *fp++ = '\\', *fp++ = 'n';
2664                     continue;
2665                 }
2666                 if (*dp == '"' || *dp == '\\')
2667                     *fp++ = '\\';
2668                 *fp++ = *dp;
2669             }
2670             *fp = NULL;
2671
2672             if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
2673                 p_optim = 1;
2674
2675             free (ep);
2676         }
2677 #endif
2678 #endif  /* MPOP */
2679     }
2680     else
2681         optim = equiv (s_form, form) && equiv (s_format, format);
2682
2683 #ifdef  MPOP
2684 #ifdef  BPOP
2685     if (p_optim && optim) {
2686         for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++)
2687             if (!(mp -> msgstats[msgnum] & SELECTED) || Msgs[msgnum].m_scanl)
2688                 break;
2689         if (msgnum > mp -> hghmsg && pop_command ("LIST") == OK) {
2690             fprintf (stderr, "Stand-by...");
2691             fflush (stderr);
2692
2693             for (;;) {
2694                 int     size;
2695
2696                 switch (pop_multiline ()) {
2697                     case NOTOK:
2698                         fprintf (stderr, "%s", response);
2699                         /* and fall... */
2700                     case DONE:
2701                         fprintf (stderr,"\n");
2702                         break;
2703
2704                     case OK:
2705                         if (sscanf (response, "%d %d", &msgnum, &size) == 2
2706                                 && mp -> lowmsg <= msgnum
2707                                 && msgnum <= mp -> hghmsg
2708                                 && (cp = index (response, '#'))
2709                                 && *++cp)
2710                             Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
2711                         continue;
2712                 }
2713                 break;
2714             }
2715         }
2716     }
2717 #endif
2718 #endif /* MPOP */
2719
2720     interrupted = 0;
2721     for (msgnum = mp -> lowsel;
2722             msgnum <= mp -> hghsel && !interrupted;
2723             msgnum++)
2724         if (mp -> msgstats[msgnum] & SELECTED) {
2725             if (optim && Msgs[msgnum].m_scanl)
2726                 printf ("%s", Msgs[msgnum].m_scanl);
2727             else {
2728 #ifdef  MPOP
2729 #ifdef  BPOP
2730                 if (p_optim
2731                         && optim
2732                         && (mp -> msgstats[msgnum] & VIRTUAL)
2733                         && pop_command ("LIST %d", msgnum) == OK
2734                         && (cp = index (response, '#'))
2735                         && *++cp) {
2736                     Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP);
2737                     printf ("%s", Msgs[msgnum].m_scanl);                    
2738                     continue;
2739                 }
2740 #endif
2741 #endif /* MPOP */
2742
2743                 zp = msh_ready (msgnum, 0);
2744                 switch (state = scan (zp, msgnum, 0, nfs, width,
2745                         msgnum == mp -> curmsg,
2746                         mp -> msgstats[msgnum] & UNSEEN,        /* ?? */
2747                         headersw, fmsh ? fmsh : mp -> foldpath,
2748                         fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2749                         1)) {
2750                     case SCNMSG:
2751                     case SCNENC:
2752                     case SCNERR:
2753                         if (optim)
2754                             Msgs[msgnum].m_scanl = getcpy (scanl);
2755                         break;
2756
2757                     default:
2758                         advise (NULLCP, "scan() botch (%d)", state);
2759                         return;
2760
2761                     case SCNEOF:
2762                         printf ("%*d  empty\n", DMAXFOLDER, msgnum);
2763                         break;
2764                     }
2765             }
2766             headersw = 0;
2767         }
2768
2769     if (clearsw)
2770         clear_screen ();
2771 }
2772
2773 /* \f */
2774
2775 static struct swit showswit[] = {
2776 #define SHDRAFT 0
2777     "draft", 5,
2778 #define SHFORM  1
2779     "form formfile", 4,
2780 #define SHPROG  2
2781     "moreproc program", 4,
2782 #define SHNPROG 3
2783     "nomoreproc", 3,
2784 #define SHLEN   4
2785     "length lines", 4,
2786 #define SHWID   5
2787     "width columns", 4,
2788 #define SHSHOW  6
2789     "showproc program", 4,
2790 #define SHNSHOW 7
2791     "noshowproc", 3,
2792 #define SHHEAD  8
2793     "header", 4,
2794 #define SHNHEAD 9
2795     "noheader", 3,
2796 #define SHHELP  10
2797     "help", 4,
2798
2799     NULL, 0
2800 };
2801
2802 /* \f */
2803
2804 showcmd (args)
2805 char  **args;
2806 {
2807     int     headersw = 1,
2808             nshow = 0,
2809             msgp = 0,
2810             vecp = 1,
2811             mhl = 0,
2812             seen = 0,
2813             mode = 0,
2814             i,
2815             msgnum;
2816     char   *cp,
2817            *proc = showproc,
2818             buf[BUFSIZ],
2819            *msgs[MAXARGS],
2820            *vec[MAXARGS];
2821
2822     if (uleq (cmd_name, "next"))
2823         mode = 1;
2824     else
2825         if (uleq (cmd_name, "prev"))
2826             mode = -1;
2827     while (cp = *args++) {
2828         if (*cp == '-')
2829             switch (i = smatch (++cp, showswit)) {
2830                 case AMBIGSW: 
2831                     ambigsw (cp, showswit);
2832                     return;
2833                 case UNKWNSW: 
2834                 case SHNPROG:
2835                     vec[vecp++] = --cp;
2836                     continue;
2837                 case SHHELP: 
2838                     (void) sprintf (buf,
2839                             "%s %s[switches] [switches for showproc]",
2840                             cmd_name, mode ? NULL : "[msgs] ");
2841                     help (buf, showswit);
2842                     return;
2843
2844                 case SHFORM: 
2845                 case SHPROG:
2846                 case SHLEN:
2847                 case SHWID:
2848                     vec[vecp++] = --cp;
2849                     if (!(cp = *args++) || *cp == '-') {
2850                         advise (NULLCP, "missing argument to %s", args[-2]);
2851                         return;
2852                     }
2853                     vec[vecp++] = cp;
2854                     continue;
2855                 case SHHEAD: 
2856                     headersw++;
2857                     continue;
2858                 case SHNHEAD: 
2859                     headersw = 0;
2860                     continue;
2861                 case SHSHOW: 
2862                     if (!(proc = *args++) || *proc == '-') {
2863                         advise (NULLCP, "missing argument to %s", args[-2]);
2864                         return;
2865                     }
2866                     nshow = 0;
2867                     continue;
2868                 case SHNSHOW: 
2869                     nshow++;
2870                     continue;
2871
2872                 case SHDRAFT: 
2873                     advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw);
2874                     return;
2875             }
2876         if (*cp == '+' || *cp == '@@') {
2877             advise (NULLCP, "sorry, no folders allowed!");
2878             return;
2879         }
2880         else
2881             if (mode) {
2882                 fprintf (stderr,
2883                         "usage: %s [switches] [switches for showproc]\n",
2884                         cmd_name);
2885                 return;
2886             }
2887             else
2888                 msgs[msgp++] = cp;
2889     }
2890     vec[vecp] = NULL;
2891
2892     if (!msgp)
2893         msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2894     for (msgnum = 0; msgnum < msgp; msgnum++)
2895         if (!m_convert (mp, msgs[msgnum]))
2896             return;
2897     m_setseq (mp);
2898
2899 #ifdef  MIME
2900     if (!nshow && !getenv ("NOMHNPROC"))
2901         for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2902             if ((mp -> msgstats[msgnum] & SELECTED) && nontext (msgnum)) {
2903                 proc = (cp = m_find ("mhnproc")) ? cp : "mhn";
2904                 vec[vecp++] = "-show";
2905                 vec[vecp++] = "-file";
2906                 vec[vecp] = NULL;
2907                 goto finish;
2908             }
2909 #endif  /* MIME */
2910
2911     if (nshow)
2912         proc = "cat";
2913     else
2914         if (strcmp (showproc, "mhl") == 0) {
2915             proc = mhlproc;
2916             mhl++;
2917         }
2918
2919 finish: ;
2920     seen = m_seqflag (mp, "unseen");
2921     vec[0] = r1bindex (proc, '/');
2922     if (mhl) {
2923         msgp = vecp;
2924         for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++)
2925             if (mp -> msgstats[msgnum] & SELECTED) {
2926                 vec[vecp++] = getcpy (m_name (msgnum));
2927                 if (seen)
2928                     (void) m_seqdel (mp, "unseen", msgnum);
2929             }
2930         vec[vecp] = NULL;
2931         if (mp -> numsel == 1 && headersw)
2932             show (mp -> lowsel);
2933         (void) mhlsbr (vecp, vec, mhl_action);
2934         m_eomsbr ((int (*)()) 0);
2935         while (msgp < vecp)
2936             free (vec[msgp++]);
2937     }
2938     else {
2939         interrupted = 0;
2940         for (msgnum = mp -> lowsel;
2941                 msgnum <= mp -> hghsel && !interrupted;
2942                 msgnum++)
2943             if (mp -> msgstats[msgnum] & SELECTED) {
2944                 switch (ask (msgnum)) {
2945                     case NOTOK: /* QUIT */
2946                         break;
2947
2948                     case OK:    /* INTR */
2949                         continue;
2950
2951                     default:
2952                         if (mp -> numsel == 1 && headersw)
2953                             show (msgnum);
2954                         if (nshow)
2955                             copy_message (msgnum, stdout);
2956                         else
2957                             (void) process (msgnum, proc, vecp, vec);
2958
2959                         if (seen)
2960                             (void) m_seqdel (mp, "unseen", msgnum);
2961                         continue;
2962                 }
2963                 break;
2964             }
2965     }
2966
2967     m_setcur (mp, mp -> hghsel);
2968 }
2969
2970 /* \f */
2971
2972 static  show (msgnum)
2973 int     msgnum;
2974 {
2975     if (Msgs[msgnum].m_bboard_id == 0)
2976         (void) readid (msgnum);
2977
2978     printf ("(Message %d", msgnum);
2979     if (Msgs[msgnum].m_bboard_id > 0)
2980         printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2981     printf (")\n");
2982 }
2983
2984
2985 /* ARGSUSED */
2986
2987 static  int eom_action (c)
2988 int     c;
2989 {
2990     return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2991 }
2992
2993
2994 static  FP mhl_action (name)
2995 char   *name;
2996 {
2997     int     msgnum;
2998
2999     if ((msgnum = m_atoi (name)) < mp -> lowmsg
3000             || msgnum > mp -> hghmsg
3001             || !(mp -> msgstats[msgnum] & EXISTS))
3002         return NULL;
3003     mhlnum = msgnum;
3004
3005     mhlfp = msh_ready (msgnum, 1);
3006     if (!fmsh)
3007         m_eomsbr (eom_action);
3008
3009     return mhlfp;
3010 }
3011
3012
3013 /* \f */
3014
3015 static  ask (msgnum)
3016 int     msgnum;
3017 {
3018     char    buf[BUFSIZ];
3019
3020     if (mp -> numsel == 1 || !interactive || redirected)
3021         return DONE;
3022
3023     if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
3024         if (mp -> lowsel != msgnum)
3025             printf ("\n\n\n");
3026         printf ("Press <return> to list \"%d\"...", msgnum);
3027     }
3028     (void) fflush (stdout);
3029     buf[0] = 0;
3030 #ifndef BSD42
3031     (void) read (fileno (stdout), buf, sizeof buf);
3032 #else   /* BSD42 */
3033     switch (setjmp (sigenv)) {
3034         case OK: 
3035             should_intr = 1;
3036             (void) read (fileno (stdout), buf, sizeof buf);/* fall... */
3037
3038         default: 
3039             should_intr = 0;
3040             break;
3041     }
3042 #endif  /* BSD42 */
3043     if (index (buf, '\n') == NULL)
3044         (void) putchar ('\n');
3045
3046     if (told_to_quit) {
3047         told_to_quit = interrupted = 0;
3048         return NOTOK;
3049     }
3050     if (interrupted) {
3051         interrupted = 0;
3052         return OK;
3053     }
3054
3055     return DONE;
3056 }
3057
3058 /* \f */
3059
3060 #ifdef  MIME
3061 #include "../h/mhn.h"
3062
3063
3064 static int  nontext (msgnum)
3065 int     msgnum;
3066 {
3067     int     result,
3068             state;
3069     register char   *bp,
3070                     *dp;
3071     char   *chset,
3072            *cp,
3073             buf[BUFSIZ],
3074             name[NAMESZ];
3075     FILE   *fp;
3076
3077     if (Msgs[msgnum].m_flags & MHNCHK)
3078         return (Msgs[msgnum].m_flags & MHNYES);
3079     Msgs[msgnum].m_flags |= MHNCHK;
3080
3081     fp = msh_ready (msgnum, 1);
3082
3083     if (!(chset = getenv ("MM_CHARSET")))
3084         chset = "us-ascii";
3085
3086     for (state = FLD;;)
3087         switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
3088             case FLD:
3089             case FLDPLUS:
3090             case FLDEOF:
3091                 if (uleq (name, TYPE_FIELD)) {
3092                     int     passno;
3093                     char    c;
3094
3095                     cp = add (buf, NULLCP);
3096                     while (state == FLDPLUS) {
3097                         state = m_getfld (state, name, buf, sizeof buf, fp);
3098                         cp = add (buf, cp);
3099                     }
3100                     bp = cp;
3101                     passno = 1;
3102
3103 again: ;
3104                     for (; isspace (*bp); bp++)
3105                         continue;
3106                     if (*bp == '(') {
3107                         int     i;
3108
3109                         for (bp++, i = 0;;) {
3110                             switch (*bp++) {
3111                                 case '\0':
3112 invalid: ;
3113                                     result = 0;
3114                                     goto out;
3115                                 case '\\':
3116                                     if (*bp++ == '\0')
3117                                         goto invalid;
3118                                     continue;
3119                                 case '(':
3120                                     i++;
3121                                     /* and fall... */
3122                                 default:
3123                                     continue;
3124                                 case ')':
3125                                     if (--i < 0)
3126                                         break;
3127                                 continue;
3128                             }
3129                             break;
3130                         }
3131                     }
3132                     if (passno == 2) {
3133                         if (*bp != '/')
3134                             goto invalid;
3135                         bp++;
3136                         passno = 3;
3137                         goto again;
3138                     }
3139                     for (dp = bp; istoken (*dp); dp++)
3140                         continue;
3141                     c = *dp, *dp = NULL;
3142                     if (*bp == NULL)
3143                         goto invalid;
3144                     if (passno > 1) {
3145                         if (result = !uleq (bp, "plain"))
3146                             goto out;
3147                         *dp = c;
3148                         for (dp++; isspace (*dp); dp++)
3149                             continue;
3150                         if (result = !uprf (dp, "charset"))
3151                             goto invalid;
3152                         dp += sizeof "charset" - 1;
3153                         while (isspace (*dp))
3154                             dp++;
3155                         if (*dp++ != '=')
3156                             goto invalid;
3157                         while (isspace (*dp))
3158                             dp++;
3159                         if (*dp == '"') {
3160                             if (bp = index (++dp, '"'))
3161                                 *bp = NULL;
3162                         }
3163                         else
3164                             for (bp = dp; *bp; bp++)
3165                                 if (isspace (*bp)) {
3166                                     *bp = NULL;
3167                                     break;
3168                                 }
3169                         if ((result = !uleq (dp, chset))
3170                                 && uleq (dp, "us-ascii")
3171                                 && uleq (chset, "iso-8859-1"))
3172                             result = 0;
3173                     }
3174                     else
3175                         if (!(result = !uleq (bp, "text"))) {
3176                             *dp = c;
3177                             bp = dp;
3178                             passno = 2;
3179                             goto again;
3180                         }
3181
3182 out: ;
3183                     free (cp);
3184
3185                     if (result) {
3186                         Msgs[msgnum].m_flags |= MHNYES;
3187                         return result;
3188                     }
3189                     break;
3190                 }
3191                 if (uleq (name, ENCODING_FIELD)) {
3192                     cp = add (buf, NULLCP);
3193                     while (state == FLDPLUS) {
3194                         state = m_getfld (state, name, buf, sizeof buf, fp);
3195                         cp = add (buf, cp);
3196                     }
3197                     for (bp = cp; isspace (*bp); bp++)
3198                         continue;
3199                     for (dp = bp; istoken (*dp); dp++)
3200                         continue;
3201                     *dp = NULL;
3202                     result = !uleq (bp, "7bit")
3203                                 && !uleq (bp, "8bit")
3204                                 && !uleq (bp, "binary");
3205
3206                     free (cp);
3207                     if (result) {
3208                         Msgs[msgnum].m_flags |= MHNYES;
3209                         return result;
3210                     }
3211                     break;
3212                 }
3213                 while (state == FLDPLUS)
3214                     state = m_getfld (state, name, buf, sizeof buf, fp);
3215                 break;
3216
3217             default:
3218                 return 0;
3219         }
3220 }
3221 #endif  /* MIME */
3222
3223 /* \f */
3224
3225 static struct swit sortswit[] = {
3226 #define SODATE  0
3227     "datefield field", 0,
3228 #define SOSUBJ  1
3229     "textfield field", 0,
3230 #define SONSUBJ 2
3231     "notextfield", 0,
3232 #define SOLIMT  3
3233     "limit days", 0,
3234 #define SONLIMT 4
3235     "nolimit", 0,
3236 #define SOVERB  5
3237     "verbose", 0,
3238 #define SONVERB 6
3239     "noverbose", 0,
3240 #define SOHELP  7
3241     "help", 4,
3242
3243     NULL, 0
3244 };
3245
3246 /* \f */
3247
3248 sortcmd (args)
3249 char  **args;
3250 {
3251     int     msgp = 0,
3252             msgnum;
3253     char   *cp,
3254            *datesw = NULL,
3255            *subjsw = NULL,
3256             buf[BUFSIZ],
3257            *msgs[MAXARGS];
3258     struct tws  tb,
3259                *tw;
3260
3261     if (fmsh) {
3262         forkcmd (args, cmd_name);
3263         return;
3264     }
3265
3266     while (cp = *args++) {
3267         if (*cp == '-')
3268             switch (smatch (++cp, sortswit)) {
3269                 case AMBIGSW: 
3270                     ambigsw (cp, sortswit);
3271                     return;
3272                 case UNKWNSW: 
3273                     fprintf (stderr, "-%s unknown\n", cp);
3274                     return;
3275                 case SOHELP: 
3276                     (void) sprintf (buf, "%s [msgs] [switches]", cmd_name);
3277                     help (buf, sortswit);
3278                     return;
3279
3280                 case SODATE: 
3281                     if (datesw) {
3282                         advise (NULLCP, "only one date field at a time!");
3283                         return;
3284                     }
3285                     if (!(datesw = *args++) || *datesw == '-') {
3286                         advise (NULLCP, "missing argument to %s", args[-2]);
3287                         return;
3288                     }
3289                     continue;
3290
3291                 case SOSUBJ:
3292                     if (subjsw) {
3293                         advise (NULLCP, "only one text field at a time!");
3294                         return;
3295                     }
3296                     if (!(subjsw = *args++) || *subjsw == '-') {
3297                         advise (NULLCP, "missing argument to %s", args[-2]);
3298                         return;
3299                     }
3300                     continue;
3301                 case SONSUBJ:
3302                     subjsw = (char *)0;
3303                     continue;
3304
3305                 case SOLIMT:            /* too hard */
3306                     if (!(cp = *args++) || *cp == '-') {
3307                         advise (NULLCP, "missing argument to %s", args[-2]);
3308                         return;
3309                     }
3310                 case SONLIMT:
3311                 case SOVERB:            /* not implemented */
3312                 case SONVERB: 
3313                     continue;
3314             }
3315         if (*cp == '+' || *cp == '@@') {
3316             advise (NULLCP, "sorry, no folders allowed!");
3317             return;
3318         }
3319         else
3320             msgs[msgp++] = cp;
3321     }
3322
3323     if (!msgp)
3324         msgs[msgp++] = "all";
3325     if (!datesw)
3326         datesw = "Date";
3327     for (msgnum = 0; msgnum < msgp; msgnum++)
3328         if (!m_convert (mp, msgs[msgnum]))
3329             return;
3330     m_setseq (mp);
3331
3332     twscopy (&tb, dtwstime ());
3333
3334     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
3335         if (Msgs[msgnum].m_scanl) {
3336             free (Msgs[msgnum].m_scanl);
3337             Msgs[msgnum].m_scanl = NULL;
3338         }
3339         if (mp -> msgstats[msgnum] & SELECTED) {
3340             if (getws (datesw, subjsw, msgnum, &Msgs[msgnum]))
3341                 twscopy (&Msgs[msgnum].m_tb,
3342                         msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
3343         }
3344         else                    /* m_scaln is already NULL */
3345             twscopy (&Msgs[msgnum].m_tb, &tb);
3346         Msgs[msgnum].m_stats = mp -> msgstats[msgnum];
3347         if (mp -> curmsg == msgnum)
3348             Msgs[msgnum].m_stats |= CUR;
3349     }
3350
3351     qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1,
3352             sizeof (struct Msg),
3353             subjsw ? subsort : msgsort);
3354
3355     for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) {
3356         if (subjsw && Msgs[msgnum].m_scanl) {
3357             free (Msgs[msgnum].m_scanl);        /* from subjsort */
3358             Msgs[msgnum].m_scanl = NULL;
3359         }
3360         mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR;
3361         if (Msgs[msgnum].m_stats & CUR)
3362             m_setcur (mp, msgnum);
3363     }
3364             
3365     mp -> msgflags |= MODIFIED;
3366     modified++;
3367 }
3368
3369 /* \f */
3370
3371 /* 
3372  * getws - parse message, and get date and subject if needed.  We'll use
3373  * the msgp->m_tb tws struct for the date, and overload the msgp->m_scanl
3374  * field with our subject string.
3375  */
3376 static int   getws (datesw, subjsw, msgnum, msgp)
3377 char   *datesw,
3378        *subjsw;
3379 int     msgnum;
3380 struct  Msg     *msgp;
3381 {
3382     int     state,
3383             gotdate = 0;
3384     char   *bp,
3385             buf[BUFSIZ],
3386             name[NAMESZ];
3387     struct tws *tw = (struct tws *)0;
3388     register FILE *zp;
3389
3390     zp = msh_ready (msgnum, 0);
3391     for (state = FLD;;) {
3392         switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
3393             case FLD: 
3394             case FLDEOF: 
3395             case FLDPLUS: 
3396                 if (uleq (name, datesw)) {
3397                     bp = getcpy (buf);
3398                     while (state == FLDPLUS) {
3399                         state = m_getfld (state, name, buf, sizeof buf, zp);
3400                         bp = add (buf, bp);
3401                     }
3402                     if ((tw = dparsetime (bp)) == NULL)
3403                         admonish (NULLCP,
3404                                 "unable to parse %s field in message %d",
3405                                 datesw, msgnum);
3406                     else
3407                         twscopy (&(msgp->m_tb), tw);
3408                     free (bp);
3409                     if (!subjsw)        /* not using this, or already done */
3410                         break;          /* all done! */
3411                     gotdate++;
3412                 }
3413                 else if (subjsw && uleq(name, subjsw)) {
3414                     bp = getcpy (buf);
3415                     while (state == FLDPLUS) {
3416                         state = m_getfld (state, name, buf, sizeof buf, zp);
3417                         bp = add (buf, bp);
3418                     }
3419                     msgp->m_scanl = sosmash(subjsw, bp);
3420                     if (gotdate)
3421                         break;          /* date done so we're done */
3422                     else
3423                         subjsw = (char *)0;/* subject done, need date */
3424                 } else {
3425                     while (state == FLDPLUS)    /* flush this one */
3426                         state = m_getfld (state, name, buf, sizeof buf, zp);
3427                 }
3428                 continue;
3429
3430             case BODY: 
3431             case BODYEOF: 
3432             case FILEEOF: 
3433                 break;
3434
3435             case LENERR: 
3436             case FMTERR: 
3437                 admonish (NULLCP, "format error in message %d", msgnum);
3438                 if (msgp->m_scanl) {    /* this might need free'd */
3439                     free (msgp->m_scanl); /* probably can't use subj anyway */
3440                     msgp->m_scanl = NULL;
3441                 }
3442                 return NOTOK;
3443
3444             default: 
3445                 adios (NULLCP, "internal error -- you lose");
3446         }
3447         break;
3448     }
3449     if (tw)
3450         return OK;      /* not an error if subj not found */
3451
3452     admonish (NULLCP, "no %s field in message %d", datesw, msgnum);
3453     return NOTOK;       /* NOTOK means use some other date */
3454 }
3455
3456 /* sort routines */
3457
3458 static int  msgsort (a, b)
3459 struct Msg *a,
3460            *b;
3461 {
3462     return twsort (&a -> m_tb, &b -> m_tb);
3463 }
3464
3465 static int  subsort (a, b)
3466 struct Msg *a,
3467            *b;
3468 {
3469         register int i;
3470
3471         if (a->m_scanl && b->m_scanl)
3472             if (i = strcmp (a->m_scanl, b->m_scanl))
3473                 return (i);
3474
3475         return twsort (&a -> m_tb, &b -> m_tb);
3476 }
3477
3478 /*
3479  * try to make the subject "canonical": delete leading "re:", everything
3480  * but letters & smash letters to lower case. 
3481  */
3482 static char *
3483 sosmash (subj, s)
3484 char *subj;
3485 register char *s;
3486 {
3487     register char  *cp,
3488                    *dp,
3489                     c;
3490     if (s) {
3491         cp = s;
3492         dp = s; /* dst pointer */
3493         if (uleq (subj, "subject"))
3494             while (c = *cp) {
3495                 if (! isspace(c)) {
3496                     if(uprf(cp, "re:"))
3497                         cp += 2;
3498                     else {
3499                         if (isalnum(c))
3500                             *dp++ = isupper(c) ? tolower(c) : c;
3501                         break;
3502                     }
3503                 }
3504                 cp++;
3505             }
3506         while (c = *cp++) {
3507             if (isalnum(c))
3508                 *dp++ = isupper(c) ? tolower(c) : c;
3509
3510         }
3511         *dp = '\0';
3512     }
3513     return s;
3514 }
3515
3516 /* \f */
3517
3518 static int  process (msgnum, proc, vecp, vec)
3519 int     msgnum,
3520         vecp;
3521 char   *proc,
3522       **vec;
3523 {
3524     int     child_id,
3525             status;
3526     char    tmpfil[80];
3527     FILE   *out;
3528
3529     if (fmsh) {
3530         (void) strcpy (tmpfil, m_name (msgnum));
3531         (void) m_delete (pfolder);
3532         m_replace (pfolder, fmsh);
3533         m_sync (mp);
3534         m_update ();
3535         goto ready;
3536     }
3537
3538     (void) strcpy (tmpfil, m_scratch ("", invo_name));
3539     if ((out = fopen (tmpfil, "w")) == NULL) {
3540         int     olderr;
3541         extern int  errno;
3542         char    newfil[80];
3543
3544         olderr = errno;
3545         (void) strcpy (newfil, m_tmpfil (invo_name));
3546         if ((out = fopen (newfil, "w")) == NULL) {
3547             errno = olderr;
3548             advise (tmpfil, "unable to create temporary file");
3549             return NOTOK;
3550         }
3551         else
3552             (void) strcpy (tmpfil, newfil);
3553     }
3554     copy_message (msgnum, out);
3555     (void) fclose (out);
3556
3557 ready: ;
3558     (void) fflush (stdout);
3559     switch (child_id = fork ()) {
3560         case NOTOK: 
3561             advise ("fork", "unable to");
3562             status = NOTOK;
3563             break;
3564             
3565         case OK: 
3566             closefds (3);
3567             (void) signal (SIGINT, istat);
3568             (void) signal (SIGQUIT, qstat);
3569
3570             vec[vecp++] = tmpfil;
3571             vec[vecp] = NULL;
3572
3573             execvp (proc, vec);
3574             fprintf (stderr, "unable to exec ");
3575             perror (proc);
3576             _exit (1);
3577
3578         default: 
3579             status = pidXwait (child_id, NULLCP);
3580             break;
3581     }
3582
3583     if (!fmsh)
3584         (void) unlink (tmpfil);
3585     return status;
3586 }
3587
3588 /* \f */
3589
3590 static  copy_message (msgnum, out)
3591 int     msgnum;
3592 FILE * out;
3593 {
3594     long    pos;
3595     static char buffer[BUFSIZ];
3596     register    FILE * zp;
3597
3598     zp = msh_ready (msgnum, 1);
3599     if (fmsh) {
3600         while (fgets (buffer, sizeof buffer, zp) != NULL) {
3601             fputs (buffer, out);
3602             if (interrupted && out == stdout)
3603                 break;
3604         }
3605     }
3606     else {
3607         pos = ftell (zp);
3608         while (fgets (buffer, sizeof buffer, zp) != NULL
3609                 && pos < Msgs[msgnum].m_stop) {
3610             fputs (buffer, out);
3611             pos += (long) strlen (buffer);
3612             if (interrupted && out == stdout)
3613                 break;
3614         }
3615     }
3616 }
3617
3618
3619 static  copy_digest (msgnum, out)
3620 int     msgnum;
3621 FILE * out;
3622 {
3623     char    c;
3624     long    pos;
3625     static char buffer[BUFSIZ];
3626     register FILE *zp;
3627
3628     c = '\n';
3629     zp = msh_ready (msgnum, 1);
3630     if (!fmsh)
3631         pos = ftell (zp);
3632     while (fgets (buffer, sizeof buffer, zp) != NULL
3633             && !fmsh && pos < Msgs[msgnum].m_stop) {
3634         if (c == '\n' && *buffer == '-')
3635             (void) fputc (' ', out);
3636         fputs (buffer, out);
3637         c = buffer[strlen (buffer) - 1];
3638         if (!fmsh)
3639             pos += (long) strlen (buffer);
3640         if (interrupted && out == stdout)
3641             break;
3642     }
3643 }
3644 @
3645
3646
3647 1.31
3648 log
3649 @mime changes from mtr
3650 @
3651 text
3652 @d3 1
3653 a3 1
3654 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.30 1995/12/06 23:44:31 jromine Exp jromine $";
3655 d2570 1
3656 a2570 1
3657                         headersw ? (fmsh ? fmsh : mp -> foldpath) : (char *)0,
3658 @
3659
3660
3661 1.30
3662 log
3663 @null ptr fix
3664 @
3665 text
3666 @d3 1
3667 a3 1
3668 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.29 1994/04/21 18:20:50 jromine Exp jromine $";
3669 d26 3
3670 d914 1
3671 a944 2
3672                 case FOMISW: 
3673                 case FONMISW: 
3674 d947 10
3675 d980 1
3676 d1022 1
3677 a1022 1
3678     forw (cmd_name, filter, vecp, vec);
3679 d1030 3
3680 a1032 2
3681 static  forw (proc, filter, vecp, vec)
3682 int     vecp;
3683 d1044 4
3684 d1082 139
3685 d1260 20
3686 d1293 3
3687 d2570 1
3688 a2570 1
3689                         headersw, fmsh ? fmsh : mp -> foldpath,
3690 d2974 1
3691 a2974 1
3692                             goto out;
3693 @
3694
3695
3696 1.29
3697 log
3698 @update for scansbr.c -- overload {folder}.c_flags with hdrflg
3699 @
3700 text
3701 @d3 1
3702 a3 1
3703 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.28 1993/12/01 03:50:31 jromine Exp jromine $";
3704 d1340 1
3705 d1346 1
3706 a1346 1
3707                         m_seq (mp, mp -> msgattrs[i]));
3708 d1349 3
3709 a1351 1
3710                 printf ("%s%s: %s\n", seqs[seqp], m_seq (mp, seqs[seqp]));
3711 @
3712
3713
3714 1.28
3715 log
3716 @fixes from mtr
3717 @
3718 text
3719 @d3 1
3720 a3 1
3721 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.27 1993/10/26 20:09:54 jromine Exp jromine $";
3722 d2387 1
3723 a2387 1
3724                         headersw ? (fmsh ? fmsh : mp -> foldpath) : (char *)0,
3725 @
3726
3727
3728 1.27
3729 log
3730 @test for iso-8859-1 and us-ascii, 8bit, binary and 7bit
3731 @
3732 text
3733 @d3 1
3734 a3 1
3735 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.25 1992/12/15 00:20:22 jromine Exp $";
3736 a22 1
3737 #include "../h/mshsbr.h"
3738 d25 1
3739 @
3740
3741
3742 1.26
3743 log
3744 @re-order mshsbr.h include
3745 @
3746 text
3747 @d3 1
3748 a3 1
3749 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.25 1992/12/15 00:20:22 jromine Exp jromine $";
3750 d23 1
3751 a25 1
3752 #include "../h/mshsbr.h"
3753 d2711 2
3754 a2712 1
3755     char   *cp,
3756 d2723 3
3757 d2800 1
3758 a2800 3
3759                             dp++;
3760                             if (strlen (dp) >= sizeof "us-ascii\""
3761                                     && *(bp = dp + sizeof "us-ascii" - 1)=='"')
3762 d2804 9
3763 a2812 5
3764                             if (strlen (dp) >= sizeof "us-ascii"
3765                                     && isspace (*(bp =
3766                                                 dp + sizeof "us-ascii" - 1)))
3767                                 *bp = NULL;
3768                         result = !uleq (dp, "us-ascii");
3769 d2842 3
3770 a2844 2
3771                     if (result = !uleq (bp, "7bit"))
3772                             Msgs[msgnum].m_flags |= MHNYES;
3773 @
3774
3775
3776 1.25
3777 log
3778 @endif sugar
3779 @
3780 text
3781 @d3 1
3782 a3 1
3783 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.24 1992/11/24 18:26:05 jromine Exp jromine $";
3784 a22 1
3785 #include "../h/mshsbr.h"
3786 d25 1
3787 @
3788
3789
3790 1.24
3791 log
3792 @add decl
3793 @
3794 text
3795 @d3 2
3796 a4 2
3797 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.23 1992/11/04 00:53:32 jromine Exp jromine $";
3798 #endif  lint
3799 d859 1
3800 a859 1
3801 #else   MIME
3802 d861 1
3803 a861 1
3804 #endif  MIME
3805 d1301 1
3806 a1301 1
3807 #else   MTR
3808 d1304 1
3809 a1304 1
3810 #endif  MTR
3811 d2672 1
3812 a2672 1
3813 #else   BSD42
3814 d2682 1
3815 a2682 1
3816 #endif  BSD42
3817 @
3818
3819
3820 1.23
3821 log
3822 @locale
3823 @
3824 text
3825 @d3 1
3826 a3 1
3827 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.22 1992/10/29 03:49:31 jromine Exp jromine $";
3828 d42 3
3829 @
3830
3831
3832 1.22
3833 log
3834 @fix burst -- previously it was losing the last message(!)
3835 @
3836 text
3837 @d3 1
3838 a3 1
3839 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.21 1992/10/26 22:21:33 jromine Exp jromine $";
3840 d3124 1
3841 a3124 1
3842             while (c = *cp++) {
3843 d3126 1
3844 a3126 2
3845                     if ((c == 'R' || c == 'r') &&
3846                             (cp[0] == 'e' || cp[0] == 'E') && cp[1] == ':')
3847 d3134 1
3848 @
3849
3850
3851 1.21
3852 log
3853 @turn off MPOP if NNTP on
3854 @
3855 text
3856 @d3 1
3857 a3 1
3858 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.20 1992/10/17 00:24:25 jromine Exp jromine $";
3859 d355 1
3860 d367 1
3861 a367 1
3862     for (msgp = 1; msgp <= MAXFOLDER;) {
3863 d378 2
3864 a379 2
3865                 fgets (buffer, sizeof buffer, zp) != NULL
3866                 && pos < Msgs[msgnum].m_stop;
3867 d382 2
3868 a383 2
3869                     && peekc (zp) == '\n'
3870                     && (msgp == 1 || c == '\n'))
3871 d390 1
3872 a390 1
3873             smsgs[msgp++].m_stop = c == '\n' && wasdlm ? pos - 1 : pos;
3874 d392 1
3875 a392 1
3876             if (wasdlm) {
3877 a393 2
3878                 msgp++;         /* fake "End of XXX Digest" */
3879             }
3880 d399 1
3881 a399 1
3882     switch (--msgp) {           /* toss "End of XXX Digest" */
3883 d411 1
3884 a411 3
3885                         msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum);
3886             if (msgp == 2)
3887                 msgp++;
3888 a414 1
3889     msgp--;
3890 d423 2
3891 a424 2
3892     mp -> hghmsg += msgp - 1;
3893     mp -> nummsg += msgp - 1;
3894 d426 1
3895 a426 1
3896         mp -> hghsel += msgp - 1;
3897 d428 1
3898 a428 1
3899     if (inplace && msgp > 1)
3900 d449 2
3901 a450 2
3902     i = inplace ? msgnum + msgp - 1 : mp -> hghmsg;
3903     for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) {
3904 @
3905
3906
3907 1.20
3908 log
3909 @#ifdef botch
3910 @
3911 text
3912 @d3 1
3913 a3 1
3914 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.19 1992/10/17 00:19:58 jromine Exp jromine $";
3915 d51 3
3916 @
3917
3918
3919 1.19
3920 log
3921 @typo
3922 @
3923 text
3924 @d3 1
3925 a3 1
3926 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.18 1992/10/16 22:34:17 jromine Exp jromine $";
3927 d2316 1
3928 d2321 1
3929 @
3930
3931
3932 1.18
3933 log
3934 @MIME changes
3935 @
3936 text
3937 @d3 1
3938 a3 1
3939 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.17 1992/10/16 21:50:20 jromine Exp jromine $";
3940 a2178 7
3941
3942 #ifdef  MPOP
3943 #ifdef  BPOP
3944 extern  int     pmsh;
3945 extern  char    response[];
3946 #endif
3947 #endif /* MPOP */
3948 @
3949
3950
3951 1.17
3952 log
3953 @#ifdef MIME
3954 @
3955 text
3956 @d3 1
3957 a3 1
3958 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.16 1992/10/16 21:47:40 jromine Exp jromine $";
3959 d2543 1
3960 a2543 1
3961     if (!nshow && (cp = m_find ("mhnproc")) && !getenv ("NOMHNPROC"))
3962 d2546 1
3963 a2546 1
3964                 proc = cp;
3965 d2710 6
3966 a2715 2
3967     int     state;
3968     char    buf[BUFSIZ],
3969 d2731 2
3970 a2732 6
3971                     int     passno,
3972                             result;
3973                     register char   *bp,
3974                                     *dp;
3975                     char    c,
3976                            *cp;
3977 d2768 1
3978 a2768 1
3979                             break;                          
3980 d2780 2
3981 a2781 2
3982                     c = *dp, *dp = '\0';
3983                     if (*bp == '\0')
3984 d2785 25
3985 a2809 1
3986                             Msgs[msgnum].m_flags |= MHNYES;
3987 d2822 26
3988 a2847 1
3989                     return result;
3990 @
3991
3992
3993 1.16
3994 log
3995 @#ifdef MIME
3996 @
3997 text
3998 @d3 1
3999 a3 1
4000 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.15 1992/10/16 21:37:18 jromine Exp jromine $";
4001 d2542 1
4002 d2552 1
4003 @
4004
4005
4006 1.15
4007 log
4008 @MIME changes
4009 @
4010 text
4011 @d3 1
4012 a3 1
4013 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.14 1992/10/16 16:51:55 jromine Exp jromine $";
4014 d2701 1
4015 d2806 1
4016 @
4017
4018
4019 1.14
4020 log
4021 @mobile pop (MPOP) ifdefs
4022 @
4023 text
4024 @d3 1
4025 a3 1
4026 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.13 1992/05/19 21:03:35 jromine Exp jromine $";
4027 d855 6
4028 d888 5
4029 a892 1
4030 #define FOWHTSW 13
4031 d894 1
4032 a894 1
4033 #define FONWTSW 14
4034 d896 1
4035 a896 1
4036 #define FOHELP  15
4037 d939 2
4038 d1368 170
4039 @
4040
4041
4042 1.13
4043 log
4044 @AIX
4045 @
4046 text
4047 @d3 1
4048 a3 1
4049 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.12 1992/03/03 17:09:57 jromine Exp jromine $";
4050 d51 1
4051 a51 1
4052
4053 d56 1
4054 d1941 1
4055 d1946 1
4056 d1998 1
4057 d2003 1
4058 a2004 1
4059
4060 d2024 1
4061 d2028 1
4062 d2107 1
4063 d2179 1
4064 d2189 1
4065 d2202 1
4066 @
4067
4068
4069 1.12
4070 log
4071 @fixes from mtr
4072 @
4073 text
4074 @d3 1
4075 a3 1
4076 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.11 1992/02/08 00:10:26 jromine Exp jromine $";
4077 d2555 1
4078 a2555 1
4079                                 case NULL:
4080 d2560 1
4081 a2560 1
4082                                     if (*bp++ == NULL)
4083 d2585 2
4084 a2586 2
4085                     c = *dp, *dp = NULL;
4086                     if (*bp == NULL)
4087 @
4088
4089
4090 1.11
4091 log
4092 @fixes from mrose
4093 @
4094 text
4095 @d3 1
4096 a3 1
4097 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.10 1992/02/05 07:26:30 jromine Exp jromine $";
4098 d51 6
4099 d1940 4
4100 @
4101
4102
4103 1.10
4104 log
4105 @put unseen sequence in mh-format
4106 @
4107 text
4108 @d3 1
4109 a3 1
4110 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.9 1992/01/31 22:19:11 jromine Exp jromine $";
4111 d2127 35
4112 @
4113
4114
4115 1.9
4116 log
4117 @kerberos
4118 @
4119 text
4120 @d3 1
4121 a3 1
4122 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.8 1992/01/31 16:33:46 jromine Exp jromine $";
4123 d1985 6
4124 d2010 3
4125 d2090 34
4126 d2136 13
4127 d2151 2
4128 a2152 1
4129                         msgnum == mp -> curmsg, 
4130 @
4131
4132
4133 1.8
4134 log
4135 @Multimedia MH
4136 @
4137 text
4138 @d3 1
4139 a3 1
4140 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.7 1992/01/23 22:58:03 jromine Exp $";
4141 d11 3
4142 d15 3
4143 d125 1
4144 a125 1
4145     NULL, NULL
4146 d231 1
4147 a231 1
4148     NULL, NULL
4149 d366 1
4150 a366 1
4151         for (c = NULL;
4152 d484 1
4153 a484 1
4154     NULL, NULL
4155 d661 1
4156 a661 1
4157     NULL, NULL
4158 d746 1
4159 a746 1
4160         if (*folder == NULL) {
4161 d882 1
4162 a882 1
4163     NULL, NULL
4164 d968 1
4165 a968 1
4166     vec[0] = mktemp (buf);
4167 d1160 1
4168 a1160 1
4169     NULL, NULL
4170 d1356 1
4171 a1356 1
4172     NULL, NULL
4173 d1546 1
4174 a1546 1
4175     NULL, NULL
4176 d1749 1
4177 a1749 1
4178     NULL, NULL
4179 d1850 1
4180 a1850 1
4181     NULL, NULL
4182 d1980 1
4183 a1980 1
4184     NULL, NULL
4185 d2148 1
4186 a2148 1
4187     NULL, NULL
4188 d2376 1
4189 a2376 1
4190     buf[0] = NULL;
4191 d2532 1
4192 a2532 1
4193     NULL, NULL
4194 @
4195
4196
4197 1.7
4198 log
4199 @change call to scan(...hdrflag...)
4200 @
4201 text
4202 @d3 1
4203 a3 1
4204 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.6 1991/01/14 16:48:39 mh Exp jromine $";
4205 d2242 10
4206 d2260 1
4207 d2397 107
4208 @
4209
4210
4211 1.6
4212 log
4213 @add -[no]rmmproc to refile
4214 delete -[no]format from repl
4215 still need to add -[no]dashmunging to forw
4216 jlr
4217 @
4218 text
4219 @d3 1
4220 a3 1
4221 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.5 90/04/05 15:01:41 sources Exp Locker: mh $";
4222 d2089 2
4223 a2090 1
4224                         msgnum == mp -> curmsg, headersw,
4225 @
4226
4227
4228 1.5
4229 log
4230 @add ID
4231 @
4232 text
4233 @d3 1
4234 a3 1
4235 static char ident[] = "@@(#)$Id:$";
4236 d471 5
4237 a475 1
4238 #define FIHELP  7
4239 d530 2
4240 d1726 1
4241 a1726 5
4242 #define REFRSW  12
4243     "format", 5,
4244 #define RENFRSW 13
4245     "noformat", 7,
4246 #define REINSW  14
4247 d1728 1
4248 a1728 1
4249 #define RENINSW 15
4250 d1730 1
4251 a1730 1
4252 #define REQUSW  16
4253 d1732 1
4254 a1732 1
4255 #define RENQUSW 17
4256 d1734 1
4257 a1734 1
4258 #define REWHTSW 18
4259 d1736 1
4260 a1736 1
4261 #define RENWTSW 19
4262 d1738 1
4263 a1738 1
4264 #define REWIDSW 20
4265 d1740 1
4266 a1740 1
4267 #define REHELP  21
4268 a1781 2
4269                 case REFRSW: 
4270                 case RENFRSW: 
4271 @
4272
4273
4274 1.4
4275 log
4276 @all arbitrary textfields in sortm
4277 @
4278 text
4279 @d2 3
4280 @
4281
4282
4283 1.3
4284 log
4285 @add sortm -[no]subject and (unimplemented) -[no]limit
4286 @
4287 text
4288 @d2389 9
4289 a2397 1
4290 #define SOVERB  1
4291 d2399 1
4292 a2399 1
4293 #define SONVERB 2
4294 a2400 8
4295 #define SOSUBJ  3
4296     "subject", 0,
4297 #define SONSUBJ 4
4298     "nosubject", 0,
4299 #define SOLIMT  5
4300     "limit days", 0,
4301 #define SONLIMT 6
4302     "nolimit", 0,
4303 d2416 1
4304 a2420 1
4305     register int subjsw = 0;
4306 d2453 8
4307 a2460 1
4308                     subjsw++;
4309 d2463 1
4310 a2463 1
4311                     subjsw = 0;
4312 d2467 4
4313 d2538 3
4314 a2540 3
4315 char   *datesw;
4316 int     msgnum,
4317         subjsw; /* on entry, 0=no, 1=yes.  internal -1=date_done */
4318 d2543 2
4319 a2544 1
4320     int     state;
4321 d2572 1
4322 a2572 1
4323                     subjsw = -1;        /* now looking for subject alone */
4324 d2574 1
4325 a2574 1
4326                 else if (subjsw && uleq(name, "subject")) {
4327 d2580 2
4328 a2581 2
4329                     msgp->m_scanl = sosmash(bp);
4330                     if (subjsw < 0)
4331 d2584 1
4332 a2584 1
4333                         subjsw = 0;     /* subject done, need date */
4334 d2644 2
4335 a2645 1
4336 sosmash (s)
4337 d2654 11
4338 a2664 9
4339         while (c = *cp++) {
4340             if (! isspace(c)) {
4341                 if ((c == 'R' || c == 'r') &&
4342                         (cp[0] == 'e' || cp[0] == 'E') && cp[1] == ':')
4343                     cp += 2;
4344                 else {
4345                     if (isalpha(c))
4346                         *dp++ = islower(c) ? c : tolower(c);
4347                     break;
4348 a2666 1
4349         }
4350 d2668 2
4351 a2669 2
4352             if (isalpha(c))
4353                 *dp++ = islower(c) ? c : tolower(c);
4354 @
4355
4356
4357 1.2
4358 log
4359 @ANSI Compilance
4360 @
4361 text
4362 @d38 3
4363 a40 2
4364 static int      msgsort ();
4365 static struct tws *getws ();
4366 d2393 9
4367 a2401 1
4368 #define SOHELP  3
4369 d2420 1
4370 d2452 9
4371 d2490 3
4372 a2492 2
4373             if ((tw = getws (datesw, msgnum)) == NULL)
4374                 tw = msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb;
4375 d2494 2
4376 a2495 3
4377         else
4378             tw = &tb;
4379         twscopy (&Msgs[msgnum].m_tb, tw);
4380 d2502 2
4381 a2503 1
4382             sizeof (struct Msg), msgsort);
4383 d2506 4
4384 d2521 6
4385 a2526 1
4386 static struct tws  *getws (datesw, msgnum)
4387 d2528 3
4388 a2530 1
4389 int     msgnum;
4390 d2536 1
4391 a2536 1
4392     struct tws *tw;
4393 d2540 1
4394 a2540 1
4395     for (state = FLD;;)
4396 d2555 2
4397 d2558 3
4398 a2560 1
4399                     return tw;
4400 d2562 16
4401 a2577 4
4402                 while (state == FLDPLUS)
4403                     state = m_getfld (state, name, buf, sizeof buf, zp);
4404                 if (state != FLDEOF)
4405                     continue;
4406 d2582 1
4407 a2582 2
4408                 admonish (NULLCP, "no %s field in message %d", datesw, msgnum);
4409                 return NULL;
4410 d2587 5
4411 a2591 1
4412                 return NULL;
4413 d2596 7
4414 d2605 1
4415 d2612 49
4416 @
4417
4418
4419 1.1
4420 log
4421 @Initial revision
4422 @
4423 text
4424 @d31 2
4425 a32 2
4426 int     eom_action ();
4427 FP      mhl_action ();
4428 d35 2
4429 d38 2
4430 a39 2
4431 int     msgsort ();
4432 struct tws *getws ();
4433 @