3 * mshcmds.c -- command handlers in msh
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
11 #include <h/signals.h>
12 #include <h/dropsbr.h>
13 #include <h/fmt_scan.h>
14 #include <h/scansbr.h>
20 #include <h/picksbr.h>
24 static char delim3[] = "-------"; /* from burst.c */
30 * Type for a compare function for qsort. This keeps
33 typedef int (*qsort_comp) (const void *, const void *);
38 void clear_screen (void); /* from termsbr.c */
39 int SOprintf (char *, ...); /* from termsbr.c */
40 int sc_width (void); /* from termsbr.c */
45 static int burst (struct Msg *, int, int, int, int);
46 static void forw (char *, char *, int, char **);
47 static void rmm (void);
48 static void show (int);
49 static int eom_action (int);
50 static FILE *mhl_action (char *);
52 static int is_nontext (int);
53 static int get_fields (char *, char *, int, struct Msg *);
54 static int msgsort (struct Msg *, struct Msg *);
55 static int subsort (struct Msg *, struct Msg *);
56 static char *sosmash (char *, char *);
57 static int process (int, char *, int, char **);
58 static void copy_message (int, FILE *);
59 static void copy_digest (int, FILE *);
62 int mhlsbr (int, char **, FILE *(*)());
65 forkcmd (char **args, char *pgm)
70 vec[0] = r1bindex (pgm, '/');
71 copyip (args, vec + 1, MAXARGS - 1);
74 context_del (pfolder);
75 context_replace (pfolder, fmsh);/* update current folder */
77 context_save (); /* save the context file */
80 switch (child_id = fork ()) {
82 advise ("fork", "unable to");
87 SIGNAL (SIGINT, istat);
88 SIGNAL (SIGQUIT, qstat);
91 fprintf (stderr, "unable to exec ");
96 pidXwait (child_id, NULL);
99 if (fmsh) { /* assume the worst case */
100 mp->msgflags |= MODIFIED;
106 static struct swit distswit[] = {
112 { "draftfolder +folder", 0 },
114 { "draftmessage msg", 0 },
116 { "nodraftfolder", 0 },
118 { "editor editor", 0 },
122 { "form formfile", 0 },
128 { "whatnowproc program", 0 },
130 { "nowhatnowproc", 0 },
138 distcmd (char **args)
141 char *cp, *msg = NULL;
142 char buf[BUFSIZ], *vec[MAXARGS];
145 forkcmd (args, cmd_name);
149 while ((cp = *args++)) {
151 switch (smatch (++cp, distswit)) {
153 ambigsw (cp, distswit);
156 fprintf (stderr, "-%s unknown\n", cp);
159 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
160 print_help (buf, distswit, 1);
163 case DIANSW: /* not implemented */
181 if (!(cp = *args++) || *cp == '-') {
182 advise (NULL, "missing argument to %s", args[-2]);
188 if (*cp == '+' || *cp == '@') {
189 advise (NULL, "sorry, no folders allowed!");
194 advise (NULL, "only one message at a time!");
202 vec[vecp++] = "-file";
206 if (!m_convert (mp, msg))
210 if (mp->numsel > 1) {
211 advise (NULL, "only one message at a time!");
214 process (mp->hghsel, cmd_name, vecp, vec);
215 seq_setcur (mp, mp->hghsel);
219 static struct swit explswit[] = {
239 explcmd (char **args)
241 int inplace = 0, quietsw = 0, verbosw = 0;
242 int msgp = 0, hi, msgnum;
243 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
247 forkcmd (args, cmd_name);
251 while ((cp = *args++)) {
253 switch (smatch (++cp, explswit)) {
255 ambigsw (cp, explswit);
258 fprintf (stderr, "-%s unknown\n", cp);
261 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
262 print_help (buf, explswit, 1);
284 if (*cp == '+' || *cp == '@') {
285 advise (NULL, "sorry, no folders allowed!");
293 msgs[msgp++] = "cur";
294 for (msgnum = 0; msgnum < msgp; msgnum++)
295 if (!m_convert (mp, msgs[msgnum]))
299 smsgs = (struct Msg *)
300 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
302 adios (NULL, "unable to allocate folder storage");
306 for (msgnum = mp->lowsel;
307 msgnum <= mp->hghsel && !interrupted;
309 if (is_selected (mp, msgnum))
310 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
313 free ((char *) smsgs);
316 seq_setcur (mp, mp->lowsel);
318 if (hi <= mp->hghmsg)
321 mp->msgflags |= MODIFIED;
327 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
329 int i, j, ld3, wasdlm, msgp;
331 char c, buffer[BUFSIZ];
334 ld3 = strlen (delim3);
336 if (Msgs[msgnum].m_scanl) {
337 free (Msgs[msgnum].m_scanl);
338 Msgs[msgnum].m_scanl = NULL;
341 pos = ftell (zp = msh_ready (msgnum, 1));
342 for (msgp = 0; msgp <= MAXFOLDER;) {
343 while (fgets (buffer, sizeof buffer, zp) != NULL
345 && pos < Msgs[msgnum].m_stop)
346 pos += (long) strlen (buffer);
347 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
349 fseek (zp, pos, SEEK_SET);
350 smsgs[msgp].m_start = pos;
353 pos < Msgs[msgnum].m_stop
354 && fgets (buffer, sizeof buffer, zp) != NULL;
356 if (strncmp (buffer, delim3, ld3) == 0
357 && (msgp == 1 || c == '\n')
358 && peekc (zp) == '\n')
361 pos += (long) strlen (buffer);
363 wasdlm = strncmp (buffer, delim3, ld3) == 0;
364 if (smsgs[msgp].m_start != pos)
365 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
366 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
368 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
371 pos += (long) strlen (buffer);
374 switch (msgp--) { /* toss "End of XXX Digest" */
376 adios (NULL, "burst() botch -- you lose big");
380 printf ("message %d not in digest format\n", msgnum);
385 printf ("%d message%s exploded from digest %d\n",
386 msgp, msgp != 1 ? "s" : "", msgnum);
390 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
391 advise (NULL, "more than %d messages", MAXFOLDER);
394 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
395 adios (NULL, "unable to allocate folder storage");
400 if (mp->hghsel > msgnum)
404 for (i = mp->hghmsg; j > msgnum; i--, j--) {
406 printf ("message %d becomes message %d\n", j, i);
408 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
409 Msgs[i].m_top = Msgs[j].m_top;
410 Msgs[i].m_start = Msgs[j].m_start;
411 Msgs[i].m_stop = Msgs[j].m_stop;
412 Msgs[i].m_scanl = NULL;
413 if (Msgs[j].m_scanl) {
414 free (Msgs[j].m_scanl);
415 Msgs[j].m_scanl = NULL;
417 copy_msg_flags (mp, i, j);
420 if (Msgs[msgnum].m_bboard_id == 0)
423 unset_selected (mp, msgnum);
424 i = inplace ? msgnum + msgp : mp->hghmsg;
425 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
426 if (verbosw && i != msgnum)
427 printf ("message %d of digest %d becomes message %d\n",
430 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
431 Msgs[i].m_top = Msgs[j].m_top;
432 Msgs[i].m_start = smsgs[j].m_start;
433 Msgs[i].m_stop = smsgs[j].m_stop;
434 Msgs[i].m_scanl = NULL;
435 copy_msg_flags (mp, i, msgnum);
442 static struct swit fileswit[] = {
454 { "src +folder", 0 },
458 { "rmmproc program", 0 },
468 filecmd (char **args)
470 int linksw = 0, msgp = 0;
471 int vecp = 1, i, msgnum;
472 char *cp, buf[BUFSIZ];
473 char *msgs[MAXARGS], *vec[MAXARGS];
476 forkcmd (args, cmd_name);
480 while ((cp = *args++)) {
482 switch (i = smatch (++cp, fileswit)) {
484 ambigsw (cp, fileswit);
487 fprintf (stderr, "-%s unknown\n", cp);
490 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
491 print_help (buf, fileswit, 1);
510 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
513 if (*cp == '+' || *cp == '@')
520 vec[vecp++] = "-file";
523 msgs[msgp++] = "cur";
524 for (msgnum = 0; msgnum < msgp; msgnum++)
525 if (!m_convert (mp, msgs[msgnum]))
530 for (msgnum = mp->lowsel;
531 msgnum <= mp->hghsel && !interrupted;
533 if (is_selected (mp, msgnum))
534 if (process (msgnum, fileproc, vecp, vec)) {
535 unset_selected (mp, msgnum);
539 if (mp->numsel != mp->nummsg || linksw)
540 seq_setcur (mp, mp->hghsel);
547 filehak (char **args)
549 int result, vecp = 0;
550 char *cp, *cwd, *vec[MAXARGS];
552 while ((cp = *args++)) {
554 switch (smatch (++cp, fileswit)) {
571 if (*cp == '+' || *cp == '@')
578 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
580 cwd = getcpy (pwd ());
581 chdir (m_maildir (""));
583 if (access (m_maildir (cp), F_OK) == NOTOK)
594 static struct swit foldswit[] = {
632 foldcmd (char **args)
634 int fastsw = 0, headersw = 0, packsw = 0;
636 char *cp, *folder = NULL, *msg = NULL;
637 char buf[BUFSIZ], **vec = args;
642 while ((cp = *args++)) {
644 switch (smatch (++cp, foldswit)) {
646 ambigsw (cp, foldswit);
649 fprintf (stderr, "-%s unknown\n", cp);
652 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
653 print_help (buf, foldswit, 1);
656 case FLALSW: /* not implemented */
686 if (*cp == '+' || *cp == '@') {
688 advise (NULL, "only one folder at a time!\n");
692 folder = fmsh ? pluspath (cp)
697 advise (NULL, "only one message at a time!\n");
706 advise (NULL, "null folder names are not permitted");
710 if (access (m_maildir (folder), R_OK) == NOTOK) {
711 advise (folder, "unable to read");
716 strncpy (buf, folder, sizeof(buf));
717 if (expand (buf) == NOTOK)
720 if (access (folder, R_OK) == NOTOK) {
721 advise (folder, "unable to read");
736 if (!m_convert (mp, msg))
740 if (mp->numsel > 1) {
741 advise (NULL, "only one message at a time!");
744 seq_setcur (mp, mp->hghsel);
749 forkcmd (vec, cmd_name);
753 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
754 adios (NULL, "unable to allocate folder storage");
756 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
757 if (does_exist (mp, msgnum)) {
758 if (msgnum != hole) {
759 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
760 Msgs[hole].m_top = Msgs[msgnum].m_top;
761 Msgs[hole].m_start = Msgs[msgnum].m_start;
762 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
763 Msgs[hole].m_scanl = NULL;
764 if (Msgs[msgnum].m_scanl) {
765 free (Msgs[msgnum].m_scanl);
766 Msgs[msgnum].m_scanl = NULL;
768 copy_msg_flags (mp, hole, msgnum);
769 if (mp->curmsg == msgnum)
770 seq_setcur (mp, hole);
774 if (mp->nummsg > 0) {
776 mp->hghmsg = hole - 1;
778 mp->msgflags |= MODIFIED;
784 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
787 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
788 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
790 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
792 /* check for empty folder */
793 if (mp->nummsg == 0) {
794 printf ("has no messages%*s",
795 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
797 printf ("has %*d message%s (%*d-%*d)",
798 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
799 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
800 if (mp->curmsg >= mp->lowmsg
801 && mp->curmsg <= mp->hghmsg)
802 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
809 static struct swit forwswit[] = {
815 { "draftfolder +folder", 0 },
817 { "draftmessage msg", 0 },
819 { "nodraftfolder", 0 },
821 { "editor editor", 0 },
825 { "filter filterfile", 0 },
827 { "form formfile", 0 },
841 { "whatnowproc program", 0 },
851 forwcmd (char **args)
853 int msgp = 0, vecp = 1, msgnum;
854 char *cp, *filter = NULL, buf[BUFSIZ];
855 char *msgs[MAXARGS], *vec[MAXARGS];
860 forkcmd (args, cmd_name);
864 while ((cp = *args++)) {
866 switch (smatch (++cp, forwswit)) {
868 ambigsw (cp, forwswit);
871 fprintf (stderr, "-%s unknown\n", cp);
874 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
875 print_help (buf, forwswit, 1);
878 case FOANSW: /* not implemented */
898 if (!(cp = *args++) || *cp == '-') {
899 advise (NULL, "missing argument to %s", args[-2]);
905 if (!(filter = *args++) || *filter == '-') {
906 advise (NULL, "missing argument to %s", args[-2]);
911 if (access (filter = myfilter, R_OK) == NOTOK) {
912 advise (filter, "unable to read default filter file");
920 if (*cp == '+' || *cp == '@') {
921 advise (NULL, "sorry, no folders allowed!");
928 /* foil search of .mh_profile */
929 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
931 tfile = m_mktemp(buf, NULL, NULL);
932 if (tfile == NULL) adios("forwcmd", "unable to create temporary file");
933 strncpy (tmpfil, tfile, sizeof(tmpfil));
936 vec[vecp++] = "-file";
939 msgs[msgp++] = "cur";
940 for (msgnum = 0; msgnum < msgp; msgnum++)
941 if (!m_convert (mp, msgs[msgnum]))
946 strncpy (buf, filter, sizeof(buf));
947 if (expand (buf) == NOTOK)
949 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
950 advise (filter, "unable to read");
955 forw (cmd_name, filter, vecp, vec);
956 seq_setcur (mp, mp->hghsel);
963 forw (char *proc, char *filter, int vecp, char **vec)
965 int i, child_id, msgnum, msgcnt;
966 char tmpfil[BUFSIZ], *args[MAXARGS];
970 tfile = m_mktemp2(NULL, invo_name, NULL, NULL);
971 if (tfile == NULL) adios("forw", "unable to create temporary file");
972 strncpy (tmpfil, tfile, sizeof(tmpfil));
976 switch (child_id = fork ()) {
978 advise ("fork", "unable to");
981 case OK: /* "trust me" */
982 if (freopen (tmpfil, "w", stdout) == NULL) {
983 fprintf (stderr, "unable to create ");
987 args[0] = r1bindex (mhlproc, '/');
989 args[i++] = "-forwall";
992 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
993 if (is_selected (mp, msgnum))
994 args[i++] = getcpy (m_name (msgnum));
996 mhlsbr (i, args, mhl_action);
997 m_eomsbr ((int (*) ()) 0);
1002 if (pidXwait (child_id, NULL))
1007 if ((out = fopen (tmpfil, "w")) == NULL) {
1008 advise (tmpfil, "unable to create temporary file");
1013 for (msgnum = mp->lowsel;
1014 msgnum <= mp->hghsel && !interrupted;
1016 if (is_selected (mp, msgnum)) {
1017 fprintf (out, "\n\n-------");
1018 if (msgnum == mp->lowsel)
1019 fprintf (out, " Forwarded Message%s",
1020 mp->numsel > 1 ? "s" : "");
1022 fprintf (out, " Message %d", msgcnt);
1023 fprintf (out, "\n\n");
1024 copy_digest (msgnum, out);
1028 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1029 mp->numsel > 1 ? "s" : "");
1035 switch (child_id = fork ()) {
1037 advise ("fork", "unable to");
1042 SIGNAL (SIGINT, istat);
1043 SIGNAL (SIGQUIT, qstat);
1045 vec[vecp++] = tmpfil;
1049 fprintf (stderr, "unable to exec ");
1054 pidXwait (child_id, NULL);
1062 static char *hlpmsg[] = {
1063 "The %s program emulates many of the commands found in the nmh",
1064 "system. Instead of operating on nmh folders, commands to %s concern",
1067 "To see the list of commands available, just type a ``?'' followed by",
1068 "the RETURN key. To find out what switches each command takes, type",
1069 "the name of the command followed by ``-help''. To leave %s, use the",
1070 "``quit'' command.",
1072 "Although a lot of nmh commands are found in %s, not all are fully",
1073 "implemented. %s will always recognize all legal switches for a",
1074 "given command though, and will let you know when you ask for an",
1075 "option that it is unable to perform.",
1077 "Running %s is fun, but using nmh from your shell is far superior.",
1078 "After you have familiarized yourself with the nmh style by using %s,",
1079 "you should try using nmh from the shell. You can still use %s for",
1080 "message files that aren't in nmh format, such as BBoard files.",
1086 helpcmd (char **args)
1092 for (i = 0; hlpmsg[i]; i++) {
1093 printf (hlpmsg[i], invo_name);
1099 static struct swit markswit[] = {
1107 { "sequence name", 0 },
1125 markcmd (char **args)
1127 int addsw = 0, deletesw = 0, debugsw = 0;
1128 int listsw = 0, zerosw = 0;
1130 int msgp = 0, msgnum;
1131 char *cp, buf[BUFSIZ];
1132 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1134 while ((cp = *args++)) {
1136 switch (smatch (++cp, markswit)) {
1138 ambigsw (cp, markswit);
1141 fprintf (stderr, "-%s unknown\n", cp);
1144 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1145 print_help (buf, markswit, 1);
1150 deletesw = listsw = 0;
1158 addsw = deletesw = 0;
1162 if (!(cp = *args++) || *cp == '-') {
1163 advise (NULL, "missing argument to %s", args[-2]);
1166 if (seqp < NUMATTRS)
1169 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1174 case MPUBSW: /* not implemented */
1190 if (*cp == '+' || *cp == '@') {
1191 advise (NULL, "sorry, no folders allowed!");
1198 if (!addsw && !deletesw && !listsw) {
1205 seqs[seqp++] = "unseen";
1209 msgs[msgp++] = "all";
1214 msgs[msgp++] = listsw ? "all" :"cur";
1215 for (msgnum = 0; msgnum < msgp; msgnum++)
1216 if (!m_convert (mp, msgs[msgnum]))
1220 printf ("invo_name=%s mypath=%s defpath=%s\n",
1221 invo_name, mypath, defpath);
1222 printf ("ctxpath=%s context flags=%s\n",
1223 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1224 printf ("foldpath=%s flags=%s\n",
1226 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1227 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1228 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1229 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1230 mp->lowsel, mp->hghsel, mp->numsel);
1231 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1234 if (seqp == 0 && (addsw || deletesw)) {
1235 advise (NULL, "-%s requires at least one -sequence argument",
1236 addsw ? "add" : "delete");
1242 for (seqp = 0; seqs[seqp]; seqp++)
1243 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1248 for (seqp = 0; seqs[seqp]; seqp++)
1249 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1253 /* Listing messages in sequences */
1256 /* list the given sequences */
1257 for (seqp = 0; seqs[seqp]; seqp++)
1258 seq_print (mp, seqs[seqp]);
1260 /* else list them all */
1266 for (msgnum = mp->lowsel;
1267 msgnum <= mp->hghsel && !interrupted;
1269 if (is_selected (mp, msgnum)) {
1270 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1273 Msgs[msgnum].m_bboard_id,
1275 (long) Msgs[msgnum].m_start,
1276 (long) Msgs[msgnum].m_stop,
1277 snprintb (buf, sizeof(buf),
1278 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1280 if (Msgs[msgnum].m_scanl)
1281 printf ("%s", Msgs[msgnum].m_scanl);
1287 static struct swit mhnswit[] = {
1290 #define MHNNAUTOSW 1
1292 #define MHNDEBUGSW 2
1294 #define MHNEBCDICSW 3
1295 { "ebcdicsafe", 0 },
1296 #define MHNNEBCDICSW 4
1297 { "noebcdicsafe", 0 },
1299 { "form formfile", 4 },
1302 #define MHNNHEADSW 7
1306 #define MHNNLISTSW 9
1308 #define MHNPARTSW 10
1309 { "part number", 0 },
1310 #define MHNSIZESW 11
1312 #define MHNNSIZESW 12
1313 { "norealsize", 0 },
1314 #define MHNRFC934SW 13
1315 { "rfc934mode", 0 },
1316 #define MHNNRFC934SW 14
1317 { "norfc934mode", 0 },
1318 #define MHNSERIALSW 15
1319 { "serialonly", 0 },
1320 #define MHNNSERIALSW 16
1321 { "noserialonly", 0 },
1322 #define MHNSHOWSW 17
1324 #define MHNNSHOWSW 18
1326 #define MHNSTORESW 19
1328 #define MHNNSTORESW 20
1330 #define MHNTYPESW 21
1331 { "type content", 0 },
1332 #define MHNVERBSW 22
1334 #define MHNNVERBSW 23
1336 #define MHNHELPSW 24
1338 #define MHNPROGSW 25
1339 { "moreproc program", -4 },
1340 #define MHNNPROGSW 26
1341 { "nomoreproc", -3 },
1343 { "length lines", -4 },
1345 { "width columns", -4 },
1351 mhncmd (char **args)
1353 int msgp = 0, vecp = 1;
1355 char *cp, buf[BUFSIZ];
1356 char *msgs[MAXARGS], *vec[MAXARGS];
1359 forkcmd (args, cmd_name);
1362 while ((cp = *args++)) {
1364 switch (smatch (++cp, mhnswit)) {
1366 ambigsw (cp, mhnswit);
1369 fprintf (stderr, "-%s unknown\n", cp);
1372 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1373 print_help (buf, mhnswit, 1);
1408 if (!(cp = *args++) || *cp == '-') {
1409 advise (NULL, "missing argument to %s", args[-2]);
1416 if (*cp == '+' || *cp == '@') {
1417 advise (NULL, "sorry, no folders allowed!");
1425 vec[vecp++] = "-file";
1428 msgs[msgp++] = "cur";
1429 for (msgnum = 0; msgnum < msgp; msgnum++)
1430 if (!m_convert (mp, msgs[msgnum]))
1435 for (msgnum = mp->lowsel;
1436 msgnum <= mp->hghsel && !interrupted;
1438 if (is_selected (mp, msgnum))
1439 if (process (msgnum, cmd_name, vecp, vec)) {
1440 unset_selected (mp, msgnum);
1444 seq_setcur (mp, mp->hghsel);
1448 static struct swit packswit[] = {
1456 static int mbx_style = MMDF_FORMAT;
1459 packcmd (char **args)
1461 int msgp = 0, md, msgnum;
1462 char *cp, *file = NULL;
1463 char buf[BUFSIZ], *msgs[MAXARGS];
1467 forkcmd (args, cmd_name);
1471 while ((cp = *args++)) {
1473 switch (smatch (++cp, packswit)) {
1475 ambigsw (cp, packswit);
1478 fprintf (stderr, "-%s unknown\n", cp);
1481 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1482 print_help (buf, packswit, 1);
1486 if (!(file = *args++) || *file == '-') {
1487 advise (NULL, "missing argument to %s", args[-2]);
1492 if (*cp == '+' || *cp == '@') {
1493 advise (NULL, "sorry, no folders allowed!");
1502 file = path (file, TFILE);
1503 if (stat (file, &st) == NOTOK) {
1504 if (errno != ENOENT) {
1505 advise (file, "error on file");
1508 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1515 msgs[msgp++] = "all";
1516 for (msgnum = 0; msgnum < msgp; msgnum++)
1517 if (!m_convert (mp, msgs[msgnum]))
1521 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1522 advise (file, "unable to open");
1525 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1526 if (is_selected (mp, msgnum))
1527 if (pack (file, md, msgnum) == NOTOK)
1529 mbx_close (file, md);
1531 if (mp->hghsel != mp->curmsg)
1532 seq_setcur (mp, mp->lowsel);
1540 pack (char *mailbox, int md, int msgnum)
1544 if (Msgs[msgnum].m_bboard_id == 0)
1547 zp = msh_ready (msgnum, 1);
1548 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1549 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1554 packhak (char **args)
1557 char *cp, *file = NULL;
1559 while ((cp = *args++)) {
1561 switch (smatch (++cp, packswit)) {
1568 if (!(file = *args++) || *file == '-')
1572 if (*cp == '+' || *cp == '@')
1576 file = path (file ? file : "./msgbox", TFILE);
1577 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1584 static struct swit pickswit[] = {
1596 { "cc pattern", 0 },
1598 { "date pattern", 0 },
1600 { "from pattern", 0 },
1602 { "search pattern", 0 },
1604 { "subject pattern", 0 },
1606 { "to pattern", 0 },
1608 { "-othercomponent pattern", 15 },
1610 { "after date", 0 },
1612 { "before date", 0 },
1614 { "datefield field", 5 },
1616 { "sequence name", 0 },
1636 pickcmd (char **args)
1638 int zerosw = 1, msgp = 0;
1640 int vecp = 0, hi, lo, msgnum;
1641 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1642 char *seqs[NUMATTRS], *vec[MAXARGS];
1645 while ((cp = *args++)) {
1651 switch (smatch (cp, pickswit)) {
1653 ambigsw (cp, pickswit);
1656 fprintf (stderr, "-%s unknown\n", cp);
1659 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1660 print_help (buf, pickswit, 1);
1674 if (!(cp = *args++)) {/* allow -xyz arguments */
1675 advise (NULL, "missing argument to %s", args[-2]);
1681 advise (NULL, "internal error!");
1692 if (!(cp = *args++) || *cp == '-') {
1693 advise (NULL, "missing argument to %s", args[-2]);
1696 if (seqp < NUMATTRS)
1699 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1710 case PIPUSW: /* not implemented */
1717 if (*cp == '+' || *cp == '@') {
1718 advise (NULL, "sorry, no folders allowed!");
1727 msgs[msgp++] = "all";
1728 for (msgnum = 0; msgnum < msgp; msgnum++)
1729 if (!m_convert (mp, msgs[msgnum]))
1734 if (!pcompile (vec, NULL))
1740 for (msgnum = mp->lowsel;
1741 msgnum <= mp->hghsel && !interrupted;
1743 if (is_selected (mp, msgnum)) {
1744 zp = msh_ready (msgnum, 1);
1745 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1746 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1753 unset_selected (mp, msgnum);
1764 if (mp->numsel <= 0) {
1765 advise (NULL, "no messages match specification");
1770 for (seqp = 0; seqs[seqp]; seqp++)
1771 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1774 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1778 static struct swit replswit[] = {
1782 { "noannotate", 0 },
1788 { "draftfolder +folder", 0 },
1790 { "draftmessage msg", 0 },
1792 { "nodraftfolder", 0 },
1794 { "editor editor", 0 },
1798 { "fcc +folder", 0 },
1800 { "filter filterfile", 0 },
1802 { "form formfile", 0 },
1812 { "whatnowproc program", 0 },
1816 { "width columns", 0 },
1824 replcmd (char **args)
1827 char *cp, *msg = NULL;
1828 char buf[BUFSIZ], *vec[MAXARGS];
1831 forkcmd (args, cmd_name);
1835 while ((cp = *args++)) {
1837 switch (smatch (++cp, replswit)) {
1839 ambigsw (cp, replswit);
1842 fprintf (stderr, "-%s unknown\n", cp);
1845 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1846 print_help (buf, replswit, 1);
1849 case REANSW: /* not implemented */
1874 if (!(cp = *args++) || *cp == '-') {
1875 advise (NULL, "missing argument to %s", args[-2]);
1881 if (*cp == '+' || *cp == '@') {
1882 advise (NULL, "sorry, no folders allowed!");
1887 advise (NULL, "only one message at a time!");
1895 vec[vecp++] = "-file";
1899 if (!m_convert (mp, msg))
1903 if (mp->numsel > 1) {
1904 advise (NULL, "only one message at a time!");
1907 process (mp->hghsel, cmd_name, vecp, vec);
1908 seq_setcur (mp, mp->hghsel);
1912 static struct swit rmmswit[] = {
1920 rmmcmd (char **args)
1922 int msgp = 0, msgnum;
1923 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1925 while ((cp = *args++)) {
1927 switch (smatch (++cp, rmmswit)) {
1929 ambigsw (cp, rmmswit);
1932 fprintf (stderr, "-%s unknown\n", cp);
1935 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1936 print_help (buf, rmmswit, 1);
1939 if (*cp == '+' || *cp == '@') {
1940 advise (NULL, "sorry, no folders allowed!");
1948 msgs[msgp++] = "cur";
1949 for (msgnum = 0; msgnum < msgp; msgnum++)
1950 if (!m_convert (mp, msgs[msgnum]))
1961 register int msgnum, vecp;
1963 char buffer[BUFSIZ], *vec[MAXARGS];
1967 if (mp->numsel > MAXARGS - 1) {
1968 advise (NULL, "more than %d messages for %s exec",
1969 MAXARGS - 1, rmmproc);
1973 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1974 if (is_selected (mp, msgnum))
1975 vec[vecp++] = getcpy (m_name (msgnum));
1977 forkcmd (vec, rmmproc);
1978 for (vecp = 0; vec[vecp]; vecp++)
1982 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1983 if (is_selected (mp, msgnum)) {
1984 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1985 if (rename (cp, buffer) == NOTOK)
1986 admonish (buffer, "unable to rename %s to", cp);
1990 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1991 if (is_selected (mp, msgnum)) {
1992 set_deleted (mp, msgnum);
1993 unset_exists (mp, msgnum);
1996 if ((mp->nummsg -= mp->numsel) <= 0) {
1998 admonish (NULL, "no messages remaining in +%s", fmsh);
2000 admonish (NULL, "no messages remaining in %s", mp->foldpath);
2001 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2003 if (mp->lowsel == mp->lowmsg) {
2004 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2005 if (does_exist (mp, msgnum))
2007 mp->lowmsg = msgnum;
2009 if (mp->hghsel == mp->hghmsg) {
2010 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2011 if (does_exist (mp, msgnum))
2013 mp->hghmsg = msgnum;
2016 mp->msgflags |= MODIFIED;
2021 static struct swit scanswit[] = {
2027 { "form formatfile", 0 },
2029 { "format string", 5 },
2035 { "width columns", 0 },
2043 scancmd (char **args)
2045 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2047 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2048 int msgnum, optim, state;
2049 char *cp, *form = NULL, *format = NULL;
2050 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2052 static int s_optim = 0;
2053 static char *s_form = NULL, *s_format = NULL;
2055 while ((cp = *args++)) {
2057 switch (smatch (++cp, scanswit)) {
2059 ambigsw (cp, scanswit);
2062 fprintf (stderr, "-%s unknown\n", cp);
2065 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2066 print_help (buf, scanswit, 1);
2082 if (!(form = *args++) || *form == '-') {
2083 advise (NULL, "missing argument to %s", args[-2]);
2089 if (!(format = *args++) || *format == '-') {
2090 advise (NULL, "missing argument to %s", args[-2]);
2096 if (!(cp = *args++) || *cp == '-') {
2097 advise (NULL, "missing argument to %s", args[-2]);
2103 if (*cp == '+' || *cp == '@') {
2104 advise (NULL, "sorry, no folders allowed!");
2112 msgs[msgp++] = "all";
2113 for (msgnum = 0; msgnum < msgp; msgnum++)
2114 if (!m_convert (mp, msgs[msgnum]))
2118 /* Get new format string */
2119 nfs = new_fs (form, format, FORMAT);
2121 /* force scansbr to (re)compile format */
2128 s_optim = optim = 1;
2129 s_form = form ? getcpy (form) : NULL;
2130 s_format = format ? getcpy (format) : NULL;
2134 optim = equiv (s_form, form) && equiv (s_format, format);
2137 for (msgnum = mp->lowsel;
2138 msgnum <= mp->hghsel && !interrupted;
2140 if (is_selected (mp, msgnum)) {
2141 if (optim && Msgs[msgnum].m_scanl)
2142 printf ("%s", Msgs[msgnum].m_scanl);
2145 zp = msh_ready (msgnum, 0);
2146 switch (state = scan (zp, msgnum, 0, nfs, width,
2147 msgnum == mp->curmsg,
2148 is_unseen (mp, msgnum),
2149 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2150 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2156 Msgs[msgnum].m_scanl = getcpy (scanl);
2160 advise (NULL, "scan() botch (%d)", state);
2164 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2176 static struct swit showswit[] = {
2180 { "form formfile", 4 },
2182 { "moreproc program", 4 },
2184 { "nomoreproc", 3 },
2186 { "length lines", 4 },
2188 { "width columns", 4 },
2190 { "showproc program", 4 },
2192 { "noshowproc", 3 },
2204 showcmd (char **args)
2206 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2207 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2208 char *cp, *proc = showproc, buf[BUFSIZ];
2209 char *msgs[MAXARGS], *vec[MAXARGS];
2211 if (!mh_strcasecmp (cmd_name, "next"))
2214 if (!mh_strcasecmp (cmd_name, "prev"))
2216 while ((cp = *args++)) {
2218 switch (i = smatch (++cp, showswit)) {
2220 ambigsw (cp, showswit);
2227 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2228 cmd_name, mode ? NULL : "[msgs] ");
2229 print_help (buf, showswit, 1);
2237 if (!(cp = *args++) || *cp == '-') {
2238 advise (NULL, "missing argument to %s", args[-2]);
2250 if (!(proc = *args++) || *proc == '-') {
2251 advise (NULL, "missing argument to %s", args[-2]);
2261 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2264 if (*cp == '+' || *cp == '@') {
2265 advise (NULL, "sorry, no folders allowed!");
2271 "usage: %s [switches] [switches for showproc]\n",
2281 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2282 for (msgnum = 0; msgnum < msgp; msgnum++)
2283 if (!m_convert (mp, msgs[msgnum]))
2287 if (!nshow && !getenv ("NOMHNPROC"))
2288 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2289 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2290 proc = showmimeproc;
2291 vec[vecp++] = "-file";
2299 if (strcmp (showproc, "mhl") == 0) {
2305 seqnum = seq_getnum (mp, "unseen");
2306 vec[0] = r1bindex (proc, '/');
2309 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2310 if (is_selected (mp, msgnum)) {
2311 vec[vecp++] = getcpy (m_name (msgnum));
2313 seq_delmsg (mp, "unseen", msgnum);
2316 if (mp->numsel == 1 && headersw)
2318 mhlsbr (vecp, vec, mhl_action);
2319 m_eomsbr ((int (*)()) 0);
2324 for (msgnum = mp->lowsel;
2325 msgnum <= mp->hghsel && !interrupted;
2327 if (is_selected (mp, msgnum)) {
2328 switch (ask (msgnum)) {
2329 case NOTOK: /* QUIT */
2336 if (mp->numsel == 1 && headersw)
2339 copy_message (msgnum, stdout);
2341 process (msgnum, proc, vecp, vec);
2344 seq_delmsg (mp, "unseen", msgnum);
2351 seq_setcur (mp, mp->hghsel);
2358 if (Msgs[msgnum].m_bboard_id == 0)
2361 printf ("(Message %d", msgnum);
2362 if (Msgs[msgnum].m_bboard_id > 0)
2363 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2374 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2379 mhl_action (char *name)
2383 if ((msgnum = m_atoi (name)) < mp->lowmsg
2384 || msgnum > mp->hghmsg
2385 || !does_exist (mp, msgnum))
2389 mhlfp = msh_ready (msgnum, 1);
2391 m_eomsbr (eom_action);
2403 if (mp->numsel == 1 || !interactive || redirected)
2406 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2407 if (mp->lowsel != msgnum)
2409 printf ("Press <return> to list \"%d\"...", msgnum);
2414 read (fileno (stdout), buf, sizeof buf);
2416 if (strchr(buf, '\n') == NULL)
2420 told_to_quit = interrupted = 0;
2435 is_nontext (int msgnum)
2438 unsigned char *bp, *dp;
2440 char buf[BUFSIZ], name[NAMESZ];
2443 if (Msgs[msgnum].m_flags & MHNCHK)
2444 return (Msgs[msgnum].m_flags & MHNYES);
2445 Msgs[msgnum].m_flags |= MHNCHK;
2447 fp = msh_ready (msgnum, 1);
2450 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2455 * Check Content-Type field
2457 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2461 cp = add (buf, NULL);
2462 while (state == FLDPLUS) {
2463 state = m_getfld (state, name, buf, sizeof buf, fp);
2470 for (; isspace (*bp); bp++)
2475 for (bp++, i = 0;;) {
2505 for (dp = bp; istoken (*dp); dp++)
2512 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2515 for (dp++; isspace (*dp); dp++)
2518 if ((result = !uprf (dp, "charset")))
2520 dp += sizeof "charset" - 1;
2521 while (isspace (*dp))
2525 while (isspace (*dp))
2528 if ((bp = strchr(++dp, '"')))
2531 for (bp = dp; *bp; bp++)
2532 if (isspace (*bp)) {
2538 /* Default character set */
2541 /* Check the character set */
2542 result = !check_charset (dp, strlen (dp));
2544 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2554 Msgs[msgnum].m_flags |= MHNYES;
2561 * Check Content-Transfer-Encoding field
2563 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2564 cp = add (buf, NULL);
2565 while (state == FLDPLUS) {
2566 state = m_getfld (state, name, buf, sizeof buf, fp);
2569 for (bp = cp; isspace (*bp); bp++)
2571 for (dp = bp; istoken (*dp); dp++)
2574 result = (mh_strcasecmp (bp, "7bit")
2575 && mh_strcasecmp (bp, "8bit")
2576 && mh_strcasecmp (bp, "binary"));
2580 Msgs[msgnum].m_flags |= MHNYES;
2587 * Just skip the rest of this header
2588 * field and go to next one.
2590 while (state == FLDPLUS)
2591 state = m_getfld (state, name, buf, sizeof(buf), fp);
2595 * We've passed the message header,
2596 * so message is just text.
2604 static struct swit sortswit[] = {
2606 { "datefield field", 0 },
2608 { "textfield field", 0 },
2610 { "notextfield", 0 },
2612 { "limit days", 0 },
2626 sortcmd (char **args)
2628 int msgp = 0, msgnum;
2629 char *cp, *datesw = NULL, *subjsw = NULL;
2630 char buf[BUFSIZ], *msgs[MAXARGS];
2634 forkcmd (args, cmd_name);
2638 while ((cp = *args++)) {
2640 switch (smatch (++cp, sortswit)) {
2642 ambigsw (cp, sortswit);
2645 fprintf (stderr, "-%s unknown\n", cp);
2648 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2649 print_help (buf, sortswit, 1);
2654 advise (NULL, "only one date field at a time!");
2657 if (!(datesw = *args++) || *datesw == '-') {
2658 advise (NULL, "missing argument to %s", args[-2]);
2665 advise (NULL, "only one text field at a time!");
2668 if (!(subjsw = *args++) || *subjsw == '-') {
2669 advise (NULL, "missing argument to %s", args[-2]);
2677 case SOLIMT: /* too hard */
2678 if (!(cp = *args++) || *cp == '-') {
2679 advise (NULL, "missing argument to %s", args[-2]);
2683 case SOVERB: /* not implemented */
2687 if (*cp == '+' || *cp == '@') {
2688 advise (NULL, "sorry, no folders allowed!");
2696 msgs[msgp++] = "all";
2699 for (msgnum = 0; msgnum < msgp; msgnum++)
2700 if (!m_convert (mp, msgs[msgnum]))
2704 twscopy (&tb, dlocaltimenow ());
2706 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2707 if (Msgs[msgnum].m_scanl) {
2708 free (Msgs[msgnum].m_scanl);
2709 Msgs[msgnum].m_scanl = NULL;
2711 if (is_selected (mp, msgnum)) {
2712 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2713 twscopy (&Msgs[msgnum].m_tb,
2714 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2716 else /* m_scaln is already NULL */
2717 twscopy (&Msgs[msgnum].m_tb, &tb);
2718 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2719 if (mp->curmsg == msgnum)
2720 Msgs[msgnum].m_stats |= CUR;
2723 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2724 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2726 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2727 if (subjsw && Msgs[msgnum].m_scanl) {
2728 free (Msgs[msgnum].m_scanl); /* from subjsort */
2729 Msgs[msgnum].m_scanl = NULL;
2731 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2732 if (Msgs[msgnum].m_stats & CUR)
2733 seq_setcur (mp, msgnum);
2736 mp->msgflags |= MODIFIED;
2742 * get_fields - parse message, and get date and subject if needed.
2743 * We'll use the msgp->m_tb tws struct for the date, and overload
2744 * the msgp->m_scanl field with our subject string.
2747 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2749 int state, gotdate = 0;
2750 char *bp, buf[BUFSIZ], name[NAMESZ];
2751 struct tws *tw = (struct tws *) 0;
2754 zp = msh_ready (msgnum, 0);
2755 for (state = FLD;;) {
2756 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2760 if (!mh_strcasecmp (name, datesw)) {
2762 while (state == FLDPLUS) {
2763 state = m_getfld (state, name, buf, sizeof buf, zp);
2766 if ((tw = dparsetime (bp)) == NULL)
2768 "unable to parse %s field in message %d",
2771 twscopy (&(msgp->m_tb), tw);
2773 if (!subjsw) /* not using this, or already done */
2774 break; /* all done! */
2777 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2779 while (state == FLDPLUS) {
2780 state = m_getfld (state, name, buf, sizeof buf, zp);
2783 msgp->m_scanl = sosmash(subjsw, bp);
2785 break; /* date done so we're done */
2787 subjsw = (char *)0;/* subject done, need date */
2789 while (state == FLDPLUS) /* flush this one */
2790 state = m_getfld (state, name, buf, sizeof buf, zp);
2801 admonish (NULL, "format error in message %d", msgnum);
2802 if (msgp->m_scanl) { /* this might need free'd */
2803 free (msgp->m_scanl); /* probably can't use subj anyway */
2804 msgp->m_scanl = NULL;
2809 adios (NULL, "internal error -- you lose");
2814 return OK; /* not an error if subj not found */
2816 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2817 return NOTOK; /* NOTOK means use some other date */
2826 msgsort (struct Msg *a, struct Msg *b)
2828 return twsort (&a->m_tb, &b->m_tb);
2833 subsort (struct Msg *a, struct Msg *b)
2837 if (a->m_scanl && b->m_scanl)
2838 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2841 return twsort (&a->m_tb, &b->m_tb);
2846 * try to make the subject "canonical": delete leading "re:", everything
2847 * but letters & smash letters to lower case.
2850 sosmash (char *subj, char *s)
2852 register char *cp, *dp;
2853 register unsigned char c;
2857 dp = s; /* dst pointer */
2858 if (!mh_strcasecmp (subj, "subject"))
2865 *dp++ = isupper(c) ? tolower(c) : c;
2871 while ((c = *cp++)) {
2873 *dp++ = isupper(c) ? tolower(c) : c;
2883 process (int msgnum, char *proc, int vecp, char **vec)
2885 int child_id, status;
2886 char tmpfil[BUFSIZ];
2891 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2892 context_del (pfolder);
2893 context_replace (pfolder, fmsh);/* update current folder */
2895 context_save (); /* save the context file */
2899 cp = m_mktemp(invo_name, NULL, &out);
2901 /* Try again, but try to create under /tmp */
2903 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2906 advise (NULL, "unable to create temporary file");
2910 copy_message (msgnum, out);
2912 strncpy(tmpfil, cp, sizeof(tmpfil));
2916 switch (child_id = fork ()) {
2918 advise ("fork", "unable to");
2924 SIGNAL (SIGINT, istat);
2925 SIGNAL (SIGQUIT, qstat);
2927 vec[vecp++] = tmpfil;
2931 fprintf (stderr, "unable to exec ");
2936 status = pidXwait (child_id, NULL);
2947 copy_message (int msgnum, FILE *out)
2950 static char buffer[BUFSIZ];
2953 zp = msh_ready (msgnum, 1);
2955 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2956 fputs (buffer, out);
2957 if (interrupted && out == stdout)
2963 while (fgets (buffer, sizeof buffer, zp) != NULL
2964 && pos < Msgs[msgnum].m_stop) {
2965 fputs (buffer, out);
2966 pos += (long) strlen (buffer);
2967 if (interrupted && out == stdout)
2975 copy_digest (int msgnum, FILE *out)
2979 static char buffer[BUFSIZ];
2983 zp = msh_ready (msgnum, 1);
2986 while (fgets (buffer, sizeof buffer, zp) != NULL
2987 && !fmsh && pos < Msgs[msgnum].m_stop) {
2988 if (c == '\n' && *buffer == '-')
2990 fputs (buffer, out);
2991 c = buffer[strlen (buffer) - 1];
2993 pos += (long) strlen (buffer);
2994 if (interrupted && out == stdout)