]> diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/mhlsbr.c
sbr/mts.c: Delete mmdlm2; use same-valued mmdlm1 instead.
[nmh] / docs / historical / mh-6.8.5 / uip / mhlsbr.c
1 /* mhlsbr.c - implement the "nifty" message lister */
2 #ifndef lint
3 static char ident[] = "@(#)$Id: mhlsbr.c,v 1.30 1995/12/08 17:57:16 jromine Exp $";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../zotnet/tws.h"
10 #ifdef SVR4
11 #undef NULLVP /* XXX */
12 #endif
13 #if defined(SYS5) && defined(AUX)
14 #define u_short ushort
15 #define u_long ulong
16 #endif
17 #include <ctype.h>
18 #include <setjmp.h>
19 #include <signal.h>
20 #include <stdio.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23
24
25 /* MAJOR BUG:
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
31 oneline(), instead of
32
33 (*onelp == '\n' && !onelp[1])
34
35 being a terminating condition,
36
37 (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT)))
38
39 is used instead. This cuts the line prematurely, and gives us a much
40 better chance of getting things right.
41 */
42
43
44 #ifdef SYS5
45 #define u_short ushort
46 #endif /* SYS5 */
47
48 #define ONECOMP 0
49 #define TWOCOMP 1
50 #define BODYCOMP 2
51
52 #define adios mhladios
53 #define done mhldone
54
55 #define QUOTE '\\'
56
57 /* \f */
58
59 static struct swit mhlswitches[] = {
60 #define BELLSW 0
61 "bell", 0,
62 #define NBELLSW 1
63 "nobell", 0,
64
65 #define CLRSW 2
66 "clear", 0,
67 #define NCLRSW 3
68 "noclear", 0,
69
70 #define FACESW 4
71 "faceproc program", 0,
72 #define NFACESW 5
73 "nofaceproc", 0,
74
75 #define FOLDSW 6
76 "folder +folder", 0,
77 #define FORMSW 7
78 "form formfile", 0,
79
80 #define PROGSW 8
81 "moreproc program", 0,
82 #define NPROGSW 9
83 "nomoreproc", 0,
84
85 #define LENSW 10
86 "length lines", 0,
87 #define WIDSW 11
88 "width columns", 0,
89
90 #define SLEEPSW 12
91 "sleep seconds", 0,
92
93 #define DASHSW 13
94 "dashmunging", -4,
95 #define NDASHSW 14
96 "nodashmunging", -6,
97
98 #define HELPSW 15
99 "help", 4,
100
101 #define FORW1SW 16
102 "forward", -7, /* interface from forw */
103 #define FORW2SW 17
104 "forwall", -7, /* .. */
105 #define DGSTSW 18
106 "digest list", -6,
107 #define VOLUMSW 19
108 "volume number", -6,
109 #define ISSUESW 20
110 "issue number", -5,
111 #define NBODYSW 21
112 "nobody", -6,
113
114 NULL, 0
115 };
116
117 /* \f */
118
119 struct mcomp {
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 */
126
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 */
132
133 long c_flags;
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 \
154 | SPLIT)
155
156 struct mcomp *c_next;
157 };
158
159 static struct mcomp *msghd = NULL;
160 static struct mcomp *msgtl = NULL;
161 static struct mcomp *fmthd = NULL;
162 static struct mcomp *fmttl = NULL;
163
164 static struct mcomp global = {
165 NULL, NULL, "", NULL, NULL, 0, -1, 80, -1, 40, BELL, 0
166 };
167 static struct mcomp holder =
168 {
169 NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, NOCOMPONENT, 0
170 };
171
172
173 static struct pair {
174 char *p_name;
175 long p_flags;
176 } pairs[] = {
177 "Date", DATEFMT,
178 "From", ADDRFMT | FACEDFLT,
179 "Sender", ADDRFMT,
180 "Reply-To", ADDRFMT,
181 "To", ADDRFMT,
182 "cc", ADDRFMT,
183 "Bcc", ADDRFMT,
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,
191 "Face", FACEFMT,
192
193 NULL
194 };
195
196 static struct triple {
197 char *t_name;
198 long t_on;
199 long t_off;
200 } triples[] = {
201 "nocomponent", NOCOMPONENT, 0,
202 "uppercase", UPPERCASE, 0,
203 "nouppercase", 0, UPPERCASE,
204 "center", CENTER, 0,
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,
213 "split", SPLIT, 0,
214 "nosplit", 0, SPLIT,
215 "addrfield", ADDRFMT, DATEFMT,
216 "bell", BELL, 0,
217 "nobell", 0, BELL,
218 "datefield", DATEFMT, ADDRFMT,
219 "newline", 0, NONEWLINE,
220 "nonewline", NONEWLINE, 0,
221
222 NULL
223 };
224
225 /* \f */
226
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;
233
234 static int sleepsw = NOTOK;
235
236 static char *digest = NULL;
237 static int volume = 0;
238 static int issue = 0;
239
240 static int exitstat = 0;
241 static int mhldebug = 0;
242
243 #define PITTY (-1)
244 #define NOTTY 0
245 #define ISTTY 1
246 static int ontty = NOTTY;
247
248 static int row;
249 static int column;
250
251 static int lm;
252 static int llim;
253 static int ovoff;
254 static int term;
255 static int wid;
256
257
258 static char *ovtxt;
259
260 static char *onelp;
261
262
263 static char *parptr;
264 static char *ignores[MAXARGS];
265
266
267 static jmp_buf env;
268 static jmp_buf mhlenv;
269
270
271 static char delim3[] = /* from forw.c */
272 "\n----------------------------------------------------------------------\n\n";
273 static char delim4[] = "\n------------------------------\n\n";
274
275
276 static FP (*mhl_action) () = (FP (*) ()) 0;
277
278
279 static void mhladios (), mhldone ();
280 static TYPESIG intrser (), pipeser (), quitser ();
281 static char *mcomp_add (), *oneline (), *parse ();
282 static struct mcomp *add_queue ();
283
284 static mhl_format(), evalvar(), process(), mhlfile(), free_queue(), putcomp();
285 static putstr(), putch(), face_format(), m_popen();
286 static int ptoi(), ptos(), doface();
287
288 void clear_screen ();
289
290 /* \f */
291
292 /* ARGSUSED */
293
294 int mhl (argc, argv)
295 int argc;
296 char *argv[];
297 {
298 int length = 0,
299 nomore = 0,
300 width = 0,
301 vecp = 0,
302 i;
303 register char *cp,
304 *folder = NULL,
305 *form = NULL,
306 **ap,
307 **argp;
308 char buf[80],
309 *arguments[MAXARGS],
310 *files[MAXARGS];
311
312 invo_name = r1bindex (argv[0], '/');
313 if ((cp = getenv ("MHLDEBUG")) && *cp)
314 mhldebug++;
315 if ((cp = m_find (invo_name)) != NULL) {
316 ap = brkstring (getcpy (cp), " ", "\n");
317 ap = copyip (ap, arguments);
318 }
319 else
320 ap = arguments;
321 (void) copyip (argv + 1, ap);
322 argp = arguments;
323
324 /* \f */
325
326 if (cp = getenv ("FACEPROC"))
327 faceproc = cp;
328
329 vecp = 0;
330 while (cp = *argp++) {
331 if (*cp == '-')
332 switch (smatch (++cp, mhlswitches)) {
333 case AMBIGSW:
334 ambigsw (cp, mhlswitches);
335 done (1);
336 case UNKWNSW:
337 adios (NULLCP, "-%s unknown\n", cp);
338 case HELPSW:
339 (void) sprintf (buf, "%s [switches] [files ...]",
340 invo_name);
341 help (buf, mhlswitches);
342 done (1);
343
344 case BELLSW:
345 bellflg = 1;
346 continue;
347 case NBELLSW:
348 bellflg = -1;
349 continue;
350
351 case CLRSW:
352 clearflg = 1;
353 continue;
354 case NCLRSW:
355 clearflg = -1;
356 continue;
357
358 case FOLDSW:
359 if (!(folder = *argp++) || *folder == '-')
360 adios (NULLCP, "missing argument to %s", argp[-2]);
361 continue;
362 case FORMSW:
363 if (!(form = *argp++) || *form == '-')
364 adios (NULLCP, "missing argument to %s", argp[-2]);
365 continue;
366
367 case FACESW:
368 if (!(faceproc = *argp++) || *faceproc == '-')
369 adios (NULLCP, "missing argument to %s", argp[-2]);
370 continue;
371 case NFACESW:
372 faceproc = NULL;
373 continue;
374 case SLEEPSW:
375 if (!(cp = *argp++) || *cp == '-')
376 adios (NULLCP, "missing argument to %s", argp[-2]);
377 sleepsw = atoi (cp);/* ZERO ok! */
378 continue;
379
380 case PROGSW:
381 if (!(moreproc = *argp++) || *moreproc == '-')
382 adios (NULLCP, "missing argument to %s", argp[-2]);
383 continue;
384 case NPROGSW:
385 nomore++;
386 continue;
387
388 case LENSW:
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);
393 continue;
394 case WIDSW:
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);
399 continue;
400
401 case DGSTSW:
402 if (!(digest = *argp++) || *digest == '-')
403 adios (NULLCP, "missing argument to %s", argp[-2]);
404 continue;
405 case ISSUESW:
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);
410 continue;
411 case VOLUMSW:
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);
416 continue;
417
418 case FORW2SW:
419 forwall++; /* fall */
420 case FORW1SW:
421 forwflg++;
422 clearflg = -1;/* XXX */
423 continue;
424
425 case DASHSW:
426 dashflg++;
427 continue;
428 case NDASHSW:
429 dashflg = 0;
430 continue;
431
432 case NBODYSW:
433 dobody = 0;
434 continue;
435 }
436 files[vecp++] = cp;
437 }
438
439 /* \f */
440
441 if (!folder)
442 folder = getenv ("mhfolder");
443
444 if (isatty (fileno (stdout)))
445 if (!nomore && !sc_hardcopy () && moreproc && *moreproc) {
446 if (mhl_action) {
447 setsig (SIGINT, SIG_IGN);
448 setsig (SIGQUIT, quitser);
449 }
450 m_popen (moreproc);
451 ontty = PITTY;
452 }
453 else {
454 setsig (SIGINT, SIG_IGN);
455 setsig (SIGQUIT, quitser);
456 ontty = ISTTY;
457 }
458 else
459 ontty = NOTTY;
460
461 mhl_format (form ? form : mhlformat, length, width);
462
463 if (vecp == 0)
464 process (folder, NULLCP, 1, vecp = 1);
465 else
466 for (i = 0; i < vecp; i++)
467 process (folder, files[i], i + 1, vecp);
468
469 if (forwall) {
470 if (digest) {
471 printf ("%s", delim4);
472 if (volume == 0) {
473 (void) sprintf (buf, "End of %s Digest\n", digest);
474 }
475 else
476 (void) sprintf (buf, "End of %s Digest [Volume %d Issue %d]\n", digest, volume, issue);
477 i = strlen (buf);
478 for (cp = buf + i; i > 1; i--)
479 *cp++ = '*';
480 *cp++ = '\n';
481 *cp = 0;
482 printf ("%s", buf);
483 }
484 else
485 printf ("\n------- End of Forwarded Message%s\n\n",
486 vecp > 1 ? "s" : "");
487 }
488
489 if (clearflg > 0 && ontty == NOTTY)
490 clear_screen ();
491
492 if (ontty == PITTY)
493 m_pclose ();
494
495 return exitstat;
496 }
497
498 /* \f */
499
500 static mhl_format (file, length, width)
501 register char *file;
502 int length,
503 width;
504 {
505 int i;
506 register char *bp,
507 *cp,
508 **ip;
509 char *ap,
510 buffer[BUFSIZ],
511 name[NAMESZ];
512 register struct mcomp *c1;
513 struct stat st;
514 register FILE *fp;
515 static dev_t dev = 0;
516 static ino_t ino = 0;
517 static time_t mtime = 0;
518
519 if (fmthd != NULL)
520 if (stat (libpath (file), &st) != NOTOK
521 && mtime == st.st_mtime
522 && dev == st.st_dev
523 && ino == st.st_ino)
524 goto out;
525 else
526 free_queue (&fmthd, &fmttl);
527
528 if ((fp = fopen (libpath (file), "r")) == NULL)
529 adios (file, "unable to open format file");
530
531 if (fstat (fileno (fp), &st) != NOTOK)
532 mtime = st.st_mtime, dev = st.st_dev, ino = st.st_ino;
533
534 global.c_ovtxt = global.c_nfs = NULL;
535 global.c_fmt = NULL;
536 global.c_offset = 0;
537 global.c_ovoff = -1;
538 if ((i = sc_width ()) > 5)
539 global.c_width = i;
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;
545
546 while (vfgets (fp, &ap) == OK) {
547 bp = ap;
548 if (*bp == ';')
549 continue;
550
551 if (cp = index (bp, '\n'))
552 *cp = 0;
553
554 if (*bp == ':') {
555 c1 = add_queue (&fmthd, &fmttl, NULLCP, bp + 1, CLEARTEXT);
556 continue;
557 }
558
559 parptr = bp;
560 (void) strcpy (name, parse ());
561 switch (*parptr) {
562 case '\0':
563 case ',':
564 case '=':
565 if (uleq (name, "ignores")) {
566 ip = copyip (brkstring (getcpy (++parptr), ",", NULLCP), ip);
567 continue;
568 }
569 parptr = bp;
570 while (*parptr) {
571 if (evalvar (&global))
572 adios (NULLCP, "format file syntax error: %s", bp);
573 if (*parptr)
574 parptr++;
575 }
576 continue;
577
578 case ':':
579 c1 = add_queue (&fmthd, &fmttl, name, NULLCP, INIT);
580 while (*parptr == ':' || *parptr == ',') {
581 parptr++;
582 if (evalvar (c1))
583 adios (NULLCP, "format file syntax error: %s", bp);
584 }
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);
589 }
590 else
591 if (c1 -> c_flags & ADDRFMT) {
592 if (global.c_flags & ADDRFMT)
593 c1 -> c_nfs = getcpy (global.c_nfs);
594 }
595 continue;
596
597 default:
598 adios (NULLCP, "format file syntax error: %s", bp);
599 }
600 }
601 (void) fclose (fp);
602
603 if (mhldebug)
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));
614 }
615
616 out: ;
617 if (clearflg == 1)
618 global.c_flags |= CLEARSCR;
619 else
620 if (clearflg == -1)
621 global.c_flags &= ~CLEARSCR;
622
623 switch (bellflg) { /* command line may override format file */
624 case 1:
625 global.c_flags |= BELL;
626 break;
627 case -1:
628 global.c_flags &= ~BELL;
629 break;
630 }
631
632 if (length)
633 global.c_length = length;
634 if (width)
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;
640 }
641
642 /* \f */
643
644 static evalvar (c1)
645 register struct mcomp *c1;
646 {
647 char *cp,
648 name[NAMESZ];
649 register struct triple *ap;
650
651 if (!*parptr)
652 return 0;
653 (void) strcpy (name, parse ());
654
655 if (uleq (name, "component")) {
656 if (ptos (name, &c1 -> c_text))
657 return 1;
658 c1 -> c_flags &= ~NOCOMPONENT;
659 return 0;
660 }
661 if (uleq (name, "overflowtext"))
662 return ptos (name, &c1 -> c_ovtxt);
663 if (uleq (name, "formatfield")) {
664 if (ptos (name, &cp))
665 return 1;
666 c1 -> c_nfs = getcpy (new_fs (NULLCP, NULLCP, cp));
667 c1 -> c_flags |= FORMAT;
668 return 0;
669 }
670
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);
683
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;
688 return 0;
689 }
690
691 return 1;
692 }
693
694 /* \f */
695
696 static int ptoi (name, i)
697 register char *name;
698 register int *i;
699 {
700 char *cp;
701
702 if (*parptr++ != '=' || !*(cp = parse ())) {
703 advise (NULLCP, "missing argument to variable %s", name);
704 return 1;
705 }
706
707 *i = atoi (cp);
708 return 0;
709 }
710
711
712 static int ptos (name, s)
713 register char *name,
714 **s;
715 {
716 char c,
717 *cp;
718
719 if (*parptr++ != '=') {
720 advise (NULLCP, "missing argument to variable %s", name);
721 return 1;
722 }
723
724 if (*parptr != '"')
725 for (cp = parptr;
726 *parptr && *parptr != ':' && *parptr != ',';
727 parptr++)
728 continue;
729 else
730 for (cp = ++parptr; *parptr && *parptr != '"'; parptr++)
731 if (*parptr == QUOTE)
732 if (!*++parptr)
733 parptr--;
734 c = *parptr;
735 *parptr = 0;
736 *s = getcpy (cp);
737 if ((*parptr = c) == '"')
738 parptr++;
739 return 0;
740 }
741
742 /* \f */
743
744 static char *parse () {
745 int c;
746 register char *cp;
747 static char result[NAMESZ];
748
749 for (cp = result; c = *parptr; parptr++)
750 if (isalnum (c)
751 || c == '.'
752 || c == '-'
753 || c == '_'
754 || c =='['
755 || c == ']')
756 *cp++ = c;
757 else
758 break;
759 *cp = 0;
760
761 return result;
762 }
763
764 /* \f */
765
766 static process (folder, fname, ofilen, ofilec)
767 char *folder,
768 *fname;
769 int ofilen,
770 ofilec;
771 {
772 char *cp;
773 FILE *fp;
774 struct mcomp *c1;
775
776 switch (setjmp (env)) {
777 case OK:
778 if (fname) {
779 fp = mhl_action ? (*mhl_action) (fname) : fopen (fname, "r");
780 if (fp == NULL) {
781 advise (fname, "unable to open");
782 exitstat++;
783 return;
784 }
785 }
786 else {
787 fname = "(stdin)";
788 fp = stdin;
789 }
790 cp = folder ? concat (folder, ":", fname, NULLCP) : getcpy (fname);
791 if (ontty != PITTY)
792 (void) signal (SIGINT, intrser);
793 mhlfile (fp, cp, ofilen, ofilec);/* fall */
794
795 default:
796 if (ontty != PITTY)
797 (void) signal (SIGINT, SIG_IGN);
798 if (mhl_action == NULL && fp != stdin)
799 (void) fclose (fp);
800 free (cp);
801 if (holder.c_text) {
802 free (holder.c_text);
803 holder.c_text = NULL;
804 }
805 free_queue (&msghd, &msgtl);
806 for (c1 = fmthd; c1; c1 = c1 -> c_next)
807 c1 -> c_flags &= ~HDROUTPUT;
808 break;
809 }
810 }
811
812 /* \f */
813
814 static mhlfile (fp, mname, ofilen, ofilec)
815 register FILE *fp;
816 register char *mname;
817 int ofilen,
818 ofilec;
819 {
820 int state;
821 register struct mcomp *c1,
822 *c2,
823 *c3;
824 register char **ip;
825 char name[NAMESZ],
826 buf[BUFSIZ];
827
828 if (forwall) {
829 if (digest)
830 printf ("%s", ofilen == 1 ? delim3 : delim4);
831 else {
832 printf ("\n-------");
833 if (ofilen == 1)
834 printf (" Forwarded Message%s", ofilec > 1 ? "s" : "");
835 else
836 printf (" Message %d", ofilen);
837 printf ("\n\n");
838 }
839 }
840 else
841 switch (ontty) {
842 case PITTY:
843 if (ofilec > 1) {
844 if (ofilen > 1) {
845 if ((global.c_flags & CLEARSCR))
846 clear_screen ();
847 else
848 printf ("\n\n\n");
849 }
850 printf (">>> %s\n\n", mname);
851 }
852 break;
853
854 case ISTTY:
855 (void) strcpy (buf, "\n");
856 if (ofilec > 1) {
857 if (SOprintf ("Press <return> to list \"%s\"...", mname)) {
858 if (ofilen > 1)
859 printf ("\n\n\n");
860 printf ("Press <return> to list \"%s\"...", mname);
861 }
862 (void) fflush (stdout);
863 buf[0] = 0;
864 (void) read (fileno (stdout), buf, sizeof buf);
865 }
866 if (index (buf, '\n')) {
867 if ((global.c_flags & CLEARSCR))
868 clear_screen ();
869 }
870 else
871 printf ("\n");
872 break;
873
874 default:
875 if (ofilec > 1) {
876 if (ofilen > 1) {
877 printf ("\n\n\n");
878 if (clearflg > 0)
879 clear_screen ();
880 }
881 printf (">>> %s\n\n", mname);
882 }
883 break;
884 }
885
886 /* \f */
887
888 for (state = FLD;;)
889 switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
890 case FLD:
891 case FLDPLUS:
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);
896 break;
897 }
898 if (*ip)
899 continue;
900
901 for (c2 = fmthd; c2; c2 = c2 -> c_next)
902 if (uleq (c2 -> c_name, name))
903 break;
904 c1 = NULL;
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)) {
908 c1 -> c_text =
909 mcomp_add (c1 -> c_flags, buf, c1 -> c_text);
910 break;
911 }
912 if (c1 == NULL)
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);
917 }
918 if (c2 == NULL)
919 c1 -> c_flags |= EXTRA;
920 continue;
921
922 case BODY:
923 case FILEEOF:
924 row = column = 0;
925 for (c1 = fmthd; c1; c1 = c1 -> c_next) {
926 if (c1 -> c_flags & CLEARTEXT) {
927 putcomp (c1, c1, ONECOMP);
928 continue;
929 }
930 if (uleq (c1 -> c_name, "messagename")) {
931 holder.c_text = concat ("(Message ", mname, ")\n",
932 NULLCP);
933 putcomp (c1, &holder, ONECOMP);
934 free (holder.c_text);
935 holder.c_text = NULL;
936 continue;
937 }
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);
942 continue;
943 }
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,
951 sizeof buf, fp);
952 }
953 free (holder.c_text);
954 holder.c_text = NULL;
955 continue;
956 }
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))
961 break;
962 }
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)
967 face_format (c2);
968 if (holder.c_text = c2 -> c_face) {
969 putcomp (c1, &holder, ONECOMP);
970 holder.c_text = NULL;
971 }
972 break;
973 }
974 }
975 return;
976
977 case LENERR:
978 case FMTERR:
979 advise (NULLCP, "format error in message %s", mname);
980 exitstat++;
981 return;
982
983 default:
984 adios (NULLCP, "getfld() returned %d", state);
985 }
986 }
987
988 /* \f */
989
990 static int mcomp_flags (name)
991 register char *name;
992 {
993 register struct pair *ap;
994
995 for (ap = pairs; ap -> p_name; ap++)
996 if (uleq (ap -> p_name, name))
997 return (ap -> p_flags);
998
999 return 0;
1000 }
1001
1002
1003 static char *mcomp_add (flags, s1, s2)
1004 long flags;
1005 register char *s1,
1006 *s2;
1007 {
1008 register char *dp;
1009
1010 if (!(flags & ADDRFMT))
1011 return add (s1, s2);
1012
1013 if (s2 && *(dp = s2 + strlen (s2) - 1) == '\n')
1014 *dp = 0;
1015
1016 return add (s1, add (",\n", s2));
1017 }
1018
1019 /* \f */
1020
1021 struct pqpair {
1022 char *pq_text;
1023 char *pq_error;
1024 struct pqpair *pq_next;
1025 };
1026
1027
1028 static mcomp_format (c1, c2)
1029 register struct mcomp *c1,
1030 *c2;
1031 {
1032 int dat[5];
1033 register char *ap,
1034 *cp;
1035 char buffer[BUFSIZ],
1036 error[BUFSIZ];
1037 register struct comp *cptr;
1038 register struct pqpair *p,
1039 *q;
1040 struct pqpair pq;
1041 register struct mailname *mp;
1042
1043 ap = c2 -> c_text;
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);
1048
1049 if (!(c1 -> c_flags & ADDRFMT)) {
1050 FINDCOMP (cptr, "text");
1051 if (cptr)
1052 cptr -> c_text = ap;
1053 if (cp = rindex(ap, '\n')) /* drop ending newline */
1054 if (!cp[1])
1055 *cp = 0;
1056
1057 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1058 c2 -> c_text = getcpy (buffer);
1059 #ifndef JLR
1060 /* Don't need to append a newline, dctime() already did */
1061 #else
1062 if (!(c1 -> c_flags & NONEWLINE))
1063 c2 -> c_text = add ("\n", c2 -> c_text);
1064 #endif
1065
1066 free (ap);
1067 return;
1068 }
1069
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");
1074
1075 if ((mp = getm (cp, NULLCP, 0, AD_NAME, error)) == NULL) {
1076 p -> pq_text = getcpy (cp);
1077 p -> pq_error = getcpy (error);
1078 }
1079 else {
1080 if ((c1 -> c_flags & FACEDFLT) && c2 -> c_face == NULL) {
1081 char *h, *o;
1082 if ((h = mp -> m_host) == NULL)
1083 h = LocalName ();
1084 if (o = OfficialName (h))
1085 h = o;
1086 c2 -> c_face = concat ("address ", h, " ", mp -> m_mbox,
1087 NULLCP);
1088 }
1089 p -> pq_text = getcpy (mp -> m_text);
1090 mnfree (mp);
1091 }
1092 q = (q -> pq_next = p);
1093 }
1094
1095 for (p = pq.pq_next; p; p = q) {
1096 FINDCOMP (cptr, "text");
1097 if (cptr)
1098 cptr -> c_text = p -> pq_text;
1099 FINDCOMP (cptr, "error");
1100 if (cptr)
1101 cptr -> c_text = p -> pq_error;
1102
1103 (void) fmtscan (c1 -> c_fmt, buffer, sizeof buffer - 1, dat);
1104 if (*buffer) {
1105 if (c2 -> c_text)
1106 c2 -> c_text = add (",\n", c2 -> c_text);
1107 if (*(cp = buffer + strlen (buffer) - 1) == '\n')
1108 *cp = 0;
1109 c2 -> c_text = add (buffer, c2 -> c_text);
1110 }
1111
1112 free (p -> pq_text);
1113 if (p -> pq_error)
1114 free (p -> pq_error);
1115 q = p -> pq_next;
1116 free ((char *) p);
1117 }
1118
1119 c2 -> c_text = add ("\n", c2 -> c_text);
1120 free (ap);
1121 }
1122
1123 /* \f */
1124
1125 static struct mcomp *add_queue (head, tail, name, text, flags)
1126 register struct mcomp **head,
1127 **tail;
1128 register char *name,
1129 *text;
1130 int flags;
1131 {
1132 register struct mcomp *c1;
1133
1134 if ((c1 = (struct mcomp *) calloc ((unsigned) 1, sizeof *c1)) == NULL)
1135 adios (NULLCP, "unable to allocate comp memory");
1136
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;
1141 if (flags & INIT) {
1142 if (global.c_ovtxt)
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;
1149 }
1150 if (*head == NULL)
1151 *head = c1;
1152 if (*tail != NULL)
1153 (*tail) -> c_next = c1;
1154 *tail = c1;
1155
1156 return c1;
1157 }
1158
1159
1160 static free_queue (head, tail)
1161 register struct mcomp **head,
1162 **tail;
1163 {
1164 register struct mcomp *c1,
1165 *c2;
1166
1167 for (c1 = *head; c1; c1 = c2) {
1168 c2 = c1 -> c_next;
1169 if (c1 -> c_name)
1170 free (c1 -> c_name);
1171 if (c1 -> c_text)
1172 free (c1 -> c_text);
1173 if (c1 -> c_ovtxt)
1174 free (c1 -> c_ovtxt);
1175 if (c1 -> c_nfs)
1176 free (c1 -> c_nfs);
1177 if (c1 -> c_fmt)
1178 free ((char *) c1 -> c_fmt);
1179 if (c1 -> c_face)
1180 free (c1 -> c_face);
1181 free ((char *) c1);
1182 }
1183
1184 *head = *tail = NULL;
1185 }
1186
1187 /* \f */
1188
1189 static putcomp (c1, c2, flag)
1190 register struct mcomp *c1,
1191 *c2;
1192 int flag;
1193 {
1194 int count,
1195 cchdr;
1196 register char *cp;
1197
1198 cchdr = 0;
1199 lm = 0;
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)
1203 + c1 -> c_offset;
1204 if ((ovtxt = c1 -> c_ovtxt ? c1 -> c_ovtxt : global.c_ovtxt) == NULL)
1205 ovtxt = "";
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);
1209 onelp = NULL;
1210
1211 if (c1 -> c_flags & CLEARTEXT) {
1212 putstr (c1 -> c_text);
1213 putstr ("\n");
1214 return;
1215 }
1216
1217 if (c1 -> c_flags & FACEFMT)
1218 switch (doface (c2)) {
1219 case NOTOK: /* error */
1220 case OK: /* async faceproc */
1221 return;
1222
1223 default: /* sync faceproc */
1224 break;
1225 }
1226
1227 if (c1 -> c_nfs && (c1 -> c_flags & (ADDRFMT | DATEFMT | FORMAT)))
1228 mcomp_format (c1, c2);
1229
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);
1236 }
1237 else
1238 if (c1 -> c_offset)
1239 lm = c1 -> c_offset;
1240
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++)
1244 if (islower (*cp))
1245 *cp = toupper (*cp);
1246 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1247 if (flag != BODYCOMP) {
1248 putstr (": ");
1249 if (!(c1 -> c_flags & SPLIT))
1250 c1 -> c_flags |= HDROUTPUT;
1251
1252 cchdr++;
1253 if ((count = c1 -> c_cwidth -
1254 strlen (c1 -> c_text ? c1 -> c_text : c1 -> c_name) - 2) > 0)
1255 while (count--)
1256 putstr (" ");
1257 }
1258 else
1259 c1 -> c_flags |= HDROUTPUT; /* for BODYCOMP */
1260 }
1261
1262 if (flag == TWOCOMP
1263 && !(c2 -> c_flags & HDROUTPUT)
1264 && !(c2 -> c_flags & NOCOMPONENT)) {
1265 if (c1 -> c_flags & UPPERCASE)
1266 for (cp = c2 -> c_name; *cp; cp++)
1267 if (islower (*cp))
1268 *cp = toupper (*cp);
1269 putstr (c2 -> c_name);
1270 putstr (": ");
1271 if (!(c1 -> c_flags & SPLIT))
1272 c2 -> c_flags |= HDROUTPUT;
1273
1274 cchdr++;
1275 if ((count = c1 -> c_cwidth - strlen (c2 -> c_name) - 2) > 0)
1276 while (count--)
1277 putstr (" ");
1278 }
1279 if (c1 -> c_flags & UPPERCASE)
1280 for (cp = c2 -> c_text; *cp; cp++)
1281 if (islower (*cp))
1282 *cp = toupper (*cp);
1283
1284 count = 0;
1285 if (cchdr)
1286 if (flag == TWOCOMP)
1287 count = (c1 -> c_cwidth >= 0) ? c1 -> c_cwidth
1288 : strlen (c2 -> c_name) + 2;
1289 else
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;
1293
1294 if (cp = oneline (c2 -> c_text, c1 -> c_flags))
1295 putstr(cp);
1296 if (term == '\n')
1297 putstr ("\n");
1298 while (cp = oneline (c2 -> c_text, c1 -> c_flags)) {
1299 lm = count;
1300 if (flag == BODYCOMP
1301 && !(c1 -> c_flags & NOCOMPONENT))
1302 putstr (c1 -> c_text ? c1 -> c_text : c1 -> c_name);
1303 if (*cp)
1304 putstr (cp);
1305 if (term == '\n')
1306 putstr ("\n");
1307 }
1308 }
1309
1310 /* \f */
1311
1312 static char *oneline (stuff, flags)
1313 register char *stuff;
1314 long flags;
1315 {
1316 int spc;
1317 register char *cp,
1318 *ret;
1319
1320 if (onelp == NULL)
1321 onelp = stuff;
1322 if (*onelp == 0)
1323 return (onelp = NULL);
1324
1325 ret = onelp;
1326 term = 0;
1327 if (flags & COMPRESS) {
1328 for (spc = 1, cp = ret; *onelp; onelp++)
1329 if (isspace (*onelp)) {
1330 if (*onelp == '\n' && (!onelp[1] || (flags & ADDRFMT))) {
1331 term = '\n';
1332 *onelp++ = 0;
1333 break;
1334 }
1335 else
1336 if (!spc) {
1337 *cp++ = ' ';
1338 spc++;
1339 }
1340 }
1341 else {
1342 *cp++ = *onelp;
1343 spc = 0;
1344 }
1345
1346 *cp = 0;
1347 }
1348 else {
1349 while (*onelp && *onelp != '\n')
1350 onelp++;
1351 if (*onelp == '\n') {
1352 term = '\n';
1353 *onelp++ = 0;
1354 }
1355 if (flags & LEFTADJUST)
1356 while (*ret == ' ' || *ret == '\t')
1357 ret++;
1358 }
1359 if (*onelp == 0 && term == '\n' && (flags & NONEWLINE))
1360 term = 0;
1361
1362 return ret;
1363 }
1364
1365 /* \f */
1366
1367 static putstr (string)
1368 register char *string;
1369 {
1370 if (!column && lm > 0)
1371 while (lm > 0)
1372 if (lm >= 8) {
1373 putch ('\t');
1374 lm -= 8;
1375 }
1376 else {
1377 putch (' ');
1378 lm--;
1379 }
1380 lm = 0;
1381 while (*string)
1382 putch (*string++);
1383 }
1384
1385 /* \f */
1386
1387 static putch (ch)
1388 register char ch;
1389 {
1390 char buf[BUFSIZ];
1391
1392 if (llim == 0)
1393 return;
1394
1395 switch (ch) {
1396 case '\n':
1397 if (llim > 0)
1398 llim--;
1399 column = 0;
1400 row++;
1401 if (ontty != ISTTY || row != global.c_length)
1402 break;
1403 if (global.c_flags & BELL)
1404 (void) putchar ('\007');
1405 (void) fflush (stdout);
1406 buf[0] = 0;
1407 (void) read (fileno (stdout), buf, sizeof buf);
1408 if (index (buf, '\n')) {
1409 if (global.c_flags & CLEARSCR)
1410 clear_screen ();
1411 row = 0;
1412 }
1413 else {
1414 (void) putchar ('\n');
1415 row = global.c_length / 3;
1416 }
1417 return;
1418
1419 case '\t':
1420 column |= 07;
1421 column++;
1422 break;
1423
1424 case '\b':
1425 column--;
1426 break;
1427
1428 case '\r':
1429 column = 0;
1430 break;
1431
1432 default:
1433 if (column == 0 && forwflg && dashflg && ch == '-')
1434 (void) putchar ('-'), putchar (' ');
1435 if (ch >= ' ')
1436 column++;
1437 break;
1438 }
1439
1440 if (column >= wid) {
1441 putch ('\n');
1442 if (ovoff > 0)
1443 lm = ovoff;
1444 putstr (ovtxt ? ovtxt : "");
1445 putch (ch);
1446 return;
1447 }
1448
1449 (void) putchar (ch);
1450 }
1451
1452 /* \f */
1453
1454 /* ARGSUSED */
1455
1456 static TYPESIG intrser (i)
1457 int i;
1458 {
1459 #ifndef BSD42
1460 (void) signal (SIGINT, intrser);
1461 #endif /* BSD42 */
1462
1463 discard (stdout);
1464 (void) putchar ('\n');
1465
1466 longjmp (env, DONE);
1467 }
1468
1469
1470 /* ARGSUSED */
1471
1472 static TYPESIG pipeser (i)
1473 int i;
1474 {
1475 #ifndef BSD42
1476 (void) signal (SIGPIPE, pipeser);
1477 #endif /* BSD42 */
1478
1479 done (NOTOK);
1480 }
1481
1482
1483 /* ARGSUSED */
1484
1485 static TYPESIG quitser (i)
1486 int i;
1487 {
1488 #ifndef BSD42
1489 (void) signal (SIGQUIT, quitser);
1490 #endif /* BSD42 */
1491
1492 (void) putchar ('\n');
1493 (void) fflush (stdout);
1494
1495 done (NOTOK);
1496 }
1497
1498 /* \f */
1499
1500 static face_format (c1)
1501 register struct mcomp *c1;
1502 {
1503 register char *cp;
1504 register struct mailname *mp;
1505
1506 if ((cp = c1 -> c_text) == NULL)
1507 return;
1508
1509 if (cp = getname (cp)) {
1510 if (mp = getm (cp, NULLCP, 0, AD_NAME, NULLCP)) {
1511 char *h, *o;
1512 if ((h = mp -> m_host) == NULL)
1513 h = LocalName ();
1514 if (o = OfficialName (h))
1515 h = o;
1516 c1 -> c_face = concat ("address ", h, " ", mp -> m_mbox, NULLCP);
1517 }
1518
1519 while (cp = getname (cp))
1520 continue;
1521 }
1522 }
1523
1524 /* \f */
1525
1526 #if defined(BSD42) || defined(SOCKETS)
1527
1528 /* faceproc is two elements defining the image agent's location:
1529 Internet host
1530 UDP port
1531 */
1532
1533 #include <sys/socket.h>
1534 #include <netinet/in.h>
1535 #include <netdb.h>
1536 #ifndef hpux
1537 #include <arpa/inet.h>
1538 #endif
1539
1540 struct hostent *gethostbystring ();
1541
1542
1543 static int doface (c1)
1544 register struct mcomp *c1;
1545 {
1546 int i,
1547 result,
1548 sd;
1549 struct sockaddr_in in_socket;
1550 register struct sockaddr_in *isock = &in_socket;
1551 static int inited = OK;
1552 static int addrlen;
1553 static struct in_addr addr;
1554 static u_short portno;
1555
1556 if (inited == OK) {
1557 u_long iaddr;
1558 char *cp;
1559 char **ap = brkstring (cp = getcpy (faceproc), " ", "\n");
1560 struct hostent *hp;
1561
1562 if (ap[0] == NULL || ap[1] == NULL) {
1563 bad_faceproc: ;
1564 free (cp);
1565 return (inited = NOTOK);
1566 }
1567
1568 if (!(hp = gethostbystring (ap[0])))
1569 goto bad_faceproc;
1570 bcopy (hp -> h_addr, (char *) &addr, addrlen = hp -> h_length);
1571
1572 portno = htons ((u_short) atoi (ap[1]));
1573 free (cp);
1574
1575 inited = DONE;
1576 }
1577 if (inited == NOTOK)
1578 return NOTOK;
1579
1580 isock -> sin_family = AF_INET;
1581 isock -> sin_port = portno;
1582 bcopy ((char *) &addr, (char *) &isock -> sin_addr, addrlen);
1583
1584 if ((sd = socket (AF_INET, SOCK_DGRAM, 0)) == NOTOK)
1585 return NOTOK;
1586
1587 result = sendto (sd, c1 -> c_text, strlen (c1 -> c_text), 0,
1588 (struct sockaddr *) isock, sizeof *isock);
1589
1590 (void) close (sd);
1591
1592 return (result != NOTOK ? OK : NOTOK);
1593 }
1594
1595 #else /* not BSD42 and not SOCKETS */
1596
1597 static int doface (c1)
1598 register struct mcomp *c1;
1599 {
1600 register int i,
1601 len,
1602 vecp;
1603 int child_id,
1604 result,
1605 pdi[2],
1606 pdo[2];
1607 register char *bp,
1608 *cp;
1609 char buffer[BUFSIZ],
1610 *vec[10];
1611
1612 if (pipe (pdi) == NOTOK)
1613 return NOTOK;
1614 if (pipe (pdo) == NOTOK) {
1615 (void) close (pdi[0]);
1616 (void) close (pdi[1]);
1617 return NOTOK;
1618 }
1619
1620 for (i = 0; (child_id = vfork ()) == NOTOK && i < 5; i++)
1621 sleep (5);
1622
1623 switch (child_id) {
1624 case NOTOK:
1625 return NOTOK;
1626
1627 case OK:
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]);
1633 }
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]);
1639 }
1640 vecp = 0;
1641 vec[vecp++] = r1bindex (faceproc, '/');
1642 vec[vecp++] = "-e";
1643 if (sleepsw != NOTOK) {
1644 vec[vecp++] = "-s";
1645 (void) sprintf (buffer, "%d", sleepsw);
1646 vec[vecp++] = buffer;
1647 }
1648 vec[vecp] = NULL;
1649 execvp (faceproc, vec);
1650 fprintf (stderr, "unable to exec ");
1651 perror (faceproc);
1652 _exit (-1); /* NOTREACHED */
1653
1654 default:
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]);
1661
1662 (void) close (pdo[1]);
1663 cp = NULL, len = 0;
1664 result = DONE;
1665 while ((i = read (pdo[0], buffer, strlen (buffer))) > 0) {
1666 if (cp) {
1667 register int j;
1668 register char *dp;
1669 if ((dp = realloc (cp, (unsigned) (j = len + i))) == NULL)
1670 adios (NULLCP, "unable to allocate face storage");
1671 bcopy (buffer, dp + len, i);
1672 cp = dp, len = j;
1673 }
1674 else {
1675 if ((cp = malloc ((unsigned) i)) == NULL)
1676 adios (NULLCP, "unable to allocate face storage");
1677 bcopy (buffer, cp, i);
1678 len = i;
1679 }
1680 if (result == DONE)
1681 for (bp = buffer + i - 1; bp >= buffer; bp--)
1682 if (!isascii (*bp) || iscntrl (*bp)) {
1683 result = OK;
1684 break;
1685 }
1686 }
1687 (void) close (pdo[0]);
1688
1689 /* no waiting for child... */
1690
1691 if (result == OK) { /* binary */
1692 if (write (1, cp, len) != len)
1693 adios ("writing", "error");
1694 free (cp);
1695 }
1696 else /* empty */
1697 if ((c1 -> c_text = cp) == NULL)
1698 result = OK;
1699 break;
1700 }
1701
1702 return result;
1703 }
1704 #endif /* not BSD42 and not SOCKETS */
1705
1706 /* \f */
1707
1708 #undef adios
1709 #undef done
1710
1711 int mhlsbr (argc, argv, action)
1712 int argc;
1713 char **argv;
1714 FP (*action) ();
1715 {
1716 TYPESIG (*istat) (), (*pstat) (), (*qstat) ();
1717 char *cp;
1718 struct mcomp *c1;
1719
1720 switch (setjmp (mhlenv)) {
1721 case OK:
1722 cp = invo_name;
1723 sleepsw = 0; /* XXX */
1724 bellflg = clearflg = forwflg = forwall = exitstat = 0;
1725 digest = NULL;
1726 ontty = NOTTY;
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 */
1734
1735 default:
1736 (void) signal (SIGINT, istat);
1737 (void) signal (SIGQUIT, qstat);
1738 (void) signal (SIGPIPE, SIG_IGN);/* XXX */
1739 if (ontty == PITTY)
1740 m_pclose ();
1741 (void) signal (SIGPIPE, pstat);
1742 invo_name = cp;
1743 if (holder.c_text) {
1744 free (holder.c_text);
1745 holder.c_text = NULL;
1746 }
1747 free_queue (&msghd, &msgtl);
1748 for (c1 = fmthd; c1; c1 = c1 -> c_next)
1749 c1 -> c_flags &= ~HDROUTPUT;
1750 return exitstat;
1751 }
1752 }
1753
1754 /* \f */
1755
1756 /* VARARGS2 */
1757
1758 static void mhladios (what, fmt, a, b, c, d, e, f)
1759 char *what,
1760 *fmt,
1761 *a,
1762 *b,
1763 *c,
1764 *d,
1765 *e,
1766 *f;
1767 {
1768 advise (what, fmt, a, b, c, d, e, f);
1769 mhldone (1);
1770 }
1771
1772
1773 static void mhldone (status)
1774 int status;
1775 {
1776 exitstat = status;
1777 if (mhl_action)
1778 longjmp (mhlenv, DONE);
1779 else
1780 done (exitstat);
1781 }
1782
1783 /* \f */
1784
1785 static int m_pid = NOTOK;
1786 static int sd = NOTOK;
1787
1788
1789 static m_popen (name)
1790 char *name;
1791 {
1792 int pd[2];
1793
1794 if (mhl_action && (sd = dup (fileno (stdout))) == NOTOK)
1795 adios ("standard output", "unable to dup()");
1796
1797 if (pipe (pd) == NOTOK)
1798 adios ("pipe", "unable to");
1799
1800 switch (m_pid = vfork ()) {
1801 case NOTOK:
1802 adios ("fork", "unable to");
1803
1804 case OK:
1805 (void) signal (SIGINT, SIG_DFL);
1806 (void) signal (SIGQUIT, SIG_DFL);
1807
1808 (void) close (pd[1]);
1809 if (pd[0] != fileno (stdin)) {
1810 (void) dup2 (pd[0], fileno (stdin));
1811 (void) close (pd[0]);
1812 }
1813 execlp (name, r1bindex (name, '/'), NULLCP);
1814 fprintf (stderr, "unable to exec ");
1815 perror (name);
1816 _exit (-1);
1817
1818 default:
1819 (void) close (pd[0]);
1820 if (pd[1] != fileno (stdout)) {
1821 (void) dup2 (pd[1], fileno (stdout));
1822 (void) close (pd[1]);
1823 }
1824 }
1825 }
1826
1827
1828 m_pclose () {
1829 if (m_pid == NOTOK)
1830 return;
1831
1832 if (sd != NOTOK) {
1833 (void) fflush (stdout);
1834 if (dup2 (sd, fileno (stdout)) == NOTOK)
1835 adios ("standard output", "unable to dup2()");
1836
1837 clearerr (stdout);
1838 (void) close (sd);
1839 sd = NOTOK;
1840 }
1841 else
1842 (void) fclose (stdout);
1843
1844 (void) pidwait (m_pid, OK);
1845 m_pid = NOTOK;
1846 }