9 date 95.12.08.17.57.16; author jromine; state Exp;
14 date 93.08.20.15.50.44; author jromine; state Exp;
19 date 92.12.15.00.20.22; author jromine; state Exp;
24 date 92.12.03.16.50.27; author jromine; state Exp;
29 date 92.12.03.16.28.56; author jromine; state Exp;
34 date 92.11.18.00.19.56; author jromine; state Exp;
39 date 92.11.18.00.19.00; author jromine; state Exp;
44 date 92.11.17.00.03.06; author jromine; state Exp;
49 date 92.10.26.23.00.16; author jromine; state Exp;
54 date 92.10.16.21.36.54; author jromine; state Exp;
59 date 92.02.10.20.30.11; author jromine; state Exp;
64 date 92.02.10.20.11.37; author jromine; state Exp;
69 date 92.02.05.07.26.30; author jromine; state Exp;
74 date 92.01.31.22.12.40; author jromine; state Exp;
79 date 91.01.25.14.49.46; author mh; state Exp;
84 date 91.01.16.08.56.04; author mh; state Exp;
89 date 90.04.05.14.58.08; author sources; state Exp;
94 date 90.03.23.15.02.52; author sources; state Exp;
99 date 90.03.22.13.59.45; author sources; state Exp;
104 date 90.03.20.22.30.10; author sources; state Exp;
109 date 90.03.20.10.36.09; author sources; state Exp;
114 date 90.02.06.13.20.49; author sources; state Exp;
119 date 90.02.05.14.57.13; author sources; state Exp;
124 date 90.02.05.14.24.31; author sources; state Exp;
129 date 90.02.05.14.00.22; author sources; state Exp;
134 date 90.02.05.13.59.39; author sources; state Exp;
139 date 90.01.31.14.19.17; author sources; state Exp;
144 date 90.01.26.15.55.57; author sources; state Exp;
149 date 89.11.17.16.12.25; author sources; state Exp;
154 date 89.11.17.16.10.27; author sources; state Exp;
165 @fixup fmtscan newline for #ifdef JLR
168 @/* mhlsbr.c - implement the "nifty" message lister */
170 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.29 1993/08/20 15:50:44 jromine Exp jromine $";
174 #include "../h/addrsbr.h"
175 #include "../h/formatsbr.h"
176 #include "../zotnet/tws.h"
178 #undef NULLVP /* XXX */
180 #if defined(SYS5) && defined(AUX)
181 #define u_short ushort
188 #include <sys/types.h>
189 #include <sys/stat.h>
193 for a component containing addresses, ADDRFMT, if COMPRESS is also
194 set, then addresses get split wrong (not at the spaces between commas).
195 To fix this correctly, putstr() should know about "atomic" strings that
196 must NOT be broken across lines. That's too difficult for right now
197 (it turns out that there are a number of degernate cases), so in
198 oneline(), instead of
200 (*onelp == '\n' && !onelp[1])
202 being a terminating condition,
204 (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT)))
206 is used instead. This cuts the line prematurely, and gives us a much
207 better chance of getting things right.
212 #define u_short ushort
219 #define adios mhladios
226 static struct swit mhlswitches[] = {
238 "faceproc program", 0,
248 "moreproc program", 0,
269 "forward", -7, /* interface from forw */
271 "forwall", -7, /* .. */
287 char *c_name; /* component name */
288 char *c_text; /* component text */
289 char *c_ovtxt; /* text overflow indicator */
290 char *c_nfs; /* iff FORMAT */
291 struct format *c_fmt; /* .. */
292 char *c_face; /* face designator */
294 int c_offset; /* left margin indentation */
295 int c_ovoff; /* overflow indentation */
296 int c_width; /* width of field */
297 int c_cwidth; /* width of component */
298 int c_length; /* length in lines */
301 #define NOCOMPONENT 0x000001/* don't show component name */
302 #define UPPERCASE 0x000002/* display in all upper case */
303 #define CENTER 0x000004/* center line */
304 #define CLEARTEXT 0x000008/* cleartext */
305 #define EXTRA 0x000010/* an "extra" component */
306 #define HDROUTPUT 0x000020/* already output */
307 #define CLEARSCR 0x000040/* clear screen */
308 #define LEFTADJUST 0x000080/* left justify multiple lines */
309 #define COMPRESS 0x000100/* compress text */
310 #define ADDRFMT 0x000200/* contains addresses */
311 #define BELL 0x000400/* sound bell at EOP */
312 #define DATEFMT 0x000800/* contains dates */
313 #define FORMAT 0x001000/* parse address/date */
314 #define INIT 0x002000/* initialize component */
315 #define FACEFMT 0x004000/* contains face */
316 #define FACEDFLT 0x008000/* default for face */
317 #define SPLIT 0x010000/* split headers (don't concatenate) */
318 #define NONEWLINE 0x020000/* don't write trailing newline */
319 #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT\022NONEWLINE"
320 #define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS \
323 struct mcomp *c_next;
326 static struct mcomp *msghd = NULL;
327 static struct mcomp *msgtl = NULL;
328 static struct mcomp *fmthd = NULL;
329 static struct mcomp *fmttl = NULL;
331 static struct mcomp global = {
332 NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, 0
334 static struct mcomp holder =
336 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, 0
345 "From", ADDRFMT | FACEDFLT,
351 "Resent-Date", DATEFMT,
352 "Resent-From", ADDRFMT,
353 "Resent-Sender", ADDRFMT,
354 "Resent-Reply-To", ADDRFMT,
355 "Resent-To", ADDRFMT,
356 "Resent-cc", ADDRFMT,
357 "Resent-Bcc", ADDRFMT,
363 static struct triple {
368 "nocomponent", NOCOMPONENT, 0,
369 "uppercase", UPPERCASE, 0,
370 "nouppercase", 0, UPPERCASE,
372 "nocenter", 0, CENTER,
373 "clearscreen", CLEARSCR, 0,
374 "noclearscreen", 0, CLEARSCR,
375 "noclear", 0, CLEARSCR,
376 "leftadjust", LEFTADJUST, 0,
377 "noleftadjust", 0, LEFTADJUST,
378 "compress", COMPRESS, 0,
379 "nocompress", 0, COMPRESS,
382 "addrfield", ADDRFMT, DATEFMT,
385 "datefield", DATEFMT, ADDRFMT,
386 "newline", 0, NONEWLINE,
387 "nonewline", NONEWLINE, 0,
394 static int bellflg = 0;
395 static int clearflg = 0;
396 static int dashflg = 1;
397 static int dobody = 1;
398 static int forwflg = 0;
399 static int forwall = 0;
401 static int sleepsw = NOTOK;
403 static char *digest = NULL;
404 static int volume = 0;
405 static int issue = 0;
407 static int exitstat = 0;
408 static int mhldebug = 0;
413 static int ontty = NOTTY;
431 static char *ignores[MAXARGS];
435 static jmp_buf mhlenv;
438 static char delim3[] = /* from forw.c */
439 "\n----------------------------------------------------------------------\n\n";
440 static char delim4[] = "\n------------------------------\n\n";
443 static FP (*mhl_action) () = (FP (*) ()) 0;
446 static void mhladios (), mhldone ();
447 static TYPESIG intrser (), pipeser (), quitser ();
448 static char *mcomp_add (), *oneline (), *parse ();
449 static struct mcomp *add_queue ();
451 static mhl_format(), evalvar(), process(), mhlfile(), free_queue(), putcomp();
452 static putstr(), putch(), face_format(), m_popen();
453 static int ptoi(), ptos(), doface();
455 void clear_screen ();
479 invo_name = r1bindex (argv[0], '/');
480 if ((cp = getenv ("MHLDEBUG")) && *cp)
482 if ((cp = m_find (invo_name)) != NULL) {
483 ap = brkstring (getcpy (cp), " ", "\n");
484 ap = copyip (ap, arguments);
488 (void) copyip (argv + 1, ap);
493 if (cp = getenv ("FACEPROC"))
497 while (cp = *argp++) {
499 switch (smatch (++cp, mhlswitches)) {
501 ambigsw (cp, mhlswitches);
504 adios (NULLCP, "-%s unknown\n", cp);
506 (void) sprintf (buf, "%s [switches] [files ...]",
508 help (buf, mhlswitches);
526 if (!(folder = *argp++) || *folder == '-')
527 adios (NULLCP, "missing argument to %s", argp[-2]);
530 if (!(form = *argp++) || *form == '-')
531 adios (NULLCP, "missing argument to %s", argp[-2]);
535 if (!(faceproc = *argp++) || *faceproc == '-')
536 adios (NULLCP, "missing argument to %s", argp[-2]);
542 if (!(cp = *argp++) || *cp == '-')
543 adios (NULLCP, "missing argument to %s", argp[-2]);
544 sleepsw = atoi (cp);/* ZERO ok! */
548 if (!(moreproc = *argp++) || *moreproc == '-')
549 adios (NULLCP, "missing argument to %s", argp[-2]);
556 if (!(cp = *argp++) || *cp == '-')
557 adios (NULLCP, "missing argument to %s", argp[-2]);
558 if ((length = atoi (cp)) < 1)
559 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
562 if (!(cp = *argp++) || *cp == '-')
563 adios (NULLCP, "missing argument to %s", argp[-2]);
564 if ((width = atoi (cp)) < 1)
565 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
569 if (!(digest = *argp++) || *digest == '-')
570 adios (NULLCP, "missing argument to %s", argp[-2]);
573 if (!(cp = *argp++) || *cp == '-')
574 adios (NULLCP, "missing argument to %s", argp[-2]);
575 if ((issue = atoi (cp)) < 1)
576 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
579 if (!(cp = *argp++) || *cp == '-')
580 adios (NULLCP, "missing argument to %s", argp[-2]);
581 if ((volume = atoi (cp)) < 1)
582 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
586 forwall++; /* fall */
589 clearflg = -1;/* XXX */
609 folder = getenv ("mhfolder");
611 if (isatty (fileno (stdout)))
612 if (!nomore && !sc_hardcopy () && moreproc && *moreproc) {
614 setsig (SIGINT, SIG_IGN);
615 setsig (SIGQUIT, quitser);
621 setsig (SIGINT, SIG_IGN);
622 setsig (SIGQUIT, quitser);
628 mhl_format (form ? form : mhlformat, length, width);
631 process (folder, NULLCP, 1, vecp = 1);
633 for (i = 0; i < vecp; i++)
634 process (folder, files[i], i + 1, vecp);
638 printf ("%s", delim4);
640 (void) sprintf (buf, "End of %s Digest\n", digest);
643 (void) sprintf (buf, "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue);
645 for (cp = buf + i; i > 1; i--)
652 printf ("\n------- End of Forwarded Message%s\n\n",
653 vecp > 1 ? "s" : "");
656 if (clearflg > 0 && ontty == NOTTY)
667 static mhl_format (file, length, width)
679 register struct mcomp *c1;
682 static dev_t dev = 0;
683 static ino_t ino = 0;
684 static time_t mtime = 0;
687 if (stat (libpath (file), &st) != NOTOK
688 && mtime == st.st_mtime
693 free_queue (&fmthd, &fmttl);
695 if ((fp = fopen (libpath (file), "r")) == NULL)
696 adios (file, "unable to open format file");
698 if (fstat (fileno (fp), &st) != NOTOK)
699 mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino;
701 global.c_ovtxt = global.c_nfs = NULL;
705 if ((i = sc_width ()) > 5)
707 global.c_cwidth = -1;
708 if ((i = sc_length ()) > 5)
709 global.c_length = i - 1;
710 global.c_flags = BELL; /* BELL is default */
711 *(ip = ignores) = NULL;
713 while (vfgets (fp, &ap) == OK) {
718 if (cp = index (bp, '\n'))
722 c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT);
727 (void) strcpy (name, parse ());
732 if (uleq (name, "ignores")) {
733 ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip);
738 if (evalvar (&global))
739 adios (NULLCP, "format file syntax error: %s", bp);
746 c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT);
747 while (*parptr == ':' || *parptr == ',') {
750 adios (NULLCP, "format file syntax error: %s", bp);
752 if (!c1 -> c_nfs && global.c_nfs)
753 if (c1 -> c_flags & DATEFMT) {
754 if (global.c_flags & DATEFMT)
755 c1 -> c_nfs = getcpy (global.c_nfs);
758 if (c1 -> c_flags & ADDRFMT) {
759 if (global.c_flags & ADDRFMT)
760 c1 -> c_nfs = getcpy (global.c_nfs);
765 adios (NULLCP, "format file syntax error: %s", bp);
771 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
772 fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n",
773 c1 -> c_name, c1 -> c_text, c1 -> c_ovtxt);
774 fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n",
775 c1 -> c_nfs, c1 -> c_fmt);
776 fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n",
777 c1 -> c_offset, c1 -> c_ovoff, c1 -> c_width,
778 c1 -> c_cwidth, c1 -> c_length);
779 fprintf (stderr, "\tflags=%s\n",
780 sprintb (buffer, (unsigned) c1 -> c_flags, LBITS));
785 global.c_flags |= CLEARSCR;
788 global.c_flags &= ~CLEARSCR;
790 switch (bellflg) { /* command line may override format file */
792 global.c_flags |= BELL;
795 global.c_flags &= ~BELL;
800 global.c_length = length;
802 global.c_width = width;
803 if (global.c_length < 5)
804 global.c_length = 10000;
805 if (global.c_width < 5)
806 global.c_width = 10000;
812 register struct mcomp *c1;
816 register struct triple *ap;
820 (void) strcpy (name, parse ());
822 if (uleq (name, "component")) {
823 if (ptos (name, &c1 -> c_text))
825 c1 -> c_flags &= ~NOCOMPONENT;
828 if (uleq (name, "overflowtext"))
829 return ptos (name, &c1 -> c_ovtxt);
830 if (uleq (name, "formatfield")) {
831 if (ptos (name, &cp))
833 c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp));
834 c1 -> c_flags |= FORMAT;
838 if (uleq (name, "offset"))
839 return ptoi (name, &c1 -> c_offset);
840 if (uleq (name, "overflowoffset"))
841 return ptoi (name, &c1 -> c_ovoff);
842 if (uleq (name, "width"))
843 return ptoi (name, &c1 -> c_width);
844 if (uleq (name, "compwidth"))
845 return ptoi (name, &c1 -> c_cwidth);
846 if (uleq (name, "length"))
847 return ptoi (name, &c1 -> c_length);
848 if (uleq (name, "nodashmunging"))
849 return (dashflg = 0);
851 for (ap = triples; ap -> t_name; ap++)
852 if (uleq (ap -> t_name, name)) {
853 c1 -> c_flags |= ap -> t_on;
854 c1 -> c_flags &= ~ap -> t_off;
863 static int ptoi (name, i)
869 if (*parptr++ != '=' || !*(cp = parse ())) {
870 advise (NULLCP, "missing argument to variable %s", name);
879 static int ptos (name, s)
886 if (*parptr++ != '=') {
887 advise (NULLCP, "missing argument to variable %s", name);
893 *parptr && *parptr != ':' && *parptr != ',';
897 for (cp = ++parptr; *parptr && *parptr != '"'; parptr++)
898 if (*parptr == QUOTE)
904 if ((*parptr = c) == '"')
911 static char *parse () {
914 static char result[NAMESZ];
916 for (cp = result; c = *parptr; parptr++)
933 static process (folder, fname, ofilen, ofilec)
943 switch (setjmp (env)) {
946 fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r");
948 advise (fname, "unable to open");
957 cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname);
959 (void) signal (SIGINT, intrser);
960 mhlfile (fp, cp, ofilen, ofilec);/* fall */
964 (void) signal (SIGINT, SIG_IGN);
965 if (mhl_action == NULL && fp != stdin)
969 free (holder.c_text);
970 holder.c_text = NULL;
972 free_queue (&msghd, &msgtl);
973 for (c1 = fmthd; c1; c1 = c1 -> c_next)
974 c1 -> c_flags &= ~HDROUTPUT;
981 static mhlfile (fp, mname, ofilen, ofilec)
983 register char *mname;
988 register struct mcomp *c1,
997 printf ("%s", ofilen == 1 ? delim3 : delim4);
999 printf ("\n-------");
1001 printf (" Forwarded Message%s", ofilec > 1 ? "s" : "");
1003 printf (" Message %d", ofilen);
1012 if ((global.c_flags & CLEARSCR))
1017 printf (">>> %s\n\n", mname);
1022 (void) strcpy (buf, "\n");
1024 if (SOprintf ("Press <return> to list \"%s\"...", mname)) {
1027 printf ("Press <return> to list \"%s\"...", mname);
1029 (void) fflush (stdout);
1031 (void) read (fileno (stdout), buf, sizeof buf);
1033 if (index (buf, '\n')) {
1034 if ((global.c_flags & CLEARSCR))
1048 printf (">>> %s\n\n", mname);
1056 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
1059 for (ip = ignores; *ip; ip++)
1060 if (uleq (name, *ip)) {
1061 while (state == FLDPLUS)
1062 state = m_getfld (state, name, buf, sizeof buf, fp);
1068 for (c2 = fmthd; c2; c2 = c2 -> c_next)
1069 if (uleq (c2 -> c_name, name))
1072 if (!((c3 = c2 ? c2 : &global) -> c_flags & SPLIT))
1073 for (c1 = msghd; c1; c1 = c1 -> c_next)
1074 if (uleq (c1 -> c_name, c3 -> c_name)) {
1076 mcomp_add (c1 -> c_flags, buf, c1 -> c_text);
1080 c1 = add_queue (&msghd, &msgtl, name, buf, 0);
1081 while (state == FLDPLUS) {
1082 state = m_getfld (state, name, buf, sizeof buf, fp);
1083 c1 -> c_text = add (buf, c1 -> c_text);
1086 c1 -> c_flags |= EXTRA;
1092 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
1093 if (c1 -> c_flags & CLEARTEXT) {
1094 putcomp (c1, c1, ONECOMP);
1097 if (uleq (c1 -> c_name, "messagename")) {
1098 holder.c_text = concat ("(Message ", mname, ")\n",
1100 putcomp (c1, &holder, ONECOMP);
1101 free (holder.c_text);
1102 holder.c_text = NULL;
1105 if (uleq (c1 -> c_name, "extras")) {
1106 for (c2 = msghd; c2; c2 = c2 -> c_next)
1107 if (c2 -> c_flags & EXTRA)
1108 putcomp (c1, c2, TWOCOMP);
1111 if (dobody && uleq (c1 -> c_name, "body")) {
1112 if ((holder.c_text = malloc (sizeof buf)) == NULL)
1113 adios (NULLCP, "unable to allocate buffer memory");
1114 (void) strcpy (holder.c_text, buf);
1115 while (state == BODY) {
1116 putcomp (c1, &holder, BODYCOMP);
1117 state = m_getfld (state, name, holder.c_text,
1120 free (holder.c_text);
1121 holder.c_text = NULL;
1124 for (c2 = msghd; c2; c2 = c2 -> c_next)
1125 if (uleq (c2 -> c_name, c1 -> c_name)) {
1126 putcomp (c1, c2, ONECOMP);
1127 if (!(c1 -> c_flags & SPLIT))
1130 if (faceproc && c2 == NULL && (c1 -> c_flags & FACEFMT))
1131 for (c2 = msghd; c2; c2 = c2 -> c_next)
1132 if (c2 -> c_flags & FACEDFLT) {
1133 if (c2 -> c_face == NULL)
1135 if (holder.c_text = c2 -> c_face) {
1136 putcomp (c1, &holder, ONECOMP);
1137 holder.c_text = NULL;
1146 advise (NULLCP, "format error in message %s", mname);
1151 adios (NULLCP, "getfld() returned %d", state);
1157 static int mcomp_flags (name)
1158 register char *name;
1160 register struct pair *ap;
1162 for (ap = pairs; ap -> p_name; ap++)
1163 if (uleq (ap -> p_name, name))
1164 return (ap -> p_flags);
1170 static char *mcomp_add (flags, s1, s2)
1177 if (!(flags & ADDRFMT))
1178 return add (s1, s2);
1180 if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n')
1183 return add (s1, add (",\n", s2));
1191 struct pqpair *pq_next;
1195 static mcomp_format (c1, c2)
1196 register struct mcomp *c1,
1202 char buffer[BUFSIZ],
1204 register struct comp *cptr;
1205 register struct pqpair *p,
1208 register struct mailname *mp;
1211 c2 -> c_text = NULL;
1212 dat[0] = dat[1] = dat[2] = dat[4] = 0;
1213 dat[3] = sizeof buffer - 1;
1214 (void) fmt_compile (c1 -> c_nfs, &c1 -> c_fmt);
1216 if (!(c1 -> c_flags & ADDRFMT)) {
1217 FINDCOMP (cptr, "text");
1219 cptr -> c_text = ap;
1220 if (cp = rindex(ap, '\n')) /* drop ending newline */
1224 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1225 c2 -> c_text = getcpy (buffer);
1227 /* Don't need to append a newline, dctime() already did */
1229 if (!(c1 -> c_flags & NONEWLINE))
1230 c2 -> c_text = add ("\n", c2 -> c_text);
1237 (q = &pq) -> pq_next = NULL;
1238 while (cp = getname (ap)) {
1239 if ((p = (struct pqpair *) calloc ((unsigned) 1, sizeof *p)) == NULL)
1240 adios (NULLCP, "unable to allocate pqpair memory");
1242 if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) {
1243 p -> pq_text = getcpy (cp);
1244 p -> pq_error = getcpy (error);
1247 if ((c1 -> c_flags & FACEDFLT) && c2 -> c_face == NULL) {
1249 if ((h = mp -> m_host) == NULL)
1251 if (o = OfficialName (h))
1253 c2 -> c_face = concat ("address ", h, " ", mp -> m_mbox,
1256 p -> pq_text = getcpy (mp -> m_text);
1259 q = (q -> pq_next = p);
1262 for (p = pq.pq_next; p; p = q) {
1263 FINDCOMP (cptr, "text");
1265 cptr -> c_text = p -> pq_text;
1266 FINDCOMP (cptr, "error");
1268 cptr -> c_text = p -> pq_error;
1270 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1273 c2 -> c_text = add (",\n", c2 -> c_text);
1274 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
1276 c2 -> c_text = add (buffer, c2 -> c_text);
1279 free (p -> pq_text);
1281 free (p -> pq_error);
1286 c2 -> c_text = add ("\n", c2 -> c_text);
1292 static struct mcomp *add_queue (head, tail, name, text, flags)
1293 register struct mcomp **head,
1295 register char *name,
1299 register struct mcomp *c1;
1301 if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL)
1302 adios (NULLCP, "unable to allocate comp memory");
1304 c1 -> c_flags = flags & ~INIT;
1305 if (c1 -> c_name = name ? getcpy (name) : NULL)
1306 c1 -> c_flags |= mcomp_flags (c1 -> c_name);
1307 c1 -> c_text = text ? getcpy (text) : NULL;
1310 c1 -> c_ovtxt = getcpy (global.c_ovtxt);
1311 c1 -> c_offset = global.c_offset;
1312 c1 -> c_ovoff = global. c_ovoff;
1313 c1 -> c_width = c1 -> c_length = 0;
1314 c1 -> c_cwidth = global.c_cwidth;
1315 c1 -> c_flags |= global.c_flags & GFLAGS;
1320 (*tail) -> c_next = c1;
1327 static free_queue (head, tail)
1328 register struct mcomp **head,
1331 register struct mcomp *c1,
1334 for (c1 = *head; c1; c1 = c2) {
1337 free (c1 -> c_name);
1339 free (c1 -> c_text);
1341 free (c1 -> c_ovtxt);
1345 free ((char *) c1 -> c_fmt);
1347 free (c1 -> c_face);
1351 *head = *tail = NULL;
1356 static putcomp (c1, c2, flag)
1357 register struct mcomp *c1,
1367 llim = c1 -> c_length ? c1 -> c_length : -1;
1368 wid = c1 -> c_width ? c1 -> c_width : global.c_width;
1369 ovoff = (c1 -> c_ovoff >= 0 ? c1 -> c_ovoff : global.c_ovoff)
1371 if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL)
1373 if (wid < ovoff + strlen (ovtxt) + 5)
1374 adios (NULLCP, "component: %s width(%d) too small for overflow(%d)",
1375 c1 -> c_name, wid, ovoff + strlen (ovtxt) + 5);
1378 if (c1 -> c_flags & CLEARTEXT) {
1379 putstr (c1 -> c_text);
1384 if (c1 -> c_flags & FACEFMT)
1385 switch (doface (c2)) {
1386 case NOTOK: /* error */
1387 case OK: /* async faceproc */
1390 default: /* sync faceproc */
1394 if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT | FORMAT)))
1395 mcomp_format (c1, c2);
1397 if (c1 -> c_flags & CENTER) {
1398 count = (c1 -> c_width ? c1 -> c_width : global.c_width)
1399 - c1 -> c_offset - strlen (c2 -> c_text);
1400 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT))
1401 count -= strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2;
1402 lm = c1 -> c_offset + (count / 2);
1406 lm = c1 -> c_offset;
1408 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) {
1409 if (c1 -> c_flags & UPPERCASE) /* uppercase component also */
1410 for (cp = (c1 -> c_text ? c1 -> c_text : c1 -> c_name); *cp; cp++)
1412 *cp = toupper (*cp);
1413 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1414 if (flag != BODYCOMP) {
1416 if (!(c1 -> c_flags & SPLIT))
1417 c1 -> c_flags |= HDROUTPUT;
1420 if ((count = c1 -> c_cwidth -
1421 strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0)
1426 c1 -> c_flags |= HDROUTPUT; /* for BODYCOMP */
1430 && !(c2 -> c_flags & HDROUTPUT)
1431 && !(c2 -> c_flags & NOCOMPONENT)) {
1432 if (c1 -> c_flags & UPPERCASE)
1433 for (cp = c2 -> c_name; *cp; cp++)
1435 *cp = toupper (*cp);
1436 putstr (c2 -> c_name);
1438 if (!(c1 -> c_flags & SPLIT))
1439 c2 -> c_flags |= HDROUTPUT;
1442 if ((count = c1 -> c_cwidth - strlen (c2 -> c_name) - 2) > 0)
1446 if (c1 -> c_flags & UPPERCASE)
1447 for (cp = c2 -> c_text; *cp; cp++)
1449 *cp = toupper (*cp);
1453 if (flag == TWOCOMP)
1454 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
1455 : strlen (c2 -> c_name) + 2;
1457 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
1458 : strlen (c1->c_text ? c1->c_text : c1->c_name) + 2;
1459 count += c1 -> c_offset;
1461 if (cp = oneline (c2 -> c_text, c1 -> c_flags))
1465 while (cp = oneline (c2 -> c_text, c1 -> c_flags)) {
1467 if (flag == BODYCOMP
1468 && !(c1 -> c_flags & NOCOMPONENT))
1469 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1479 static char *oneline (stuff, flags)
1480 register char *stuff;
1490 return (onelp = NULL);
1494 if (flags & COMPRESS) {
1495 for (spc = 1, cp = ret; *onelp; onelp++)
1496 if (isspace (*onelp)) {
1497 if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) {
1516 while (*onelp && *onelp != '\n')
1518 if (*onelp == '\n') {
1522 if (flags & LEFTADJUST)
1523 while (*ret == ' ' || *ret == '\t')
1526 if (*onelp == 0 && term == '\n' && (flags & NONEWLINE))
1534 static putstr (string)
1535 register char *string;
1537 if (!column && lm > 0)
1568 if (ontty != ISTTY || row != global.c_length)
1570 if (global.c_flags & BELL)
1571 (void) putchar ('\007');
1572 (void) fflush (stdout);
1574 (void) read (fileno (stdout), buf, sizeof buf);
1575 if (index (buf, '\n')) {
1576 if (global.c_flags & CLEARSCR)
1581 (void) putchar ('\n');
1582 row = global.c_length / 3;
1600 if (column == 0 && forwflg && dashflg && ch == '-')
1601 (void) putchar ('-'), putchar (' ');
1607 if (column >= wid) {
1611 putstr (ovtxt ? ovtxt : "");
1616 (void) putchar (ch);
1623 static TYPESIG intrser (i)
1627 (void) signal (SIGINT, intrser);
1631 (void) putchar ('\n');
1633 longjmp (env, DONE);
1639 static TYPESIG pipeser (i)
1643 (void) signal (SIGPIPE, pipeser);
1652 static TYPESIG quitser (i)
1656 (void) signal (SIGQUIT, quitser);
1659 (void) putchar ('\n');
1660 (void) fflush (stdout);
1667 static face_format (c1)
1668 register struct mcomp *c1;
1671 register struct mailname *mp;
1673 if ((cp = c1 -> c_text) == NULL)
1676 if (cp = getname (cp)) {
1677 if (mp = getm (cp, NULLCP, 0, AD_NAME, NULLCP)) {
1679 if ((h = mp -> m_host) == NULL)
1681 if (o = OfficialName (h))
1683 c1 -> c_face = concat ("address ", h, " ", mp -> m_mbox, NULLCP);
1686 while (cp = getname (cp))
1693 #if defined(BSD42) || defined(SOCKETS)
1695 /* faceproc is two elements defining the image agent's location:
1700 #include <sys/socket.h>
1701 #include <netinet/in.h>
1704 #include <arpa/inet.h>
1707 struct hostent *gethostbystring ();
1710 static int doface (c1)
1711 register struct mcomp *c1;
1716 struct sockaddr_in in_socket;
1717 register struct sockaddr_in *isock = &in_socket;
1718 static int inited = OK;
1720 static struct in_addr addr;
1721 static u_short portno;
1726 char **ap = brkstring (cp = getcpy (faceproc), " ", "\n");
1729 if (ap[0] == NULL || ap[1] == NULL) {
1732 return (inited = NOTOK);
1735 if (!(hp = gethostbystring (ap[0])))
1737 bcopy (hp -> h_addr, (char *) &addr, addrlen = hp -> h_length);
1739 portno = htons ((u_short) atoi (ap[1]));
1744 if (inited == NOTOK)
1747 isock -> sin_family = AF_INET;
1748 isock -> sin_port = portno;
1749 bcopy ((char *) &addr, (char *) &isock -> sin_addr, addrlen);
1751 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
1754 result = sendto (sd, c1 -> c_text, strlen (c1 -> c_text), 0,
1755 (struct sockaddr *) isock, sizeof *isock);
1759 return (result != NOTOK ? OK : NOTOK);
1762 #else /* not BSD42 and not SOCKETS */
1764 static int doface (c1)
1765 register struct mcomp *c1;
1776 char buffer[BUFSIZ],
1779 if (pipe (pdi) == NOTOK)
1781 if (pipe (pdo) == NOTOK) {
1782 (void) close (pdi[0]);
1783 (void) close (pdi[1]);
1787 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
1795 (void) signal (SIGINT, SIG_IGN);
1796 (void) signal (SIGQUIT, SIG_IGN);
1797 if (pdi[0] != fileno (stdin)) {
1798 (void) dup2 (pdi[0], fileno (stdin));
1799 (void) close (pdi[0]);
1801 (void) close (pdi[1]);
1802 (void) close (pdo[0]);
1803 if (pdo[1] != fileno (stdout)) {
1804 (void) dup2 (pdo[1], fileno (stdout));
1805 (void) close (pdo[1]);
1808 vec[vecp++] = r1bindex (faceproc, '/');
1810 if (sleepsw != NOTOK) {
1812 (void) sprintf (buffer, "%d", sleepsw);
1813 vec[vecp++] = buffer;
1816 execvp (faceproc, vec);
1817 fprintf (stderr, "unable to exec ");
1819 _exit (-1); /* NOTREACHED */
1822 (void) close (pdi[0]);
1823 i = strlen (c1 -> c_text);
1824 if (write (pdi[1], c1 -> c_text, i) != i)
1825 adios ("pipe", "error writing to");
1826 free (c1 -> c_text), c1 -> c_text = NULL;
1827 (void) close (pdi[1]);
1829 (void) close (pdo[1]);
1832 while ((i = read (pdo[0], buffer, strlen (buffer))) > 0) {
1836 if ((dp = realloc (cp, (unsigned) (j = len + i))) == NULL)
1837 adios (NULLCP, "unable to allocate face storage");
1838 bcopy (buffer, dp + len, i);
1842 if ((cp = malloc ((unsigned) i)) == NULL)
1843 adios (NULLCP, "unable to allocate face storage");
1844 bcopy (buffer, cp, i);
1848 for (bp = buffer + i - 1; bp >= buffer; bp--)
1849 if (!isascii (*bp) || iscntrl (*bp)) {
1854 (void) close (pdo[0]);
1856 /* no waiting for child... */
1858 if (result == OK) { /* binary */
1859 if (write (1, cp, len) != len)
1860 adios ("writing", "error");
1864 if ((c1 -> c_text = cp) == NULL)
1871 #endif /* not BSD42 and not SOCKETS */
1878 int mhlsbr (argc, argv, action)
1883 TYPESIG (*istat) (), (*pstat) (), (*qstat) ();
1887 switch (setjmp (mhlenv)) {
1890 sleepsw = 0; /* XXX */
1891 bellflg = clearflg = forwflg = forwall = exitstat = 0;
1894 mhl_action = action;
1895 if ((istat = signal (SIGINT, SIG_IGN)) != SIG_DFL)
1896 (void) signal (SIGINT, istat);
1897 if ((qstat = signal (SIGQUIT, SIG_IGN)) != SIG_DFL)
1898 (void) signal (SIGQUIT, qstat);
1899 pstat = signal (SIGPIPE, pipeser);
1900 (void) mhl (argc, argv); /* fall */
1903 (void) signal (SIGINT, istat);
1904 (void) signal (SIGQUIT, qstat);
1905 (void) signal (SIGPIPE, SIG_IGN);/* XXX */
1908 (void) signal (SIGPIPE, pstat);
1910 if (holder.c_text) {
1911 free (holder.c_text);
1912 holder.c_text = NULL;
1914 free_queue (&msghd, &msgtl);
1915 for (c1 = fmthd; c1; c1 = c1 -> c_next)
1916 c1 -> c_flags &= ~HDROUTPUT;
1925 static void mhladios (what, fmt, a, b, c, d, e, f)
1935 advise (what, fmt, a, b, c, d, e, f);
1940 static void mhldone (status)
1945 longjmp (mhlenv, DONE);
1952 static int m_pid = NOTOK;
1953 static int sd = NOTOK;
1956 static m_popen (name)
1961 if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
1962 adios ("standard output", "unable to dup()");
1964 if (pipe (pd) == NOTOK)
1965 adios ("pipe", "unable to");
1967 switch (m_pid = vfork ()) {
1969 adios ("fork", "unable to");
1972 (void) signal (SIGINT, SIG_DFL);
1973 (void) signal (SIGQUIT, SIG_DFL);
1975 (void) close (pd[1]);
1976 if (pd[0] != fileno (stdin)) {
1977 (void) dup2 (pd[0], fileno (stdin));
1978 (void) close (pd[0]);
1980 execlp (name, r1bindex (name, '/'), NULLCP);
1981 fprintf (stderr, "unable to exec ");
1986 (void) close (pd[0]);
1987 if (pd[1] != fileno (stdout)) {
1988 (void) dup2 (pd[1], fileno (stdout));
1989 (void) close (pd[1]);
2000 (void) fflush (stdout);
2001 if (dup2 (sd, fileno (stdout)) == NOTOK)
2002 adios ("standard output", "unable to dup2()");
2009 (void) fclose (stdout);
2011 (void) pidwait (m_pid, OK);
2019 @use gethostbystring()
2024 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.28 1992/12/15 00:20:22 jromine Exp jromine $";
2028 c2 -> c_text = getcpy (buffer);
2039 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.27 1992/12/03 16:50:27 jromine Exp jromine $";
2043 if (hp = gethostbyname (ap[0]))
2044 bcopy (hp -> h_addr, (char *) &addr, addrlen = hp -> h_length);
2046 if (iaddr = inet_addr (ap[0]))
2047 bcopy ((char *) &iaddr, (char *) &addr,
2048 addrlen = sizeof iaddr);
2056 @put u_short ifdef under #if AUX
2061 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.26 1992/12/03 16:28:56 jromine Exp jromine $";
2077 #else not BSD42 and not SOCKETS
2080 #endif not BSD42 and not SOCKETS
2086 @u_short AUX changes from Jim Guyton
2091 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.25 1992/11/18 00:19:56 jromine Exp jromine $";
2100 @add "newline" for consistency
2105 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.24 1992/11/18 00:19:00 jromine Exp jromine $";
2112 @add "nonewline" option
2117 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.23 1992/11/17 00:03:06 jromine Exp jromine $";
2119 "nonewline", NONEWLINE, 0,
2126 @don't put an extra space at the end of the `%{text}' in a formatfield
2131 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.22 1992/10/26 23:00:16 jromine Exp jromine $";
2134 #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT"
2147 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.21 1992/10/16 21:36:54 jromine Exp jromine $";
2159 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.20 1992/02/10 20:30:11 jromine Exp jromine $";
2163 static int intrser (), pipeser (), quitser ();
2166 static int intrser (i)
2169 static int pipeser (i)
2172 static int quitser (i)
2178 @conform with RFC1153 for digests
2183 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.19 1992/02/10 20:11:37 jromine Exp jromine $";
2189 if (uleq (c1 -> c_name, "body")) {
2200 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.18 1992/02/05 07:26:30 jromine Exp jromine $";
2203 "\n------------------------------------------------------------\n\n";
2209 @put unseen sequence in mh-format
2214 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.17 1992/01/31 22:12:40 jromine Exp jromine $";
2217 putstr (oneline (c2 -> c_text, c1 -> c_flags));
2228 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.16 1991/01/25 14:49:46 mh Exp jromine $";
2234 dat[0] = dat[1] = dat[2] = 0;
2240 @don't include arpa/inet.h on hpux
2245 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.15 91/01/16 08:56:04 mh Exp Locker: mh $";
2251 NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, NULL
2254 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, NULL
2299 @add :nodashmunging option
2304 static char ident[] = "@@(#)$Id: mhlsbr.c,v 1.14 90/04/05 14:58:08 sources Exp Locker: mh $";
2317 static char ident[] = "@@(#)$Id:$";
2324 @make -[no]dashmunging hidden
2333 @allow formatfield on all fields
2347 @goof in #define ...SW ordering
2352 if (c1 -> c_flags & DATEFMT) {
2355 if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT)))
2361 @additions for digests
2401 (void) sprintf (buf, "End of %s Digest\n", digest);
2412 void mhladios (), mhldone ();
2413 int intrser (), pipeser (), quitser ();
2414 char *mcomp_add (), *oneline (), *parse ();
2415 struct mcomp *add_queue ();
2427 #if defined(BSD42) || defined(hpux)
2444 int (*istat) (), (*pstat) (), (*qstat) ();
2460 @body: fix for missing component on blank lines
2468 "nodashmunging", -6,
2486 @fix for BODYCOMP bug
2491 while (cp = oneline (c2 -> c_text, c1 -> c_flags))
2494 if (flag == BODYCOMP
2495 && !(c1 -> c_flags & NOCOMPONENT))
2496 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
2510 @don't append extra newline to date fields
2515 && !(c1 -> c_flags & HDROUTPUT)
2526 c2 -> c_text = concat (buffer, "\n", NULLCP);