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)
1093 for (i = 0; hlpmsg[i]; i++) {
1094 printf (hlpmsg[i], invo_name);
1100 static struct swit markswit[] = {
1108 { "sequence name", 0 },
1126 markcmd (char **args)
1128 int addsw = 0, deletesw = 0, debugsw = 0;
1129 int listsw = 0, zerosw = 0, seqp = 0;
1130 int msgp = 0, msgnum;
1131 char *cp, buf[BUFSIZ];
1132 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1134 while ((cp = *args++)) {
1136 switch (smatch (++cp, markswit)) {
1138 ambigsw (cp, markswit);
1141 fprintf (stderr, "-%s unknown\n", cp);
1144 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1145 print_help (buf, markswit, 1);
1150 deletesw = listsw = 0;
1158 addsw = deletesw = 0;
1162 if (!(cp = *args++) || *cp == '-') {
1163 advise (NULL, "missing argument to %s", args[-2]);
1166 if (seqp < NUMATTRS)
1169 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1174 case MPUBSW: /* not implemented */
1190 if (*cp == '+' || *cp == '@') {
1191 advise (NULL, "sorry, no folders allowed!");
1198 if (!addsw && !deletesw && !listsw) {
1205 seqs[seqp++] = "unseen";
1209 msgs[msgp++] = "all";
1214 msgs[msgp++] = listsw ? "all" :"cur";
1215 for (msgnum = 0; msgnum < msgp; msgnum++)
1216 if (!m_convert (mp, msgs[msgnum]))
1220 printf ("invo_name=%s mypath=%s defpath=%s\n",
1221 invo_name, mypath, defpath);
1222 printf ("ctxpath=%s context flags=%s\n",
1223 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1224 printf ("foldpath=%s flags=%s\n",
1226 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1227 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1228 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1229 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1230 mp->lowsel, mp->hghsel, mp->numsel);
1231 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1234 if (seqp == 0 && (addsw || deletesw)) {
1235 advise (NULL, "-%s requires at least one -sequence argument",
1236 addsw ? "add" : "delete");
1242 for (seqp = 0; seqs[seqp]; seqp++)
1243 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1248 for (seqp = 0; seqs[seqp]; seqp++)
1249 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1253 /* Listing messages in sequences */
1256 /* list the given sequences */
1257 for (seqp = 0; seqs[seqp]; seqp++)
1258 seq_print (mp, seqs[seqp]);
1260 /* else list them all */
1266 for (msgnum = mp->lowsel;
1267 msgnum <= mp->hghsel && !interrupted;
1269 if (is_selected (mp, msgnum)) {
1270 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1273 Msgs[msgnum].m_bboard_id,
1275 (long) Msgs[msgnum].m_start,
1276 (long) Msgs[msgnum].m_stop,
1277 snprintb (buf, sizeof(buf),
1278 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1280 if (Msgs[msgnum].m_scanl)
1281 printf ("%s", Msgs[msgnum].m_scanl);
1287 static struct swit mhnswit[] = {
1290 #define MHNNAUTOSW 1
1292 #define MHNDEBUGSW 2
1294 #define MHNEBCDICSW 3
1295 { "ebcdicsafe", 0 },
1296 #define MHNNEBCDICSW 4
1297 { "noebcdicsafe", 0 },
1299 { "form formfile", 4 },
1302 #define MHNNHEADSW 7
1306 #define MHNNLISTSW 9
1308 #define MHNPARTSW 10
1309 { "part number", 0 },
1310 #define MHNSIZESW 11
1312 #define MHNNSIZESW 12
1313 { "norealsize", 0 },
1314 #define MHNRFC934SW 13
1315 { "rfc934mode", 0 },
1316 #define MHNNRFC934SW 14
1317 { "norfc934mode", 0 },
1318 #define MHNSERIALSW 15
1319 { "serialonly", 0 },
1320 #define MHNNSERIALSW 16
1321 { "noserialonly", 0 },
1322 #define MHNSHOWSW 17
1324 #define MHNNSHOWSW 18
1326 #define MHNSTORESW 19
1328 #define MHNNSTORESW 20
1330 #define MHNTYPESW 21
1331 { "type content", 0 },
1332 #define MHNVERBSW 22
1334 #define MHNNVERBSW 23
1336 #define MHNHELPSW 24
1338 #define MHNPROGSW 25
1339 { "moreproc program", -4 },
1340 #define MHNNPROGSW 26
1341 { "nomoreproc", -3 },
1343 { "length lines", -4 },
1345 { "width columns", -4 },
1351 mhncmd (char **args)
1353 int msgp = 0, vecp = 1;
1355 char *cp, buf[BUFSIZ];
1356 char *msgs[MAXARGS], *vec[MAXARGS];
1359 forkcmd (args, cmd_name);
1362 while ((cp = *args++)) {
1364 switch (smatch (++cp, mhnswit)) {
1366 ambigsw (cp, mhnswit);
1369 fprintf (stderr, "-%s unknown\n", cp);
1372 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1373 print_help (buf, mhnswit, 1);
1408 if (!(cp = *args++) || *cp == '-') {
1409 advise (NULL, "missing argument to %s", args[-2]);
1416 if (*cp == '+' || *cp == '@') {
1417 advise (NULL, "sorry, no folders allowed!");
1425 vec[vecp++] = "-file";
1428 msgs[msgp++] = "cur";
1429 for (msgnum = 0; msgnum < msgp; msgnum++)
1430 if (!m_convert (mp, msgs[msgnum]))
1435 for (msgnum = mp->lowsel;
1436 msgnum <= mp->hghsel && !interrupted;
1438 if (is_selected (mp, msgnum))
1439 if (process (msgnum, cmd_name, vecp, vec)) {
1440 unset_selected (mp, msgnum);
1444 seq_setcur (mp, mp->hghsel);
1448 static struct swit packswit[] = {
1456 static int mbx_style = MMDF_FORMAT;
1459 packcmd (char **args)
1461 int msgp = 0, md, msgnum;
1462 char *cp, *file = NULL;
1463 char buf[BUFSIZ], *msgs[MAXARGS];
1467 forkcmd (args, cmd_name);
1471 while ((cp = *args++)) {
1473 switch (smatch (++cp, packswit)) {
1475 ambigsw (cp, packswit);
1478 fprintf (stderr, "-%s unknown\n", cp);
1481 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1482 print_help (buf, packswit, 1);
1486 if (!(file = *args++) || *file == '-') {
1487 advise (NULL, "missing argument to %s", args[-2]);
1492 if (*cp == '+' || *cp == '@') {
1493 advise (NULL, "sorry, no folders allowed!");
1502 file = path (file, TFILE);
1503 if (stat (file, &st) == NOTOK) {
1504 if (errno != ENOENT) {
1505 advise (file, "error on file");
1508 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1515 msgs[msgp++] = "all";
1516 for (msgnum = 0; msgnum < msgp; msgnum++)
1517 if (!m_convert (mp, msgs[msgnum]))
1521 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1522 advise (file, "unable to open");
1525 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1526 if (is_selected (mp, msgnum))
1527 if (pack (file, md, msgnum) == NOTOK)
1529 mbx_close (file, md);
1531 if (mp->hghsel != mp->curmsg)
1532 seq_setcur (mp, mp->lowsel);
1540 pack (char *mailbox, int md, int msgnum)
1544 if (Msgs[msgnum].m_bboard_id == 0)
1547 zp = msh_ready (msgnum, 1);
1548 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1549 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1554 packhak (char **args)
1557 char *cp, *file = NULL;
1559 while ((cp = *args++)) {
1561 switch (smatch (++cp, packswit)) {
1568 if (!(file = *args++) || *file == '-')
1572 if (*cp == '+' || *cp == '@')
1576 file = path (file ? file : "./msgbox", TFILE);
1577 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1584 static struct swit pickswit[] = {
1596 { "cc pattern", 0 },
1598 { "date pattern", 0 },
1600 { "from pattern", 0 },
1602 { "search pattern", 0 },
1604 { "subject pattern", 0 },
1606 { "to pattern", 0 },
1608 { "-othercomponent pattern", 15 },
1610 { "after date", 0 },
1612 { "before date", 0 },
1614 { "datefield field", 5 },
1616 { "sequence name", 0 },
1636 pickcmd (char **args)
1638 int zerosw = 1, msgp = 0, seqp = 0;
1639 int vecp = 0, hi, lo, msgnum;
1640 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1641 char *seqs[NUMATTRS], *vec[MAXARGS];
1644 while ((cp = *args++)) {
1650 switch (smatch (cp, pickswit)) {
1652 ambigsw (cp, pickswit);
1655 fprintf (stderr, "-%s unknown\n", cp);
1658 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1659 print_help (buf, pickswit, 1);
1673 if (!(cp = *args++)) {/* allow -xyz arguments */
1674 advise (NULL, "missing argument to %s", args[-2]);
1680 advise (NULL, "internal error!");
1691 if (!(cp = *args++) || *cp == '-') {
1692 advise (NULL, "missing argument to %s", args[-2]);
1695 if (seqp < NUMATTRS)
1698 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1709 case PIPUSW: /* not implemented */
1716 if (*cp == '+' || *cp == '@') {
1717 advise (NULL, "sorry, no folders allowed!");
1726 msgs[msgp++] = "all";
1727 for (msgnum = 0; msgnum < msgp; msgnum++)
1728 if (!m_convert (mp, msgs[msgnum]))
1733 if (!pcompile (vec, NULL))
1739 for (msgnum = mp->lowsel;
1740 msgnum <= mp->hghsel && !interrupted;
1742 if (is_selected (mp, msgnum)) {
1743 zp = msh_ready (msgnum, 1);
1744 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1745 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1752 unset_selected (mp, msgnum);
1763 if (mp->numsel <= 0) {
1764 advise (NULL, "no messages match specification");
1769 for (seqp = 0; seqs[seqp]; seqp++)
1770 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1773 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1777 static struct swit replswit[] = {
1781 { "noannotate", 0 },
1787 { "draftfolder +folder", 0 },
1789 { "draftmessage msg", 0 },
1791 { "nodraftfolder", 0 },
1793 { "editor editor", 0 },
1797 { "fcc +folder", 0 },
1799 { "filter filterfile", 0 },
1801 { "form formfile", 0 },
1811 { "whatnowproc program", 0 },
1815 { "width columns", 0 },
1823 replcmd (char **args)
1826 char *cp, *msg = NULL;
1827 char buf[BUFSIZ], *vec[MAXARGS];
1830 forkcmd (args, cmd_name);
1834 while ((cp = *args++)) {
1836 switch (smatch (++cp, replswit)) {
1838 ambigsw (cp, replswit);
1841 fprintf (stderr, "-%s unknown\n", cp);
1844 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1845 print_help (buf, replswit, 1);
1848 case REANSW: /* not implemented */
1873 if (!(cp = *args++) || *cp == '-') {
1874 advise (NULL, "missing argument to %s", args[-2]);
1880 if (*cp == '+' || *cp == '@') {
1881 advise (NULL, "sorry, no folders allowed!");
1886 advise (NULL, "only one message at a time!");
1894 vec[vecp++] = "-file";
1898 if (!m_convert (mp, msg))
1902 if (mp->numsel > 1) {
1903 advise (NULL, "only one message at a time!");
1906 process (mp->hghsel, cmd_name, vecp, vec);
1907 seq_setcur (mp, mp->hghsel);
1911 static struct swit rmmswit[] = {
1919 rmmcmd (char **args)
1921 int msgp = 0, msgnum;
1922 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1924 while ((cp = *args++)) {
1926 switch (smatch (++cp, rmmswit)) {
1928 ambigsw (cp, rmmswit);
1931 fprintf (stderr, "-%s unknown\n", cp);
1934 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1935 print_help (buf, rmmswit, 1);
1938 if (*cp == '+' || *cp == '@') {
1939 advise (NULL, "sorry, no folders allowed!");
1947 msgs[msgp++] = "cur";
1948 for (msgnum = 0; msgnum < msgp; msgnum++)
1949 if (!m_convert (mp, msgs[msgnum]))
1960 register int msgnum, vecp;
1962 char buffer[BUFSIZ], *vec[MAXARGS];
1966 if (mp->numsel > MAXARGS - 1) {
1967 advise (NULL, "more than %d messages for %s exec",
1968 MAXARGS - 1, rmmproc);
1972 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1973 if (is_selected (mp, msgnum))
1974 vec[vecp++] = getcpy (m_name (msgnum));
1976 forkcmd (vec, rmmproc);
1977 for (vecp = 0; vec[vecp]; vecp++)
1981 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1982 if (is_selected (mp, msgnum)) {
1983 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1984 if (rename (cp, buffer) == NOTOK)
1985 admonish (buffer, "unable to rename %s to", cp);
1989 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1990 if (is_selected (mp, msgnum)) {
1991 set_deleted (mp, msgnum);
1992 unset_exists (mp, msgnum);
1995 if ((mp->nummsg -= mp->numsel) <= 0) {
1997 admonish (NULL, "no messages remaining in +%s", fmsh);
1999 admonish (NULL, "no messages remaining in %s", mp->foldpath);
2000 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2002 if (mp->lowsel == mp->lowmsg) {
2003 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2004 if (does_exist (mp, msgnum))
2006 mp->lowmsg = msgnum;
2008 if (mp->hghsel == mp->hghmsg) {
2009 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2010 if (does_exist (mp, msgnum))
2012 mp->hghmsg = msgnum;
2015 mp->msgflags |= MODIFIED;
2020 static struct swit scanswit[] = {
2026 { "form formatfile", 0 },
2028 { "format string", 5 },
2034 { "width columns", 0 },
2042 scancmd (char **args)
2044 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2046 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2047 int msgnum, optim, state;
2048 char *cp, *form = NULL, *format = NULL;
2049 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2051 static int s_optim = 0;
2052 static char *s_form = NULL, *s_format = NULL;
2054 while ((cp = *args++)) {
2056 switch (smatch (++cp, scanswit)) {
2058 ambigsw (cp, scanswit);
2061 fprintf (stderr, "-%s unknown\n", cp);
2064 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2065 print_help (buf, scanswit, 1);
2081 if (!(form = *args++) || *form == '-') {
2082 advise (NULL, "missing argument to %s", args[-2]);
2088 if (!(format = *args++) || *format == '-') {
2089 advise (NULL, "missing argument to %s", args[-2]);
2095 if (!(cp = *args++) || *cp == '-') {
2096 advise (NULL, "missing argument to %s", args[-2]);
2102 if (*cp == '+' || *cp == '@') {
2103 advise (NULL, "sorry, no folders allowed!");
2111 msgs[msgp++] = "all";
2112 for (msgnum = 0; msgnum < msgp; msgnum++)
2113 if (!m_convert (mp, msgs[msgnum]))
2117 /* Get new format string */
2118 nfs = new_fs (form, format, FORMAT);
2120 /* force scansbr to (re)compile format */
2127 s_optim = optim = 1;
2128 s_form = form ? getcpy (form) : NULL;
2129 s_format = format ? getcpy (format) : NULL;
2133 optim = equiv (s_form, form) && equiv (s_format, format);
2136 for (msgnum = mp->lowsel;
2137 msgnum <= mp->hghsel && !interrupted;
2139 if (is_selected (mp, msgnum)) {
2140 if (optim && Msgs[msgnum].m_scanl)
2141 printf ("%s", Msgs[msgnum].m_scanl);
2144 zp = msh_ready (msgnum, 0);
2145 switch (state = scan (zp, msgnum, 0, nfs, width,
2146 msgnum == mp->curmsg,
2147 is_unseen (mp, msgnum),
2148 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2149 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2155 Msgs[msgnum].m_scanl = getcpy (scanl);
2159 advise (NULL, "scan() botch (%d)", state);
2163 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2175 static struct swit showswit[] = {
2179 { "form formfile", 4 },
2181 { "moreproc program", 4 },
2183 { "nomoreproc", 3 },
2185 { "length lines", 4 },
2187 { "width columns", 4 },
2189 { "showproc program", 4 },
2191 { "noshowproc", 3 },
2203 showcmd (char **args)
2205 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2206 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2207 char *cp, *proc = showproc, buf[BUFSIZ];
2208 char *msgs[MAXARGS], *vec[MAXARGS];
2210 if (!mh_strcasecmp (cmd_name, "next"))
2213 if (!mh_strcasecmp (cmd_name, "prev"))
2215 while ((cp = *args++)) {
2217 switch (i = smatch (++cp, showswit)) {
2219 ambigsw (cp, showswit);
2226 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2227 cmd_name, mode ? NULL : "[msgs] ");
2228 print_help (buf, showswit, 1);
2236 if (!(cp = *args++) || *cp == '-') {
2237 advise (NULL, "missing argument to %s", args[-2]);
2249 if (!(proc = *args++) || *proc == '-') {
2250 advise (NULL, "missing argument to %s", args[-2]);
2260 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2263 if (*cp == '+' || *cp == '@') {
2264 advise (NULL, "sorry, no folders allowed!");
2270 "usage: %s [switches] [switches for showproc]\n",
2280 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2281 for (msgnum = 0; msgnum < msgp; msgnum++)
2282 if (!m_convert (mp, msgs[msgnum]))
2286 if (!nshow && !getenv ("NOMHNPROC"))
2287 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2288 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2289 proc = showmimeproc;
2290 vec[vecp++] = "-file";
2298 if (strcmp (showproc, "mhl") == 0) {
2304 seqnum = seq_getnum (mp, "unseen");
2305 vec[0] = r1bindex (proc, '/');
2308 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2309 if (is_selected (mp, msgnum)) {
2310 vec[vecp++] = getcpy (m_name (msgnum));
2312 seq_delmsg (mp, "unseen", msgnum);
2315 if (mp->numsel == 1 && headersw)
2317 mhlsbr (vecp, vec, mhl_action);
2318 m_eomsbr ((int (*)()) 0);
2323 for (msgnum = mp->lowsel;
2324 msgnum <= mp->hghsel && !interrupted;
2326 if (is_selected (mp, msgnum)) {
2327 switch (ask (msgnum)) {
2328 case NOTOK: /* QUIT */
2335 if (mp->numsel == 1 && headersw)
2338 copy_message (msgnum, stdout);
2340 process (msgnum, proc, vecp, vec);
2343 seq_delmsg (mp, "unseen", msgnum);
2350 seq_setcur (mp, mp->hghsel);
2357 if (Msgs[msgnum].m_bboard_id == 0)
2360 printf ("(Message %d", msgnum);
2361 if (Msgs[msgnum].m_bboard_id > 0)
2362 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2373 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2378 mhl_action (char *name)
2382 if ((msgnum = m_atoi (name)) < mp->lowmsg
2383 || msgnum > mp->hghmsg
2384 || !does_exist (mp, msgnum))
2388 mhlfp = msh_ready (msgnum, 1);
2390 m_eomsbr (eom_action);
2402 if (mp->numsel == 1 || !interactive || redirected)
2405 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2406 if (mp->lowsel != msgnum)
2408 printf ("Press <return> to list \"%d\"...", msgnum);
2413 read (fileno (stdout), buf, sizeof buf);
2415 if (strchr(buf, '\n') == NULL)
2419 told_to_quit = interrupted = 0;
2434 is_nontext (int msgnum)
2437 unsigned char *bp, *dp;
2439 char buf[BUFSIZ], name[NAMESZ];
2442 if (Msgs[msgnum].m_flags & MHNCHK)
2443 return (Msgs[msgnum].m_flags & MHNYES);
2444 Msgs[msgnum].m_flags |= MHNCHK;
2446 fp = msh_ready (msgnum, 1);
2449 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2454 * Check Content-Type field
2456 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2460 cp = add (buf, NULL);
2461 while (state == FLDPLUS) {
2462 state = m_getfld (state, name, buf, sizeof buf, fp);
2469 for (; isspace (*bp); bp++)
2474 for (bp++, i = 0;;) {
2504 for (dp = bp; istoken (*dp); dp++)
2511 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2514 for (dp++; isspace (*dp); dp++)
2517 if ((result = !uprf (dp, "charset")))
2519 dp += sizeof "charset" - 1;
2520 while (isspace (*dp))
2524 while (isspace (*dp))
2527 if ((bp = strchr(++dp, '"')))
2530 for (bp = dp; *bp; bp++)
2531 if (isspace (*bp)) {
2537 /* Default character set */
2540 /* Check the character set */
2541 result = !check_charset (dp, strlen (dp));
2543 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2553 Msgs[msgnum].m_flags |= MHNYES;
2560 * Check Content-Transfer-Encoding field
2562 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2563 cp = add (buf, NULL);
2564 while (state == FLDPLUS) {
2565 state = m_getfld (state, name, buf, sizeof buf, fp);
2568 for (bp = cp; isspace (*bp); bp++)
2570 for (dp = bp; istoken (*dp); dp++)
2573 result = (mh_strcasecmp (bp, "7bit")
2574 && mh_strcasecmp (bp, "8bit")
2575 && mh_strcasecmp (bp, "binary"));
2579 Msgs[msgnum].m_flags |= MHNYES;
2586 * Just skip the rest of this header
2587 * field and go to next one.
2589 while (state == FLDPLUS)
2590 state = m_getfld (state, name, buf, sizeof(buf), fp);
2594 * We've passed the message header,
2595 * so message is just text.
2603 static struct swit sortswit[] = {
2605 { "datefield field", 0 },
2607 { "textfield field", 0 },
2609 { "notextfield", 0 },
2611 { "limit days", 0 },
2625 sortcmd (char **args)
2627 int msgp = 0, msgnum;
2628 char *cp, *datesw = NULL, *subjsw = NULL;
2629 char buf[BUFSIZ], *msgs[MAXARGS];
2633 forkcmd (args, cmd_name);
2637 while ((cp = *args++)) {
2639 switch (smatch (++cp, sortswit)) {
2641 ambigsw (cp, sortswit);
2644 fprintf (stderr, "-%s unknown\n", cp);
2647 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2648 print_help (buf, sortswit, 1);
2653 advise (NULL, "only one date field at a time!");
2656 if (!(datesw = *args++) || *datesw == '-') {
2657 advise (NULL, "missing argument to %s", args[-2]);
2664 advise (NULL, "only one text field at a time!");
2667 if (!(subjsw = *args++) || *subjsw == '-') {
2668 advise (NULL, "missing argument to %s", args[-2]);
2676 case SOLIMT: /* too hard */
2677 if (!(cp = *args++) || *cp == '-') {
2678 advise (NULL, "missing argument to %s", args[-2]);
2682 case SOVERB: /* not implemented */
2686 if (*cp == '+' || *cp == '@') {
2687 advise (NULL, "sorry, no folders allowed!");
2695 msgs[msgp++] = "all";
2698 for (msgnum = 0; msgnum < msgp; msgnum++)
2699 if (!m_convert (mp, msgs[msgnum]))
2703 twscopy (&tb, dlocaltimenow ());
2705 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2706 if (Msgs[msgnum].m_scanl) {
2707 free (Msgs[msgnum].m_scanl);
2708 Msgs[msgnum].m_scanl = NULL;
2710 if (is_selected (mp, msgnum)) {
2711 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2712 twscopy (&Msgs[msgnum].m_tb,
2713 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2715 else /* m_scaln is already NULL */
2716 twscopy (&Msgs[msgnum].m_tb, &tb);
2717 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2718 if (mp->curmsg == msgnum)
2719 Msgs[msgnum].m_stats |= CUR;
2722 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2723 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2725 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2726 if (subjsw && Msgs[msgnum].m_scanl) {
2727 free (Msgs[msgnum].m_scanl); /* from subjsort */
2728 Msgs[msgnum].m_scanl = NULL;
2730 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2731 if (Msgs[msgnum].m_stats & CUR)
2732 seq_setcur (mp, msgnum);
2735 mp->msgflags |= MODIFIED;
2741 * get_fields - parse message, and get date and subject if needed.
2742 * We'll use the msgp->m_tb tws struct for the date, and overload
2743 * the msgp->m_scanl field with our subject string.
2746 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2748 int state, gotdate = 0;
2749 char *bp, buf[BUFSIZ], name[NAMESZ];
2750 struct tws *tw = (struct tws *) 0;
2753 zp = msh_ready (msgnum, 0);
2754 for (state = FLD;;) {
2755 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2759 if (!mh_strcasecmp (name, datesw)) {
2761 while (state == FLDPLUS) {
2762 state = m_getfld (state, name, buf, sizeof buf, zp);
2765 if ((tw = dparsetime (bp)) == NULL)
2767 "unable to parse %s field in message %d",
2770 twscopy (&(msgp->m_tb), tw);
2772 if (!subjsw) /* not using this, or already done */
2773 break; /* all done! */
2776 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2778 while (state == FLDPLUS) {
2779 state = m_getfld (state, name, buf, sizeof buf, zp);
2782 msgp->m_scanl = sosmash(subjsw, bp);
2784 break; /* date done so we're done */
2786 subjsw = (char *)0;/* subject done, need date */
2788 while (state == FLDPLUS) /* flush this one */
2789 state = m_getfld (state, name, buf, sizeof buf, zp);
2800 admonish (NULL, "format error in message %d", msgnum);
2801 if (msgp->m_scanl) { /* this might need free'd */
2802 free (msgp->m_scanl); /* probably can't use subj anyway */
2803 msgp->m_scanl = NULL;
2808 adios (NULL, "internal error -- you lose");
2813 return OK; /* not an error if subj not found */
2815 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2816 return NOTOK; /* NOTOK means use some other date */
2825 msgsort (struct Msg *a, struct Msg *b)
2827 return twsort (&a->m_tb, &b->m_tb);
2832 subsort (struct Msg *a, struct Msg *b)
2836 if (a->m_scanl && b->m_scanl)
2837 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2840 return twsort (&a->m_tb, &b->m_tb);
2845 * try to make the subject "canonical": delete leading "re:", everything
2846 * but letters & smash letters to lower case.
2849 sosmash (char *subj, char *s)
2851 register char *cp, *dp;
2852 register unsigned char c;
2856 dp = s; /* dst pointer */
2857 if (!mh_strcasecmp (subj, "subject"))
2864 *dp++ = isupper(c) ? tolower(c) : c;
2870 while ((c = *cp++)) {
2872 *dp++ = isupper(c) ? tolower(c) : c;
2882 process (int msgnum, char *proc, int vecp, char **vec)
2884 int child_id, status;
2885 char tmpfil[BUFSIZ];
2890 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2891 context_del (pfolder);
2892 context_replace (pfolder, fmsh);/* update current folder */
2894 context_save (); /* save the context file */
2898 cp = m_mktemp(invo_name, NULL, &out);
2900 /* Try again, but try to create under /tmp */
2902 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2905 advise (NULL, "unable to create temporary file");
2909 copy_message (msgnum, out);
2911 strncpy(tmpfil, cp, sizeof(tmpfil));
2915 switch (child_id = fork ()) {
2917 advise ("fork", "unable to");
2923 SIGNAL (SIGINT, istat);
2924 SIGNAL (SIGQUIT, qstat);
2926 vec[vecp++] = tmpfil;
2930 fprintf (stderr, "unable to exec ");
2935 status = pidXwait (child_id, NULL);
2946 copy_message (int msgnum, FILE *out)
2949 static char buffer[BUFSIZ];
2952 zp = msh_ready (msgnum, 1);
2954 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2955 fputs (buffer, out);
2956 if (interrupted && out == stdout)
2962 while (fgets (buffer, sizeof buffer, zp) != NULL
2963 && pos < Msgs[msgnum].m_stop) {
2964 fputs (buffer, out);
2965 pos += (long) strlen (buffer);
2966 if (interrupted && out == stdout)
2974 copy_digest (int msgnum, FILE *out)
2978 static char buffer[BUFSIZ];
2982 zp = msh_ready (msgnum, 1);
2985 while (fgets (buffer, sizeof buffer, zp) != NULL
2986 && !fmsh && pos < Msgs[msgnum].m_stop) {
2987 if (c == '\n' && *buffer == '-')
2989 fputs (buffer, out);
2990 c = buffer[strlen (buffer) - 1];
2992 pos += (long) strlen (buffer);
2993 if (interrupted && out == stdout)