3 * mshcmds.c -- command handlers in msh
10 #include <h/dropsbr.h>
11 #include <h/fmt_scan.h>
12 #include <h/scansbr.h>
13 #include <zotnet/tws/tws.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 *);
73 forkcmd (char **args, char *pgm)
78 vec[0] = r1bindex (pgm, '/');
79 copyip (args, vec + 1, MAXARGS - 1);
82 context_del (pfolder);
83 context_replace (pfolder, fmsh);/* update current folder */
85 context_save (); /* save the context file */
88 switch (child_id = fork ()) {
90 advise ("fork", "unable to");
95 SIGNAL (SIGINT, istat);
96 SIGNAL (SIGQUIT, qstat);
99 fprintf (stderr, "unable to exec ");
104 pidXwait (child_id, NULL);
107 if (fmsh) { /* assume the worst case */
108 mp->msgflags |= MODIFIED;
114 static struct swit distswit[] = {
120 { "draftfolder +folder", 0 },
122 { "draftmessage msg", 0 },
124 { "nodraftfolder", 0 },
126 { "editor editor", 0 },
130 { "form formfile", 0 },
136 { "whatnowproc program", 0 },
138 { "nowhatnowproc", 0 },
146 distcmd (char **args)
149 char *cp, *msg = NULL;
150 char buf[BUFSIZ], *vec[MAXARGS];
153 forkcmd (args, cmd_name);
157 while ((cp = *args++)) {
159 switch (smatch (++cp, distswit)) {
161 ambigsw (cp, distswit);
164 fprintf (stderr, "-%s unknown\n", cp);
167 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
168 print_help (buf, distswit, 1);
171 case DIANSW: /* not implemented */
189 if (!(cp = *args++) || *cp == '-') {
190 advise (NULL, "missing argument to %s", args[-2]);
196 if (*cp == '+' || *cp == '@') {
197 advise (NULL, "sorry, no folders allowed!");
202 advise (NULL, "only one message at a time!");
210 vec[vecp++] = "-file";
214 if (!m_convert (mp, msg))
218 if (mp->numsel > 1) {
219 advise (NULL, "only one message at a time!");
222 process (mp->hghsel, cmd_name, vecp, vec);
223 seq_setcur (mp, mp->hghsel);
227 static struct swit explswit[] = {
247 explcmd (char **args)
249 int inplace = 0, quietsw = 0, verbosw = 0;
250 int msgp = 0, hi, msgnum;
251 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
255 forkcmd (args, cmd_name);
259 while ((cp = *args++)) {
261 switch (smatch (++cp, explswit)) {
263 ambigsw (cp, explswit);
266 fprintf (stderr, "-%s unknown\n", cp);
269 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
270 print_help (buf, explswit, 1);
292 if (*cp == '+' || *cp == '@') {
293 advise (NULL, "sorry, no folders allowed!");
301 msgs[msgp++] = "cur";
302 for (msgnum = 0; msgnum < msgp; msgnum++)
303 if (!m_convert (mp, msgs[msgnum]))
307 smsgs = (struct Msg *)
308 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
310 adios (NULL, "unable to allocate folder storage");
314 for (msgnum = mp->lowsel;
315 msgnum <= mp->hghsel && !interrupted;
317 if (is_selected (mp, msgnum))
318 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
321 free ((char *) smsgs);
324 seq_setcur (mp, mp->lowsel);
326 if (hi <= mp->hghmsg)
329 mp->msgflags |= MODIFIED;
335 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
337 int i, j, ld3, wasdlm, msgp;
339 char c, buffer[BUFSIZ];
342 ld3 = strlen (delim3);
344 if (Msgs[msgnum].m_scanl) {
345 free (Msgs[msgnum].m_scanl);
346 Msgs[msgnum].m_scanl = NULL;
349 pos = ftell (zp = msh_ready (msgnum, 1));
350 for (msgp = 0; msgp <= MAXFOLDER;) {
351 while (fgets (buffer, sizeof buffer, zp) != NULL
353 && pos < Msgs[msgnum].m_stop)
354 pos += (long) strlen (buffer);
355 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
357 fseek (zp, pos, SEEK_SET);
358 smsgs[msgp].m_start = pos;
361 pos < Msgs[msgnum].m_stop
362 && fgets (buffer, sizeof buffer, zp) != NULL;
364 if (strncmp (buffer, delim3, ld3) == 0
365 && (msgp == 1 || c == '\n')
366 && peekc (zp) == '\n')
369 pos += (long) strlen (buffer);
371 wasdlm = strncmp (buffer, delim3, ld3) == 0;
372 if (smsgs[msgp].m_start != pos)
373 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
374 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
376 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
379 pos += (long) strlen (buffer);
382 switch (msgp--) { /* toss "End of XXX Digest" */
384 adios (NULL, "burst() botch -- you lose big");
388 printf ("message %d not in digest format\n", msgnum);
393 printf ("%d message%s exploded from digest %d\n",
394 msgp, msgp != 1 ? "s" : "", msgnum);
398 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
399 advise (NULL, "more than %d messages", MAXFOLDER);
402 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
403 adios (NULL, "unable to allocate folder storage");
408 if (mp->hghsel > msgnum)
412 for (i = mp->hghmsg; j > msgnum; i--, j--) {
414 printf ("message %d becomes message %d\n", j, i);
416 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
417 Msgs[i].m_top = Msgs[j].m_top;
418 Msgs[i].m_start = Msgs[j].m_start;
419 Msgs[i].m_stop = Msgs[j].m_stop;
420 Msgs[i].m_scanl = NULL;
421 if (Msgs[j].m_scanl) {
422 free (Msgs[j].m_scanl);
423 Msgs[j].m_scanl = NULL;
425 copy_msg_flags (mp, i, j);
428 if (Msgs[msgnum].m_bboard_id == 0)
431 unset_selected (mp, msgnum);
432 i = inplace ? msgnum + msgp : mp->hghmsg;
433 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
434 if (verbosw && i != msgnum)
435 printf ("message %d of digest %d becomes message %d\n",
438 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
439 Msgs[i].m_top = Msgs[j].m_top;
440 Msgs[i].m_start = smsgs[j].m_start;
441 Msgs[i].m_stop = smsgs[j].m_stop;
442 Msgs[i].m_scanl = NULL;
443 copy_msg_flags (mp, i, msgnum);
450 static struct swit fileswit[] = {
462 { "src +folder", 0 },
466 { "rmmproc program", 0 },
476 filecmd (char **args)
478 int linksw = 0, msgp = 0;
479 int vecp = 1, i, msgnum;
480 char *cp, buf[BUFSIZ];
481 char *msgs[MAXARGS], *vec[MAXARGS];
484 forkcmd (args, cmd_name);
488 while ((cp = *args++)) {
490 switch (i = smatch (++cp, fileswit)) {
492 ambigsw (cp, fileswit);
495 fprintf (stderr, "-%s unknown\n", cp);
498 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
499 print_help (buf, fileswit, 1);
518 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
521 if (*cp == '+' || *cp == '@')
528 vec[vecp++] = "-file";
531 msgs[msgp++] = "cur";
532 for (msgnum = 0; msgnum < msgp; msgnum++)
533 if (!m_convert (mp, msgs[msgnum]))
538 for (msgnum = mp->lowsel;
539 msgnum <= mp->hghsel && !interrupted;
541 if (is_selected (mp, msgnum))
542 if (process (msgnum, fileproc, vecp, vec)) {
543 unset_selected (mp, msgnum);
547 if (mp->numsel != mp->nummsg || linksw)
548 seq_setcur (mp, mp->hghsel);
555 filehak (char **args)
557 int result, vecp = 0;
558 char *cp, *cwd, *vec[MAXARGS];
560 while ((cp = *args++)) {
562 switch (smatch (++cp, fileswit)) {
579 if (*cp == '+' || *cp == '@')
586 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
588 cwd = getcpy (pwd ());
589 chdir (m_maildir (""));
590 cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF);
591 if (access (m_maildir (cp), F_OK) == NOTOK)
602 static struct swit foldswit[] = {
640 foldcmd (char **args)
642 int fastsw = 0, headersw = 0, packsw = 0;
644 char *cp, *folder = NULL, *msg = NULL;
645 char buf[BUFSIZ], **vec = args;
650 while ((cp = *args++)) {
652 switch (smatch (++cp, foldswit)) {
654 ambigsw (cp, foldswit);
657 fprintf (stderr, "-%s unknown\n", cp);
660 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
661 print_help (buf, foldswit, 1);
664 case FLALSW: /* not implemented */
694 if (*cp == '+' || *cp == '@')
696 advise (NULL, "only one folder at a time!\n");
700 folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF)
704 advise (NULL, "only one message at a time!\n");
713 advise (NULL, "null folder names are not permitted");
717 if (access (m_maildir (folder), R_OK) == NOTOK) {
718 advise (folder, "unable to read");
723 strncpy (buf, folder, sizeof(buf));
724 if (expand (buf) == NOTOK)
727 if (access (folder, R_OK) == NOTOK) {
728 advise (folder, "unable to read");
743 if (!m_convert (mp, msg))
747 if (mp->numsel > 1) {
748 advise (NULL, "only one message at a time!");
751 seq_setcur (mp, mp->hghsel);
756 forkcmd (vec, cmd_name);
760 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
761 adios (NULL, "unable to allocate folder storage");
763 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
764 if (does_exist (mp, msgnum)) {
765 if (msgnum != hole) {
766 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
767 Msgs[hole].m_top = Msgs[msgnum].m_top;
768 Msgs[hole].m_start = Msgs[msgnum].m_start;
769 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
770 Msgs[hole].m_scanl = NULL;
771 if (Msgs[msgnum].m_scanl) {
772 free (Msgs[msgnum].m_scanl);
773 Msgs[msgnum].m_scanl = NULL;
775 copy_msg_flags (mp, hole, msgnum);
776 if (mp->curmsg == msgnum)
777 seq_setcur (mp, hole);
781 if (mp->nummsg > 0) {
783 mp->hghmsg = hole - 1;
785 mp->msgflags |= MODIFIED;
791 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
794 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
795 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
797 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
799 /* check for empty folder */
800 if (mp->nummsg == 0) {
801 printf ("has no messages%*s",
802 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
804 printf ("has %*d message%s (%*d-%*d)",
805 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
806 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
807 if (mp->curmsg >= mp->lowmsg
808 && mp->curmsg <= mp->hghmsg)
809 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
816 static struct swit forwswit[] = {
822 { "draftfolder +folder", 0 },
824 { "draftmessage msg", 0 },
826 { "nodraftfolder", 0 },
828 { "editor editor", 0 },
832 { "filter filterfile", 0 },
834 { "form formfile", 0 },
848 { "whatnowproc program", 0 },
858 forwcmd (char **args)
860 int msgp = 0, vecp = 1, msgnum;
861 char *cp, *filter = NULL, buf[BUFSIZ];
862 char *msgs[MAXARGS], *vec[MAXARGS];
865 forkcmd (args, cmd_name);
869 while ((cp = *args++)) {
871 switch (smatch (++cp, forwswit)) {
873 ambigsw (cp, forwswit);
876 fprintf (stderr, "-%s unknown\n", cp);
879 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
880 print_help (buf, forwswit, 1);
883 case FOANSW: /* not implemented */
903 if (!(cp = *args++) || *cp == '-') {
904 advise (NULL, "missing argument to %s", args[-2]);
910 if (!(filter = *args++) || *filter == '-') {
911 advise (NULL, "missing argument to %s", args[-2]);
916 if (access (filter = myfilter, R_OK) == NOTOK) {
917 advise (filter, "unable to read default filter file");
925 if (*cp == '+' || *cp == '@') {
926 advise (NULL, "sorry, no folders allowed!");
933 /* foil search of .mh_profile */
934 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
935 vec[0] = (char *)mktemp (buf);
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[80], *args[MAXARGS];
969 strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
972 switch (child_id = fork ()) {
974 advise ("fork", "unable to");
977 case OK: /* "trust me" */
978 if (freopen (tmpfil, "w", stdout) == NULL) {
979 fprintf (stderr, "unable to create ");
983 args[0] = r1bindex (mhlproc, '/');
985 args[i++] = "-forwall";
988 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
989 if (is_selected (mp, msgnum))
990 args[i++] = getcpy (m_name (msgnum));
992 mhlsbr (i, args, mhl_action);
993 m_eomsbr ((int (*) ()) 0);
998 if (pidXwait (child_id, NULL))
1003 if ((out = fopen (tmpfil, "w")) == NULL) {
1004 advise (tmpfil, "unable to create temporary file");
1009 for (msgnum = mp->lowsel;
1010 msgnum <= mp->hghsel && !interrupted;
1012 if (is_selected (mp, msgnum)) {
1013 fprintf (out, "\n\n-------");
1014 if (msgnum == mp->lowsel)
1015 fprintf (out, " Forwarded Message%s",
1016 mp->numsel > 1 ? "s" : "");
1018 fprintf (out, " Message %d", msgcnt);
1019 fprintf (out, "\n\n");
1020 copy_digest (msgnum, out);
1024 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1025 mp->numsel > 1 ? "s" : "");
1031 switch (child_id = fork ()) {
1033 advise ("fork", "unable to");
1038 SIGNAL (SIGINT, istat);
1039 SIGNAL (SIGQUIT, qstat);
1041 vec[vecp++] = tmpfil;
1045 fprintf (stderr, "unable to exec ");
1050 pidXwait (child_id, NULL);
1058 static char *hlpmsg[] = {
1059 "The %s program emulates many of the commands found in the nmh",
1060 "system. Instead of operating on nmh folders, commands to %s concern",
1063 "To see the list of commands available, just type a ``?'' followed by",
1064 "the RETURN key. To find out what switches each command takes, type",
1065 "the name of the command followed by ``-help''. To leave %s, use the",
1066 "``quit'' command.",
1068 "Although a lot of nmh commands are found in %s, not all are fully",
1069 "implemented. %s will always recognize all legal switches for a",
1070 "given command though, and will let you know when you ask for an",
1071 "option that it is unable to perform.",
1073 "Running %s is fun, but using nmh from your shell is far superior.",
1074 "After you have familiarized yourself with the nmh style by using %s,",
1075 "you should try using nmh from the shell. You can still use %s for",
1076 "message files that aren't in nmh format, such as BBoard files.",
1082 helpcmd (char **args)
1086 for (i = 0; hlpmsg[i]; i++) {
1087 printf (hlpmsg[i], invo_name);
1093 static struct swit markswit[] = {
1101 { "sequence name", 0 },
1119 markcmd (char **args)
1121 int addsw = 0, deletesw = 0, debugsw = 0;
1122 int listsw = 0, zerosw = 0, seqp = 0;
1123 int msgp = 0, msgnum;
1124 char *cp, buf[BUFSIZ];
1125 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1127 while ((cp = *args++)) {
1129 switch (smatch (++cp, markswit)) {
1131 ambigsw (cp, markswit);
1134 fprintf (stderr, "-%s unknown\n", cp);
1137 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1138 print_help (buf, markswit, 1);
1143 deletesw = listsw = 0;
1151 addsw = deletesw = 0;
1155 if (!(cp = *args++) || *cp == '-') {
1156 advise (NULL, "missing argument to %s", args[-2]);
1159 if (seqp < NUMATTRS)
1162 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1167 case MPUBSW: /* not implemented */
1183 if (*cp == '+' || *cp == '@') {
1184 advise (NULL, "sorry, no folders allowed!");
1191 if (!addsw && !deletesw && !listsw)
1198 seqs[seqp++] = "unseen";
1202 msgs[msgp++] = "all";
1206 msgs[msgp++] = listsw ? "all" :"cur";
1207 for (msgnum = 0; msgnum < msgp; msgnum++)
1208 if (!m_convert (mp, msgs[msgnum]))
1212 printf ("invo_name=%s mypath=%s defpath=%s\n",
1213 invo_name, mypath, defpath);
1214 printf ("ctxpath=%s context flags=%s\n",
1215 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1216 printf ("foldpath=%s flags=%s\n",
1218 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1219 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1220 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1221 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1222 mp->lowsel, mp->hghsel, mp->numsel);
1223 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1226 if (seqp == 0 && (addsw || deletesw)) {
1227 advise (NULL, "-%s requires at least one -sequence argument",
1228 addsw ? "add" : "delete");
1234 for (seqp = 0; seqs[seqp]; seqp++)
1235 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1240 for (seqp = 0; seqs[seqp]; seqp++)
1241 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1245 /* Listing messages in sequences */
1248 /* list the given sequences */
1249 for (seqp = 0; seqs[seqp]; seqp++)
1250 seq_print (mp, seqs[seqp]);
1252 /* else list them all */
1258 for (msgnum = mp->lowsel;
1259 msgnum <= mp->hghsel && !interrupted;
1261 if (is_selected (mp, msgnum)) {
1262 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1265 Msgs[msgnum].m_bboard_id,
1267 (long) Msgs[msgnum].m_start,
1268 (long) Msgs[msgnum].m_stop,
1269 snprintb (buf, sizeof(buf),
1270 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1272 if (Msgs[msgnum].m_scanl)
1273 printf ("%s", Msgs[msgnum].m_scanl);
1279 static struct swit mhnswit[] = {
1282 #define MHNNAUTOSW 1
1284 #define MHNDEBUGSW 2
1286 #define MHNEBCDICSW 3
1287 { "ebcdicsafe", 0 },
1288 #define MHNNEBCDICSW 4
1289 { "noebcdicsafe", 0 },
1291 { "form formfile", 4 },
1294 #define MHNNHEADSW 7
1298 #define MHNNLISTSW 9
1300 #define MHNPARTSW 10
1301 { "part number", 0 },
1302 #define MHNSIZESW 11
1304 #define MHNNSIZESW 12
1305 { "norealsize", 0 },
1306 #define MHNRFC934SW 13
1307 { "rfc934mode", 0 },
1308 #define MHNNRFC934SW 14
1309 { "norfc934mode", 0 },
1310 #define MHNSERIALSW 15
1311 { "serialonly", 0 },
1312 #define MHNNSERIALSW 16
1313 { "noserialonly", 0 },
1314 #define MHNSHOWSW 17
1316 #define MHNNSHOWSW 18
1318 #define MHNSTORESW 19
1320 #define MHNNSTORESW 20
1322 #define MHNTYPESW 21
1323 { "type content", 0 },
1324 #define MHNVERBSW 22
1326 #define MHNNVERBSW 23
1328 #define MHNHELPSW 24
1330 #define MHNPROGSW 25
1331 { "moreproc program", -4 },
1332 #define MHNNPROGSW 26
1333 { "nomoreproc", -3 },
1335 { "length lines", -4 },
1337 { "width columns", -4 },
1343 mhncmd (char **args)
1345 int msgp = 0, vecp = 1;
1347 char *cp, buf[BUFSIZ];
1348 char *msgs[MAXARGS], *vec[MAXARGS];
1351 forkcmd (args, cmd_name);
1354 while ((cp = *args++)) {
1356 switch (smatch (++cp, mhnswit)) {
1358 ambigsw (cp, mhnswit);
1361 fprintf (stderr, "-%s unknown\n", cp);
1364 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1365 print_help (buf, mhnswit, 1);
1400 if (!(cp = *args++) || *cp == '-') {
1401 advise (NULL, "missing argument to %s", args[-2]);
1408 if (*cp == '+' || *cp == '@') {
1409 advise (NULL, "sorry, no folders allowed!");
1417 vec[vecp++] = "-file";
1420 msgs[msgp++] = "cur";
1421 for (msgnum = 0; msgnum < msgp; msgnum++)
1422 if (!m_convert (mp, msgs[msgnum]))
1427 for (msgnum = mp->lowsel;
1428 msgnum <= mp->hghsel && !interrupted;
1430 if (is_selected (mp, msgnum))
1431 if (process (msgnum, cmd_name, vecp, vec)) {
1432 unset_selected (mp, msgnum);
1436 seq_setcur (mp, mp->hghsel);
1440 static struct swit packswit[] = {
1448 static mbx_style = MMDF_FORMAT;
1451 packcmd (char **args)
1453 int msgp = 0, md, msgnum;
1454 char *cp, *file = NULL;
1455 char buf[BUFSIZ], *msgs[MAXARGS];
1459 forkcmd (args, cmd_name);
1463 while ((cp = *args++)) {
1465 switch (smatch (++cp, packswit)) {
1467 ambigsw (cp, packswit);
1470 fprintf (stderr, "-%s unknown\n", cp);
1473 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1474 print_help (buf, packswit, 1);
1478 if (!(file = *args++) || *file == '-') {
1479 advise (NULL, "missing argument to %s", args[-2]);
1484 if (*cp == '+' || *cp == '@') {
1485 advise (NULL, "sorry, no folders allowed!");
1494 file = path (file, TFILE);
1495 if (stat (file, &st) == NOTOK) {
1496 if (errno != ENOENT) {
1497 advise (file, "error on file");
1500 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1507 msgs[msgp++] = "all";
1508 for (msgnum = 0; msgnum < msgp; msgnum++)
1509 if (!m_convert (mp, msgs[msgnum]))
1513 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1514 advise (file, "unable to open");
1517 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1518 if (is_selected (mp, msgnum))
1519 if (pack (file, md, msgnum) == NOTOK)
1521 mbx_close (file, md);
1523 if (mp->hghsel != mp->curmsg)
1524 seq_setcur (mp, mp->lowsel);
1532 pack (char *mailbox, int md, int msgnum)
1536 if (Msgs[msgnum].m_bboard_id == 0)
1539 zp = msh_ready (msgnum, 1);
1540 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1541 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1546 packhak (char **args)
1549 char *cp, *file = NULL;
1551 while ((cp = *args++)) {
1553 switch (smatch (++cp, packswit)) {
1560 if (!(file = *args++) || *file == '-')
1564 if (*cp == '+' || *cp == '@')
1568 file = path (file ? file : "./msgbox", TFILE);
1569 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1576 static struct swit pickswit[] = {
1588 { "cc pattern", 0 },
1590 { "date pattern", 0 },
1592 { "from pattern", 0 },
1594 { "search pattern", 0 },
1596 { "subject pattern", 0 },
1598 { "to pattern", 0 },
1600 { "-othercomponent pattern", 15 },
1602 { "after date", 0 },
1604 { "before date", 0 },
1606 { "datefield field", 5 },
1608 { "sequence name", 0 },
1628 pickcmd (char **args)
1630 int zerosw = 1, msgp = 0, seqp = 0;
1631 int vecp = 0, hi, lo, msgnum;
1632 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1633 char *seqs[NUMATTRS], *vec[MAXARGS];
1636 while ((cp = *args++)) {
1642 switch (smatch (cp, pickswit)) {
1644 ambigsw (cp, pickswit);
1647 fprintf (stderr, "-%s unknown\n", cp);
1650 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1651 print_help (buf, pickswit, 1);
1665 if (!(cp = *args++)) {/* allow -xyz arguments */
1666 advise (NULL, "missing argument to %s", args[-2]);
1672 advise (NULL, "internal error!");
1683 if (!(cp = *args++) || *cp == '-') {
1684 advise (NULL, "missing argument to %s", args[-2]);
1687 if (seqp < NUMATTRS)
1690 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1701 case PIPUSW: /* not implemented */
1708 if (*cp == '+' || *cp == '@') {
1709 advise (NULL, "sorry, no folders allowed!");
1718 msgs[msgp++] = "all";
1719 for (msgnum = 0; msgnum < msgp; msgnum++)
1720 if (!m_convert (mp, msgs[msgnum]))
1725 if (!pcompile (vec, NULL))
1731 for (msgnum = mp->lowsel;
1732 msgnum <= mp->hghsel && !interrupted;
1734 if (is_selected (mp, msgnum)) {
1735 zp = msh_ready (msgnum, 1);
1736 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1737 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1744 unset_selected (mp, msgnum);
1755 if (mp->numsel <= 0) {
1756 advise (NULL, "no messages match specification");
1761 for (seqp = 0; seqs[seqp]; seqp++)
1762 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1765 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1769 static struct swit replswit[] = {
1773 { "noannotate", 0 },
1779 { "draftfolder +folder", 0 },
1781 { "draftmessage msg", 0 },
1783 { "nodraftfolder", 0 },
1785 { "editor editor", 0 },
1789 { "fcc +folder", 0 },
1791 { "filter filterfile", 0 },
1793 { "form formfile", 0 },
1803 { "whatnowproc program", 0 },
1807 { "width columns", 0 },
1815 replcmd (char **args)
1818 char *cp, *msg = NULL;
1819 char buf[BUFSIZ], *vec[MAXARGS];
1822 forkcmd (args, cmd_name);
1826 while ((cp = *args++)) {
1828 switch (smatch (++cp, replswit)) {
1830 ambigsw (cp, replswit);
1833 fprintf (stderr, "-%s unknown\n", cp);
1836 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1837 print_help (buf, replswit, 1);
1840 case REANSW: /* not implemented */
1865 if (!(cp = *args++) || *cp == '-') {
1866 advise (NULL, "missing argument to %s", args[-2]);
1872 if (*cp == '+' || *cp == '@') {
1873 advise (NULL, "sorry, no folders allowed!");
1878 advise (NULL, "only one message at a time!");
1886 vec[vecp++] = "-file";
1890 if (!m_convert (mp, msg))
1894 if (mp->numsel > 1) {
1895 advise (NULL, "only one message at a time!");
1898 process (mp->hghsel, cmd_name, vecp, vec);
1899 seq_setcur (mp, mp->hghsel);
1903 static struct swit rmmswit[] = {
1911 rmmcmd (char **args)
1913 int msgp = 0, msgnum;
1914 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1916 while ((cp = *args++)) {
1918 switch (smatch (++cp, rmmswit)) {
1920 ambigsw (cp, rmmswit);
1923 fprintf (stderr, "-%s unknown\n", cp);
1926 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1927 print_help (buf, rmmswit, 1);
1930 if (*cp == '+' || *cp == '@') {
1931 advise (NULL, "sorry, no folders allowed!");
1939 msgs[msgp++] = "cur";
1940 for (msgnum = 0; msgnum < msgp; msgnum++)
1941 if (!m_convert (mp, msgs[msgnum]))
1952 register int msgnum, vecp;
1954 char buffer[BUFSIZ], *vec[MAXARGS];
1958 if (mp->numsel > MAXARGS - 1) {
1959 advise (NULL, "more than %d messages for %s exec",
1960 MAXARGS - 1, rmmproc);
1964 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1965 if (is_selected (mp, msgnum))
1966 vec[vecp++] = getcpy (m_name (msgnum));
1968 forkcmd (vec, rmmproc);
1969 for (vecp = 0; vec[vecp]; vecp++)
1973 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1974 if (is_selected (mp, msgnum)) {
1975 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1976 if (rename (cp, buffer) == NOTOK)
1977 admonish (buffer, "unable to rename %s to", cp);
1981 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1982 if (is_selected (mp, msgnum)) {
1983 set_deleted (mp, msgnum);
1984 unset_exists (mp, msgnum);
1987 if (pmsh && pop_dele (msgnum) != OK)
1988 fprintf (stderr, "%s", response);
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];
2051 static int p_optim = 0;
2054 static int s_optim = 0;
2055 static char *s_form = NULL, *s_format = NULL;
2057 while ((cp = *args++)) {
2059 switch (smatch (++cp, scanswit)) {
2061 ambigsw (cp, scanswit);
2064 fprintf (stderr, "-%s unknown\n", cp);
2067 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2068 print_help (buf, scanswit, 1);
2084 if (!(form = *args++) || *form == '-') {
2085 advise (NULL, "missing argument to %s", args[-2]);
2091 if (!(format = *args++) || *format == '-') {
2092 advise (NULL, "missing argument to %s", args[-2]);
2098 if (!(cp = *args++) || *cp == '-') {
2099 advise (NULL, "missing argument to %s", args[-2]);
2105 if (*cp == '+' || *cp == '@') {
2106 advise (NULL, "sorry, no folders allowed!");
2114 msgs[msgp++] = "all";
2115 for (msgnum = 0; msgnum < msgp; msgnum++)
2116 if (!m_convert (mp, msgs[msgnum]))
2120 /* Get new format string */
2121 nfs = new_fs (form, format, FORMAT);
2123 /* force scansbr to (re)compile format */
2130 s_optim = optim = 1;
2131 s_form = form ? getcpy (form) : NULL;
2132 s_format = format ? getcpy (format) : NULL;
2141 width = sc_width ();
2143 for (dp = nfs, i = 0; *dp; dp++, i++)
2144 if (*dp == '\\' || *dp == '"' || *dp == '\n')
2147 if ((ep = malloc ((unsigned) i)) == NULL)
2148 adios (NULL, "out of memory");
2149 for (dp = nfs, fp = ep; *dp; dp++) {
2151 *fp++ = '\\', *fp++ = 'n';
2154 if (*dp == '"' || *dp == '\\')
2160 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
2169 optim = equiv (s_form, form) && equiv (s_format, format);
2173 if (p_optim && optim) {
2174 for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
2175 if (!is_selected(mp, msgnum) || Msgs[msgnum].m_scanl)
2177 if (msgnum > mp->hghmsg && pop_command ("LIST") == OK) {
2178 fprintf (stderr, "Stand-by...");
2184 switch (pop_multiline ()) {
2186 fprintf (stderr, "%s", response);
2189 fprintf (stderr,"\n");
2193 if (sscanf (response, "%d %d", &msgnum, &size) == 2
2194 && mp->lowmsg <= msgnum
2195 && msgnum <= mp->hghmsg
2196 && (cp = strchr(response, '#'))
2198 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2209 for (msgnum = mp->lowsel;
2210 msgnum <= mp->hghsel && !interrupted;
2212 if (is_selected (mp, msgnum)) {
2213 if (optim && Msgs[msgnum].m_scanl)
2214 printf ("%s", Msgs[msgnum].m_scanl);
2220 && is_virtual (mp, msgnum)
2221 && pop_command ("LIST %d", msgnum) == OK
2222 && (cp = strchr(response, '#'))
2224 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2225 printf ("%s", Msgs[msgnum].m_scanl);
2231 zp = msh_ready (msgnum, 0);
2232 switch (state = scan (zp, msgnum, 0, nfs, width,
2233 msgnum == mp->curmsg,
2234 is_unseen (mp, msgnum),
2235 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2236 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2242 Msgs[msgnum].m_scanl = getcpy (scanl);
2246 advise (NULL, "scan() botch (%d)", state);
2250 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2262 static struct swit showswit[] = {
2266 { "form formfile", 4 },
2268 { "moreproc program", 4 },
2270 { "nomoreproc", 3 },
2272 { "length lines", 4 },
2274 { "width columns", 4 },
2276 { "showproc program", 4 },
2278 { "noshowproc", 3 },
2290 showcmd (char **args)
2292 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2293 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2294 char *cp, *proc = showproc, buf[BUFSIZ];
2295 char *msgs[MAXARGS], *vec[MAXARGS];
2297 if (!strcasecmp (cmd_name, "next"))
2300 if (!strcasecmp (cmd_name, "prev"))
2302 while ((cp = *args++)) {
2304 switch (i = smatch (++cp, showswit)) {
2306 ambigsw (cp, showswit);
2313 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2314 cmd_name, mode ? NULL : "[msgs] ");
2315 print_help (buf, showswit, 1);
2323 if (!(cp = *args++) || *cp == '-') {
2324 advise (NULL, "missing argument to %s", args[-2]);
2336 if (!(proc = *args++) || *proc == '-') {
2337 advise (NULL, "missing argument to %s", args[-2]);
2347 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2350 if (*cp == '+' || *cp == '@') {
2351 advise (NULL, "sorry, no folders allowed!");
2357 "usage: %s [switches] [switches for showproc]\n",
2367 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2368 for (msgnum = 0; msgnum < msgp; msgnum++)
2369 if (!m_convert (mp, msgs[msgnum]))
2373 if (!nshow && !getenv ("NOMHNPROC"))
2374 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2375 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2376 proc = showmimeproc;
2377 vec[vecp++] = "-show";
2378 vec[vecp++] = "-file";
2386 if (strcmp (showproc, "mhl") == 0) {
2392 seqnum = seq_getnum (mp, "unseen");
2393 vec[0] = r1bindex (proc, '/');
2396 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2397 if (is_selected (mp, msgnum)) {
2398 vec[vecp++] = getcpy (m_name (msgnum));
2400 seq_delmsg (mp, "unseen", msgnum);
2403 if (mp->numsel == 1 && headersw)
2405 mhlsbr (vecp, vec, mhl_action);
2406 m_eomsbr ((int (*)()) 0);
2411 for (msgnum = mp->lowsel;
2412 msgnum <= mp->hghsel && !interrupted;
2414 if (is_selected (mp, msgnum)) {
2415 switch (ask (msgnum)) {
2416 case NOTOK: /* QUIT */
2423 if (mp->numsel == 1 && headersw)
2426 copy_message (msgnum, stdout);
2428 process (msgnum, proc, vecp, vec);
2431 seq_delmsg (mp, "unseen", msgnum);
2438 seq_setcur (mp, mp->hghsel);
2445 if (Msgs[msgnum].m_bboard_id == 0)
2448 printf ("(Message %d", msgnum);
2449 if (Msgs[msgnum].m_bboard_id > 0)
2450 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2459 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2464 mhl_action (char *name)
2468 if ((msgnum = m_atoi (name)) < mp->lowmsg
2469 || msgnum > mp->hghmsg
2470 || !does_exist (mp, msgnum))
2474 mhlfp = msh_ready (msgnum, 1);
2476 m_eomsbr (eom_action);
2488 if (mp->numsel == 1 || !interactive || redirected)
2491 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2492 if (mp->lowsel != msgnum)
2494 printf ("Press <return> to list \"%d\"...", msgnum);
2500 read (fileno (stdout), buf, sizeof buf);
2502 switch (setjmp (sigenv)) {
2505 read (fileno (stdout), buf, sizeof buf);/* fall... */
2513 if (strchr(buf, '\n') == NULL)
2517 told_to_quit = interrupted = 0;
2532 is_nontext (int msgnum)
2536 char buf[BUFSIZ], name[NAMESZ];
2539 if (Msgs[msgnum].m_flags & MHNCHK)
2540 return (Msgs[msgnum].m_flags & MHNYES);
2541 Msgs[msgnum].m_flags |= MHNCHK;
2543 fp = msh_ready (msgnum, 1);
2546 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2551 * Check Content-Type field
2553 if (!strcasecmp (name, TYPE_FIELD)) {
2557 cp = add (buf, NULL);
2558 while (state == FLDPLUS) {
2559 state = m_getfld (state, name, buf, sizeof buf, fp);
2566 for (; isspace (*bp); bp++)
2571 for (bp++, i = 0;;) {
2601 for (dp = bp; istoken (*dp); dp++)
2608 if ((result = (strcasecmp (bp, "plain") != 0)))
2611 for (dp++; isspace (*dp); dp++)
2614 if ((result = !uprf (dp, "charset")))
2616 dp += sizeof "charset" - 1;
2617 while (isspace (*dp))
2621 while (isspace (*dp))
2624 if ((bp = strchr(++dp, '"')))
2627 for (bp = dp; *bp; bp++)
2628 if (isspace (*bp)) {
2634 /* Default character set */
2637 /* Check the character set */
2638 result = !check_charset (dp, strlen (dp));
2640 if (!(result = (strcasecmp (bp, "text") != 0))) {
2650 Msgs[msgnum].m_flags |= MHNYES;
2657 * Check Content-Transfer-Encoding field
2659 if (!strcasecmp (name, ENCODING_FIELD)) {
2660 cp = add (buf, NULL);
2661 while (state == FLDPLUS) {
2662 state = m_getfld (state, name, buf, sizeof buf, fp);
2665 for (bp = cp; isspace (*bp); bp++)
2667 for (dp = bp; istoken (*dp); dp++)
2670 result = (strcasecmp (bp, "7bit")
2671 && strcasecmp (bp, "8bit")
2672 && strcasecmp (bp, "binary"));
2676 Msgs[msgnum].m_flags |= MHNYES;
2683 * Just skip the rest of this header
2684 * field and go to next one.
2686 while (state == FLDPLUS)
2687 state = m_getfld (state, name, buf, sizeof(buf), fp);
2691 * We've passed the message header,
2692 * so message is just text.
2700 static struct swit sortswit[] = {
2702 { "datefield field", 0 },
2704 { "textfield field", 0 },
2706 { "notextfield", 0 },
2708 { "limit days", 0 },
2722 sortcmd (char **args)
2724 int msgp = 0, msgnum;
2725 char *cp, *datesw = NULL, *subjsw = NULL;
2726 char buf[BUFSIZ], *msgs[MAXARGS];
2730 forkcmd (args, cmd_name);
2734 while ((cp = *args++)) {
2736 switch (smatch (++cp, sortswit)) {
2738 ambigsw (cp, sortswit);
2741 fprintf (stderr, "-%s unknown\n", cp);
2744 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2745 print_help (buf, sortswit, 1);
2750 advise (NULL, "only one date field at a time!");
2753 if (!(datesw = *args++) || *datesw == '-') {
2754 advise (NULL, "missing argument to %s", args[-2]);
2761 advise (NULL, "only one text field at a time!");
2764 if (!(subjsw = *args++) || *subjsw == '-') {
2765 advise (NULL, "missing argument to %s", args[-2]);
2773 case SOLIMT: /* too hard */
2774 if (!(cp = *args++) || *cp == '-') {
2775 advise (NULL, "missing argument to %s", args[-2]);
2779 case SOVERB: /* not implemented */
2783 if (*cp == '+' || *cp == '@') {
2784 advise (NULL, "sorry, no folders allowed!");
2792 msgs[msgp++] = "all";
2795 for (msgnum = 0; msgnum < msgp; msgnum++)
2796 if (!m_convert (mp, msgs[msgnum]))
2800 twscopy (&tb, dlocaltimenow ());
2802 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2803 if (Msgs[msgnum].m_scanl) {
2804 free (Msgs[msgnum].m_scanl);
2805 Msgs[msgnum].m_scanl = NULL;
2807 if (is_selected (mp, msgnum)) {
2808 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2809 twscopy (&Msgs[msgnum].m_tb,
2810 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2812 else /* m_scaln is already NULL */
2813 twscopy (&Msgs[msgnum].m_tb, &tb);
2814 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2815 if (mp->curmsg == msgnum)
2816 Msgs[msgnum].m_stats |= CUR;
2819 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2820 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2822 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2823 if (subjsw && Msgs[msgnum].m_scanl) {
2824 free (Msgs[msgnum].m_scanl); /* from subjsort */
2825 Msgs[msgnum].m_scanl = NULL;
2827 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2828 if (Msgs[msgnum].m_stats & CUR)
2829 seq_setcur (mp, msgnum);
2832 mp->msgflags |= MODIFIED;
2838 * get_fields - parse message, and get date and subject if needed.
2839 * We'll use the msgp->m_tb tws struct for the date, and overload
2840 * the msgp->m_scanl field with our subject string.
2843 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2845 int state, gotdate = 0;
2846 char *bp, buf[BUFSIZ], name[NAMESZ];
2847 struct tws *tw = (struct tws *) 0;
2850 zp = msh_ready (msgnum, 0);
2851 for (state = FLD;;) {
2852 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2856 if (!strcasecmp (name, datesw)) {
2858 while (state == FLDPLUS) {
2859 state = m_getfld (state, name, buf, sizeof buf, zp);
2862 if ((tw = dparsetime (bp)) == NULL)
2864 "unable to parse %s field in message %d",
2867 twscopy (&(msgp->m_tb), tw);
2869 if (!subjsw) /* not using this, or already done */
2870 break; /* all done! */
2873 else if (subjsw && !strcasecmp(name, subjsw)) {
2875 while (state == FLDPLUS) {
2876 state = m_getfld (state, name, buf, sizeof buf, zp);
2879 msgp->m_scanl = sosmash(subjsw, bp);
2881 break; /* date done so we're done */
2883 subjsw = (char *)0;/* subject done, need date */
2885 while (state == FLDPLUS) /* flush this one */
2886 state = m_getfld (state, name, buf, sizeof buf, zp);
2897 admonish (NULL, "format error in message %d", msgnum);
2898 if (msgp->m_scanl) { /* this might need free'd */
2899 free (msgp->m_scanl); /* probably can't use subj anyway */
2900 msgp->m_scanl = NULL;
2905 adios (NULL, "internal error -- you lose");
2910 return OK; /* not an error if subj not found */
2912 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2913 return NOTOK; /* NOTOK means use some other date */
2922 msgsort (struct Msg *a, struct Msg *b)
2924 return twsort (&a->m_tb, &b->m_tb);
2929 subsort (struct Msg *a, struct Msg *b)
2933 if (a->m_scanl && b->m_scanl)
2934 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2937 return twsort (&a->m_tb, &b->m_tb);
2942 * try to make the subject "canonical": delete leading "re:", everything
2943 * but letters & smash letters to lower case.
2946 sosmash (char *subj, char *s)
2948 register char *cp, *dp, c;
2952 dp = s; /* dst pointer */
2953 if (!strcasecmp (subj, "subject"))
2960 *dp++ = isupper(c) ? tolower(c) : c;
2966 while ((c = *cp++)) {
2968 *dp++ = isupper(c) ? tolower(c) : c;
2978 process (int msgnum, char *proc, int vecp, char **vec)
2980 int child_id, status;
2985 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2986 context_del (pfolder);
2987 context_replace (pfolder, fmsh);/* update current folder */
2989 context_save (); /* save the context file */
2993 strncpy (tmpfil, m_scratch ("", invo_name), sizeof(tmpfil));
2994 if ((out = fopen (tmpfil, "w")) == NULL) {
3000 strncpy (newfil, m_tmpfil (invo_name), sizeof(newfil));
3001 if ((out = fopen (newfil, "w")) == NULL) {
3003 advise (tmpfil, "unable to create temporary file");
3006 strncpy (tmpfil, newfil, sizeof(tmpfil));
3009 copy_message (msgnum, out);
3014 switch (child_id = fork ()) {
3016 advise ("fork", "unable to");
3022 SIGNAL (SIGINT, istat);
3023 SIGNAL (SIGQUIT, qstat);
3025 vec[vecp++] = tmpfil;
3029 fprintf (stderr, "unable to exec ");
3034 status = pidXwait (child_id, NULL);
3045 copy_message (int msgnum, FILE *out)
3048 static char buffer[BUFSIZ];
3051 zp = msh_ready (msgnum, 1);
3053 while (fgets (buffer, sizeof buffer, zp) != NULL) {
3054 fputs (buffer, out);
3055 if (interrupted && out == stdout)
3061 while (fgets (buffer, sizeof buffer, zp) != NULL
3062 && pos < Msgs[msgnum].m_stop) {
3063 fputs (buffer, out);
3064 pos += (long) strlen (buffer);
3065 if (interrupted && out == stdout)
3073 copy_digest (int msgnum, FILE *out)
3077 static char buffer[BUFSIZ];
3081 zp = msh_ready (msgnum, 1);
3084 while (fgets (buffer, sizeof buffer, zp) != NULL
3085 && !fmsh && pos < Msgs[msgnum].m_stop) {
3086 if (c == '\n' && *buffer == '-')
3088 fputs (buffer, out);
3089 c = buffer[strlen (buffer) - 1];
3091 pos += (long) strlen (buffer);
3092 if (interrupted && out == stdout)