3 * mshcmds.c -- command handlers in msh
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
11 #include <h/signals.h>
12 #include <h/dropsbr.h>
13 #include <h/fmt_scan.h>
14 #include <h/scansbr.h>
20 #include <h/picksbr.h>
24 static char delim3[] = "-------"; /* from burst.c */
30 * Type for a compare function for qsort. This keeps
33 typedef int (*qsort_comp) (const void *, const void *);
38 static int burst (struct Msg *, int, int, int, int);
39 static void forw (char *, char *, int, char **);
40 static void rmm (void);
41 static void show (int);
42 static int eom_action (int);
43 static FILE *mhl_action (char *);
45 static int is_nontext (int);
46 static int get_fields (char *, char *, int, struct Msg *);
47 static int msgsort (struct Msg *, struct Msg *);
48 static int subsort (struct Msg *, struct Msg *);
49 static char *sosmash (char *, char *);
50 static int process (int, char *, int, char **);
51 static void copy_message (int, FILE *);
52 static void copy_digest (int, FILE *);
55 forkcmd (char **args, char *pgm)
60 vec[0] = r1bindex (pgm, '/');
61 copyip (args, vec + 1, MAXARGS - 1);
64 context_del (pfolder);
65 context_replace (pfolder, fmsh);/* update current folder */
67 context_save (); /* save the context file */
70 switch (child_id = fork ()) {
72 advise ("fork", "unable to");
77 SIGNAL (SIGINT, istat);
78 SIGNAL (SIGQUIT, qstat);
81 fprintf (stderr, "unable to exec ");
86 pidXwait (child_id, NULL);
89 if (fmsh) { /* assume the worst case */
90 mp->msgflags |= MODIFIED;
96 static struct swit distswit[] = {
102 { "draftfolder +folder", 0 },
104 { "draftmessage msg", 0 },
106 { "nodraftfolder", 0 },
108 { "editor editor", 0 },
112 { "form formfile", 0 },
118 { "whatnowproc program", 0 },
120 { "nowhatnowproc", 0 },
128 distcmd (char **args)
131 char *cp, *msg = NULL;
132 char buf[BUFSIZ], *vec[MAXARGS];
135 forkcmd (args, cmd_name);
139 while ((cp = *args++)) {
141 switch (smatch (++cp, distswit)) {
143 ambigsw (cp, distswit);
146 fprintf (stderr, "-%s unknown\n", cp);
149 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
150 print_help (buf, distswit, 1);
153 case DIANSW: /* not implemented */
171 if (!(cp = *args++) || *cp == '-') {
172 advise (NULL, "missing argument to %s", args[-2]);
178 if (*cp == '+' || *cp == '@') {
179 advise (NULL, "sorry, no folders allowed!");
184 advise (NULL, "only one message at a time!");
192 vec[vecp++] = "-file";
196 if (!m_convert (mp, msg))
200 if (mp->numsel > 1) {
201 advise (NULL, "only one message at a time!");
204 process (mp->hghsel, cmd_name, vecp, vec);
205 seq_setcur (mp, mp->hghsel);
209 static struct swit explswit[] = {
229 explcmd (char **args)
231 int inplace = 0, quietsw = 0, verbosw = 0;
232 int msgp = 0, hi, msgnum;
233 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
237 forkcmd (args, cmd_name);
241 while ((cp = *args++)) {
243 switch (smatch (++cp, explswit)) {
245 ambigsw (cp, explswit);
248 fprintf (stderr, "-%s unknown\n", cp);
251 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
252 print_help (buf, explswit, 1);
274 if (*cp == '+' || *cp == '@') {
275 advise (NULL, "sorry, no folders allowed!");
283 msgs[msgp++] = "cur";
284 for (msgnum = 0; msgnum < msgp; msgnum++)
285 if (!m_convert (mp, msgs[msgnum]))
289 smsgs = (struct Msg *)
290 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
292 adios (NULL, "unable to allocate folder storage");
296 for (msgnum = mp->lowsel;
297 msgnum <= mp->hghsel && !interrupted;
299 if (is_selected (mp, msgnum))
300 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
303 free ((char *) smsgs);
306 seq_setcur (mp, mp->lowsel);
308 if (hi <= mp->hghmsg)
311 mp->msgflags |= MODIFIED;
317 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
319 int i, j, ld3, wasdlm, msgp;
321 char c, buffer[BUFSIZ];
324 ld3 = strlen (delim3);
326 if (Msgs[msgnum].m_scanl) {
327 free (Msgs[msgnum].m_scanl);
328 Msgs[msgnum].m_scanl = NULL;
331 pos = ftell (zp = msh_ready (msgnum, 1));
332 for (msgp = 0; msgp <= MAXFOLDER;) {
333 while (fgets (buffer, sizeof buffer, zp) != NULL
335 && pos < Msgs[msgnum].m_stop)
336 pos += (long) strlen (buffer);
337 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
339 fseek (zp, pos, SEEK_SET);
340 smsgs[msgp].m_start = pos;
343 pos < Msgs[msgnum].m_stop
344 && fgets (buffer, sizeof buffer, zp) != NULL;
346 if (strncmp (buffer, delim3, ld3) == 0
347 && (msgp == 1 || c == '\n')
348 && peekc (zp) == '\n')
351 pos += (long) strlen (buffer);
353 wasdlm = strncmp (buffer, delim3, ld3) == 0;
354 if (smsgs[msgp].m_start != pos)
355 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
356 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
358 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
361 pos += (long) strlen (buffer);
364 switch (msgp--) { /* toss "End of XXX Digest" */
366 adios (NULL, "burst() botch -- you lose big");
370 printf ("message %d not in digest format\n", msgnum);
375 printf ("%d message%s exploded from digest %d\n",
376 msgp, msgp != 1 ? "s" : "", msgnum);
380 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
381 advise (NULL, "more than %d messages", MAXFOLDER);
384 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
385 adios (NULL, "unable to allocate folder storage");
390 if (mp->hghsel > msgnum)
394 for (i = mp->hghmsg; j > msgnum; i--, j--) {
396 printf ("message %d becomes message %d\n", j, i);
398 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
399 Msgs[i].m_top = Msgs[j].m_top;
400 Msgs[i].m_start = Msgs[j].m_start;
401 Msgs[i].m_stop = Msgs[j].m_stop;
402 Msgs[i].m_scanl = NULL;
403 if (Msgs[j].m_scanl) {
404 free (Msgs[j].m_scanl);
405 Msgs[j].m_scanl = NULL;
407 copy_msg_flags (mp, i, j);
410 if (Msgs[msgnum].m_bboard_id == 0)
413 unset_selected (mp, msgnum);
414 i = inplace ? msgnum + msgp : mp->hghmsg;
415 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
416 if (verbosw && i != msgnum)
417 printf ("message %d of digest %d becomes message %d\n",
420 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
421 Msgs[i].m_top = Msgs[j].m_top;
422 Msgs[i].m_start = smsgs[j].m_start;
423 Msgs[i].m_stop = smsgs[j].m_stop;
424 Msgs[i].m_scanl = NULL;
425 copy_msg_flags (mp, i, msgnum);
432 static struct swit fileswit[] = {
444 { "src +folder", 0 },
448 { "rmmproc program", 0 },
458 filecmd (char **args)
460 int linksw = 0, msgp = 0;
461 int vecp = 1, i, msgnum;
462 char *cp, buf[BUFSIZ];
463 char *msgs[MAXARGS], *vec[MAXARGS];
466 forkcmd (args, cmd_name);
470 while ((cp = *args++)) {
472 switch (i = smatch (++cp, fileswit)) {
474 ambigsw (cp, fileswit);
477 fprintf (stderr, "-%s unknown\n", cp);
480 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
481 print_help (buf, fileswit, 1);
500 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
503 if (*cp == '+' || *cp == '@')
510 vec[vecp++] = "-file";
513 msgs[msgp++] = "cur";
514 for (msgnum = 0; msgnum < msgp; msgnum++)
515 if (!m_convert (mp, msgs[msgnum]))
520 for (msgnum = mp->lowsel;
521 msgnum <= mp->hghsel && !interrupted;
523 if (is_selected (mp, msgnum))
524 if (process (msgnum, fileproc, vecp, vec)) {
525 unset_selected (mp, msgnum);
529 if (mp->numsel != mp->nummsg || linksw)
530 seq_setcur (mp, mp->hghsel);
537 filehak (char **args)
539 int result, vecp = 0;
540 char *cp, *cwd, *vec[MAXARGS];
542 while ((cp = *args++)) {
544 switch (smatch (++cp, fileswit)) {
561 if (*cp == '+' || *cp == '@')
568 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
570 cwd = getcpy (pwd ());
571 chdir (m_maildir (""));
573 if (access (m_maildir (cp), F_OK) == NOTOK)
584 static struct swit foldswit[] = {
622 foldcmd (char **args)
624 int fastsw = 0, headersw = 0, packsw = 0;
626 char *cp, *folder = NULL, *msg = NULL;
627 char buf[BUFSIZ], **vec = args;
632 while ((cp = *args++)) {
634 switch (smatch (++cp, foldswit)) {
636 ambigsw (cp, foldswit);
639 fprintf (stderr, "-%s unknown\n", cp);
642 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
643 print_help (buf, foldswit, 1);
646 case FLALSW: /* not implemented */
676 if (*cp == '+' || *cp == '@') {
678 advise (NULL, "only one folder at a time!\n");
682 folder = fmsh ? pluspath (cp)
687 advise (NULL, "only one message at a time!\n");
696 advise (NULL, "null folder names are not permitted");
700 if (access (m_maildir (folder), R_OK) == NOTOK) {
701 advise (folder, "unable to read");
706 strncpy (buf, folder, sizeof(buf));
707 if (expand (buf) == NOTOK)
710 if (access (folder, R_OK) == NOTOK) {
711 advise (folder, "unable to read");
726 if (!m_convert (mp, msg))
730 if (mp->numsel > 1) {
731 advise (NULL, "only one message at a time!");
734 seq_setcur (mp, mp->hghsel);
739 forkcmd (vec, cmd_name);
743 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
744 adios (NULL, "unable to allocate folder storage");
746 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
747 if (does_exist (mp, msgnum)) {
748 if (msgnum != hole) {
749 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
750 Msgs[hole].m_top = Msgs[msgnum].m_top;
751 Msgs[hole].m_start = Msgs[msgnum].m_start;
752 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
753 Msgs[hole].m_scanl = NULL;
754 if (Msgs[msgnum].m_scanl) {
755 free (Msgs[msgnum].m_scanl);
756 Msgs[msgnum].m_scanl = NULL;
758 copy_msg_flags (mp, hole, msgnum);
759 if (mp->curmsg == msgnum)
760 seq_setcur (mp, hole);
764 if (mp->nummsg > 0) {
766 mp->hghmsg = hole - 1;
768 mp->msgflags |= MODIFIED;
774 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
777 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
778 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
780 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
782 /* check for empty folder */
783 if (mp->nummsg == 0) {
784 printf ("has no messages%*s",
785 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
787 printf ("has %*d message%s (%*d-%*d)",
788 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
789 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
790 if (mp->curmsg >= mp->lowmsg
791 && mp->curmsg <= mp->hghmsg)
792 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
799 static struct swit forwswit[] = {
805 { "draftfolder +folder", 0 },
807 { "draftmessage msg", 0 },
809 { "nodraftfolder", 0 },
811 { "editor editor", 0 },
815 { "filter filterfile", 0 },
817 { "form formfile", 0 },
831 { "whatnowproc program", 0 },
841 forwcmd (char **args)
843 int msgp = 0, vecp = 1, msgnum;
844 char *cp, *filter = NULL, buf[BUFSIZ];
845 char *msgs[MAXARGS], *vec[MAXARGS];
850 forkcmd (args, cmd_name);
854 while ((cp = *args++)) {
856 switch (smatch (++cp, forwswit)) {
858 ambigsw (cp, forwswit);
861 fprintf (stderr, "-%s unknown\n", cp);
864 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
865 print_help (buf, forwswit, 1);
868 case FOANSW: /* not implemented */
888 if (!(cp = *args++) || *cp == '-') {
889 advise (NULL, "missing argument to %s", args[-2]);
895 if (!(filter = *args++) || *filter == '-') {
896 advise (NULL, "missing argument to %s", args[-2]);
901 if (access (filter = myfilter, R_OK) == NOTOK) {
902 advise (filter, "unable to read default filter file");
910 if (*cp == '+' || *cp == '@') {
911 advise (NULL, "sorry, no folders allowed!");
918 /* foil search of .mh_profile */
919 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
921 tfile = m_mktemp(buf, NULL, NULL);
922 if (tfile == NULL) adios("forwcmd", "unable to create temporary file");
923 strncpy (tmpfil, tfile, sizeof(tmpfil));
926 vec[vecp++] = "-file";
929 msgs[msgp++] = "cur";
930 for (msgnum = 0; msgnum < msgp; msgnum++)
931 if (!m_convert (mp, msgs[msgnum]))
936 strncpy (buf, filter, sizeof(buf));
937 if (expand (buf) == NOTOK)
939 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
940 advise (filter, "unable to read");
945 forw (cmd_name, filter, vecp, vec);
946 seq_setcur (mp, mp->hghsel);
953 forw (char *proc, char *filter, int vecp, char **vec)
955 int i, child_id, msgnum, msgcnt;
956 char tmpfil[BUFSIZ], *args[MAXARGS];
960 tfile = m_mktemp2(NULL, invo_name, NULL, NULL);
961 if (tfile == NULL) adios("forw", "unable to create temporary file");
962 strncpy (tmpfil, tfile, sizeof(tmpfil));
966 switch (child_id = fork ()) {
968 advise ("fork", "unable to");
971 case OK: /* "trust me" */
972 if (freopen (tmpfil, "w", stdout) == NULL) {
973 fprintf (stderr, "unable to create ");
977 args[0] = r1bindex (mhlproc, '/');
979 args[i++] = "-forwall";
982 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
983 if (is_selected (mp, msgnum))
984 args[i++] = getcpy (m_name (msgnum));
986 mhlsbr (i, args, mhl_action);
987 m_eomsbr ((int (*) ()) 0);
992 if (pidXwait (child_id, NULL))
997 if ((out = fopen (tmpfil, "w")) == NULL) {
998 advise (tmpfil, "unable to create temporary file");
1003 for (msgnum = mp->lowsel;
1004 msgnum <= mp->hghsel && !interrupted;
1006 if (is_selected (mp, msgnum)) {
1007 fprintf (out, "\n\n-------");
1008 if (msgnum == mp->lowsel)
1009 fprintf (out, " Forwarded Message%s",
1010 mp->numsel > 1 ? "s" : "");
1012 fprintf (out, " Message %d", msgcnt);
1013 fprintf (out, "\n\n");
1014 copy_digest (msgnum, out);
1018 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1019 mp->numsel > 1 ? "s" : "");
1025 switch (child_id = fork ()) {
1027 advise ("fork", "unable to");
1032 SIGNAL (SIGINT, istat);
1033 SIGNAL (SIGQUIT, qstat);
1035 vec[vecp++] = tmpfil;
1039 fprintf (stderr, "unable to exec ");
1044 pidXwait (child_id, NULL);
1052 static char *hlpmsg[] = {
1053 "The %s program emulates many of the commands found in the nmh",
1054 "system. Instead of operating on nmh folders, commands to %s concern",
1057 "To see the list of commands available, just type a ``?'' followed by",
1058 "the RETURN key. To find out what switches each command takes, type",
1059 "the name of the command followed by ``-help''. To leave %s, use the",
1060 "``quit'' command.",
1062 "Although a lot of nmh commands are found in %s, not all are fully",
1063 "implemented. %s will always recognize all legal switches for a",
1064 "given command though, and will let you know when you ask for an",
1065 "option that it is unable to perform.",
1067 "Running %s is fun, but using nmh from your shell is far superior.",
1068 "After you have familiarized yourself with the nmh style by using %s,",
1069 "you should try using nmh from the shell. You can still use %s for",
1070 "message files that aren't in nmh format, such as BBoard files.",
1076 helpcmd (char **args)
1081 for (i = 0; hlpmsg[i]; i++) {
1082 printf (hlpmsg[i], invo_name);
1088 static struct swit markswit[] = {
1096 { "sequence name", 0 },
1114 markcmd (char **args)
1116 int addsw = 0, deletesw = 0, debugsw = 0;
1117 int listsw = 0, zerosw = 0;
1119 int msgp = 0, msgnum;
1120 char *cp, buf[BUFSIZ];
1121 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1123 while ((cp = *args++)) {
1125 switch (smatch (++cp, markswit)) {
1127 ambigsw (cp, markswit);
1130 fprintf (stderr, "-%s unknown\n", cp);
1133 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1134 print_help (buf, markswit, 1);
1139 deletesw = listsw = 0;
1147 addsw = deletesw = 0;
1151 if (!(cp = *args++) || *cp == '-') {
1152 advise (NULL, "missing argument to %s", args[-2]);
1155 if (seqp < NUMATTRS)
1158 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1163 case MPUBSW: /* not implemented */
1179 if (*cp == '+' || *cp == '@') {
1180 advise (NULL, "sorry, no folders allowed!");
1187 if (!addsw && !deletesw && !listsw) {
1194 seqs[seqp++] = "unseen";
1198 msgs[msgp++] = "all";
1203 msgs[msgp++] = listsw ? "all" :"cur";
1204 for (msgnum = 0; msgnum < msgp; msgnum++)
1205 if (!m_convert (mp, msgs[msgnum]))
1209 printf ("invo_name=%s mypath=%s defpath=%s\n",
1210 invo_name, mypath, defpath);
1211 printf ("ctxpath=%s context flags=%s\n",
1212 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1213 printf ("foldpath=%s flags=%s\n",
1215 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1216 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1217 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1218 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1219 mp->lowsel, mp->hghsel, mp->numsel);
1220 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1223 if (seqp == 0 && (addsw || deletesw)) {
1224 advise (NULL, "-%s requires at least one -sequence argument",
1225 addsw ? "add" : "delete");
1231 for (seqp = 0; seqs[seqp]; seqp++)
1232 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1237 for (seqp = 0; seqs[seqp]; seqp++)
1238 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1242 /* Listing messages in sequences */
1245 /* list the given sequences */
1246 for (seqp = 0; seqs[seqp]; seqp++)
1247 seq_print (mp, seqs[seqp]);
1249 /* else list them all */
1255 for (msgnum = mp->lowsel;
1256 msgnum <= mp->hghsel && !interrupted;
1258 if (is_selected (mp, msgnum)) {
1259 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1262 Msgs[msgnum].m_bboard_id,
1264 (long) Msgs[msgnum].m_start,
1265 (long) Msgs[msgnum].m_stop,
1266 snprintb (buf, sizeof(buf),
1267 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1269 if (Msgs[msgnum].m_scanl)
1270 printf ("%s", Msgs[msgnum].m_scanl);
1276 static struct swit mhnswit[] = {
1279 #define MHNNAUTOSW 1
1281 #define MHNDEBUGSW 2
1283 #define MHNEBCDICSW 3
1284 { "ebcdicsafe", 0 },
1285 #define MHNNEBCDICSW 4
1286 { "noebcdicsafe", 0 },
1288 { "form formfile", 4 },
1291 #define MHNNHEADSW 7
1295 #define MHNNLISTSW 9
1297 #define MHNPARTSW 10
1298 { "part number", 0 },
1299 #define MHNSIZESW 11
1301 #define MHNNSIZESW 12
1302 { "norealsize", 0 },
1303 #define MHNRFC934SW 13
1304 { "rfc934mode", 0 },
1305 #define MHNNRFC934SW 14
1306 { "norfc934mode", 0 },
1307 #define MHNSERIALSW 15
1308 { "serialonly", 0 },
1309 #define MHNNSERIALSW 16
1310 { "noserialonly", 0 },
1311 #define MHNSHOWSW 17
1313 #define MHNNSHOWSW 18
1315 #define MHNSTORESW 19
1317 #define MHNNSTORESW 20
1319 #define MHNTYPESW 21
1320 { "type content", 0 },
1321 #define MHNVERBSW 22
1323 #define MHNNVERBSW 23
1325 #define MHNHELPSW 24
1327 #define MHNPROGSW 25
1328 { "moreproc program", -4 },
1329 #define MHNNPROGSW 26
1330 { "nomoreproc", -3 },
1332 { "length lines", -4 },
1334 { "width columns", -4 },
1340 mhncmd (char **args)
1342 int msgp = 0, vecp = 1;
1344 char *cp, buf[BUFSIZ];
1345 char *msgs[MAXARGS], *vec[MAXARGS];
1348 forkcmd (args, cmd_name);
1351 while ((cp = *args++)) {
1353 switch (smatch (++cp, mhnswit)) {
1355 ambigsw (cp, mhnswit);
1358 fprintf (stderr, "-%s unknown\n", cp);
1361 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1362 print_help (buf, mhnswit, 1);
1397 if (!(cp = *args++) || *cp == '-') {
1398 advise (NULL, "missing argument to %s", args[-2]);
1405 if (*cp == '+' || *cp == '@') {
1406 advise (NULL, "sorry, no folders allowed!");
1414 vec[vecp++] = "-file";
1417 msgs[msgp++] = "cur";
1418 for (msgnum = 0; msgnum < msgp; msgnum++)
1419 if (!m_convert (mp, msgs[msgnum]))
1424 for (msgnum = mp->lowsel;
1425 msgnum <= mp->hghsel && !interrupted;
1427 if (is_selected (mp, msgnum))
1428 if (process (msgnum, cmd_name, vecp, vec)) {
1429 unset_selected (mp, msgnum);
1433 seq_setcur (mp, mp->hghsel);
1437 static struct swit packswit[] = {
1445 static int mbx_style = MMDF_FORMAT;
1448 packcmd (char **args)
1450 int msgp = 0, md, msgnum;
1451 char *cp, *file = NULL;
1452 char buf[BUFSIZ], *msgs[MAXARGS];
1456 forkcmd (args, cmd_name);
1460 while ((cp = *args++)) {
1462 switch (smatch (++cp, packswit)) {
1464 ambigsw (cp, packswit);
1467 fprintf (stderr, "-%s unknown\n", cp);
1470 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1471 print_help (buf, packswit, 1);
1475 if (!(file = *args++) || *file == '-') {
1476 advise (NULL, "missing argument to %s", args[-2]);
1481 if (*cp == '+' || *cp == '@') {
1482 advise (NULL, "sorry, no folders allowed!");
1491 file = path (file, TFILE);
1492 if (stat (file, &st) == NOTOK) {
1493 if (errno != ENOENT) {
1494 advise (file, "error on file");
1497 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1504 msgs[msgp++] = "all";
1505 for (msgnum = 0; msgnum < msgp; msgnum++)
1506 if (!m_convert (mp, msgs[msgnum]))
1510 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1511 advise (file, "unable to open");
1514 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1515 if (is_selected (mp, msgnum))
1516 if (pack (file, md, msgnum) == NOTOK)
1518 mbx_close (file, md);
1520 if (mp->hghsel != mp->curmsg)
1521 seq_setcur (mp, mp->lowsel);
1529 pack (char *mailbox, int md, int msgnum)
1533 if (Msgs[msgnum].m_bboard_id == 0)
1536 zp = msh_ready (msgnum, 1);
1537 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1538 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1543 packhak (char **args)
1546 char *cp, *file = NULL;
1548 while ((cp = *args++)) {
1550 switch (smatch (++cp, packswit)) {
1557 if (!(file = *args++) || *file == '-')
1561 if (*cp == '+' || *cp == '@')
1565 file = path (file ? file : "./msgbox", TFILE);
1566 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1573 static struct swit pickswit[] = {
1585 { "cc pattern", 0 },
1587 { "date pattern", 0 },
1589 { "from pattern", 0 },
1591 { "search pattern", 0 },
1593 { "subject pattern", 0 },
1595 { "to pattern", 0 },
1597 { "-othercomponent pattern", 15 },
1599 { "after date", 0 },
1601 { "before date", 0 },
1603 { "datefield field", 5 },
1605 { "sequence name", 0 },
1625 pickcmd (char **args)
1627 int zerosw = 1, msgp = 0;
1629 int vecp = 0, hi, lo, msgnum;
1630 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1631 char *seqs[NUMATTRS], *vec[MAXARGS];
1634 while ((cp = *args++)) {
1640 switch (smatch (cp, pickswit)) {
1642 ambigsw (cp, pickswit);
1645 fprintf (stderr, "-%s unknown\n", cp);
1648 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1649 print_help (buf, pickswit, 1);
1663 if (!(cp = *args++)) {/* allow -xyz arguments */
1664 advise (NULL, "missing argument to %s", args[-2]);
1670 advise (NULL, "internal error!");
1681 if (!(cp = *args++) || *cp == '-') {
1682 advise (NULL, "missing argument to %s", args[-2]);
1685 if (seqp < NUMATTRS)
1688 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1699 case PIPUSW: /* not implemented */
1706 if (*cp == '+' || *cp == '@') {
1707 advise (NULL, "sorry, no folders allowed!");
1716 msgs[msgp++] = "all";
1717 for (msgnum = 0; msgnum < msgp; msgnum++)
1718 if (!m_convert (mp, msgs[msgnum]))
1723 if (!pcompile (vec, NULL))
1729 for (msgnum = mp->lowsel;
1730 msgnum <= mp->hghsel && !interrupted;
1732 if (is_selected (mp, msgnum)) {
1733 zp = msh_ready (msgnum, 1);
1734 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1735 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1742 unset_selected (mp, msgnum);
1753 if (mp->numsel <= 0) {
1754 advise (NULL, "no messages match specification");
1759 for (seqp = 0; seqs[seqp]; seqp++)
1760 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1763 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1767 static struct swit replswit[] = {
1771 { "noannotate", 0 },
1777 { "draftfolder +folder", 0 },
1779 { "draftmessage msg", 0 },
1781 { "nodraftfolder", 0 },
1783 { "editor editor", 0 },
1787 { "fcc +folder", 0 },
1789 { "filter filterfile", 0 },
1791 { "form formfile", 0 },
1801 { "whatnowproc program", 0 },
1805 { "width columns", 0 },
1813 replcmd (char **args)
1816 char *cp, *msg = NULL;
1817 char buf[BUFSIZ], *vec[MAXARGS];
1820 forkcmd (args, cmd_name);
1824 while ((cp = *args++)) {
1826 switch (smatch (++cp, replswit)) {
1828 ambigsw (cp, replswit);
1831 fprintf (stderr, "-%s unknown\n", cp);
1834 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1835 print_help (buf, replswit, 1);
1838 case REANSW: /* not implemented */
1863 if (!(cp = *args++) || *cp == '-') {
1864 advise (NULL, "missing argument to %s", args[-2]);
1870 if (*cp == '+' || *cp == '@') {
1871 advise (NULL, "sorry, no folders allowed!");
1876 advise (NULL, "only one message at a time!");
1884 vec[vecp++] = "-file";
1888 if (!m_convert (mp, msg))
1892 if (mp->numsel > 1) {
1893 advise (NULL, "only one message at a time!");
1896 process (mp->hghsel, cmd_name, vecp, vec);
1897 seq_setcur (mp, mp->hghsel);
1901 static struct swit rmmswit[] = {
1909 rmmcmd (char **args)
1911 int msgp = 0, msgnum;
1912 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1914 while ((cp = *args++)) {
1916 switch (smatch (++cp, rmmswit)) {
1918 ambigsw (cp, rmmswit);
1921 fprintf (stderr, "-%s unknown\n", cp);
1924 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1925 print_help (buf, rmmswit, 1);
1928 if (*cp == '+' || *cp == '@') {
1929 advise (NULL, "sorry, no folders allowed!");
1937 msgs[msgp++] = "cur";
1938 for (msgnum = 0; msgnum < msgp; msgnum++)
1939 if (!m_convert (mp, msgs[msgnum]))
1950 register int msgnum, vecp;
1952 char buffer[BUFSIZ], *vec[MAXARGS];
1956 if (mp->numsel > MAXARGS - 1) {
1957 advise (NULL, "more than %d messages for %s exec",
1958 MAXARGS - 1, rmmproc);
1962 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1963 if (is_selected (mp, msgnum))
1964 vec[vecp++] = getcpy (m_name (msgnum));
1966 forkcmd (vec, rmmproc);
1967 for (vecp = 0; vec[vecp]; vecp++)
1971 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1972 if (is_selected (mp, msgnum)) {
1973 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1974 if (rename (cp, buffer) == NOTOK)
1975 admonish (buffer, "unable to rename %s to", cp);
1979 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1980 if (is_selected (mp, msgnum)) {
1981 set_deleted (mp, msgnum);
1982 unset_exists (mp, msgnum);
1985 if ((mp->nummsg -= mp->numsel) <= 0) {
1987 admonish (NULL, "no messages remaining in +%s", fmsh);
1989 admonish (NULL, "no messages remaining in %s", mp->foldpath);
1990 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
1992 if (mp->lowsel == mp->lowmsg) {
1993 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
1994 if (does_exist (mp, msgnum))
1996 mp->lowmsg = msgnum;
1998 if (mp->hghsel == mp->hghmsg) {
1999 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2000 if (does_exist (mp, msgnum))
2002 mp->hghmsg = msgnum;
2005 mp->msgflags |= MODIFIED;
2010 static struct swit scanswit[] = {
2016 { "form formatfile", 0 },
2018 { "format string", 5 },
2024 { "width columns", 0 },
2032 scancmd (char **args)
2034 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2036 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2037 int msgnum, optim, state;
2038 char *cp, *form = NULL, *format = NULL;
2039 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2041 static int s_optim = 0;
2042 static char *s_form = NULL, *s_format = NULL;
2044 while ((cp = *args++)) {
2046 switch (smatch (++cp, scanswit)) {
2048 ambigsw (cp, scanswit);
2051 fprintf (stderr, "-%s unknown\n", cp);
2054 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2055 print_help (buf, scanswit, 1);
2071 if (!(form = *args++) || *form == '-') {
2072 advise (NULL, "missing argument to %s", args[-2]);
2078 if (!(format = *args++) || *format == '-') {
2079 advise (NULL, "missing argument to %s", args[-2]);
2085 if (!(cp = *args++) || *cp == '-') {
2086 advise (NULL, "missing argument to %s", args[-2]);
2092 if (*cp == '+' || *cp == '@') {
2093 advise (NULL, "sorry, no folders allowed!");
2101 msgs[msgp++] = "all";
2102 for (msgnum = 0; msgnum < msgp; msgnum++)
2103 if (!m_convert (mp, msgs[msgnum]))
2107 /* Get new format string */
2108 nfs = new_fs (form, format, FORMAT);
2110 /* force scansbr to (re)compile format */
2117 s_optim = optim = 1;
2118 s_form = form ? getcpy (form) : NULL;
2119 s_format = format ? getcpy (format) : NULL;
2123 optim = equiv (s_form, form) && equiv (s_format, format);
2126 for (msgnum = mp->lowsel;
2127 msgnum <= mp->hghsel && !interrupted;
2129 if (is_selected (mp, msgnum)) {
2130 if (optim && Msgs[msgnum].m_scanl)
2131 printf ("%s", Msgs[msgnum].m_scanl);
2134 zp = msh_ready (msgnum, 0);
2135 switch (state = scan (zp, msgnum, 0, nfs, width,
2136 msgnum == mp->curmsg,
2137 is_unseen (mp, msgnum),
2138 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2139 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2145 Msgs[msgnum].m_scanl = getcpy (scanl);
2149 advise (NULL, "scan() botch (%d)", state);
2153 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2165 static struct swit showswit[] = {
2169 { "form formfile", 4 },
2171 { "moreproc program", 4 },
2173 { "nomoreproc", 3 },
2175 { "length lines", 4 },
2177 { "width columns", 4 },
2179 { "showproc program", 4 },
2181 { "noshowproc", 3 },
2193 showcmd (char **args)
2195 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2196 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2197 char *cp, *proc = showproc, buf[BUFSIZ];
2198 char *msgs[MAXARGS], *vec[MAXARGS];
2200 if (!mh_strcasecmp (cmd_name, "next"))
2203 if (!mh_strcasecmp (cmd_name, "prev"))
2205 while ((cp = *args++)) {
2207 switch (i = smatch (++cp, showswit)) {
2209 ambigsw (cp, showswit);
2216 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2217 cmd_name, mode ? NULL : "[msgs] ");
2218 print_help (buf, showswit, 1);
2226 if (!(cp = *args++) || *cp == '-') {
2227 advise (NULL, "missing argument to %s", args[-2]);
2239 if (!(proc = *args++) || *proc == '-') {
2240 advise (NULL, "missing argument to %s", args[-2]);
2250 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2253 if (*cp == '+' || *cp == '@') {
2254 advise (NULL, "sorry, no folders allowed!");
2260 "usage: %s [switches] [switches for showproc]\n",
2270 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2271 for (msgnum = 0; msgnum < msgp; msgnum++)
2272 if (!m_convert (mp, msgs[msgnum]))
2277 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2278 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2279 proc = showmimeproc;
2280 vec[vecp++] = "-file";
2288 if (strcmp (showproc, "mhl") == 0) {
2294 seqnum = seq_getnum (mp, "unseen");
2295 vec[0] = r1bindex (proc, '/');
2298 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2299 if (is_selected (mp, msgnum)) {
2300 vec[vecp++] = getcpy (m_name (msgnum));
2302 seq_delmsg (mp, "unseen", msgnum);
2305 if (mp->numsel == 1 && headersw)
2307 mhlsbr (vecp, vec, mhl_action);
2308 m_eomsbr ((int (*)()) 0);
2313 for (msgnum = mp->lowsel;
2314 msgnum <= mp->hghsel && !interrupted;
2316 if (is_selected (mp, msgnum)) {
2317 switch (ask (msgnum)) {
2318 case NOTOK: /* QUIT */
2325 if (mp->numsel == 1 && headersw)
2328 copy_message (msgnum, stdout);
2330 process (msgnum, proc, vecp, vec);
2333 seq_delmsg (mp, "unseen", msgnum);
2340 seq_setcur (mp, mp->hghsel);
2347 if (Msgs[msgnum].m_bboard_id == 0)
2350 printf ("(Message %d", msgnum);
2351 if (Msgs[msgnum].m_bboard_id > 0)
2352 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2363 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2368 mhl_action (char *name)
2372 if ((msgnum = m_atoi (name)) < mp->lowmsg
2373 || msgnum > mp->hghmsg
2374 || !does_exist (mp, msgnum))
2378 mhlfp = msh_ready (msgnum, 1);
2380 m_eomsbr (eom_action);
2392 if (mp->numsel == 1 || !interactive || redirected)
2395 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2396 if (mp->lowsel != msgnum)
2398 printf ("Press <return> to list \"%d\"...", msgnum);
2403 read (fileno (stdout), buf, sizeof buf);
2405 if (strchr(buf, '\n') == NULL)
2409 told_to_quit = interrupted = 0;
2424 is_nontext (int msgnum)
2427 unsigned char *bp, *dp;
2429 char buf[BUFSIZ], name[NAMESZ];
2432 if (Msgs[msgnum].m_flags & MHNCHK)
2433 return (Msgs[msgnum].m_flags & MHNYES);
2434 Msgs[msgnum].m_flags |= MHNCHK;
2436 fp = msh_ready (msgnum, 1);
2439 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2444 * Check Content-Type field
2446 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2450 cp = add (buf, NULL);
2451 while (state == FLDPLUS) {
2452 state = m_getfld (state, name, buf, sizeof buf, fp);
2459 for (; isspace (*bp); bp++)
2464 for (bp++, i = 0;;) {
2494 for (dp = bp; istoken (*dp); dp++)
2501 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2504 for (dp++; isspace (*dp); dp++)
2507 if ((result = !uprf (dp, "charset")))
2509 dp += sizeof "charset" - 1;
2510 while (isspace (*dp))
2514 while (isspace (*dp))
2517 if ((bp = strchr(++dp, '"')))
2520 for (bp = dp; *bp; bp++)
2521 if (isspace (*bp)) {
2527 /* Default character set */
2530 /* Check the character set */
2531 result = !check_charset (dp, strlen (dp));
2533 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2543 Msgs[msgnum].m_flags |= MHNYES;
2550 * Check Content-Transfer-Encoding field
2552 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2553 cp = add (buf, NULL);
2554 while (state == FLDPLUS) {
2555 state = m_getfld (state, name, buf, sizeof buf, fp);
2558 for (bp = cp; isspace (*bp); bp++)
2560 for (dp = bp; istoken (*dp); dp++)
2563 result = (mh_strcasecmp (bp, "7bit")
2564 && mh_strcasecmp (bp, "8bit")
2565 && mh_strcasecmp (bp, "binary"));
2569 Msgs[msgnum].m_flags |= MHNYES;
2576 * Just skip the rest of this header
2577 * field and go to next one.
2579 while (state == FLDPLUS)
2580 state = m_getfld (state, name, buf, sizeof(buf), fp);
2584 * We've passed the message header,
2585 * so message is just text.
2593 static struct swit sortswit[] = {
2595 { "datefield field", 0 },
2597 { "textfield field", 0 },
2599 { "notextfield", 0 },
2601 { "limit days", 0 },
2615 sortcmd (char **args)
2617 int msgp = 0, msgnum;
2618 char *cp, *datesw = NULL, *subjsw = NULL;
2619 char buf[BUFSIZ], *msgs[MAXARGS];
2623 forkcmd (args, cmd_name);
2627 while ((cp = *args++)) {
2629 switch (smatch (++cp, sortswit)) {
2631 ambigsw (cp, sortswit);
2634 fprintf (stderr, "-%s unknown\n", cp);
2637 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2638 print_help (buf, sortswit, 1);
2643 advise (NULL, "only one date field at a time!");
2646 if (!(datesw = *args++) || *datesw == '-') {
2647 advise (NULL, "missing argument to %s", args[-2]);
2654 advise (NULL, "only one text field at a time!");
2657 if (!(subjsw = *args++) || *subjsw == '-') {
2658 advise (NULL, "missing argument to %s", args[-2]);
2666 case SOLIMT: /* too hard */
2667 if (!(cp = *args++) || *cp == '-') {
2668 advise (NULL, "missing argument to %s", args[-2]);
2672 case SOVERB: /* not implemented */
2676 if (*cp == '+' || *cp == '@') {
2677 advise (NULL, "sorry, no folders allowed!");
2685 msgs[msgp++] = "all";
2688 for (msgnum = 0; msgnum < msgp; msgnum++)
2689 if (!m_convert (mp, msgs[msgnum]))
2693 twscopy (&tb, dlocaltimenow ());
2695 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2696 if (Msgs[msgnum].m_scanl) {
2697 free (Msgs[msgnum].m_scanl);
2698 Msgs[msgnum].m_scanl = NULL;
2700 if (is_selected (mp, msgnum)) {
2701 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2702 twscopy (&Msgs[msgnum].m_tb,
2703 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2705 else /* m_scaln is already NULL */
2706 twscopy (&Msgs[msgnum].m_tb, &tb);
2707 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2708 if (mp->curmsg == msgnum)
2709 Msgs[msgnum].m_stats |= CUR;
2712 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2713 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2715 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2716 if (subjsw && Msgs[msgnum].m_scanl) {
2717 free (Msgs[msgnum].m_scanl); /* from subjsort */
2718 Msgs[msgnum].m_scanl = NULL;
2720 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2721 if (Msgs[msgnum].m_stats & CUR)
2722 seq_setcur (mp, msgnum);
2725 mp->msgflags |= MODIFIED;
2731 * get_fields - parse message, and get date and subject if needed.
2732 * We'll use the msgp->m_tb tws struct for the date, and overload
2733 * the msgp->m_scanl field with our subject string.
2736 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2738 int state, gotdate = 0;
2739 char *bp, buf[BUFSIZ], name[NAMESZ];
2740 struct tws *tw = (struct tws *) 0;
2743 zp = msh_ready (msgnum, 0);
2744 for (state = FLD;;) {
2745 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2749 if (!mh_strcasecmp (name, datesw)) {
2751 while (state == FLDPLUS) {
2752 state = m_getfld (state, name, buf, sizeof buf, zp);
2755 if ((tw = dparsetime (bp)) == NULL)
2757 "unable to parse %s field in message %d",
2760 twscopy (&(msgp->m_tb), tw);
2762 if (!subjsw) /* not using this, or already done */
2763 break; /* all done! */
2766 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2768 while (state == FLDPLUS) {
2769 state = m_getfld (state, name, buf, sizeof buf, zp);
2772 msgp->m_scanl = sosmash(subjsw, bp);
2774 break; /* date done so we're done */
2776 subjsw = (char *)0;/* subject done, need date */
2778 while (state == FLDPLUS) /* flush this one */
2779 state = m_getfld (state, name, buf, sizeof buf, zp);
2790 admonish (NULL, "format error in message %d", msgnum);
2791 if (msgp->m_scanl) { /* this might need free'd */
2792 free (msgp->m_scanl); /* probably can't use subj anyway */
2793 msgp->m_scanl = NULL;
2798 adios (NULL, "internal error -- you lose");
2803 return OK; /* not an error if subj not found */
2805 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2806 return NOTOK; /* NOTOK means use some other date */
2815 msgsort (struct Msg *a, struct Msg *b)
2817 return twsort (&a->m_tb, &b->m_tb);
2822 subsort (struct Msg *a, struct Msg *b)
2826 if (a->m_scanl && b->m_scanl)
2827 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2830 return twsort (&a->m_tb, &b->m_tb);
2835 * try to make the subject "canonical": delete leading "re:", everything
2836 * but letters & smash letters to lower case.
2839 sosmash (char *subj, char *s)
2841 register char *cp, *dp;
2842 register unsigned char c;
2846 dp = s; /* dst pointer */
2847 if (!mh_strcasecmp (subj, "subject"))
2854 *dp++ = isupper(c) ? tolower(c) : c;
2860 while ((c = *cp++)) {
2862 *dp++ = isupper(c) ? tolower(c) : c;
2872 process (int msgnum, char *proc, int vecp, char **vec)
2874 int child_id, status;
2875 char tmpfil[BUFSIZ];
2880 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2881 context_del (pfolder);
2882 context_replace (pfolder, fmsh);/* update current folder */
2884 context_save (); /* save the context file */
2888 cp = m_mktemp(invo_name, NULL, &out);
2890 /* Try again, but try to create under /tmp */
2892 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2895 advise (NULL, "unable to create temporary file");
2899 copy_message (msgnum, out);
2901 strncpy(tmpfil, cp, sizeof(tmpfil));
2905 switch (child_id = fork ()) {
2907 advise ("fork", "unable to");
2913 SIGNAL (SIGINT, istat);
2914 SIGNAL (SIGQUIT, qstat);
2916 vec[vecp++] = tmpfil;
2920 fprintf (stderr, "unable to exec ");
2925 status = pidXwait (child_id, NULL);
2936 copy_message (int msgnum, FILE *out)
2939 static char buffer[BUFSIZ];
2942 zp = msh_ready (msgnum, 1);
2944 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2945 fputs (buffer, out);
2946 if (interrupted && out == stdout)
2952 while (fgets (buffer, sizeof buffer, zp) != NULL
2953 && pos < Msgs[msgnum].m_stop) {
2954 fputs (buffer, out);
2955 pos += (long) strlen (buffer);
2956 if (interrupted && out == stdout)
2964 copy_digest (int msgnum, FILE *out)
2968 static char buffer[BUFSIZ];
2972 zp = msh_ready (msgnum, 1);
2975 while (fgets (buffer, sizeof buffer, zp) != NULL
2976 && !fmsh && pos < Msgs[msgnum].m_stop) {
2977 if (c == '\n' && *buffer == '-')
2979 fputs (buffer, out);
2980 c = buffer[strlen (buffer) - 1];
2982 pos += (long) strlen (buffer);
2983 if (interrupted && out == stdout)