📄 mhlsbr.c
字号:
/* mhlsbr.c - implement the "nifty" message lister */#ifndef lintstatic char ident[] = "@(#)$Id: mhlsbr.c,v 1.2 90/11/25 19:04:55 sharpe Exp $";#endif lint#include "../h/mh.h"#include "../h/addrsbr.h"#include "../h/formatsbr.h"#include "../zotnet/tws.h"#include <ctype.h>#include <setjmp.h>#include <signal.h>#include <stdio.h>#include <sys/types.h>#include <sys/stat.h>/* MAJOR BUG: for a component containing addresses, ADDRFMT, if COMPRESS is also set, then addresses get split wrong (not at the spaces between commas). To fix this correctly, putstr() should know about "atomic" strings that must NOT be broken across lines. That's too difficult for right now (it turns out that there are a number of degernate cases), so in oneline(), instead of (*onelp == '\n' && !onelp[1]) being a terminating condition, (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) is used instead. This cuts the line prematurely, and gives us a much better chance of getting things right. */#ifdef SYS5#define u_short ushort#endif SYS5#define ONECOMP 0#define TWOCOMP 1#define BODYCOMP 2#define adios mhladios#define done mhldone#define QUOTE '\\'/* */static struct swit mhlswitches[] = {#define BELLSW 0 "bell", 0,#define NBELLSW 1 "nobell", 0,#define CLRSW 2 "clear", 0,#define NCLRSW 3 "noclear", 0,#define FACESW 4 "faceproc program", 0,#define NFACESW 5 "nofaceproc", 0,#define FOLDSW 6 "folder +folder", 0,#define FORMSW 7 "form formfile", 0,#define PROGSW 8 "moreproc program", 0,#define NPROGSW 9 "nomoreproc", 0,#define LENSW 10 "length lines", 0,#define WIDSW 11 "width columns", 0,#define SLEEPSW 12 "sleep seconds", 0,#define DASHSW 13 "dashmunging", -4,#define NDASHSW 14 "nodashmunging", -6,#define HELPSW 15 "help", 4,#define FORW1SW 16 "forward", -7, /* interface from forw */#define FORW2SW 17 "forwall", -7, /* .. */#define DGSTSW 18 "digest list", -6,#define VOLUMSW 19 "volume number", -6,#define ISSUESW 20 "issue number", -5, NULL, NULL};/* */struct mcomp { char *c_name; /* component name */ char *c_text; /* component text */ char *c_ovtxt; /* text overflow indicator */ char *c_nfs; /* iff FORMAT */ struct format *c_fmt; /* .. */ char *c_face; /* face designator */ int c_offset; /* left margin indentation */ int c_ovoff; /* overflow indentation */ int c_width; /* width of field */ int c_cwidth; /* width of component */ int c_length; /* length in lines */ long c_flags;#define NOCOMPONENT 0x000001/* don't show component name */#define UPPERCASE 0x000002/* display in all upper case */#define CENTER 0x000004/* center line */#define CLEARTEXT 0x000008/* cleartext */#define EXTRA 0x000010/* an "extra" component */#define HDROUTPUT 0x000020/* already output */#define CLEARSCR 0x000040/* clear screen */#define LEFTADJUST 0x000080/* left justify multiple lines */#define COMPRESS 0x000100/* compress text */#define ADDRFMT 0x000200/* contains addresses */#define BELL 0x000400/* sound bell at EOP */#define DATEFMT 0x000800/* contains dates */#define FORMAT 0x001000/* parse address/date */#define INIT 0x002000/* initialize component */#define FACEFMT 0x004000/* contains face */#define FACEDFLT 0x008000/* default for face */#define SPLIT 0x010000/* split headers (don't concatenate) */#define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT"#define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS \ | SPLIT) struct mcomp *c_next;};static struct mcomp *msghd = NULL;static struct mcomp *msgtl = NULL;static struct mcomp *fmthd = NULL;static struct mcomp *fmttl = NULL;static struct mcomp global = { NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, NULL};static struct mcomp holder ={ NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, NULL};static struct pair { char *p_name; long p_flags;} pairs[] = { "Date", DATEFMT, "From", ADDRFMT | FACEDFLT, "Sender", ADDRFMT, "Reply-To", ADDRFMT, "To", ADDRFMT, "cc", ADDRFMT, "Bcc", ADDRFMT, "Resent-Date", DATEFMT, "Resent-From", ADDRFMT, "Resent-Sender", ADDRFMT, "Resent-Reply-To", ADDRFMT, "Resent-To", ADDRFMT, "Resent-cc", ADDRFMT, "Resent-Bcc", ADDRFMT, "Face", FACEFMT, NULL};static struct triple { char *t_name; long t_on; long t_off;} triples[] = { "nocomponent", NOCOMPONENT, 0, "uppercase", UPPERCASE, 0, "nouppercase", 0, UPPERCASE, "center", CENTER, 0, "nocenter", 0, CENTER, "clearscreen", CLEARSCR, 0, "noclearscreen", 0, CLEARSCR, "noclear", 0, CLEARSCR, "leftadjust", LEFTADJUST, 0, "noleftadjust", 0, LEFTADJUST, "compress", COMPRESS, 0, "nocompress", 0, COMPRESS, "split", SPLIT, 0, "nosplit", 0, SPLIT, "addrfield", ADDRFMT, DATEFMT, "bell", BELL, 0, "nobell", 0, BELL, "datefield", DATEFMT, ADDRFMT, NULL};/* */static int bellflg = 0;static int clearflg = 0;static int dashflg = 1;static int forwflg = 0;static int forwall = 0;static int sleepsw = NOTOK;static char *digest = NULL;static int volume = 0;static int issue = 0;static int exitstat = 0;static int mhldebug = 0;#define PITTY (-1)#define NOTTY 0#define ISTTY 1static int ontty = NOTTY;static int row;static int column;static int lm;static int llim;static int ovoff;static int term;static int wid;static char *ovtxt;static char *onelp;static char *parptr;static char *ignores[MAXARGS];static jmp_buf env;static jmp_buf mhlenv;static char delim3[] = /* from forw.c */ "\n------------------------------------------------------------\n\n";static char delim4[] = "\n------------------------------\n\n";static FP (*mhl_action) () = (FP (*) ()) 0;static void mhladios (), mhldone ();static int intrser (), pipeser (), quitser ();static char *mcomp_add (), *oneline (), *parse ();static struct mcomp *add_queue ();static mhl_format(), evalvar(), process(), mhlfile(), free_queue(), putcomp();static putstr(), putch(), face_format(), m_popen();static int ptoi(), ptos(), doface();void clear_screen ();/* *//* ARGSUSED */int mhl (argc, argv)int argc;char *argv[];{ int length = 0, nomore = 0, width = 0, vecp = 0, i; register char *cp, *folder = NULL, *form = NULL, **ap, **argp; char buf[80], *arguments[MAXARGS], *files[MAXARGS]; invo_name = r1bindex (argv[0], '/'); if ((cp = getenv ("MHLDEBUG")) && *cp) mhldebug++; if ((cp = m_find (invo_name)) != NULL) { ap = brkstring (getcpy (cp), " ", "\n"); ap = copyip (ap, arguments); } else ap = arguments; (void) copyip (argv + 1, ap); argp = arguments;/* */ if (cp = getenv ("FACEPROC")) faceproc = cp; vecp = 0; while (cp = *argp++) { if (*cp == '-') switch (smatch (++cp, mhlswitches)) { case AMBIGSW: ambigsw (cp, mhlswitches); done (1); case UNKWNSW: adios (NULLCP, "-%s unknown\n", cp); case HELPSW: (void) sprintf (buf, "%s [switches] [files ...]", invo_name); help (buf, mhlswitches); done (1); case BELLSW: bellflg = 1; continue; case NBELLSW: bellflg = -1; continue; case CLRSW: clearflg = 1; continue; case NCLRSW: clearflg = -1; continue; case FOLDSW: if (!(folder = *argp++) || *folder == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case FORMSW: if (!(form = *argp++) || *form == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case FACESW: if (!(faceproc = *argp++) || *faceproc == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case NFACESW: faceproc = NULL; continue; case SLEEPSW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); sleepsw = atoi (cp);/* ZERO ok! */ continue; case PROGSW: if (!(moreproc = *argp++) || *moreproc == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case NPROGSW: nomore++; continue; case LENSW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); if ((length = atoi (cp)) < 1) adios (NULLCP, "bad argument %s %s", argp[-2], cp); continue; case WIDSW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); if ((width = atoi (cp)) < 1) adios (NULLCP, "bad argument %s %s", argp[-2], cp); continue; case DGSTSW: if (!(digest = *argp++) || *digest == '-') adios (NULLCP, "missing argument to %s", argp[-2]); continue; case ISSUESW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); if ((issue = atoi (cp)) < 1) adios (NULLCP, "bad argument %s %s", argp[-2], cp); continue; case VOLUMSW: if (!(cp = *argp++) || *cp == '-') adios (NULLCP, "missing argument to %s", argp[-2]); if ((volume = atoi (cp)) < 1) adios (NULLCP, "bad argument %s %s", argp[-2], cp); continue; case FORW2SW: forwall++; /* fall */ case FORW1SW: forwflg++; clearflg = -1;/* XXX */ continue; case DASHSW: dashflg++; continue; case NDASHSW: dashflg = 0; continue; } files[vecp++] = cp; }/* */ if (!folder) folder = getenv ("mhfolder"); if (isatty (fileno (stdout))) if (!nomore && !sc_hardcopy () && moreproc && *moreproc) { if (mhl_action) { setsig (SIGINT, SIG_IGN); setsig (SIGQUIT, quitser); } m_popen (moreproc); ontty = PITTY; } else { setsig (SIGINT, SIG_IGN); setsig (SIGQUIT, quitser); ontty = ISTTY; } else ontty = NOTTY; mhl_format (form ? form : mhlformat, length, width); if (vecp == 0) process (folder, NULLCP, 1, vecp = 1); else for (i = 0; i < vecp; i++) process (folder, files[i], i + 1, vecp); if (forwall) { if (digest) { printf ("%s", delim4); if (volume == 0) { (void) sprintf (buf, "End of %s Digest\n", digest); } else (void) sprintf (buf, "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue); i = strlen (buf); for (cp = buf + i; i > 1; i--) *cp++ = '*'; *cp++ = '\n'; *cp = NULL; printf ("%s", buf); } else printf ("\n------- End of Forwarded Message%s\n\n", vecp > 1 ? "s" : ""); } if (clearflg > 0 && ontty == NOTTY) clear_screen (); if (ontty == PITTY) m_pclose (); return exitstat;}/* */static mhl_format (file, length, width)register char *file;int length, width;{ int i; register char *bp, *cp, **ip; char *ap, buffer[BUFSIZ], name[NAMESZ]; register struct mcomp *c1; struct stat st; register FILE *fp; static dev_t dev = 0; static ino_t ino = 0; static time_t mtime = 0; if (fmthd != NULL) if (stat (libpath (file), &st) != NOTOK && mtime == st.st_mtime && dev == st.st_dev && ino == st.st_ino) goto out; else free_queue (&fmthd, &fmttl); if ((fp = fopen (libpath (file), "r")) == NULL) adios (file, "unable to open format file"); if (fstat (fileno (fp), &st) != NOTOK) mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino; global.c_ovtxt = global.c_nfs = NULL; global.c_fmt = NULL; global.c_offset = 0; global.c_ovoff = -1; if ((i = sc_width ()) > 5) global.c_width = i; global.c_cwidth = -1; if ((i = sc_length ()) > 5) global.c_length = i - 1; global.c_flags = BELL; /* BELL is default */ *(ip = ignores) = NULL; while (vfgets (fp, &ap) == OK) { bp = ap; if (*bp == ';') continue; if (cp = index (bp, '\n')) *cp = NULL; if (*bp == ':') { c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT); continue; } parptr = bp; (void) strcpy (name, parse ()); switch (*parptr) { case '\0': case ',': case '=': if (uleq (name, "ignores")) { ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip); continue; } parptr = bp; while (*parptr) { if (evalvar (&global)) adios (NULLCP, "format file syntax error: %s", bp); if (*parptr) parptr++; } continue; case ':': c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT); while (*parptr == ':' || *parptr == ',') { parptr++; if (evalvar (c1)) adios (NULLCP, "format file syntax error: %s", bp); } if (!c1 -> c_nfs && global.c_nfs) if (c1 -> c_flags & DATEFMT) { if (global.c_flags & DATEFMT) c1 -> c_nfs = getcpy (global.c_nfs); } else if (c1 -> c_flags & ADDRFMT) { if (global.c_flags & ADDRFMT) c1 -> c_nfs = getcpy (global.c_nfs); } continue; default: adios (NULLCP, "format file syntax error: %s", bp); } } (void) fclose (fp); if (mhldebug) for (c1 = fmthd; c1; c1 = c1 -> c_next) { fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n", c1 -> c_name, c1 -> c_text, c1 -> c_ovtxt); fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n", c1 -> c_nfs, c1 -> c_fmt); fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n", c1 -> c_offset, c1 -> c_ovoff, c1 -> c_width, c1 -> c_cwidth, c1 -> c_length); fprintf (stderr, "\tflags=%s\n", sprintb (buffer, (unsigned) c1 -> c_flags, LBITS)); }out: ; if (clearflg == 1) global.c_flags |= CLEARSCR; else if (clearflg == -1) global.c_flags &= ~CLEARSCR; switch (bellflg) { /* command line may override format file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -