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>
21 #include <h/picksbr.h>
25 static char delim3[] = "-------"; /* from burst.c */
31 * Type for a compare function for qsort. This keeps
34 typedef int (*qsort_comp) (const void *, const void *);
39 void clear_screen (void); /* from termsbr.c */
40 int SOprintf (char *, ...); /* from termsbr.c */
41 int sc_width (void); /* from termsbr.c */
46 static int burst (struct Msg *, int, int, int, int);
47 static void forw (char *, char *, int, char **);
48 static void rmm (void);
49 static void show (int);
50 static int eom_action (int);
51 static FILE *mhl_action (char *);
53 static int is_nontext (int);
54 static int get_fields (char *, char *, int, struct Msg *);
55 static int msgsort (struct Msg *, struct Msg *);
56 static int subsort (struct Msg *, struct Msg *);
57 static char *sosmash (char *, char *);
58 static int process (int, char *, int, char **);
59 static void copy_message (int, FILE *);
60 static void copy_digest (int, FILE *);
63 int mhlsbr (int, char **, FILE *(*)());
66 forkcmd (char **args, char *pgm)
71 vec[0] = r1bindex (pgm, '/');
72 copyip (args, vec + 1, MAXARGS - 1);
75 context_del (pfolder);
76 context_replace (pfolder, fmsh);/* update current folder */
78 context_save (); /* save the context file */
81 switch (child_id = fork ()) {
83 advise ("fork", "unable to");
88 SIGNAL (SIGINT, istat);
89 SIGNAL (SIGQUIT, qstat);
92 fprintf (stderr, "unable to exec ");
97 pidXwait (child_id, NULL);
100 if (fmsh) { /* assume the worst case */
101 mp->msgflags |= MODIFIED;
107 static struct swit distswit[] = {
113 { "draftfolder +folder", 0 },
115 { "draftmessage msg", 0 },
117 { "nodraftfolder", 0 },
119 { "editor editor", 0 },
123 { "form formfile", 0 },
129 { "whatnowproc program", 0 },
131 { "nowhatnowproc", 0 },
139 distcmd (char **args)
142 char *cp, *msg = NULL;
143 char buf[BUFSIZ], *vec[MAXARGS];
146 forkcmd (args, cmd_name);
150 while ((cp = *args++)) {
152 switch (smatch (++cp, distswit)) {
154 ambigsw (cp, distswit);
157 fprintf (stderr, "-%s unknown\n", cp);
160 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
161 print_help (buf, distswit, 1);
164 case DIANSW: /* not implemented */
182 if (!(cp = *args++) || *cp == '-') {
183 advise (NULL, "missing argument to %s", args[-2]);
189 if (*cp == '+' || *cp == '@') {
190 advise (NULL, "sorry, no folders allowed!");
195 advise (NULL, "only one message at a time!");
203 vec[vecp++] = "-file";
207 if (!m_convert (mp, msg))
211 if (mp->numsel > 1) {
212 advise (NULL, "only one message at a time!");
215 process (mp->hghsel, cmd_name, vecp, vec);
216 seq_setcur (mp, mp->hghsel);
220 static struct swit explswit[] = {
240 explcmd (char **args)
242 int inplace = 0, quietsw = 0, verbosw = 0;
243 int msgp = 0, hi, msgnum;
244 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
248 forkcmd (args, cmd_name);
252 while ((cp = *args++)) {
254 switch (smatch (++cp, explswit)) {
256 ambigsw (cp, explswit);
259 fprintf (stderr, "-%s unknown\n", cp);
262 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
263 print_help (buf, explswit, 1);
285 if (*cp == '+' || *cp == '@') {
286 advise (NULL, "sorry, no folders allowed!");
294 msgs[msgp++] = "cur";
295 for (msgnum = 0; msgnum < msgp; msgnum++)
296 if (!m_convert (mp, msgs[msgnum]))
300 smsgs = (struct Msg *)
301 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
303 adios (NULL, "unable to allocate folder storage");
307 for (msgnum = mp->lowsel;
308 msgnum <= mp->hghsel && !interrupted;
310 if (is_selected (mp, msgnum))
311 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
314 free ((char *) smsgs);
317 seq_setcur (mp, mp->lowsel);
319 if (hi <= mp->hghmsg)
322 mp->msgflags |= MODIFIED;
328 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
330 int i, j, ld3, wasdlm, msgp;
332 char c, buffer[BUFSIZ];
335 ld3 = strlen (delim3);
337 if (Msgs[msgnum].m_scanl) {
338 free (Msgs[msgnum].m_scanl);
339 Msgs[msgnum].m_scanl = NULL;
342 pos = ftell (zp = msh_ready (msgnum, 1));
343 for (msgp = 0; msgp <= MAXFOLDER;) {
344 while (fgets (buffer, sizeof buffer, zp) != NULL
346 && pos < Msgs[msgnum].m_stop)
347 pos += (long) strlen (buffer);
348 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
350 fseek (zp, pos, SEEK_SET);
351 smsgs[msgp].m_start = pos;
354 pos < Msgs[msgnum].m_stop
355 && fgets (buffer, sizeof buffer, zp) != NULL;
357 if (strncmp (buffer, delim3, ld3) == 0
358 && (msgp == 1 || c == '\n')
359 && peekc (zp) == '\n')
362 pos += (long) strlen (buffer);
364 wasdlm = strncmp (buffer, delim3, ld3) == 0;
365 if (smsgs[msgp].m_start != pos)
366 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
367 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
369 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
372 pos += (long) strlen (buffer);
375 switch (msgp--) { /* toss "End of XXX Digest" */
377 adios (NULL, "burst() botch -- you lose big");
381 printf ("message %d not in digest format\n", msgnum);
386 printf ("%d message%s exploded from digest %d\n",
387 msgp, msgp != 1 ? "s" : "", msgnum);
391 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
392 advise (NULL, "more than %d messages", MAXFOLDER);
395 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
396 adios (NULL, "unable to allocate folder storage");
401 if (mp->hghsel > msgnum)
405 for (i = mp->hghmsg; j > msgnum; i--, j--) {
407 printf ("message %d becomes message %d\n", j, i);
409 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
410 Msgs[i].m_top = Msgs[j].m_top;
411 Msgs[i].m_start = Msgs[j].m_start;
412 Msgs[i].m_stop = Msgs[j].m_stop;
413 Msgs[i].m_scanl = NULL;
414 if (Msgs[j].m_scanl) {
415 free (Msgs[j].m_scanl);
416 Msgs[j].m_scanl = NULL;
418 copy_msg_flags (mp, i, j);
421 if (Msgs[msgnum].m_bboard_id == 0)
424 unset_selected (mp, msgnum);
425 i = inplace ? msgnum + msgp : mp->hghmsg;
426 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
427 if (verbosw && i != msgnum)
428 printf ("message %d of digest %d becomes message %d\n",
431 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
432 Msgs[i].m_top = Msgs[j].m_top;
433 Msgs[i].m_start = smsgs[j].m_start;
434 Msgs[i].m_stop = smsgs[j].m_stop;
435 Msgs[i].m_scanl = NULL;
436 copy_msg_flags (mp, i, msgnum);
443 static struct swit fileswit[] = {
455 { "src +folder", 0 },
459 { "rmmproc program", 0 },
469 filecmd (char **args)
471 int linksw = 0, msgp = 0;
472 int vecp = 1, i, msgnum;
473 char *cp, buf[BUFSIZ];
474 char *msgs[MAXARGS], *vec[MAXARGS];
477 forkcmd (args, cmd_name);
481 while ((cp = *args++)) {
483 switch (i = smatch (++cp, fileswit)) {
485 ambigsw (cp, fileswit);
488 fprintf (stderr, "-%s unknown\n", cp);
491 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
492 print_help (buf, fileswit, 1);
511 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
514 if (*cp == '+' || *cp == '@')
521 vec[vecp++] = "-file";
524 msgs[msgp++] = "cur";
525 for (msgnum = 0; msgnum < msgp; msgnum++)
526 if (!m_convert (mp, msgs[msgnum]))
531 for (msgnum = mp->lowsel;
532 msgnum <= mp->hghsel && !interrupted;
534 if (is_selected (mp, msgnum))
535 if (process (msgnum, fileproc, vecp, vec)) {
536 unset_selected (mp, msgnum);
540 if (mp->numsel != mp->nummsg || linksw)
541 seq_setcur (mp, mp->hghsel);
548 filehak (char **args)
550 int result, vecp = 0;
551 char *cp, *cwd, *vec[MAXARGS];
553 while ((cp = *args++)) {
555 switch (smatch (++cp, fileswit)) {
572 if (*cp == '+' || *cp == '@')
579 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
581 cwd = getcpy (pwd ());
582 chdir (m_maildir (""));
584 if (access (m_maildir (cp), F_OK) == NOTOK)
595 static struct swit foldswit[] = {
633 foldcmd (char **args)
635 int fastsw = 0, headersw = 0, packsw = 0;
637 char *cp, *folder = NULL, *msg = NULL;
638 char buf[BUFSIZ], **vec = args;
643 while ((cp = *args++)) {
645 switch (smatch (++cp, foldswit)) {
647 ambigsw (cp, foldswit);
650 fprintf (stderr, "-%s unknown\n", cp);
653 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
654 print_help (buf, foldswit, 1);
657 case FLALSW: /* not implemented */
687 if (*cp == '+' || *cp == '@') {
689 advise (NULL, "only one folder at a time!\n");
693 folder = fmsh ? pluspath (cp)
698 advise (NULL, "only one message at a time!\n");
707 advise (NULL, "null folder names are not permitted");
711 if (access (m_maildir (folder), R_OK) == NOTOK) {
712 advise (folder, "unable to read");
717 strncpy (buf, folder, sizeof(buf));
718 if (expand (buf) == NOTOK)
721 if (access (folder, R_OK) == NOTOK) {
722 advise (folder, "unable to read");
737 if (!m_convert (mp, msg))
741 if (mp->numsel > 1) {
742 advise (NULL, "only one message at a time!");
745 seq_setcur (mp, mp->hghsel);
750 forkcmd (vec, cmd_name);
754 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
755 adios (NULL, "unable to allocate folder storage");
757 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
758 if (does_exist (mp, msgnum)) {
759 if (msgnum != hole) {
760 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
761 Msgs[hole].m_top = Msgs[msgnum].m_top;
762 Msgs[hole].m_start = Msgs[msgnum].m_start;
763 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
764 Msgs[hole].m_scanl = NULL;
765 if (Msgs[msgnum].m_scanl) {
766 free (Msgs[msgnum].m_scanl);
767 Msgs[msgnum].m_scanl = NULL;
769 copy_msg_flags (mp, hole, msgnum);
770 if (mp->curmsg == msgnum)
771 seq_setcur (mp, hole);
775 if (mp->nummsg > 0) {
777 mp->hghmsg = hole - 1;
779 mp->msgflags |= MODIFIED;
785 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
788 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
789 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
791 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
793 /* check for empty folder */
794 if (mp->nummsg == 0) {
795 printf ("has no messages%*s",
796 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
798 printf ("has %*d message%s (%*d-%*d)",
799 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
800 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
801 if (mp->curmsg >= mp->lowmsg
802 && mp->curmsg <= mp->hghmsg)
803 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
810 static struct swit forwswit[] = {
816 { "draftfolder +folder", 0 },
818 { "draftmessage msg", 0 },
820 { "nodraftfolder", 0 },
822 { "editor editor", 0 },
826 { "filter filterfile", 0 },
828 { "form formfile", 0 },
842 { "whatnowproc program", 0 },
852 forwcmd (char **args)
854 int msgp = 0, vecp = 1, msgnum;
855 char *cp, *filter = NULL, buf[BUFSIZ];
856 char *msgs[MAXARGS], *vec[MAXARGS];
861 forkcmd (args, cmd_name);
865 while ((cp = *args++)) {
867 switch (smatch (++cp, forwswit)) {
869 ambigsw (cp, forwswit);
872 fprintf (stderr, "-%s unknown\n", cp);
875 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
876 print_help (buf, forwswit, 1);
879 case FOANSW: /* not implemented */
899 if (!(cp = *args++) || *cp == '-') {
900 advise (NULL, "missing argument to %s", args[-2]);
906 if (!(filter = *args++) || *filter == '-') {
907 advise (NULL, "missing argument to %s", args[-2]);
912 if (access (filter = myfilter, R_OK) == NOTOK) {
913 advise (filter, "unable to read default filter file");
921 if (*cp == '+' || *cp == '@') {
922 advise (NULL, "sorry, no folders allowed!");
929 /* foil search of .mh_profile */
930 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
932 tfile = m_mktemp(buf, NULL, NULL);
933 if (tfile == NULL) adios("forwcmd", "unable to create temporary file");
934 strncpy (tmpfil, tfile, sizeof(tmpfil));
937 vec[vecp++] = "-file";
940 msgs[msgp++] = "cur";
941 for (msgnum = 0; msgnum < msgp; msgnum++)
942 if (!m_convert (mp, msgs[msgnum]))
947 strncpy (buf, filter, sizeof(buf));
948 if (expand (buf) == NOTOK)
950 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
951 advise (filter, "unable to read");
956 forw (cmd_name, filter, vecp, vec);
957 seq_setcur (mp, mp->hghsel);
964 forw (char *proc, char *filter, int vecp, char **vec)
966 int i, child_id, msgnum, msgcnt;
967 char tmpfil[BUFSIZ], *args[MAXARGS];
971 tfile = m_mktemp2(NULL, invo_name, NULL, NULL);
972 if (tfile == NULL) adios("forw", "unable to create temporary file");
973 strncpy (tmpfil, tfile, sizeof(tmpfil));
977 switch (child_id = fork ()) {
979 advise ("fork", "unable to");
982 case OK: /* "trust me" */
983 if (freopen (tmpfil, "w", stdout) == NULL) {
984 fprintf (stderr, "unable to create ");
988 args[0] = r1bindex (mhlproc, '/');
990 args[i++] = "-forwall";
993 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
994 if (is_selected (mp, msgnum))
995 args[i++] = getcpy (m_name (msgnum));
997 mhlsbr (i, args, mhl_action);
998 m_eomsbr ((int (*) ()) 0);
1003 if (pidXwait (child_id, NULL))
1008 if ((out = fopen (tmpfil, "w")) == NULL) {
1009 advise (tmpfil, "unable to create temporary file");
1014 for (msgnum = mp->lowsel;
1015 msgnum <= mp->hghsel && !interrupted;
1017 if (is_selected (mp, msgnum)) {
1018 fprintf (out, "\n\n-------");
1019 if (msgnum == mp->lowsel)
1020 fprintf (out, " Forwarded Message%s",
1021 mp->numsel > 1 ? "s" : "");
1023 fprintf (out, " Message %d", msgcnt);
1024 fprintf (out, "\n\n");
1025 copy_digest (msgnum, out);
1029 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1030 mp->numsel > 1 ? "s" : "");
1036 switch (child_id = fork ()) {
1038 advise ("fork", "unable to");
1043 SIGNAL (SIGINT, istat);
1044 SIGNAL (SIGQUIT, qstat);
1046 vec[vecp++] = tmpfil;
1050 fprintf (stderr, "unable to exec ");
1055 pidXwait (child_id, NULL);
1063 static char *hlpmsg[] = {
1064 "The %s program emulates many of the commands found in the nmh",
1065 "system. Instead of operating on nmh folders, commands to %s concern",
1068 "To see the list of commands available, just type a ``?'' followed by",
1069 "the RETURN key. To find out what switches each command takes, type",
1070 "the name of the command followed by ``-help''. To leave %s, use the",
1071 "``quit'' command.",
1073 "Although a lot of nmh commands are found in %s, not all are fully",
1074 "implemented. %s will always recognize all legal switches for a",
1075 "given command though, and will let you know when you ask for an",
1076 "option that it is unable to perform.",
1078 "Running %s is fun, but using nmh from your shell is far superior.",
1079 "After you have familiarized yourself with the nmh style by using %s,",
1080 "you should try using nmh from the shell. You can still use %s for",
1081 "message files that aren't in nmh format, such as BBoard files.",
1087 helpcmd (char **args)
1091 for (i = 0; hlpmsg[i]; i++) {
1092 printf (hlpmsg[i], invo_name);
1098 static struct swit markswit[] = {
1106 { "sequence name", 0 },
1124 markcmd (char **args)
1126 int addsw = 0, deletesw = 0, debugsw = 0;
1127 int listsw = 0, zerosw = 0, seqp = 0;
1128 int msgp = 0, msgnum;
1129 char *cp, buf[BUFSIZ];
1130 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1132 while ((cp = *args++)) {
1134 switch (smatch (++cp, markswit)) {
1136 ambigsw (cp, markswit);
1139 fprintf (stderr, "-%s unknown\n", cp);
1142 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1143 print_help (buf, markswit, 1);
1148 deletesw = listsw = 0;
1156 addsw = deletesw = 0;
1160 if (!(cp = *args++) || *cp == '-') {
1161 advise (NULL, "missing argument to %s", args[-2]);
1164 if (seqp < NUMATTRS)
1167 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1172 case MPUBSW: /* not implemented */
1188 if (*cp == '+' || *cp == '@') {
1189 advise (NULL, "sorry, no folders allowed!");
1196 if (!addsw && !deletesw && !listsw) {
1203 seqs[seqp++] = "unseen";
1207 msgs[msgp++] = "all";
1212 msgs[msgp++] = listsw ? "all" :"cur";
1213 for (msgnum = 0; msgnum < msgp; msgnum++)
1214 if (!m_convert (mp, msgs[msgnum]))
1218 printf ("invo_name=%s mypath=%s defpath=%s\n",
1219 invo_name, mypath, defpath);
1220 printf ("ctxpath=%s context flags=%s\n",
1221 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1222 printf ("foldpath=%s flags=%s\n",
1224 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1225 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1226 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1227 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1228 mp->lowsel, mp->hghsel, mp->numsel);
1229 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1232 if (seqp == 0 && (addsw || deletesw)) {
1233 advise (NULL, "-%s requires at least one -sequence argument",
1234 addsw ? "add" : "delete");
1240 for (seqp = 0; seqs[seqp]; seqp++)
1241 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1246 for (seqp = 0; seqs[seqp]; seqp++)
1247 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1251 /* Listing messages in sequences */
1254 /* list the given sequences */
1255 for (seqp = 0; seqs[seqp]; seqp++)
1256 seq_print (mp, seqs[seqp]);
1258 /* else list them all */
1264 for (msgnum = mp->lowsel;
1265 msgnum <= mp->hghsel && !interrupted;
1267 if (is_selected (mp, msgnum)) {
1268 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1271 Msgs[msgnum].m_bboard_id,
1273 (long) Msgs[msgnum].m_start,
1274 (long) Msgs[msgnum].m_stop,
1275 snprintb (buf, sizeof(buf),
1276 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1278 if (Msgs[msgnum].m_scanl)
1279 printf ("%s", Msgs[msgnum].m_scanl);
1285 static struct swit mhnswit[] = {
1288 #define MHNNAUTOSW 1
1290 #define MHNDEBUGSW 2
1292 #define MHNEBCDICSW 3
1293 { "ebcdicsafe", 0 },
1294 #define MHNNEBCDICSW 4
1295 { "noebcdicsafe", 0 },
1297 { "form formfile", 4 },
1300 #define MHNNHEADSW 7
1304 #define MHNNLISTSW 9
1306 #define MHNPARTSW 10
1307 { "part number", 0 },
1308 #define MHNSIZESW 11
1310 #define MHNNSIZESW 12
1311 { "norealsize", 0 },
1312 #define MHNRFC934SW 13
1313 { "rfc934mode", 0 },
1314 #define MHNNRFC934SW 14
1315 { "norfc934mode", 0 },
1316 #define MHNSERIALSW 15
1317 { "serialonly", 0 },
1318 #define MHNNSERIALSW 16
1319 { "noserialonly", 0 },
1320 #define MHNSHOWSW 17
1322 #define MHNNSHOWSW 18
1324 #define MHNSTORESW 19
1326 #define MHNNSTORESW 20
1328 #define MHNTYPESW 21
1329 { "type content", 0 },
1330 #define MHNVERBSW 22
1332 #define MHNNVERBSW 23
1334 #define MHNHELPSW 24
1336 #define MHNPROGSW 25
1337 { "moreproc program", -4 },
1338 #define MHNNPROGSW 26
1339 { "nomoreproc", -3 },
1341 { "length lines", -4 },
1343 { "width columns", -4 },
1349 mhncmd (char **args)
1351 int msgp = 0, vecp = 1;
1353 char *cp, buf[BUFSIZ];
1354 char *msgs[MAXARGS], *vec[MAXARGS];
1357 forkcmd (args, cmd_name);
1360 while ((cp = *args++)) {
1362 switch (smatch (++cp, mhnswit)) {
1364 ambigsw (cp, mhnswit);
1367 fprintf (stderr, "-%s unknown\n", cp);
1370 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1371 print_help (buf, mhnswit, 1);
1406 if (!(cp = *args++) || *cp == '-') {
1407 advise (NULL, "missing argument to %s", args[-2]);
1414 if (*cp == '+' || *cp == '@') {
1415 advise (NULL, "sorry, no folders allowed!");
1423 vec[vecp++] = "-file";
1426 msgs[msgp++] = "cur";
1427 for (msgnum = 0; msgnum < msgp; msgnum++)
1428 if (!m_convert (mp, msgs[msgnum]))
1433 for (msgnum = mp->lowsel;
1434 msgnum <= mp->hghsel && !interrupted;
1436 if (is_selected (mp, msgnum))
1437 if (process (msgnum, cmd_name, vecp, vec)) {
1438 unset_selected (mp, msgnum);
1442 seq_setcur (mp, mp->hghsel);
1446 static struct swit packswit[] = {
1454 static int mbx_style = MMDF_FORMAT;
1457 packcmd (char **args)
1459 int msgp = 0, md, msgnum;
1460 char *cp, *file = NULL;
1461 char buf[BUFSIZ], *msgs[MAXARGS];
1465 forkcmd (args, cmd_name);
1469 while ((cp = *args++)) {
1471 switch (smatch (++cp, packswit)) {
1473 ambigsw (cp, packswit);
1476 fprintf (stderr, "-%s unknown\n", cp);
1479 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1480 print_help (buf, packswit, 1);
1484 if (!(file = *args++) || *file == '-') {
1485 advise (NULL, "missing argument to %s", args[-2]);
1490 if (*cp == '+' || *cp == '@') {
1491 advise (NULL, "sorry, no folders allowed!");
1500 file = path (file, TFILE);
1501 if (stat (file, &st) == NOTOK) {
1502 if (errno != ENOENT) {
1503 advise (file, "error on file");
1506 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1513 msgs[msgp++] = "all";
1514 for (msgnum = 0; msgnum < msgp; msgnum++)
1515 if (!m_convert (mp, msgs[msgnum]))
1519 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1520 advise (file, "unable to open");
1523 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1524 if (is_selected (mp, msgnum))
1525 if (pack (file, md, msgnum) == NOTOK)
1527 mbx_close (file, md);
1529 if (mp->hghsel != mp->curmsg)
1530 seq_setcur (mp, mp->lowsel);
1538 pack (char *mailbox, int md, int msgnum)
1542 if (Msgs[msgnum].m_bboard_id == 0)
1545 zp = msh_ready (msgnum, 1);
1546 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1547 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1552 packhak (char **args)
1555 char *cp, *file = NULL;
1557 while ((cp = *args++)) {
1559 switch (smatch (++cp, packswit)) {
1566 if (!(file = *args++) || *file == '-')
1570 if (*cp == '+' || *cp == '@')
1574 file = path (file ? file : "./msgbox", TFILE);
1575 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1582 static struct swit pickswit[] = {
1594 { "cc pattern", 0 },
1596 { "date pattern", 0 },
1598 { "from pattern", 0 },
1600 { "search pattern", 0 },
1602 { "subject pattern", 0 },
1604 { "to pattern", 0 },
1606 { "-othercomponent pattern", 15 },
1608 { "after date", 0 },
1610 { "before date", 0 },
1612 { "datefield field", 5 },
1614 { "sequence name", 0 },
1634 pickcmd (char **args)
1636 int zerosw = 1, msgp = 0, seqp = 0;
1637 int vecp = 0, hi, lo, msgnum;
1638 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1639 char *seqs[NUMATTRS], *vec[MAXARGS];
1642 while ((cp = *args++)) {
1648 switch (smatch (cp, pickswit)) {
1650 ambigsw (cp, pickswit);
1653 fprintf (stderr, "-%s unknown\n", cp);
1656 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1657 print_help (buf, pickswit, 1);
1671 if (!(cp = *args++)) {/* allow -xyz arguments */
1672 advise (NULL, "missing argument to %s", args[-2]);
1678 advise (NULL, "internal error!");
1689 if (!(cp = *args++) || *cp == '-') {
1690 advise (NULL, "missing argument to %s", args[-2]);
1693 if (seqp < NUMATTRS)
1696 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1707 case PIPUSW: /* not implemented */
1714 if (*cp == '+' || *cp == '@') {
1715 advise (NULL, "sorry, no folders allowed!");
1724 msgs[msgp++] = "all";
1725 for (msgnum = 0; msgnum < msgp; msgnum++)
1726 if (!m_convert (mp, msgs[msgnum]))
1731 if (!pcompile (vec, NULL))
1737 for (msgnum = mp->lowsel;
1738 msgnum <= mp->hghsel && !interrupted;
1740 if (is_selected (mp, msgnum)) {
1741 zp = msh_ready (msgnum, 1);
1742 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1743 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1750 unset_selected (mp, msgnum);
1761 if (mp->numsel <= 0) {
1762 advise (NULL, "no messages match specification");
1767 for (seqp = 0; seqs[seqp]; seqp++)
1768 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1771 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1775 static struct swit replswit[] = {
1779 { "noannotate", 0 },
1785 { "draftfolder +folder", 0 },
1787 { "draftmessage msg", 0 },
1789 { "nodraftfolder", 0 },
1791 { "editor editor", 0 },
1795 { "fcc +folder", 0 },
1797 { "filter filterfile", 0 },
1799 { "form formfile", 0 },
1809 { "whatnowproc program", 0 },
1813 { "width columns", 0 },
1821 replcmd (char **args)
1824 char *cp, *msg = NULL;
1825 char buf[BUFSIZ], *vec[MAXARGS];
1828 forkcmd (args, cmd_name);
1832 while ((cp = *args++)) {
1834 switch (smatch (++cp, replswit)) {
1836 ambigsw (cp, replswit);
1839 fprintf (stderr, "-%s unknown\n", cp);
1842 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1843 print_help (buf, replswit, 1);
1846 case REANSW: /* not implemented */
1871 if (!(cp = *args++) || *cp == '-') {
1872 advise (NULL, "missing argument to %s", args[-2]);
1878 if (*cp == '+' || *cp == '@') {
1879 advise (NULL, "sorry, no folders allowed!");
1884 advise (NULL, "only one message at a time!");
1892 vec[vecp++] = "-file";
1896 if (!m_convert (mp, msg))
1900 if (mp->numsel > 1) {
1901 advise (NULL, "only one message at a time!");
1904 process (mp->hghsel, cmd_name, vecp, vec);
1905 seq_setcur (mp, mp->hghsel);
1909 static struct swit rmmswit[] = {
1917 rmmcmd (char **args)
1919 int msgp = 0, msgnum;
1920 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1922 while ((cp = *args++)) {
1924 switch (smatch (++cp, rmmswit)) {
1926 ambigsw (cp, rmmswit);
1929 fprintf (stderr, "-%s unknown\n", cp);
1932 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1933 print_help (buf, rmmswit, 1);
1936 if (*cp == '+' || *cp == '@') {
1937 advise (NULL, "sorry, no folders allowed!");
1945 msgs[msgp++] = "cur";
1946 for (msgnum = 0; msgnum < msgp; msgnum++)
1947 if (!m_convert (mp, msgs[msgnum]))
1958 register int msgnum, vecp;
1960 char buffer[BUFSIZ], *vec[MAXARGS];
1964 if (mp->numsel > MAXARGS - 1) {
1965 advise (NULL, "more than %d messages for %s exec",
1966 MAXARGS - 1, rmmproc);
1970 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1971 if (is_selected (mp, msgnum))
1972 vec[vecp++] = getcpy (m_name (msgnum));
1974 forkcmd (vec, rmmproc);
1975 for (vecp = 0; vec[vecp]; vecp++)
1979 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1980 if (is_selected (mp, msgnum)) {
1981 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1982 if (rename (cp, buffer) == NOTOK)
1983 admonish (buffer, "unable to rename %s to", cp);
1987 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1988 if (is_selected (mp, msgnum)) {
1989 set_deleted (mp, msgnum);
1990 unset_exists (mp, msgnum);
1993 if ((mp->nummsg -= mp->numsel) <= 0) {
1995 admonish (NULL, "no messages remaining in +%s", fmsh);
1997 admonish (NULL, "no messages remaining in %s", mp->foldpath);
1998 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2000 if (mp->lowsel == mp->lowmsg) {
2001 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2002 if (does_exist (mp, msgnum))
2004 mp->lowmsg = msgnum;
2006 if (mp->hghsel == mp->hghmsg) {
2007 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2008 if (does_exist (mp, msgnum))
2010 mp->hghmsg = msgnum;
2013 mp->msgflags |= MODIFIED;
2018 static struct swit scanswit[] = {
2024 { "form formatfile", 0 },
2026 { "format string", 5 },
2032 { "width columns", 0 },
2040 scancmd (char **args)
2042 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2044 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2045 int msgnum, optim, state;
2046 char *cp, *form = NULL, *format = NULL;
2047 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2049 static int s_optim = 0;
2050 static char *s_form = NULL, *s_format = NULL;
2052 while ((cp = *args++)) {
2054 switch (smatch (++cp, scanswit)) {
2056 ambigsw (cp, scanswit);
2059 fprintf (stderr, "-%s unknown\n", cp);
2062 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2063 print_help (buf, scanswit, 1);
2079 if (!(form = *args++) || *form == '-') {
2080 advise (NULL, "missing argument to %s", args[-2]);
2086 if (!(format = *args++) || *format == '-') {
2087 advise (NULL, "missing argument to %s", args[-2]);
2093 if (!(cp = *args++) || *cp == '-') {
2094 advise (NULL, "missing argument to %s", args[-2]);
2100 if (*cp == '+' || *cp == '@') {
2101 advise (NULL, "sorry, no folders allowed!");
2109 msgs[msgp++] = "all";
2110 for (msgnum = 0; msgnum < msgp; msgnum++)
2111 if (!m_convert (mp, msgs[msgnum]))
2115 /* Get new format string */
2116 nfs = new_fs (form, format, FORMAT);
2118 /* force scansbr to (re)compile format */
2125 s_optim = optim = 1;
2126 s_form = form ? getcpy (form) : NULL;
2127 s_format = format ? getcpy (format) : NULL;
2131 optim = equiv (s_form, form) && equiv (s_format, format);
2134 for (msgnum = mp->lowsel;
2135 msgnum <= mp->hghsel && !interrupted;
2137 if (is_selected (mp, msgnum)) {
2138 if (optim && Msgs[msgnum].m_scanl)
2139 printf ("%s", Msgs[msgnum].m_scanl);
2142 zp = msh_ready (msgnum, 0);
2143 switch (state = scan (zp, msgnum, 0, nfs, width,
2144 msgnum == mp->curmsg,
2145 is_unseen (mp, msgnum),
2146 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2147 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2153 Msgs[msgnum].m_scanl = getcpy (scanl);
2157 advise (NULL, "scan() botch (%d)", state);
2161 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2173 static struct swit showswit[] = {
2177 { "form formfile", 4 },
2179 { "moreproc program", 4 },
2181 { "nomoreproc", 3 },
2183 { "length lines", 4 },
2185 { "width columns", 4 },
2187 { "showproc program", 4 },
2189 { "noshowproc", 3 },
2201 showcmd (char **args)
2203 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2204 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2205 char *cp, *proc = showproc, buf[BUFSIZ];
2206 char *msgs[MAXARGS], *vec[MAXARGS];
2208 if (!mh_strcasecmp (cmd_name, "next"))
2211 if (!mh_strcasecmp (cmd_name, "prev"))
2213 while ((cp = *args++)) {
2215 switch (i = smatch (++cp, showswit)) {
2217 ambigsw (cp, showswit);
2224 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2225 cmd_name, mode ? NULL : "[msgs] ");
2226 print_help (buf, showswit, 1);
2234 if (!(cp = *args++) || *cp == '-') {
2235 advise (NULL, "missing argument to %s", args[-2]);
2247 if (!(proc = *args++) || *proc == '-') {
2248 advise (NULL, "missing argument to %s", args[-2]);
2258 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2261 if (*cp == '+' || *cp == '@') {
2262 advise (NULL, "sorry, no folders allowed!");
2268 "usage: %s [switches] [switches for showproc]\n",
2278 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2279 for (msgnum = 0; msgnum < msgp; msgnum++)
2280 if (!m_convert (mp, msgs[msgnum]))
2284 if (!nshow && !getenv ("NOMHNPROC"))
2285 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2286 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2287 proc = showmimeproc;
2288 vec[vecp++] = "-file";
2296 if (strcmp (showproc, "mhl") == 0) {
2302 seqnum = seq_getnum (mp, "unseen");
2303 vec[0] = r1bindex (proc, '/');
2306 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2307 if (is_selected (mp, msgnum)) {
2308 vec[vecp++] = getcpy (m_name (msgnum));
2310 seq_delmsg (mp, "unseen", msgnum);
2313 if (mp->numsel == 1 && headersw)
2315 mhlsbr (vecp, vec, mhl_action);
2316 m_eomsbr ((int (*)()) 0);
2321 for (msgnum = mp->lowsel;
2322 msgnum <= mp->hghsel && !interrupted;
2324 if (is_selected (mp, msgnum)) {
2325 switch (ask (msgnum)) {
2326 case NOTOK: /* QUIT */
2333 if (mp->numsel == 1 && headersw)
2336 copy_message (msgnum, stdout);
2338 process (msgnum, proc, vecp, vec);
2341 seq_delmsg (mp, "unseen", msgnum);
2348 seq_setcur (mp, mp->hghsel);
2355 if (Msgs[msgnum].m_bboard_id == 0)
2358 printf ("(Message %d", msgnum);
2359 if (Msgs[msgnum].m_bboard_id > 0)
2360 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2369 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2374 mhl_action (char *name)
2378 if ((msgnum = m_atoi (name)) < mp->lowmsg
2379 || msgnum > mp->hghmsg
2380 || !does_exist (mp, msgnum))
2384 mhlfp = msh_ready (msgnum, 1);
2386 m_eomsbr (eom_action);
2398 if (mp->numsel == 1 || !interactive || redirected)
2401 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2402 if (mp->lowsel != msgnum)
2404 printf ("Press <return> to list \"%d\"...", msgnum);
2410 read (fileno (stdout), buf, sizeof buf);
2412 switch (setjmp (sigenv)) {
2415 read (fileno (stdout), buf, sizeof buf);/* fall... */
2423 if (strchr(buf, '\n') == NULL)
2427 told_to_quit = interrupted = 0;
2442 is_nontext (int msgnum)
2445 unsigned char *bp, *dp;
2447 char buf[BUFSIZ], name[NAMESZ];
2450 if (Msgs[msgnum].m_flags & MHNCHK)
2451 return (Msgs[msgnum].m_flags & MHNYES);
2452 Msgs[msgnum].m_flags |= MHNCHK;
2454 fp = msh_ready (msgnum, 1);
2457 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2462 * Check Content-Type field
2464 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2468 cp = add (buf, NULL);
2469 while (state == FLDPLUS) {
2470 state = m_getfld (state, name, buf, sizeof buf, fp);
2477 for (; isspace (*bp); bp++)
2482 for (bp++, i = 0;;) {
2512 for (dp = bp; istoken (*dp); dp++)
2519 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2522 for (dp++; isspace (*dp); dp++)
2525 if ((result = !uprf (dp, "charset")))
2527 dp += sizeof "charset" - 1;
2528 while (isspace (*dp))
2532 while (isspace (*dp))
2535 if ((bp = strchr(++dp, '"')))
2538 for (bp = dp; *bp; bp++)
2539 if (isspace (*bp)) {
2545 /* Default character set */
2548 /* Check the character set */
2549 result = !check_charset (dp, strlen (dp));
2551 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2561 Msgs[msgnum].m_flags |= MHNYES;
2568 * Check Content-Transfer-Encoding field
2570 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2571 cp = add (buf, NULL);
2572 while (state == FLDPLUS) {
2573 state = m_getfld (state, name, buf, sizeof buf, fp);
2576 for (bp = cp; isspace (*bp); bp++)
2578 for (dp = bp; istoken (*dp); dp++)
2581 result = (mh_strcasecmp (bp, "7bit")
2582 && mh_strcasecmp (bp, "8bit")
2583 && mh_strcasecmp (bp, "binary"));
2587 Msgs[msgnum].m_flags |= MHNYES;
2594 * Just skip the rest of this header
2595 * field and go to next one.
2597 while (state == FLDPLUS)
2598 state = m_getfld (state, name, buf, sizeof(buf), fp);
2602 * We've passed the message header,
2603 * so message is just text.
2611 static struct swit sortswit[] = {
2613 { "datefield field", 0 },
2615 { "textfield field", 0 },
2617 { "notextfield", 0 },
2619 { "limit days", 0 },
2633 sortcmd (char **args)
2635 int msgp = 0, msgnum;
2636 char *cp, *datesw = NULL, *subjsw = NULL;
2637 char buf[BUFSIZ], *msgs[MAXARGS];
2641 forkcmd (args, cmd_name);
2645 while ((cp = *args++)) {
2647 switch (smatch (++cp, sortswit)) {
2649 ambigsw (cp, sortswit);
2652 fprintf (stderr, "-%s unknown\n", cp);
2655 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2656 print_help (buf, sortswit, 1);
2661 advise (NULL, "only one date field at a time!");
2664 if (!(datesw = *args++) || *datesw == '-') {
2665 advise (NULL, "missing argument to %s", args[-2]);
2672 advise (NULL, "only one text field at a time!");
2675 if (!(subjsw = *args++) || *subjsw == '-') {
2676 advise (NULL, "missing argument to %s", args[-2]);
2684 case SOLIMT: /* too hard */
2685 if (!(cp = *args++) || *cp == '-') {
2686 advise (NULL, "missing argument to %s", args[-2]);
2690 case SOVERB: /* not implemented */
2694 if (*cp == '+' || *cp == '@') {
2695 advise (NULL, "sorry, no folders allowed!");
2703 msgs[msgp++] = "all";
2706 for (msgnum = 0; msgnum < msgp; msgnum++)
2707 if (!m_convert (mp, msgs[msgnum]))
2711 twscopy (&tb, dlocaltimenow ());
2713 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2714 if (Msgs[msgnum].m_scanl) {
2715 free (Msgs[msgnum].m_scanl);
2716 Msgs[msgnum].m_scanl = NULL;
2718 if (is_selected (mp, msgnum)) {
2719 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2720 twscopy (&Msgs[msgnum].m_tb,
2721 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2723 else /* m_scaln is already NULL */
2724 twscopy (&Msgs[msgnum].m_tb, &tb);
2725 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2726 if (mp->curmsg == msgnum)
2727 Msgs[msgnum].m_stats |= CUR;
2730 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2731 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2733 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2734 if (subjsw && Msgs[msgnum].m_scanl) {
2735 free (Msgs[msgnum].m_scanl); /* from subjsort */
2736 Msgs[msgnum].m_scanl = NULL;
2738 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2739 if (Msgs[msgnum].m_stats & CUR)
2740 seq_setcur (mp, msgnum);
2743 mp->msgflags |= MODIFIED;
2749 * get_fields - parse message, and get date and subject if needed.
2750 * We'll use the msgp->m_tb tws struct for the date, and overload
2751 * the msgp->m_scanl field with our subject string.
2754 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2756 int state, gotdate = 0;
2757 char *bp, buf[BUFSIZ], name[NAMESZ];
2758 struct tws *tw = (struct tws *) 0;
2761 zp = msh_ready (msgnum, 0);
2762 for (state = FLD;;) {
2763 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2767 if (!mh_strcasecmp (name, datesw)) {
2769 while (state == FLDPLUS) {
2770 state = m_getfld (state, name, buf, sizeof buf, zp);
2773 if ((tw = dparsetime (bp)) == NULL)
2775 "unable to parse %s field in message %d",
2778 twscopy (&(msgp->m_tb), tw);
2780 if (!subjsw) /* not using this, or already done */
2781 break; /* all done! */
2784 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2786 while (state == FLDPLUS) {
2787 state = m_getfld (state, name, buf, sizeof buf, zp);
2790 msgp->m_scanl = sosmash(subjsw, bp);
2792 break; /* date done so we're done */
2794 subjsw = (char *)0;/* subject done, need date */
2796 while (state == FLDPLUS) /* flush this one */
2797 state = m_getfld (state, name, buf, sizeof buf, zp);
2808 admonish (NULL, "format error in message %d", msgnum);
2809 if (msgp->m_scanl) { /* this might need free'd */
2810 free (msgp->m_scanl); /* probably can't use subj anyway */
2811 msgp->m_scanl = NULL;
2816 adios (NULL, "internal error -- you lose");
2821 return OK; /* not an error if subj not found */
2823 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2824 return NOTOK; /* NOTOK means use some other date */
2833 msgsort (struct Msg *a, struct Msg *b)
2835 return twsort (&a->m_tb, &b->m_tb);
2840 subsort (struct Msg *a, struct Msg *b)
2844 if (a->m_scanl && b->m_scanl)
2845 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2848 return twsort (&a->m_tb, &b->m_tb);
2853 * try to make the subject "canonical": delete leading "re:", everything
2854 * but letters & smash letters to lower case.
2857 sosmash (char *subj, char *s)
2859 register char *cp, *dp;
2860 register unsigned char c;
2864 dp = s; /* dst pointer */
2865 if (!mh_strcasecmp (subj, "subject"))
2872 *dp++ = isupper(c) ? tolower(c) : c;
2878 while ((c = *cp++)) {
2880 *dp++ = isupper(c) ? tolower(c) : c;
2890 process (int msgnum, char *proc, int vecp, char **vec)
2892 int child_id, status;
2893 char tmpfil[BUFSIZ];
2898 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2899 context_del (pfolder);
2900 context_replace (pfolder, fmsh);/* update current folder */
2902 context_save (); /* save the context file */
2906 cp = m_mktemp(invo_name, NULL, &out);
2908 /* Try again, but try to create under /tmp */
2910 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2913 advise (NULL, "unable to create temporary file");
2917 copy_message (msgnum, out);
2919 strncpy(tmpfil, cp, sizeof(tmpfil));
2923 switch (child_id = fork ()) {
2925 advise ("fork", "unable to");
2931 SIGNAL (SIGINT, istat);
2932 SIGNAL (SIGQUIT, qstat);
2934 vec[vecp++] = tmpfil;
2938 fprintf (stderr, "unable to exec ");
2943 status = pidXwait (child_id, NULL);
2954 copy_message (int msgnum, FILE *out)
2957 static char buffer[BUFSIZ];
2960 zp = msh_ready (msgnum, 1);
2962 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2963 fputs (buffer, out);
2964 if (interrupted && out == stdout)
2970 while (fgets (buffer, sizeof buffer, zp) != NULL
2971 && pos < Msgs[msgnum].m_stop) {
2972 fputs (buffer, out);
2973 pos += (long) strlen (buffer);
2974 if (interrupted && out == stdout)
2982 copy_digest (int msgnum, FILE *out)
2986 static char buffer[BUFSIZ];
2990 zp = msh_ready (msgnum, 1);
2993 while (fgets (buffer, sizeof buffer, zp) != NULL
2994 && !fmsh && pos < Msgs[msgnum].m_stop) {
2995 if (c == '\n' && *buffer == '-')
2997 fputs (buffer, out);
2998 c = buffer[strlen (buffer) - 1];
3000 pos += (long) strlen (buffer);
3001 if (interrupted && out == stdout)