3 * mshcmds.c -- command handlers in msh
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
11 #include <h/signals.h>
12 #include <h/dropsbr.h>
13 #include <h/fmt_scan.h>
14 #include <h/scansbr.h>
21 #include <h/picksbr.h>
25 static char delim3[] = "-------"; /* from burst.c */
31 * Type for a compare function for qsort. This keeps
34 typedef int (*qsort_comp) (const void *, const void *);
39 void clear_screen (void); /* from termsbr.c */
40 int SOprintf (char *, ...); /* from termsbr.c */
41 int sc_width (void); /* from termsbr.c */
46 static int burst (struct Msg *, int, int, int, int);
47 static void forw (char *, char *, int, char **);
48 static void rmm (void);
49 static void show (int);
50 static int eom_action (int);
51 static FILE *mhl_action (char *);
53 static int is_nontext (int);
54 static int get_fields (char *, char *, int, struct Msg *);
55 static int msgsort (struct Msg *, struct Msg *);
56 static int subsort (struct Msg *, struct Msg *);
57 static char *sosmash (char *, char *);
58 static int process (int, char *, int, char **);
59 static void copy_message (int, FILE *);
60 static void copy_digest (int, FILE *);
63 int mhlsbr (int, char **, FILE *(*)());
66 forkcmd (char **args, char *pgm)
71 vec[0] = r1bindex (pgm, '/');
72 copyip (args, vec + 1, MAXARGS - 1);
75 context_del (pfolder);
76 context_replace (pfolder, fmsh);/* update current folder */
78 context_save (); /* save the context file */
81 switch (child_id = fork ()) {
83 advise ("fork", "unable to");
88 SIGNAL (SIGINT, istat);
89 SIGNAL (SIGQUIT, qstat);
92 fprintf (stderr, "unable to exec ");
97 pidXwait (child_id, NULL);
100 if (fmsh) { /* assume the worst case */
101 mp->msgflags |= MODIFIED;
107 static struct swit distswit[] = {
113 { "draftfolder +folder", 0 },
115 { "draftmessage msg", 0 },
117 { "nodraftfolder", 0 },
119 { "editor editor", 0 },
123 { "form formfile", 0 },
129 { "whatnowproc program", 0 },
131 { "nowhatnowproc", 0 },
139 distcmd (char **args)
142 char *cp, *msg = NULL;
143 char buf[BUFSIZ], *vec[MAXARGS];
146 forkcmd (args, cmd_name);
150 while ((cp = *args++)) {
152 switch (smatch (++cp, distswit)) {
154 ambigsw (cp, distswit);
157 fprintf (stderr, "-%s unknown\n", cp);
160 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
161 print_help (buf, distswit, 1);
164 case DIANSW: /* not implemented */
182 if (!(cp = *args++) || *cp == '-') {
183 advise (NULL, "missing argument to %s", args[-2]);
189 if (*cp == '+' || *cp == '@') {
190 advise (NULL, "sorry, no folders allowed!");
195 advise (NULL, "only one message at a time!");
203 vec[vecp++] = "-file";
207 if (!m_convert (mp, msg))
211 if (mp->numsel > 1) {
212 advise (NULL, "only one message at a time!");
215 process (mp->hghsel, cmd_name, vecp, vec);
216 seq_setcur (mp, mp->hghsel);
220 static struct swit explswit[] = {
240 explcmd (char **args)
242 int inplace = 0, quietsw = 0, verbosw = 0;
243 int msgp = 0, hi, msgnum;
244 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
248 forkcmd (args, cmd_name);
252 while ((cp = *args++)) {
254 switch (smatch (++cp, explswit)) {
256 ambigsw (cp, explswit);
259 fprintf (stderr, "-%s unknown\n", cp);
262 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
263 print_help (buf, explswit, 1);
285 if (*cp == '+' || *cp == '@') {
286 advise (NULL, "sorry, no folders allowed!");
294 msgs[msgp++] = "cur";
295 for (msgnum = 0; msgnum < msgp; msgnum++)
296 if (!m_convert (mp, msgs[msgnum]))
300 smsgs = (struct Msg *)
301 calloc ((size_t) (MAXFOLDER + 2), sizeof *smsgs);
303 adios (NULL, "unable to allocate folder storage");
307 for (msgnum = mp->lowsel;
308 msgnum <= mp->hghsel && !interrupted;
310 if (is_selected (mp, msgnum))
311 if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK)
314 free ((char *) smsgs);
317 seq_setcur (mp, mp->lowsel);
319 if (hi <= mp->hghmsg)
322 mp->msgflags |= MODIFIED;
328 burst (struct Msg *smsgs, int msgnum, int inplace, int quietsw, int verbosw)
330 int i, j, ld3, wasdlm, msgp;
332 char c, buffer[BUFSIZ];
335 ld3 = strlen (delim3);
337 if (Msgs[msgnum].m_scanl) {
338 free (Msgs[msgnum].m_scanl);
339 Msgs[msgnum].m_scanl = NULL;
342 pos = ftell (zp = msh_ready (msgnum, 1));
343 for (msgp = 0; msgp <= MAXFOLDER;) {
344 while (fgets (buffer, sizeof buffer, zp) != NULL
346 && pos < Msgs[msgnum].m_stop)
347 pos += (long) strlen (buffer);
348 if (feof (zp) || pos >= Msgs[msgnum].m_stop)
350 fseek (zp, pos, SEEK_SET);
351 smsgs[msgp].m_start = pos;
354 pos < Msgs[msgnum].m_stop
355 && fgets (buffer, sizeof buffer, zp) != NULL;
357 if (strncmp (buffer, delim3, ld3) == 0
358 && (msgp == 1 || c == '\n')
359 && peekc (zp) == '\n')
362 pos += (long) strlen (buffer);
364 wasdlm = strncmp (buffer, delim3, ld3) == 0;
365 if (smsgs[msgp].m_start != pos)
366 smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos;
367 if (feof (zp) || pos >= Msgs[msgnum].m_stop) {
369 smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1);
372 pos += (long) strlen (buffer);
375 switch (msgp--) { /* toss "End of XXX Digest" */
377 adios (NULL, "burst() botch -- you lose big");
381 printf ("message %d not in digest format\n", msgnum);
386 printf ("%d message%s exploded from digest %d\n",
387 msgp, msgp != 1 ? "s" : "", msgnum);
391 if ((i = msgp + mp->hghmsg) > MAXFOLDER) {
392 advise (NULL, "more than %d messages", MAXFOLDER);
395 if (!(mp = folder_realloc (mp, mp->lowoff, i)))
396 adios (NULL, "unable to allocate folder storage");
401 if (mp->hghsel > msgnum)
405 for (i = mp->hghmsg; j > msgnum; i--, j--) {
407 printf ("message %d becomes message %d\n", j, i);
409 Msgs[i].m_bboard_id = Msgs[j].m_bboard_id;
410 Msgs[i].m_top = Msgs[j].m_top;
411 Msgs[i].m_start = Msgs[j].m_start;
412 Msgs[i].m_stop = Msgs[j].m_stop;
413 Msgs[i].m_scanl = NULL;
414 if (Msgs[j].m_scanl) {
415 free (Msgs[j].m_scanl);
416 Msgs[j].m_scanl = NULL;
418 copy_msg_flags (mp, i, j);
421 if (Msgs[msgnum].m_bboard_id == 0)
424 unset_selected (mp, msgnum);
425 i = inplace ? msgnum + msgp : mp->hghmsg;
426 for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) {
427 if (verbosw && i != msgnum)
428 printf ("message %d of digest %d becomes message %d\n",
431 Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id;
432 Msgs[i].m_top = Msgs[j].m_top;
433 Msgs[i].m_start = smsgs[j].m_start;
434 Msgs[i].m_stop = smsgs[j].m_stop;
435 Msgs[i].m_scanl = NULL;
436 copy_msg_flags (mp, i, msgnum);
443 static struct swit fileswit[] = {
455 { "src +folder", 0 },
459 { "rmmproc program", 0 },
469 filecmd (char **args)
471 int linksw = 0, msgp = 0;
472 int vecp = 1, i, msgnum;
473 char *cp, buf[BUFSIZ];
474 char *msgs[MAXARGS], *vec[MAXARGS];
477 forkcmd (args, cmd_name);
481 while ((cp = *args++)) {
483 switch (i = smatch (++cp, fileswit)) {
485 ambigsw (cp, fileswit);
488 fprintf (stderr, "-%s unknown\n", cp);
491 snprintf (buf, sizeof(buf), "%s +folder... [msgs] [switches]", cmd_name);
492 print_help (buf, fileswit, 1);
511 advise (NULL, "sorry, -%s not allowed!", fileswit[i].sw);
514 if (*cp == '+' || *cp == '@')
521 vec[vecp++] = "-file";
524 msgs[msgp++] = "cur";
525 for (msgnum = 0; msgnum < msgp; msgnum++)
526 if (!m_convert (mp, msgs[msgnum]))
531 for (msgnum = mp->lowsel;
532 msgnum <= mp->hghsel && !interrupted;
534 if (is_selected (mp, msgnum))
535 if (process (msgnum, fileproc, vecp, vec)) {
536 unset_selected (mp, msgnum);
540 if (mp->numsel != mp->nummsg || linksw)
541 seq_setcur (mp, mp->hghsel);
548 filehak (char **args)
550 int result, vecp = 0;
551 char *cp, *cwd, *vec[MAXARGS];
553 while ((cp = *args++)) {
555 switch (smatch (++cp, fileswit)) {
572 if (*cp == '+' || *cp == '@')
579 for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) {
581 cwd = getcpy (pwd ());
582 chdir (m_maildir (""));
584 if (access (m_maildir (cp), F_OK) == NOTOK)
595 static struct swit foldswit[] = {
633 foldcmd (char **args)
635 int fastsw = 0, headersw = 0, packsw = 0;
637 char *cp, *folder = NULL, *msg = NULL;
638 char buf[BUFSIZ], **vec = args;
643 while ((cp = *args++)) {
645 switch (smatch (++cp, foldswit)) {
647 ambigsw (cp, foldswit);
650 fprintf (stderr, "-%s unknown\n", cp);
653 snprintf (buf, sizeof(buf), "%s [+folder] [msg] [switches]", cmd_name);
654 print_help (buf, foldswit, 1);
657 case FLALSW: /* not implemented */
687 if (*cp == '+' || *cp == '@') {
689 advise (NULL, "only one folder at a time!\n");
693 folder = fmsh ? pluspath (cp)
698 advise (NULL, "only one message at a time!\n");
707 advise (NULL, "null folder names are not permitted");
711 if (access (m_maildir (folder), R_OK) == NOTOK) {
712 advise (folder, "unable to read");
717 strncpy (buf, folder, sizeof(buf));
718 if (expand (buf) == NOTOK)
721 if (access (folder, R_OK) == NOTOK) {
722 advise (folder, "unable to read");
737 if (!m_convert (mp, msg))
741 if (mp->numsel > 1) {
742 advise (NULL, "only one message at a time!");
745 seq_setcur (mp, mp->hghsel);
750 forkcmd (vec, cmd_name);
754 if (mp->lowoff > 1 && !(mp = folder_realloc (mp, 1, mp->hghmsg)))
755 adios (NULL, "unable to allocate folder storage");
757 for (msgnum = mp->lowmsg, hole = 1; msgnum <= mp->hghmsg; msgnum++)
758 if (does_exist (mp, msgnum)) {
759 if (msgnum != hole) {
760 Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id;
761 Msgs[hole].m_top = Msgs[msgnum].m_top;
762 Msgs[hole].m_start = Msgs[msgnum].m_start;
763 Msgs[hole].m_stop = Msgs[msgnum].m_stop;
764 Msgs[hole].m_scanl = NULL;
765 if (Msgs[msgnum].m_scanl) {
766 free (Msgs[msgnum].m_scanl);
767 Msgs[msgnum].m_scanl = NULL;
769 copy_msg_flags (mp, hole, msgnum);
770 if (mp->curmsg == msgnum)
771 seq_setcur (mp, hole);
775 if (mp->nummsg > 0) {
777 mp->hghmsg = hole - 1;
779 mp->msgflags |= MODIFIED;
785 printf ("%s\n", fmsh ? fmsh : mp->foldpath);
788 printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n",
789 DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "",
791 printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp->foldpath);
793 /* check for empty folder */
794 if (mp->nummsg == 0) {
795 printf ("has no messages%*s",
796 mp->msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, "");
798 printf ("has %*d message%s (%*d-%*d)",
799 DMAXFOLDER, mp->nummsg, mp->nummsg != 1 ? "s" : "",
800 DMAXFOLDER, mp->lowmsg, DMAXFOLDER, mp->hghmsg);
801 if (mp->curmsg >= mp->lowmsg
802 && mp->curmsg <= mp->hghmsg)
803 printf ("; cur=%*d", DMAXFOLDER, mp->curmsg);
810 static struct swit forwswit[] = {
816 { "draftfolder +folder", 0 },
818 { "draftmessage msg", 0 },
820 { "nodraftfolder", 0 },
822 { "editor editor", 0 },
826 { "filter filterfile", 0 },
828 { "form formfile", 0 },
842 { "whatnowproc program", 0 },
852 forwcmd (char **args)
854 int msgp = 0, vecp = 1, msgnum;
855 char *cp, *filter = NULL, buf[BUFSIZ];
856 char *msgs[MAXARGS], *vec[MAXARGS];
861 forkcmd (args, cmd_name);
865 while ((cp = *args++)) {
867 switch (smatch (++cp, forwswit)) {
869 ambigsw (cp, forwswit);
872 fprintf (stderr, "-%s unknown\n", cp);
875 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
876 print_help (buf, forwswit, 1);
879 case FOANSW: /* not implemented */
899 if (!(cp = *args++) || *cp == '-') {
900 advise (NULL, "missing argument to %s", args[-2]);
906 if (!(filter = *args++) || *filter == '-') {
907 advise (NULL, "missing argument to %s", args[-2]);
912 if (access (filter = myfilter, R_OK) == NOTOK) {
913 advise (filter, "unable to read default filter file");
921 if (*cp == '+' || *cp == '@') {
922 advise (NULL, "sorry, no folders allowed!");
929 /* foil search of .mh_profile */
930 snprintf (buf, sizeof(buf), "%sXXXXXX", invo_name);
932 tfile = m_mktemp(buf, NULL, NULL);
933 if (tfile == NULL) adios("forwcmd", "unable to create temporary file");
934 strncpy (tmpfil, tfile, sizeof(tmpfil));
937 vec[vecp++] = "-file";
940 msgs[msgp++] = "cur";
941 for (msgnum = 0; msgnum < msgp; msgnum++)
942 if (!m_convert (mp, msgs[msgnum]))
947 strncpy (buf, filter, sizeof(buf));
948 if (expand (buf) == NOTOK)
950 if (access (filter = getcpy (etcpath (buf)), R_OK) == NOTOK) {
951 advise (filter, "unable to read");
956 forw (cmd_name, filter, vecp, vec);
957 seq_setcur (mp, mp->hghsel);
964 forw (char *proc, char *filter, int vecp, char **vec)
966 int i, child_id, msgnum, msgcnt;
967 char tmpfil[BUFSIZ], *args[MAXARGS];
971 tfile = m_mktemp2(NULL, invo_name, NULL, NULL);
972 if (tfile == NULL) adios("forw", "unable to create temporary file");
973 strncpy (tmpfil, tfile, sizeof(tmpfil));
977 switch (child_id = fork ()) {
979 advise ("fork", "unable to");
982 case OK: /* "trust me" */
983 if (freopen (tmpfil, "w", stdout) == NULL) {
984 fprintf (stderr, "unable to create ");
988 args[0] = r1bindex (mhlproc, '/');
990 args[i++] = "-forwall";
993 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
994 if (is_selected (mp, msgnum))
995 args[i++] = getcpy (m_name (msgnum));
997 mhlsbr (i, args, mhl_action);
998 m_eomsbr ((int (*) ()) 0);
1003 if (pidXwait (child_id, NULL))
1008 if ((out = fopen (tmpfil, "w")) == NULL) {
1009 advise (tmpfil, "unable to create temporary file");
1014 for (msgnum = mp->lowsel;
1015 msgnum <= mp->hghsel && !interrupted;
1017 if (is_selected (mp, msgnum)) {
1018 fprintf (out, "\n\n-------");
1019 if (msgnum == mp->lowsel)
1020 fprintf (out, " Forwarded Message%s",
1021 mp->numsel > 1 ? "s" : "");
1023 fprintf (out, " Message %d", msgcnt);
1024 fprintf (out, "\n\n");
1025 copy_digest (msgnum, out);
1029 fprintf (out, "\n\n------- End of Forwarded Message%s\n",
1030 mp->numsel > 1 ? "s" : "");
1036 switch (child_id = fork ()) {
1038 advise ("fork", "unable to");
1043 SIGNAL (SIGINT, istat);
1044 SIGNAL (SIGQUIT, qstat);
1046 vec[vecp++] = tmpfil;
1050 fprintf (stderr, "unable to exec ");
1055 pidXwait (child_id, NULL);
1063 static char *hlpmsg[] = {
1064 "The %s program emulates many of the commands found in the nmh",
1065 "system. Instead of operating on nmh folders, commands to %s concern",
1068 "To see the list of commands available, just type a ``?'' followed by",
1069 "the RETURN key. To find out what switches each command takes, type",
1070 "the name of the command followed by ``-help''. To leave %s, use the",
1071 "``quit'' command.",
1073 "Although a lot of nmh commands are found in %s, not all are fully",
1074 "implemented. %s will always recognize all legal switches for a",
1075 "given command though, and will let you know when you ask for an",
1076 "option that it is unable to perform.",
1078 "Running %s is fun, but using nmh from your shell is far superior.",
1079 "After you have familiarized yourself with the nmh style by using %s,",
1080 "you should try using nmh from the shell. You can still use %s for",
1081 "message files that aren't in nmh format, such as BBoard files.",
1087 helpcmd (char **args)
1093 for (i = 0; hlpmsg[i]; i++) {
1094 printf (hlpmsg[i], invo_name);
1100 static struct swit markswit[] = {
1108 { "sequence name", 0 },
1126 markcmd (char **args)
1128 int addsw = 0, deletesw = 0, debugsw = 0;
1129 int listsw = 0, zerosw = 0;
1131 int msgp = 0, msgnum;
1132 char *cp, buf[BUFSIZ];
1133 char *seqs[NUMATTRS + 1], *msgs[MAXARGS];
1135 while ((cp = *args++)) {
1137 switch (smatch (++cp, markswit)) {
1139 ambigsw (cp, markswit);
1142 fprintf (stderr, "-%s unknown\n", cp);
1145 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1146 print_help (buf, markswit, 1);
1151 deletesw = listsw = 0;
1159 addsw = deletesw = 0;
1163 if (!(cp = *args++) || *cp == '-') {
1164 advise (NULL, "missing argument to %s", args[-2]);
1167 if (seqp < NUMATTRS)
1170 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1175 case MPUBSW: /* not implemented */
1191 if (*cp == '+' || *cp == '@') {
1192 advise (NULL, "sorry, no folders allowed!");
1199 if (!addsw && !deletesw && !listsw) {
1206 seqs[seqp++] = "unseen";
1210 msgs[msgp++] = "all";
1215 msgs[msgp++] = listsw ? "all" :"cur";
1216 for (msgnum = 0; msgnum < msgp; msgnum++)
1217 if (!m_convert (mp, msgs[msgnum]))
1221 printf ("invo_name=%s mypath=%s defpath=%s\n",
1222 invo_name, mypath, defpath);
1223 printf ("ctxpath=%s context flags=%s\n",
1224 ctxpath, snprintb (buf, sizeof(buf), (unsigned) ctxflags, DBITS));
1225 printf ("foldpath=%s flags=%s\n",
1227 snprintb (buf, sizeof(buf), (unsigned) mp->msgflags, FBITS));
1228 printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n",
1229 mp->hghmsg, mp->lowmsg, mp->nummsg, mp->curmsg);
1230 printf ("lowsel=%d hghsel=%d numsel=%d\n",
1231 mp->lowsel, mp->hghsel, mp->numsel);
1232 printf ("lowoff=%d hghoff=%d\n", mp->lowoff, mp->hghoff);
1235 if (seqp == 0 && (addsw || deletesw)) {
1236 advise (NULL, "-%s requires at least one -sequence argument",
1237 addsw ? "add" : "delete");
1243 for (seqp = 0; seqs[seqp]; seqp++)
1244 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1249 for (seqp = 0; seqs[seqp]; seqp++)
1250 if (!seq_delsel (mp, seqs[seqp], 0, zerosw))
1254 /* Listing messages in sequences */
1257 /* list the given sequences */
1258 for (seqp = 0; seqs[seqp]; seqp++)
1259 seq_print (mp, seqs[seqp]);
1261 /* else list them all */
1267 for (msgnum = mp->lowsel;
1268 msgnum <= mp->hghsel && !interrupted;
1270 if (is_selected (mp, msgnum)) {
1271 printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n",
1274 Msgs[msgnum].m_bboard_id,
1276 (long) Msgs[msgnum].m_start,
1277 (long) Msgs[msgnum].m_stop,
1278 snprintb (buf, sizeof(buf),
1279 (unsigned) mp->msgstats[msgnum - mp->lowoff],
1281 if (Msgs[msgnum].m_scanl)
1282 printf ("%s", Msgs[msgnum].m_scanl);
1288 static struct swit mhnswit[] = {
1291 #define MHNNAUTOSW 1
1293 #define MHNDEBUGSW 2
1295 #define MHNEBCDICSW 3
1296 { "ebcdicsafe", 0 },
1297 #define MHNNEBCDICSW 4
1298 { "noebcdicsafe", 0 },
1300 { "form formfile", 4 },
1303 #define MHNNHEADSW 7
1307 #define MHNNLISTSW 9
1309 #define MHNPARTSW 10
1310 { "part number", 0 },
1311 #define MHNSIZESW 11
1313 #define MHNNSIZESW 12
1314 { "norealsize", 0 },
1315 #define MHNRFC934SW 13
1316 { "rfc934mode", 0 },
1317 #define MHNNRFC934SW 14
1318 { "norfc934mode", 0 },
1319 #define MHNSERIALSW 15
1320 { "serialonly", 0 },
1321 #define MHNNSERIALSW 16
1322 { "noserialonly", 0 },
1323 #define MHNSHOWSW 17
1325 #define MHNNSHOWSW 18
1327 #define MHNSTORESW 19
1329 #define MHNNSTORESW 20
1331 #define MHNTYPESW 21
1332 { "type content", 0 },
1333 #define MHNVERBSW 22
1335 #define MHNNVERBSW 23
1337 #define MHNHELPSW 24
1339 #define MHNPROGSW 25
1340 { "moreproc program", -4 },
1341 #define MHNNPROGSW 26
1342 { "nomoreproc", -3 },
1344 { "length lines", -4 },
1346 { "width columns", -4 },
1352 mhncmd (char **args)
1354 int msgp = 0, vecp = 1;
1356 char *cp, buf[BUFSIZ];
1357 char *msgs[MAXARGS], *vec[MAXARGS];
1360 forkcmd (args, cmd_name);
1363 while ((cp = *args++)) {
1365 switch (smatch (++cp, mhnswit)) {
1367 ambigsw (cp, mhnswit);
1370 fprintf (stderr, "-%s unknown\n", cp);
1373 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1374 print_help (buf, mhnswit, 1);
1409 if (!(cp = *args++) || *cp == '-') {
1410 advise (NULL, "missing argument to %s", args[-2]);
1417 if (*cp == '+' || *cp == '@') {
1418 advise (NULL, "sorry, no folders allowed!");
1426 vec[vecp++] = "-file";
1429 msgs[msgp++] = "cur";
1430 for (msgnum = 0; msgnum < msgp; msgnum++)
1431 if (!m_convert (mp, msgs[msgnum]))
1436 for (msgnum = mp->lowsel;
1437 msgnum <= mp->hghsel && !interrupted;
1439 if (is_selected (mp, msgnum))
1440 if (process (msgnum, cmd_name, vecp, vec)) {
1441 unset_selected (mp, msgnum);
1445 seq_setcur (mp, mp->hghsel);
1449 static struct swit packswit[] = {
1457 static int mbx_style = MMDF_FORMAT;
1460 packcmd (char **args)
1462 int msgp = 0, md, msgnum;
1463 char *cp, *file = NULL;
1464 char buf[BUFSIZ], *msgs[MAXARGS];
1468 forkcmd (args, cmd_name);
1472 while ((cp = *args++)) {
1474 switch (smatch (++cp, packswit)) {
1476 ambigsw (cp, packswit);
1479 fprintf (stderr, "-%s unknown\n", cp);
1482 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1483 print_help (buf, packswit, 1);
1487 if (!(file = *args++) || *file == '-') {
1488 advise (NULL, "missing argument to %s", args[-2]);
1493 if (*cp == '+' || *cp == '@') {
1494 advise (NULL, "sorry, no folders allowed!");
1503 file = path (file, TFILE);
1504 if (stat (file, &st) == NOTOK) {
1505 if (errno != ENOENT) {
1506 advise (file, "error on file");
1509 md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULL));
1516 msgs[msgp++] = "all";
1517 for (msgnum = 0; msgnum < msgp; msgnum++)
1518 if (!m_convert (mp, msgs[msgnum]))
1522 if ((md = mbx_open (file, mbx_style, getuid (), getgid (), m_gmprot ())) == NOTOK) {
1523 advise (file, "unable to open");
1526 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1527 if (is_selected (mp, msgnum))
1528 if (pack (file, md, msgnum) == NOTOK)
1530 mbx_close (file, md);
1532 if (mp->hghsel != mp->curmsg)
1533 seq_setcur (mp, mp->lowsel);
1541 pack (char *mailbox, int md, int msgnum)
1545 if (Msgs[msgnum].m_bboard_id == 0)
1548 zp = msh_ready (msgnum, 1);
1549 return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id,
1550 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1);
1555 packhak (char **args)
1558 char *cp, *file = NULL;
1560 while ((cp = *args++)) {
1562 switch (smatch (++cp, packswit)) {
1569 if (!(file = *args++) || *file == '-')
1573 if (*cp == '+' || *cp == '@')
1577 file = path (file ? file : "./msgbox", TFILE);
1578 result = access (file, F_OK) == NOTOK ? OK : NOTOK;
1585 static struct swit pickswit[] = {
1597 { "cc pattern", 0 },
1599 { "date pattern", 0 },
1601 { "from pattern", 0 },
1603 { "search pattern", 0 },
1605 { "subject pattern", 0 },
1607 { "to pattern", 0 },
1609 { "-othercomponent pattern", 15 },
1611 { "after date", 0 },
1613 { "before date", 0 },
1615 { "datefield field", 5 },
1617 { "sequence name", 0 },
1637 pickcmd (char **args)
1639 int zerosw = 1, msgp = 0;
1641 int vecp = 0, hi, lo, msgnum;
1642 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1643 char *seqs[NUMATTRS], *vec[MAXARGS];
1646 while ((cp = *args++)) {
1652 switch (smatch (cp, pickswit)) {
1654 ambigsw (cp, pickswit);
1657 fprintf (stderr, "-%s unknown\n", cp);
1660 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1661 print_help (buf, pickswit, 1);
1675 if (!(cp = *args++)) {/* allow -xyz arguments */
1676 advise (NULL, "missing argument to %s", args[-2]);
1682 advise (NULL, "internal error!");
1693 if (!(cp = *args++) || *cp == '-') {
1694 advise (NULL, "missing argument to %s", args[-2]);
1697 if (seqp < NUMATTRS)
1700 advise (NULL, "only %d sequences allowed!", NUMATTRS);
1711 case PIPUSW: /* not implemented */
1718 if (*cp == '+' || *cp == '@') {
1719 advise (NULL, "sorry, no folders allowed!");
1728 msgs[msgp++] = "all";
1729 for (msgnum = 0; msgnum < msgp; msgnum++)
1730 if (!m_convert (mp, msgs[msgnum]))
1735 if (!pcompile (vec, NULL))
1741 for (msgnum = mp->lowsel;
1742 msgnum <= mp->hghsel && !interrupted;
1744 if (is_selected (mp, msgnum)) {
1745 zp = msh_ready (msgnum, 1);
1746 if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start,
1747 fmsh ? 0L : Msgs[msgnum].m_stop)) {
1754 unset_selected (mp, msgnum);
1765 if (mp->numsel <= 0) {
1766 advise (NULL, "no messages match specification");
1771 for (seqp = 0; seqs[seqp]; seqp++)
1772 if (!seq_addsel (mp, seqs[seqp], 0, zerosw))
1775 printf ("%d hit%s\n", mp->numsel, mp->numsel == 1 ? "" : "s");
1779 static struct swit replswit[] = {
1783 { "noannotate", 0 },
1789 { "draftfolder +folder", 0 },
1791 { "draftmessage msg", 0 },
1793 { "nodraftfolder", 0 },
1795 { "editor editor", 0 },
1799 { "fcc +folder", 0 },
1801 { "filter filterfile", 0 },
1803 { "form formfile", 0 },
1813 { "whatnowproc program", 0 },
1817 { "width columns", 0 },
1825 replcmd (char **args)
1828 char *cp, *msg = NULL;
1829 char buf[BUFSIZ], *vec[MAXARGS];
1832 forkcmd (args, cmd_name);
1836 while ((cp = *args++)) {
1838 switch (smatch (++cp, replswit)) {
1840 ambigsw (cp, replswit);
1843 fprintf (stderr, "-%s unknown\n", cp);
1846 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1847 print_help (buf, replswit, 1);
1850 case REANSW: /* not implemented */
1875 if (!(cp = *args++) || *cp == '-') {
1876 advise (NULL, "missing argument to %s", args[-2]);
1882 if (*cp == '+' || *cp == '@') {
1883 advise (NULL, "sorry, no folders allowed!");
1888 advise (NULL, "only one message at a time!");
1896 vec[vecp++] = "-file";
1900 if (!m_convert (mp, msg))
1904 if (mp->numsel > 1) {
1905 advise (NULL, "only one message at a time!");
1908 process (mp->hghsel, cmd_name, vecp, vec);
1909 seq_setcur (mp, mp->hghsel);
1913 static struct swit rmmswit[] = {
1921 rmmcmd (char **args)
1923 int msgp = 0, msgnum;
1924 char *cp, buf[BUFSIZ], *msgs[MAXARGS];
1926 while ((cp = *args++)) {
1928 switch (smatch (++cp, rmmswit)) {
1930 ambigsw (cp, rmmswit);
1933 fprintf (stderr, "-%s unknown\n", cp);
1936 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
1937 print_help (buf, rmmswit, 1);
1940 if (*cp == '+' || *cp == '@') {
1941 advise (NULL, "sorry, no folders allowed!");
1949 msgs[msgp++] = "cur";
1950 for (msgnum = 0; msgnum < msgp; msgnum++)
1951 if (!m_convert (mp, msgs[msgnum]))
1962 register int msgnum, vecp;
1964 char buffer[BUFSIZ], *vec[MAXARGS];
1968 if (mp->numsel > MAXARGS - 1) {
1969 advise (NULL, "more than %d messages for %s exec",
1970 MAXARGS - 1, rmmproc);
1974 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1975 if (is_selected (mp, msgnum))
1976 vec[vecp++] = getcpy (m_name (msgnum));
1978 forkcmd (vec, rmmproc);
1979 for (vecp = 0; vec[vecp]; vecp++)
1983 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1984 if (is_selected (mp, msgnum)) {
1985 strncpy (buffer, m_backup (cp = m_name (msgnum)), sizeof(buffer));
1986 if (rename (cp, buffer) == NOTOK)
1987 admonish (buffer, "unable to rename %s to", cp);
1991 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
1992 if (is_selected (mp, msgnum)) {
1993 set_deleted (mp, msgnum);
1994 unset_exists (mp, msgnum);
1997 if ((mp->nummsg -= mp->numsel) <= 0) {
1999 admonish (NULL, "no messages remaining in +%s", fmsh);
2001 admonish (NULL, "no messages remaining in %s", mp->foldpath);
2002 mp->lowmsg = mp->hghmsg = mp->nummsg = 0;
2004 if (mp->lowsel == mp->lowmsg) {
2005 for (msgnum = mp->lowmsg + 1; msgnum <= mp->hghmsg; msgnum++)
2006 if (does_exist (mp, msgnum))
2008 mp->lowmsg = msgnum;
2010 if (mp->hghsel == mp->hghmsg) {
2011 for (msgnum = mp->hghmsg - 1; msgnum >= mp->lowmsg; msgnum--)
2012 if (does_exist (mp, msgnum))
2014 mp->hghmsg = msgnum;
2017 mp->msgflags |= MODIFIED;
2022 static struct swit scanswit[] = {
2028 { "form formatfile", 0 },
2030 { "format string", 5 },
2036 { "width columns", 0 },
2044 scancmd (char **args)
2046 #define equiv(a,b) (a ? b && !strcmp (a, b) : !b)
2048 int clearsw = 0, headersw = 0, width = 0, msgp = 0;
2049 int msgnum, optim, state;
2050 char *cp, *form = NULL, *format = NULL;
2051 char buf[BUFSIZ], *nfs, *msgs[MAXARGS];
2053 static int s_optim = 0;
2054 static char *s_form = NULL, *s_format = NULL;
2056 while ((cp = *args++)) {
2058 switch (smatch (++cp, scanswit)) {
2060 ambigsw (cp, scanswit);
2063 fprintf (stderr, "-%s unknown\n", cp);
2066 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2067 print_help (buf, scanswit, 1);
2083 if (!(form = *args++) || *form == '-') {
2084 advise (NULL, "missing argument to %s", args[-2]);
2090 if (!(format = *args++) || *format == '-') {
2091 advise (NULL, "missing argument to %s", args[-2]);
2097 if (!(cp = *args++) || *cp == '-') {
2098 advise (NULL, "missing argument to %s", args[-2]);
2104 if (*cp == '+' || *cp == '@') {
2105 advise (NULL, "sorry, no folders allowed!");
2113 msgs[msgp++] = "all";
2114 for (msgnum = 0; msgnum < msgp; msgnum++)
2115 if (!m_convert (mp, msgs[msgnum]))
2119 /* Get new format string */
2120 nfs = new_fs (form, format, FORMAT);
2122 /* force scansbr to (re)compile format */
2129 s_optim = optim = 1;
2130 s_form = form ? getcpy (form) : NULL;
2131 s_format = format ? getcpy (format) : NULL;
2135 optim = equiv (s_form, form) && equiv (s_format, format);
2138 for (msgnum = mp->lowsel;
2139 msgnum <= mp->hghsel && !interrupted;
2141 if (is_selected (mp, msgnum)) {
2142 if (optim && Msgs[msgnum].m_scanl)
2143 printf ("%s", Msgs[msgnum].m_scanl);
2146 zp = msh_ready (msgnum, 0);
2147 switch (state = scan (zp, msgnum, 0, nfs, width,
2148 msgnum == mp->curmsg,
2149 is_unseen (mp, msgnum),
2150 headersw ? (fmsh ? fmsh : mp->foldpath) : NULL,
2151 fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start),
2157 Msgs[msgnum].m_scanl = getcpy (scanl);
2161 advise (NULL, "scan() botch (%d)", state);
2165 printf ("%*d empty\n", DMAXFOLDER, msgnum);
2177 static struct swit showswit[] = {
2181 { "form formfile", 4 },
2183 { "moreproc program", 4 },
2185 { "nomoreproc", 3 },
2187 { "length lines", 4 },
2189 { "width columns", 4 },
2191 { "showproc program", 4 },
2193 { "noshowproc", 3 },
2205 showcmd (char **args)
2207 int headersw = 1, nshow = 0, msgp = 0, vecp = 1;
2208 int mhl = 0, seqnum = -1, mode = 0, i, msgnum;
2209 char *cp, *proc = showproc, buf[BUFSIZ];
2210 char *msgs[MAXARGS], *vec[MAXARGS];
2212 if (!mh_strcasecmp (cmd_name, "next"))
2215 if (!mh_strcasecmp (cmd_name, "prev"))
2217 while ((cp = *args++)) {
2219 switch (i = smatch (++cp, showswit)) {
2221 ambigsw (cp, showswit);
2228 snprintf (buf, sizeof(buf), "%s %s[switches] [switches for showproc]",
2229 cmd_name, mode ? NULL : "[msgs] ");
2230 print_help (buf, showswit, 1);
2238 if (!(cp = *args++) || *cp == '-') {
2239 advise (NULL, "missing argument to %s", args[-2]);
2251 if (!(proc = *args++) || *proc == '-') {
2252 advise (NULL, "missing argument to %s", args[-2]);
2262 advise (NULL, "sorry, -%s not allowed!", showswit[i].sw);
2265 if (*cp == '+' || *cp == '@') {
2266 advise (NULL, "sorry, no folders allowed!");
2272 "usage: %s [switches] [switches for showproc]\n",
2282 msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur";
2283 for (msgnum = 0; msgnum < msgp; msgnum++)
2284 if (!m_convert (mp, msgs[msgnum]))
2288 if (!nshow && !getenv ("NOMHNPROC"))
2289 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2290 if (is_selected (mp, msgnum) && is_nontext (msgnum)) {
2291 proc = showmimeproc;
2292 vec[vecp++] = "-file";
2300 if (strcmp (showproc, "mhl") == 0) {
2306 seqnum = seq_getnum (mp, "unseen");
2307 vec[0] = r1bindex (proc, '/');
2310 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++)
2311 if (is_selected (mp, msgnum)) {
2312 vec[vecp++] = getcpy (m_name (msgnum));
2314 seq_delmsg (mp, "unseen", msgnum);
2317 if (mp->numsel == 1 && headersw)
2319 mhlsbr (vecp, vec, mhl_action);
2320 m_eomsbr ((int (*)()) 0);
2325 for (msgnum = mp->lowsel;
2326 msgnum <= mp->hghsel && !interrupted;
2328 if (is_selected (mp, msgnum)) {
2329 switch (ask (msgnum)) {
2330 case NOTOK: /* QUIT */
2337 if (mp->numsel == 1 && headersw)
2340 copy_message (msgnum, stdout);
2342 process (msgnum, proc, vecp, vec);
2345 seq_delmsg (mp, "unseen", msgnum);
2352 seq_setcur (mp, mp->hghsel);
2359 if (Msgs[msgnum].m_bboard_id == 0)
2362 printf ("(Message %d", msgnum);
2363 if (Msgs[msgnum].m_bboard_id > 0)
2364 printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id);
2375 return (ftell (mhlfp) >= Msgs[mhlnum].m_stop);
2380 mhl_action (char *name)
2384 if ((msgnum = m_atoi (name)) < mp->lowmsg
2385 || msgnum > mp->hghmsg
2386 || !does_exist (mp, msgnum))
2390 mhlfp = msh_ready (msgnum, 1);
2392 m_eomsbr (eom_action);
2404 if (mp->numsel == 1 || !interactive || redirected)
2407 if (SOprintf ("Press <return> to list \"%d\"...", msgnum)) {
2408 if (mp->lowsel != msgnum)
2410 printf ("Press <return> to list \"%d\"...", msgnum);
2415 read (fileno (stdout), buf, sizeof buf);
2417 if (strchr(buf, '\n') == NULL)
2421 told_to_quit = interrupted = 0;
2436 is_nontext (int msgnum)
2439 unsigned char *bp, *dp;
2441 char buf[BUFSIZ], name[NAMESZ];
2444 if (Msgs[msgnum].m_flags & MHNCHK)
2445 return (Msgs[msgnum].m_flags & MHNYES);
2446 Msgs[msgnum].m_flags |= MHNCHK;
2448 fp = msh_ready (msgnum, 1);
2451 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
2456 * Check Content-Type field
2458 if (!mh_strcasecmp (name, TYPE_FIELD)) {
2462 cp = add (buf, NULL);
2463 while (state == FLDPLUS) {
2464 state = m_getfld (state, name, buf, sizeof buf, fp);
2471 for (; isspace (*bp); bp++)
2476 for (bp++, i = 0;;) {
2506 for (dp = bp; istoken (*dp); dp++)
2513 if ((result = (mh_strcasecmp (bp, "plain") != 0)))
2516 for (dp++; isspace (*dp); dp++)
2519 if ((result = !uprf (dp, "charset")))
2521 dp += sizeof "charset" - 1;
2522 while (isspace (*dp))
2526 while (isspace (*dp))
2529 if ((bp = strchr(++dp, '"')))
2532 for (bp = dp; *bp; bp++)
2533 if (isspace (*bp)) {
2539 /* Default character set */
2542 /* Check the character set */
2543 result = !check_charset (dp, strlen (dp));
2545 if (!(result = (mh_strcasecmp (bp, "text") != 0))) {
2555 Msgs[msgnum].m_flags |= MHNYES;
2562 * Check Content-Transfer-Encoding field
2564 if (!mh_strcasecmp (name, ENCODING_FIELD)) {
2565 cp = add (buf, NULL);
2566 while (state == FLDPLUS) {
2567 state = m_getfld (state, name, buf, sizeof buf, fp);
2570 for (bp = cp; isspace (*bp); bp++)
2572 for (dp = bp; istoken (*dp); dp++)
2575 result = (mh_strcasecmp (bp, "7bit")
2576 && mh_strcasecmp (bp, "8bit")
2577 && mh_strcasecmp (bp, "binary"));
2581 Msgs[msgnum].m_flags |= MHNYES;
2588 * Just skip the rest of this header
2589 * field and go to next one.
2591 while (state == FLDPLUS)
2592 state = m_getfld (state, name, buf, sizeof(buf), fp);
2596 * We've passed the message header,
2597 * so message is just text.
2605 static struct swit sortswit[] = {
2607 { "datefield field", 0 },
2609 { "textfield field", 0 },
2611 { "notextfield", 0 },
2613 { "limit days", 0 },
2627 sortcmd (char **args)
2629 int msgp = 0, msgnum;
2630 char *cp, *datesw = NULL, *subjsw = NULL;
2631 char buf[BUFSIZ], *msgs[MAXARGS];
2635 forkcmd (args, cmd_name);
2639 while ((cp = *args++)) {
2641 switch (smatch (++cp, sortswit)) {
2643 ambigsw (cp, sortswit);
2646 fprintf (stderr, "-%s unknown\n", cp);
2649 snprintf (buf, sizeof(buf), "%s [msgs] [switches]", cmd_name);
2650 print_help (buf, sortswit, 1);
2655 advise (NULL, "only one date field at a time!");
2658 if (!(datesw = *args++) || *datesw == '-') {
2659 advise (NULL, "missing argument to %s", args[-2]);
2666 advise (NULL, "only one text field at a time!");
2669 if (!(subjsw = *args++) || *subjsw == '-') {
2670 advise (NULL, "missing argument to %s", args[-2]);
2678 case SOLIMT: /* too hard */
2679 if (!(cp = *args++) || *cp == '-') {
2680 advise (NULL, "missing argument to %s", args[-2]);
2684 case SOVERB: /* not implemented */
2688 if (*cp == '+' || *cp == '@') {
2689 advise (NULL, "sorry, no folders allowed!");
2697 msgs[msgp++] = "all";
2700 for (msgnum = 0; msgnum < msgp; msgnum++)
2701 if (!m_convert (mp, msgs[msgnum]))
2705 twscopy (&tb, dlocaltimenow ());
2707 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2708 if (Msgs[msgnum].m_scanl) {
2709 free (Msgs[msgnum].m_scanl);
2710 Msgs[msgnum].m_scanl = NULL;
2712 if (is_selected (mp, msgnum)) {
2713 if (get_fields (datesw, subjsw, msgnum, &Msgs[msgnum]))
2714 twscopy (&Msgs[msgnum].m_tb,
2715 msgnum != mp->lowsel ? &Msgs[msgnum - 1].m_tb : &tb);
2717 else /* m_scaln is already NULL */
2718 twscopy (&Msgs[msgnum].m_tb, &tb);
2719 Msgs[msgnum].m_stats = mp->msgstats[msgnum - mp->lowoff];
2720 if (mp->curmsg == msgnum)
2721 Msgs[msgnum].m_stats |= CUR;
2724 qsort ((char *) &Msgs[mp->lowsel], mp->hghsel - mp->lowsel + 1,
2725 sizeof(struct Msg), (qsort_comp) (subjsw ? subsort : msgsort));
2727 for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) {
2728 if (subjsw && Msgs[msgnum].m_scanl) {
2729 free (Msgs[msgnum].m_scanl); /* from subjsort */
2730 Msgs[msgnum].m_scanl = NULL;
2732 mp->msgstats[msgnum - mp->lowoff] = Msgs[msgnum].m_stats & ~CUR;
2733 if (Msgs[msgnum].m_stats & CUR)
2734 seq_setcur (mp, msgnum);
2737 mp->msgflags |= MODIFIED;
2743 * get_fields - parse message, and get date and subject if needed.
2744 * We'll use the msgp->m_tb tws struct for the date, and overload
2745 * the msgp->m_scanl field with our subject string.
2748 get_fields (char *datesw, char *subjsw, int msgnum, struct Msg *msgp)
2750 int state, gotdate = 0;
2751 char *bp, buf[BUFSIZ], name[NAMESZ];
2752 struct tws *tw = (struct tws *) 0;
2755 zp = msh_ready (msgnum, 0);
2756 for (state = FLD;;) {
2757 switch (state = m_getfld (state, name, buf, sizeof buf, zp)) {
2761 if (!mh_strcasecmp (name, datesw)) {
2763 while (state == FLDPLUS) {
2764 state = m_getfld (state, name, buf, sizeof buf, zp);
2767 if ((tw = dparsetime (bp)) == NULL)
2769 "unable to parse %s field in message %d",
2772 twscopy (&(msgp->m_tb), tw);
2774 if (!subjsw) /* not using this, or already done */
2775 break; /* all done! */
2778 else if (subjsw && !mh_strcasecmp(name, subjsw)) {
2780 while (state == FLDPLUS) {
2781 state = m_getfld (state, name, buf, sizeof buf, zp);
2784 msgp->m_scanl = sosmash(subjsw, bp);
2786 break; /* date done so we're done */
2788 subjsw = (char *)0;/* subject done, need date */
2790 while (state == FLDPLUS) /* flush this one */
2791 state = m_getfld (state, name, buf, sizeof buf, zp);
2802 admonish (NULL, "format error in message %d", msgnum);
2803 if (msgp->m_scanl) { /* this might need free'd */
2804 free (msgp->m_scanl); /* probably can't use subj anyway */
2805 msgp->m_scanl = NULL;
2810 adios (NULL, "internal error -- you lose");
2815 return OK; /* not an error if subj not found */
2817 admonish (NULL, "no %s field in message %d", datesw, msgnum);
2818 return NOTOK; /* NOTOK means use some other date */
2827 msgsort (struct Msg *a, struct Msg *b)
2829 return twsort (&a->m_tb, &b->m_tb);
2834 subsort (struct Msg *a, struct Msg *b)
2838 if (a->m_scanl && b->m_scanl)
2839 if ((i = strcmp (a->m_scanl, b->m_scanl)))
2842 return twsort (&a->m_tb, &b->m_tb);
2847 * try to make the subject "canonical": delete leading "re:", everything
2848 * but letters & smash letters to lower case.
2851 sosmash (char *subj, char *s)
2853 register char *cp, *dp;
2854 register unsigned char c;
2858 dp = s; /* dst pointer */
2859 if (!mh_strcasecmp (subj, "subject"))
2866 *dp++ = isupper(c) ? tolower(c) : c;
2872 while ((c = *cp++)) {
2874 *dp++ = isupper(c) ? tolower(c) : c;
2884 process (int msgnum, char *proc, int vecp, char **vec)
2886 int child_id, status;
2887 char tmpfil[BUFSIZ];
2892 strncpy (tmpfil, m_name (msgnum), sizeof(tmpfil));
2893 context_del (pfolder);
2894 context_replace (pfolder, fmsh);/* update current folder */
2896 context_save (); /* save the context file */
2900 cp = m_mktemp(invo_name, NULL, &out);
2902 /* Try again, but try to create under /tmp */
2904 cp = m_mktemp2(NULL, invo_name, NULL, &out);
2907 advise (NULL, "unable to create temporary file");
2911 copy_message (msgnum, out);
2913 strncpy(tmpfil, cp, sizeof(tmpfil));
2917 switch (child_id = fork ()) {
2919 advise ("fork", "unable to");
2925 SIGNAL (SIGINT, istat);
2926 SIGNAL (SIGQUIT, qstat);
2928 vec[vecp++] = tmpfil;
2932 fprintf (stderr, "unable to exec ");
2937 status = pidXwait (child_id, NULL);
2948 copy_message (int msgnum, FILE *out)
2951 static char buffer[BUFSIZ];
2954 zp = msh_ready (msgnum, 1);
2956 while (fgets (buffer, sizeof buffer, zp) != NULL) {
2957 fputs (buffer, out);
2958 if (interrupted && out == stdout)
2964 while (fgets (buffer, sizeof buffer, zp) != NULL
2965 && pos < Msgs[msgnum].m_stop) {
2966 fputs (buffer, out);
2967 pos += (long) strlen (buffer);
2968 if (interrupted && out == stdout)
2976 copy_digest (int msgnum, FILE *out)
2980 static char buffer[BUFSIZ];
2984 zp = msh_ready (msgnum, 1);
2987 while (fgets (buffer, sizeof buffer, zp) != NULL
2988 && !fmsh && pos < Msgs[msgnum].m_stop) {
2989 if (c == '\n' && *buffer == '-')
2991 fputs (buffer, out);
2992 c = buffer[strlen (buffer) - 1];
2994 pos += (long) strlen (buffer);
2995 if (interrupted && out == stdout)