head 1.32; access; symbols; locks; strict; comment @ * @; 1.32 date 95.12.11.18.19.26; author jromine; state Exp; branches; next 1.31; 1.31 date 95.12.07.18.20.22; author jromine; state Exp; branches; next 1.30; 1.30 date 95.12.06.23.44.31; author jromine; state Exp; branches; next 1.29; 1.29 date 94.04.21.18.20.50; author jromine; state Exp; branches; next 1.28; 1.28 date 93.12.01.03.50.31; author jromine; state Exp; branches; next 1.27; 1.27 date 93.10.26.20.09.54; author jromine; state Exp; branches; next 1.26; 1.26 date 93.08.27.23.23.26; author jromine; state Exp; branches; next 1.25; 1.25 date 92.12.15.00.20.22; author jromine; state Exp; branches; next 1.24; 1.24 date 92.11.24.18.26.05; author jromine; state Exp; branches; next 1.23; 1.23 date 92.11.04.00.53.32; author jromine; state Exp; branches; next 1.22; 1.22 date 92.10.29.03.49.31; author jromine; state Exp; branches; next 1.21; 1.21 date 92.10.26.22.21.33; author jromine; state Exp; branches; next 1.20; 1.20 date 92.10.17.00.24.25; author jromine; state Exp; branches; next 1.19; 1.19 date 92.10.17.00.19.58; author jromine; state Exp; branches; next 1.18; 1.18 date 92.10.16.22.34.17; author jromine; state Exp; branches; next 1.17; 1.17 date 92.10.16.21.50.20; author jromine; state Exp; branches; next 1.16; 1.16 date 92.10.16.21.47.40; author jromine; state Exp; branches; next 1.15; 1.15 date 92.10.16.21.37.18; author jromine; state Exp; branches; next 1.14; 1.14 date 92.10.16.16.51.55; author jromine; state Exp; branches; next 1.13; 1.13 date 92.05.19.21.03.35; author jromine; state Exp; branches; next 1.12; 1.12 date 92.03.03.17.09.57; author jromine; state Exp; branches; next 1.11; 1.11 date 92.02.08.00.10.26; author jromine; state Exp; branches; next 1.10; 1.10 date 92.02.05.07.26.30; author jromine; state Exp; branches; next 1.9; 1.9 date 92.01.31.22.19.11; author jromine; state Exp; branches; next 1.8; 1.8 date 92.01.31.16.33.46; author jromine; state Exp; branches; next 1.7; 1.7 date 92.01.23.22.58.03; author jromine; state Exp; branches; next 1.6; 1.6 date 91.01.14.16.48.39; author mh; state Exp; branches; next 1.5; 1.5 date 90.04.05.15.01.41; author sources; state Exp; branches; next 1.4; 1.4 date 90.03.23.14.14.55; author sources; state Exp; branches; next 1.3; 1.3 date 90.03.22.16.59.48; author sources; state Exp; branches; next 1.2; 1.2 date 90.02.06.13.23.35; author sources; state Exp; branches; next 1.1; 1.1 date 90.02.06.13.23.00; author sources; state Exp; branches; next ; desc @@ 1.32 log @fix merge error (mtr fixes) @ text @/* mshcmds.c - command handlers in msh */ #ifndef lint static char ident[] = "@@(#)$Id: mshcmds.c,v 1.31 1995/12/07 18:20:22 jromine Exp jromine $"; #endif /* lint */ #include "../h/mh.h" #include "../h/dropsbr.h" #include "../h/formatsbr.h" #include "../h/scansbr.h" #include "../zotnet/tws.h" #ifdef _AIX /* AIX 1.2.1 declares getws() */ #define getws _getws #endif #include #ifdef _AIX #undef getws #endif #include "../zotnet/mts.h" #include #include #include #include #include #include #include "../h/mshsbr.h" #ifdef MIME #include "../h/mhn.h" #endif /* MIME */ /* */ extern int errno; /* BURST */ static char delim3[] = "-------";/* from burst.c */ /* SHOW */ static int mhlnum; static FILE *mhlfp; void clear_screen (); static int eom_action (); static FP mhl_action (); #ifdef MIME static int nontext(); #endif static burst(), forw(), rmm(), show(), ask(), copy_message(), copy_digest(); static int process(); /* SORTM */ static int msgsort (), subsort(); static int getws (); static char *sosmash (); #if defined(NNTP) && defined(MPOP) #undef MPOP #endif #ifdef MPOP #ifdef BPOP extern int pmsh; extern char response[]; #endif #endif /* MPOP */ /* */ forkcmd (args, pgm) char **args, *pgm; { int child_id; char *vec[MAXARGS]; vec[0] = r1bindex (pgm, '/'); (void) copyip (args, vec + 1); if (fmsh) { (void) m_delete (pfolder); m_replace (pfolder, fmsh); m_sync (mp); m_update (); } (void) fflush (stdout); switch (child_id = fork ()) { case NOTOK: advise ("fork", "unable to"); return; case OK: closefds (3); (void) signal (SIGINT, istat); (void) signal (SIGQUIT, qstat); execvp (pgm, vec); fprintf (stderr, "unable to exec "); perror (cmd_name); _exit (1); default: (void) pidXwait (child_id, NULLCP); break; } if (fmsh) { /* assume the worst case */ mp -> msgflags |= MODIFIED; modified++; } } /* */ static struct swit distswit[] = { #define DIANSW 0 "annotate", 0, #define DINANSW 1 "noannotate", 0, #define DIDFSW 2 "draftfolder +folder", 0, #define DIDMSW 3 "draftmessage msg", 0, #define DINDFSW 4 "nodraftfolder", 0, #define DIEDTSW 5 "editor editor", 0, #define DINEDSW 6 "noedit", 0, #define DIFRMSW 7 "form formfile", 0, #define DIINSW 8 "inplace", 0, #define DININSW 9 "noinplace", 0, #define DIWHTSW 10 "whatnowproc program", 0, #define DINWTSW 11 "nowhatnowproc", 0, #define DIHELP 12 "help", 4, NULL, 0 }; /* */ distcmd (args) char **args; { int vecp = 1; char *cp, *msg = NULL, buf[BUFSIZ], *vec[MAXARGS]; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, distswit)) { case AMBIGSW: ambigsw (cp, distswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case DIHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, distswit); return; case DIANSW: /* not implemented */ case DINANSW: case DIINSW: case DININSW: continue; case DINDFSW: case DINEDSW: case DINWTSW: vec[vecp++] = --cp; continue; case DIEDTSW: case DIFRMSW: case DIDFSW: case DIDMSW: case DIWHTSW: vec[vecp++] = --cp; if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else if (msg) { advise (NULLCP, "only one message at a time!"); return; } else msg = cp; } vec[0] = cmd_name; vec[vecp++] = "-file"; vec[vecp] = NULL; if (!msg) msg = "cur"; if (!m_convert (mp, msg)) return; m_setseq (mp); if (mp -> numsel > 1) { advise (NULLCP, "only one message at a time!"); return; } (void) process (mp -> hghsel, cmd_name, vecp, vec); m_setcur (mp, mp -> hghsel); } /* */ static struct swit explswit[] = { #define EXINSW 0 "inplace", 0, #define EXNINSW 1 "noinplace", 0, #define EXQISW 2 "quiet", 0, #define EXNQISW 3 "noquiet", 0, #define EXVBSW 4 "verbose", 0, #define EXNVBSW 5 "noverbose", 0, #define EXHELP 6 "help", 4, NULL, 0 }; /* */ explcmd (args) char **args; { int inplace = 0, quietsw = 0, verbosw = 0, msgp = 0, hi, msgnum; char *cp, buf[BUFSIZ], *msgs[MAXARGS]; struct Msg *smsgs; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, explswit)) { case AMBIGSW: ambigsw (cp, explswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case EXHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, explswit); return; case EXINSW: inplace++; continue; case EXNINSW: inplace = 0; continue; case EXQISW: quietsw++; continue; case EXNQISW: quietsw = 0; continue; case EXVBSW: verbosw++; continue; case EXNVBSW: verbosw = 0; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!msgp) msgs[msgp++] = "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); smsgs = (struct Msg *) calloc ((unsigned) (MAXFOLDER + 2), sizeof *smsgs); if (smsgs == NULL) adios (NULLCP, "unable to allocate folder storage"); hi = mp -> hghmsg + 1; interrupted = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (burst (smsgs, msgnum, inplace, quietsw, verbosw) != OK) break; free ((char *) smsgs); if (inplace) m_setcur (mp, mp -> lowsel); else if (hi <= mp -> hghmsg) m_setcur (mp, hi); mp -> msgflags |= MODIFIED; modified++; } /* */ static burst (smsgs, msgnum, inplace, quietsw, verbosw) struct Msg *smsgs; int msgnum, inplace, quietsw, verbosw; { int i, j, ld3, wasdlm, msgp; long pos; char c, cc, buffer[BUFSIZ]; register FILE *zp; ld3 = strlen (delim3); if (Msgs[msgnum].m_scanl) { free (Msgs[msgnum].m_scanl); Msgs[msgnum].m_scanl = NULL; } pos = ftell (zp = msh_ready (msgnum, 1)); for (msgp = 0; msgp <= MAXFOLDER;) { while (fgets (buffer, sizeof buffer, zp) != NULL && buffer[0] == '\n' && pos < Msgs[msgnum].m_stop) pos += (long) strlen (buffer); if (feof (zp) || pos >= Msgs[msgnum].m_stop) break; (void) fseek (zp, pos, 0); smsgs[msgp].m_start = pos; for (c = 0; pos < Msgs[msgnum].m_stop && fgets (buffer, sizeof buffer, zp) != NULL; c = buffer[0]) if (strncmp (buffer, delim3, ld3) == 0 && (msgp == 1 || c == '\n') && peekc (zp) == '\n') break; else pos += (long) strlen (buffer); wasdlm = strncmp (buffer, delim3, ld3) == 0; if (smsgs[msgp].m_start != pos) smsgs[msgp++].m_stop = (c == '\n' && wasdlm) ? pos - 1 : pos; if (feof (zp) || pos >= Msgs[msgnum].m_stop) { if (wasdlm) smsgs[msgp - 1].m_stop -= ((long) strlen (buffer) + 1); break; } pos += (long) strlen (buffer); } switch (msgp--) { /* toss "End of XXX Digest" */ case 0: adios (NULLCP, "burst() botch -- you lose big"); case 1: if (!quietsw) printf ("message %d not in digest format\n", msgnum); return OK; default: if (verbosw) printf ("%d message%s exploded from digest %d\n", msgp, msgp != 1 ? "s" : "", msgnum); break; } if ((i = msgp + mp -> hghmsg) > MAXFOLDER) { advise (NULLCP, "more than %d messages", MAXFOLDER); return NOTOK; } if ((mp = m_remsg (mp, 0, i)) == NULL) adios (NULLCP, "unable to allocate folder storage"); j = mp -> hghmsg; mp -> hghmsg += msgp; mp -> nummsg += msgp; if (mp -> hghsel > msgnum) mp -> hghsel += msgp; if (inplace) for (i = mp -> hghmsg; j > msgnum; i--, j--) { if (verbosw) printf ("message %d becomes message %d\n", j, i); Msgs[i].m_bboard_id = Msgs[j].m_bboard_id; Msgs[i].m_top = Msgs[j].m_top; Msgs[i].m_start = Msgs[j].m_start; Msgs[i].m_stop = Msgs[j].m_stop; Msgs[i].m_scanl = NULL; if (Msgs[j].m_scanl) { free (Msgs[j].m_scanl); Msgs[j].m_scanl = NULL; } mp -> msgstats[i] = mp -> msgstats[j]; } if (Msgs[msgnum].m_bboard_id == 0) (void) readid (msgnum); mp -> msgstats[msgnum] &= ~SELECTED; i = inplace ? msgnum + msgp : mp -> hghmsg; for (j = msgp; j >= (inplace ? 0 : 1); i--, j--) { if (verbosw && i != msgnum) printf ("message %d of digest %d becomes message %d\n", j, msgnum, i); Msgs[i].m_bboard_id = Msgs[msgnum].m_bboard_id; Msgs[i].m_top = Msgs[j].m_top; Msgs[i].m_start = smsgs[j].m_start; Msgs[i].m_stop = smsgs[j].m_stop; Msgs[i].m_scanl = NULL; mp -> msgstats[i] = mp -> msgstats[msgnum]; } return OK; } /* */ static struct swit fileswit[] = { #define FIDRFT 0 "draft", 0, #define FILINK 1 "link", 0, #define FINLINK 2 "nolink", 0, #define FIPRES 3 "preserve", 0, #define FINPRES 4 "nopreserve", 0, #define FISRC 5 "src +folder", 0, #define FIFILE 6 "file file", 0, #define FIPROC 7 "rmmproc program", 0, #define FINPRC 8 "normmproc", 0, #define FIHELP 9 "help", 4, NULL, 0 }; /* */ filecmd (args) char **args; { int linksw = 0, msgp = 0, vecp = 1, i, msgnum; char *cp, buf[BUFSIZ], *msgs[MAXARGS], *vec[MAXARGS]; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (i = smatch (++cp, fileswit)) { case AMBIGSW: ambigsw (cp, fileswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case FIHELP: (void) sprintf (buf, "%s +folder... [msgs] [switches]", cmd_name); help (buf, fileswit); return; case FILINK: linksw++; continue; case FINLINK: linksw = 0; continue; case FIPRES: case FINPRES: continue; case FISRC: case FIDRFT: case FIFILE: case FIPROC: case FINPRC: advise (NULLCP, "sorry, -%s not allowed!", fileswit[i].sw); return; } if (*cp == '+' || *cp == '@@') vec[vecp++] = cp; else msgs[msgp++] = cp; } vec[0] = cmd_name; vec[vecp++] = "-file"; vec[vecp] = NULL; if (!msgp) msgs[msgp++] = "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); interrupted = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (process (msgnum, fileproc, vecp, vec)) { mp -> msgstats[msgnum] &= ~SELECTED; mp -> numsel--; } if (mp -> numsel != mp -> nummsg || linksw) m_setcur (mp, mp -> hghsel); if (!linksw) rmm (); } /* */ int filehak (args) char **args; { int result, vecp = 0; char *cp, *cwd, *vec[MAXARGS]; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, fileswit)) { case AMBIGSW: case UNKWNSW: case FIHELP: return NOTOK; case FILINK: case FINLINK: case FIPRES: case FINPRES: continue; case FISRC: case FIDRFT: case FIFILE: return NOTOK; } if (*cp == '+' || *cp == '@@') vec[vecp++] = cp; } vec[vecp] = NULL; result = NOTOK; cwd = NULL; for (vecp = 0; (cp = vec[vecp]) && result == NOTOK; vecp++) { if (cwd == NULL) cwd = getcpy (pwd ()); (void) chdir (m_maildir ("")); cp = path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF); if (access (m_maildir (cp), 0) == NOTOK) result = OK; free (cp); } if (cwd) (void) chdir (cwd); return result; } /* */ static struct swit foldswit[] = { #define FLALSW 0 "all", 0, #define FLFASW 1 "fast", 0, #define FLNFASW 2 "nofast", 0, #define FLHDSW 3 "header", 0, #define FLNHDSW 4 "noheader", 0, #define FLPKSW 5 "pack", 0, #define FLNPKSW 6 "nopack", 0, #define FLRCSW 7 "recurse", 0, #define FLNRCSW 8 "norecurse", 0, #define FLTLSW 9 "total", 0, #define FLNTLSW 10 "nototal", 0, #define FLPRSW 11 "print", 0, #define FLPUSW 12 "push", 0, #define FLPOSW 13 "pop", 0, #define FLLISW 14 "list", 0, #define FLHELP 15 "help", 4, NULL, 0 }; /* */ foldcmd (args) char **args; { int fastsw = 0, headersw = 0, packsw = 0, hole, msgnum; char *cp, *folder = NULL, *msg = NULL, buf[BUFSIZ], **vec = args; if (args == NULL) goto fast; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, foldswit)) { case AMBIGSW: ambigsw (cp, foldswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case FLHELP: (void) sprintf (buf, "%s [+folder] [msg] [switches]", cmd_name); help (buf, foldswit); return; case FLALSW: /* not implemented */ case FLRCSW: case FLNRCSW: case FLTLSW: case FLNTLSW: case FLPRSW: case FLPUSW: case FLPOSW: case FLLISW: continue; case FLFASW: fastsw++; continue; case FLNFASW: fastsw = 0; continue; case FLHDSW: headersw++; continue; case FLNHDSW: headersw = 0; continue; case FLPKSW: packsw++; continue; case FLNPKSW: packsw = 0; continue; } if (*cp == '+' || *cp == '@@') if (folder) { advise (NULLCP, "only one folder at a time!\n"); return; } else folder = fmsh ? path (cp + 1, *cp == '+' ? TFOLDER : TSUBCWF) : cp + 1; else if (msg) { advise (NULLCP, "only one message at a time!\n"); return; } else msg = cp; } if (folder) { if (*folder == 0) { advise (NULLCP, "null folder names are not permitted"); return; } if (fmsh) { if (access (m_maildir (folder), 04) == NOTOK) { advise (folder, "unable to read"); return; } } else { (void) strcpy (buf, folder); if (expand (buf) == NOTOK) return; folder = buf; if (access (folder, 04) == NOTOK) { advise (folder, "unable to read"); return; } } m_reset (); if (fmsh) fsetup (folder); else setup (folder); readids (0); display_info (0); } if (msg) { if (!m_convert (mp, msg)) return; m_setseq (mp); if (mp -> numsel > 1) { advise (NULLCP, "only one message at a time!"); return; } m_setcur (mp, mp -> hghsel); } if (packsw) { if (fmsh) { forkcmd (vec, cmd_name); return; } if (mp -> lowmsg > 1 && (mp = m_remsg (mp, 1, mp -> hghmsg)) == NULL) adios (NULLCP, "unable to allocate folder storage"); for (msgnum = mp -> lowmsg, hole = 1; msgnum <= mp -> hghmsg; msgnum++) if (mp -> msgstats[msgnum] & EXISTS) { if (msgnum != hole) { Msgs[hole].m_bboard_id = Msgs[msgnum].m_bboard_id; Msgs[hole].m_top = Msgs[msgnum].m_top; Msgs[hole].m_start = Msgs[msgnum].m_start; Msgs[hole].m_stop = Msgs[msgnum].m_stop; Msgs[hole].m_scanl = NULL; if (Msgs[msgnum].m_scanl) { free (Msgs[msgnum].m_scanl); Msgs[msgnum].m_scanl = NULL; } mp -> msgstats[hole] = mp -> msgstats[msgnum]; if (mp -> curmsg == msgnum) m_setcur (mp, hole); } hole++; } if (mp -> nummsg > 0) { mp -> lowmsg = 1; mp -> hghmsg = hole - 1; } mp -> msgflags |= MODIFIED; modified++; } fast: ; if (fastsw) printf ("%s\n", fmsh ? fmsh : mp -> foldpath); else { if (headersw) printf ("\t\tFolder %*s# of messages (%*srange%*s); cur%*smsg\n", DMAXFOLDER, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, "", DMAXFOLDER - 2, ""); printf (args ? "%22s " : "%s ", fmsh ? fmsh : mp -> foldpath); if (mp -> hghmsg == 0) printf ("has no messages%*s", mp -> msgflags & OTHERS ? DMAXFOLDER * 2 + 4 : 0, ""); else { printf ("has %*d message%s (%*d-%*d)", DMAXFOLDER, mp -> nummsg, mp -> nummsg != 1 ? "s" : "", DMAXFOLDER, mp -> lowmsg, DMAXFOLDER, mp -> hghmsg); if (mp -> curmsg >= mp -> lowmsg && mp -> curmsg <= mp -> hghmsg) printf ("; cur=%*d", DMAXFOLDER, mp -> curmsg); } printf (".\n"); } } /* */ #ifndef MIME #define MIMEminc(a) (a) #else /* MIME */ #define MIMEminc(a) 0 #endif /* MIME */ static struct swit forwswit[] = { #define FOANSW 0 "annotate", 0, #define FONANSW 1 "noannotate", 0, #define FODFSW 2 "draftfolder +folder", 0, #define FODMSW 3 "draftmessage msg", 0, #define FONDFSW 4 "nodraftfolder", 0, #define FOEDTSW 5 "editor editor", 0, #define FONEDSW 6 "noedit", 0, #define FOFTRSW 7 "filter filterfile", 0, #define FOFRMSW 8 "form formfile", 0, #define FOFTSW 9 "format", 5, #define FONFTSW 10 "noformat", 7, #define FOINSW 11 "inplace", 0, #define FONINSW 12 "noinplace", 0, #define FOMISW 13 "mime", MIMEminc(-4), #define FONMISW 14 "nomime", MIMEminc(-6), #define FOWHTSW 15 "whatnowproc program", 0, #define FONWTSW 16 "nowhatnow", 0, #define FOHELP 17 "help", 4, NULL, 0 }; /* */ forwcmd (args) char **args; { int msgp = 0, vecp = 1, mime = 0, msgnum; char *cp, *filter = NULL, buf[BUFSIZ], *msgs[MAXARGS], *vec[MAXARGS]; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, forwswit)) { case AMBIGSW: ambigsw (cp, forwswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case FOHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, forwswit); return; case FOANSW: /* not implemented */ case FONANSW: case FOINSW: case FONINSW: continue; case FOMISW: #ifdef MIME mime = 1; filter = NULL; #endif /* MIME */ continue; case FONMISW: mime = 0; continue; case FONDFSW: case FONEDSW: case FONWTSW: vec[vecp++] = --cp; continue; case FOEDTSW: case FOFRMSW: case FODFSW: case FODMSW: case FOWHTSW: vec[vecp++] = --cp; if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; case FOFTRSW: if (!(filter = *args++) || *filter == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } mime = 0; continue; case FOFTSW: if (access (filter = myfilter, 04) == NOTOK) { advise (filter, "unable to read default filter file"); return; } continue; case FONFTSW: filter = NULL; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } /* foil search of .mh_profile */ (void) sprintf (buf, "%sXXXXXX", invo_name); vec[0] = (char *)mktemp (buf); vec[vecp++] = "-file"; vec[vecp] = NULL; if (!msgp) msgs[msgp++] = "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); if (filter) { (void) strcpy (buf, filter); if (expand (buf) == NOTOK) return; if (access (filter = getcpy (libpath (buf)), 04) == NOTOK) { advise (filter, "unable to read"); free (filter); return; } } forw (cmd_name, filter, vecp, vec, mime); m_setcur (mp, mp -> hghsel); if (filter) free (filter); } /* */ static forw (proc, filter, vecp, vec, mime) int vecp, mime; char *proc, *filter, **vec; { int i, child_id, msgnum, msgcnt; char tmpfil[80], *args[MAXARGS]; FILE *out; #ifdef MIME int nedit = 0; char *ed = NULL; #endif /* MIME */ (void) strcpy (tmpfil, m_tmpfil (invo_name)); interrupted = 0; if (filter) switch (child_id = fork ()) { case NOTOK: advise ("fork", "unable to"); return; case OK: /* "trust me" */ if (freopen (tmpfil, "w", stdout) == NULL) { fprintf (stderr, "unable to create "); perror (tmpfil); _exit (1); } args[0] = r1bindex (mhlproc, '/'); i = 1; args[i++] = "-forwall"; args[i++] = "-form"; args[i++] = filter; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) args[i++] = getcpy (m_name (msgnum)); args[i] = NULL; (void) mhlsbr (i, args, mhl_action); m_eomsbr ((int (*) ()) 0); (void) fclose (stdout); _exit (0); default: if (pidXwait (child_id, NULLCP)) interrupted++; break; } #ifdef MIME else if (mime) { int isdf = 0, len, nwhat = 0; #define INITIAL_PREFIX "----- =_aaaaaaaaaa" char *cp, *form = NULL, buffer[BUFSIZ], prefix[sizeof INITIAL_PREFIX]; FILE *zp; proc = whatnowproc; for (vecp = 1; cp = vec[vecp++]; ) if (*cp == '-') switch (smatch (++cp, forwswit)) { case FOEDTSW: ed = vec[vecp++]; nedit = 0; continue; case FONEDSW: nedit++; continue; case FOFRMSW: form = vec[vecp++]; continue; case FOWHTSW: proc = vec[vecp++]; nwhat = 0; continue; case FONWTSW: nwhat++; continue; /* ignore -draftfolder / -draftmessage / -nodraftfolder */ case FODFSW: case FODMSW: vecp++; case FONDFSW: continue; } (void) strcpy (tmpfil, m_draft (NULLCP, NULLCP, NOUSE, &isdf)); if (!ed && !(ed = m_find ("editor"))) ed = sysed; (void) strcpy (prefix, INITIAL_PREFIX); cp = index (prefix, 'a'); len = strlen (prefix); for (;;) { int hit = 0; long pos; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted && !hit; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { zp = msh_ready (msgnum, 1); if (!fmsh) pos = ftell (zp); while (fgets (buffer, sizeof buffer, zp) != NULL && !fmsh && pos < Msgs[msgnum].m_stop) { register char *pp; if (buffer[0] != '-' || buffer[1] != '-') continue; for (pp = buffer + strlen (buffer) - 1; pp >= buffer; pp--) if (!isspace (*pp)) break; *pp++ = '\0'; if (strncmp (buffer + 2, prefix, len)) continue; hit = 1; break; } } if (!hit) break; if (*cp < 'z') (*cp)++; else if (*++cp == 0) { advise (NULLCP, "unable to determine unique delimiter string?!?"); return; } else (*cp)++; } if ((out = fopen (tmpfil, "w")) == NULL) { advise (tmpfil, "unable to create temporary file"); return; } (void) chmod (tmpfil, m_gmprot ()); fprintf (out, "%s: %s\n", VRSN_FIELD, VRSN_VALUE); fprintf (out, "%s: multipart/digest; boundary=\"%s\"\n", TYPE_FIELD, prefix); if (!(zp = fopen (libpath (form ? form : forwcomps), "r"))) { if (form) advise (form, "unable to open form file"); else advise (forwcomps, "unable to open default components file"); (void) fclose (out); (void) unlink (tmpfil); return; } while (fgets (buffer, sizeof buffer, zp)) (void) fputs (buffer, out); (void) fclose (zp); for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { fprintf (out, "\n--%s\n%s: message/rfc822\n\n", prefix, TYPE_FIELD); copy_message (msgnum, out); } fprintf (out, "\n--%s--\n", prefix); (void) fclose (out); if (nwhat) return; } #endif /* MIME */ else { if ((out = fopen (tmpfil, "w")) == NULL) { advise (tmpfil, "unable to create temporary file"); return; } msgcnt = 1; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { fprintf (out, "\n\n-------"); if (msgnum == mp -> lowsel) fprintf (out, " Forwarded Message%s", mp -> numsel > 1 ? "s" : ""); else fprintf (out, " Message %d", msgcnt); fprintf (out, "\n\n"); copy_digest (msgnum, out); msgcnt++; } fprintf (out, "\n\n------- End of Forwarded Message%s\n", mp -> numsel > 1 ? "s" : ""); (void) fclose (out); } (void) fflush (stdout); if (!interrupted) switch (child_id = fork ()) { case NOTOK: advise ("fork", "unable to"); break; case OK: closefds (3); (void) signal (SIGINT, istat); (void) signal (SIGQUIT, qstat); #ifdef MIME if (mime) { vecp = 0; vec[vecp++] = r1bindex (proc, '/'); (void) m_putenv ("mhdraft", tmpfil); (void) unputenv ("mhfolder"); (void) unputenv ("mhaltmsg"); (void) m_putenv ("mhdist", "0"); if (nedit) (void) unputenv ("mheditor"); else (void) m_putenv ("mheditor", ed); (void) m_putenv ("mhuse", "0"); (void) unputenv ("mhmessages"); (void) unputenv ("mhannotate"); (void) unputenv ("mhinplace"); } else #endif /* MIME */ vec[vecp++] = tmpfil; vec[vecp] = NULL; execvp (proc, vec); fprintf (stderr, "unable to exec "); perror (proc); _exit (1); default: (void) pidXwait (child_id, NULLCP); break; } #ifdef MIME if (!mime) #endif /* MIME */ (void) unlink (tmpfil); } /* */ static char *hlpmsg[] = { "The %s program emulates many of the commands found in the Rand MH", "system. Instead of operating on MH folders, commands to %s concern", "a single file.", "", "To see the list of commands available, just type a ``?'' followed by", "the RETURN key. To find out what switches each command takes, type", "the name of the command followed by ``-help''. To leave %s, use the", "``quit'' command.", "", "Although a lot of MH commands are found in %s, not all are fully", "implemented. %s will always recognize all legal switches for a", "given command though, and will let you know when you ask for an", "option that it is unable to perform.", "", "Running %s is fun, but using MH from your shell is far superior.", "After you have familiarized yourself with the MH style by using %s,", "you should try using MH from the shell. You can still use %s for", "message files that aren't in MH format, such as BBoard files.", NULL }; /* ARGSUSED */ helpcmd (args) char **args; { int i; for (i = 0; hlpmsg[i]; i++) { printf (hlpmsg[i], invo_name); (void) putchar ('\n'); } } /* */ static struct swit markswit[] = { #define MADDSW 0 "add", 0, #define MDELSW 1 "delete", 0, #define MLSTSW 2 "list", 0, #define MSEQSW 3 "sequence name", 0, #define MPUBSW 4 "public", 0, #define MNPUBSW 5 "nopublic", 0, #define MZERSW 6 "zero", 0, #define MNZERSW 7 "nozero", 0, #define MHELP 8 "help", 4, #define MDBUGSW 9 "debug", -5, NULL, 0 }; /* */ markcmd (args) char **args; { int addsw = 0, deletesw = 0, debugsw = 0, listsw = 0, zerosw = 0, seqp = 0, msgp = 0, i, msgnum; char *cp, buf[BUFSIZ], *seqs[NATTRS + 1], *msgs[MAXARGS]; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, markswit)) { case AMBIGSW: ambigsw (cp, markswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case MHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, markswit); return; case MADDSW: addsw++; deletesw = listsw = 0; continue; case MDELSW: deletesw++; addsw = listsw = 0; continue; case MLSTSW: listsw++; addsw = deletesw = 0; continue; case MSEQSW: if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } if (seqp < NATTRS) seqs[seqp++] = cp; else { advise (NULLCP, "only %d sequences allowed!", NATTRS); return; } continue; case MPUBSW: /* not implemented */ case MNPUBSW: continue; case MDBUGSW: debugsw++; continue; case MZERSW: zerosw++; continue; case MNZERSW: zerosw = 0; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!addsw && !deletesw && !listsw) if (seqp) addsw++; else if (debugsw) listsw++; else { seqs[seqp++] = "unseen"; deletesw++; zerosw = 0; if (!msgp) msgs[msgp++] = "all"; } if (!msgp) msgs[msgp++] = listsw ? "all" :"cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; if (debugsw) { printf ("invo_name=%s mypath=%s defpath=%s\n", invo_name, mypath, defpath); printf ("ctxpath=%s context flags=%s\n", ctxpath, sprintb (buf, (unsigned) ctxflags, DBITS)); printf ("foldpath=%s flags=%s\n", mp -> foldpath, sprintb (buf, (unsigned) mp -> msgflags, FBITS)); printf ("hghmsg=%d lowmsg=%d nummsg=%d curmsg=%d\n", mp -> hghmsg, mp -> lowmsg, mp -> nummsg, mp -> curmsg); printf ("lowsel=%d hghsel=%d numsel=%d\n", mp -> lowsel, mp -> hghsel, mp -> numsel); #ifndef MTR printf ("lowoff=%d hghoff=%d\n", mp -> lowoff, mp -> hghoff); #else /* MTR */ printf ("lowoff=%d hghoff=%d msgbase=0x%x msgstats=0x%x\n", mp -> lowoff, mp -> hghoff, mp -> msgbase, mp -> msgstats); #endif /* MTR */ } if (seqp == 0 && (addsw || deletesw)) { advise (NULLCP, "-%s requires at least one -sequence argument", addsw ? "add" : "delete"); return; } seqs[seqp] = NULL; if (addsw) for (seqp = 0; seqs[seqp]; seqp++) { if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) return; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) return; } if (deletesw) for (seqp = 0; seqs[seqp]; seqp++) { if (zerosw) for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) if (mp -> msgstats[msgnum] & EXISTS) if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) return; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (!m_seqdel (mp, seqs[seqp], msgnum)) return; } if (listsw) { int bits = FFATTRSLOT; #define empty(s) ((s) ? (s) : "") if (seqp == 0) for (i = 0; mp -> msgattrs[i]; i++) printf ("%s%s: %s\n", mp -> msgattrs[i], mp -> attrstats & (1 << (bits + i)) ? " (private)" : "", empty(m_seq (mp, mp -> msgattrs[i]))); else for (seqp = 0; seqs[seqp]; seqp++) printf ("%s%s: %s\n", seqs[seqp], empty(m_seq (mp, seqs[seqp]))); #undef empty interrupted = 0; if (debugsw) for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { printf ("%*d: id=%d top=%d start=%ld stop=%ld %s\n", DMAXFOLDER, msgnum, Msgs[msgnum].m_bboard_id, Msgs[msgnum].m_top, Msgs[msgnum].m_start, Msgs[msgnum].m_stop, sprintb (buf, (unsigned) mp -> msgstats[msgnum], m_seqbits (mp))); if (Msgs[msgnum].m_scanl) printf ("%s", Msgs[msgnum].m_scanl); } } } /* */ #ifdef MIME static struct swit mhnswit[] = { #define MHNAUTOSW 0 "auto", 0, #define MHNNAUTOSW 1 "noauto", 0, #define MHNDEBUGSW 2 "debug", -5, #define MHNEBCDICSW 3 "ebcdicsafe", 0, #define MHNNEBCDICSW 4 "noebcdicsafe", 0, #define MHNFORMSW 5 "form formfile", 4, #define MHNHEADSW 6 "headers", 0, #define MHNNHEADSW 7 "noheaders", 0, #define MHNLISTSW 8 "list", 0, #define MHNNLISTSW 9 "nolist", 0, #define MHNPARTSW 10 "part number", 0, #define MHNSIZESW 11 "realsize", 0, #define MHNNSIZESW 12 "norealsize", 0, #define MHNRFC934SW 13 "rfc934mode", 0, #define MHNNRFC934SW 14 "norfc934mode", 0, #define MHNSERIALSW 15 "serialonly", 0, #define MHNNSERIALSW 16 "noserialonly", 0, #define MHNSHOWSW 17 "show", 0, #define MHNNSHOWSW 18 "noshow", 0, #define MHNSTORESW 19 "store", 0, #define MHNNSTORESW 20 "nostore", 0, #define MHNTYPESW 21 "type content", 0, #define MHNVERBSW 22 "verbose", 0, #define MHNNVERBSW 23 "noverbose", 0, #define MHNHELPSW 24 "help", 4, #define MHNPROGSW 25 "moreproc program", -4, #define MHNNPROGSW 26 "nomoreproc", -3, #define MHNLENSW 27 "length lines", -4, #define MHNWIDSW 28 "width columns", -4, NULL, 0 }; /* */ mhncmd (args) char **args; { int msgp = 0, vecp = 1, i, msgnum; char *cp, buf[BUFSIZ], *msgs[MAXARGS], *vec[MAXARGS]; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, mhnswit)) { case AMBIGSW: ambigsw (cp, mhnswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case MHNHELPSW: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, mhnswit); return; case MHNAUTOSW: case MHNNAUTOSW: case MHNDEBUGSW: case MHNEBCDICSW: case MHNNEBCDICSW: case MHNHEADSW: case MHNNHEADSW: case MHNLISTSW: case MHNNLISTSW: case MHNSIZESW: case MHNNSIZESW: case MHNRFC934SW: case MHNNRFC934SW: case MHNSERIALSW: case MHNNSERIALSW: case MHNSHOWSW: case MHNNSHOWSW: case MHNSTORESW: case MHNNSTORESW: case MHNVERBSW: case MHNNVERBSW: case MHNNPROGSW: vec[vecp++] = --cp; continue; case MHNFORMSW: case MHNPARTSW: case MHNTYPESW: case MHNPROGSW: case MHNLENSW: case MHNWIDSW: vec[vecp++] = --cp; if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } vec[0] = cmd_name; vec[vecp++] = "-file"; vec[vecp] = NULL; if (!msgp) msgs[msgp++] = "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); interrupted = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (process (msgnum, cmd_name, vecp, vec)) { mp -> msgstats[msgnum] &= ~SELECTED; mp -> numsel--; } m_setcur (mp, mp -> hghsel); } /* */ #endif /* MIME */ static struct swit packswit[] = { #define PAFISW 0 "file name", 0, #define PAHELP 1 "help", 4, NULL, 0 }; /* */ packcmd (args) char **args; { int msgp = 0, md, msgnum; char *cp, *file = NULL, buf[BUFSIZ], *msgs[MAXARGS]; struct stat st; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, packswit)) { case AMBIGSW: ambigsw (cp, packswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case PAHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, packswit); return; case PAFISW: if (!(file = *args++) || *file == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!file) file = "./msgbox"; file = path (file, TFILE); if (stat (file, &st) == NOTOK) { if (errno != ENOENT) { advise (file, "error on file"); goto done_pack; } md = getanswer (cp = concat ("Create file \"", file, "\"? ", NULLCP)); free (cp); if (!md) goto done_pack; } if (!msgp) msgs[msgp++] = "all"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) goto done_pack; m_setseq (mp); if ((md = mbx_open (file, getuid (), getgid (), m_gmprot ())) == NOTOK) { advise (file, "unable to open"); goto done_pack; } for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (pack (file, md, msgnum) == NOTOK) break; (void) mbx_close (file, md); if (mp -> hghsel != mp -> curmsg) m_setcur (mp, mp -> lowsel); done_pack: ; free (file); } /* */ int pack (mailbox, md, msgnum) char *mailbox; int md, msgnum; { register FILE *zp; if (Msgs[msgnum].m_bboard_id == 0) (void) readid (msgnum); zp = msh_ready (msgnum, 1); return mbx_write (mailbox, md, zp, Msgs[msgnum].m_bboard_id, 0L, ftell (zp), Msgs[msgnum].m_stop, 1, 1); } /* */ int packhak (args) char **args; { int result; char *cp, *file = NULL; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, packswit)) { case AMBIGSW: case UNKWNSW: case PAHELP: return NOTOK; case PAFISW: if (!(file = *args++) || *file == '-') return NOTOK; continue; } if (*cp == '+' || *cp == '@@') return NOTOK; } file = path (file ? file : "./msgbox", TFILE); result = access (file, 0) == NOTOK ? OK : NOTOK; free (file); return result; } /* */ static struct swit pickswit[] = { #define PIANSW 0 "and", 0, #define PIORSW 1 "or", 0, #define PINTSW 2 "not", 0, #define PILBSW 3 "lbrace", 0, #define PIRBSW 4 "rbrace", 0, #define PICCSW 5 "cc pattern", 0, #define PIDASW 6 "date pattern", 0, #define PIFRSW 7 "from pattern", 0, #define PISESW 8 "search pattern", 0, #define PISUSW 9 "subject pattern", 0, #define PITOSW 10 "to pattern", 0, #define PIOTSW 11 "-othercomponent pattern", 15, #define PIAFSW 12 "after date", 0, #define PIBFSW 13 "before date", 0, #define PIDFSW 14 "datefield field", 5, #define PISQSW 15 "sequence name", 0, #define PIPUSW 16 "public", 0, #define PINPUSW 17 "nopublic", 0, #define PIZRSW 18 "zero", 0, #define PINZRSW 19 "nozero", 0, #define PILISW 20 "list", 0, #define PINLISW 21 "nolist", 0, #define PIHELP 22 "help", 4, NULL, 0 }; /* */ pickcmd (args) char **args; { int zerosw = 1, msgp = 0, seqp = 0, vecp = 0, hi, lo, msgnum; char *cp, buf[BUFSIZ], *msgs[MAXARGS], *seqs[NATTRS], *vec[MAXARGS]; register FILE *zp; while (cp = *args++) { if (*cp == '-') { if (*++cp == '-') { vec[vecp++] = --cp; goto pattern; } switch (smatch (cp, pickswit)) { case AMBIGSW: ambigsw (cp, pickswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case PIHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, pickswit); return; case PICCSW: case PIDASW: case PIFRSW: case PISUSW: case PITOSW: case PIDFSW: case PIAFSW: case PIBFSW: case PISESW: vec[vecp++] = --cp; pattern: ; if (!(cp = *args++)) {/* allow -xyz arguments */ advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; case PIOTSW: advise (NULLCP, "internal error!"); return; case PIANSW: case PIORSW: case PINTSW: case PILBSW: case PIRBSW: vec[vecp++] = --cp; continue; case PISQSW: if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } if (seqp < NATTRS) seqs[seqp++] = cp; else { advise (NULLCP, "only %d sequences allowed!", NATTRS); return; } continue; case PIZRSW: zerosw++; continue; case PINZRSW: zerosw = 0; continue; case PIPUSW: /* not implemented */ case PINPUSW: case PILISW: case PINLISW: continue; } } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } vec[vecp] = NULL; if (!msgp) msgs[msgp++] = "all"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); interrupted = 0; if (!pcompile (vec, NULLCP)) return; lo = mp -> lowsel; hi = mp -> hghsel; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { zp = msh_ready (msgnum, 1); if (pmatches (zp, msgnum, fmsh ? 0L : Msgs[msgnum].m_start, fmsh ? 0L : Msgs[msgnum].m_stop)) { if (msgnum < lo) lo = msgnum; if (msgnum > hi) hi = msgnum; } else { mp -> msgstats[msgnum] &= ~SELECTED; mp -> numsel--; } } if (interrupted) return; mp -> lowsel = lo; mp -> hghsel = hi; if (mp -> numsel <= 0) { advise (NULLCP, "no messages match specification"); return; } seqs[seqp] = NULL; for (seqp = 0; seqs[seqp]; seqp++) { if (zerosw && !m_seqnew (mp, seqs[seqp], 0)) return; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) if (!m_seqadd (mp, seqs[seqp], msgnum, 0)) return; } printf ("%d hit%s\n", mp -> numsel, mp -> numsel == 1 ? "" : "s"); } /* */ static struct swit replswit[] = { #define REANSW 0 "annotate", 0, #define RENANSW 1 "noannotate", 0, #define RECCSW 2 "cc type", 0, #define RENCCSW 3 "nocc type", 0, #define REDFSW 4 "draftfolder +folder", 0, #define REDMSW 5 "draftmessage msg", 0, #define RENDFSW 6 "nodraftfolder", 0, #define REEDTSW 7 "editor editor", 0, #define RENEDSW 8 "noedit", 0, #define REFCCSW 9 "fcc +folder", 0, #define REFLTSW 10 "filter filterfile", 0, #define REFRMSW 11 "form formfile", 0, #define REINSW 12 "inplace", 0, #define RENINSW 13 "noinplace", 0, #define REQUSW 14 "query", 0, #define RENQUSW 15 "noquery", 0, #define REWHTSW 16 "whatnowproc program", 0, #define RENWTSW 17 "nowhatnow", 0, #define REWIDSW 19 "width columns", 0, #define REHELP 20 "help", 4, NULL, 0 }; /* */ replcmd (args) char **args; { int vecp = 1; char *cp, *msg = NULL, buf[BUFSIZ], *vec[MAXARGS]; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, replswit)) { case AMBIGSW: ambigsw (cp, replswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case REHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, replswit); return; case REANSW: /* not implemented */ case RENANSW: case REINSW: case RENINSW: continue; case REQUSW: case RENQUSW: case RENDFSW: case RENEDSW: case RENWTSW: vec[vecp++] = --cp; continue; case RECCSW: case RENCCSW: case REEDTSW: case REFCCSW: case REFLTSW: case REFRMSW: case REWIDSW: case REDFSW: case REDMSW: case REWHTSW: vec[vecp++] = --cp; if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else if (msg) { advise (NULLCP, "only one message at a time!"); return; } else msg = cp; } vec[0] = cmd_name; vec[vecp++] = "-file"; vec[vecp] = NULL; if (!msg) msg = "cur"; if (!m_convert (mp, msg)) return; m_setseq (mp); if (mp -> numsel > 1) { advise (NULLCP, "only one message at a time!"); return; } (void) process (mp -> hghsel, cmd_name, vecp, vec); m_setcur (mp, mp -> hghsel); } /* */ static struct swit rmmswit[] = { #define RMHELP 0 "help", 4, NULL, 0 }; /* */ rmmcmd (args) char **args; { int msgp = 0, msgnum; char *cp, buf[BUFSIZ], *msgs[MAXARGS]; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, rmmswit)) { case AMBIGSW: ambigsw (cp, rmmswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case RMHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, rmmswit); return; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!msgp) msgs[msgp++] = "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); rmm (); } /* */ static rmm () { register int msgnum, vecp; register char *cp; char buffer[BUFSIZ], *vec[MAXARGS]; if (fmsh) { if (rmmproc) { if (mp -> numsel > MAXARGS - 1) { advise (NULLCP, "more than %d messages for %s exec", MAXARGS - 1, rmmproc); return; } vecp = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) vec[vecp++] = getcpy (m_name (msgnum)); vec[vecp] = NULL; forkcmd (vec, rmmproc); for (vecp = 0; vec[vecp]; vecp++) free (vec[vecp]); } else for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { (void) strcpy (buffer, m_backup (cp = m_name (msgnum))); if (rename (cp, buffer) == NOTOK) admonish (buffer, "unable to rename %s to", cp); } } for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { mp -> msgstats[msgnum] |= DELETED; mp -> msgstats[msgnum] &= ~EXISTS; #ifdef MPOP #ifdef BPOP if (pmsh && pop_dele (msgnum) != OK) fprintf (stderr, "%s", response); #endif #endif /* MPOP */ } if ((mp -> nummsg -= mp -> numsel) <= 0) { if (fmsh) admonish (NULLCP, "no messages remaining in +%s", fmsh); else admonish (NULLCP, "no messages remaining in %s", mp -> foldpath); mp -> lowmsg = mp -> hghmsg = mp -> nummsg = 0; } if (mp -> lowsel == mp -> lowmsg) { for (msgnum = mp -> lowmsg + 1; msgnum <= mp -> hghmsg; msgnum++) if (mp -> msgstats[msgnum] & EXISTS) break; mp -> lowmsg = msgnum; } if (mp -> hghsel == mp -> hghmsg) { for (msgnum = mp -> hghmsg - 1; msgnum >= mp -> lowmsg; msgnum--) if (mp -> msgstats[msgnum] & EXISTS) break; mp -> hghmsg = msgnum; } mp -> msgflags |= MODIFIED; modified++; } /* */ static struct swit scanswit[] = { #define SCCLR 0 "clear", 0, #define SCNCLR 1 "noclear", 0, #define SCFORM 2 "form formatfile", 0, #define SCFMT 3 "format string", 5, #define SCHEAD 4 "header", 0, #define SCNHEAD 5 "noheader", 0, #define SCWID 6 "width columns", 0, #define SCHELP 7 "help", 4, NULL, 0 }; /* */ scancmd (args) char **args; { #define equiv(a,b) (a ? b && !strcmp (a, b) : !b) int clearsw = 0, headersw = 0, width = 0, msgp = 0, msgnum, optim, state; char *cp, *form = NULL, *format = NULL, buf[BUFSIZ], *nfs, *msgs[MAXARGS]; register FILE *zp; #ifdef MPOP #ifdef BPOP static int p_optim = 0; #endif #endif /* MPOP */ static int s_optim = 0; static char *s_form = NULL, *s_format = NULL; while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, scanswit)) { case AMBIGSW: ambigsw (cp, scanswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case SCHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, scanswit); return; case SCCLR: clearsw++; continue; case SCNCLR: clearsw = 0; continue; case SCHEAD: headersw++; continue; case SCNHEAD: headersw = 0; continue; case SCFORM: if (!(form = *args++) || *form == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } format = NULL; continue; case SCFMT: if (!(format = *args++) || *format == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } form = NULL; continue; case SCWID: if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } width = atoi (cp); continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!msgp) msgs[msgp++] = "all"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); nfs = new_fs (form, format, FORMAT); if (scanl) { /* force scansbr to (re)compile format */ (void) free (scanl); scanl = NULL; } if (s_optim == 0) { s_optim = optim = 1; s_form = form ? getcpy (form) : NULL; s_format = format ? getcpy (format) : NULL; #ifdef MPOP #ifdef BPOP if (pmsh) { int i; char *dp, *ep, *fp; if (width == 0) width = sc_width (); for (dp = nfs, i = 0; *dp; dp++, i++) if (*dp == '\\' || *dp == '"' || *dp == '\n') i++; i++; if ((ep = malloc ((unsigned) i)) == NULL) adios (NULLCP, "out of memory"); for (dp = nfs, fp = ep; *dp; dp++) { if (*dp == '\n') { *fp++ = '\\', *fp++ = 'n'; continue; } if (*dp == '"' || *dp == '\\') *fp++ = '\\'; *fp++ = *dp; } *fp = NULL; if (pop_command ("XTND SCAN %d \"%s\"", width, ep) == OK) p_optim = 1; free (ep); } #endif #endif /* MPOP */ } else optim = equiv (s_form, form) && equiv (s_format, format); #ifdef MPOP #ifdef BPOP if (p_optim && optim) { for (msgnum = mp -> lowmsg; msgnum <= mp -> hghmsg; msgnum++) if (!(mp -> msgstats[msgnum] & SELECTED) || Msgs[msgnum].m_scanl) break; if (msgnum > mp -> hghmsg && pop_command ("LIST") == OK) { fprintf (stderr, "Stand-by..."); fflush (stderr); for (;;) { int size; switch (pop_multiline ()) { case NOTOK: fprintf (stderr, "%s", response); /* and fall... */ case DONE: fprintf (stderr,"\n"); break; case OK: if (sscanf (response, "%d %d", &msgnum, &size) == 2 && mp -> lowmsg <= msgnum && msgnum <= mp -> hghmsg && (cp = index (response, '#')) && *++cp) Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP); continue; } break; } } } #endif #endif /* MPOP */ interrupted = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { if (optim && Msgs[msgnum].m_scanl) printf ("%s", Msgs[msgnum].m_scanl); else { #ifdef MPOP #ifdef BPOP if (p_optim && optim && (mp -> msgstats[msgnum] & VIRTUAL) && pop_command ("LIST %d", msgnum) == OK && (cp = index (response, '#')) && *++cp) { Msgs[msgnum].m_scanl = concat (cp, "\n", NULLCP); printf ("%s", Msgs[msgnum].m_scanl); continue; } #endif #endif /* MPOP */ zp = msh_ready (msgnum, 0); switch (state = scan (zp, msgnum, 0, nfs, width, msgnum == mp -> curmsg, mp -> msgstats[msgnum] & UNSEEN, /* ?? */ headersw, fmsh ? fmsh : mp -> foldpath, fmsh ? 0L : (long) (Msgs[msgnum].m_stop - Msgs[msgnum].m_start), 1)) { case SCNMSG: case SCNENC: case SCNERR: if (optim) Msgs[msgnum].m_scanl = getcpy (scanl); break; default: advise (NULLCP, "scan() botch (%d)", state); return; case SCNEOF: printf ("%*d empty\n", DMAXFOLDER, msgnum); break; } } headersw = 0; } if (clearsw) clear_screen (); } /* */ static struct swit showswit[] = { #define SHDRAFT 0 "draft", 5, #define SHFORM 1 "form formfile", 4, #define SHPROG 2 "moreproc program", 4, #define SHNPROG 3 "nomoreproc", 3, #define SHLEN 4 "length lines", 4, #define SHWID 5 "width columns", 4, #define SHSHOW 6 "showproc program", 4, #define SHNSHOW 7 "noshowproc", 3, #define SHHEAD 8 "header", 4, #define SHNHEAD 9 "noheader", 3, #define SHHELP 10 "help", 4, NULL, 0 }; /* */ showcmd (args) char **args; { int headersw = 1, nshow = 0, msgp = 0, vecp = 1, mhl = 0, seen = 0, mode = 0, i, msgnum; char *cp, *proc = showproc, buf[BUFSIZ], *msgs[MAXARGS], *vec[MAXARGS]; if (uleq (cmd_name, "next")) mode = 1; else if (uleq (cmd_name, "prev")) mode = -1; while (cp = *args++) { if (*cp == '-') switch (i = smatch (++cp, showswit)) { case AMBIGSW: ambigsw (cp, showswit); return; case UNKWNSW: case SHNPROG: vec[vecp++] = --cp; continue; case SHHELP: (void) sprintf (buf, "%s %s[switches] [switches for showproc]", cmd_name, mode ? NULL : "[msgs] "); help (buf, showswit); return; case SHFORM: case SHPROG: case SHLEN: case SHWID: vec[vecp++] = --cp; if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } vec[vecp++] = cp; continue; case SHHEAD: headersw++; continue; case SHNHEAD: headersw = 0; continue; case SHSHOW: if (!(proc = *args++) || *proc == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } nshow = 0; continue; case SHNSHOW: nshow++; continue; case SHDRAFT: advise (NULLCP, "sorry, -%s not allowed!", showswit[i].sw); return; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else if (mode) { fprintf (stderr, "usage: %s [switches] [switches for showproc]\n", cmd_name); return; } else msgs[msgp++] = cp; } vec[vecp] = NULL; if (!msgp) msgs[msgp++] = mode > 0 ? "next" : mode < 0 ? "prev" : "cur"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); #ifdef MIME if (!nshow && !getenv ("NOMHNPROC")) for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if ((mp -> msgstats[msgnum] & SELECTED) && nontext (msgnum)) { proc = (cp = m_find ("mhnproc")) ? cp : "mhn"; vec[vecp++] = "-show"; vec[vecp++] = "-file"; vec[vecp] = NULL; goto finish; } #endif /* MIME */ if (nshow) proc = "cat"; else if (strcmp (showproc, "mhl") == 0) { proc = mhlproc; mhl++; } finish: ; seen = m_seqflag (mp, "unseen"); vec[0] = r1bindex (proc, '/'); if (mhl) { msgp = vecp; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { vec[vecp++] = getcpy (m_name (msgnum)); if (seen) (void) m_seqdel (mp, "unseen", msgnum); } vec[vecp] = NULL; if (mp -> numsel == 1 && headersw) show (mp -> lowsel); (void) mhlsbr (vecp, vec, mhl_action); m_eomsbr ((int (*)()) 0); while (msgp < vecp) free (vec[msgp++]); } else { interrupted = 0; for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel && !interrupted; msgnum++) if (mp -> msgstats[msgnum] & SELECTED) { switch (ask (msgnum)) { case NOTOK: /* QUIT */ break; case OK: /* INTR */ continue; default: if (mp -> numsel == 1 && headersw) show (msgnum); if (nshow) copy_message (msgnum, stdout); else (void) process (msgnum, proc, vecp, vec); if (seen) (void) m_seqdel (mp, "unseen", msgnum); continue; } break; } } m_setcur (mp, mp -> hghsel); } /* */ static show (msgnum) int msgnum; { if (Msgs[msgnum].m_bboard_id == 0) (void) readid (msgnum); printf ("(Message %d", msgnum); if (Msgs[msgnum].m_bboard_id > 0) printf (", %s: %d", BBoard_ID, Msgs[msgnum].m_bboard_id); printf (")\n"); } /* ARGSUSED */ static int eom_action (c) int c; { return (ftell (mhlfp) >= Msgs[mhlnum].m_stop); } static FP mhl_action (name) char *name; { int msgnum; if ((msgnum = m_atoi (name)) < mp -> lowmsg || msgnum > mp -> hghmsg || !(mp -> msgstats[msgnum] & EXISTS)) return NULL; mhlnum = msgnum; mhlfp = msh_ready (msgnum, 1); if (!fmsh) m_eomsbr (eom_action); return mhlfp; } /* */ static ask (msgnum) int msgnum; { char buf[BUFSIZ]; if (mp -> numsel == 1 || !interactive || redirected) return DONE; if (SOprintf ("Press to list \"%d\"...", msgnum)) { if (mp -> lowsel != msgnum) printf ("\n\n\n"); printf ("Press to list \"%d\"...", msgnum); } (void) fflush (stdout); buf[0] = 0; #ifndef BSD42 (void) read (fileno (stdout), buf, sizeof buf); #else /* BSD42 */ switch (setjmp (sigenv)) { case OK: should_intr = 1; (void) read (fileno (stdout), buf, sizeof buf);/* fall... */ default: should_intr = 0; break; } #endif /* BSD42 */ if (index (buf, '\n') == NULL) (void) putchar ('\n'); if (told_to_quit) { told_to_quit = interrupted = 0; return NOTOK; } if (interrupted) { interrupted = 0; return OK; } return DONE; } /* */ #ifdef MIME #include "../h/mhn.h" static int nontext (msgnum) int msgnum; { int result, state; register char *bp, *dp; char *chset, *cp, buf[BUFSIZ], name[NAMESZ]; FILE *fp; if (Msgs[msgnum].m_flags & MHNCHK) return (Msgs[msgnum].m_flags & MHNYES); Msgs[msgnum].m_flags |= MHNCHK; fp = msh_ready (msgnum, 1); if (!(chset = getenv ("MM_CHARSET"))) chset = "us-ascii"; for (state = FLD;;) switch (state = m_getfld (state, name, buf, sizeof buf, fp)) { case FLD: case FLDPLUS: case FLDEOF: if (uleq (name, TYPE_FIELD)) { int passno; char c; cp = add (buf, NULLCP); while (state == FLDPLUS) { state = m_getfld (state, name, buf, sizeof buf, fp); cp = add (buf, cp); } bp = cp; passno = 1; again: ; for (; isspace (*bp); bp++) continue; if (*bp == '(') { int i; for (bp++, i = 0;;) { switch (*bp++) { case '\0': invalid: ; result = 0; goto out; case '\\': if (*bp++ == '\0') goto invalid; continue; case '(': i++; /* and fall... */ default: continue; case ')': if (--i < 0) break; continue; } break; } } if (passno == 2) { if (*bp != '/') goto invalid; bp++; passno = 3; goto again; } for (dp = bp; istoken (*dp); dp++) continue; c = *dp, *dp = NULL; if (*bp == NULL) goto invalid; if (passno > 1) { if (result = !uleq (bp, "plain")) goto out; *dp = c; for (dp++; isspace (*dp); dp++) continue; if (result = !uprf (dp, "charset")) goto invalid; dp += sizeof "charset" - 1; while (isspace (*dp)) dp++; if (*dp++ != '=') goto invalid; while (isspace (*dp)) dp++; if (*dp == '"') { if (bp = index (++dp, '"')) *bp = NULL; } else for (bp = dp; *bp; bp++) if (isspace (*bp)) { *bp = NULL; break; } if ((result = !uleq (dp, chset)) && uleq (dp, "us-ascii") && uleq (chset, "iso-8859-1")) result = 0; } else if (!(result = !uleq (bp, "text"))) { *dp = c; bp = dp; passno = 2; goto again; } out: ; free (cp); if (result) { Msgs[msgnum].m_flags |= MHNYES; return result; } break; } if (uleq (name, ENCODING_FIELD)) { cp = add (buf, NULLCP); while (state == FLDPLUS) { state = m_getfld (state, name, buf, sizeof buf, fp); cp = add (buf, cp); } for (bp = cp; isspace (*bp); bp++) continue; for (dp = bp; istoken (*dp); dp++) continue; *dp = NULL; result = !uleq (bp, "7bit") && !uleq (bp, "8bit") && !uleq (bp, "binary"); free (cp); if (result) { Msgs[msgnum].m_flags |= MHNYES; return result; } break; } while (state == FLDPLUS) state = m_getfld (state, name, buf, sizeof buf, fp); break; default: return 0; } } #endif /* MIME */ /* */ static struct swit sortswit[] = { #define SODATE 0 "datefield field", 0, #define SOSUBJ 1 "textfield field", 0, #define SONSUBJ 2 "notextfield", 0, #define SOLIMT 3 "limit days", 0, #define SONLIMT 4 "nolimit", 0, #define SOVERB 5 "verbose", 0, #define SONVERB 6 "noverbose", 0, #define SOHELP 7 "help", 4, NULL, 0 }; /* */ sortcmd (args) char **args; { int msgp = 0, msgnum; char *cp, *datesw = NULL, *subjsw = NULL, buf[BUFSIZ], *msgs[MAXARGS]; struct tws tb, *tw; if (fmsh) { forkcmd (args, cmd_name); return; } while (cp = *args++) { if (*cp == '-') switch (smatch (++cp, sortswit)) { case AMBIGSW: ambigsw (cp, sortswit); return; case UNKWNSW: fprintf (stderr, "-%s unknown\n", cp); return; case SOHELP: (void) sprintf (buf, "%s [msgs] [switches]", cmd_name); help (buf, sortswit); return; case SODATE: if (datesw) { advise (NULLCP, "only one date field at a time!"); return; } if (!(datesw = *args++) || *datesw == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } continue; case SOSUBJ: if (subjsw) { advise (NULLCP, "only one text field at a time!"); return; } if (!(subjsw = *args++) || *subjsw == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } continue; case SONSUBJ: subjsw = (char *)0; continue; case SOLIMT: /* too hard */ if (!(cp = *args++) || *cp == '-') { advise (NULLCP, "missing argument to %s", args[-2]); return; } case SONLIMT: case SOVERB: /* not implemented */ case SONVERB: continue; } if (*cp == '+' || *cp == '@@') { advise (NULLCP, "sorry, no folders allowed!"); return; } else msgs[msgp++] = cp; } if (!msgp) msgs[msgp++] = "all"; if (!datesw) datesw = "Date"; for (msgnum = 0; msgnum < msgp; msgnum++) if (!m_convert (mp, msgs[msgnum])) return; m_setseq (mp); twscopy (&tb, dtwstime ()); for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { if (Msgs[msgnum].m_scanl) { free (Msgs[msgnum].m_scanl); Msgs[msgnum].m_scanl = NULL; } if (mp -> msgstats[msgnum] & SELECTED) { if (getws (datesw, subjsw, msgnum, &Msgs[msgnum])) twscopy (&Msgs[msgnum].m_tb, msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb); } else /* m_scaln is already NULL */ twscopy (&Msgs[msgnum].m_tb, &tb); Msgs[msgnum].m_stats = mp -> msgstats[msgnum]; if (mp -> curmsg == msgnum) Msgs[msgnum].m_stats |= CUR; } qsort ((char *) &Msgs[mp -> lowsel], mp -> hghsel - mp -> lowsel + 1, sizeof (struct Msg), subjsw ? subsort : msgsort); for (msgnum = mp -> lowsel; msgnum <= mp -> hghsel; msgnum++) { if (subjsw && Msgs[msgnum].m_scanl) { free (Msgs[msgnum].m_scanl); /* from subjsort */ Msgs[msgnum].m_scanl = NULL; } mp -> msgstats[msgnum] = Msgs[msgnum].m_stats & ~CUR; if (Msgs[msgnum].m_stats & CUR) m_setcur (mp, msgnum); } mp -> msgflags |= MODIFIED; modified++; } /* */ /* * getws - parse message, and get date and subject if needed. We'll use * the msgp->m_tb tws struct for the date, and overload the msgp->m_scanl * field with our subject string. */ static int getws (datesw, subjsw, msgnum, msgp) char *datesw, *subjsw; int msgnum; struct Msg *msgp; { int state, gotdate = 0; char *bp, buf[BUFSIZ], name[NAMESZ]; struct tws *tw = (struct tws *)0; register FILE *zp; zp = msh_ready (msgnum, 0); for (state = FLD;;) { switch (state = m_getfld (state, name, buf, sizeof buf, zp)) { case FLD: case FLDEOF: case FLDPLUS: if (uleq (name, datesw)) { bp = getcpy (buf); while (state == FLDPLUS) { state = m_getfld (state, name, buf, sizeof buf, zp); bp = add (buf, bp); } if ((tw = dparsetime (bp)) == NULL) admonish (NULLCP, "unable to parse %s field in message %d", datesw, msgnum); else twscopy (&(msgp->m_tb), tw); free (bp); if (!subjsw) /* not using this, or already done */ break; /* all done! */ gotdate++; } else if (subjsw && uleq(name, subjsw)) { bp = getcpy (buf); while (state == FLDPLUS) { state = m_getfld (state, name, buf, sizeof buf, zp); bp = add (buf, bp); } msgp->m_scanl = sosmash(subjsw, bp); if (gotdate) break; /* date done so we're done */ else subjsw = (char *)0;/* subject done, need date */ } else { while (state == FLDPLUS) /* flush this one */ state = m_getfld (state, name, buf, sizeof buf, zp); } continue; case BODY: case BODYEOF: case FILEEOF: break; case LENERR: case FMTERR: admonish (NULLCP, "format error in message %d", msgnum); if (msgp->m_scanl) { /* this might need free'd */ free (msgp->m_scanl); /* probably can't use subj anyway */ msgp->m_scanl = NULL; } return NOTOK; default: adios (NULLCP, "internal error -- you lose"); } break; } if (tw) return OK; /* not an error if subj not found */ admonish (NULLCP, "no %s field in message %d", datesw, msgnum); return NOTOK; /* NOTOK means use some other date */ } /* sort routines */ static int msgsort (a, b) struct Msg *a, *b; { return twsort (&a -> m_tb, &b -> m_tb); } static int subsort (a, b) struct Msg *a, *b; { register int i; if (a->m_scanl && b->m_scanl) if (i = strcmp (a->m_scanl, b->m_scanl)) return (i); return twsort (&a -> m_tb, &b -> m_tb); } /* * try to make the subject "canonical": delete leading "re:", everything * but letters & smash letters to lower case. */ static char * sosmash (subj, s) char *subj; register char *s; { register char *cp, *dp, c; if (s) { cp = s; dp = s; /* dst pointer */ if (uleq (subj, "subject")) while (c = *cp) { if (! isspace(c)) { if(uprf(cp, "re:")) cp += 2; else { if (isalnum(c)) *dp++ = isupper(c) ? tolower(c) : c; break; } } cp++; } while (c = *cp++) { if (isalnum(c)) *dp++ = isupper(c) ? tolower(c) : c; } *dp = '\0'; } return s; } /* */ static int process (msgnum, proc, vecp, vec) int msgnum, vecp; char *proc, **vec; { int child_id, status; char tmpfil[80]; FILE *out; if (fmsh) { (void) strcpy (tmpfil, m_name (msgnum)); (void) m_delete (pfolder); m_replace (pfolder, fmsh); m_sync (mp); m_update (); goto ready; } (void) strcpy (tmpfil, m_scratch ("", invo_name)); if ((out = fopen (tmpfil, "w")) == NULL) { int olderr; extern int errno; char newfil[80]; olderr = errno; (void) strcpy (newfil, m_tmpfil (invo_name)); if ((out = fopen (newfil, "w")) == NULL) { errno = olderr; advise (tmpfil, "unable to create temporary file"); return NOTOK; } else (void) strcpy (tmpfil, newfil); } copy_message (msgnum, out); (void) fclose (out); ready: ; (void) fflush (stdout); switch (child_id = fork ()) { case NOTOK: advise ("fork", "unable to"); status = NOTOK; break; case OK: closefds (3); (void) signal (SIGINT, istat); (void) signal (SIGQUIT, qstat); vec[vecp++] = tmpfil; vec[vecp] = NULL; execvp (proc, vec); fprintf (stderr, "unable to exec "); perror (proc); _exit (1); default: status = pidXwait (child_id, NULLCP); break; } if (!fmsh) (void) unlink (tmpfil); return status; } /* */ static copy_message (msgnum, out) int msgnum; FILE * out; { long pos; static char buffer[BUFSIZ]; register FILE * zp; zp = msh_ready (msgnum, 1); if (fmsh) { while (fgets (buffer, sizeof buffer, zp) != NULL) { fputs (buffer, out); if (interrupted && out == stdout) break; } } else { pos = ftell (zp); while (fgets (buffer, sizeof buffer, zp) != NULL && pos < Msgs[msgnum].m_stop) { fputs (buffer, out); pos += (long) strlen (buffer); if (interrupted && out == stdout) break; } } } static copy_digest (msgnum, out) int msgnum; FILE * out; { char c; long pos; static char buffer[BUFSIZ]; register FILE *zp; c = '\n'; zp = msh_ready (msgnum, 1); if (!fmsh) pos = ftell (zp); while (fgets (buffer, sizeof buffer, zp) != NULL && !fmsh && pos < Msgs[msgnum].m_stop) { if (c == '\n' && *buffer == '-') (void) fputc (' ', out); fputs (buffer, out); c = buffer[strlen (buffer) - 1]; if (!fmsh) pos += (long) strlen (buffer); if (interrupted && out == stdout) break; } } @ 1.31 log @mime changes from mtr @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.30 1995/12/06 23:44:31 jromine Exp jromine $"; d2570 1 a2570 1 headersw ? (fmsh ? fmsh : mp -> foldpath) : (char *)0, @ 1.30 log @null ptr fix @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.29 1994/04/21 18:20:50 jromine Exp jromine $"; d26 3 d914 1 a944 2 case FOMISW: case FONMISW: d947 10 d980 1 d1022 1 a1022 1 forw (cmd_name, filter, vecp, vec); d1030 3 a1032 2 static forw (proc, filter, vecp, vec) int vecp; d1044 4 d1082 139 d1260 20 d1293 3 d2570 1 a2570 1 headersw, fmsh ? fmsh : mp -> foldpath, d2974 1 a2974 1 goto out; @ 1.29 log @update for scansbr.c -- overload {folder}.c_flags with hdrflg @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.28 1993/12/01 03:50:31 jromine Exp jromine $"; d1340 1 d1346 1 a1346 1 m_seq (mp, mp -> msgattrs[i])); d1349 3 a1351 1 printf ("%s%s: %s\n", seqs[seqp], m_seq (mp, seqs[seqp])); @ 1.28 log @fixes from mtr @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.27 1993/10/26 20:09:54 jromine Exp jromine $"; d2387 1 a2387 1 headersw ? (fmsh ? fmsh : mp -> foldpath) : (char *)0, @ 1.27 log @test for iso-8859-1 and us-ascii, 8bit, binary and 7bit @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.25 1992/12/15 00:20:22 jromine Exp $"; a22 1 #include "../h/mshsbr.h" d25 1 @ 1.26 log @re-order mshsbr.h include @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.25 1992/12/15 00:20:22 jromine Exp jromine $"; d23 1 a25 1 #include "../h/mshsbr.h" d2711 2 a2712 1 char *cp, d2723 3 d2800 1 a2800 3 dp++; if (strlen (dp) >= sizeof "us-ascii\"" && *(bp = dp + sizeof "us-ascii" - 1)=='"') d2804 9 a2812 5 if (strlen (dp) >= sizeof "us-ascii" && isspace (*(bp = dp + sizeof "us-ascii" - 1))) *bp = NULL; result = !uleq (dp, "us-ascii"); d2842 3 a2844 2 if (result = !uleq (bp, "7bit")) Msgs[msgnum].m_flags |= MHNYES; @ 1.25 log @endif sugar @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.24 1992/11/24 18:26:05 jromine Exp jromine $"; a22 1 #include "../h/mshsbr.h" d25 1 @ 1.24 log @add decl @ text @d3 2 a4 2 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.23 1992/11/04 00:53:32 jromine Exp jromine $"; #endif lint d859 1 a859 1 #else MIME d861 1 a861 1 #endif MIME d1301 1 a1301 1 #else MTR d1304 1 a1304 1 #endif MTR d2672 1 a2672 1 #else BSD42 d2682 1 a2682 1 #endif BSD42 @ 1.23 log @locale @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.22 1992/10/29 03:49:31 jromine Exp jromine $"; d42 3 @ 1.22 log @fix burst -- previously it was losing the last message(!) @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.21 1992/10/26 22:21:33 jromine Exp jromine $"; d3124 1 a3124 1 while (c = *cp++) { d3126 1 a3126 2 if ((c == 'R' || c == 'r') && (cp[0] == 'e' || cp[0] == 'E') && cp[1] == ':') d3134 1 @ 1.21 log @turn off MPOP if NNTP on @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.20 1992/10/17 00:24:25 jromine Exp jromine $"; d355 1 d367 1 a367 1 for (msgp = 1; msgp <= MAXFOLDER;) { d378 2 a379 2 fgets (buffer, sizeof buffer, zp) != NULL && pos < Msgs[msgnum].m_stop; d382 2 a383 2 && peekc (zp) == '\n' && (msgp == 1 || c == '\n')) d390 1 a390 1 smsgs[msgp++].m_stop = c == '\n' && wasdlm ? pos - 1 : pos; d392 1 a392 1 if (wasdlm) { a393 2 msgp++; /* fake "End of XXX Digest" */ } d399 1 a399 1 switch (--msgp) { /* toss "End of XXX Digest" */ d411 1 a411 3 msgp - 1, msgp - 1 != 1 ? "s" : "", msgnum); if (msgp == 2) msgp++; a414 1 msgp--; d423 2 a424 2 mp -> hghmsg += msgp - 1; mp -> nummsg += msgp - 1; d426 1 a426 1 mp -> hghsel += msgp - 1; d428 1 a428 1 if (inplace && msgp > 1) d449 2 a450 2 i = inplace ? msgnum + msgp - 1 : mp -> hghmsg; for (j = msgp; j >= (inplace ? 1 : 2); i--, j--) { @ 1.20 log @#ifdef botch @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.19 1992/10/17 00:19:58 jromine Exp jromine $"; d51 3 @ 1.19 log @typo @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.18 1992/10/16 22:34:17 jromine Exp jromine $"; d2316 1 d2321 1 @ 1.18 log @MIME changes @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.17 1992/10/16 21:50:20 jromine Exp jromine $"; a2178 7 #ifdef MPOP #ifdef BPOP extern int pmsh; extern char response[]; #endif #endif /* MPOP */ @ 1.17 log @#ifdef MIME @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.16 1992/10/16 21:47:40 jromine Exp jromine $"; d2543 1 a2543 1 if (!nshow && (cp = m_find ("mhnproc")) && !getenv ("NOMHNPROC")) d2546 1 a2546 1 proc = cp; d2710 6 a2715 2 int state; char buf[BUFSIZ], d2731 2 a2732 6 int passno, result; register char *bp, *dp; char c, *cp; d2768 1 a2768 1 break; d2780 2 a2781 2 c = *dp, *dp = '\0'; if (*bp == '\0') d2785 25 a2809 1 Msgs[msgnum].m_flags |= MHNYES; d2822 26 a2847 1 return result; @ 1.16 log @#ifdef MIME @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.15 1992/10/16 21:37:18 jromine Exp jromine $"; d2542 1 d2552 1 @ 1.15 log @MIME changes @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.14 1992/10/16 16:51:55 jromine Exp jromine $"; d2701 1 d2806 1 @ 1.14 log @mobile pop (MPOP) ifdefs @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.13 1992/05/19 21:03:35 jromine Exp jromine $"; d855 6 d888 5 a892 1 #define FOWHTSW 13 d894 1 a894 1 #define FONWTSW 14 d896 1 a896 1 #define FOHELP 15 d939 2 d1368 170 @ 1.13 log @AIX @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.12 1992/03/03 17:09:57 jromine Exp jromine $"; d51 1 a51 1 d56 1 d1941 1 d1946 1 d1998 1 d2003 1 a2004 1 d2024 1 d2028 1 d2107 1 d2179 1 d2189 1 d2202 1 @ 1.12 log @fixes from mtr @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.11 1992/02/08 00:10:26 jromine Exp jromine $"; d2555 1 a2555 1 case NULL: d2560 1 a2560 1 if (*bp++ == NULL) d2585 2 a2586 2 c = *dp, *dp = NULL; if (*bp == NULL) @ 1.11 log @fixes from mrose @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.10 1992/02/05 07:26:30 jromine Exp jromine $"; d51 6 d1940 4 @ 1.10 log @put unseen sequence in mh-format @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.9 1992/01/31 22:19:11 jromine Exp jromine $"; d2127 35 @ 1.9 log @kerberos @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.8 1992/01/31 16:33:46 jromine Exp jromine $"; d1985 6 d2010 3 d2090 34 d2136 13 d2151 2 a2152 1 msgnum == mp -> curmsg, @ 1.8 log @Multimedia MH @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.7 1992/01/23 22:58:03 jromine Exp $"; d11 3 d15 3 d125 1 a125 1 NULL, NULL d231 1 a231 1 NULL, NULL d366 1 a366 1 for (c = NULL; d484 1 a484 1 NULL, NULL d661 1 a661 1 NULL, NULL d746 1 a746 1 if (*folder == NULL) { d882 1 a882 1 NULL, NULL d968 1 a968 1 vec[0] = mktemp (buf); d1160 1 a1160 1 NULL, NULL d1356 1 a1356 1 NULL, NULL d1546 1 a1546 1 NULL, NULL d1749 1 a1749 1 NULL, NULL d1850 1 a1850 1 NULL, NULL d1980 1 a1980 1 NULL, NULL d2148 1 a2148 1 NULL, NULL d2376 1 a2376 1 buf[0] = NULL; d2532 1 a2532 1 NULL, NULL @ 1.7 log @change call to scan(...hdrflag...) @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.6 1991/01/14 16:48:39 mh Exp jromine $"; d2242 10 d2260 1 d2397 107 @ 1.6 log @add -[no]rmmproc to refile delete -[no]format from repl still need to add -[no]dashmunging to forw jlr @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id: mshcmds.c,v 1.5 90/04/05 15:01:41 sources Exp Locker: mh $"; d2089 2 a2090 1 msgnum == mp -> curmsg, headersw, @ 1.5 log @add ID @ text @d3 1 a3 1 static char ident[] = "@@(#)$Id:$"; d471 5 a475 1 #define FIHELP 7 d530 2 d1726 1 a1726 5 #define REFRSW 12 "format", 5, #define RENFRSW 13 "noformat", 7, #define REINSW 14 d1728 1 a1728 1 #define RENINSW 15 d1730 1 a1730 1 #define REQUSW 16 d1732 1 a1732 1 #define RENQUSW 17 d1734 1 a1734 1 #define REWHTSW 18 d1736 1 a1736 1 #define RENWTSW 19 d1738 1 a1738 1 #define REWIDSW 20 d1740 1 a1740 1 #define REHELP 21 a1781 2 case REFRSW: case RENFRSW: @ 1.4 log @all arbitrary textfields in sortm @ text @d2 3 @ 1.3 log @add sortm -[no]subject and (unimplemented) -[no]limit @ text @d2389 9 a2397 1 #define SOVERB 1 d2399 1 a2399 1 #define SONVERB 2 a2400 8 #define SOSUBJ 3 "subject", 0, #define SONSUBJ 4 "nosubject", 0, #define SOLIMT 5 "limit days", 0, #define SONLIMT 6 "nolimit", 0, d2416 1 a2420 1 register int subjsw = 0; d2453 8 a2460 1 subjsw++; d2463 1 a2463 1 subjsw = 0; d2467 4 d2538 3 a2540 3 char *datesw; int msgnum, subjsw; /* on entry, 0=no, 1=yes. internal -1=date_done */ d2543 2 a2544 1 int state; d2572 1 a2572 1 subjsw = -1; /* now looking for subject alone */ d2574 1 a2574 1 else if (subjsw && uleq(name, "subject")) { d2580 2 a2581 2 msgp->m_scanl = sosmash(bp); if (subjsw < 0) d2584 1 a2584 1 subjsw = 0; /* subject done, need date */ d2644 2 a2645 1 sosmash (s) d2654 11 a2664 9 while (c = *cp++) { if (! isspace(c)) { if ((c == 'R' || c == 'r') && (cp[0] == 'e' || cp[0] == 'E') && cp[1] == ':') cp += 2; else { if (isalpha(c)) *dp++ = islower(c) ? c : tolower(c); break; a2666 1 } d2668 2 a2669 2 if (isalpha(c)) *dp++ = islower(c) ? c : tolower(c); @ 1.2 log @ANSI Compilance @ text @d38 3 a40 2 static int msgsort (); static struct tws *getws (); d2393 9 a2401 1 #define SOHELP 3 d2420 1 d2452 9 d2490 3 a2492 2 if ((tw = getws (datesw, msgnum)) == NULL) tw = msgnum != mp -> lowsel ? &Msgs[msgnum - 1].m_tb : &tb; d2494 2 a2495 3 else tw = &tb; twscopy (&Msgs[msgnum].m_tb, tw); d2502 2 a2503 1 sizeof (struct Msg), msgsort); d2506 4 d2521 6 a2526 1 static struct tws *getws (datesw, msgnum) d2528 3 a2530 1 int msgnum; d2536 1 a2536 1 struct tws *tw; d2540 1 a2540 1 for (state = FLD;;) d2555 2 d2558 3 a2560 1 return tw; d2562 16 a2577 4 while (state == FLDPLUS) state = m_getfld (state, name, buf, sizeof buf, zp); if (state != FLDEOF) continue; d2582 1 a2582 2 admonish (NULLCP, "no %s field in message %d", datesw, msgnum); return NULL; d2587 5 a2591 1 return NULL; d2596 7 d2605 1 d2612 49 @ 1.1 log @Initial revision @ text @d31 2 a32 2 int eom_action (); FP mhl_action (); d35 2 d38 2 a39 2 int msgsort (); struct tws *getws (); @