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)
705 advise (NULL, "only one message at a time!\n");
714 advise (NULL, "null folder names are not permitted");
718 if (access (m_maildir (folder), R_OK) == NOTOK) {
719 advise (folder, "unable to read");
724 strncpy (buf, folder, sizeof(buf));
725 if (expand (buf) == NOTOK)
728 if (access (folder, R_OK) == NOTOK) {
729 advise (folder, "unable to read");
744 if (!m_convert (mp, msg))
748 if (mp->numsel > 1) {
749 advise (NULL, "only one message at a time!");
752 seq_setcur (mp, mp->hghsel);
757 forkcmd (vec, cmd_name);
761 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
762 adios (NULL, "unable to allocate folder storage");
764 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
765 if (does_exist (mp, msgnum)) {
766 if (msgnum != hole) {
767 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
768 Msgs[hole].m_top = Msgs[msgnum].m_top;
769 Msgs[hole].m_start = Msgs[msgnum].m_start;
770 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
771 Msgs[hole].m_scanl = NULL;
772 if (Msgs[msgnum].m_scanl) {
773 free (Msgs[msgnum].m_scanl);
774 Msgs[msgnum].m_scanl = NULL;
776 copy_msg_flags (mp, hole, msgnum);
777 if (mp->curmsg == msgnum)
778 seq_setcur (mp, hole);
782 if (mp->nummsg > 0) {
784 mp->hghmsg = hole - 1;
786 mp->msgflags |= MODIFIED;
792 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
795 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
796 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
798 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
800 /* check for empty folder */
801 if (mp->nummsg == 0) {
802 printf ("has no messages%*s",
803 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
805 printf ("has %*d message%s (%*d-%*d)",
806 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
807 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
808 if (mp->curmsg >= mp->lowmsg
809 && mp->curmsg <= mp->hghmsg)
810 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
817 static struct swit forwswit[] = {
823 { "draftfolder +folder", 0 },
825 { "draftmessage msg", 0 },
827 { "nodraftfolder", 0 },
829 { "editor editor", 0 },
833 { "filter filterfile", 0 },
835 { "form formfile", 0 },
849 { "whatnowproc program", 0 },
859 forwcmd (char **args)
861 int msgp = 0, vecp = 1, msgnum;
862 char *cp, *filter = NULL, buf[BUFSIZ];
863 char *msgs[MAXARGS], *vec[MAXARGS];
866 forkcmd (args, cmd_name);
870 while ((cp = *args++)) {
872 switch (smatch (++cp, forwswit)) {
874 ambigsw (cp, forwswit);
877 fprintf (stderr, "-%s unknown\n", cp);
880 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
881 print_help (buf, forwswit, 1);
884 case FOANSW: /* not implemented */
904 if (!(cp = *args++) || *cp == '-') {
905 advise (NULL, "missing argument to %s", args[-2]);
911 if (!(filter = *args++) || *filter == '-') {
912 advise (NULL, "missing argument to %s", args[-2]);
917 if (access (filter = myfilter, R_OK) == NOTOK) {
918 advise (filter, "unable to read default filter file");
926 if (*cp == '+' || *cp == '@') {
927 advise (NULL, "sorry, no folders allowed!");
934 /* foil search of .mh_profile */
935 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
937 Mkstemp work postponed until later -Doug
939 vec[0] = (char *)mkstemp (buf);
942 vec[0] = (char *)mktemp (buf);
946 vec[vecp++] = "-file";
949 msgs[msgp++] = "cur";
950 for (msgnum = 0; msgnum < msgp; msgnum++)
951 if (!m_convert (mp, msgs[msgnum]))
956 strncpy (buf, filter, sizeof(buf));
957 if (expand (buf) == NOTOK)
959 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
960 advise (filter, "unable to read");
965 forw (cmd_name, filter, vecp, vec);
966 seq_setcur (mp, mp->hghsel);
973 forw (char *proc, char *filter, int vecp, char **vec)
975 int i, child_id, msgnum, msgcnt;
976 char tmpfil[80], *args[MAXARGS];
979 strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
982 switch (child_id = fork ()) {
984 advise ("fork", "unable to");
987 case OK: /* "trust me" */
988 if (freopen (tmpfil, "w", stdout) == NULL) {
989 fprintf (stderr, "unable to create ");
993 args[0] = r1bindex (mhlproc, '/');
995 args[i++] = "-forwall";
998 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
999 if (is_selected (mp, msgnum))
1000 args[i++] = getcpy (m_name (msgnum));
1002 mhlsbr (i, args, mhl_action);
1003 m_eomsbr ((int (*) ()) 0);
1008 if (pidXwait (child_id, NULL))
1013 if ((out = fopen (tmpfil, "w")) == NULL) {
1014 advise (tmpfil, "unable to create temporary file");
1019 for (msgnum = mp->lowsel;
1020 msgnum <= mp->hghsel && !interrupted;
1022 if (is_selected (mp, msgnum)) {
1023 fprintf (out, "\n\n-------");
1024 if (msgnum == mp->lowsel)
1025 fprintf (out, " Forwarded Message%s",
1026 mp->numsel > 1 ? "s" : "");
1028 fprintf (out, " Message %d", msgcnt);
1029 fprintf (out, "\n\n");
1030 copy_digest (msgnum, out);
1034 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1035 mp->numsel > 1 ? "s" : "");
1041 switch (child_id = fork ()) {
1043 advise ("fork", "unable to");
1048 SIGNAL (SIGINT, istat);
1049 SIGNAL (SIGQUIT, qstat);
1051 vec[vecp++] = tmpfil;
1055 fprintf (stderr, "unable to exec ");
1060 pidXwait (child_id, NULL);
1068 static char *hlpmsg[] = {
1069 "The %s program emulates many of the commands found in the nmh",
1070 "system. Instead of operating on nmh folders, commands to %s concern",
1073 "To see the list of commands available, just type a ``?'' followed by",
1074 "the RETURN key. To find out what switches each command takes, type",
1075 "the name of the command followed by ``-help''. To leave %s, use the",
1076 "``quit'' command.",
1078 "Although a lot of nmh commands are found in %s, not all are fully",
1079 "implemented. %s will always recognize all legal switches for a",
1080 "given command though, and will let you know when you ask for an",
1081 "option that it is unable to perform.",
1083 "Running %s is fun, but using nmh from your shell is far superior.",
1084 "After you have familiarized yourself with the nmh style by using %s,",
1085 "you should try using nmh from the shell. You can still use %s for",
1086 "message files that aren't in nmh format, such as BBoard files.",
1092 helpcmd (char **args)
1096 for (i = 0; hlpmsg[i]; i++) {
1097 printf (hlpmsg[i], invo_name);
1103 static struct swit markswit[] = {
1111 { "sequence name", 0 },
1129 markcmd (char **args)
1131 int addsw = 0, deletesw = 0, debugsw = 0;
1132 int listsw = 0, zerosw = 0, seqp = 0;
1133 int msgp = 0, msgnum;
1134 char *cp, buf[BUFSIZ];
1135 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1137 while ((cp = *args++)) {
1139 switch (smatch (++cp, markswit)) {
1141 ambigsw (cp, markswit);
1144 fprintf (stderr, "-%s unknown\n", cp);
1147 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1148 print_help (buf, markswit, 1);
1153 deletesw = listsw = 0;
1161 addsw = deletesw = 0;
1165 if (!(cp = *args++) || *cp == '-') {
1166 advise (NULL, "missing argument to %s", args[-2]);
1169 if (seqp < NUMATTRS)
1172 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1177 case MPUBSW: /* not implemented */
1193 if (*cp == '+' || *cp == '@') {
1194 advise (NULL, "sorry, no folders allowed!");
1201 if (!addsw && !deletesw && !listsw) {
1208 seqs[seqp++] = "unseen";
1212 msgs[msgp++] = "all";
1217 msgs[msgp++] = listsw ? "all" :"cur";
1218 for (msgnum = 0; msgnum < msgp; msgnum++)
1219 if (!m_convert (mp, msgs[msgnum]))
1223 printf ("invo_name=%s mypath=%s defpath=%s\n",
1224 invo_name, mypath, defpath);
1225 printf ("ctxpath=%s context flags=%s\n",
1226 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1227 printf ("foldpath=%s flags=%s\n",
1229 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1230 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1231 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1232 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1233 mp->lowsel, mp->hghsel, mp->numsel);
1234 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1237 if (seqp == 0 && (addsw || deletesw)) {
1238 advise (NULL, "-%s requires at least one -sequence argument",
1239 addsw ? "add" : "delete");
1245 for (seqp = 0; seqs[seqp]; seqp++)
1246 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1251 for (seqp = 0; seqs[seqp]; seqp++)
1252 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1256 /* Listing messages in sequences */
1259 /* list the given sequences */
1260 for (seqp = 0; seqs[seqp]; seqp++)
1261 seq_print (mp, seqs[seqp]);
1263 /* else list them all */
1269 for (msgnum = mp->lowsel;
1270 msgnum <= mp->hghsel && !interrupted;
1272 if (is_selected (mp, msgnum)) {
1273 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1276 Msgs[msgnum].m_bboard_id,
1278 (long) Msgs[msgnum].m_start,
1279 (long) Msgs[msgnum].m_stop,
1280 snprintb (buf, sizeof(buf),
1281 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1283 if (Msgs[msgnum].m_scanl)
1284 printf ("%s", Msgs[msgnum].m_scanl);
1290 static struct swit mhnswit[] = {
1293 #define MHNNAUTOSW 1
1295 #define MHNDEBUGSW 2
1297 #define MHNEBCDICSW 3
1298 { "ebcdicsafe", 0 },
1299 #define MHNNEBCDICSW 4
1300 { "noebcdicsafe", 0 },
1302 { "form formfile", 4 },
1305 #define MHNNHEADSW 7
1309 #define MHNNLISTSW 9
1311 #define MHNPARTSW 10
1312 { "part number", 0 },
1313 #define MHNSIZESW 11
1315 #define MHNNSIZESW 12
1316 { "norealsize", 0 },
1317 #define MHNRFC934SW 13
1318 { "rfc934mode", 0 },
1319 #define MHNNRFC934SW 14
1320 { "norfc934mode", 0 },
1321 #define MHNSERIALSW 15
1322 { "serialonly", 0 },
1323 #define MHNNSERIALSW 16
1324 { "noserialonly", 0 },
1325 #define MHNSHOWSW 17
1327 #define MHNNSHOWSW 18
1329 #define MHNSTORESW 19
1331 #define MHNNSTORESW 20
1333 #define MHNTYPESW 21
1334 { "type content", 0 },
1335 #define MHNVERBSW 22
1337 #define MHNNVERBSW 23
1339 #define MHNHELPSW 24
1341 #define MHNPROGSW 25
1342 { "moreproc program", -4 },
1343 #define MHNNPROGSW 26
1344 { "nomoreproc", -3 },
1346 { "length lines", -4 },
1348 { "width columns", -4 },
1354 mhncmd (char **args)
1356 int msgp = 0, vecp = 1;
1358 char *cp, buf[BUFSIZ];
1359 char *msgs[MAXARGS], *vec[MAXARGS];
1362 forkcmd (args, cmd_name);
1365 while ((cp = *args++)) {
1367 switch (smatch (++cp, mhnswit)) {
1369 ambigsw (cp, mhnswit);
1372 fprintf (stderr, "-%s unknown\n", cp);
1375 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1376 print_help (buf, mhnswit, 1);
1411 if (!(cp = *args++) || *cp == '-') {
1412 advise (NULL, "missing argument to %s", args[-2]);
1419 if (*cp == '+' || *cp == '@') {
1420 advise (NULL, "sorry, no folders allowed!");
1428 vec[vecp++] = "-file";
1431 msgs[msgp++] = "cur";
1432 for (msgnum = 0; msgnum < msgp; msgnum++)
1433 if (!m_convert (mp, msgs[msgnum]))
1438 for (msgnum = mp->lowsel;
1439 msgnum <= mp->hghsel && !interrupted;
1441 if (is_selected (mp, msgnum))
1442 if (process (msgnum, cmd_name, vecp, vec)) {
1443 unset_selected (mp, msgnum);
1447 seq_setcur (mp, mp->hghsel);
1451 static struct swit packswit[] = {
1459 static mbx_style = MMDF_FORMAT;
1462 packcmd (char **args)
1464 int msgp = 0, md, msgnum;
1465 char *cp, *file = NULL;
1466 char buf[BUFSIZ], *msgs[MAXARGS];
1470 forkcmd (args, cmd_name);
1474 while ((cp = *args++)) {
1476 switch (smatch (++cp, packswit)) {
1478 ambigsw (cp, packswit);
1481 fprintf (stderr, "-%s unknown\n", cp);
1484 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1485 print_help (buf, packswit, 1);
1489 if (!(file = *args++) || *file == '-') {
1490 advise (NULL, "missing argument to %s", args[-2]);
1495 if (*cp == '+' || *cp == '@') {
1496 advise (NULL, "sorry, no folders allowed!");
1505 file = path (file, TFILE);
1506 if (stat (file, &st) == NOTOK) {
1507 if (errno != ENOENT) {
1508 advise (file, "error on file");
1511 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1518 msgs[msgp++] = "all";
1519 for (msgnum = 0; msgnum < msgp; msgnum++)
1520 if (!m_convert (mp, msgs[msgnum]))
1524 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1525 advise (file, "unable to open");
1528 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1529 if (is_selected (mp, msgnum))
1530 if (pack (file, md, msgnum) == NOTOK)
1532 mbx_close (file, md);
1534 if (mp->hghsel != mp->curmsg)
1535 seq_setcur (mp, mp->lowsel);
1543 pack (char *mailbox, int md, int msgnum)
1547 if (Msgs[msgnum].m_bboard_id == 0)
1550 zp = msh_ready (msgnum, 1);
1551 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1552 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1557 packhak (char **args)
1560 char *cp, *file = NULL;
1562 while ((cp = *args++)) {
1564 switch (smatch (++cp, packswit)) {
1571 if (!(file = *args++) || *file == '-')
1575 if (*cp == '+' || *cp == '@')
1579 file = path (file ? file : "./msgbox", TFILE);
1580 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1587 static struct swit pickswit[] = {
1599 { "cc pattern", 0 },
1601 { "date pattern", 0 },
1603 { "from pattern", 0 },
1605 { "search pattern", 0 },
1607 { "subject pattern", 0 },
1609 { "to pattern", 0 },
1611 { "-othercomponent pattern", 15 },
1613 { "after date", 0 },
1615 { "before date", 0 },
1617 { "datefield field", 5 },
1619 { "sequence name", 0 },
1639 pickcmd (char **args)
1641 int zerosw = 1, msgp = 0, seqp = 0;
1642 int vecp = 0, hi, lo, msgnum;
1643 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1644 char *seqs[NUMATTRS], *vec[MAXARGS];
1647 while ((cp = *args++)) {
1653 switch (smatch (cp, pickswit)) {
1655 ambigsw (cp, pickswit);
1658 fprintf (stderr, "-%s unknown\n", cp);
1661 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1662 print_help (buf, pickswit, 1);
1676 if (!(cp = *args++)) {/* allow -xyz arguments */
1677 advise (NULL, "missing argument to %s", args[-2]);
1683 advise (NULL, "internal error!");
1694 if (!(cp = *args++) || *cp == '-') {
1695 advise (NULL, "missing argument to %s", args[-2]);
1698 if (seqp < NUMATTRS)
1701 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1712 case PIPUSW: /* not implemented */
1719 if (*cp == '+' || *cp == '@') {
1720 advise (NULL, "sorry, no folders allowed!");
1729 msgs[msgp++] = "all";
1730 for (msgnum = 0; msgnum < msgp; msgnum++)
1731 if (!m_convert (mp, msgs[msgnum]))
1736 if (!pcompile (vec, NULL))
1742 for (msgnum = mp->lowsel;
1743 msgnum <= mp->hghsel && !interrupted;
1745 if (is_selected (mp, msgnum)) {
1746 zp = msh_ready (msgnum, 1);
1747 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1748 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1755 unset_selected (mp, msgnum);
1766 if (mp->numsel <= 0) {
1767 advise (NULL, "no messages match specification");
1772 for (seqp = 0; seqs[seqp]; seqp++)
1773 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1776 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1780 static struct swit replswit[] = {
1784 { "noannotate", 0 },
1790 { "draftfolder +folder", 0 },
1792 { "draftmessage msg", 0 },
1794 { "nodraftfolder", 0 },
1796 { "editor editor", 0 },
1800 { "fcc +folder", 0 },
1802 { "filter filterfile", 0 },
1804 { "form formfile", 0 },
1814 { "whatnowproc program", 0 },
1818 { "width columns", 0 },
1826 replcmd (char **args)
1829 char *cp, *msg = NULL;
1830 char buf[BUFSIZ], *vec[MAXARGS];
1833 forkcmd (args, cmd_name);
1837 while ((cp = *args++)) {
1839 switch (smatch (++cp, replswit)) {
1841 ambigsw (cp, replswit);
1844 fprintf (stderr, "-%s unknown\n", cp);
1847 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1848 print_help (buf, replswit, 1);
1851 case REANSW: /* not implemented */
1876 if (!(cp = *args++) || *cp == '-') {
1877 advise (NULL, "missing argument to %s", args[-2]);
1883 if (*cp == '+' || *cp == '@') {
1884 advise (NULL, "sorry, no folders allowed!");
1889 advise (NULL, "only one message at a time!");
1897 vec[vecp++] = "-file";
1901 if (!m_convert (mp, msg))
1905 if (mp->numsel > 1) {
1906 advise (NULL, "only one message at a time!");
1909 process (mp->hghsel, cmd_name, vecp, vec);
1910 seq_setcur (mp, mp->hghsel);
1914 static struct swit rmmswit[] = {
1922 rmmcmd (char **args)
1924 int msgp = 0, msgnum;
1925 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1927 while ((cp = *args++)) {
1929 switch (smatch (++cp, rmmswit)) {
1931 ambigsw (cp, rmmswit);
1934 fprintf (stderr, "-%s unknown\n", cp);
1937 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1938 print_help (buf, rmmswit, 1);
1941 if (*cp == '+' || *cp == '@') {
1942 advise (NULL, "sorry, no folders allowed!");
1950 msgs[msgp++] = "cur";
1951 for (msgnum = 0; msgnum < msgp; msgnum++)
1952 if (!m_convert (mp, msgs[msgnum]))
1963 register int msgnum, vecp;
1965 char buffer[BUFSIZ], *vec[MAXARGS];
1969 if (mp->numsel > MAXARGS - 1) {
1970 advise (NULL, "more than %d messages for %s exec",
1971 MAXARGS - 1, rmmproc);
1975 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1976 if (is_selected (mp, msgnum))
1977 vec[vecp++] = getcpy (m_name (msgnum));
1979 forkcmd (vec, rmmproc);
1980 for (vecp = 0; vec[vecp]; vecp++)
1984 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1985 if (is_selected (mp, msgnum)) {
1986 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1987 if (rename (cp, buffer) == NOTOK)
1988 admonish (buffer, "unable to rename %s to", cp);
1992 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1993 if (is_selected (mp, msgnum)) {
1994 set_deleted (mp, msgnum);
1995 unset_exists (mp, msgnum);
1998 if (pmsh && pop_dele (msgnum) != OK)
1999 fprintf (stderr, "%s", response);
2004 if ((mp->nummsg -= mp->numsel) <= 0) {
2006 admonish (NULL, "no messages remaining in +%s", fmsh);
2008 admonish (NULL, "no messages remaining in %s", mp->foldpath);
2009 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2011 if (mp->lowsel == mp->lowmsg) {
2012 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2013 if (does_exist (mp, msgnum))
2015 mp->lowmsg = msgnum;
2017 if (mp->hghsel == mp->hghmsg) {
2018 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2019 if (does_exist (mp, msgnum))
2021 mp->hghmsg = msgnum;
2024 mp->msgflags |= MODIFIED;
2029 static struct swit scanswit[] = {
2035 { "form formatfile", 0 },
2037 { "format string", 5 },
2043 { "width columns", 0 },
2051 scancmd (char **args)
2053 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2055 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2056 int msgnum, optim, state;
2057 char *cp, *form = NULL, *format = NULL;
2058 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2062 static int p_optim = 0;
2065 static int s_optim = 0;
2066 static char *s_form = NULL, *s_format = NULL;
2068 while ((cp = *args++)) {
2070 switch (smatch (++cp, scanswit)) {
2072 ambigsw (cp, scanswit);
2075 fprintf (stderr, "-%s unknown\n", cp);
2078 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2079 print_help (buf, scanswit, 1);
2095 if (!(form = *args++) || *form == '-') {
2096 advise (NULL, "missing argument to %s", args[-2]);
2102 if (!(format = *args++) || *format == '-') {
2103 advise (NULL, "missing argument to %s", args[-2]);
2109 if (!(cp = *args++) || *cp == '-') {
2110 advise (NULL, "missing argument to %s", args[-2]);
2116 if (*cp == '+' || *cp == '@') {
2117 advise (NULL, "sorry, no folders allowed!");
2125 msgs[msgp++] = "all";
2126 for (msgnum = 0; msgnum < msgp; msgnum++)
2127 if (!m_convert (mp, msgs[msgnum]))
2131 /* Get new format string */
2132 nfs = new_fs (form, format, FORMAT);
2134 /* force scansbr to (re)compile format */
2141 s_optim = optim = 1;
2142 s_form = form ? getcpy (form) : NULL;
2143 s_format = format ? getcpy (format) : NULL;
2152 width = sc_width ();
2154 for (dp = nfs, i = 0; *dp; dp++, i++)
2155 if (*dp == '\\' || *dp == '"' || *dp == '\n')
2158 if ((ep = malloc ((unsigned) i)) == NULL)
2159 adios (NULL, "out of memory");
2160 for (dp = nfs, fp = ep; *dp; dp++) {
2162 *fp++ = '\\', *fp++ = 'n';
2165 if (*dp == '"' || *dp == '\\')
2171 if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK)
2180 optim = equiv (s_form, form) && equiv (s_format, format);
2184 if (p_optim && optim) {
2185 for (msgnum = mp->lowmsg; msgnum <= mp->hghmsg; msgnum++)
2186 if (!is_selected(mp, msgnum) || Msgs[msgnum].m_scanl)
2188 if (msgnum > mp->hghmsg && pop_command ("LIST") == OK) {
2189 fprintf (stderr, "Stand-by...");
2195 switch (pop_multiline ()) {
2197 fprintf (stderr, "%s", response);
2200 fprintf (stderr,"\n");
2204 if (sscanf (response, "%d %d", &msgnum, &size) == 2
2205 && mp->lowmsg <= msgnum
2206 && msgnum <= mp->hghmsg
2207 && (cp = strchr(response, '#'))
2209 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2220 for (msgnum = mp->lowsel;
2221 msgnum <= mp->hghsel && !interrupted;
2223 if (is_selected (mp, msgnum)) {
2224 if (optim && Msgs[msgnum].m_scanl)
2225 printf ("%s", Msgs[msgnum].m_scanl);
2231 && is_virtual (mp, msgnum)
2232 && pop_command ("LIST %d", msgnum) == OK
2233 && (cp = strchr(response, '#'))
2235 Msgs[msgnum].m_scanl = concat (cp, "\n", NULL);
2236 printf ("%s", Msgs[msgnum].m_scanl);
2242 zp = msh_ready (msgnum, 0);
2243 switch (state = scan (zp, msgnum, 0, nfs, width,
2244 msgnum == mp->curmsg,
2245 is_unseen (mp, msgnum),
2246 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2247 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2253 Msgs[msgnum].m_scanl = getcpy (scanl);
2257 advise (NULL, "scan() botch (%d)", state);
2261 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2273 static struct swit showswit[] = {
2277 { "form formfile", 4 },
2279 { "moreproc program", 4 },
2281 { "nomoreproc", 3 },
2283 { "length lines", 4 },
2285 { "width columns", 4 },
2287 { "showproc program", 4 },
2289 { "noshowproc", 3 },
2301 showcmd (char **args)
2303 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2304 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2305 char *cp, *proc = showproc, buf[BUFSIZ];
2306 char *msgs[MAXARGS], *vec[MAXARGS];
2308 if (!strcasecmp (cmd_name, "next"))
2311 if (!strcasecmp (cmd_name, "prev"))
2313 while ((cp = *args++)) {
2315 switch (i = smatch (++cp, showswit)) {
2317 ambigsw (cp, showswit);
2324 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2325 cmd_name, mode ? NULL : "[msgs] ");
2326 print_help (buf, showswit, 1);
2334 if (!(cp = *args++) || *cp == '-') {
2335 advise (NULL, "missing argument to %s", args[-2]);
2347 if (!(proc = *args++) || *proc == '-') {
2348 advise (NULL, "missing argument to %s", args[-2]);
2358 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2361 if (*cp == '+' || *cp == '@') {
2362 advise (NULL, "sorry, no folders allowed!");
2368 "usage: %s [switches] [switches for showproc]\n",
2378 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2379 for (msgnum = 0; msgnum < msgp; msgnum++)
2380 if (!m_convert (mp, msgs[msgnum]))
2384 if (!nshow && !getenv ("NOMHNPROC"))
2385 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2386 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2387 proc = showmimeproc;
2388 vec[vecp++] = "-show";
2389 vec[vecp++] = "-file";
2397 if (strcmp (showproc, "mhl") == 0) {
2403 seqnum = seq_getnum (mp, "unseen");
2404 vec[0] = r1bindex (proc, '/');
2407 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2408 if (is_selected (mp, msgnum)) {
2409 vec[vecp++] = getcpy (m_name (msgnum));
2411 seq_delmsg (mp, "unseen", msgnum);
2414 if (mp->numsel == 1 && headersw)
2416 mhlsbr (vecp, vec, mhl_action);
2417 m_eomsbr ((int (*)()) 0);
2422 for (msgnum = mp->lowsel;
2423 msgnum <= mp->hghsel && !interrupted;
2425 if (is_selected (mp, msgnum)) {
2426 switch (ask (msgnum)) {
2427 case NOTOK: /* QUIT */
2434 if (mp->numsel == 1 && headersw)
2437 copy_message (msgnum, stdout);
2439 process (msgnum, proc, vecp, vec);
2442 seq_delmsg (mp, "unseen", msgnum);
2449 seq_setcur (mp, mp->hghsel);
2456 if (Msgs[msgnum].m_bboard_id == 0)
2459 printf ("(Message %d", msgnum);
2460 if (Msgs[msgnum].m_bboard_id > 0)
2461 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2470 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2475 mhl_action (char *name)
2479 if ((msgnum = m_atoi (name)) < mp->lowmsg
2480 || msgnum > mp->hghmsg
2481 || !does_exist (mp, msgnum))
2485 mhlfp = msh_ready (msgnum, 1);
2487 m_eomsbr (eom_action);
2499 if (mp->numsel == 1 || !interactive || redirected)
2502 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2503 if (mp->lowsel != msgnum)
2505 printf ("Press <return> to list \"%d\"...", msgnum);
2511 read (fileno (stdout), buf, sizeof buf);
2513 switch (setjmp (sigenv)) {
2516 read (fileno (stdout), buf, sizeof buf);/* fall... */
2524 if (strchr(buf, '\n') == NULL)
2528 told_to_quit = interrupted = 0;
2543 is_nontext (int msgnum)
2547 char buf[BUFSIZ], name[NAMESZ];
2550 if (Msgs[msgnum].m_flags & MHNCHK)
2551 return (Msgs[msgnum].m_flags & MHNYES);
2552 Msgs[msgnum].m_flags |= MHNCHK;
2554 fp = msh_ready (msgnum, 1);
2557 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2562 * Check Content-Type field
2564 if (!strcasecmp (name, TYPE_FIELD)) {
2568 cp = add (buf, NULL);
2569 while (state == FLDPLUS) {
2570 state = m_getfld (state, name, buf, sizeof buf, fp);
2577 for (; isspace (*bp); bp++)
2582 for (bp++, i = 0;;) {
2612 for (dp = bp; istoken (*dp); dp++)
2619 if ((result = (strcasecmp (bp, "plain") != 0)))
2622 for (dp++; isspace (*dp); dp++)
2625 if ((result = !uprf (dp, "charset")))
2627 dp += sizeof "charset" - 1;
2628 while (isspace (*dp))
2632 while (isspace (*dp))
2635 if ((bp = strchr(++dp, '"')))
2638 for (bp = dp; *bp; bp++)
2639 if (isspace (*bp)) {
2645 /* Default character set */
2648 /* Check the character set */
2649 result = !check_charset (dp, strlen (dp));
2651 if (!(result = (strcasecmp (bp, "text") != 0))) {
2661 Msgs[msgnum].m_flags |= MHNYES;
2668 * Check Content-Transfer-Encoding field
2670 if (!strcasecmp (name, ENCODING_FIELD)) {
2671 cp = add (buf, NULL);
2672 while (state == FLDPLUS) {
2673 state = m_getfld (state, name, buf, sizeof buf, fp);
2676 for (bp = cp; isspace (*bp); bp++)
2678 for (dp = bp; istoken (*dp); dp++)
2681 result = (strcasecmp (bp, "7bit")
2682 && strcasecmp (bp, "8bit")
2683 && strcasecmp (bp, "binary"));
2687 Msgs[msgnum].m_flags |= MHNYES;
2694 * Just skip the rest of this header
2695 * field and go to next one.
2697 while (state == FLDPLUS)
2698 state = m_getfld (state, name, buf, sizeof(buf), fp);
2702 * We've passed the message header,
2703 * so message is just text.
2711 static struct swit sortswit[] = {
2713 { "datefield field", 0 },
2715 { "textfield field", 0 },
2717 { "notextfield", 0 },
2719 { "limit days", 0 },
2733 sortcmd (char **args)
2735 int msgp = 0, msgnum;
2736 char *cp, *datesw = NULL, *subjsw = NULL;
2737 char buf[BUFSIZ], *msgs[MAXARGS];
2741 forkcmd (args, cmd_name);
2745 while ((cp = *args++)) {
2747 switch (smatch (++cp, sortswit)) {
2749 ambigsw (cp, sortswit);
2752 fprintf (stderr, "-%s unknown\n", cp);
2755 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2756 print_help (buf, sortswit, 1);
2761 advise (NULL, "only one date field at a time!");
2764 if (!(datesw = *args++) || *datesw == '-') {
2765 advise (NULL, "missing argument to %s", args[-2]);
2772 advise (NULL, "only one text field at a time!");
2775 if (!(subjsw = *args++) || *subjsw == '-') {
2776 advise (NULL, "missing argument to %s", args[-2]);
2784 case SOLIMT: /* too hard */
2785 if (!(cp = *args++) || *cp == '-') {
2786 advise (NULL, "missing argument to %s", args[-2]);
2790 case SOVERB: /* not implemented */
2794 if (*cp == '+' || *cp == '@') {
2795 advise (NULL, "sorry, no folders allowed!");
2803 msgs[msgp++] = "all";
2806 for (msgnum = 0; msgnum < msgp; msgnum++)
2807 if (!m_convert (mp, msgs[msgnum]))
2811 twscopy (&tb, dlocaltimenow ());
2813 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2814 if (Msgs[msgnum].m_scanl) {
2815 free (Msgs[msgnum].m_scanl);
2816 Msgs[msgnum].m_scanl = NULL;
2818 if (is_selected (mp, msgnum)) {
2819 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2820 twscopy (&Msgs[msgnum].m_tb,
2821 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2823 else /* m_scaln is already NULL */
2824 twscopy (&Msgs[msgnum].m_tb, &tb);
2825 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2826 if (mp->curmsg == msgnum)
2827 Msgs[msgnum].m_stats |= CUR;
2830 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2831 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2833 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2834 if (subjsw && Msgs[msgnum].m_scanl) {
2835 free (Msgs[msgnum].m_scanl); /* from subjsort */
2836 Msgs[msgnum].m_scanl = NULL;
2838 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2839 if (Msgs[msgnum].m_stats & CUR)
2840 seq_setcur (mp, msgnum);
2843 mp->msgflags |= MODIFIED;
2849 * get_fields - parse message, and get date and subject if needed.
2850 * We'll use the msgp->m_tb tws struct for the date, and overload
2851 * the msgp->m_scanl field with our subject string.
2854 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2856 int state, gotdate = 0;
2857 char *bp, buf[BUFSIZ], name[NAMESZ];
2858 struct tws *tw = (struct tws *) 0;
2861 zp = msh_ready (msgnum, 0);
2862 for (state = FLD;;) {
2863 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2867 if (!strcasecmp (name, datesw)) {
2869 while (state == FLDPLUS) {
2870 state = m_getfld (state, name, buf, sizeof buf, zp);
2873 if ((tw = dparsetime (bp)) == NULL)
2875 "unable to parse %s field in message %d",
2878 twscopy (&(msgp->m_tb), tw);
2880 if (!subjsw) /* not using this, or already done */
2881 break; /* all done! */
2884 else if (subjsw && !strcasecmp(name, subjsw)) {
2886 while (state == FLDPLUS) {
2887 state = m_getfld (state, name, buf, sizeof buf, zp);
2890 msgp->m_scanl = sosmash(subjsw, bp);
2892 break; /* date done so we're done */
2894 subjsw = (char *)0;/* subject done, need date */
2896 while (state == FLDPLUS) /* flush this one */
2897 state = m_getfld (state, name, buf, sizeof buf, zp);
2908 admonish (NULL, "format error in message %d", msgnum);
2909 if (msgp->m_scanl) { /* this might need free'd */
2910 free (msgp->m_scanl); /* probably can't use subj anyway */
2911 msgp->m_scanl = NULL;
2916 adios (NULL, "internal error -- you lose");
2921 return OK; /* not an error if subj not found */
2923 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2924 return NOTOK; /* NOTOK means use some other date */
2933 msgsort (struct Msg *a, struct Msg *b)
2935 return twsort (&a->m_tb, &b->m_tb);
2940 subsort (struct Msg *a, struct Msg *b)
2944 if (a->m_scanl && b->m_scanl)
2945 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2948 return twsort (&a->m_tb, &b->m_tb);
2953 * try to make the subject "canonical": delete leading "re:", everything
2954 * but letters & smash letters to lower case.
2957 sosmash (char *subj, char *s)
2959 register char *cp, *dp, c;
2963 dp = s; /* dst pointer */
2964 if (!strcasecmp (subj, "subject"))
2971 *dp++ = isupper(c) ? tolower(c) : c;
2977 while ((c = *cp++)) {
2979 *dp++ = isupper(c) ? tolower(c) : c;
2989 process (int msgnum, char *proc, int vecp, char **vec)
2991 int child_id, status;
2996 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2997 context_del (pfolder);
2998 context_replace (pfolder, fmsh);/* update current folder */
3000 context_save (); /* save the context file */
3004 strncpy (tmpfil, m_scratch ("", invo_name), sizeof(tmpfil));
3005 if ((out = fopen (tmpfil, "w")) == NULL) {
3011 strncpy (newfil, m_tmpfil (invo_name), sizeof(newfil));
3012 if ((out = fopen (newfil, "w")) == NULL) {
3014 advise (tmpfil, "unable to create temporary file");
3017 strncpy (tmpfil, newfil, sizeof(tmpfil));
3020 copy_message (msgnum, out);
3025 switch (child_id = fork ()) {
3027 advise ("fork", "unable to");
3033 SIGNAL (SIGINT, istat);
3034 SIGNAL (SIGQUIT, qstat);
3036 vec[vecp++] = tmpfil;
3040 fprintf (stderr, "unable to exec ");
3045 status = pidXwait (child_id, NULL);
3056 copy_message (int msgnum, FILE *out)
3059 static char buffer[BUFSIZ];
3062 zp = msh_ready (msgnum, 1);
3064 while (fgets (buffer, sizeof buffer, zp) != NULL) {
3065 fputs (buffer, out);
3066 if (interrupted && out == stdout)
3072 while (fgets (buffer, sizeof buffer, zp) != NULL
3073 && pos < Msgs[msgnum].m_stop) {
3074 fputs (buffer, out);
3075 pos += (long) strlen (buffer);
3076 if (interrupted && out == stdout)
3084 copy_digest (int msgnum, FILE *out)
3088 static char buffer[BUFSIZ];
3092 zp = msh_ready (msgnum, 1);
3095 while (fgets (buffer, sizeof buffer, zp) != NULL
3096 && !fmsh && pos < Msgs[msgnum].m_stop) {
3097 if (c == '\n' && *buffer == '-')
3099 fputs (buffer, out);
3100 c = buffer[strlen (buffer) - 1];
3102 pos += (long) strlen (buffer);
3103 if (interrupted && out == stdout)