Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / zotnet / mf / RCS / mf.c,v
1 head    1.10;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.10
9 date    92.12.15.00.20.22;      author jromine; state Exp;
10 branches;
11 next    1.9;
12
13 1.9
14 date    92.12.11.22.13.12;      author jromine; state Exp;
15 branches;
16 next    1.8;
17
18 1.8
19 date    92.01.31.22.33.19;      author jromine; state Exp;
20 branches;
21 next    1.7;
22
23 1.7
24 date    92.01.30.22.40.35;      author jromine; state Exp;
25 branches;
26 next    1.6;
27
28 1.6
29 date    90.04.05.15.04.19;      author sources; state Exp;
30 branches;
31 next    1.5;
32
33 1.5
34 date    90.02.06.13.39.34;      author sources; state Exp;
35 branches;
36 next    1.4;
37
38 1.4
39 date    90.02.05.15.29.59;      author sources; state Exp;
40 branches;
41 next    1.3;
42
43 1.3
44 date    90.02.05.15.29.16;      author sources; state Exp;
45 branches;
46 next    1.2;
47
48 1.2
49 date    90.01.23.16.06.55;      author sources; state Exp;
50 branches;
51 next    1.1;
52
53 1.1
54 date    90.01.23.15.56.16;      author sources; state Exp;
55 branches;
56 next    ;
57
58
59 desc
60 @@
61
62
63 1.10
64 log
65 @endif sugar
66 @
67 text
68 @/* mf.c - mail filter subroutines */
69 #ifndef lint
70 static char ident[] = "@@(#)$Id: mf.c,v 1.9 1992/12/11 22:13:12 jromine Exp jromine $";
71 #endif  /* lint */
72
73 #include "mf.h"
74 #include <ctype.h>
75 #include <stdio.h>
76
77 static int      isat(), parse_address(), phrase();
78 static int      route_addr(), local_part(), domain(), route();
79 static int      my_lex();
80 static void     compress();
81 /* \f */
82
83 static char *getcpy (s)
84 register char   *s;
85 {
86     register char   *p;
87
88 if (!s) { _cleanup(); abort(); for(;;) pause();}
89     if ((p = malloc ((unsigned) (strlen (s) + 2))) != NULL)
90         (void) strcpy (p, s);
91     return p;
92 }
93
94
95 static char *add (s1, s2)
96 register char   *s1,
97                 *s2;
98 {
99     register char   *p;
100
101     if (s2 == NULL)
102         return getcpy (s1);
103
104     if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) != NULL)
105         (void) sprintf (p, "%s%s", s2, s1);
106     free (s2);
107     return p;
108 }
109
110 /* \f */
111
112 int     isfrom (string)
113 register char   *string;
114 {
115     return (strncmp (string, "From ", 5) == 0
116             || strncmp (string, ">From ", 6) == 0);
117 }
118
119
120 int     lequal (a, b)
121 register char   *a,
122                 *b;
123 {
124     for (; *a; a++, b++)
125         if (*b == 0)
126             return FALSE;
127         else {
128             char    c1 = islower (*a) ? toupper (*a) : *a;
129             char    c2 = islower (*b) ? toupper (*b) : *b;
130             if (c1 != c2)
131                 return FALSE;
132         }
133
134     return (*b == 0);
135 }
136
137 /* \f */
138
139 /* 
140  *
141  * seekadrx() is tricky.  We want to cover both UUCP-style and ARPA-style
142  * addresses, so for each list of addresses we see if we can find some
143  * character to give us a hint.
144  *
145  */
146
147
148 #define CHKADR  0               /* undertermined address style */
149 #define UNIXDR  1               /* UNIX-style address */
150 #define ARPADR  2               /* ARPAnet-style address */
151
152
153 static char *punctuators = ";<>.()[]";
154 static char *vp = NULL;
155 static char *tp = NULL;
156
157 static struct adrx  adrxs1;
158
159 /* \f */
160
161 struct adrx *seekadrx (addrs)
162 register char   *addrs;
163 {
164     static int  state = CHKADR;
165     register char   *cp;
166     register struct adrx *adrxp;
167
168     if (state == CHKADR)
169         for (state = UNIXDR, cp = addrs; *cp; cp++)
170             if (index (punctuators, *cp)) {
171                 state = ARPADR;
172                 break;
173             }
174
175     switch (state) {
176         case UNIXDR: 
177             adrxp = uucpadrx (addrs);
178             break;
179
180         case ARPADR: 
181         default:
182             adrxp = getadrx (addrs);
183             break;
184     }
185
186     if (adrxp == NULL)
187         state = CHKADR;
188
189     return adrxp;
190 }
191
192 /* \f */
193
194 /*
195  *
196  * uucpadrx() implements a partial UUCP-style address parser.  It's based
197  * on the UUCP notion that addresses are separated by spaces or commas.
198  *
199  */
200
201
202 struct adrx *uucpadrx (addrs)
203 register char   *addrs;
204 {
205     register char  *cp,
206                    *wp,
207                    *xp,
208                    *yp,
209                    *zp;
210     register struct adrx   *adrxp = &adrxs1;
211
212     if (vp == NULL) {
213         vp = tp = getcpy (addrs);
214         compress (addrs, vp);
215     }
216     else
217         if (tp == NULL) {
218             free (vp);
219             vp = NULL;
220             return NULL;
221         }
222
223     for (cp = tp; isspace (*cp); cp++)
224         continue;
225     if (*cp == 0) {
226         free (vp);
227         vp = tp = NULL;
228         return NULL;
229     }
230
231 /* \f */
232
233     if ((wp = index (cp, ',')) == NULL)
234         if ((wp = index (cp, ' ')) != NULL) {
235             xp = wp;
236             while (isspace (*xp))
237                 xp++;
238             if (*xp != 0 && isat (--xp)) {
239                 yp = xp + 4;
240                 while (isspace (*yp))
241                     yp++;
242                 if (*yp != 0)
243                     if ((zp = index (yp, ' ')) != NULL)
244                         *zp = 0, tp = ++zp;
245                     else
246                         tp = NULL;
247                 else
248                     *wp = 0, tp = ++wp;
249             }
250             else
251                 *wp = 0, tp = ++wp;
252         }
253         else
254             tp = NULL;
255     else
256         *wp = 0, tp = ++wp;
257
258     if (adrxp -> text)
259         free (adrxp -> text);
260     adrxp -> text = getcpy (cp);
261     adrxp -> mbox = cp;
262     adrxp -> host = adrxp -> path = NULL;
263     if ((wp = rindex (cp, '@@')) != NULL) {
264         *wp++ = 0;
265         adrxp -> host = *wp ? wp : NULL;
266     }
267     else
268         for (wp = cp + strlen (cp) - 4; wp >= cp; wp--)
269             if (isat (wp)) {
270                 *wp++ = 0;
271                 adrxp -> host = wp + 3;
272             }
273
274     adrxp -> pers = adrxp -> grp = adrxp -> note = adrxp -> err = NULL;
275     adrxp -> ingrp = 0;
276
277     return adrxp;
278 }
279
280 /* \f */
281
282 static void  compress (fp, tp)
283 register char   *fp,
284                 *tp;
285 {
286     register char   c,
287                    *cp;
288
289     for (c = ' ', cp = tp; (*tp = *fp++) != 0;)
290         if (isspace (*tp)) {
291             if (c != ' ')
292                 *tp++ = c = ' ';
293         }
294         else
295             c = *tp++;
296
297     if (c == ' ' && cp < tp)
298         *--tp = 0;
299 }
300
301
302 static int  isat (p)
303 register char   *p;
304 {
305     return (strncmp (p, " AT ", 4)
306             && strncmp (p, " At ", 4)
307             && strncmp (p, " aT ", 4)
308             && strncmp (p, " at ", 4) ? FALSE : TRUE);
309 }
310
311 /* \f */
312
313 /*
314  *
315  * getadrx() implements a partial 822-style address parser.  The parser
316  * is neither complete nor correct.  It does however recognize nearly all
317  * of the 822 address syntax.  In addition it handles the majority of the
318  * 733 syntax as well.  Most problems arise from trying to accomodate both.
319  *
320  * In terms of 822, the route-specification in 
321  *
322  *               "<" [route] local-part "@@" domain ">"
323  *
324  * is parsed and returned unchanged.  Multiple at-signs are compressed
325  * via source-routing.  Recursive groups are not allowed as per the 
326  * standard.
327  *
328  * In terms of 733, " at " is recognized as equivalent to "@@".
329  *
330  * In terms of both the parser will not complain about missing hosts.
331  *
332  * -----
333  *
334  * We should not allow addresses like   
335  *
336  *              Marshall T. Rose <MRose@@UCI>
337  *
338  * but should insist on
339  *
340  *              "Marshall T. Rose" <MRose@@UCI>
341  *
342  * Unfortunately, a lot of mailers stupidly let people get away with this.
343  *
344  * -----
345  *
346  * We should not allow addresses like
347  *
348  *              <MRose@@UCI>
349  *
350  * but should insist on
351  *
352  *              MRose@@UCI
353  *
354  * Unfortunately, a lot of mailers stupidly let people's UAs get away with
355  * this.
356  *
357  * -----
358  *
359  * We should not allow addresses like
360  *
361  *              @@UCI:MRose@@UCI-750a
362  *
363  * but should insist on
364  *
365  *              Marshall Rose <@@UCI:MRose@@UCI-750a>
366  *
367  * Unfortunately, a lot of mailers stupidly do this.
368  *
369  */
370
371 /* \f */
372
373 #define QUOTE   '\\'
374
375 #define LX_END  0
376 #define LX_ERR  1
377 #define LX_ATOM 2
378 #define LX_QSTR 3
379 #define LX_DLIT 4
380 #define LX_SEMI 5
381 #define LX_COMA 6
382 #define LX_LBRK 7
383 #define LX_RBRK 8
384 #define LX_COLN 9
385 #define LX_DOT  10
386 #define LX_AT   11
387
388 static struct {
389     char    lx_chr;
390     int     lx_val;
391 }               special[] = {
392                     ';', LX_SEMI,
393                     ',', LX_COMA,
394                     '<', LX_LBRK,
395                     '>', LX_RBRK,
396                     ':', LX_COLN,
397                     '.', LX_DOT,
398                     '@@', LX_AT,
399                     '(', LX_ERR,
400                     ')', LX_ERR,
401                     QUOTE, LX_ERR,
402                     '"', LX_ERR,
403                     '[', LX_ERR,
404                     ']', LX_ERR,
405                     0, 0
406 };
407
408 /* \f */
409
410 static int  glevel = 0;
411 static int  ingrp = 0;
412 static int  last_lex = LX_END;
413
414 static char *dp = NULL;
415 static char *cp = NULL;
416 static char *ap = NULL;
417 static char *pers = NULL;
418 static char *mbox = NULL;
419 static char *host = NULL;
420 static char *path = NULL;
421 static char *grp = NULL;
422 static char *note = NULL;
423 static char err[BUFSIZ];
424 static char adr[BUFSIZ];
425
426 static struct adrx  adrxs2;
427
428 /* \f */
429
430 struct adrx *getadrx (addrs)
431 register char   *addrs;
432 {
433     register char   *bp;
434     register struct adrx *adrxp = &adrxs2;
435
436     if (pers)
437         free (pers);
438     if (mbox)
439         free (mbox);
440     if (host)
441         free (host);
442     if (path)
443         free (path);
444     if (grp)
445         free (grp);
446     if (note)
447         free (note);
448     pers = mbox = host = path = grp = note = NULL;
449     err[0] = 0;
450
451     if (dp == NULL) {
452         dp = cp = getcpy (addrs ? addrs : "");
453         glevel = 0;
454     }
455     else
456         if (cp == NULL) {
457             free (dp);
458             dp = NULL;
459             return NULL;
460         }
461
462     switch (parse_address ()) {
463         case DONE:
464             free (dp);
465             dp = cp = NULL;
466             return NULL;
467
468         case OK:
469             switch (last_lex) {
470                 case LX_COMA:
471                 case LX_END:
472                     break;
473
474                 default:        /* catch trailing comments */
475                     bp = cp;
476                     (void) my_lex (adr);
477                     cp = bp;
478                     break;
479             }
480             break;
481
482         default:
483             break;
484         }
485
486     if (err[0])
487         for (;;) {
488             switch (last_lex) {
489                 case LX_COMA: 
490                 case LX_END: 
491                     break;
492
493                 default: 
494                     (void) my_lex (adr);
495                     continue;
496             }
497             break;
498         }
499     while (isspace (*ap))
500         ap++;
501     if (cp)
502         (void) sprintf (adr, "%.*s", cp - ap, ap);
503     else
504         (void) strcpy (adr, ap);
505     bp = adr + strlen (adr) - 1;
506     if (*bp == ',' || *bp == ';' || *bp == '\n')
507         *bp = 0;
508
509 /* \f */
510
511     adrxp -> text = adr;
512     adrxp -> pers = pers;
513     adrxp -> mbox = mbox;
514     adrxp -> host = host;
515     adrxp -> path = path;
516     adrxp -> grp = grp;
517     adrxp -> ingrp = ingrp;
518     adrxp -> note = note;
519     adrxp -> err = err[0] ? err : NULL;
520
521     return adrxp;
522 }
523
524 /* \f */
525
526 static int  parse_address () {
527     char    buffer[BUFSIZ];
528
529 again: ;
530     ap = cp;
531     switch (my_lex (buffer)) {
532         case LX_ATOM: 
533         case LX_QSTR: 
534             pers = getcpy (buffer);
535             break;
536
537         case LX_SEMI: 
538             if (glevel-- <= 0) {
539                 (void) strcpy (err, "extraneous semi-colon");
540                 return NOTOK;
541             }
542         case LX_COMA: 
543             if (note) {
544                 free (note);
545                 note = NULL;
546             }
547             goto again;
548
549         case LX_END: 
550             return DONE;
551
552         case LX_LBRK:           /* sigh (2) */
553             goto get_addr;
554
555         case LX_AT:             /* sigh (3) */
556             cp = ap;
557             if (route_addr (buffer) == NOTOK)
558                 return NOTOK;
559             return OK;          /* why be choosy? */
560
561         default: 
562             (void) sprintf (err, "illegal address construct (%s)", buffer);
563             return NOTOK;
564     }
565
566 /* \f */
567
568     switch (my_lex (buffer)) {
569         case LX_ATOM: 
570         case LX_QSTR: 
571             pers = add (buffer, add (" ", pers));
572     more_phrase: ;              /* sigh (1) */
573             if (phrase (buffer) == NOTOK)
574                 return NOTOK;
575
576             switch (last_lex) {
577                 case LX_LBRK: 
578             get_addr: ;
579                     if (route_addr (buffer) == NOTOK)
580                         return NOTOK;
581                     if (last_lex == LX_RBRK)
582                         return OK;
583                     (void) sprintf (err, "missing right-bracket (%s)", buffer);
584                     return NOTOK;
585
586                 case LX_COLN: 
587             get_group: ;
588                     if (glevel++ > 0) {
589                         (void) sprintf (err, "nested groups not allowed (%s)",
590                                 pers);
591                         return NOTOK;
592                     }
593                     grp = add (": ", pers);
594                     pers = NULL;
595                     {
596                         char   *pp = cp;
597
598                         for (;;)
599                             switch (my_lex (buffer)) {
600                                 case LX_SEMI: 
601                                 case LX_END: /* tsk, tsk */
602                                     glevel--;
603                                     return OK;
604
605                                 case LX_COMA: 
606                                     continue;
607
608                                 default: 
609                                     cp = pp;
610                                     return parse_address ();
611                             }
612                     }
613
614                 case LX_DOT:    /* sigh (1) */
615                     pers = add (".", pers);
616                     goto more_phrase;
617
618                 default: 
619                     (void) sprintf (err,
620                             "no mailbox in address, only a phrase (%s%s)",
621                             pers, buffer);
622                     return NOTOK;
623             }
624
625 /* \f */
626
627         case LX_LBRK: 
628             goto get_addr;
629
630         case LX_COLN: 
631             goto get_group;
632
633         case LX_DOT: 
634             mbox = add (buffer, pers);
635             pers = NULL;
636             if (route_addr (buffer) == NOTOK)
637                 return NOTOK;
638             goto check_end;
639
640         case LX_AT: 
641             ingrp = glevel;
642             mbox = pers;
643             pers = NULL;
644             if (domain (buffer) == NOTOK)
645                 return NOTOK;
646     check_end: ;
647             switch (last_lex) {
648                 case LX_SEMI: 
649                     if (glevel-- <= 0) {
650                         (void) strcpy (err, "extraneous semi-colon");
651                         return NOTOK;
652                     }
653                 case LX_COMA: 
654                 case LX_END: 
655                     return OK;
656
657                 default: 
658                     (void) sprintf (err, "junk after local@@domain (%s)",
659                             buffer);
660                     return NOTOK;
661             }
662
663         case LX_SEMI:           /* no host */
664         case LX_COMA: 
665         case LX_END: 
666             ingrp = glevel;
667             if (last_lex == LX_SEMI && glevel-- <= 0) {
668                 (void) strcpy (err, "extraneous semi-colon");
669                 return NOTOK;
670             }
671             mbox = pers;
672             pers = NULL;
673             return OK;
674
675         default: 
676             (void) sprintf (err, "missing mailbox (%s)", buffer);
677             return NOTOK;
678     }
679 }
680
681 /* \f */
682
683 static int  phrase (buffer)
684 register char   *buffer;
685 {
686     for (;;)
687         switch (my_lex (buffer)) {
688             case LX_ATOM: 
689             case LX_QSTR: 
690                 pers = add (buffer, add (" ", pers));
691                 continue;
692
693             default: 
694                 return OK;
695         }
696 }
697
698 /* \f */
699
700 static int  route_addr (buffer)
701 register char   *buffer;
702 {
703     register char   *pp = cp;
704
705     if (my_lex (buffer) == LX_AT) {
706         if (route (buffer) == NOTOK)
707             return NOTOK;
708     }
709     else
710         cp = pp;
711
712     if (local_part (buffer) == NOTOK)
713         return NOTOK;
714
715     switch (last_lex) {
716         case LX_AT: 
717             return domain (buffer);
718
719         case LX_SEMI:   /* if in group */
720         case LX_RBRK:           /* no host */
721         case LX_COMA:
722         case LX_END: 
723             return OK;
724
725         default: 
726             (void) sprintf (err, "no at-sign after local-part (%s)", buffer);
727             return NOTOK;
728     }
729 }
730
731 /* \f */
732
733 static int  local_part (buffer)
734 register char   *buffer;
735 {
736     ingrp = glevel;
737
738     for (;;) {
739         switch (my_lex (buffer)) {
740             case LX_ATOM: 
741             case LX_QSTR: 
742                 mbox = add (buffer, mbox);
743                 break;
744
745             default: 
746                 (void) sprintf (err, "no mailbox in local-part (%s)", buffer);
747                 return NOTOK;
748         }
749
750         switch (my_lex (buffer)) {
751             case LX_DOT: 
752                 mbox = add (buffer, mbox);
753                 continue;
754
755             default: 
756                 return OK;
757         }
758     }
759 }
760
761 /* \f */
762
763 static int  domain (buffer)
764 register char   *buffer;
765 {
766     for (;;) {
767         switch (my_lex (buffer)) {
768             case LX_ATOM: 
769             case LX_DLIT: 
770                 host = add (buffer, host);
771                 break;
772
773             default: 
774                 (void) sprintf (err,
775                         "no sub-domain in domain-part of address (%s)", 
776                         buffer);
777                 return NOTOK;
778         }
779
780         switch (my_lex (buffer)) {
781             case LX_DOT: 
782                 host = add (buffer, host);
783                 continue;
784
785             case LX_AT:         /* sigh (0) */
786                 mbox = add (host, add ("%", mbox));
787                 free (host);
788                 host = NULL;
789                 continue;
790
791             default: 
792                 return OK;
793         }
794     }
795 }
796
797 /* \f */
798
799 static int  route (buffer)
800 register char   *buffer;
801 {
802     path = getcpy ("@@");
803
804     for (;;) {
805         switch (my_lex (buffer)) {
806             case LX_ATOM: 
807             case LX_DLIT: 
808                 path = add (buffer, path);
809                 break;
810
811             default: 
812                 (void) sprintf (err,
813                         "no sub-domain in domain-part of address (%s)",
814                         buffer);
815                 return NOTOK;
816         }
817         switch (my_lex (buffer)) {
818             case LX_COMA: 
819                 path = add (buffer, path);
820                 for (;;) {
821                     switch (my_lex (buffer)) {
822                         case LX_COMA: 
823                             continue;
824
825                         case LX_AT: 
826                             path = add (buffer, path);
827                             break;
828
829                         default: 
830                             (void) sprintf (err,
831                                     "no at-sign found for next domain in route (%s)",
832                             buffer);
833                     }
834                     break;
835                 }
836                 continue;
837
838             case LX_AT:         /* XXX */
839             case LX_DOT: 
840                 path = add (buffer, path);
841                 continue;
842
843             case LX_COLN: 
844                 path = add (buffer, path);
845                 return OK;
846
847             default: 
848                 (void) sprintf (err,
849                         "no colon found to terminate route (%s)", buffer);
850                 return NOTOK;
851         }
852     }
853 }
854
855 /* \f */
856
857 static int  my_lex (buffer)
858 register char   *buffer;
859 {
860     int     i, gotat = 0;
861     register char    c,
862                     *bp;
863
864     bp = buffer;
865     *bp = 0;
866     if (!cp)
867         return (last_lex = LX_END);
868
869     gotat = isat (cp);
870     c = *cp++;
871     while (isspace (c))
872         c = *cp++;
873     if (c == 0) {
874         cp = NULL;
875         return (last_lex = LX_END);
876     }
877
878     if (c == '(')
879         for (*bp++ = c, i = 0;;)
880             switch (c = *cp++) {
881                 case 0: 
882                     cp = NULL;
883                     return (last_lex = LX_ERR);
884                 case QUOTE: 
885                     *bp++ = c;
886                     if ((c = *cp++) == 0) {
887                         cp = NULL;
888                         return (last_lex = LX_ERR);
889                     }
890                     *bp++ = c;
891                     continue;
892                 case '(': 
893                     i++;
894                 default: 
895                     *bp++ = c;
896                     continue;
897                 case ')': 
898                     *bp++ = c;
899                     if (--i < 0) {
900                         *bp = 0;
901                         note = note ? add (buffer, add (" ", note))
902                             : getcpy (buffer);
903                         return my_lex (buffer);
904                     }
905             }
906
907 /* \f */
908
909     if (c == '"')
910         for (*bp++ = c;;)
911             switch (c = *cp++) {
912                 case 0: 
913                     cp = NULL;
914                     return (last_lex = LX_ERR);
915                 case QUOTE: 
916                     *bp++ = c;
917                     if ((c = *cp++) == 0) {
918                         cp = NULL;
919                         return (last_lex = LX_ERR);
920                     }
921                 default: 
922                     *bp++ = c;
923                     continue;
924                 case '"': 
925                     *bp++ = c;
926                     *bp = 0;
927                     return (last_lex = LX_QSTR);
928             }
929
930     if (c == '[')
931         for (*bp++ = c;;)
932             switch (c = *cp++) {
933                 case 0: 
934                     cp = NULL;
935                     return (last_lex = LX_ERR);
936                 case QUOTE: 
937                     *bp++ = c;
938                     if ((c = *cp++) == 0) {
939                         cp = NULL;
940                         return (last_lex = LX_ERR);
941                     }
942                 default: 
943                     *bp++ = c;
944                     continue;
945                 case ']': 
946                     *bp++ = c;
947                     *bp = 0;
948                     return (last_lex = LX_DLIT);
949             }
950
951 /* \f */
952
953     *bp++ = c;
954     *bp = 0;
955     for (i = 0; special[i].lx_chr != 0; i++)
956         if (c == special[i].lx_chr)
957             return (last_lex = special[i].lx_val);
958
959     if (iscntrl (c))
960         return (last_lex = LX_ERR);
961
962     for (;;) {
963         if ((c = *cp++) == 0)
964             break;
965         for (i = 0; special[i].lx_chr != 0; i++)
966             if (c == special[i].lx_chr)
967                 goto got_atom;
968         if (iscntrl (c) || isspace (c))
969             break;
970         *bp++ = c;
971     }
972 got_atom: ;
973     if (c == 0)
974         cp = NULL;
975     else
976         cp--;
977     *bp = 0;
978     last_lex = !gotat || cp == NULL || index (cp, '<') != NULL
979         ? LX_ATOM : LX_AT;
980     return last_lex;
981 }
982
983 /* \f */
984
985 char   *legal_person (p)
986 register char   *p;
987 {
988     int     i;
989     register char   *cp;
990     static char buffer[BUFSIZ];
991
992     if (*p == '"')
993         return p;
994     for (cp = p; *cp; cp++)
995         for (i = 0; special[i].lx_chr; i++)
996             if (*cp == special[i].lx_chr) {
997                 (void) sprintf (buffer, "\"%s\"", p);
998                 return buffer;
999             }
1000
1001     return p;
1002 }
1003
1004 /* \f */
1005
1006 int     mfgets (in, bp)
1007 register FILE *in;
1008 register char  **bp;
1009 {
1010     int     i;
1011     register char   *cp,
1012                     *dp,
1013                     *ep;
1014     static int  len = 0;
1015     static char *pp = NULL;
1016
1017     if (pp == NULL)
1018         if ((pp = malloc ((unsigned) (len = BUFSIZ))) == NULL)
1019             return NOTOK;
1020
1021     for (ep = (cp = pp) + len - 2;;) {
1022         switch (i = getc (in)) {
1023             case EOF: 
1024         eol:    ;
1025                 if (cp != pp) {
1026                     *cp = 0;
1027                     *bp = pp;
1028                     return OK;
1029                 }
1030         eoh:    ;
1031                 *bp = NULL;
1032                 free (pp);
1033                 pp = NULL;
1034                 return DONE;
1035
1036             case 0: 
1037                 continue;
1038
1039             case '\n': 
1040                 if (cp == pp)   /* end of headers, gobble it */
1041                     goto eoh;
1042                 switch (i = getc (in)) {
1043                     default:    /* end of line */
1044                     case '\n':  /* end of headers, save for next call */
1045                         (void) ungetc (i, in);
1046                         goto eol;
1047
1048                     case ' ':   /* continue headers */
1049                     case '\t': 
1050                         *cp++ = '\n';
1051                         break;
1052                 }               /* fall into default case */
1053
1054             default: 
1055                 *cp++ = i;
1056                 break;
1057         }
1058         if (cp >= ep)
1059             if ((dp = realloc (pp, (unsigned) (len += BUFSIZ))) == NULL) {
1060                 free (pp);
1061                 pp = NULL;
1062                 return NOTOK;
1063             }
1064             else
1065                 cp += dp - pp, ep = (pp = cp) + len - 2;
1066     }
1067 }
1068 @
1069
1070
1071 1.9
1072 log
1073 @int/void fixup
1074 @
1075 text
1076 @d3 2
1077 a4 2
1078 static char ident[] = "@@(#)$Id: mf.c,v 1.8 1992/01/31 22:33:19 jromine Exp jromine $";
1079 #endif  lint
1080 @
1081
1082
1083 1.8
1084 log
1085 @kerberos
1086 @
1087 text
1088 @d3 1
1089 a3 1
1090 static char ident[] = "@@(#)$Id: mf.c,v 1.7 1992/01/30 22:40:35 jromine Exp jromine $";
1091 d10 1
1092 a10 1
1093 static int      compress(), isat(), parse_address(), phrase();
1094 d13 1
1095 d215 1
1096 a215 1
1097 static int  compress (fp, tp)
1098 @
1099
1100
1101 1.7
1102 log
1103 @remove WP
1104 @
1105 text
1106 @d3 1
1107 a3 1
1108 static char ident[] = "@@(#)$Id: mf.c,v 1.6 1990/04/05 15:04:19 sources Exp jromine $";
1109 d57 1
1110 a57 1
1111         if (*b == NULL)
1112 d66 1
1113 a66 1
1114     return (*b == NULL);
1115 d157 1
1116 a157 1
1117     if (*cp == NULL) {
1118 d170 1
1119 a170 1
1120             if (*xp != NULL && isat (--xp)) {
1121 d174 1
1122 a174 1
1123                 if (*yp != NULL)
1124 d176 1
1125 a176 1
1126                         *zp = NULL, tp = ++zp;
1127 d180 1
1128 a180 1
1129                     *wp = NULL, tp = ++wp;
1130 d183 1
1131 a183 1
1132                 *wp = NULL, tp = ++wp;
1133 d188 1
1134 a188 1
1135         *wp = NULL, tp = ++wp;
1136 d196 1
1137 a196 1
1138         *wp++ = NULL;
1139 d202 1
1140 a202 1
1141                 *wp++ = NULL;
1142 d221 1
1143 a221 1
1144     for (c = ' ', cp = tp; (*tp = *fp++) != NULL;)
1145 d230 1
1146 a230 1
1147         *--tp = NULL;
1148 d337 1
1149 a337 1
1150                     NULL, NULL
1151 d381 1
1152 a381 1
1153     err[0] = NULL;
1154 d439 1
1155 a439 1
1156         *bp = NULL;
1157 d797 1
1158 a797 1
1159     *bp = NULL;
1160 d805 1
1161 a805 1
1162     if (c == NULL) {
1163 d813 1
1164 a813 1
1165                 case NULL: 
1166 d818 1
1167 a818 1
1168                     if ((c = *cp++) == NULL) {
1169 d832 1
1170 a832 1
1171                         *bp = NULL;
1172 d844 1
1173 a844 1
1174                 case NULL: 
1175 d849 1
1176 a849 1
1177                     if ((c = *cp++) == NULL) {
1178 d858 1
1179 a858 1
1180                     *bp = NULL;
1181 d865 1
1182 a865 1
1183                 case NULL: 
1184 d870 1
1185 a870 1
1186                     if ((c = *cp++) == NULL) {
1187 d879 1
1188 a879 1
1189                     *bp = NULL;
1190 d886 2
1191 a887 2
1192     *bp = NULL;
1193     for (i = 0; special[i].lx_chr != NULL; i++)
1194 d895 1
1195 a895 1
1196         if ((c = *cp++) == NULL)
1197 d897 1
1198 a897 1
1199         for (i = 0; special[i].lx_chr != NULL; i++)
1200 d905 1
1201 a905 1
1202     if (c == NULL)
1203 d909 1
1204 a909 1
1205     *bp = NULL;
1206 d958 1
1207 a958 1
1208                     *cp = NULL;
1209 d968 1
1210 a968 1
1211             case NULL: 
1212 @
1213
1214
1215 1.6
1216 log
1217 @add ID
1218 @
1219 text
1220 @d3 1
1221 a3 1
1222 static char ident[] = "@@(#)$Id:$";
1223 a306 3
1224 #ifdef  WP
1225 #define LX_WP   (-1)
1226 #endif
1227 a359 8
1228
1229 #ifdef  WP
1230 char   *concat ();
1231
1232 extern int      do_wp;
1233 char   *wp_expand ();
1234 #endif
1235
1236 a364 3
1237 #ifdef  WP
1238     int     save_lex;
1239 #endif
1240 a393 23
1241 #ifdef  WP
1242     bp = cp, save_lex = last_lex;
1243     if (my_lex (adr) == LX_WP) {
1244         register char *ep,
1245                       *fp;
1246
1247         if (fp = wp_expand (adr, err)) {
1248             *bp = NULL;
1249             ep = concat (dp, fp, cp, (char *) NULL);
1250             cp = ep + strlen (dp), last_lex = save_lex;
1251             free (dp);
1252             dp = ep;
1253             free (fp);
1254         }
1255         else {
1256             ap = bp, save_lex = last_lex;
1257             goto out;
1258         }
1259     }
1260     else
1261         cp = bp, last_lex = save_lex;
1262 #endif
1263
1264 a417 3
1265 #ifdef  WP
1266 out: ;
1267 #endif
1268 a808 15
1269
1270 #ifdef  WP
1271     if (do_wp && c == '<' && *cp == '<')
1272         for (cp++;;)
1273             switch (c = *cp++) {
1274                 case '>':
1275                     *bp = NULL;
1276                     cp++;
1277                     return (last_lex = LX_WP);
1278
1279                 default:
1280                     *bp++ = c;
1281                     continue;
1282             }
1283 #endif
1284 @
1285
1286
1287 1.5
1288 log
1289 @ANSI Compilance
1290 @
1291 text
1292 @d2 3
1293 @
1294
1295
1296 1.4
1297 log
1298 @WP changes
1299 @
1300 text
1301 @d7 3
1302 @
1303
1304
1305 1.3
1306 log
1307 @fix for "at" domain names
1308 @
1309 text
1310 @d301 3
1311 d357 8
1312 d370 3
1313 d402 23
1314 d449 3
1315 d843 15
1316 @
1317
1318
1319 1.2
1320 log
1321 @Fix for "test: foo.bar;" case.  This probably breaks something else,
1322 but it's as good as I can do for now.
1323 /JLR
1324 @
1325 text
1326 @d786 1
1327 a786 1
1328     int     i;
1329 d795 1
1330 d904 1
1331 a904 1
1332     last_lex = !lequal (buffer, "at") || cp == NULL || index (cp, '<') != NULL
1333 @
1334
1335
1336 1.1
1337 log
1338 @Initial revision
1339 @
1340 text
1341 @d645 1
1342 @