3 * mshcmds.c -- command handlers in msh
10 #include <h/dropsbr.h>
11 #include <h/fmt_scan.h>
12 #include <h/scansbr.h>
14 #include <zotnet/mts/mts.h>
19 #include <h/picksbr.h>
23 static char delim3[] = "-------"; /* from burst.c */
28 #if defined(NNTP) && defined(MPOP)
35 extern char response[];
40 * Type for a compare function for qsort. This keeps
43 typedef int (*qsort_comp) (const void *, const void *);
48 void clear_screen (void); /* from termsbr.c */
49 int SOprintf (char *, ...); /* from termsbr.c */
50 int sc_width (void); /* from termsbr.c */
55 static int burst (struct Msg *, int, int, int, int);
56 static void forw (char *, char *, int, char **);
57 static void rmm (void);
58 static void show (int);
59 static int eom_action (int);
60 static FILE *mhl_action (char *);
62 static int is_nontext (int);
63 static int get_fields (char *, char *, int, struct Msg *);
64 static int msgsort (struct Msg *, struct Msg *);
65 static int subsort (struct Msg *, struct Msg *);
66 static char *sosmash (char *, char *);
67 static int process (int, char *, int, char **);
68 static void copy_message (int, FILE *);
69 static void copy_digest (int, FILE *);
72 int mhlsbr (int, char **, FILE *(*)());
75 forkcmd (char **args, char *pgm)
80 vec[0] = r1bindex (pgm, '/');
81 copyip (args, vec + 1, MAXARGS - 1);
84 context_del (pfolder);
85 context_replace (pfolder, fmsh);/* update current folder */
87 context_save (); /* save the context file */
90 switch (child_id = fork ()) {
92 advise ("fork", "unable to");
97 SIGNAL (SIGINT, istat);
98 SIGNAL (SIGQUIT, qstat);
101 fprintf (stderr, "unable to exec ");
106 pidXwait (child_id, NULL);
109 if (fmsh) { /* assume the worst case */
110 mp->msgflags |= MODIFIED;
116 static struct swit distswit[] = {
122 { "draftfolder +folder", 0 },
124 { "draftmessage msg", 0 },
126 { "nodraftfolder", 0 },
128 { "editor editor", 0 },
132 { "form formfile", 0 },
138 { "whatnowproc program", 0 },
140 { "nowhatnowproc", 0 },
148 distcmd (char **args)
151 char *cp, *msg = NULL;
152 char buf[BUFSIZ], *vec[MAXARGS];
155 forkcmd (args, cmd_name);
159 while ((cp = *args++)) {
161 switch (smatch (++cp, distswit)) {
163 ambigsw (cp, distswit);
166 fprintf (stderr, "-%s unknown\n", cp);
169 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
170 print_help (buf, distswit, 1);
173 case DIANSW: /* not implemented */
191 if (!(cp = *args++) || *cp == '-') {
192 advise (NULL, "missing argument to %s", args[-2]);
198 if (*cp == '+' || *cp == '@') {
199 advise (NULL, "sorry, no folders allowed!");
204 advise (NULL, "only one message at a time!");
212 vec[vecp++] = "-file";
216 if (!m_convert (mp, msg))
220 if (mp->numsel > 1) {
221 advise (NULL, "only one message at a time!");
224 process (mp->hghsel, cmd_name, vecp, vec);
225 seq_setcur (mp, mp->hghsel);
229 static struct swit explswit[] = {
249 explcmd (char **args)
251 int inplace = 0, quietsw = 0, verbosw = 0;
252 int msgp = 0, hi, msgnum;
253 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
257 forkcmd (args, cmd_name);
261 while ((cp = *args++)) {
263 switch (smatch (++cp, explswit)) {
265 ambigsw (cp, explswit);
268 fprintf (stderr, "-%s unknown\n", cp);
271 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
272 print_help (buf, explswit, 1);
294 if (*cp == '+' || *cp == '@') {
295 advise (NULL, "sorry, no folders allowed!");
303 msgs[msgp++] = "cur";
304 for (msgnum = 0; msgnum < msgp; msgnum++)
305 if (!m_convert (mp, msgs[msgnum]))
309 smsgs = (struct Msg *)
310 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
312 adios (NULL, "unable to allocate folder storage");
316 for (msgnum = mp->lowsel;
317 msgnum <= mp->hghsel && !interrupted;
319 if (is_selected (mp, msgnum))
320 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
323 free ((char *) smsgs);
326 seq_setcur (mp, mp->lowsel);
328 if (hi <= mp->hghmsg)
331 mp->msgflags |= MODIFIED;
337 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
339 int i, j, ld3, wasdlm, msgp;
341 char c, buffer[BUFSIZ];
344 ld3 = strlen (delim3);
346 if (Msgs[msgnum].m_scanl) {
347 free (Msgs[msgnum].m_scanl);
348 Msgs[msgnum].m_scanl = NULL;
351 pos = ftell (zp = msh_ready (msgnum, 1));
352 for (msgp = 0; msgp <= MAXFOLDER;) {
353 while (fgets (buffer, sizeof buffer, zp) != NULL
355 && pos < Msgs[msgnum].m_stop)
356 pos += (long) strlen (buffer);
357 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
359 fseek (zp, pos, SEEK_SET);
360 smsgs[msgp].m_start = pos;
363 pos < Msgs[msgnum].m_stop
364 && fgets (buffer, sizeof buffer, zp) != NULL;
366 if (strncmp (buffer, delim3, ld3) == 0
367 && (msgp == 1 || c == '\n')
368 && peekc (zp) == '\n')
371 pos += (long) strlen (buffer);
373 wasdlm = strncmp (buffer, delim3, ld3) == 0;
374 if (smsgs[msgp].m_start != pos)
375 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
376 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
378 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
381 pos += (long) strlen (buffer);
384 switch (msgp--) { /* toss "End of XXX Digest" */
386 adios (NULL, "burst() botch -- you lose big");
390 printf ("message %d not in digest format\n", msgnum);
395 printf ("%d message%s exploded from digest %d\n",
396 msgp, msgp != 1 ? "s" : "", msgnum);
400 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
401 advise (NULL, "more than %d messages", MAXFOLDER);
404 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
405 adios (NULL, "unable to allocate folder storage");
410 if (mp->hghsel > msgnum)
414 for (i = mp->hghmsg; j > msgnum; i--, j--) {
416 printf ("message %d becomes message %d\n", j, i);
418 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
419 Msgs[i].m_top = Msgs[j].m_top;
420 Msgs[i].m_start = Msgs[j].m_start;
421 Msgs[i].m_stop = Msgs[j].m_stop;
422 Msgs[i].m_scanl = NULL;
423 if (Msgs[j].m_scanl) {
424 free (Msgs[j].m_scanl);
425 Msgs[j].m_scanl = NULL;
427 copy_msg_flags (mp, i, j);
430 if (Msgs[msgnum].m_bboard_id == 0)
433 unset_selected (mp, msgnum);
434 i = inplace ? msgnum + msgp : mp->hghmsg;
435 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
436 if (verbosw && i != msgnum)
437 printf ("message %d of digest %d becomes message %d\n",
440 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
441 Msgs[i].m_top = Msgs[j].m_top;
442 Msgs[i].m_start = smsgs[j].m_start;
443 Msgs[i].m_stop = smsgs[j].m_stop;
444 Msgs[i].m_scanl = NULL;
445 copy_msg_flags (mp, i, msgnum);
452 static struct swit fileswit[] = {
464 { "src +folder", 0 },
468 { "rmmproc program", 0 },
478 filecmd (char **args)
480 int linksw = 0, msgp = 0;
481 int vecp = 1, i, msgnum;
482 char *cp, buf[BUFSIZ];
483 char *msgs[MAXARGS], *vec[MAXARGS];
486 forkcmd (args, cmd_name);
490 while ((cp = *args++)) {
492 switch (i = smatch (++cp, fileswit)) {
494 ambigsw (cp, fileswit);
497 fprintf (stderr, "-%s unknown\n", cp);
500 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
501 print_help (buf, fileswit, 1);
520 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
523 if (*cp == '+' || *cp == '@')
530 vec[vecp++] = "-file";
533 msgs[msgp++] = "cur";
534 for (msgnum = 0; msgnum < msgp; msgnum++)
535 if (!m_convert (mp, msgs[msgnum]))
540 for (msgnum = mp->lowsel;
541 msgnum <= mp->hghsel && !interrupted;
543 if (is_selected (mp, msgnum))
544 if (process (msgnum, fileproc, vecp, vec)) {
545 unset_selected (mp, msgnum);
549 if (mp->numsel != mp->nummsg || linksw)
550 seq_setcur (mp, mp->hghsel);
557 filehak (char **args)
559 int result, vecp = 0;
560 char *cp, *cwd, *vec[MAXARGS];
562 while ((cp = *args++)) {
564 switch (smatch (++cp, fileswit)) {
581 if (*cp == '+' || *cp == '@')
588 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
590 cwd = getcpy (pwd ());
591 chdir (m_maildir (""));
592 cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
593 if (access (m_maildir (cp), F_OK) == NOTOK)
604 static struct swit foldswit[] = {
642 foldcmd (char **args)
644 int fastsw = 0, headersw = 0, packsw = 0;
646 char *cp, *folder = NULL, *msg = NULL;
647 char buf[BUFSIZ], **vec = args;
652 while ((cp = *args++)) {
654 switch (smatch (++cp, foldswit)) {
656 ambigsw (cp, foldswit);
659 fprintf (stderr, "-%s unknown\n", cp);
662 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
663 print_help (buf, foldswit, 1);
666 case FLALSW: /* not implemented */
696 if (*cp == '+' || *cp == '@') {
698 advise (NULL, "only one folder at a time!\n");
702 folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
707 advise (NULL, "only one message at a time!\n");
716 advise (NULL, "null folder names are not permitted");
720 if (access (m_maildir (folder), R_OK) == NOTOK) {
721 advise (folder, "unable to read");
726 strncpy (buf, folder, sizeof(buf));
727 if (expand (buf) == NOTOK)
730 if (access (folder, R_OK) == NOTOK) {
731 advise (folder, "unable to read");
746 if (!m_convert (mp, msg))
750 if (mp->numsel > 1) {
751 advise (NULL, "only one message at a time!");
754 seq_setcur (mp, mp->hghsel);
759 forkcmd (vec, cmd_name);
763 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
764 adios (NULL, "unable to allocate folder storage");
766 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
767 if (does_exist (mp, msgnum)) {
768 if (msgnum != hole) {
769 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
770 Msgs[hole].m_top = Msgs[msgnum].m_top;
771 Msgs[hole].m_start = Msgs[msgnum].m_start;
772 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
773 Msgs[hole].m_scanl = NULL;
774 if (Msgs[msgnum].m_scanl) {
775 free (Msgs[msgnum].m_scanl);
776 Msgs[msgnum].m_scanl = NULL;
778 copy_msg_flags (mp, hole, msgnum);
779 if (mp->curmsg == msgnum)
780 seq_setcur (mp, hole);
784 if (mp->nummsg > 0) {
786 mp->hghmsg = hole - 1;
788 mp->msgflags |= MODIFIED;
794 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
797 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
798 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
800 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
802 /* check for empty folder */
803 if (mp->nummsg == 0) {
804 printf ("has no messages%*s",
805 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
807 printf ("has %*d message%s (%*d-%*d)",
808 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
809 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
810 if (mp->curmsg >= mp->lowmsg
811 && mp->curmsg <= mp->hghmsg)
812 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
819 static struct swit forwswit[] = {
825 { "draftfolder +folder", 0 },
827 { "draftmessage msg", 0 },
829 { "nodraftfolder", 0 },
831 { "editor editor", 0 },
835 { "filter filterfile", 0 },
837 { "form formfile", 0 },
851 { "whatnowproc program", 0 },
861 forwcmd (char **args)
863 int msgp = 0, vecp = 1, msgnum;
864 char *cp, *filter = NULL, buf[BUFSIZ];
865 char *msgs[MAXARGS], *vec[MAXARGS];
868 forkcmd (args, cmd_name);
872 while ((cp = *args++)) {
874 switch (smatch (++cp, forwswit)) {
876 ambigsw (cp, forwswit);
879 fprintf (stderr, "-%s unknown\n", cp);
882 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
883 print_help (buf, forwswit, 1);
886 case FOANSW: /* not implemented */
906 if (!(cp = *args++) || *cp == '-') {
907 advise (NULL, "missing argument to %s", args[-2]);
913 if (!(filter = *args++) || *filter == '-') {
914 advise (NULL, "missing argument to %s", args[-2]);
919 if (access (filter = myfilter, R_OK) == NOTOK) {
920 advise (filter, "unable to read default filter file");
928 if (*cp == '+' || *cp == '@') {
929 advise (NULL, "sorry, no folders allowed!");
936 /* foil search of .mh_profile */
937 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
939 Mkstemp work postponed until later -Doug
941 vec[0] = (char *)mkstemp (buf);
944 vec[0] = (char *)mktemp (buf);
948 vec[vecp++] = "-file";
951 msgs[msgp++] = "cur";
952 for (msgnum = 0; msgnum < msgp; msgnum++)
953 if (!m_convert (mp, msgs[msgnum]))
958 strncpy (buf, filter, sizeof(buf));
959 if (expand (buf) == NOTOK)
961 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
962 advise (filter, "unable to read");
967 forw (cmd_name, filter, vecp, vec);
968 seq_setcur (mp, mp->hghsel);
975 forw (char *proc, char *filter, int vecp, char **vec)
977 int i, child_id, msgnum, msgcnt;
978 char tmpfil[80], *args[MAXARGS];
981 strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
984 switch (child_id = fork ()) {
986 advise ("fork", "unable to");
989 case OK: /* "trust me" */
990 if (freopen (tmpfil, "w", stdout) == NULL) {
991 fprintf (stderr, "unable to create ");
995 args[0] = r1bindex (mhlproc, '/');
997 args[i++] = "-forwall";
1000 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1001 if (is_selected (mp, msgnum))
1002 args[i++] = getcpy (m_name (msgnum));
1004 mhlsbr (i, args, mhl_action);
1005 m_eomsbr ((int (*) ()) 0);
1010 if (pidXwait (child_id, NULL))
1015 if ((out = fopen (tmpfil, "w")) == NULL) {
1016 advise (tmpfil, "unable to create temporary file");
1021 for (msgnum = mp->lowsel;
1022 msgnum <= mp->hghsel && !interrupted;
1024 if (is_selected (mp, msgnum)) {
1025 fprintf (out, "\n\n-------");
1026 if (msgnum == mp->lowsel)
1027 fprintf (out, " Forwarded Message%s",
1028 mp->numsel > 1 ? "s" : "");
1030 fprintf (out, " Message %d", msgcnt);
1031 fprintf (out, "\n\n");
1032 copy_digest (msgnum, out);
1036 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1037 mp->numsel > 1 ? "s" : "");
1043 switch (child_id = fork ()) {
1045 advise ("fork", "unable to");
1050 SIGNAL (SIGINT, istat);
1051 SIGNAL (SIGQUIT, qstat);
1053 vec[vecp++] = tmpfil;
1057 fprintf (stderr, "unable to exec ");
1062 pidXwait (child_id, NULL);
1070 static char *hlpmsg[] = {
1071 "The %s program emulates many of the commands found in the nmh",
1072 "system. Instead of operating on nmh folders, commands to %s concern",
1075 "To see the list of commands available, just type a ``?'' followed by",
1076 "the RETURN key. To find out what switches each command takes, type",
1077 "the name of the command followed by ``-help''. To leave %s, use the",
1078 "``quit'' command.",
1080 "Although a lot of nmh commands are found in %s, not all are fully",
1081 "implemented. %s will always recognize all legal switches for a",
1082 "given command though, and will let you know when you ask for an",
1083 "option that it is unable to perform.",
1085 "Running %s is fun, but using nmh from your shell is far superior.",
1086 "After you have familiarized yourself with the nmh style by using %s,",
1087 "you should try using nmh from the shell. You can still use %s for",
1088 "message files that aren't in nmh format, such as BBoard files.",
1094 helpcmd (char **args)
1098 for (i = 0; hlpmsg[i]; i++) {
1099 printf (hlpmsg[i], invo_name);
1105 static struct swit markswit[] = {
1113 { "sequence name", 0 },
1131 markcmd (char **args)
1133 int addsw = 0, deletesw = 0, debugsw = 0;
1134 int listsw = 0, zerosw = 0, seqp = 0;
1135 int msgp = 0, msgnum;
1136 char *cp, buf[BUFSIZ];
1137 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1139 while ((cp = *args++)) {
1141 switch (smatch (++cp, markswit)) {
1143 ambigsw (cp, markswit);
1146 fprintf (stderr, "-%s unknown\n", cp);
1149 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1150 print_help (buf, markswit, 1);
1155 deletesw = listsw = 0;
1163 addsw = deletesw = 0;
1167 if (!(cp = *args++) || *cp == '-') {
1168 advise (NULL, "missing argument to %s", args[-2]);
1171 if (seqp < NUMATTRS)
1174 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1179 case MPUBSW: /* not implemented */
1195 if (*cp == '+' || *cp == '@') {
1196 advise (NULL, "sorry, no folders allowed!");
1203 if (!addsw && !deletesw && !listsw) {
1210 seqs[seqp++] = "unseen";
1214 msgs[msgp++] = "all";
1219 msgs[msgp++] = listsw ? "all" :"cur";
1220 for (msgnum = 0; msgnum < msgp; msgnum++)
1221 if (!m_convert (mp, msgs[msgnum]))
1225 printf ("invo_name=%s mypath=%s defpath=%s\n",
1226 invo_name, mypath, defpath);
1227 printf ("ctxpath=%s context flags=%s\n",
1228 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1229 printf ("foldpath=%s flags=%s\n",
1231 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1232 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1233 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1234 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1235 mp->lowsel, mp->hghsel, mp->numsel);
1236 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1239 if (seqp == 0 && (addsw || deletesw)) {
1240 advise (NULL, "-%s requires at least one -sequence argument",
1241 addsw ? "add" : "delete");
1247 for (seqp = 0; seqs[seqp]; seqp++)
1248 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1253 for (seqp = 0; seqs[seqp]; seqp++)
1254 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1258 /* Listing messages in sequences */
1261 /* list the given sequences */
1262 for (seqp = 0; seqs[seqp]; seqp++)
1263 seq_print (mp, seqs[seqp]);
1265 /* else list them all */
1271 for (msgnum = mp->lowsel;
1272 msgnum <= mp->hghsel && !interrupted;
1274 if (is_selected (mp, msgnum)) {
1275 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1278 Msgs[msgnum].m_bboard_id,
1280 (long) Msgs[msgnum].m_start,
1281 (long) Msgs[msgnum].m_stop,
1282 snprintb (buf, sizeof(buf),
1283 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1285 if (Msgs[msgnum].m_scanl)
1286 printf ("%s", Msgs[msgnum].m_scanl);
1292 static struct swit mhnswit[] = {
1295 #define MHNNAUTOSW 1
1297 #define MHNDEBUGSW 2
1299 #define MHNEBCDICSW 3
1300 { "ebcdicsafe", 0 },
1301 #define MHNNEBCDICSW 4
1302 { "noebcdicsafe", 0 },
1304 { "form formfile", 4 },
1307 #define MHNNHEADSW 7
1311 #define MHNNLISTSW 9
1313 #define MHNPARTSW 10
1314 { "part number", 0 },
1315 #define MHNSIZESW 11
1317 #define MHNNSIZESW 12
1318 { "norealsize", 0 },
1319 #define MHNRFC934SW 13
1320 { "rfc934mode", 0 },
1321 #define MHNNRFC934SW 14
1322 { "norfc934mode", 0 },
1323 #define MHNSERIALSW 15
1324 { "serialonly", 0 },
1325 #define MHNNSERIALSW 16
1326 { "noserialonly", 0 },
1327 #define MHNSHOWSW 17
1329 #define MHNNSHOWSW 18
1331 #define MHNSTORESW 19
1333 #define MHNNSTORESW 20
1335 #define MHNTYPESW 21
1336 { "type content", 0 },
1337 #define MHNVERBSW 22
1339 #define MHNNVERBSW 23
1341 #define MHNHELPSW 24
1343 #define MHNPROGSW 25
1344 { "moreproc program", -4 },
1345 #define MHNNPROGSW 26
1346 { "nomoreproc", -3 },
1348 { "length lines", -4 },
1350 { "width columns", -4 },
1356 mhncmd (char **args)
1358 int msgp = 0, vecp = 1;
1360 char *cp, buf[BUFSIZ];
1361 char *msgs[MAXARGS], *vec[MAXARGS];
1364 forkcmd (args, cmd_name);
1367 while ((cp = *args++)) {
1369 switch (smatch (++cp, mhnswit)) {
1371 ambigsw (cp, mhnswit);
1374 fprintf (stderr, "-%s unknown\n", cp);
1377 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1378 print_help (buf, mhnswit, 1);
1413 if (!(cp = *args++) || *cp == '-') {
1414 advise (NULL, "missing argument to %s", args[-2]);
1421 if (*cp == '+' || *cp == '@') {
1422 advise (NULL, "sorry, no folders allowed!");
1430 vec[vecp++] = "-file";
1433 msgs[msgp++] = "cur";
1434 for (msgnum = 0; msgnum < msgp; msgnum++)
1435 if (!m_convert (mp, msgs[msgnum]))
1440 for (msgnum = mp->lowsel;
1441 msgnum <= mp->hghsel && !interrupted;
1443 if (is_selected (mp, msgnum))
1444 if (process (msgnum, cmd_name, vecp, vec)) {
1445 unset_selected (mp, msgnum);
1449 seq_setcur (mp, mp->hghsel);
1453 static struct swit packswit[] = {
1461 static int mbx_style = MMDF_FORMAT;
1464 packcmd (char **args)
1466 int msgp = 0, md, msgnum;
1467 char *cp, *file = NULL;
1468 char buf[BUFSIZ], *msgs[MAXARGS];
1472 forkcmd (args, cmd_name);
1476 while ((cp = *args++)) {
1478 switch (smatch (++cp, packswit)) {
1480 ambigsw (cp, packswit);
1483 fprintf (stderr, "-%s unknown\n", cp);
1486 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1487 print_help (buf, packswit, 1);
1491 if (!(file = *args++) || *file == '-') {
1492 advise (NULL, "missing argument to %s", args[-2]);
1497 if (*cp == '+' || *cp == '@') {
1498 advise (NULL, "sorry, no folders allowed!");
1507 file = path (file, TFILE);
1508 if (stat (file, &st) == NOTOK) {
1509 if (errno != ENOENT) {
1510 advise (file, "error on file");
1513 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1520 msgs[msgp++] = "all";
1521 for (msgnum = 0; msgnum < msgp; msgnum++)
1522 if (!m_convert (mp, msgs[msgnum]))
1526 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1527 advise (file, "unable to open");
1530 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1531 if (is_selected (mp, msgnum))
1532 if (pack (file, md, msgnum) == NOTOK)
1534 mbx_close (file, md);
1536 if (mp->hghsel != mp->curmsg)
1537 seq_setcur (mp, mp->lowsel);
1545 pack (char *mailbox, int md, int msgnum)
1549 if (Msgs[msgnum].m_bboard_id == 0)
1552 zp = msh_ready (msgnum, 1);
1553 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1554 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1559 packhak (char **args)
1562 char *cp, *file = NULL;
1564 while ((cp = *args++)) {
1566 switch (smatch (++cp, packswit)) {
1573 if (!(file = *args++) || *file == '-')
1577 if (*cp == '+' || *cp == '@')
1581 file = path (file ? file : "./msgbox", TFILE);
1582 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1589 static struct swit pickswit[] = {
1601 { "cc pattern", 0 },
1603 { "date pattern", 0 },
1605 { "from pattern", 0 },
1607 { "search pattern", 0 },
1609 { "subject pattern", 0 },
1611 { "to pattern", 0 },
1613 { "-othercomponent pattern", 15 },
1615 { "after date", 0 },
1617 { "before date", 0 },
1619 { "datefield field", 5 },
1621 { "sequence name", 0 },
1641 pickcmd (char **args)
1643 int zerosw = 1, msgp = 0, seqp = 0;
1644 int vecp = 0, hi, lo, msgnum;
1645 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1646 char *seqs[NUMATTRS], *vec[MAXARGS];
1649 while ((cp = *args++)) {
1655 switch (smatch (cp, pickswit)) {
1657 ambigsw (cp, pickswit);
1660 fprintf (stderr, "-%s unknown\n", cp);
1663 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1664 print_help (buf, pickswit, 1);
1678 if (!(cp = *args++)) {/* allow -xyz arguments */
1679 advise (NULL, "missing argument to %s", args[-2]);
1685 advise (NULL, "internal error!");
1696 if (!(cp = *args++) || *cp == '-') {
1697 advise (NULL, "missing argument to %s", args[-2]);
1700 if (seqp < NUMATTRS)
1703 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1714 case PIPUSW: /* not implemented */
1721 if (*cp == '+' || *cp == '@') {
1722 advise (NULL, "sorry, no folders allowed!");
1731 msgs[msgp++] = "all";
1732 for (msgnum = 0; msgnum < msgp; msgnum++)
1733 if (!m_convert (mp, msgs[msgnum]))
1738 if (!pcompile (vec, NULL))
1744 for (msgnum = mp->lowsel;
1745 msgnum <= mp->hghsel && !interrupted;
1747 if (is_selected (mp, msgnum)) {
1748 zp = msh_ready (msgnum, 1);
1749 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1750 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1757 unset_selected (mp, msgnum);
1768 if (mp->numsel <= 0) {
1769 advise (NULL, "no messages match specification");
1774 for (seqp = 0; seqs[seqp]; seqp++)
1775 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1778 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1782 static struct swit replswit[] = {
1786 { "noannotate", 0 },
1792 { "draftfolder +folder", 0 },
1794 { "draftmessage msg", 0 },
1796 { "nodraftfolder", 0 },
1798 { "editor editor", 0 },
1802 { "fcc +folder", 0 },
1804 { "filter filterfile", 0 },
1806 { "form formfile", 0 },
1816 { "whatnowproc program", 0 },
1820 { "width columns", 0 },
1828 replcmd (char **args)
1831 char *cp, *msg = NULL;
1832 char buf[BUFSIZ], *vec[MAXARGS];
1835 forkcmd (args, cmd_name);
1839 while ((cp = *args++)) {
1841 switch (smatch (++cp, replswit)) {
1843 ambigsw (cp, replswit);
1846 fprintf (stderr, "-%s unknown\n", cp);
1849 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1850 print_help (buf, replswit, 1);
1853 case REANSW: /* not implemented */
1878 if (!(cp = *args++) || *cp == '-') {
1879 advise (NULL, "missing argument to %s", args[-2]);
1885 if (*cp == '+' || *cp == '@') {
1886 advise (NULL, "sorry, no folders allowed!");
1891 advise (NULL, "only one message at a time!");
1899 vec[vecp++] = "-file";
1903 if (!m_convert (mp, msg))
1907 if (mp->numsel > 1) {
1908 advise (NULL, "only one message at a time!");
1911 process (mp->hghsel, cmd_name, vecp, vec);
1912 seq_setcur (mp, mp->hghsel);
1916 static struct swit rmmswit[] = {
1924 rmmcmd (char **args)
1926 int msgp = 0, msgnum;
1927 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1929 while ((cp = *args++)) {
1931 switch (smatch (++cp, rmmswit)) {
1933 ambigsw (cp, rmmswit);
1936 fprintf (stderr, "-%s unknown\n", cp);
1939 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1940 print_help (buf, rmmswit, 1);
1943 if (*cp == '+' || *cp == '@') {
1944 advise (NULL, "sorry, no folders allowed!");
1952 msgs[msgp++] = "cur";
1953 for (msgnum = 0; msgnum < msgp; msgnum++)
1954 if (!m_convert (mp, msgs[msgnum]))
1965 register int msgnum, vecp;
1967 char buffer[BUFSIZ], *vec[MAXARGS];
1971 if (mp->numsel > MAXARGS - 1) {
1972 advise (NULL, "more than %d messages for %s exec",
1973 MAXARGS - 1, rmmproc);
1977 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1978 if (is_selected (mp, msgnum))
1979 vec[vecp++] = getcpy (m_name (msgnum));
1981 forkcmd (vec, rmmproc);
1982 for (vecp = 0; vec[vecp]; vecp++)
1986 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1987 if (is_selected (mp, msgnum)) {
1988 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1989 if (rename (cp, buffer) == NOTOK)
1990 admonish (buffer, "unable to rename %s to", cp);
1994 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1995 if (is_selected (mp, msgnum)) {
1996 set_deleted (mp, msgnum);
1997 unset_exists (mp, msgnum);
2000 if (pmsh && pop_dele (msgnum) != OK)
2001 fprintf (stderr, "%s", response);
2006 if ((mp->nummsg -= mp->numsel) <= 0) {
2008 admonish (NULL, "no messages remaining in +%s", fmsh);
2010 admonish (NULL, "no messages remaining in %s", mp->foldpath);
2011 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2013 if (mp->lowsel == mp->lowmsg) {
2014 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2015 if (does_exist (mp, msgnum))
2017 mp->lowmsg = msgnum;
2019 if (mp->hghsel == mp->hghmsg) {
2020 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2021 if (does_exist (mp, msgnum))
2023 mp->hghmsg = msgnum;
2026 mp->msgflags |= MODIFIED;
2031 static struct swit scanswit[] = {
2037 { "form formatfile", 0 },
2039 { "format string", 5 },
2045 { "width columns", 0 },
2053 scancmd (char **args)
2055 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2057 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2058 int msgnum, optim, state;
2059 char *cp, *form = NULL, *format = NULL;
2060 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2064 static int p_optim = 0;
2067 static int s_optim = 0;
2068 static char *s_form = NULL, *s_format = NULL;
2070 while ((cp = *args++)) {
2072 switch (smatch (++cp, scanswit)) {
2074 ambigsw (cp, scanswit);
2077 fprintf (stderr, "-%s unknown\n", cp);
2080 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2081 print_help (buf, scanswit, 1);
2097 if (!(form = *args++) || *form == '-') {
2098 advise (NULL, "missing argument to %s", args[-2]);
2104 if (!(format = *args++) || *format == '-') {
2105 advise (NULL, "missing argument to %s", args[-2]);
2111 if (!(cp = *args++) || *cp == '-') {
2112 advise (NULL, "missing argument to %s", args[-2]);
2118 if (*cp == '+' || *cp == '@') {
2119 advise (NULL, "sorry, no folders allowed!");
2127 msgs[msgp++] = "all";
2128 for (msgnum = 0; msgnum < msgp; msgnum++)
2129 if (!m_convert (mp, msgs[msgnum]))
2133 /* Get new format string */
2134 nfs = new_fs (form, format, FORMAT);
2136 /* force scansbr to (re)compile format */
2143 s_optim = optim = 1;
2144 s_form = form ? getcpy (form) : NULL;
2145 s_format = format ? getcpy (format) : NULL;
2154 width = sc_width ();
2156 for (dp = nfs, i = 0; *dp; dp++, i++)
2157 if (*dp == '\\' || *dp == '"' || *dp == '\n')
2160 if ((ep = malloc ((unsigned) i)) == NULL)
2161 adios (NULL, "out of memory");
2162 for (dp = nfs, fp = ep; *dp; dp++) {
2164 *fp++ = '\\', *fp++ = 'n';
2167 if (*dp == '"' || *dp == '\\')
2173 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
2182 optim = equiv (s_form, form) && equiv (s_format, format);
2186 if (p_optim && optim) {
2187 for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
2188 if (!is_selected(mp, msgnum) || Msgs[msgnum].m_scanl)
2190 if (msgnum > mp->hghmsg && pop_command ("LIST") == OK) {
2191 fprintf (stderr, "Stand-by...");
2197 switch (pop_multiline ()) {
2199 fprintf (stderr, "%s", response);
2202 fprintf (stderr,"\n");
2206 if (sscanf (response, "%d %d", &msgnum, &size) == 2
2207 && mp->lowmsg <= msgnum
2208 && msgnum <= mp->hghmsg
2209 && (cp = strchr(response, '#'))
2211 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2222 for (msgnum = mp->lowsel;
2223 msgnum <= mp->hghsel && !interrupted;
2225 if (is_selected (mp, msgnum)) {
2226 if (optim && Msgs[msgnum].m_scanl)
2227 printf ("%s", Msgs[msgnum].m_scanl);
2233 && is_virtual (mp, msgnum)
2234 && pop_command ("LIST %d", msgnum) == OK
2235 && (cp = strchr(response, '#'))
2237 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2238 printf ("%s", Msgs[msgnum].m_scanl);
2244 zp = msh_ready (msgnum, 0);
2245 switch (state = scan (zp, msgnum, 0, nfs, width,
2246 msgnum == mp->curmsg,
2247 is_unseen (mp, msgnum),
2248 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2249 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2255 Msgs[msgnum].m_scanl = getcpy (scanl);
2259 advise (NULL, "scan() botch (%d)", state);
2263 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2275 static struct swit showswit[] = {
2279 { "form formfile", 4 },
2281 { "moreproc program", 4 },
2283 { "nomoreproc", 3 },
2285 { "length lines", 4 },
2287 { "width columns", 4 },
2289 { "showproc program", 4 },
2291 { "noshowproc", 3 },
2303 showcmd (char **args)
2305 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2306 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2307 char *cp, *proc = showproc, buf[BUFSIZ];
2308 char *msgs[MAXARGS], *vec[MAXARGS];
2310 if (!strcasecmp (cmd_name, "next"))
2313 if (!strcasecmp (cmd_name, "prev"))
2315 while ((cp = *args++)) {
2317 switch (i = smatch (++cp, showswit)) {
2319 ambigsw (cp, showswit);
2326 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2327 cmd_name, mode ? NULL : "[msgs] ");
2328 print_help (buf, showswit, 1);
2336 if (!(cp = *args++) || *cp == '-') {
2337 advise (NULL, "missing argument to %s", args[-2]);
2349 if (!(proc = *args++) || *proc == '-') {
2350 advise (NULL, "missing argument to %s", args[-2]);
2360 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2363 if (*cp == '+' || *cp == '@') {
2364 advise (NULL, "sorry, no folders allowed!");
2370 "usage: %s [switches] [switches for showproc]\n",
2380 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2381 for (msgnum = 0; msgnum < msgp; msgnum++)
2382 if (!m_convert (mp, msgs[msgnum]))
2386 if (!nshow && !getenv ("NOMHNPROC"))
2387 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2388 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2389 proc = showmimeproc;
2390 vec[vecp++] = "-file";
2398 if (strcmp (showproc, "mhl") == 0) {
2404 seqnum = seq_getnum (mp, "unseen");
2405 vec[0] = r1bindex (proc, '/');
2408 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2409 if (is_selected (mp, msgnum)) {
2410 vec[vecp++] = getcpy (m_name (msgnum));
2412 seq_delmsg (mp, "unseen", msgnum);
2415 if (mp->numsel == 1 && headersw)
2417 mhlsbr (vecp, vec, mhl_action);
2418 m_eomsbr ((int (*)()) 0);
2423 for (msgnum = mp->lowsel;
2424 msgnum <= mp->hghsel && !interrupted;
2426 if (is_selected (mp, msgnum)) {
2427 switch (ask (msgnum)) {
2428 case NOTOK: /* QUIT */
2435 if (mp->numsel == 1 && headersw)
2438 copy_message (msgnum, stdout);
2440 process (msgnum, proc, vecp, vec);
2443 seq_delmsg (mp, "unseen", msgnum);
2450 seq_setcur (mp, mp->hghsel);
2457 if (Msgs[msgnum].m_bboard_id == 0)
2460 printf ("(Message %d", msgnum);
2461 if (Msgs[msgnum].m_bboard_id > 0)
2462 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2471 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2476 mhl_action (char *name)
2480 if ((msgnum = m_atoi (name)) < mp->lowmsg
2481 || msgnum > mp->hghmsg
2482 || !does_exist (mp, msgnum))
2486 mhlfp = msh_ready (msgnum, 1);
2488 m_eomsbr (eom_action);
2500 if (mp->numsel == 1 || !interactive || redirected)
2503 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2504 if (mp->lowsel != msgnum)
2506 printf ("Press <return> to list \"%d\"...", msgnum);
2512 read (fileno (stdout), buf, sizeof buf);
2514 switch (setjmp (sigenv)) {
2517 read (fileno (stdout), buf, sizeof buf);/* fall... */
2525 if (strchr(buf, '\n') == NULL)
2529 told_to_quit = interrupted = 0;
2544 is_nontext (int msgnum)
2548 char buf[BUFSIZ], name[NAMESZ];
2551 if (Msgs[msgnum].m_flags & MHNCHK)
2552 return (Msgs[msgnum].m_flags & MHNYES);
2553 Msgs[msgnum].m_flags |= MHNCHK;
2555 fp = msh_ready (msgnum, 1);
2558 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2563 * Check Content-Type field
2565 if (!strcasecmp (name, TYPE_FIELD)) {
2569 cp = add (buf, NULL);
2570 while (state == FLDPLUS) {
2571 state = m_getfld (state, name, buf, sizeof buf, fp);
2578 for (; isspace (*bp); bp++)
2583 for (bp++, i = 0;;) {
2613 for (dp = bp; istoken (*dp); dp++)
2620 if ((result = (strcasecmp (bp, "plain") != 0)))
2623 for (dp++; isspace (*dp); dp++)
2626 if ((result = !uprf (dp, "charset")))
2628 dp += sizeof "charset" - 1;
2629 while (isspace (*dp))
2633 while (isspace (*dp))
2636 if ((bp = strchr(++dp, '"')))
2639 for (bp = dp; *bp; bp++)
2640 if (isspace (*bp)) {
2646 /* Default character set */
2649 /* Check the character set */
2650 result = !check_charset (dp, strlen (dp));
2652 if (!(result = (strcasecmp (bp, "text") != 0))) {
2662 Msgs[msgnum].m_flags |= MHNYES;
2669 * Check Content-Transfer-Encoding field
2671 if (!strcasecmp (name, ENCODING_FIELD)) {
2672 cp = add (buf, NULL);
2673 while (state == FLDPLUS) {
2674 state = m_getfld (state, name, buf, sizeof buf, fp);
2677 for (bp = cp; isspace (*bp); bp++)
2679 for (dp = bp; istoken (*dp); dp++)
2682 result = (strcasecmp (bp, "7bit")
2683 && strcasecmp (bp, "8bit")
2684 && strcasecmp (bp, "binary"));
2688 Msgs[msgnum].m_flags |= MHNYES;
2695 * Just skip the rest of this header
2696 * field and go to next one.
2698 while (state == FLDPLUS)
2699 state = m_getfld (state, name, buf, sizeof(buf), fp);
2703 * We've passed the message header,
2704 * so message is just text.
2712 static struct swit sortswit[] = {
2714 { "datefield field", 0 },
2716 { "textfield field", 0 },
2718 { "notextfield", 0 },
2720 { "limit days", 0 },
2734 sortcmd (char **args)
2736 int msgp = 0, msgnum;
2737 char *cp, *datesw = NULL, *subjsw = NULL;
2738 char buf[BUFSIZ], *msgs[MAXARGS];
2742 forkcmd (args, cmd_name);
2746 while ((cp = *args++)) {
2748 switch (smatch (++cp, sortswit)) {
2750 ambigsw (cp, sortswit);
2753 fprintf (stderr, "-%s unknown\n", cp);
2756 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2757 print_help (buf, sortswit, 1);
2762 advise (NULL, "only one date field at a time!");
2765 if (!(datesw = *args++) || *datesw == '-') {
2766 advise (NULL, "missing argument to %s", args[-2]);
2773 advise (NULL, "only one text field at a time!");
2776 if (!(subjsw = *args++) || *subjsw == '-') {
2777 advise (NULL, "missing argument to %s", args[-2]);
2785 case SOLIMT: /* too hard */
2786 if (!(cp = *args++) || *cp == '-') {
2787 advise (NULL, "missing argument to %s", args[-2]);
2791 case SOVERB: /* not implemented */
2795 if (*cp == '+' || *cp == '@') {
2796 advise (NULL, "sorry, no folders allowed!");
2804 msgs[msgp++] = "all";
2807 for (msgnum = 0; msgnum < msgp; msgnum++)
2808 if (!m_convert (mp, msgs[msgnum]))
2812 twscopy (&tb, dlocaltimenow ());
2814 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2815 if (Msgs[msgnum].m_scanl) {
2816 free (Msgs[msgnum].m_scanl);
2817 Msgs[msgnum].m_scanl = NULL;
2819 if (is_selected (mp, msgnum)) {
2820 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2821 twscopy (&Msgs[msgnum].m_tb,
2822 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2824 else /* m_scaln is already NULL */
2825 twscopy (&Msgs[msgnum].m_tb, &tb);
2826 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2827 if (mp->curmsg == msgnum)
2828 Msgs[msgnum].m_stats |= CUR;
2831 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2832 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2834 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2835 if (subjsw && Msgs[msgnum].m_scanl) {
2836 free (Msgs[msgnum].m_scanl); /* from subjsort */
2837 Msgs[msgnum].m_scanl = NULL;
2839 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2840 if (Msgs[msgnum].m_stats & CUR)
2841 seq_setcur (mp, msgnum);
2844 mp->msgflags |= MODIFIED;
2850 * get_fields - parse message, and get date and subject if needed.
2851 * We'll use the msgp->m_tb tws struct for the date, and overload
2852 * the msgp->m_scanl field with our subject string.
2855 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2857 int state, gotdate = 0;
2858 char *bp, buf[BUFSIZ], name[NAMESZ];
2859 struct tws *tw = (struct tws *) 0;
2862 zp = msh_ready (msgnum, 0);
2863 for (state = FLD;;) {
2864 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2868 if (!strcasecmp (name, datesw)) {
2870 while (state == FLDPLUS) {
2871 state = m_getfld (state, name, buf, sizeof buf, zp);
2874 if ((tw = dparsetime (bp)) == NULL)
2876 "unable to parse %s field in message %d",
2879 twscopy (&(msgp->m_tb), tw);
2881 if (!subjsw) /* not using this, or already done */
2882 break; /* all done! */
2885 else if (subjsw && !strcasecmp(name, subjsw)) {
2887 while (state == FLDPLUS) {
2888 state = m_getfld (state, name, buf, sizeof buf, zp);
2891 msgp->m_scanl = sosmash(subjsw, bp);
2893 break; /* date done so we're done */
2895 subjsw = (char *)0;/* subject done, need date */
2897 while (state == FLDPLUS) /* flush this one */
2898 state = m_getfld (state, name, buf, sizeof buf, zp);
2909 admonish (NULL, "format error in message %d", msgnum);
2910 if (msgp->m_scanl) { /* this might need free'd */
2911 free (msgp->m_scanl); /* probably can't use subj anyway */
2912 msgp->m_scanl = NULL;
2917 adios (NULL, "internal error -- you lose");
2922 return OK; /* not an error if subj not found */
2924 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2925 return NOTOK; /* NOTOK means use some other date */
2934 msgsort (struct Msg *a, struct Msg *b)
2936 return twsort (&a->m_tb, &b->m_tb);
2941 subsort (struct Msg *a, struct Msg *b)
2945 if (a->m_scanl && b->m_scanl)
2946 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2949 return twsort (&a->m_tb, &b->m_tb);
2954 * try to make the subject "canonical": delete leading "re:", everything
2955 * but letters & smash letters to lower case.
2958 sosmash (char *subj, char *s)
2960 register char *cp, *dp, c;
2964 dp = s; /* dst pointer */
2965 if (!strcasecmp (subj, "subject"))
2972 *dp++ = isupper(c) ? tolower(c) : c;
2978 while ((c = *cp++)) {
2980 *dp++ = isupper(c) ? tolower(c) : c;
2990 process (int msgnum, char *proc, int vecp, char **vec)
2992 int child_id, status;
2997 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2998 context_del (pfolder);
2999 context_replace (pfolder, fmsh);/* update current folder */
3001 context_save (); /* save the context file */
3005 strncpy (tmpfil, m_scratch ("", invo_name), sizeof(tmpfil));
3006 if ((out = fopen (tmpfil, "w")) == NULL) {
3012 strncpy (newfil, m_tmpfil (invo_name), sizeof(newfil));
3013 if ((out = fopen (newfil, "w")) == NULL) {
3015 advise (tmpfil, "unable to create temporary file");
3018 strncpy (tmpfil, newfil, sizeof(tmpfil));
3021 copy_message (msgnum, out);
3026 switch (child_id = fork ()) {
3028 advise ("fork", "unable to");
3034 SIGNAL (SIGINT, istat);
3035 SIGNAL (SIGQUIT, qstat);
3037 vec[vecp++] = tmpfil;
3041 fprintf (stderr, "unable to exec ");
3046 status = pidXwait (child_id, NULL);
3057 copy_message (int msgnum, FILE *out)
3060 static char buffer[BUFSIZ];
3063 zp = msh_ready (msgnum, 1);
3065 while (fgets (buffer, sizeof buffer, zp) != NULL) {
3066 fputs (buffer, out);
3067 if (interrupted && out == stdout)
3073 while (fgets (buffer, sizeof buffer, zp) != NULL
3074 && pos < Msgs[msgnum].m_stop) {
3075 fputs (buffer, out);
3076 pos += (long) strlen (buffer);
3077 if (interrupted && out == stdout)
3085 copy_digest (int msgnum, FILE *out)
3089 static char buffer[BUFSIZ];
3093 zp = msh_ready (msgnum, 1);
3096 while (fgets (buffer, sizeof buffer, zp) != NULL
3097 && !fmsh && pos < Msgs[msgnum].m_stop) {
3098 if (c == '\n' && *buffer == '-')
3100 fputs (buffer, out);
3101 c = buffer[strlen (buffer) - 1];
3103 pos += (long) strlen (buffer);
3104 if (interrupted && out == stdout)