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)
1082 for (i = 0; hlpmsg[i]; i++) {
1083 printf (hlpmsg[i], invo_name);
1089 static struct swit markswit[] = {
1097 { "sequence name", 0 },
1115 markcmd (char **args)
1117 int addsw = 0, deletesw = 0, debugsw = 0;
1118 int listsw = 0, zerosw = 0;
1120 int msgp = 0, msgnum;
1121 char *cp, buf[BUFSIZ];
1122 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1124 while ((cp = *args++)) {
1126 switch (smatch (++cp, markswit)) {
1128 ambigsw (cp, markswit);
1131 fprintf (stderr, "-%s unknown\n", cp);
1134 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1135 print_help (buf, markswit, 1);
1140 deletesw = listsw = 0;
1148 addsw = deletesw = 0;
1152 if (!(cp = *args++) || *cp == '-') {
1153 advise (NULL, "missing argument to %s", args[-2]);
1156 if (seqp < NUMATTRS)
1159 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1164 case MPUBSW: /* not implemented */
1180 if (*cp == '+' || *cp == '@') {
1181 advise (NULL, "sorry, no folders allowed!");
1188 if (!addsw && !deletesw && !listsw) {
1195 seqs[seqp++] = "unseen";
1199 msgs[msgp++] = "all";
1204 msgs[msgp++] = listsw ? "all" :"cur";
1205 for (msgnum = 0; msgnum < msgp; msgnum++)
1206 if (!m_convert (mp, msgs[msgnum]))
1210 printf ("invo_name=%s mypath=%s defpath=%s\n",
1211 invo_name, mypath, defpath);
1212 printf ("ctxpath=%s context flags=%s\n",
1213 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1214 printf ("foldpath=%s flags=%s\n",
1216 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1217 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1218 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1219 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1220 mp->lowsel, mp->hghsel, mp->numsel);
1221 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1224 if (seqp == 0 && (addsw || deletesw)) {
1225 advise (NULL, "-%s requires at least one -sequence argument",
1226 addsw ? "add" : "delete");
1232 for (seqp = 0; seqs[seqp]; seqp++)
1233 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1238 for (seqp = 0; seqs[seqp]; seqp++)
1239 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1243 /* Listing messages in sequences */
1246 /* list the given sequences */
1247 for (seqp = 0; seqs[seqp]; seqp++)
1248 seq_print (mp, seqs[seqp]);
1250 /* else list them all */
1256 for (msgnum = mp->lowsel;
1257 msgnum <= mp->hghsel && !interrupted;
1259 if (is_selected (mp, msgnum)) {
1260 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1263 Msgs[msgnum].m_bboard_id,
1265 (long) Msgs[msgnum].m_start,
1266 (long) Msgs[msgnum].m_stop,
1267 snprintb (buf, sizeof(buf),
1268 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1270 if (Msgs[msgnum].m_scanl)
1271 printf ("%s", Msgs[msgnum].m_scanl);
1277 static struct swit mhnswit[] = {
1280 #define MHNNAUTOSW 1
1282 #define MHNDEBUGSW 2
1284 #define MHNEBCDICSW 3
1285 { "ebcdicsafe", 0 },
1286 #define MHNNEBCDICSW 4
1287 { "noebcdicsafe", 0 },
1289 { "form formfile", 4 },
1292 #define MHNNHEADSW 7
1296 #define MHNNLISTSW 9
1298 #define MHNPARTSW 10
1299 { "part number", 0 },
1300 #define MHNSIZESW 11
1302 #define MHNNSIZESW 12
1303 { "norealsize", 0 },
1304 #define MHNRFC934SW 13
1305 { "rfc934mode", 0 },
1306 #define MHNNRFC934SW 14
1307 { "norfc934mode", 0 },
1308 #define MHNSERIALSW 15
1309 { "serialonly", 0 },
1310 #define MHNNSERIALSW 16
1311 { "noserialonly", 0 },
1312 #define MHNSHOWSW 17
1314 #define MHNNSHOWSW 18
1316 #define MHNSTORESW 19
1318 #define MHNNSTORESW 20
1320 #define MHNTYPESW 21
1321 { "type content", 0 },
1322 #define MHNVERBSW 22
1324 #define MHNNVERBSW 23
1326 #define MHNHELPSW 24
1328 #define MHNPROGSW 25
1329 { "moreproc program", -4 },
1330 #define MHNNPROGSW 26
1331 { "nomoreproc", -3 },
1333 { "length lines", -4 },
1335 { "width columns", -4 },
1341 mhncmd (char **args)
1343 int msgp = 0, vecp = 1;
1345 char *cp, buf[BUFSIZ];
1346 char *msgs[MAXARGS], *vec[MAXARGS];
1349 forkcmd (args, cmd_name);
1352 while ((cp = *args++)) {
1354 switch (smatch (++cp, mhnswit)) {
1356 ambigsw (cp, mhnswit);
1359 fprintf (stderr, "-%s unknown\n", cp);
1362 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1363 print_help (buf, mhnswit, 1);
1398 if (!(cp = *args++) || *cp == '-') {
1399 advise (NULL, "missing argument to %s", args[-2]);
1406 if (*cp == '+' || *cp == '@') {
1407 advise (NULL, "sorry, no folders allowed!");
1415 vec[vecp++] = "-file";
1418 msgs[msgp++] = "cur";
1419 for (msgnum = 0; msgnum < msgp; msgnum++)
1420 if (!m_convert (mp, msgs[msgnum]))
1425 for (msgnum = mp->lowsel;
1426 msgnum <= mp->hghsel && !interrupted;
1428 if (is_selected (mp, msgnum))
1429 if (process (msgnum, cmd_name, vecp, vec)) {
1430 unset_selected (mp, msgnum);
1434 seq_setcur (mp, mp->hghsel);
1438 static struct swit packswit[] = {
1446 static int mbx_style = MMDF_FORMAT;
1449 packcmd (char **args)
1451 int msgp = 0, md, msgnum;
1452 char *cp, *file = NULL;
1453 char buf[BUFSIZ], *msgs[MAXARGS];
1457 forkcmd (args, cmd_name);
1461 while ((cp = *args++)) {
1463 switch (smatch (++cp, packswit)) {
1465 ambigsw (cp, packswit);
1468 fprintf (stderr, "-%s unknown\n", cp);
1471 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1472 print_help (buf, packswit, 1);
1476 if (!(file = *args++) || *file == '-') {
1477 advise (NULL, "missing argument to %s", args[-2]);
1482 if (*cp == '+' || *cp == '@') {
1483 advise (NULL, "sorry, no folders allowed!");
1492 file = path (file, TFILE);
1493 if (stat (file, &st) == NOTOK) {
1494 if (errno != ENOENT) {
1495 advise (file, "error on file");
1498 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1505 msgs[msgp++] = "all";
1506 for (msgnum = 0; msgnum < msgp; msgnum++)
1507 if (!m_convert (mp, msgs[msgnum]))
1511 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1512 advise (file, "unable to open");
1515 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1516 if (is_selected (mp, msgnum))
1517 if (pack (file, md, msgnum) == NOTOK)
1519 mbx_close (file, md);
1521 if (mp->hghsel != mp->curmsg)
1522 seq_setcur (mp, mp->lowsel);
1530 pack (char *mailbox, int md, int msgnum)
1534 if (Msgs[msgnum].m_bboard_id == 0)
1537 zp = msh_ready (msgnum, 1);
1538 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1539 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1544 packhak (char **args)
1547 char *cp, *file = NULL;
1549 while ((cp = *args++)) {
1551 switch (smatch (++cp, packswit)) {
1558 if (!(file = *args++) || *file == '-')
1562 if (*cp == '+' || *cp == '@')
1566 file = path (file ? file : "./msgbox", TFILE);
1567 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1574 static struct swit pickswit[] = {
1586 { "cc pattern", 0 },
1588 { "date pattern", 0 },
1590 { "from pattern", 0 },
1592 { "search pattern", 0 },
1594 { "subject pattern", 0 },
1596 { "to pattern", 0 },
1598 { "-othercomponent pattern", 15 },
1600 { "after date", 0 },
1602 { "before date", 0 },
1604 { "datefield field", 5 },
1606 { "sequence name", 0 },
1626 pickcmd (char **args)
1628 int zerosw = 1, msgp = 0;
1630 int vecp = 0, hi, lo, msgnum;
1631 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1632 char *seqs[NUMATTRS], *vec[MAXARGS];
1635 while ((cp = *args++)) {
1641 switch (smatch (cp, pickswit)) {
1643 ambigsw (cp, pickswit);
1646 fprintf (stderr, "-%s unknown\n", cp);
1649 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1650 print_help (buf, pickswit, 1);
1664 if (!(cp = *args++)) {/* allow -xyz arguments */
1665 advise (NULL, "missing argument to %s", args[-2]);
1671 advise (NULL, "internal error!");
1682 if (!(cp = *args++) || *cp == '-') {
1683 advise (NULL, "missing argument to %s", args[-2]);
1686 if (seqp < NUMATTRS)
1689 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1700 case PIPUSW: /* not implemented */
1707 if (*cp == '+' || *cp == '@') {
1708 advise (NULL, "sorry, no folders allowed!");
1717 msgs[msgp++] = "all";
1718 for (msgnum = 0; msgnum < msgp; msgnum++)
1719 if (!m_convert (mp, msgs[msgnum]))
1724 if (!pcompile (vec, NULL))
1730 for (msgnum = mp->lowsel;
1731 msgnum <= mp->hghsel && !interrupted;
1733 if (is_selected (mp, msgnum)) {
1734 zp = msh_ready (msgnum, 1);
1735 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1736 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1743 unset_selected (mp, msgnum);
1754 if (mp->numsel <= 0) {
1755 advise (NULL, "no messages match specification");
1760 for (seqp = 0; seqs[seqp]; seqp++)
1761 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1764 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1768 static struct swit replswit[] = {
1772 { "noannotate", 0 },
1778 { "draftfolder +folder", 0 },
1780 { "draftmessage msg", 0 },
1782 { "nodraftfolder", 0 },
1784 { "editor editor", 0 },
1788 { "fcc +folder", 0 },
1790 { "filter filterfile", 0 },
1792 { "form formfile", 0 },
1802 { "whatnowproc program", 0 },
1806 { "width columns", 0 },
1814 replcmd (char **args)
1817 char *cp, *msg = NULL;
1818 char buf[BUFSIZ], *vec[MAXARGS];
1821 forkcmd (args, cmd_name);
1825 while ((cp = *args++)) {
1827 switch (smatch (++cp, replswit)) {
1829 ambigsw (cp, replswit);
1832 fprintf (stderr, "-%s unknown\n", cp);
1835 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1836 print_help (buf, replswit, 1);
1839 case REANSW: /* not implemented */
1864 if (!(cp = *args++) || *cp == '-') {
1865 advise (NULL, "missing argument to %s", args[-2]);
1871 if (*cp == '+' || *cp == '@') {
1872 advise (NULL, "sorry, no folders allowed!");
1877 advise (NULL, "only one message at a time!");
1885 vec[vecp++] = "-file";
1889 if (!m_convert (mp, msg))
1893 if (mp->numsel > 1) {
1894 advise (NULL, "only one message at a time!");
1897 process (mp->hghsel, cmd_name, vecp, vec);
1898 seq_setcur (mp, mp->hghsel);
1902 static struct swit rmmswit[] = {
1910 rmmcmd (char **args)
1912 int msgp = 0, msgnum;
1913 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1915 while ((cp = *args++)) {
1917 switch (smatch (++cp, rmmswit)) {
1919 ambigsw (cp, rmmswit);
1922 fprintf (stderr, "-%s unknown\n", cp);
1925 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1926 print_help (buf, rmmswit, 1);
1929 if (*cp == '+' || *cp == '@') {
1930 advise (NULL, "sorry, no folders allowed!");
1938 msgs[msgp++] = "cur";
1939 for (msgnum = 0; msgnum < msgp; msgnum++)
1940 if (!m_convert (mp, msgs[msgnum]))
1951 register int msgnum, vecp;
1953 char buffer[BUFSIZ], *vec[MAXARGS];
1957 if (mp->numsel > MAXARGS - 1) {
1958 advise (NULL, "more than %d messages for %s exec",
1959 MAXARGS - 1, rmmproc);
1963 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1964 if (is_selected (mp, msgnum))
1965 vec[vecp++] = getcpy (m_name (msgnum));
1967 forkcmd (vec, rmmproc);
1968 for (vecp = 0; vec[vecp]; vecp++)
1972 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1973 if (is_selected (mp, msgnum)) {
1974 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1975 if (rename (cp, buffer) == NOTOK)
1976 admonish (buffer, "unable to rename %s to", cp);
1980 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1981 if (is_selected (mp, msgnum)) {
1982 set_deleted (mp, msgnum);
1983 unset_exists (mp, msgnum);
1986 if ((mp->nummsg -= mp->numsel) <= 0) {
1988 admonish (NULL, "no messages remaining in +%s", fmsh);
1990 admonish (NULL, "no messages remaining in %s", mp->foldpath);
1991 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
1993 if (mp->lowsel == mp->lowmsg) {
1994 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
1995 if (does_exist (mp, msgnum))
1997 mp->lowmsg = msgnum;
1999 if (mp->hghsel == mp->hghmsg) {
2000 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2001 if (does_exist (mp, msgnum))
2003 mp->hghmsg = msgnum;
2006 mp->msgflags |= MODIFIED;
2011 static struct swit scanswit[] = {
2017 { "form formatfile", 0 },
2019 { "format string", 5 },
2025 { "width columns", 0 },
2033 scancmd (char **args)
2035 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2037 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2038 int msgnum, optim, state;
2039 char *cp, *form = NULL, *format = NULL;
2040 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2042 static int s_optim = 0;
2043 static char *s_form = NULL, *s_format = NULL;
2045 while ((cp = *args++)) {
2047 switch (smatch (++cp, scanswit)) {
2049 ambigsw (cp, scanswit);
2052 fprintf (stderr, "-%s unknown\n", cp);
2055 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2056 print_help (buf, scanswit, 1);
2072 if (!(form = *args++) || *form == '-') {
2073 advise (NULL, "missing argument to %s", args[-2]);
2079 if (!(format = *args++) || *format == '-') {
2080 advise (NULL, "missing argument to %s", args[-2]);
2086 if (!(cp = *args++) || *cp == '-') {
2087 advise (NULL, "missing argument to %s", args[-2]);
2093 if (*cp == '+' || *cp == '@') {
2094 advise (NULL, "sorry, no folders allowed!");
2102 msgs[msgp++] = "all";
2103 for (msgnum = 0; msgnum < msgp; msgnum++)
2104 if (!m_convert (mp, msgs[msgnum]))
2108 /* Get new format string */
2109 nfs = new_fs (form, format, FORMAT);
2111 /* force scansbr to (re)compile format */
2118 s_optim = optim = 1;
2119 s_form = form ? getcpy (form) : NULL;
2120 s_format = format ? getcpy (format) : NULL;
2124 optim = equiv (s_form, form) && equiv (s_format, format);
2127 for (msgnum = mp->lowsel;
2128 msgnum <= mp->hghsel && !interrupted;
2130 if (is_selected (mp, msgnum)) {
2131 if (optim && Msgs[msgnum].m_scanl)
2132 printf ("%s", Msgs[msgnum].m_scanl);
2135 zp = msh_ready (msgnum, 0);
2136 switch (state = scan (zp, msgnum, 0, nfs, width,
2137 msgnum == mp->curmsg,
2138 is_unseen (mp, msgnum),
2139 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2140 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2146 Msgs[msgnum].m_scanl = getcpy (scanl);
2150 advise (NULL, "scan() botch (%d)", state);
2154 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2166 static struct swit showswit[] = {
2170 { "form formfile", 4 },
2172 { "moreproc program", 4 },
2174 { "nomoreproc", 3 },
2176 { "length lines", 4 },
2178 { "width columns", 4 },
2180 { "showproc program", 4 },
2182 { "noshowproc", 3 },
2194 showcmd (char **args)
2196 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2197 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2198 char *cp, *proc = showproc, buf[BUFSIZ];
2199 char *msgs[MAXARGS], *vec[MAXARGS];
2201 if (!mh_strcasecmp (cmd_name, "next"))
2204 if (!mh_strcasecmp (cmd_name, "prev"))
2206 while ((cp = *args++)) {
2208 switch (i = smatch (++cp, showswit)) {
2210 ambigsw (cp, showswit);
2217 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2218 cmd_name, mode ? NULL : "[msgs] ");
2219 print_help (buf, showswit, 1);
2227 if (!(cp = *args++) || *cp == '-') {
2228 advise (NULL, "missing argument to %s", args[-2]);
2240 if (!(proc = *args++) || *proc == '-') {
2241 advise (NULL, "missing argument to %s", args[-2]);
2251 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2254 if (*cp == '+' || *cp == '@') {
2255 advise (NULL, "sorry, no folders allowed!");
2261 "usage: %s [switches] [switches for showproc]\n",
2271 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2272 for (msgnum = 0; msgnum < msgp; msgnum++)
2273 if (!m_convert (mp, msgs[msgnum]))
2277 if (!nshow && !getenv ("NOMHNPROC"))
2278 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2279 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2280 proc = showmimeproc;
2281 vec[vecp++] = "-file";
2289 if (strcmp (showproc, "mhl") == 0) {
2295 seqnum = seq_getnum (mp, "unseen");
2296 vec[0] = r1bindex (proc, '/');
2299 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2300 if (is_selected (mp, msgnum)) {
2301 vec[vecp++] = getcpy (m_name (msgnum));
2303 seq_delmsg (mp, "unseen", msgnum);
2306 if (mp->numsel == 1 && headersw)
2308 mhlsbr (vecp, vec, mhl_action);
2309 m_eomsbr ((int (*)()) 0);
2314 for (msgnum = mp->lowsel;
2315 msgnum <= mp->hghsel && !interrupted;
2317 if (is_selected (mp, msgnum)) {
2318 switch (ask (msgnum)) {
2319 case NOTOK: /* QUIT */
2326 if (mp->numsel == 1 && headersw)
2329 copy_message (msgnum, stdout);
2331 process (msgnum, proc, vecp, vec);
2334 seq_delmsg (mp, "unseen", msgnum);
2341 seq_setcur (mp, mp->hghsel);
2348 if (Msgs[msgnum].m_bboard_id == 0)
2351 printf ("(Message %d", msgnum);
2352 if (Msgs[msgnum].m_bboard_id > 0)
2353 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2364 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2369 mhl_action (char *name)
2373 if ((msgnum = m_atoi (name)) < mp->lowmsg
2374 || msgnum > mp->hghmsg
2375 || !does_exist (mp, msgnum))
2379 mhlfp = msh_ready (msgnum, 1);
2381 m_eomsbr (eom_action);
2393 if (mp->numsel == 1 || !interactive || redirected)
2396 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2397 if (mp->lowsel != msgnum)
2399 printf ("Press <return> to list \"%d\"...", msgnum);
2404 read (fileno (stdout), buf, sizeof buf);
2406 if (strchr(buf, '\n') == NULL)
2410 told_to_quit = interrupted = 0;
2425 is_nontext (int msgnum)
2428 unsigned char *bp, *dp;
2430 char buf[BUFSIZ], name[NAMESZ];
2433 if (Msgs[msgnum].m_flags & MHNCHK)
2434 return (Msgs[msgnum].m_flags & MHNYES);
2435 Msgs[msgnum].m_flags |= MHNCHK;
2437 fp = msh_ready (msgnum, 1);
2440 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2445 * Check Content-Type field
2447 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2451 cp = add (buf, NULL);
2452 while (state == FLDPLUS) {
2453 state = m_getfld (state, name, buf, sizeof buf, fp);
2460 for (; isspace (*bp); bp++)
2465 for (bp++, i = 0;;) {
2495 for (dp = bp; istoken (*dp); dp++)
2502 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2505 for (dp++; isspace (*dp); dp++)
2508 if ((result = !uprf (dp, "charset")))
2510 dp += sizeof "charset" - 1;
2511 while (isspace (*dp))
2515 while (isspace (*dp))
2518 if ((bp = strchr(++dp, '"')))
2521 for (bp = dp; *bp; bp++)
2522 if (isspace (*bp)) {
2528 /* Default character set */
2531 /* Check the character set */
2532 result = !check_charset (dp, strlen (dp));
2534 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2544 Msgs[msgnum].m_flags |= MHNYES;
2551 * Check Content-Transfer-Encoding field
2553 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2554 cp = add (buf, NULL);
2555 while (state == FLDPLUS) {
2556 state = m_getfld (state, name, buf, sizeof buf, fp);
2559 for (bp = cp; isspace (*bp); bp++)
2561 for (dp = bp; istoken (*dp); dp++)
2564 result = (mh_strcasecmp (bp, "7bit")
2565 && mh_strcasecmp (bp, "8bit")
2566 && mh_strcasecmp (bp, "binary"));
2570 Msgs[msgnum].m_flags |= MHNYES;
2577 * Just skip the rest of this header
2578 * field and go to next one.
2580 while (state == FLDPLUS)
2581 state = m_getfld (state, name, buf, sizeof(buf), fp);
2585 * We've passed the message header,
2586 * so message is just text.
2594 static struct swit sortswit[] = {
2596 { "datefield field", 0 },
2598 { "textfield field", 0 },
2600 { "notextfield", 0 },
2602 { "limit days", 0 },
2616 sortcmd (char **args)
2618 int msgp = 0, msgnum;
2619 char *cp, *datesw = NULL, *subjsw = NULL;
2620 char buf[BUFSIZ], *msgs[MAXARGS];
2624 forkcmd (args, cmd_name);
2628 while ((cp = *args++)) {
2630 switch (smatch (++cp, sortswit)) {
2632 ambigsw (cp, sortswit);
2635 fprintf (stderr, "-%s unknown\n", cp);
2638 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2639 print_help (buf, sortswit, 1);
2644 advise (NULL, "only one date field at a time!");
2647 if (!(datesw = *args++) || *datesw == '-') {
2648 advise (NULL, "missing argument to %s", args[-2]);
2655 advise (NULL, "only one text field at a time!");
2658 if (!(subjsw = *args++) || *subjsw == '-') {
2659 advise (NULL, "missing argument to %s", args[-2]);
2667 case SOLIMT: /* too hard */
2668 if (!(cp = *args++) || *cp == '-') {
2669 advise (NULL, "missing argument to %s", args[-2]);
2673 case SOVERB: /* not implemented */
2677 if (*cp == '+' || *cp == '@') {
2678 advise (NULL, "sorry, no folders allowed!");
2686 msgs[msgp++] = "all";
2689 for (msgnum = 0; msgnum < msgp; msgnum++)
2690 if (!m_convert (mp, msgs[msgnum]))
2694 twscopy (&tb, dlocaltimenow ());
2696 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2697 if (Msgs[msgnum].m_scanl) {
2698 free (Msgs[msgnum].m_scanl);
2699 Msgs[msgnum].m_scanl = NULL;
2701 if (is_selected (mp, msgnum)) {
2702 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2703 twscopy (&Msgs[msgnum].m_tb,
2704 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2706 else /* m_scaln is already NULL */
2707 twscopy (&Msgs[msgnum].m_tb, &tb);
2708 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2709 if (mp->curmsg == msgnum)
2710 Msgs[msgnum].m_stats |= CUR;
2713 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2714 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2716 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2717 if (subjsw && Msgs[msgnum].m_scanl) {
2718 free (Msgs[msgnum].m_scanl); /* from subjsort */
2719 Msgs[msgnum].m_scanl = NULL;
2721 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2722 if (Msgs[msgnum].m_stats & CUR)
2723 seq_setcur (mp, msgnum);
2726 mp->msgflags |= MODIFIED;
2732 * get_fields - parse message, and get date and subject if needed.
2733 * We'll use the msgp->m_tb tws struct for the date, and overload
2734 * the msgp->m_scanl field with our subject string.
2737 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2739 int state, gotdate = 0;
2740 char *bp, buf[BUFSIZ], name[NAMESZ];
2741 struct tws *tw = (struct tws *) 0;
2744 zp = msh_ready (msgnum, 0);
2745 for (state = FLD;;) {
2746 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2750 if (!mh_strcasecmp (name, datesw)) {
2752 while (state == FLDPLUS) {
2753 state = m_getfld (state, name, buf, sizeof buf, zp);
2756 if ((tw = dparsetime (bp)) == NULL)
2758 "unable to parse %s field in message %d",
2761 twscopy (&(msgp->m_tb), tw);
2763 if (!subjsw) /* not using this, or already done */
2764 break; /* all done! */
2767 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2769 while (state == FLDPLUS) {
2770 state = m_getfld (state, name, buf, sizeof buf, zp);
2773 msgp->m_scanl = sosmash(subjsw, bp);
2775 break; /* date done so we're done */
2777 subjsw = (char *)0;/* subject done, need date */
2779 while (state == FLDPLUS) /* flush this one */
2780 state = m_getfld (state, name, buf, sizeof buf, zp);
2791 admonish (NULL, "format error in message %d", msgnum);
2792 if (msgp->m_scanl) { /* this might need free'd */
2793 free (msgp->m_scanl); /* probably can't use subj anyway */
2794 msgp->m_scanl = NULL;
2799 adios (NULL, "internal error -- you lose");
2804 return OK; /* not an error if subj not found */
2806 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2807 return NOTOK; /* NOTOK means use some other date */
2816 msgsort (struct Msg *a, struct Msg *b)
2818 return twsort (&a->m_tb, &b->m_tb);
2823 subsort (struct Msg *a, struct Msg *b)
2827 if (a->m_scanl && b->m_scanl)
2828 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2831 return twsort (&a->m_tb, &b->m_tb);
2836 * try to make the subject "canonical": delete leading "re:", everything
2837 * but letters & smash letters to lower case.
2840 sosmash (char *subj, char *s)
2842 register char *cp, *dp;
2843 register unsigned char c;
2847 dp = s; /* dst pointer */
2848 if (!mh_strcasecmp (subj, "subject"))
2855 *dp++ = isupper(c) ? tolower(c) : c;
2861 while ((c = *cp++)) {
2863 *dp++ = isupper(c) ? tolower(c) : c;
2873 process (int msgnum, char *proc, int vecp, char **vec)
2875 int child_id, status;
2876 char tmpfil[BUFSIZ];
2881 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2882 context_del (pfolder);
2883 context_replace (pfolder, fmsh);/* update current folder */
2885 context_save (); /* save the context file */
2889 cp = m_mktemp(invo_name, NULL, &out);
2891 /* Try again, but try to create under /tmp */
2893 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2896 advise (NULL, "unable to create temporary file");
2900 copy_message (msgnum, out);
2902 strncpy(tmpfil, cp, sizeof(tmpfil));
2906 switch (child_id = fork ()) {
2908 advise ("fork", "unable to");
2914 SIGNAL (SIGINT, istat);
2915 SIGNAL (SIGQUIT, qstat);
2917 vec[vecp++] = tmpfil;
2921 fprintf (stderr, "unable to exec ");
2926 status = pidXwait (child_id, NULL);
2937 copy_message (int msgnum, FILE *out)
2940 static char buffer[BUFSIZ];
2943 zp = msh_ready (msgnum, 1);
2945 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2946 fputs (buffer, out);
2947 if (interrupted && out == stdout)
2953 while (fgets (buffer, sizeof buffer, zp) != NULL
2954 && pos < Msgs[msgnum].m_stop) {
2955 fputs (buffer, out);
2956 pos += (long) strlen (buffer);
2957 if (interrupted && out == stdout)
2965 copy_digest (int msgnum, FILE *out)
2969 static char buffer[BUFSIZ];
2973 zp = msh_ready (msgnum, 1);
2976 while (fgets (buffer, sizeof buffer, zp) != NULL
2977 && !fmsh && pos < Msgs[msgnum].m_stop) {
2978 if (c == '\n' && *buffer == '-')
2980 fputs (buffer, out);
2981 c = buffer[strlen (buffer) - 1];
2983 pos += (long) strlen (buffer);
2984 if (interrupted && out == stdout)