From: CSRG Date: Fri, 7 Mar 1986 00:01:36 +0000 (-0800) Subject: BSD 4_3 development X-Git-Tag: BSD-4_3~429 X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/commitdiff_plain/3c39e56aece646de2e64bf1342676963964fb95a BSD 4_3 development Work on file usr/contrib/mh/uip/mhlsbr.c Synthesized-from: CSRG/cd1/4.3 --- diff --git a/usr/contrib/mh/uip/mhlsbr.c b/usr/contrib/mh/uip/mhlsbr.c new file mode 100644 index 0000000000..98d07e2859 --- /dev/null +++ b/usr/contrib/mh/uip/mhlsbr.c @@ -0,0 +1,1474 @@ +/* mhlsbr.c - implement the "nifty" message lister */ + +#include "../h/mh.h" +#include "../h/addrsbr.h" +#include "../h/formatsbr.h" +#include "../zotnet/tws.h" +#include +#include +#include +#include +#include +#include + + +/* 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. + */ + + +#define ONECOMP 0 +#define TWOCOMP 1 + +#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 FOLDSW 4 + "folder +folder", 0, +#define FORMSW 5 + "form formfile", 0, + +#define PROGSW 6 + "moreproc program", 0, +#define NPROGSW 7 + "nomoreproc", 0, + +#define LENSW 8 + "length lines", 0, +#define WIDSW 9 + "width columns", 0, + +#define HELPSW 10 + "help", 4, + +#define FORW1SW 11 + "forward", -7, /* interface from forw */ +#define FORW2SW 12 + "forwall", -7, /* .. */ +#define DGSTSW 13 + "digest list", -6, + + 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; /* .. */ + + 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 */ + + short c_flags; +#define NOCOMPONENT 0x0001 /* don't show component name */ +#define UPPERCASE 0x0002 /* display in all upper case */ +#define CENTER 0x0004 /* center line */ +#define CLEARTEXT 0x0008 /* cleartext */ +#define EXTRA 0x0010 /* an "extra" component */ +#define HDROUTPUT 0x0020 /* already output */ +#define CLEARSCR 0x0040 /* clear screen */ +#define LEFTADJUST 0x0080 /* left justify multiple lines */ +#define COMPRESS 0x0100 /* compress text */ +#define ADDRFMT 0x0200 /* contains addresses */ +#define BELL 0x0400 /* sound bell at EOP */ +#define DATEFMT 0x0800 /* contains dates */ +#define FORMAT 0x1000 /* parse address/date */ +#define INIT 0x2000 +#define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT" +#define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS) + + 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; + short p_flags; +} pairs[] = { + "Date", DATEFMT, + "From", ADDRFMT, + "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, + + NULL +}; + +static struct triple { + char *t_name; + short t_on; + short 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, + "addrfield", ADDRFMT, DATEFMT, + "bell", BELL, 0, + "nobell", 0, BELL, + "datefield", DATEFMT, ADDRFMT, + + NULL +}; + +/* */ + +static int bellflg = 0; +static int clearflg = 0; +static int forwflg = 0; +static int forwall = 0; + +static char *digest = NULL; + +static int exitstat = 0; +static int mhldebug = 0; + +#define PITTY (-1) +#define NOTTY 0 +#define ISTTY 1 +static 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; + + +void mhladios (), mhldone (); +int intrser (), pipeser (), quitser (); +char *mcomp_add (), *oneline (), *parse (); +struct mcomp *add_queue (); + + +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; + +/* */ + + 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 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]); + case FORW2SW: + forwall++; /* fall */ + case FORW1SW: + forwflg++; + clearflg = -1;/* XXX */ + continue; + } + files[vecp++] = cp; + } + +/* */ + + if (!folder) + folder = getenv ("mhfolder"); + + if (isatty (fileno (stdout))) + if (!nomore && 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); + (void) sprintf (buf, "End of %s Digest\n", digest); + 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 */ + case 1: + global.c_flags |= BELL; + break; + case -1: + global.c_flags &= ~BELL; + break; + } + + if (length) + global.c_length = length; + if (width) + global.c_width = width; + if (global.c_length < 5) + global.c_length = 10000; + if (global.c_width < 5) + global.c_width = 10000; +} + +/* */ + +static evalvar (c1) +register struct mcomp *c1; +{ + char *cp, + name[NAMESZ]; + register struct triple *ap; + + if (!*parptr) + return 0; + (void) strcpy (name, parse ()); + + if (uleq (name, "component")) { + if (ptos (name, &c1 -> c_text)) + return 1; + c1 -> c_flags &= ~NOCOMPONENT; + return 0; + } + if (uleq (name, "overflowtext")) + return ptos (name, &c1 -> c_ovtxt); + if (uleq (name, "formatfield")) { + if (ptos (name, &cp)) + return 1; + c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp)); + c1 -> c_flags |= FORMAT; + return 0; + } + + if (uleq (name, "offset")) + return ptoi (name, &c1 -> c_offset); + if (uleq (name, "overflowoffset")) + return ptoi (name, &c1 -> c_ovoff); + if (uleq (name, "width")) + return ptoi (name, &c1 -> c_width); + if (uleq (name, "compwidth")) + return ptoi (name, &c1 -> c_cwidth); + if (uleq (name, "length")) + return ptoi (name, &c1 -> c_length); + + for (ap = triples; ap -> t_name; ap++) + if (uleq (ap -> t_name, name)) { + c1 -> c_flags |= ap -> t_on; + c1 -> c_flags &= ~ap -> t_off; + return 0; + } + + return 1; +} + +/* */ + +static int ptoi (name, i) +register char *name; +register int *i; +{ + char *cp; + + if (*parptr++ != '=' || !*(cp = parse ())) { + advise (NULLCP, "missing argument to variable %s", name); + return 1; + } + + *i = atoi (cp); + return 0; +} + + +static int ptos (name, s) +register char *name, + **s; +{ + char c, + *cp; + + if (*parptr++ != '=') { + advise (NULLCP, "missing argument to variable %s", name); + return 1; + } + + if (*parptr != '"') + for (cp = parptr; + *parptr && *parptr != ':' && *parptr != ','; + parptr++) + continue; + else + for (cp = ++parptr; *parptr && *parptr != '"'; parptr++) + if (*parptr == QUOTE) + if (!*++parptr) + parptr--; + c = *parptr; + *parptr = NULL; + *s = getcpy (cp); + if ((*parptr = c) == '"') + parptr++; + return 0; +} + +/* */ + +static char *parse () { + int c; + register char *cp; + static char result[NAMESZ]; + + for (cp = result; c = *parptr; parptr++) + if (isalnum (c) + || c == '.' + || c == '-' + || c == '_' + || c =='[' + || c == ']') + *cp++ = c; + else + break; + *cp = NULL; + + return result; +} + +/* */ + +static process (folder, fname, ofilen, ofilec) +register char *folder, + *fname; +int ofilen, + ofilec; +{ + register char *cp; + register struct mcomp *c1; + register FILE *fp; + + switch (setjmp (env)) { + case OK: + if (fname) { + fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r"); + if (fp == NULL) { + advise (fname, "unable to open"); + exitstat++; + return; + } + } + else { + fname = "(stdin)"; + fp = stdin; + } + cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname); + if (ontty != PITTY) + (void) signal (SIGINT, intrser); + mhlfile (fp, cp, ofilen, ofilec);/* fall */ + + default: + if (ontty != PITTY) + (void) signal (SIGINT, SIG_IGN); + if (mhl_action == NULL && fp != stdin) + (void) fclose (fp); + free (cp); + if (holder.c_text) { + free (holder.c_text); + holder.c_text = NULL; + } + free_queue (&msghd, &msgtl); + for (c1 = fmthd; c1; c1 = c1 -> c_next) + c1 -> c_flags &= ~HDROUTPUT; + break; + } +} + +/* */ + +static mhlfile (fp, mname, ofilen, ofilec) +register FILE *fp; +register char *mname; +int ofilen, + ofilec; +{ + int state; + register struct mcomp *c1, + *c2; + register char **ip; + char name[NAMESZ], + buf[BUFSIZ]; + + if (forwall) { + if (digest) + printf ("%s", ofilen == 1 ? delim3 : delim4); + else { + printf ("\n-------"); + if (ofilen == 1) + printf (" Forwarded Message%s", ofilec > 1 ? "s" : ""); + else + printf (" Message %d", ofilen); + printf ("\n\n"); + } + } + else + switch (ontty) { + case PITTY: + if (ofilec > 1) { + if (ofilen > 1) { + if ((global.c_flags & CLEARSCR)) + clear_screen (); + else + printf ("\n\n\n"); + } + printf (">>> %s\n\n", mname); + } + break; + + case ISTTY: + (void) strcpy (buf, "\n"); + if (ofilec > 1) { + if (SOprintf ("Press to list \"%s\"...", mname)) { + if (ofilen > 1) + printf ("\n\n\n"); + printf ("Press to list \"%s\"...", mname); + } + (void) fflush (stdout); + buf[0] = NULL; + (void) read (fileno (stdout), buf, sizeof buf); + } + if (index (buf, '\n')) { + if ((global.c_flags & CLEARSCR)) + clear_screen (); + } + else + printf ("\n"); + break; + + default: + if (ofilec > 1) { + if (ofilen > 1) { + printf ("\n\n\n"); + if (clearflg > 0) + clear_screen (); + } + printf (">>> %s\n\n", mname); + } + break; + } + +/* */ + + for (state = FLD;;) + switch (state = m_getfld (state, name, buf, sizeof buf, fp)) { + case FLD: + case FLDPLUS: + for (ip = ignores; *ip; ip++) + if (uleq (name, *ip)) { + while (state == FLDPLUS) + state = m_getfld (state, name, buf, sizeof buf, fp); + break; + } + if (*ip) + continue; + + for (c1 = msghd; c1; c1 = c1 -> c_next) + if (uleq (name, c1 -> c_name)) { + c1 -> c_text = + mcomp_add (c1 -> c_flags, buf, c1 -> c_text); + break; + } + if (c1 == NULL) + c1 = add_queue (&msghd, &msgtl, name, buf, 0); + while (state == FLDPLUS) { + state = m_getfld (state, name, buf, sizeof buf, fp); + c1 -> c_text = add (buf, c1 -> c_text); + } + + for (c2 = fmthd; c2; c2 = c2 -> c_next) + if (uleq (c2 -> c_name, c1 -> c_name)) + break; + if (c2 == NULL) + c1 -> c_flags |= EXTRA; + continue; + + case BODY: + case FILEEOF: + row = column = 0; + for (c1 = fmthd; c1; c1 = c1 -> c_next) { + if (c1 -> c_flags & CLEARTEXT) { + putcomp (c1, c1, ONECOMP); + continue; + } + if (uleq (c1 -> c_name, "messagename")) { + holder.c_text = concat ("(Message ", mname, ")\n", + NULLCP); + putcomp (c1, &holder, ONECOMP); + free (holder.c_text); + holder.c_text = NULL; + continue; + } + if (uleq (c1 -> c_name, "extras")) { + for (c2 = msghd; c2; c2 = c2 -> c_next) + if (c2 -> c_flags & EXTRA) + putcomp (c1, c2, TWOCOMP); + continue; + } + if (uleq (c1 -> c_name, "body")) { + if ((holder.c_text = malloc (sizeof buf)) == NULL) + adios (NULLCP, "unable to allocate buffer memory"); + (void) strcpy (holder.c_text, buf); + while (state == BODY) { + putcomp (c1, &holder, ONECOMP); + state = m_getfld (state, name, holder.c_text, + sizeof buf, fp); + } + free (holder.c_text); + holder.c_text = NULL; + continue; + } + for (c2 = msghd; c2; c2 = c2 -> c_next) + if (uleq (c2 -> c_name, c1 -> c_name)) { + putcomp (c1, c2, ONECOMP); + break; + } + } + return; + + case LENERR: + case FMTERR: + advise (NULLCP, "format error in message %s", mname); + exitstat++; + return; + + default: + adios (NULLCP, "getfld() returned %d", state); + } +} + +/* */ + +static int mcomp_flags (name) +register char *name; +{ + register struct pair *ap; + + for (ap = pairs; ap -> p_name; ap++) + if (uleq (ap -> p_name, name)) + return (ap -> p_flags); + + return NULL; +} + + +static char *mcomp_add (flags, s1, s2) +short flags; +register char *s1, + *s2; +{ + register char *dp; + + if (!(flags & ADDRFMT)) + return add (s1, s2); + + if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n') + *dp = NULL; + + return add (s1, add (",\n", s2)); +} + +/* */ + +struct pqpair { + char *pq_text; + char *pq_error; + struct pqpair *pq_next; +}; + + +static mcomp_format (c1, c2) +register struct mcomp *c1, + *c2; +{ + int dat[4]; + register char *ap, + *cp; + char buffer[BUFSIZ], + error[BUFSIZ]; + register struct comp *cptr; + register struct pqpair *p, + *q; + struct pqpair pq; + register struct mailname *mp; + + ap = c2 -> c_text; + c2 -> c_text = NULL; + dat[0] = dat[1] = dat[2] = 0; + dat[3] = sizeof buffer - 1; + (void) fmt_compile (c1 -> c_nfs, &c1 -> c_fmt); + + if (c1 -> c_flags & DATEFMT) { + FINDCOMP (cptr, "text"); + if (cptr) + cptr -> c_text = ap; + + (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat); + c2 -> c_text = concat (buffer, "\n", NULLCP); + + free (ap); + return; + } + + (q = &pq) -> pq_next = NULL; + while (cp = getname (ap)) { + if ((p = (struct pqpair *) calloc ((unsigned) 1, sizeof *p)) == NULL) + adios (NULLCP, "unable to allocate pqpair memory"); + + if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) { + p -> pq_text = getcpy (cp); + p -> pq_error = getcpy (error); + } + else { + p -> pq_text = getcpy (mp -> m_text); + mnfree (mp); + } + q = (q -> pq_next = p); + } + + for (p = pq.pq_next; p; p = q) { + FINDCOMP (cptr, "text"); + if (cptr) + cptr -> c_text = p -> pq_text; + FINDCOMP (cptr, "error"); + if (cptr) + cptr -> c_text = p -> pq_error; + + (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat); + if (*buffer) { + if (c2 -> c_text) + c2 -> c_text = add (",\n", c2 -> c_text); + if (*(cp = buffer + strlen (buffer) - 1) == '\n') + *cp = NULL; + c2 -> c_text = add (buffer, c2 -> c_text); + } + + free (p -> pq_text); + if (p -> pq_error) + free (p -> pq_error); + q = p -> pq_next; + free ((char *) p); + } + + c2 -> c_text = add ("\n", c2 -> c_text); + free (ap); +} + +/* */ + +static struct mcomp *add_queue (head, tail, name, text, flags) +register struct mcomp **head, + **tail; +register char *name, + *text; +int flags; +{ + register struct mcomp *c1; + + if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL) + adios (NULLCP, "unable to allocate comp memory"); + + c1 -> c_flags = flags & ~INIT; + if (c1 -> c_name = name ? getcpy (name) : NULL) + c1 -> c_flags |= mcomp_flags (c1 -> c_name); + c1 -> c_text = text ? getcpy (text) : NULL; + if (flags & INIT) { + if (global.c_ovtxt) + c1 -> c_ovtxt = getcpy (global.c_ovtxt); + c1 -> c_offset = global.c_offset; + c1 -> c_ovoff = global. c_ovoff; + c1 -> c_width = c1 -> c_length = 0; + c1 -> c_cwidth = global.c_cwidth; + c1 -> c_flags |= global.c_flags & GFLAGS; + } + if (*head == NULL) + *head = c1; + if (*tail != NULL) + (*tail) -> c_next = c1; + *tail = c1; + + return c1; +} + + +static free_queue (head, tail) +register struct mcomp **head, + **tail; +{ + register struct mcomp *c1, + *c2; + + for (c1 = *head; c1; c1 = c2) { + c2 = c1 -> c_next; + if (c1 -> c_name) + free (c1 -> c_name); + if (c1 -> c_text) + free (c1 -> c_text); + if (c1 -> c_ovtxt) + free (c1 -> c_ovtxt); + if (c1 -> c_nfs) + free (c1 -> c_nfs); + if (c1 -> c_fmt) + free ((char *) c1 -> c_fmt); + free ((char *) c1); + } + + *head = *tail = NULL; +} + +/* */ + +static putcomp (c1, c2, flag) +register struct mcomp *c1, + *c2; +int flag; +{ + int count, + cchdr; + register char *cp; + + cchdr = 0; + lm = 0; + llim = c1 -> c_length ? c1 -> c_length : -1; + wid = c1 -> c_width ? c1 -> c_width : global.c_width; + ovoff = (c1 -> c_ovoff >= 0 ? c1 -> c_ovoff : global.c_ovoff) + + c1 -> c_offset; + if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL) + ovtxt = ""; + if (wid < ovoff + strlen (ovtxt) + 5) + adios (NULLCP, "component: %s width(%d) too small for overflow(%d)", + c1 -> c_name, wid, ovoff + strlen (ovtxt) + 5); + onelp = NULL; + + if (c1 -> c_flags & CLEARTEXT) { + putstr (c1 -> c_text); + putstr ("\n"); + return; + } + + if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT))) + mcomp_format (c1, c2); + + if (c1 -> c_flags & CENTER) { + count = (c1 -> c_width ? c1 -> c_width : global.c_width) + - c1 -> c_offset - strlen (c2 -> c_text); + if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) + count -= strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2; + lm = c1 -> c_offset + (count / 2); + } + else + if (c1 -> c_offset) + lm = c1 -> c_offset; + + if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) { + if (c1 -> c_flags & UPPERCASE) /* uppercase component also */ + for (cp = (c1 -> c_text ? c1 -> c_text : c1 -> c_name); *cp; cp++) + if (islower (*cp)) + *cp = toupper (*cp); + putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name); + putstr (": "); + c1 -> c_flags |= HDROUTPUT; + + cchdr++; + if ((count = c1 -> c_cwidth - + strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0) + while (count--) + putstr (" "); + } + + if (flag == TWOCOMP + && !(c2 -> c_flags & HDROUTPUT) + && !(c2 -> c_flags & NOCOMPONENT)) { + if (c1 -> c_flags & UPPERCASE) + for (cp = c2 -> c_name; *cp; cp++) + if (islower (*cp)) + *cp = toupper (*cp); + putstr (c2 -> c_name); + putstr (": "); + c2 -> c_flags |= HDROUTPUT; + } + if (c1 -> c_flags & UPPERCASE) + for (cp = c2 -> c_text; *cp; cp++) + if (islower (*cp)) + *cp = toupper (*cp); + + count = 0; + if (cchdr) + count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth + : strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2; + count += c1 -> c_offset; + + putstr (oneline (c2 -> c_text, c1 -> c_flags)); + if (term == '\n') + putstr ("\n"); + while (cp = oneline (c2 -> c_text, c1 -> c_flags)) + if (*cp) { + lm = count; + putstr (cp); + if (term == '\n') + putstr ("\n"); + } + else + if (term == '\n') + putstr ("\n"); +} + +/* */ + +static char *oneline (stuff, flags) +register char *stuff; +short flags; +{ + int spc; + register char *cp, + *ret; + + if (onelp == NULL) + onelp = stuff; + if (*onelp == NULL) + return (onelp = NULL); + + ret = onelp; + term = 0; + if (flags & COMPRESS) { + for (spc = 1, cp = ret; *onelp; onelp++) + if (isspace (*onelp)) { + if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) { + term = '\n'; + *onelp++ = NULL; + break; + } + else + if (!spc) { + *cp++ = ' '; + spc++; + } + } + else { + *cp++ = *onelp; + spc = 0; + } + + *cp = NULL; + } + else { + while (*onelp && *onelp != '\n') + onelp++; + if (*onelp == '\n') { + term = '\n'; + *onelp++ = NULL; + } + if (flags & LEFTADJUST) + while (*ret == ' ' || *ret == '\t') + ret++; + } + + return ret; +} + +/* */ + +static putstr (string) +register char *string; +{ + if (!column && lm > 0) + while (lm > 0) + if (lm >= 8) { + putch ('\t'); + lm -= 8; + } + else { + putch (' '); + lm--; + } + lm = 0; + while (*string) + putch (*string++); +} + +/* */ + +static putch (ch) +register char ch; +{ + char buf[BUFSIZ]; + + if (llim == 0) + return; + + switch (ch) { + case '\n': + if (llim > 0) + llim--; + column = 0; + row++; + if (ontty != ISTTY || row != global.c_length) + break; + if (global.c_flags & BELL) + (void) putchar ('\007'); + (void) fflush (stdout); + buf[0] = NULL; + (void) read (fileno (stdout), buf, sizeof buf); + if (index (buf, '\n')) { + if (global.c_flags & CLEARSCR) + clear_screen (); + row = 0; + } + else { + (void) putchar ('\n'); + row = global.c_length / 3; + } + return; + + case '\t': + column |= 07; + column++; + break; + + case '\b': + column--; + break; + + case '\r': + column = 0; + break; + + default: + if (column == 0 && forwflg && ch == '-') + (void) putchar ('-'), putchar (' '); + if (ch >= ' ') + column++; + break; + } + + if (column >= wid) { + putch ('\n'); + if (ovoff > 0) + lm = ovoff; + putstr (ovtxt ? ovtxt : ""); + putch (ch); + return; + } + + (void) putchar (ch); +} + +/* */ + +/* ARGSUSED */ + +static int intrser (i) +int i; +{ +#ifndef BSD42 + (void) signal (SIGINT, intrser); +#endif BSD42 + + discard (stdout); + (void) putchar ('\n'); + + longjmp (env, DONE); +} + + +/* ARGSUSED */ + +static int pipeser (i) +int i; +{ +#ifndef BSD42 + (void) signal (SIGPIPE, pipeser); +#endif BSD42 + + done (NOTOK); +} + + +/* ARGSUSED */ + +static int quitser (i) +int i; +{ +#ifndef BSD42 + (void) signal (SIGQUIT, quitser); +#endif BSD42 + + (void) putchar ('\n'); + (void) fflush (stdout); + + done (NOTOK); +} + +/* */ + +#undef adios +#undef done + +int mhlsbr (argc, argv, action) +int argc; +register char **argv; +register FP (*action) (); +{ + int (*istat) (), (*pstat) (), (*qstat) (); + register char *cp; + register struct mcomp *c1; + + switch (setjmp (mhlenv)) { + case OK: + cp = invo_name; + bellflg = clearflg = forwflg = forwall = exitstat = 0; + digest = NULL; + ontty = NOTTY; + mhl_action = action; + if ((istat = signal (SIGINT, SIG_IGN)) != SIG_DFL) + (void) signal (SIGINT, istat); + if ((qstat = signal (SIGQUIT, SIG_IGN)) != SIG_DFL) + (void) signal (SIGQUIT, qstat); + pstat = signal (SIGPIPE, pipeser); + (void) mhl (argc, argv); /* fall */ + + default: + (void) signal (SIGINT, istat); + (void) signal (SIGQUIT, qstat); + (void) signal (SIGPIPE, SIG_IGN);/* XXX */ + if (ontty == PITTY) + m_pclose (); + (void) signal (SIGPIPE, pstat); + invo_name = cp; + if (holder.c_text) { + free (holder.c_text); + holder.c_text = NULL; + } + free_queue (&msghd, &msgtl); + for (c1 = fmthd; c1; c1 = c1 -> c_next) + c1 -> c_flags &= ~HDROUTPUT; + return exitstat; + } +} + +/* */ + +/* VARARGS2 */ + +static void mhladios (what, fmt, a, b, c, d, e, f) +char *what, + *fmt, + *a, + *b, + *c, + *d, + *e, + *f; +{ + advise (what, fmt, a, b, c, d, e, f); + mhldone (1); +} + + +static void mhldone (status) +int status; +{ + exitstat = status; + if (mhl_action) + longjmp (mhlenv, DONE); + else + done (exitstat); +} + +/* */ + +static int m_pid = NOTOK; +static int sd = NOTOK; + + +static m_popen (name) +char *name; +{ + int pd[2]; + + if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK) + adios ("standard output", "unable to dup()"); + + if (pipe (pd) == NOTOK) + adios ("pipe", "unable to"); + + switch (m_pid = vfork ()) { + case NOTOK: + adios ("fork", "unable to"); + + case OK: + (void) signal (SIGINT, SIG_DFL); + (void) signal (SIGQUIT, SIG_DFL); + + (void) close (pd[1]); + if (pd[0] != fileno (stdin)) { + (void) dup2 (pd[0], fileno (stdin)); + (void) close (pd[0]); + } + execlp (name, r1bindex (name, '/'), NULLCP); + fprintf (stderr, "unable to exec "); + perror (name); + _exit (-1); + + default: + (void) close (pd[0]); + if (pd[1] != fileno (stdout)) { + (void) dup2 (pd[1], fileno (stdout)); + (void) close (pd[1]); + } + } +} + + +m_pclose () { + if (m_pid == NOTOK) + return; + + if (sd != NOTOK) { + (void) fflush (stdout); + if (dup2 (sd, fileno (stdout)) == NOTOK) + adios ("standard output", "unable to dup2()"); + + clearerr (stdout); + (void) close (sd); + sd = NOTOK; + } + else + (void) fclose (stdout); + + (void) pidwait (m_pid, OK); + m_pid = NOTOK; +}