1 /* mhlsbr.c - implement the "nifty" message lister */
3 static char ident[] = "@(#)$Id: mhlsbr.c,v 1.30 1995/12/08 17:57:16 jromine Exp $";
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../zotnet/tws.h"
11 #undef NULLVP /* XXX */
13 #if defined(SYS5) && defined(AUX)
14 #define u_short ushort
21 #include <sys/types.h>
26 for a component containing addresses, ADDRFMT, if COMPRESS is also
27 set, then addresses get split wrong (not at the spaces between commas).
28 To fix this correctly, putstr() should know about "atomic" strings that
29 must NOT be broken across lines. That's too difficult for right now
30 (it turns out that there are a number of degernate cases), so in
33 (*onelp == '\n' && !onelp[1])
35 being a terminating condition,
37 (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT)))
39 is used instead. This cuts the line prematurely, and gives us a much
40 better chance of getting things right.
45 #define u_short ushort
52 #define adios mhladios
59 static struct swit mhlswitches[] = {
71 "faceproc program", 0,
81 "moreproc program", 0,
102 "forward", -7, /* interface from forw */
104 "forwall", -7, /* .. */
120 char *c_name; /* component name */
121 char *c_text; /* component text */
122 char *c_ovtxt; /* text overflow indicator */
123 char *c_nfs; /* iff FORMAT */
124 struct format *c_fmt; /* .. */
125 char *c_face; /* face designator */
127 int c_offset; /* left margin indentation */
128 int c_ovoff; /* overflow indentation */
129 int c_width; /* width of field */
130 int c_cwidth; /* width of component */
131 int c_length; /* length in lines */
134 #define NOCOMPONENT 0x000001/* don't show component name */
135 #define UPPERCASE 0x000002/* display in all upper case */
136 #define CENTER 0x000004/* center line */
137 #define CLEARTEXT 0x000008/* cleartext */
138 #define EXTRA 0x000010/* an "extra" component */
139 #define HDROUTPUT 0x000020/* already output */
140 #define CLEARSCR 0x000040/* clear screen */
141 #define LEFTADJUST 0x000080/* left justify multiple lines */
142 #define COMPRESS 0x000100/* compress text */
143 #define ADDRFMT 0x000200/* contains addresses */
144 #define BELL 0x000400/* sound bell at EOP */
145 #define DATEFMT 0x000800/* contains dates */
146 #define FORMAT 0x001000/* parse address/date */
147 #define INIT 0x002000/* initialize component */
148 #define FACEFMT 0x004000/* contains face */
149 #define FACEDFLT 0x008000/* default for face */
150 #define SPLIT 0x010000/* split headers (don't concatenate) */
151 #define NONEWLINE 0x020000/* don't write trailing newline */
152 #define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07CLEARSCR\010LEFTADJUST\011COMPRESS\012ADDRFMT\013BELL\014DATEFMT\015FORMAT\016INIT\017FACEFMT\020FACEDFLT\021SPLIT\022NONEWLINE"
153 #define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS \
156 struct mcomp *c_next;
159 static struct mcomp *msghd = NULL;
160 static struct mcomp *msgtl = NULL;
161 static struct mcomp *fmthd = NULL;
162 static struct mcomp *fmttl = NULL;
164 static struct mcomp global = {
165 NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, 0
167 static struct mcomp holder =
169 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, 0
178 "From", ADDRFMT | FACEDFLT,
184 "Resent-Date", DATEFMT,
185 "Resent-From", ADDRFMT,
186 "Resent-Sender", ADDRFMT,
187 "Resent-Reply-To", ADDRFMT,
188 "Resent-To", ADDRFMT,
189 "Resent-cc", ADDRFMT,
190 "Resent-Bcc", ADDRFMT,
196 static struct triple {
201 "nocomponent", NOCOMPONENT, 0,
202 "uppercase", UPPERCASE, 0,
203 "nouppercase", 0, UPPERCASE,
205 "nocenter", 0, CENTER,
206 "clearscreen", CLEARSCR, 0,
207 "noclearscreen", 0, CLEARSCR,
208 "noclear", 0, CLEARSCR,
209 "leftadjust", LEFTADJUST, 0,
210 "noleftadjust", 0, LEFTADJUST,
211 "compress", COMPRESS, 0,
212 "nocompress", 0, COMPRESS,
215 "addrfield", ADDRFMT, DATEFMT,
218 "datefield", DATEFMT, ADDRFMT,
219 "newline", 0, NONEWLINE,
220 "nonewline", NONEWLINE, 0,
227 static int bellflg = 0;
228 static int clearflg = 0;
229 static int dashflg = 1;
230 static int dobody = 1;
231 static int forwflg = 0;
232 static int forwall = 0;
234 static int sleepsw = NOTOK;
236 static char *digest = NULL;
237 static int volume = 0;
238 static int issue = 0;
240 static int exitstat = 0;
241 static int mhldebug = 0;
246 static int ontty = NOTTY;
264 static char *ignores[MAXARGS];
268 static jmp_buf mhlenv;
271 static char delim3[] = /* from forw.c */
272 "\n----------------------------------------------------------------------\n\n";
273 static char delim4[] = "\n------------------------------\n\n";
276 static FP (*mhl_action) () = (FP (*) ()) 0;
279 static void mhladios (), mhldone ();
280 static TYPESIG intrser (), pipeser (), quitser ();
281 static char *mcomp_add (), *oneline (), *parse ();
282 static struct mcomp *add_queue ();
284 static mhl_format(), evalvar(), process(), mhlfile(), free_queue(), putcomp();
285 static putstr(), putch(), face_format(), m_popen();
286 static int ptoi(), ptos(), doface();
288 void clear_screen ();
312 invo_name = r1bindex (argv[0], '/');
313 if ((cp = getenv ("MHLDEBUG")) && *cp)
315 if ((cp = m_find (invo_name)) != NULL) {
316 ap = brkstring (getcpy (cp), " ", "\n");
317 ap = copyip (ap, arguments);
321 (void) copyip (argv + 1, ap);
326 if (cp = getenv ("FACEPROC"))
330 while (cp = *argp++) {
332 switch (smatch (++cp, mhlswitches)) {
334 ambigsw (cp, mhlswitches);
337 adios (NULLCP, "-%s unknown\n", cp);
339 (void) sprintf (buf, "%s [switches] [files ...]",
341 help (buf, mhlswitches);
359 if (!(folder = *argp++) || *folder == '-')
360 adios (NULLCP, "missing argument to %s", argp[-2]);
363 if (!(form = *argp++) || *form == '-')
364 adios (NULLCP, "missing argument to %s", argp[-2]);
368 if (!(faceproc = *argp++) || *faceproc == '-')
369 adios (NULLCP, "missing argument to %s", argp[-2]);
375 if (!(cp = *argp++) || *cp == '-')
376 adios (NULLCP, "missing argument to %s", argp[-2]);
377 sleepsw = atoi (cp);/* ZERO ok! */
381 if (!(moreproc = *argp++) || *moreproc == '-')
382 adios (NULLCP, "missing argument to %s", argp[-2]);
389 if (!(cp = *argp++) || *cp == '-')
390 adios (NULLCP, "missing argument to %s", argp[-2]);
391 if ((length = atoi (cp)) < 1)
392 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
395 if (!(cp = *argp++) || *cp == '-')
396 adios (NULLCP, "missing argument to %s", argp[-2]);
397 if ((width = atoi (cp)) < 1)
398 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
402 if (!(digest = *argp++) || *digest == '-')
403 adios (NULLCP, "missing argument to %s", argp[-2]);
406 if (!(cp = *argp++) || *cp == '-')
407 adios (NULLCP, "missing argument to %s", argp[-2]);
408 if ((issue = atoi (cp)) < 1)
409 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
412 if (!(cp = *argp++) || *cp == '-')
413 adios (NULLCP, "missing argument to %s", argp[-2]);
414 if ((volume = atoi (cp)) < 1)
415 adios (NULLCP, "bad argument %s %s", argp[-2], cp);
419 forwall++; /* fall */
422 clearflg = -1;/* XXX */
442 folder = getenv ("mhfolder");
444 if (isatty (fileno (stdout)))
445 if (!nomore && !sc_hardcopy () && moreproc && *moreproc) {
447 setsig (SIGINT, SIG_IGN);
448 setsig (SIGQUIT, quitser);
454 setsig (SIGINT, SIG_IGN);
455 setsig (SIGQUIT, quitser);
461 mhl_format (form ? form : mhlformat, length, width);
464 process (folder, NULLCP, 1, vecp = 1);
466 for (i = 0; i < vecp; i++)
467 process (folder, files[i], i + 1, vecp);
471 printf ("%s", delim4);
473 (void) sprintf (buf, "End of %s Digest\n", digest);
476 (void) sprintf (buf, "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue);
478 for (cp = buf + i; i > 1; i--)
485 printf ("\n------- End of Forwarded Message%s\n\n",
486 vecp > 1 ? "s" : "");
489 if (clearflg > 0 && ontty == NOTTY)
500 static mhl_format (file, length, width)
512 register struct mcomp *c1;
515 static dev_t dev = 0;
516 static ino_t ino = 0;
517 static time_t mtime = 0;
520 if (stat (libpath (file), &st) != NOTOK
521 && mtime == st.st_mtime
526 free_queue (&fmthd, &fmttl);
528 if ((fp = fopen (libpath (file), "r")) == NULL)
529 adios (file, "unable to open format file");
531 if (fstat (fileno (fp), &st) != NOTOK)
532 mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino;
534 global.c_ovtxt = global.c_nfs = NULL;
538 if ((i = sc_width ()) > 5)
540 global.c_cwidth = -1;
541 if ((i = sc_length ()) > 5)
542 global.c_length = i - 1;
543 global.c_flags = BELL; /* BELL is default */
544 *(ip = ignores) = NULL;
546 while (vfgets (fp, &ap) == OK) {
551 if (cp = index (bp, '\n'))
555 c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT);
560 (void) strcpy (name, parse ());
565 if (uleq (name, "ignores")) {
566 ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip);
571 if (evalvar (&global))
572 adios (NULLCP, "format file syntax error: %s", bp);
579 c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT);
580 while (*parptr == ':' || *parptr == ',') {
583 adios (NULLCP, "format file syntax error: %s", bp);
585 if (!c1 -> c_nfs && global.c_nfs)
586 if (c1 -> c_flags & DATEFMT) {
587 if (global.c_flags & DATEFMT)
588 c1 -> c_nfs = getcpy (global.c_nfs);
591 if (c1 -> c_flags & ADDRFMT) {
592 if (global.c_flags & ADDRFMT)
593 c1 -> c_nfs = getcpy (global.c_nfs);
598 adios (NULLCP, "format file syntax error: %s", bp);
604 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
605 fprintf (stderr, "c1: name=\"%s\" text=\"%s\" ovtxt=\"%s\"\n",
606 c1 -> c_name, c1 -> c_text, c1 -> c_ovtxt);
607 fprintf (stderr, "\tnfs=0x%x fmt=0x%x\n",
608 c1 -> c_nfs, c1 -> c_fmt);
609 fprintf (stderr, "\toffset=%d ovoff=%d width=%d cwidth=%d length=%d\n",
610 c1 -> c_offset, c1 -> c_ovoff, c1 -> c_width,
611 c1 -> c_cwidth, c1 -> c_length);
612 fprintf (stderr, "\tflags=%s\n",
613 sprintb (buffer, (unsigned) c1 -> c_flags, LBITS));
618 global.c_flags |= CLEARSCR;
621 global.c_flags &= ~CLEARSCR;
623 switch (bellflg) { /* command line may override format file */
625 global.c_flags |= BELL;
628 global.c_flags &= ~BELL;
633 global.c_length = length;
635 global.c_width = width;
636 if (global.c_length < 5)
637 global.c_length = 10000;
638 if (global.c_width < 5)
639 global.c_width = 10000;
645 register struct mcomp *c1;
649 register struct triple *ap;
653 (void) strcpy (name, parse ());
655 if (uleq (name, "component")) {
656 if (ptos (name, &c1 -> c_text))
658 c1 -> c_flags &= ~NOCOMPONENT;
661 if (uleq (name, "overflowtext"))
662 return ptos (name, &c1 -> c_ovtxt);
663 if (uleq (name, "formatfield")) {
664 if (ptos (name, &cp))
666 c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp));
667 c1 -> c_flags |= FORMAT;
671 if (uleq (name, "offset"))
672 return ptoi (name, &c1 -> c_offset);
673 if (uleq (name, "overflowoffset"))
674 return ptoi (name, &c1 -> c_ovoff);
675 if (uleq (name, "width"))
676 return ptoi (name, &c1 -> c_width);
677 if (uleq (name, "compwidth"))
678 return ptoi (name, &c1 -> c_cwidth);
679 if (uleq (name, "length"))
680 return ptoi (name, &c1 -> c_length);
681 if (uleq (name, "nodashmunging"))
682 return (dashflg = 0);
684 for (ap = triples; ap -> t_name; ap++)
685 if (uleq (ap -> t_name, name)) {
686 c1 -> c_flags |= ap -> t_on;
687 c1 -> c_flags &= ~ap -> t_off;
696 static int ptoi (name, i)
702 if (*parptr++ != '=' || !*(cp = parse ())) {
703 advise (NULLCP, "missing argument to variable %s", name);
712 static int ptos (name, s)
719 if (*parptr++ != '=') {
720 advise (NULLCP, "missing argument to variable %s", name);
726 *parptr && *parptr != ':' && *parptr != ',';
730 for (cp = ++parptr; *parptr && *parptr != '"'; parptr++)
731 if (*parptr == QUOTE)
737 if ((*parptr = c) == '"')
744 static char *parse () {
747 static char result[NAMESZ];
749 for (cp = result; c = *parptr; parptr++)
766 static process (folder, fname, ofilen, ofilec)
776 switch (setjmp (env)) {
779 fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r");
781 advise (fname, "unable to open");
790 cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname);
792 (void) signal (SIGINT, intrser);
793 mhlfile (fp, cp, ofilen, ofilec);/* fall */
797 (void) signal (SIGINT, SIG_IGN);
798 if (mhl_action == NULL && fp != stdin)
802 free (holder.c_text);
803 holder.c_text = NULL;
805 free_queue (&msghd, &msgtl);
806 for (c1 = fmthd; c1; c1 = c1 -> c_next)
807 c1 -> c_flags &= ~HDROUTPUT;
814 static mhlfile (fp, mname, ofilen, ofilec)
816 register char *mname;
821 register struct mcomp *c1,
830 printf ("%s", ofilen == 1 ? delim3 : delim4);
832 printf ("\n-------");
834 printf (" Forwarded Message%s", ofilec > 1 ? "s" : "");
836 printf (" Message %d", ofilen);
845 if ((global.c_flags & CLEARSCR))
850 printf (">>> %s\n\n", mname);
855 (void) strcpy (buf, "\n");
857 if (SOprintf ("Press <return> to list \"%s\"...", mname)) {
860 printf ("Press <return> to list \"%s\"...", mname);
862 (void) fflush (stdout);
864 (void) read (fileno (stdout), buf, sizeof buf);
866 if (index (buf, '\n')) {
867 if ((global.c_flags & CLEARSCR))
881 printf (">>> %s\n\n", mname);
889 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
892 for (ip = ignores; *ip; ip++)
893 if (uleq (name, *ip)) {
894 while (state == FLDPLUS)
895 state = m_getfld (state, name, buf, sizeof buf, fp);
901 for (c2 = fmthd; c2; c2 = c2 -> c_next)
902 if (uleq (c2 -> c_name, name))
905 if (!((c3 = c2 ? c2 : &global) -> c_flags & SPLIT))
906 for (c1 = msghd; c1; c1 = c1 -> c_next)
907 if (uleq (c1 -> c_name, c3 -> c_name)) {
909 mcomp_add (c1 -> c_flags, buf, c1 -> c_text);
913 c1 = add_queue (&msghd, &msgtl, name, buf, 0);
914 while (state == FLDPLUS) {
915 state = m_getfld (state, name, buf, sizeof buf, fp);
916 c1 -> c_text = add (buf, c1 -> c_text);
919 c1 -> c_flags |= EXTRA;
925 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
926 if (c1 -> c_flags & CLEARTEXT) {
927 putcomp (c1, c1, ONECOMP);
930 if (uleq (c1 -> c_name, "messagename")) {
931 holder.c_text = concat ("(Message ", mname, ")\n",
933 putcomp (c1, &holder, ONECOMP);
934 free (holder.c_text);
935 holder.c_text = NULL;
938 if (uleq (c1 -> c_name, "extras")) {
939 for (c2 = msghd; c2; c2 = c2 -> c_next)
940 if (c2 -> c_flags & EXTRA)
941 putcomp (c1, c2, TWOCOMP);
944 if (dobody && uleq (c1 -> c_name, "body")) {
945 if ((holder.c_text = malloc (sizeof buf)) == NULL)
946 adios (NULLCP, "unable to allocate buffer memory");
947 (void) strcpy (holder.c_text, buf);
948 while (state == BODY) {
949 putcomp (c1, &holder, BODYCOMP);
950 state = m_getfld (state, name, holder.c_text,
953 free (holder.c_text);
954 holder.c_text = NULL;
957 for (c2 = msghd; c2; c2 = c2 -> c_next)
958 if (uleq (c2 -> c_name, c1 -> c_name)) {
959 putcomp (c1, c2, ONECOMP);
960 if (!(c1 -> c_flags & SPLIT))
963 if (faceproc && c2 == NULL && (c1 -> c_flags & FACEFMT))
964 for (c2 = msghd; c2; c2 = c2 -> c_next)
965 if (c2 -> c_flags & FACEDFLT) {
966 if (c2 -> c_face == NULL)
968 if (holder.c_text = c2 -> c_face) {
969 putcomp (c1, &holder, ONECOMP);
970 holder.c_text = NULL;
979 advise (NULLCP, "format error in message %s", mname);
984 adios (NULLCP, "getfld() returned %d", state);
990 static int mcomp_flags (name)
993 register struct pair *ap;
995 for (ap = pairs; ap -> p_name; ap++)
996 if (uleq (ap -> p_name, name))
997 return (ap -> p_flags);
1003 static char *mcomp_add (flags, s1, s2)
1010 if (!(flags & ADDRFMT))
1011 return add (s1, s2);
1013 if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n')
1016 return add (s1, add (",\n", s2));
1024 struct pqpair *pq_next;
1028 static mcomp_format (c1, c2)
1029 register struct mcomp *c1,
1035 char buffer[BUFSIZ],
1037 register struct comp *cptr;
1038 register struct pqpair *p,
1041 register struct mailname *mp;
1044 c2 -> c_text = NULL;
1045 dat[0] = dat[1] = dat[2] = dat[4] = 0;
1046 dat[3] = sizeof buffer - 1;
1047 (void) fmt_compile (c1 -> c_nfs, &c1 -> c_fmt);
1049 if (!(c1 -> c_flags & ADDRFMT)) {
1050 FINDCOMP (cptr, "text");
1052 cptr -> c_text = ap;
1053 if (cp = rindex(ap, '\n')) /* drop ending newline */
1057 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1058 c2 -> c_text = getcpy (buffer);
1060 /* Don't need to append a newline, dctime() already did */
1062 if (!(c1 -> c_flags & NONEWLINE))
1063 c2 -> c_text = add ("\n", c2 -> c_text);
1070 (q = &pq) -> pq_next = NULL;
1071 while (cp = getname (ap)) {
1072 if ((p = (struct pqpair *) calloc ((unsigned) 1, sizeof *p)) == NULL)
1073 adios (NULLCP, "unable to allocate pqpair memory");
1075 if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) {
1076 p -> pq_text = getcpy (cp);
1077 p -> pq_error = getcpy (error);
1080 if ((c1 -> c_flags & FACEDFLT) && c2 -> c_face == NULL) {
1082 if ((h = mp -> m_host) == NULL)
1084 if (o = OfficialName (h))
1086 c2 -> c_face = concat ("address ", h, " ", mp -> m_mbox,
1089 p -> pq_text = getcpy (mp -> m_text);
1092 q = (q -> pq_next = p);
1095 for (p = pq.pq_next; p; p = q) {
1096 FINDCOMP (cptr, "text");
1098 cptr -> c_text = p -> pq_text;
1099 FINDCOMP (cptr, "error");
1101 cptr -> c_text = p -> pq_error;
1103 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1106 c2 -> c_text = add (",\n", c2 -> c_text);
1107 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
1109 c2 -> c_text = add (buffer, c2 -> c_text);
1112 free (p -> pq_text);
1114 free (p -> pq_error);
1119 c2 -> c_text = add ("\n", c2 -> c_text);
1125 static struct mcomp *add_queue (head, tail, name, text, flags)
1126 register struct mcomp **head,
1128 register char *name,
1132 register struct mcomp *c1;
1134 if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL)
1135 adios (NULLCP, "unable to allocate comp memory");
1137 c1 -> c_flags = flags & ~INIT;
1138 if (c1 -> c_name = name ? getcpy (name) : NULL)
1139 c1 -> c_flags |= mcomp_flags (c1 -> c_name);
1140 c1 -> c_text = text ? getcpy (text) : NULL;
1143 c1 -> c_ovtxt = getcpy (global.c_ovtxt);
1144 c1 -> c_offset = global.c_offset;
1145 c1 -> c_ovoff = global. c_ovoff;
1146 c1 -> c_width = c1 -> c_length = 0;
1147 c1 -> c_cwidth = global.c_cwidth;
1148 c1 -> c_flags |= global.c_flags & GFLAGS;
1153 (*tail) -> c_next = c1;
1160 static free_queue (head, tail)
1161 register struct mcomp **head,
1164 register struct mcomp *c1,
1167 for (c1 = *head; c1; c1 = c2) {
1170 free (c1 -> c_name);
1172 free (c1 -> c_text);
1174 free (c1 -> c_ovtxt);
1178 free ((char *) c1 -> c_fmt);
1180 free (c1 -> c_face);
1184 *head = *tail = NULL;
1189 static putcomp (c1, c2, flag)
1190 register struct mcomp *c1,
1200 llim = c1 -> c_length ? c1 -> c_length : -1;
1201 wid = c1 -> c_width ? c1 -> c_width : global.c_width;
1202 ovoff = (c1 -> c_ovoff >= 0 ? c1 -> c_ovoff : global.c_ovoff)
1204 if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL)
1206 if (wid < ovoff + strlen (ovtxt) + 5)
1207 adios (NULLCP, "component: %s width(%d) too small for overflow(%d)",
1208 c1 -> c_name, wid, ovoff + strlen (ovtxt) + 5);
1211 if (c1 -> c_flags & CLEARTEXT) {
1212 putstr (c1 -> c_text);
1217 if (c1 -> c_flags & FACEFMT)
1218 switch (doface (c2)) {
1219 case NOTOK: /* error */
1220 case OK: /* async faceproc */
1223 default: /* sync faceproc */
1227 if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT | FORMAT)))
1228 mcomp_format (c1, c2);
1230 if (c1 -> c_flags & CENTER) {
1231 count = (c1 -> c_width ? c1 -> c_width : global.c_width)
1232 - c1 -> c_offset - strlen (c2 -> c_text);
1233 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT))
1234 count -= strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) + 2;
1235 lm = c1 -> c_offset + (count / 2);
1239 lm = c1 -> c_offset;
1241 if (!(c1 -> c_flags & HDROUTPUT) && !(c1 -> c_flags & NOCOMPONENT)) {
1242 if (c1 -> c_flags & UPPERCASE) /* uppercase component also */
1243 for (cp = (c1 -> c_text ? c1 -> c_text : c1 -> c_name); *cp; cp++)
1245 *cp = toupper (*cp);
1246 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1247 if (flag != BODYCOMP) {
1249 if (!(c1 -> c_flags & SPLIT))
1250 c1 -> c_flags |= HDROUTPUT;
1253 if ((count = c1 -> c_cwidth -
1254 strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0)
1259 c1 -> c_flags |= HDROUTPUT; /* for BODYCOMP */
1263 && !(c2 -> c_flags & HDROUTPUT)
1264 && !(c2 -> c_flags & NOCOMPONENT)) {
1265 if (c1 -> c_flags & UPPERCASE)
1266 for (cp = c2 -> c_name; *cp; cp++)
1268 *cp = toupper (*cp);
1269 putstr (c2 -> c_name);
1271 if (!(c1 -> c_flags & SPLIT))
1272 c2 -> c_flags |= HDROUTPUT;
1275 if ((count = c1 -> c_cwidth - strlen (c2 -> c_name) - 2) > 0)
1279 if (c1 -> c_flags & UPPERCASE)
1280 for (cp = c2 -> c_text; *cp; cp++)
1282 *cp = toupper (*cp);
1286 if (flag == TWOCOMP)
1287 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
1288 : strlen (c2 -> c_name) + 2;
1290 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
1291 : strlen (c1->c_text ? c1->c_text : c1->c_name) + 2;
1292 count += c1 -> c_offset;
1294 if (cp = oneline (c2 -> c_text, c1 -> c_flags))
1298 while (cp = oneline (c2 -> c_text, c1 -> c_flags)) {
1300 if (flag == BODYCOMP
1301 && !(c1 -> c_flags & NOCOMPONENT))
1302 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1312 static char *oneline (stuff, flags)
1313 register char *stuff;
1323 return (onelp = NULL);
1327 if (flags & COMPRESS) {
1328 for (spc = 1, cp = ret; *onelp; onelp++)
1329 if (isspace (*onelp)) {
1330 if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) {
1349 while (*onelp && *onelp != '\n')
1351 if (*onelp == '\n') {
1355 if (flags & LEFTADJUST)
1356 while (*ret == ' ' || *ret == '\t')
1359 if (*onelp == 0 && term == '\n' && (flags & NONEWLINE))
1367 static putstr (string)
1368 register char *string;
1370 if (!column && lm > 0)
1401 if (ontty != ISTTY || row != global.c_length)
1403 if (global.c_flags & BELL)
1404 (void) putchar ('\007');
1405 (void) fflush (stdout);
1407 (void) read (fileno (stdout), buf, sizeof buf);
1408 if (index (buf, '\n')) {
1409 if (global.c_flags & CLEARSCR)
1414 (void) putchar ('\n');
1415 row = global.c_length / 3;
1433 if (column == 0 && forwflg && dashflg && ch == '-')
1434 (void) putchar ('-'), putchar (' ');
1440 if (column >= wid) {
1444 putstr (ovtxt ? ovtxt : "");
1449 (void) putchar (ch);
1456 static TYPESIG intrser (i)
1460 (void) signal (SIGINT, intrser);
1464 (void) putchar ('\n');
1466 longjmp (env, DONE);
1472 static TYPESIG pipeser (i)
1476 (void) signal (SIGPIPE, pipeser);
1485 static TYPESIG quitser (i)
1489 (void) signal (SIGQUIT, quitser);
1492 (void) putchar ('\n');
1493 (void) fflush (stdout);
1500 static face_format (c1)
1501 register struct mcomp *c1;
1504 register struct mailname *mp;
1506 if ((cp = c1 -> c_text) == NULL)
1509 if (cp = getname (cp)) {
1510 if (mp = getm (cp, NULLCP, 0, AD_NAME, NULLCP)) {
1512 if ((h = mp -> m_host) == NULL)
1514 if (o = OfficialName (h))
1516 c1 -> c_face = concat ("address ", h, " ", mp -> m_mbox, NULLCP);
1519 while (cp = getname (cp))
1526 #if defined(BSD42) || defined(SOCKETS)
1528 /* faceproc is two elements defining the image agent's location:
1533 #include <sys/socket.h>
1534 #include <netinet/in.h>
1537 #include <arpa/inet.h>
1540 struct hostent *gethostbystring ();
1543 static int doface (c1)
1544 register struct mcomp *c1;
1549 struct sockaddr_in in_socket;
1550 register struct sockaddr_in *isock = &in_socket;
1551 static int inited = OK;
1553 static struct in_addr addr;
1554 static u_short portno;
1559 char **ap = brkstring (cp = getcpy (faceproc), " ", "\n");
1562 if (ap[0] == NULL || ap[1] == NULL) {
1565 return (inited = NOTOK);
1568 if (!(hp = gethostbystring (ap[0])))
1570 bcopy (hp -> h_addr, (char *) &addr, addrlen = hp -> h_length);
1572 portno = htons ((u_short) atoi (ap[1]));
1577 if (inited == NOTOK)
1580 isock -> sin_family = AF_INET;
1581 isock -> sin_port = portno;
1582 bcopy ((char *) &addr, (char *) &isock -> sin_addr, addrlen);
1584 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
1587 result = sendto (sd, c1 -> c_text, strlen (c1 -> c_text), 0,
1588 (struct sockaddr *) isock, sizeof *isock);
1592 return (result != NOTOK ? OK : NOTOK);
1595 #else /* not BSD42 and not SOCKETS */
1597 static int doface (c1)
1598 register struct mcomp *c1;
1609 char buffer[BUFSIZ],
1612 if (pipe (pdi) == NOTOK)
1614 if (pipe (pdo) == NOTOK) {
1615 (void) close (pdi[0]);
1616 (void) close (pdi[1]);
1620 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
1628 (void) signal (SIGINT, SIG_IGN);
1629 (void) signal (SIGQUIT, SIG_IGN);
1630 if (pdi[0] != fileno (stdin)) {
1631 (void) dup2 (pdi[0], fileno (stdin));
1632 (void) close (pdi[0]);
1634 (void) close (pdi[1]);
1635 (void) close (pdo[0]);
1636 if (pdo[1] != fileno (stdout)) {
1637 (void) dup2 (pdo[1], fileno (stdout));
1638 (void) close (pdo[1]);
1641 vec[vecp++] = r1bindex (faceproc, '/');
1643 if (sleepsw != NOTOK) {
1645 (void) sprintf (buffer, "%d", sleepsw);
1646 vec[vecp++] = buffer;
1649 execvp (faceproc, vec);
1650 fprintf (stderr, "unable to exec ");
1652 _exit (-1); /* NOTREACHED */
1655 (void) close (pdi[0]);
1656 i = strlen (c1 -> c_text);
1657 if (write (pdi[1], c1 -> c_text, i) != i)
1658 adios ("pipe", "error writing to");
1659 free (c1 -> c_text), c1 -> c_text = NULL;
1660 (void) close (pdi[1]);
1662 (void) close (pdo[1]);
1665 while ((i = read (pdo[0], buffer, strlen (buffer))) > 0) {
1669 if ((dp = realloc (cp, (unsigned) (j = len + i))) == NULL)
1670 adios (NULLCP, "unable to allocate face storage");
1671 bcopy (buffer, dp + len, i);
1675 if ((cp = malloc ((unsigned) i)) == NULL)
1676 adios (NULLCP, "unable to allocate face storage");
1677 bcopy (buffer, cp, i);
1681 for (bp = buffer + i - 1; bp >= buffer; bp--)
1682 if (!isascii (*bp) || iscntrl (*bp)) {
1687 (void) close (pdo[0]);
1689 /* no waiting for child... */
1691 if (result == OK) { /* binary */
1692 if (write (1, cp, len) != len)
1693 adios ("writing", "error");
1697 if ((c1 -> c_text = cp) == NULL)
1704 #endif /* not BSD42 and not SOCKETS */
1711 int mhlsbr (argc, argv, action)
1716 TYPESIG (*istat) (), (*pstat) (), (*qstat) ();
1720 switch (setjmp (mhlenv)) {
1723 sleepsw = 0; /* XXX */
1724 bellflg = clearflg = forwflg = forwall = exitstat = 0;
1727 mhl_action = action;
1728 if ((istat = signal (SIGINT, SIG_IGN)) != SIG_DFL)
1729 (void) signal (SIGINT, istat);
1730 if ((qstat = signal (SIGQUIT, SIG_IGN)) != SIG_DFL)
1731 (void) signal (SIGQUIT, qstat);
1732 pstat = signal (SIGPIPE, pipeser);
1733 (void) mhl (argc, argv); /* fall */
1736 (void) signal (SIGINT, istat);
1737 (void) signal (SIGQUIT, qstat);
1738 (void) signal (SIGPIPE, SIG_IGN);/* XXX */
1741 (void) signal (SIGPIPE, pstat);
1743 if (holder.c_text) {
1744 free (holder.c_text);
1745 holder.c_text = NULL;
1747 free_queue (&msghd, &msgtl);
1748 for (c1 = fmthd; c1; c1 = c1 -> c_next)
1749 c1 -> c_flags &= ~HDROUTPUT;
1758 static void mhladios (what, fmt, a, b, c, d, e, f)
1768 advise (what, fmt, a, b, c, d, e, f);
1773 static void mhldone (status)
1778 longjmp (mhlenv, DONE);
1785 static int m_pid = NOTOK;
1786 static int sd = NOTOK;
1789 static m_popen (name)
1794 if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
1795 adios ("standard output", "unable to dup()");
1797 if (pipe (pd) == NOTOK)
1798 adios ("pipe", "unable to");
1800 switch (m_pid = vfork ()) {
1802 adios ("fork", "unable to");
1805 (void) signal (SIGINT, SIG_DFL);
1806 (void) signal (SIGQUIT, SIG_DFL);
1808 (void) close (pd[1]);
1809 if (pd[0] != fileno (stdin)) {
1810 (void) dup2 (pd[0], fileno (stdin));
1811 (void) close (pd[0]);
1813 execlp (name, r1bindex (name, '/'), NULLCP);
1814 fprintf (stderr, "unable to exec ");
1819 (void) close (pd[0]);
1820 if (pd[1] != fileno (stdout)) {
1821 (void) dup2 (pd[1], fileno (stdout));
1822 (void) close (pd[1]);
1833 (void) fflush (stdout);
1834 if (dup2 (sd, fileno (stdout)) == NOTOK)
1835 adios ("standard output", "unable to dup2()");
1842 (void) fclose (stdout);
1844 (void) pidwait (m_pid, OK);