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)
1091 for (i = 0; hlpmsg[i]; i++) {
1092 printf (hlpmsg[i], invo_name);
1098 static struct swit markswit[] = {
1106 { "sequence name", 0 },
1124 markcmd (char **args)
1126 int addsw = 0, deletesw = 0, debugsw = 0;
1127 int listsw = 0, zerosw = 0, seqp = 0;
1128 int msgp = 0, msgnum;
1129 char *cp, buf[BUFSIZ];
1130 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1132 while ((cp = *args++)) {
1134 switch (smatch (++cp, markswit)) {
1136 ambigsw (cp, markswit);
1139 fprintf (stderr, "-%s unknown\n", cp);
1142 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1143 print_help (buf, markswit, 1);
1148 deletesw = listsw = 0;
1156 addsw = deletesw = 0;
1160 if (!(cp = *args++) || *cp == '-') {
1161 advise (NULL, "missing argument to %s", args[-2]);
1164 if (seqp < NUMATTRS)
1167 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1172 case MPUBSW: /* not implemented */
1188 if (*cp == '+' || *cp == '@') {
1189 advise (NULL, "sorry, no folders allowed!");
1196 if (!addsw && !deletesw && !listsw) {
1203 seqs[seqp++] = "unseen";
1207 msgs[msgp++] = "all";
1212 msgs[msgp++] = listsw ? "all" :"cur";
1213 for (msgnum = 0; msgnum < msgp; msgnum++)
1214 if (!m_convert (mp, msgs[msgnum]))
1218 printf ("invo_name=%s mypath=%s defpath=%s\n",
1219 invo_name, mypath, defpath);
1220 printf ("ctxpath=%s context flags=%s\n",
1221 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1222 printf ("foldpath=%s flags=%s\n",
1224 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1225 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1226 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1227 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1228 mp->lowsel, mp->hghsel, mp->numsel);
1229 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1232 if (seqp == 0 && (addsw || deletesw)) {
1233 advise (NULL, "-%s requires at least one -sequence argument",
1234 addsw ? "add" : "delete");
1240 for (seqp = 0; seqs[seqp]; seqp++)
1241 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1246 for (seqp = 0; seqs[seqp]; seqp++)
1247 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1251 /* Listing messages in sequences */
1254 /* list the given sequences */
1255 for (seqp = 0; seqs[seqp]; seqp++)
1256 seq_print (mp, seqs[seqp]);
1258 /* else list them all */
1264 for (msgnum = mp->lowsel;
1265 msgnum <= mp->hghsel && !interrupted;
1267 if (is_selected (mp, msgnum)) {
1268 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1271 Msgs[msgnum].m_bboard_id,
1273 (long) Msgs[msgnum].m_start,
1274 (long) Msgs[msgnum].m_stop,
1275 snprintb (buf, sizeof(buf),
1276 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1278 if (Msgs[msgnum].m_scanl)
1279 printf ("%s", Msgs[msgnum].m_scanl);
1285 static struct swit mhnswit[] = {
1288 #define MHNNAUTOSW 1
1290 #define MHNDEBUGSW 2
1292 #define MHNEBCDICSW 3
1293 { "ebcdicsafe", 0 },
1294 #define MHNNEBCDICSW 4
1295 { "noebcdicsafe", 0 },
1297 { "form formfile", 4 },
1300 #define MHNNHEADSW 7
1304 #define MHNNLISTSW 9
1306 #define MHNPARTSW 10
1307 { "part number", 0 },
1308 #define MHNSIZESW 11
1310 #define MHNNSIZESW 12
1311 { "norealsize", 0 },
1312 #define MHNRFC934SW 13
1313 { "rfc934mode", 0 },
1314 #define MHNNRFC934SW 14
1315 { "norfc934mode", 0 },
1316 #define MHNSERIALSW 15
1317 { "serialonly", 0 },
1318 #define MHNNSERIALSW 16
1319 { "noserialonly", 0 },
1320 #define MHNSHOWSW 17
1322 #define MHNNSHOWSW 18
1324 #define MHNSTORESW 19
1326 #define MHNNSTORESW 20
1328 #define MHNTYPESW 21
1329 { "type content", 0 },
1330 #define MHNVERBSW 22
1332 #define MHNNVERBSW 23
1334 #define MHNHELPSW 24
1336 #define MHNPROGSW 25
1337 { "moreproc program", -4 },
1338 #define MHNNPROGSW 26
1339 { "nomoreproc", -3 },
1341 { "length lines", -4 },
1343 { "width columns", -4 },
1349 mhncmd (char **args)
1351 int msgp = 0, vecp = 1;
1353 char *cp, buf[BUFSIZ];
1354 char *msgs[MAXARGS], *vec[MAXARGS];
1357 forkcmd (args, cmd_name);
1360 while ((cp = *args++)) {
1362 switch (smatch (++cp, mhnswit)) {
1364 ambigsw (cp, mhnswit);
1367 fprintf (stderr, "-%s unknown\n", cp);
1370 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1371 print_help (buf, mhnswit, 1);
1406 if (!(cp = *args++) || *cp == '-') {
1407 advise (NULL, "missing argument to %s", args[-2]);
1414 if (*cp == '+' || *cp == '@') {
1415 advise (NULL, "sorry, no folders allowed!");
1423 vec[vecp++] = "-file";
1426 msgs[msgp++] = "cur";
1427 for (msgnum = 0; msgnum < msgp; msgnum++)
1428 if (!m_convert (mp, msgs[msgnum]))
1433 for (msgnum = mp->lowsel;
1434 msgnum <= mp->hghsel && !interrupted;
1436 if (is_selected (mp, msgnum))
1437 if (process (msgnum, cmd_name, vecp, vec)) {
1438 unset_selected (mp, msgnum);
1442 seq_setcur (mp, mp->hghsel);
1446 static struct swit packswit[] = {
1454 static int mbx_style = MMDF_FORMAT;
1457 packcmd (char **args)
1459 int msgp = 0, md, msgnum;
1460 char *cp, *file = NULL;
1461 char buf[BUFSIZ], *msgs[MAXARGS];
1465 forkcmd (args, cmd_name);
1469 while ((cp = *args++)) {
1471 switch (smatch (++cp, packswit)) {
1473 ambigsw (cp, packswit);
1476 fprintf (stderr, "-%s unknown\n", cp);
1479 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1480 print_help (buf, packswit, 1);
1484 if (!(file = *args++) || *file == '-') {
1485 advise (NULL, "missing argument to %s", args[-2]);
1490 if (*cp == '+' || *cp == '@') {
1491 advise (NULL, "sorry, no folders allowed!");
1500 file = path (file, TFILE);
1501 if (stat (file, &st) == NOTOK) {
1502 if (errno != ENOENT) {
1503 advise (file, "error on file");
1506 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1513 msgs[msgp++] = "all";
1514 for (msgnum = 0; msgnum < msgp; msgnum++)
1515 if (!m_convert (mp, msgs[msgnum]))
1519 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1520 advise (file, "unable to open");
1523 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1524 if (is_selected (mp, msgnum))
1525 if (pack (file, md, msgnum) == NOTOK)
1527 mbx_close (file, md);
1529 if (mp->hghsel != mp->curmsg)
1530 seq_setcur (mp, mp->lowsel);
1538 pack (char *mailbox, int md, int msgnum)
1542 if (Msgs[msgnum].m_bboard_id == 0)
1545 zp = msh_ready (msgnum, 1);
1546 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1547 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1552 packhak (char **args)
1555 char *cp, *file = NULL;
1557 while ((cp = *args++)) {
1559 switch (smatch (++cp, packswit)) {
1566 if (!(file = *args++) || *file == '-')
1570 if (*cp == '+' || *cp == '@')
1574 file = path (file ? file : "./msgbox", TFILE);
1575 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1582 static struct swit pickswit[] = {
1594 { "cc pattern", 0 },
1596 { "date pattern", 0 },
1598 { "from pattern", 0 },
1600 { "search pattern", 0 },
1602 { "subject pattern", 0 },
1604 { "to pattern", 0 },
1606 { "-othercomponent pattern", 15 },
1608 { "after date", 0 },
1610 { "before date", 0 },
1612 { "datefield field", 5 },
1614 { "sequence name", 0 },
1634 pickcmd (char **args)
1636 int zerosw = 1, msgp = 0, seqp = 0;
1637 int vecp = 0, hi, lo, msgnum;
1638 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1639 char *seqs[NUMATTRS], *vec[MAXARGS];
1642 while ((cp = *args++)) {
1648 switch (smatch (cp, pickswit)) {
1650 ambigsw (cp, pickswit);
1653 fprintf (stderr, "-%s unknown\n", cp);
1656 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1657 print_help (buf, pickswit, 1);
1671 if (!(cp = *args++)) {/* allow -xyz arguments */
1672 advise (NULL, "missing argument to %s", args[-2]);
1678 advise (NULL, "internal error!");
1689 if (!(cp = *args++) || *cp == '-') {
1690 advise (NULL, "missing argument to %s", args[-2]);
1693 if (seqp < NUMATTRS)
1696 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1707 case PIPUSW: /* not implemented */
1714 if (*cp == '+' || *cp == '@') {
1715 advise (NULL, "sorry, no folders allowed!");
1724 msgs[msgp++] = "all";
1725 for (msgnum = 0; msgnum < msgp; msgnum++)
1726 if (!m_convert (mp, msgs[msgnum]))
1731 if (!pcompile (vec, NULL))
1737 for (msgnum = mp->lowsel;
1738 msgnum <= mp->hghsel && !interrupted;
1740 if (is_selected (mp, msgnum)) {
1741 zp = msh_ready (msgnum, 1);
1742 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1743 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1750 unset_selected (mp, msgnum);
1761 if (mp->numsel <= 0) {
1762 advise (NULL, "no messages match specification");
1767 for (seqp = 0; seqs[seqp]; seqp++)
1768 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1771 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1775 static struct swit replswit[] = {
1779 { "noannotate", 0 },
1785 { "draftfolder +folder", 0 },
1787 { "draftmessage msg", 0 },
1789 { "nodraftfolder", 0 },
1791 { "editor editor", 0 },
1795 { "fcc +folder", 0 },
1797 { "filter filterfile", 0 },
1799 { "form formfile", 0 },
1809 { "whatnowproc program", 0 },
1813 { "width columns", 0 },
1821 replcmd (char **args)
1824 char *cp, *msg = NULL;
1825 char buf[BUFSIZ], *vec[MAXARGS];
1828 forkcmd (args, cmd_name);
1832 while ((cp = *args++)) {
1834 switch (smatch (++cp, replswit)) {
1836 ambigsw (cp, replswit);
1839 fprintf (stderr, "-%s unknown\n", cp);
1842 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1843 print_help (buf, replswit, 1);
1846 case REANSW: /* not implemented */
1871 if (!(cp = *args++) || *cp == '-') {
1872 advise (NULL, "missing argument to %s", args[-2]);
1878 if (*cp == '+' || *cp == '@') {
1879 advise (NULL, "sorry, no folders allowed!");
1884 advise (NULL, "only one message at a time!");
1892 vec[vecp++] = "-file";
1896 if (!m_convert (mp, msg))
1900 if (mp->numsel > 1) {
1901 advise (NULL, "only one message at a time!");
1904 process (mp->hghsel, cmd_name, vecp, vec);
1905 seq_setcur (mp, mp->hghsel);
1909 static struct swit rmmswit[] = {
1917 rmmcmd (char **args)
1919 int msgp = 0, msgnum;
1920 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1922 while ((cp = *args++)) {
1924 switch (smatch (++cp, rmmswit)) {
1926 ambigsw (cp, rmmswit);
1929 fprintf (stderr, "-%s unknown\n", cp);
1932 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1933 print_help (buf, rmmswit, 1);
1936 if (*cp == '+' || *cp == '@') {
1937 advise (NULL, "sorry, no folders allowed!");
1945 msgs[msgp++] = "cur";
1946 for (msgnum = 0; msgnum < msgp; msgnum++)
1947 if (!m_convert (mp, msgs[msgnum]))
1958 register int msgnum, vecp;
1960 char buffer[BUFSIZ], *vec[MAXARGS];
1964 if (mp->numsel > MAXARGS - 1) {
1965 advise (NULL, "more than %d messages for %s exec",
1966 MAXARGS - 1, rmmproc);
1970 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1971 if (is_selected (mp, msgnum))
1972 vec[vecp++] = getcpy (m_name (msgnum));
1974 forkcmd (vec, rmmproc);
1975 for (vecp = 0; vec[vecp]; vecp++)
1979 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1980 if (is_selected (mp, msgnum)) {
1981 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1982 if (rename (cp, buffer) == NOTOK)
1983 admonish (buffer, "unable to rename %s to", cp);
1987 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1988 if (is_selected (mp, msgnum)) {
1989 set_deleted (mp, msgnum);
1990 unset_exists (mp, msgnum);
1993 if ((mp->nummsg -= mp->numsel) <= 0) {
1995 admonish (NULL, "no messages remaining in +%s", fmsh);
1997 admonish (NULL, "no messages remaining in %s", mp->foldpath);
1998 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2000 if (mp->lowsel == mp->lowmsg) {
2001 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2002 if (does_exist (mp, msgnum))
2004 mp->lowmsg = msgnum;
2006 if (mp->hghsel == mp->hghmsg) {
2007 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2008 if (does_exist (mp, msgnum))
2010 mp->hghmsg = msgnum;
2013 mp->msgflags |= MODIFIED;
2018 static struct swit scanswit[] = {
2024 { "form formatfile", 0 },
2026 { "format string", 5 },
2032 { "width columns", 0 },
2040 scancmd (char **args)
2042 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2044 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2045 int msgnum, optim, state;
2046 char *cp, *form = NULL, *format = NULL;
2047 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2049 static int s_optim = 0;
2050 static char *s_form = NULL, *s_format = NULL;
2052 while ((cp = *args++)) {
2054 switch (smatch (++cp, scanswit)) {
2056 ambigsw (cp, scanswit);
2059 fprintf (stderr, "-%s unknown\n", cp);
2062 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2063 print_help (buf, scanswit, 1);
2079 if (!(form = *args++) || *form == '-') {
2080 advise (NULL, "missing argument to %s", args[-2]);
2086 if (!(format = *args++) || *format == '-') {
2087 advise (NULL, "missing argument to %s", args[-2]);
2093 if (!(cp = *args++) || *cp == '-') {
2094 advise (NULL, "missing argument to %s", args[-2]);
2100 if (*cp == '+' || *cp == '@') {
2101 advise (NULL, "sorry, no folders allowed!");
2109 msgs[msgp++] = "all";
2110 for (msgnum = 0; msgnum < msgp; msgnum++)
2111 if (!m_convert (mp, msgs[msgnum]))
2115 /* Get new format string */
2116 nfs = new_fs (form, format, FORMAT);
2118 /* force scansbr to (re)compile format */
2125 s_optim = optim = 1;
2126 s_form = form ? getcpy (form) : NULL;
2127 s_format = format ? getcpy (format) : NULL;
2131 optim = equiv (s_form, form) && equiv (s_format, format);
2134 for (msgnum = mp->lowsel;
2135 msgnum <= mp->hghsel && !interrupted;
2137 if (is_selected (mp, msgnum)) {
2138 if (optim && Msgs[msgnum].m_scanl)
2139 printf ("%s", Msgs[msgnum].m_scanl);
2142 zp = msh_ready (msgnum, 0);
2143 switch (state = scan (zp, msgnum, 0, nfs, width,
2144 msgnum == mp->curmsg,
2145 is_unseen (mp, msgnum),
2146 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2147 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2153 Msgs[msgnum].m_scanl = getcpy (scanl);
2157 advise (NULL, "scan() botch (%d)", state);
2161 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2173 static struct swit showswit[] = {
2177 { "form formfile", 4 },
2179 { "moreproc program", 4 },
2181 { "nomoreproc", 3 },
2183 { "length lines", 4 },
2185 { "width columns", 4 },
2187 { "showproc program", 4 },
2189 { "noshowproc", 3 },
2201 showcmd (char **args)
2203 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2204 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2205 char *cp, *proc = showproc, buf[BUFSIZ];
2206 char *msgs[MAXARGS], *vec[MAXARGS];
2208 if (!mh_strcasecmp (cmd_name, "next"))
2211 if (!mh_strcasecmp (cmd_name, "prev"))
2213 while ((cp = *args++)) {
2215 switch (i = smatch (++cp, showswit)) {
2217 ambigsw (cp, showswit);
2224 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2225 cmd_name, mode ? NULL : "[msgs] ");
2226 print_help (buf, showswit, 1);
2234 if (!(cp = *args++) || *cp == '-') {
2235 advise (NULL, "missing argument to %s", args[-2]);
2247 if (!(proc = *args++) || *proc == '-') {
2248 advise (NULL, "missing argument to %s", args[-2]);
2258 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2261 if (*cp == '+' || *cp == '@') {
2262 advise (NULL, "sorry, no folders allowed!");
2268 "usage: %s [switches] [switches for showproc]\n",
2278 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2279 for (msgnum = 0; msgnum < msgp; msgnum++)
2280 if (!m_convert (mp, msgs[msgnum]))
2284 if (!nshow && !getenv ("NOMHNPROC"))
2285 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2286 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2287 proc = showmimeproc;
2288 vec[vecp++] = "-file";
2296 if (strcmp (showproc, "mhl") == 0) {
2302 seqnum = seq_getnum (mp, "unseen");
2303 vec[0] = r1bindex (proc, '/');
2306 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2307 if (is_selected (mp, msgnum)) {
2308 vec[vecp++] = getcpy (m_name (msgnum));
2310 seq_delmsg (mp, "unseen", msgnum);
2313 if (mp->numsel == 1 && headersw)
2315 mhlsbr (vecp, vec, mhl_action);
2316 m_eomsbr ((int (*)()) 0);
2321 for (msgnum = mp->lowsel;
2322 msgnum <= mp->hghsel && !interrupted;
2324 if (is_selected (mp, msgnum)) {
2325 switch (ask (msgnum)) {
2326 case NOTOK: /* QUIT */
2333 if (mp->numsel == 1 && headersw)
2336 copy_message (msgnum, stdout);
2338 process (msgnum, proc, vecp, vec);
2341 seq_delmsg (mp, "unseen", msgnum);
2348 seq_setcur (mp, mp->hghsel);
2355 if (Msgs[msgnum].m_bboard_id == 0)
2358 printf ("(Message %d", msgnum);
2359 if (Msgs[msgnum].m_bboard_id > 0)
2360 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2369 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2374 mhl_action (char *name)
2378 if ((msgnum = m_atoi (name)) < mp->lowmsg
2379 || msgnum > mp->hghmsg
2380 || !does_exist (mp, msgnum))
2384 mhlfp = msh_ready (msgnum, 1);
2386 m_eomsbr (eom_action);
2398 if (mp->numsel == 1 || !interactive || redirected)
2401 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2402 if (mp->lowsel != msgnum)
2404 printf ("Press <return> to list \"%d\"...", msgnum);
2409 read (fileno (stdout), buf, sizeof buf);
2411 if (strchr(buf, '\n') == NULL)
2415 told_to_quit = interrupted = 0;
2430 is_nontext (int msgnum)
2433 unsigned char *bp, *dp;
2435 char buf[BUFSIZ], name[NAMESZ];
2438 if (Msgs[msgnum].m_flags & MHNCHK)
2439 return (Msgs[msgnum].m_flags & MHNYES);
2440 Msgs[msgnum].m_flags |= MHNCHK;
2442 fp = msh_ready (msgnum, 1);
2445 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2450 * Check Content-Type field
2452 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2456 cp = add (buf, NULL);
2457 while (state == FLDPLUS) {
2458 state = m_getfld (state, name, buf, sizeof buf, fp);
2465 for (; isspace (*bp); bp++)
2470 for (bp++, i = 0;;) {
2500 for (dp = bp; istoken (*dp); dp++)
2507 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2510 for (dp++; isspace (*dp); dp++)
2513 if ((result = !uprf (dp, "charset")))
2515 dp += sizeof "charset" - 1;
2516 while (isspace (*dp))
2520 while (isspace (*dp))
2523 if ((bp = strchr(++dp, '"')))
2526 for (bp = dp; *bp; bp++)
2527 if (isspace (*bp)) {
2533 /* Default character set */
2536 /* Check the character set */
2537 result = !check_charset (dp, strlen (dp));
2539 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2549 Msgs[msgnum].m_flags |= MHNYES;
2556 * Check Content-Transfer-Encoding field
2558 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2559 cp = add (buf, NULL);
2560 while (state == FLDPLUS) {
2561 state = m_getfld (state, name, buf, sizeof buf, fp);
2564 for (bp = cp; isspace (*bp); bp++)
2566 for (dp = bp; istoken (*dp); dp++)
2569 result = (mh_strcasecmp (bp, "7bit")
2570 && mh_strcasecmp (bp, "8bit")
2571 && mh_strcasecmp (bp, "binary"));
2575 Msgs[msgnum].m_flags |= MHNYES;
2582 * Just skip the rest of this header
2583 * field and go to next one.
2585 while (state == FLDPLUS)
2586 state = m_getfld (state, name, buf, sizeof(buf), fp);
2590 * We've passed the message header,
2591 * so message is just text.
2599 static struct swit sortswit[] = {
2601 { "datefield field", 0 },
2603 { "textfield field", 0 },
2605 { "notextfield", 0 },
2607 { "limit days", 0 },
2621 sortcmd (char **args)
2623 int msgp = 0, msgnum;
2624 char *cp, *datesw = NULL, *subjsw = NULL;
2625 char buf[BUFSIZ], *msgs[MAXARGS];
2629 forkcmd (args, cmd_name);
2633 while ((cp = *args++)) {
2635 switch (smatch (++cp, sortswit)) {
2637 ambigsw (cp, sortswit);
2640 fprintf (stderr, "-%s unknown\n", cp);
2643 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2644 print_help (buf, sortswit, 1);
2649 advise (NULL, "only one date field at a time!");
2652 if (!(datesw = *args++) || *datesw == '-') {
2653 advise (NULL, "missing argument to %s", args[-2]);
2660 advise (NULL, "only one text field at a time!");
2663 if (!(subjsw = *args++) || *subjsw == '-') {
2664 advise (NULL, "missing argument to %s", args[-2]);
2672 case SOLIMT: /* too hard */
2673 if (!(cp = *args++) || *cp == '-') {
2674 advise (NULL, "missing argument to %s", args[-2]);
2678 case SOVERB: /* not implemented */
2682 if (*cp == '+' || *cp == '@') {
2683 advise (NULL, "sorry, no folders allowed!");
2691 msgs[msgp++] = "all";
2694 for (msgnum = 0; msgnum < msgp; msgnum++)
2695 if (!m_convert (mp, msgs[msgnum]))
2699 twscopy (&tb, dlocaltimenow ());
2701 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2702 if (Msgs[msgnum].m_scanl) {
2703 free (Msgs[msgnum].m_scanl);
2704 Msgs[msgnum].m_scanl = NULL;
2706 if (is_selected (mp, msgnum)) {
2707 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2708 twscopy (&Msgs[msgnum].m_tb,
2709 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2711 else /* m_scaln is already NULL */
2712 twscopy (&Msgs[msgnum].m_tb, &tb);
2713 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2714 if (mp->curmsg == msgnum)
2715 Msgs[msgnum].m_stats |= CUR;
2718 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2719 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2721 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2722 if (subjsw && Msgs[msgnum].m_scanl) {
2723 free (Msgs[msgnum].m_scanl); /* from subjsort */
2724 Msgs[msgnum].m_scanl = NULL;
2726 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2727 if (Msgs[msgnum].m_stats & CUR)
2728 seq_setcur (mp, msgnum);
2731 mp->msgflags |= MODIFIED;
2737 * get_fields - parse message, and get date and subject if needed.
2738 * We'll use the msgp->m_tb tws struct for the date, and overload
2739 * the msgp->m_scanl field with our subject string.
2742 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2744 int state, gotdate = 0;
2745 char *bp, buf[BUFSIZ], name[NAMESZ];
2746 struct tws *tw = (struct tws *) 0;
2749 zp = msh_ready (msgnum, 0);
2750 for (state = FLD;;) {
2751 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2755 if (!mh_strcasecmp (name, datesw)) {
2757 while (state == FLDPLUS) {
2758 state = m_getfld (state, name, buf, sizeof buf, zp);
2761 if ((tw = dparsetime (bp)) == NULL)
2763 "unable to parse %s field in message %d",
2766 twscopy (&(msgp->m_tb), tw);
2768 if (!subjsw) /* not using this, or already done */
2769 break; /* all done! */
2772 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2774 while (state == FLDPLUS) {
2775 state = m_getfld (state, name, buf, sizeof buf, zp);
2778 msgp->m_scanl = sosmash(subjsw, bp);
2780 break; /* date done so we're done */
2782 subjsw = (char *)0;/* subject done, need date */
2784 while (state == FLDPLUS) /* flush this one */
2785 state = m_getfld (state, name, buf, sizeof buf, zp);
2796 admonish (NULL, "format error in message %d", msgnum);
2797 if (msgp->m_scanl) { /* this might need free'd */
2798 free (msgp->m_scanl); /* probably can't use subj anyway */
2799 msgp->m_scanl = NULL;
2804 adios (NULL, "internal error -- you lose");
2809 return OK; /* not an error if subj not found */
2811 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2812 return NOTOK; /* NOTOK means use some other date */
2821 msgsort (struct Msg *a, struct Msg *b)
2823 return twsort (&a->m_tb, &b->m_tb);
2828 subsort (struct Msg *a, struct Msg *b)
2832 if (a->m_scanl && b->m_scanl)
2833 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2836 return twsort (&a->m_tb, &b->m_tb);
2841 * try to make the subject "canonical": delete leading "re:", everything
2842 * but letters & smash letters to lower case.
2845 sosmash (char *subj, char *s)
2847 register char *cp, *dp;
2848 register unsigned char c;
2852 dp = s; /* dst pointer */
2853 if (!mh_strcasecmp (subj, "subject"))
2860 *dp++ = isupper(c) ? tolower(c) : c;
2866 while ((c = *cp++)) {
2868 *dp++ = isupper(c) ? tolower(c) : c;
2878 process (int msgnum, char *proc, int vecp, char **vec)
2880 int child_id, status;
2881 char tmpfil[BUFSIZ];
2886 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2887 context_del (pfolder);
2888 context_replace (pfolder, fmsh);/* update current folder */
2890 context_save (); /* save the context file */
2894 cp = m_mktemp(invo_name, NULL, &out);
2896 /* Try again, but try to create under /tmp */
2898 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2901 advise (NULL, "unable to create temporary file");
2905 copy_message (msgnum, out);
2907 strncpy(tmpfil, cp, sizeof(tmpfil));
2911 switch (child_id = fork ()) {
2913 advise ("fork", "unable to");
2919 SIGNAL (SIGINT, istat);
2920 SIGNAL (SIGQUIT, qstat);
2922 vec[vecp++] = tmpfil;
2926 fprintf (stderr, "unable to exec ");
2931 status = pidXwait (child_id, NULL);
2942 copy_message (int msgnum, FILE *out)
2945 static char buffer[BUFSIZ];
2948 zp = msh_ready (msgnum, 1);
2950 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2951 fputs (buffer, out);
2952 if (interrupted && out == stdout)
2958 while (fgets (buffer, sizeof buffer, zp) != NULL
2959 && pos < Msgs[msgnum].m_stop) {
2960 fputs (buffer, out);
2961 pos += (long) strlen (buffer);
2962 if (interrupted && out == stdout)
2970 copy_digest (int msgnum, FILE *out)
2974 static char buffer[BUFSIZ];
2978 zp = msh_ready (msgnum, 1);
2981 while (fgets (buffer, sizeof buffer, zp) != NULL
2982 && !fmsh && pos < Msgs[msgnum].m_stop) {
2983 if (c == '\n' && *buffer == '-')
2985 fputs (buffer, out);
2986 c = buffer[strlen (buffer) - 1];
2988 pos += (long) strlen (buffer);
2989 if (interrupted && out == stdout)