Added all of the MH sources, including RCS files, in
[mmh] / docs / historical / mh-6.8.5 / mts / sendmail / RCS / smail.c,v
1 head    1.30;
2 access;
3 symbols;
4 locks; strict;
5 comment @ * @;
6
7
8 1.30
9 date    96.02.09.23.05.06;      author jromine; state Exp;
10 branches;
11 next    1.29;
12
13 1.29
14 date    95.12.06.22.29.38;      author jromine; state Exp;
15 branches;
16 next    1.28;
17
18 1.28
19 date    94.03.23.23.24.51;      author jromine; state Exp;
20 branches;
21 next    1.27;
22
23 1.27
24 date    93.12.01.03.50.31;      author jromine; state Exp;
25 branches;
26 next    1.26;
27
28 1.26
29 date    93.09.01.20.55.22;      author jromine; state Exp;
30 branches;
31 next    1.25;
32
33 1.25
34 date    93.08.25.17.17.29;      author jromine; state Exp;
35 branches;
36 next    1.24;
37
38 1.24
39 date    93.08.20.16.14.30;      author jromine; state Exp;
40 branches;
41 next    1.23;
42
43 1.23
44 date    93.08.20.15.47.14;      author jromine; state Exp;
45 branches;
46 next    1.22;
47
48 1.22
49 date    93.08.19.23.35.31;      author jromine; state Exp;
50 branches;
51 next    1.21;
52
53 1.21
54 date    92.11.09.18.19.32;      author jromine; state Exp;
55 branches;
56 next    1.20;
57
58 1.20
59 date    92.11.06.18.04.48;      author jromine; state Exp;
60 branches;
61 next    1.19;
62
63 1.19
64 date    92.11.06.17.26.22;      author jromine; state Exp;
65 branches;
66 next    1.18;
67
68 1.18
69 date    92.11.02.18.55.04;      author jromine; state Exp;
70 branches;
71 next    1.17;
72
73 1.17
74 date    92.10.26.22.42.56;      author jromine; state Exp;
75 branches;
76 next    1.16;
77
78 1.16
79 date    92.10.26.16.39.18;      author jromine; state Exp;
80 branches;
81 next    1.15;
82
83 1.15
84 date    92.10.21.03.27.12;      author jromine; state Exp;
85 branches;
86 next    1.14;
87
88 1.14
89 date    92.10.21.03.26.43;      author jromine; state Exp;
90 branches;
91 next    1.13;
92
93 1.13
94 date    92.10.20.15.36.40;      author jromine; state Exp;
95 branches;
96 next    1.12;
97
98 1.12
99 date    92.10.16.16.51.15;      author jromine; state Exp;
100 branches;
101 next    1.11;
102
103 1.11
104 date    92.03.03.17.11.03;      author jromine; state Exp;
105 branches;
106 next    1.10;
107
108 1.10
109 date    92.03.03.17.09.57;      author jromine; state Exp;
110 branches;
111 next    1.9;
112
113 1.9
114 date    92.02.10.18.12.35;      author jromine; state Exp;
115 branches;
116 next    1.8;
117
118 1.8
119 date    92.02.05.22.10.36;      author jromine; state Exp;
120 branches;
121 next    1.7;
122
123 1.7
124 date    92.01.31.21.40.09;      author jromine; state Exp;
125 branches;
126 next    1.6;
127
128 1.6
129 date    90.04.05.15.30.07;      author sources; state Exp;
130 branches;
131 next    1.5;
132
133 1.5
134 date    90.04.05.14.43.29;      author sources; state Exp;
135 branches;
136 next    1.4;
137
138 1.4
139 date    90.02.06.12.58.44;      author sources; state Exp;
140 branches;
141 next    1.3;
142
143 1.3
144 date    90.02.05.14.56.10;      author sources; state Exp;
145 branches;
146 next    1.2;
147
148 1.2
149 date    90.02.01.14.00.49;      author sources; state Exp;
150 branches;
151 next    1.1;
152
153 1.1
154 date    90.02.01.13.39.06;      author sources; state Exp;
155 branches;
156 next    ;
157
158
159 desc
160 @@
161
162
163 1.30
164 log
165 @loop over servers when initial response is bad
166 @
167 text
168 @/* smail.c - MH interface to SendMail/SMTP */
169 #ifndef lint
170 static char ident[] = "@@(#)$Id: smail.c,v 1.29 1995/12/06 22:29:38 jromine Exp jromine $";
171 #endif
172
173 /* LINTLIBRARY */
174
175 /* This module implements an interface to SendMail very similar to the
176    MMDF mm_(3) routines.  The sm_() routines herein talk SMTP to a
177    sendmail process, mapping SMTP reply codes into RP_-style codes.
178  */
179
180 #ifdef  BSD42
181 /* Under 4.2BSD, the alarm handing stuff for time-outs will NOT work due to
182    the way syscalls get restarted.  This really is not crucial, since we
183    expect SendMail to be well-behaved and not hang on us.  The only time
184    I've ever seen Sendmail hang was with a bogus configuration file...
185  */
186 #endif  /* BSD42 */
187 #ifdef  SENDMAILBUG
188 /*
189  * It appears that some versions of Sendmail will return Code 451
190  * when they don't really want to indicate a failure.
191  * "Code 451 almost always means sendmail has deferred; we don't
192  * really want bomb out at this point since sendmail will rectify
193  * things later."  So, if you define SENDMAILBUG, Code 451 is
194  * considered the same as Code 250.  Yuck!
195  */
196 #ifndef SENDMAIL
197 #undef          SENDMAILBUG
198 #endif  /* not SENDMAIL */
199 #endif  /* SENDMAILBUG */
200
201 #ifdef hpux     
202 /* HP-UX has this capability. It also handles (some) signals. */
203 #define BSD42 
204 #endif /* hpux */
205
206 #if     !defined(BSD42) && !defined(SOCKETS)
207 #undef  SMTP
208 #endif  /* not BSD42 and not SOCKETS */
209 #ifdef  SMTP
210 #undef  SENDMAIL
211 #endif  /* SMTP */
212
213
214 #include "../h/strings.h"
215 #include <stdio.h>
216 #include "smail.h"
217 #include "../zotnet/mts.h"
218 #include <ctype.h>
219 #include <signal.h>
220
221 #ifndef TYPESIG
222 #define TYPESIG int
223 #endif
224
225 #define NOTOK   (-1)
226 #define OK      0
227 #define DONE    1
228
229 #define TRUE    1
230 #define FALSE   0
231
232 #define NBITS   ((sizeof (int)) * 8)
233
234 #define min(a,b)        ((a) < (b) ? (a) : (b))
235
236
237                 /* these codes must all be different! */
238 #define SM_OPEN  90      /* Changed from 30 in case of nameserver flakiness */
239 #define SM_HELO  20
240 #define SM_RSET  15
241 #define SM_MAIL  40
242 #define SM_RCPT 120
243 #define SM_DATA  20
244 #define SM_TEXT 150
245 #define SM_DOT  180
246 #define SM_QUIT  30
247 #define SM_CLOS  10
248
249 /* \f */
250
251 static TYPESIG  alrmser ();
252
253 static int  sm_addrs = 0;
254 static int  sm_alarmed = 0;
255 #ifndef SMTP
256 static int  sm_child = NOTOK;
257 #endif  /* not SMTP */
258 static int  sm_debug = 0;
259 static int  sm_nl = TRUE;
260 static int  sm_verbose = 0;
261
262 static  FILE * sm_rfp = NULL;
263 static  FILE * sm_wfp = NULL;
264
265 #ifdef  MPOP
266 static  int  sm_ispool = 0;
267 static  char sm_tmpfil[BUFSIZ];
268 #endif /* MPOP */
269
270 static char *sm_noreply = "No reply text given";
271 static char *sm_moreply = "; ";
272
273 struct smtp sm_reply;           /* global... */
274
275
276 void    discard ();
277 char   *r1bindex ();
278
279 static int      rclient(), sm_ierror(), smtalk(), sm_wrecord(), sm_wstream();
280 static int      sm_werror(), smhear(), sm_rrecord(), sm_rerror();
281
282 #ifdef  MPOP
283 extern  int     errno;
284 #ifndef BSD44
285 extern  int     sys_nerr;
286 extern  char   *sys_errlist[];
287 #endif
288 #endif
289
290 static  int     doingEHLO;
291
292 #define MAXEHLO 10
293 char   *EHLOkeys[MAXEHLO + 1];
294
295 char   *EHLOset ();
296
297 #ifdef  SMTP
298 #ifndef MAXARGS
299 #define MAXARGS 1000
300 #endif
301
302 extern  char  **brkstring (), **copyip (), *getcpy ();
303 #endif
304
305 /* \f */
306
307 #ifndef SMTP
308
309 /* ARGSUSED */
310
311 int     sm_init (client, server, watch, verbose, debug, onex, queued)
312 char   *client,
313        *server;
314 int     watch,
315         verbose,
316         debug,
317         onex,
318         queued;
319 {
320     register int    i,
321                     result,
322                     vecp;
323     int     pdi[2],
324             pdo[2];
325     char   *vec[15];
326
327     if (watch)
328 #ifndef SUN40
329         verbose = TRUE;
330 #else   /* to show the transaction, -watch must imply -snoop */
331         debug = verbose = TRUE;
332 #endif
333     sm_verbose = verbose;
334     sm_debug = debug;
335     if (sm_rfp != NULL && sm_wfp != NULL)
336         return RP_OK;
337
338     if (client == NULL || *client == '\0')
339         client = clientname;
340 #ifdef ZMAILER
341     if (client == NULL || *client == '\0')
342         client = "localhost";
343 #endif
344
345     if (pipe (pdi) == NOTOK)
346         return sm_ierror ("no pipes");
347     if (pipe (pdo) == NOTOK) {
348         (void) close (pdi[0]);
349         (void) close (pdi[1]);
350         return sm_ierror ("no pipes");
351     }
352
353     for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++)
354         sleep (5);
355     switch (sm_child) {
356         case NOTOK: 
357             (void) close (pdo[0]);
358             (void) close (pdo[1]);
359             (void) close (pdi[0]);
360             (void) close (pdi[1]);
361             return sm_ierror ("unable to fork");
362
363         case OK: 
364             if (pdo[0] != fileno (stdin))
365                 (void) dup2 (pdo[0], fileno (stdin));
366             if (pdi[1] != fileno (stdout))
367                 (void) dup2 (pdi[1], fileno (stdout));
368             if (pdi[1] != fileno (stderr))
369                 (void) dup2 (pdi[1], fileno (stderr));
370             for (i = fileno (stderr) + 1; i < NBITS; i++)
371                 (void) close (i);
372
373             vecp = 0;
374             vec[vecp++] = r1bindex (sendmail, '/');
375             vec[vecp++] = "-bs";
376 #ifndef ZMAILER
377             vec[vecp++] = watch ? "-odi" : queued ? "-odq" : "-odb";
378             vec[vecp++] = "-oem";
379             vec[vecp++] = "-om";
380 #ifndef RAND
381             if (verbose)
382                 vec[vecp++] = "-ov";
383 #endif  /* not RAND */
384 #endif  /* not ZMAILER */
385             vec[vecp++] = NULL;
386
387             (void) setgid (getegid ());
388             (void) setuid (geteuid ());
389             execvp (sendmail, vec);
390             fprintf (stderr, "unable to exec ");
391             perror (sendmail);
392             _exit (-1);         /* NOTREACHED */
393
394         default: 
395             (void) signal (SIGALRM, alrmser);
396             (void) signal (SIGPIPE, SIG_IGN);
397
398             (void) close (pdi[1]);
399             (void) close (pdo[0]);
400             if ((sm_rfp = fdopen (pdi[0], "r")) == NULL
401                     || (sm_wfp = fdopen (pdo[1], "w")) == NULL) {
402                 (void) close (pdi[0]);
403                 (void) close (pdo[1]);
404                 sm_rfp = sm_wfp = NULL;
405                 return sm_ierror ("unable to fdopen");
406             }
407             sm_alarmed = 0;
408             (void) alarm (SM_OPEN);
409             result = smhear ();
410             (void) alarm (0);
411             switch (result) {
412                 case 220: 
413                     break;
414
415                 default: 
416                     (void) sm_end (NOTOK);
417                     return RP_RPLY;
418             }
419
420             if (client && *client) {
421                 doingEHLO = 1;
422                 result = smtalk (SM_HELO, "EHLO %s", client);
423                 doingEHLO = 0;
424
425                 if (500 <= result && result <= 599)
426                     result = smtalk (SM_HELO, "HELO %s", client);
427
428                 switch (result) {
429                     case 250:
430                         break;
431
432                     default:
433                         (void) sm_end (NOTOK);
434                         return RP_RPLY;
435                 }
436             }
437
438 #ifndef ZMAILER
439             if (onex)
440                 (void) smtalk (SM_HELO, "ONEX");
441 #endif
442             if (watch)
443                 (void) smtalk (SM_HELO, "VERB on");
444
445             return RP_OK;
446     }
447 }
448 #else   /* SMTP */
449
450 /* \f */
451
452 int     sm_init (client, server, watch, verbose, debug, onex, queued)
453 char   *client,
454        *server;
455 int     watch,
456         verbose,
457         debug,
458         onex,
459         queued;
460 {
461     register int    result,
462                     sd1,
463                     sd2;
464     register char **ap;
465     char   *cp,
466            *arguments[MAXARGS];
467
468     ap = arguments;
469     if (!server || !*server)
470         server = servers;
471     (void) copyip (brkstring (getcpy (server), " ", "\n"), ap);
472
473     if (watch)
474 #if     !defined(SUN40) || defined(MMDFII)
475         verbose = TRUE;
476 #else   /* to show the transaction, -watch must imply -snoop */
477         debug = verbose = TRUE;
478 #endif
479     sm_verbose = verbose;
480     sm_debug = debug;
481 #ifdef  MPOP
482     if (sm_ispool)
483         goto all_done;
484 #endif
485     if (sm_rfp != NULL && sm_wfp != NULL)
486         goto send_options;
487
488     if (client == NULL || *client == '\0')
489         if (clientname)
490             client = clientname;
491         else
492             client = LocalName ();      /* no clientname -> LocalName */
493 #ifdef ZMAILER
494     if (client == NULL || *client == '\0')
495         client = "localhost";
496 #endif  /* not ZMAILER */
497
498     ap = arguments;
499 again: ;
500     for (sd1 = NOTOK; *ap; ap++) {
501         if ((sd1 = rclient (*ap, "tcp", "smtp")) != NOTOK)
502             break;
503     }
504     if (sd1 == NOTOK)
505         return RP_BHST;
506 #ifdef  MPOP
507     if (sm_ispool) {
508         if (sm_rfp) {
509             (void) alarm (SM_CLOS);
510             (void) fclose (sm_rfp);
511             (void) alarm (0);
512             sm_rfp = NULL;
513         }
514         if ((sm_wfp = fdopen (sd1, "w")) == NULL) {
515             (void) unlink (sm_tmpfil);
516             (void) close (sd1);
517             return sm_ierror ("unable to fdopen");
518         }
519 all_done: ;
520         sm_reply.text[sm_reply.length = 0] = NULL;
521         return (sm_reply.code = RP_OK);
522     }
523 #endif /* MPOP */
524     if ((sd2 = dup (sd1)) == NOTOK) {
525         (void) close (sd1);
526         return sm_ierror ("unable to dup");
527     }
528
529     (void) signal (SIGALRM, alrmser);
530     (void) signal (SIGPIPE, SIG_IGN);
531
532     if ((sm_rfp = fdopen (sd1, "r")) == NULL
533             || (sm_wfp = fdopen (sd2, "w")) == NULL) {
534         (void) close (sd1);
535         (void) close (sd2);
536         sm_rfp = sm_wfp = NULL;
537         return sm_ierror ("unable to fdopen");
538     }
539     sm_alarmed = 0;
540     (void) alarm (SM_OPEN);
541     result = smhear ();
542     (void) alarm (0);
543     switch (result) {
544         case 220: 
545             break;
546
547         default:
548             (void) sm_end (NOTOK);
549             if (*++ap) {
550                 sd1 = NOTOK;
551                 goto again;
552             }
553             return RP_RPLY;
554     }
555
556     if (client && *client) {
557         doingEHLO = 1;
558         result = smtalk (SM_HELO, "EHLO %s", client);
559         doingEHLO = 0;
560
561         if (500 <= result && result <= 599)
562             result = smtalk (SM_HELO, "HELO %s", client);
563
564         switch (result) {
565             case 250: 
566                 break;
567
568             default: 
569                 (void) sm_end (NOTOK);
570                 return RP_RPLY;
571         }
572     }
573
574 send_options: ;
575     if (watch && EHLOset ("XVRB"))
576         (void) smtalk (SM_HELO, "VERB on");
577     if (onex && EHLOset ("XONE"))
578         (void) smtalk (SM_HELO, "ONEX");
579     if (queued && EHLOset ("XQUE"))
580         (void) smtalk (SM_HELO, "QUED");
581
582     return RP_OK;
583 }
584
585
586 static int rclient (server, protocol, service)
587 char   *server,
588        *protocol,
589        *service;
590 {
591     int     sd;
592     char    response[BUFSIZ];
593 #ifdef  MPOP
594     char   *cp;
595 #endif /* MPOP */
596
597     if ((sd = client (server, protocol, service, FALSE, response)) != NOTOK)
598         return sd;
599
600 #ifdef  MPOP
601     if (!server && servers && (cp = index (servers, '/'))) {
602         register char  **ap;
603         char   *arguments[MAXARGS];
604
605         (void) copyip (brkstring (cp = getcpy (servers), " ", "\n"),
606                        arguments);
607
608         for (ap = arguments; *ap; ap++)
609             if (**ap == '/') {
610                 register char *dp;
611
612                 if ((dp = rindex (*ap, '/')) && *++dp == NULL)
613                     *--dp = NULL;
614                 (void) sprintf (sm_tmpfil, "%s/smtpXXXXXX", *ap);
615                 (void) mktemp (sm_tmpfil);
616
617                 if ((sd = creat (sm_tmpfil, 0600)) != NOTOK) {
618                     sm_ispool = 1;
619                     break;
620                 }
621             }
622
623         free (cp);
624         if (sd != NOTOK)
625             return sd;
626     }
627 #endif /* MPOP */
628
629     (void) sm_ierror ("%s", response);
630     return NOTOK;
631 }
632 #endif  /* SMTP */
633
634 /* \f */
635
636 int     sm_winit (mode, from)
637 register int    mode;
638 register char   *from;
639 {
640 #ifdef  MPOP
641     if (sm_ispool && !sm_wfp) {
642         (void) strlen (strcpy (sm_reply.text,
643                                "unable to create new spool file"));
644         sm_reply.code = NOTOK;
645         return RP_BHST;
646     }
647 #endif /* MPOP */
648
649     switch (smtalk (SM_MAIL, "%s FROM:<%s>",
650                 mode == S_SEND ? "SEND" : mode == S_SOML ? "SOML"
651                 : mode == S_SAML ? "SAML" : "MAIL", from)) {
652         case 250: 
653             sm_addrs = 0;
654             return RP_OK;
655
656         case 500: 
657         case 501: 
658         case 552: 
659             return RP_PARM;
660
661         default: 
662             return RP_RPLY;
663     }
664 }
665
666 /* \f */
667
668 #ifdef  BERK
669 /* ARGUSED */
670 #endif  /* BERK */
671
672 int     sm_wadr (mbox, host, path)
673 register char   *mbox;
674 #ifndef BERK
675 register
676 #endif  /* not BERK */
677          char   *host,
678                 *path;
679 {
680 #ifndef BERK
681     switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@@%s>"
682                                            : "RCPT TO:<%s%s>",
683                              path ? path : "", mbox, host)) {
684 #else   /* BERK */
685     switch (smtalk (SM_RCPT, "RCPT TO:%s", mbox)) {
686 #endif  /* BERK */
687         case 250: 
688         case 251: 
689             sm_addrs++;
690             return RP_OK;
691
692         case 451: 
693 #ifdef SENDMAILBUG
694             sm_addrs++;
695             return RP_OK;
696 #endif /* SENDMAILBUG */
697         case 421: 
698         case 450: 
699         case 452: 
700             return RP_NO;
701
702         case 500: 
703         case 501: 
704             return RP_PARM;
705
706         case 550: 
707         case 551: 
708         case 552: 
709         case 553: 
710             return RP_USER;
711
712         default: 
713             return RP_RPLY;
714     }
715 }
716
717 /* \f */
718
719 int     sm_waend () {
720     switch (smtalk (SM_DATA, "DATA")) {
721         case 354: 
722             sm_nl = TRUE;
723             return RP_OK;
724
725         case 451: 
726 #ifdef SENDMAILBUG
727             sm_nl = TRUE;
728             return RP_OK;
729 #endif /* SENDMAILBUG */
730         case 421: 
731             return RP_NO;
732
733         case 500: 
734         case 501: 
735         case 503: 
736         case 554: 
737             return RP_NDEL;
738
739         default: 
740             return RP_RPLY;
741     }
742 }
743
744 /* \f */
745
746 int     sm_wtxt (buffer, len)
747 register char   *buffer;
748 register int     len;
749 {
750     register int    result;
751
752     sm_alarmed = 0;
753     (void) alarm (SM_TEXT);
754     result = sm_wstream (buffer, len);
755     (void) alarm (0);
756
757     return (result == NOTOK ? RP_BHST : RP_OK);
758 }
759
760 /* \f */
761
762 int     sm_wtend () {
763     if (sm_wstream ((char *) NULL, 0) == NOTOK)
764         return RP_BHST;
765
766     switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) {
767         case 250: 
768         case 251: 
769             return RP_OK;
770
771         case 451: 
772 #ifdef SENDMAILBUG
773             return RP_OK;
774 #endif /* SENDMAILBUG */
775         case 452: 
776         default: 
777             return RP_NO;
778
779         case 552: 
780         case 554: 
781             return RP_NDEL;
782     }
783 }
784
785 /* \f */
786
787 int     sm_end (type)
788 register int     type;
789 {
790     register int    status;
791     struct smtp sm_note;
792
793 #ifndef SMTP
794     switch (sm_child) {
795         case NOTOK: 
796         case OK: 
797             return RP_OK;
798
799         default: 
800             break;
801     }
802 #endif  /* not SMTP */
803     if (sm_rfp == NULL && sm_wfp == NULL)
804         return RP_OK;
805
806     switch (type) {
807         case OK: 
808             (void) smtalk (SM_QUIT, "QUIT");
809             break;
810
811         case NOTOK: 
812             sm_note.code = sm_reply.code;
813             (void) strncpy (sm_note.text, sm_reply.text,
814                     sm_note.length = sm_reply.length);/* fall */
815         case DONE: 
816             if (smtalk (SM_RSET, "RSET") == 250 && type == DONE)
817                 return RP_OK;
818 #ifndef SMTP
819             (void) kill (sm_child, SIGKILL);
820             discard (sm_rfp);
821             discard (sm_wfp);
822 #else   /* SMTP */
823             (void) smtalk (SM_QUIT, "QUIT");
824 #endif  /* not SMTP */
825             if (type == NOTOK) {
826                 sm_reply.code = sm_note.code;
827                 (void) strncpy (sm_reply.text, sm_note.text,
828                         sm_reply.length = sm_note.length);
829             }
830             break;
831     }
832 #ifdef  MPOP
833 #ifdef  SMTP
834     if (sm_ispool) {
835         sm_ispool = 0;
836
837         if (sm_wfp) {
838             (void) unlink (sm_tmpfil);
839             (void) fclose (sm_wfp);
840             sm_wfp = NULL;
841         }
842     }
843 #endif
844 #endif /* MPOP */
845     if (sm_rfp != NULL) {
846         (void) alarm (SM_CLOS);
847         (void) fclose (sm_rfp);
848         (void) alarm (0);
849     }
850     if (sm_wfp != NULL) {
851         (void) alarm (SM_CLOS);
852         (void) fclose (sm_wfp);
853         (void) alarm (0);
854     }
855
856 #ifndef SMTP
857     status = pidwait (sm_child);
858
859     sm_child = NOTOK;
860 #else   /* SMTP */
861     status = 0;
862 #endif  /* SMTP */
863     sm_rfp = sm_wfp = NULL;
864
865     return (status ? RP_BHST : RP_OK);
866 }
867
868 /* \f */
869
870 #ifdef  MPOP
871 #ifdef  SMTP
872 #include <sys/types.h>
873 #include <sys/stat.h>
874
875
876 int     sm_bulk (file)
877 char   *file;
878 {
879     int     cc,
880             i,
881             j,
882             k,
883             result;
884     long    pos;
885     register char *dp;
886     char   *bp,
887            *cp,
888             buffer[BUFSIZ],
889             sender[BUFSIZ];
890     FILE   *fp,
891            *gp;
892
893     gp = NULL;
894     k = strlen (file) - sizeof ".bulk";
895     if ((fp = fopen (file, "r")) == NULL) {
896         (void) sprintf (bp = sm_reply.text, "unable to read %s: ", file);
897         bp += strlen (bp);
898         if (errno > 0 && errno < sys_nerr)
899             (void) sprintf (bp, "%s", sys_errlist[errno]);
900         else
901             (void) sprintf (bp, "Error %d", errno);
902         sm_reply.length = strlen (sm_reply.text);
903         sm_reply.code = NOTOK;
904         return RP_BHST;
905     }
906     if (sm_debug) {
907         printf ("reading file %s\n", file);
908         (void) fflush (stdout);
909     }
910
911     i = j = 0;
912     while (fgets (buffer, sizeof buffer, fp)) {
913         if (j++ == 0)
914             (void) strcpy (sender, buffer + sizeof "MAIL FROM:" - 1);
915         if (strcmp (buffer, "DATA\r\n") == 0) {
916             i = 1;
917             break;
918         }
919     }
920     if (i == 0) {
921         if (sm_debug) {
922             printf ("no DATA...\n");
923             (void) fflush (stdout);
924         }
925 losing0: ;
926         (void) sprintf (buffer, "%s.bad", file);
927         (void) rename (file, buffer);
928         if (gp) {
929             (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
930             (void) unlink (buffer);
931             (void) fclose (gp);
932         }
933         (void) fclose (fp);
934         return RP_OK;
935     }
936     if (j < 3) {
937         if (sm_debug) {
938             printf ("no %srecipients...\n", j < 1 ? "sender or " : "");
939             (void) fflush (stdout);
940         }
941         goto losing0;
942     }
943
944     if ((cp = malloc ((unsigned) (cc = (pos = ftell (fp)) + 1))) == NULL) {
945         sm_reply.length = strlen (strcpy (sm_reply.text, "out of memory"));
946 losing1: ;
947         sm_reply.code = NOTOK;
948         (void) fclose (fp);
949         return RP_BHST;
950     }
951     (void) fseek (fp, 0L, 0);
952     for (dp = cp, i = 0; i++ < j; dp += strlen (dp))
953         if (fgets (dp, cc - (dp - cp), fp) == NULL) {
954             sm_reply.length = strlen (strcpy (sm_reply.text, "premature eof"));
955 losing2: ;
956             free (cp);
957             goto losing1;
958         }
959     *dp = NULL;
960
961     for (dp = cp, i = cc - 1; i > 0; dp += cc, i -= cc)
962         if ((cc = write (fileno (sm_wfp), dp, i)) == NOTOK) {
963 losing3: ;
964             (void) strcpy (bp = sm_reply.text, "error writing to server: ");
965             bp += strlen (bp);
966             if (errno > 0 && errno < sys_nerr)
967                 (void) sprintf (bp, "%s", sys_errlist[errno]);
968             else
969                 (void) sprintf (bp, "Error %d", errno);
970             sm_reply.length = strlen (sm_reply.text);
971             goto losing2;
972         }
973         else
974             if (sm_debug) {
975                 printf ("wrote %d octets to server\n", cc);
976                 (void) fflush (stdout);
977             }
978
979     for (dp = cp, i = 0; i++ < j; dp = index (dp, '\n'), dp++) {
980         if (sm_debug) {
981             if (bp = index (dp, '\r'))
982                 *bp = NULL;
983             printf ("=> %s\n", dp);
984             (void) fflush (stdout);
985             if (bp)
986                 *bp = '\r';
987         }
988
989         switch (smhear () + (i == 1 ? 1000 : i != j ? 2000 : 3000)) {
990             case 1000 + 250:
991                 sm_addrs = 0;
992                 result = RP_OK;
993                 break;
994
995             case 1000 + 500: 
996             case 1000 + 501: 
997             case 1000 + 552: 
998             case 2000 + 500: 
999             case 2000 + 501:
1000                 result = RP_PARM;
1001                 (void) smtalk (SM_RSET, "RSET");
1002                 free (cp);
1003                 goto losing0;
1004
1005             case 2000 + 250:
1006             case 2000 + 251:
1007                 sm_addrs++;
1008                 result = RP_OK;
1009                 break;
1010
1011             case 2000 + 451: 
1012 #ifdef SENDMAILBUG
1013                 sm_addrs++;
1014                 result = RP_OK;
1015                 break;
1016 #endif
1017             case 2000 + 421: 
1018             case 2000 + 450: 
1019             case 2000 + 452: 
1020                 result = RP_NO;
1021                 goto bad_addr;
1022
1023             case 2000 + 550: 
1024             case 2000 + 551: 
1025             case 2000 + 552: 
1026             case 2000 + 553: 
1027                 result = RP_USER;
1028 bad_addr: ;
1029                 if (k <= 0 || strcmp (sender, "<>\r\n") == 0)
1030                     break;
1031                 if (gp == NULL) {
1032                     int     l;
1033                     (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1034                     if ((gp = fopen (buffer, "w+")) == NULL)
1035                         goto bad_data;
1036                     fprintf (gp, "MAIL FROM:<>\r\nRCPT TO:%sDATA\r\n", sender);
1037                     l = strlen (sender);
1038                     fprintf (gp,
1039                              "To: %*.*s\r\nSubject: Invalid addresses (%s)\r\n",
1040                              l - 4, l - 4, sender + 1, file);
1041                     fprintf (gp, "Date: %s\r\nFrom: Postmaster@@%s\r\n\r\n",
1042                              dtimenow (), LocalName ());
1043                 }
1044                 if (bp = index (dp, '\r'))
1045                     *bp = NULL;
1046                 fprintf (gp, "=>        %s\r\n", dp);
1047                 if (bp)
1048                     *bp = '\r';
1049                 fprintf (gp, "<= %s\r\n", rp_string (result));
1050                 (void) fflush (gp);
1051                 break;
1052
1053             case 3000 + 354: 
1054 #ifdef SENDMAILBUG
1055 ok_data: ;
1056 #endif
1057                 result = RP_OK;
1058                 break;
1059
1060             case 3000 + 451: 
1061 #ifdef SENDMAILBUG
1062                 goto ok_data;
1063 #endif
1064             case 3000 + 421:
1065                 result = RP_NO;
1066 bad_data: ;
1067                 (void) smtalk (SM_RSET, "RSET");
1068                 free (cp);
1069                 if (gp) {
1070                     (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1071                     (void) unlink (buffer);
1072                     (void) fclose (gp);
1073                 }
1074                 (void) fclose (fp);
1075                 return result;
1076
1077             case 3000 + 500: 
1078             case 3000 + 501: 
1079             case 3000 + 503: 
1080             case 3000 + 554: 
1081                 (void) smtalk (SM_RSET, "RSET");
1082                 free (cp);
1083                 goto no_dice;
1084
1085             default:
1086                 result = RP_RPLY;
1087                 goto bad_data;
1088         }
1089     }
1090     free (cp);
1091
1092     {
1093         struct stat st;
1094
1095 #ifdef SYS5
1096         cc = BUFSIZ;
1097 #else
1098         if (fstat (fileno (sm_wfp), &st) == NOTOK
1099                 || (cc = st.st_blksize) < BUFSIZ)
1100             cc = BUFSIZ;
1101 #endif
1102         if ((cp = malloc ((unsigned) cc)) == NULL) {
1103             (void) smtalk (SM_RSET, "RSET");
1104             sm_reply.length = strlen (strcpy (sm_reply.text, "out of memory"));
1105             goto losing1;
1106         }
1107     }
1108     (void) fseek (fp, pos, 0);
1109     for (;;) {
1110         int     eof = 0;
1111
1112         for (dp = cp, i = cc; i > 0; dp += j, i -= j)
1113             if ((j = fread (cp, sizeof *cp, i, fp)) == OK) {
1114                 if (ferror (fp)) {
1115                     (void) sprintf (bp = sm_reply.text,
1116                                     "error reading %s: ", file);
1117                     bp += strlen (bp);
1118                     if (errno > 0 && errno < sys_nerr)
1119                         (void) sprintf (bp, "%s", sys_errlist[errno]);
1120                     else
1121                         (void) sprintf (bp, "Error %d", errno);
1122                     sm_reply.length = strlen (sm_reply.text);
1123                     goto losing2;
1124                 }
1125                 cc = dp - cp;
1126                 eof = 1;
1127                 break;
1128             }
1129
1130         for (dp = cp, i = cc; i > 0; dp += j, i -= j)
1131             if ((j = write (fileno (sm_wfp), dp, i)) == NOTOK)
1132                 goto losing3;
1133             else
1134                 if (sm_debug) {
1135                     printf ("wrote %d octets to server\n", j);
1136                     (void) fflush (stdout);
1137                 }
1138
1139         if (eof)
1140             break;
1141     }
1142     free (cp);
1143
1144     switch (smhear ()) {
1145         case 250: 
1146         case 251: 
1147 #ifdef SENDMAILBUG
1148 ok_dot: ;
1149 #endif
1150             result = RP_OK;
1151             (void) unlink (file);
1152             break;
1153
1154         case 451: 
1155 #ifdef SENDMAILBUG
1156             goto ok_dot;
1157 #endif
1158         case 452: 
1159         default: 
1160             result = RP_NO;
1161             if (gp) {
1162                 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1163                 (void) unlink (buffer);
1164                 (void) fclose (gp);
1165                 gp = NULL;
1166             }
1167             break;
1168
1169         case 552: 
1170         case 554: 
1171 no_dice: ;
1172             result = RP_NDEL;
1173             if (k <= 0 || strcmp (sender, "<>\r\n") == 0) {
1174                 (void) unlink (file);
1175                 break;
1176             }
1177             if (gp) {
1178                 (void) fflush (gp);
1179                 (void) ftruncate (fileno (gp), 0L);
1180                 (void) fseek (gp, 0L, 0);
1181             }
1182             else {
1183                 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1184                 if ((gp = fopen (buffer, "w")) == NULL)
1185                     break;
1186             }
1187             fprintf (gp, "MAIL FROM:<>\r\nRCPT TO:%sDATA\r\n", sender);
1188             i = strlen (sender);
1189             fprintf (gp, "To: %*.*s\r\nSubject: Failed mail (%s)\r\n",
1190                      i - 4, i - 4, sender + 1, file);
1191             fprintf (gp, "Date: %s\r\nFrom: Postmaster@@%s\r\n\r\n",
1192                      dtimenow (), LocalName ());
1193             break;
1194     }
1195
1196     if (gp) {
1197         (void) fputs ("\r\n------- Begin Returned message\r\n\r\n", gp);
1198         (void) fseek (fp, pos, 0);
1199         while (fgets (buffer, sizeof buffer, fp)) {
1200             if (buffer[0] == '-')
1201                 (void) fputs ("- ", gp);
1202             if (strcmp (buffer, ".\r\n"))
1203                 (void) fputs (buffer, gp);
1204         }
1205         (void) fputs ("\r\n------- End Returned Message\r\n\r\n.\r\n", gp);
1206         (void) fflush (gp);
1207         if (!ferror (gp))
1208             (void) unlink (file);
1209         (void) fclose (gp);
1210     }
1211     (void) fclose (fp);
1212
1213     return result;
1214 }
1215 #endif
1216 #endif /* MPOP */
1217
1218 /* \f */
1219
1220 /* VARARGS */
1221
1222 static int  sm_ierror (fmt, a, b, c, d)
1223 char   *fmt,
1224        *a,
1225        *b,
1226        *c,
1227        *d;
1228 {
1229     (void) sprintf (sm_reply.text, fmt, a, b, c, d);
1230     sm_reply.length = strlen (sm_reply.text);
1231     sm_reply.code = NOTOK;
1232
1233     return RP_BHST;
1234 }
1235
1236 /* \f */
1237
1238 /* VARARGS2 */
1239
1240 static int  smtalk (time, fmt, a, b, c, d)
1241 register int     time;
1242 register char   *fmt;
1243 register char   *a, *b, *c, *d;
1244 {
1245     register int    result;
1246     char    buffer[BUFSIZ];
1247
1248     (void) sprintf (buffer, fmt, a, b, c, d);
1249     if (sm_debug) {
1250         printf ("=> %s\n", buffer);
1251         (void) fflush (stdout);
1252     }
1253
1254 #ifdef  MPOP
1255     if (sm_ispool) {
1256         char    file[BUFSIZ];
1257
1258         if (strcmp (buffer, ".") == 0)
1259             time = SM_DOT;
1260         fprintf (sm_wfp, "%s\r\n", buffer);
1261         switch (time) {
1262             case SM_DOT:
1263                 (void) fflush (sm_wfp);
1264                 if (ferror (sm_wfp))
1265                     return sm_werror ();
1266                 (void) sprintf (file, "%s%c.bulk", sm_tmpfil,
1267                                 (char) (sm_ispool + 'a' - 1));
1268                 if (rename (sm_tmpfil, file) == NOTOK) {
1269                     char   *bp;
1270                     (void) sprintf (bp = sm_reply.text,
1271                                     "error renaming %s to %s: ",
1272                                     sm_tmpfil, file);
1273                     bp += strlen (bp);
1274                     if (errno > 0 && errno < sys_nerr)
1275                         (void) sprintf (bp, "%s", sys_errlist[errno]);
1276                     else
1277                         (void) sprintf (bp, "Error %d", errno);
1278                     sm_reply.length = strlen (sm_reply.text);
1279                     sm_reply.code = NOTOK;
1280                     return RP_BHST;
1281                 }
1282                 (void) fclose (sm_wfp);
1283                 if (sm_wfp = fopen (sm_tmpfil, "w"))
1284                     (void) chmod (sm_tmpfil, 0600);
1285                 sm_ispool++;
1286                 /* and fall... */
1287
1288             case SM_MAIL:
1289             case SM_RCPT:
1290                 result = 250;
1291                 break;
1292
1293             case SM_RSET:
1294                 (void) fflush (sm_wfp);
1295                 (void) ftruncate (fileno (sm_wfp), 0L);
1296                 (void) fseek (sm_wfp, 0L, 0);
1297                 result = 250;
1298                 break;
1299
1300             case SM_DATA:
1301                 result = 354;
1302                 break;
1303
1304             case SM_QUIT:
1305                 (void) unlink (sm_tmpfil);
1306                 sm_ispool = 0;
1307                 result = 221;
1308                 break;
1309
1310             default:
1311                 result = 500;
1312                 break;
1313         }
1314         if (sm_debug) {
1315             printf ("<= %d\n", result);
1316             (void) fflush (stdout);
1317         }
1318
1319         sm_reply.text[sm_reply.length = 0] = NULL;
1320         return (sm_reply.code = result);
1321     }
1322 #endif /* MPOP */
1323
1324     sm_alarmed = 0;
1325     (void) alarm ((unsigned) time);
1326     if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK)
1327         result = smhear ();
1328     (void) alarm (0);
1329
1330     return result;
1331 }
1332
1333 /* \f */
1334
1335 static int  sm_wrecord (buffer, len)
1336 register char   *buffer;
1337 register int     len;
1338 {
1339     if (sm_wfp == NULL)
1340         return sm_werror ();
1341
1342     (void) fwrite (buffer, sizeof *buffer, len, sm_wfp);
1343     (void) fputs ("\r\n", sm_wfp);
1344     (void) fflush (sm_wfp);
1345
1346     return (ferror (sm_wfp) ? sm_werror () : OK);
1347 }
1348
1349 /* \f */
1350
1351 static int  sm_wstream (buffer, len)
1352 register char   *buffer;
1353 register int     len;
1354 {
1355     register char  *bp;
1356     static char lc = 0;
1357
1358     if (sm_wfp == NULL)
1359         return sm_werror ();
1360
1361     if (buffer == NULL && len == 0) {
1362         if (lc != '\n')
1363             (void) fputs ("\r\n", sm_wfp);
1364         lc = 0;
1365         return (ferror (sm_wfp) ? sm_werror () : OK);
1366     }
1367
1368     for (bp = buffer; len > 0; bp++, len--) {
1369         switch (*bp) {
1370             case '\n': 
1371                 sm_nl = TRUE;
1372                 (void) fputc ('\r', sm_wfp);
1373                 break;
1374
1375             case '.': 
1376                 if (sm_nl)
1377                     (void) fputc ('.', sm_wfp);/* FALL THROUGH */
1378             default: 
1379                 sm_nl = FALSE;
1380         }
1381         (void) fputc (*bp, sm_wfp);
1382         if (ferror (sm_wfp))
1383             return sm_werror ();
1384     }
1385
1386     if (bp > buffer)
1387         lc = *--bp;
1388     return (ferror (sm_wfp) ? sm_werror () : OK);
1389 }
1390
1391 /* \f */
1392
1393 #ifdef _AIX
1394 /*
1395  * AIX by default will inline the strlen and strcpy commands by redefining
1396  * them as __strlen and __strcpy respectively.  This causes compile problems
1397  * with the #ifdef MPOP in the middle.  Should the #ifdef MPOP be removed,
1398  * remove these #undefs.
1399  */
1400 #undef strlen
1401 #undef strcpy
1402 #endif /* _AIX */
1403
1404 static int  sm_werror () {
1405     sm_reply.length =
1406 #ifdef  SMTP
1407         strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened"
1408             : sm_alarmed ? "write to socket timed out"
1409 #ifdef  MPOP
1410             : sm_ispool ? "error writing to spool file"
1411 #endif
1412             : "error writing to socket"));
1413 #else   /* !SMTP */
1414         strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no pipe opened"
1415             : sm_alarmed ? "write to pipe timed out"
1416             : "error writing to pipe"));
1417 #endif  /* !SMTP */
1418
1419     return (sm_reply.code = NOTOK);
1420 }
1421
1422 /* \f */
1423
1424 static int  smhear () {
1425     register int    i,
1426                     code,
1427                     cont,
1428                     rc,
1429                     more;
1430     int     bc;
1431     register char  *bp,
1432                    *rp;
1433     char  **ehlo,
1434             buffer[BUFSIZ];
1435
1436     if (doingEHLO) {
1437         static  int     at_least_once = 0;
1438
1439         if (at_least_once) {
1440             char   *ep;
1441
1442             for (ehlo = EHLOkeys; ep = *ehlo; ehlo++)
1443                 free (ep);
1444         }
1445         else
1446             at_least_once = 1;
1447
1448         *(ehlo = EHLOkeys) = NULL;
1449     }
1450
1451 again: ;
1452
1453     sm_reply.text[sm_reply.length = 0] = 0;
1454
1455     rp = sm_reply.text, rc = sizeof sm_reply.text - 1;
1456     for (more = FALSE; sm_rrecord (bp = buffer, &bc) != NOTOK;) {
1457         if (sm_debug) {
1458             printf ("<= %s\n", buffer);
1459             (void) fflush (stdout);
1460         }
1461
1462         if (doingEHLO
1463                 && strncmp (buffer, "250", sizeof "250" - 1) == 0
1464                 && (buffer[3] == '-' || doingEHLO == 2)
1465                 && buffer[4]) {
1466             if (doingEHLO == 2) {
1467                 int     len = strlen (buffer + 4);
1468
1469                 if (*ehlo = malloc ((unsigned) (strlen (buffer + 4) + 1))) {
1470                     (void) strcpy (*ehlo++, buffer + 4);
1471                     *ehlo = NULL;
1472                     if (ehlo >= EHLOkeys + MAXEHLO)
1473                         doingEHLO = 0;
1474                 }
1475                 else
1476                     doingEHLO = 0;
1477             }
1478             else
1479                 doingEHLO = 2;
1480         }
1481
1482         for (; bc > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, bc--)
1483             continue;
1484
1485         cont = FALSE;
1486         code = atoi (bp);
1487         bp += 3, bc -= 3;
1488         for (; bc > 0 && isspace (*bp); bp++, bc--)
1489             continue;
1490         if (bc > 0 && *bp == '-') {
1491             cont = TRUE;
1492             bp++, bc--;
1493             for (; bc > 0 && isspace (*bp); bp++, bc--)
1494                 continue;
1495         }
1496
1497         if (more) {
1498             if (code != sm_reply.code || cont)
1499                 continue;
1500             more = FALSE;
1501         }
1502         else {
1503             sm_reply.code = code;
1504             more = cont;
1505             if (bc <= 0) {
1506                 (void) strcpy (bp = buffer, sm_noreply);
1507                 bc = strlen (sm_noreply);
1508             }
1509         }
1510         if ((i = min (bc, rc)) > 0) {
1511             (void) strncpy (rp, bp, i);
1512             rp += i, rc -= i;
1513             if (more && rc > strlen (sm_moreply) + 1) {
1514                 (void) strcpy (sm_reply.text + rc, sm_moreply);
1515                 rc += strlen (sm_moreply);
1516             }
1517         }
1518         if (more)
1519             continue;
1520         if (sm_reply.code < 100) {
1521             if (sm_verbose) {
1522                 printf ("%s\n", sm_reply.text);
1523                 (void) fflush (stdout);
1524             }
1525             goto again;
1526         }
1527
1528         sm_reply.length = rp - sm_reply.text;
1529
1530         return sm_reply.code;
1531     }
1532
1533     return NOTOK;
1534 }
1535
1536 /* \f */
1537
1538 static int  sm_rrecord (buffer, len)
1539 register char   *buffer;
1540 register int    *len;
1541 {
1542     if (sm_rfp == NULL)
1543         return sm_rerror ();
1544
1545     buffer[*len = 0] = 0;
1546
1547     (void) fgets (buffer, BUFSIZ, sm_rfp);
1548     *len = strlen (buffer);
1549     if (ferror (sm_rfp) || feof (sm_rfp))
1550         return sm_rerror ();
1551     if (buffer[*len - 1] != '\n')
1552         while (getc (sm_rfp) != '\n' && !ferror (sm_rfp) && !feof (sm_rfp))
1553             continue;
1554     else
1555         if (buffer[*len - 2] == '\r')
1556             *len -= 1;
1557     buffer[*len - 1] = 0;
1558
1559     return OK;
1560 }
1561
1562 /* \f */
1563
1564 static int  sm_rerror () {
1565     sm_reply.length =
1566 #ifdef  SMTP
1567         strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no socket opened"
1568             : sm_alarmed ? "read from socket timed out"
1569             : feof (sm_rfp) ? "premature end-of-file on socket"
1570             : "error reading from socket"));
1571 #else   /* not SMTP */
1572         strlen (strcpy (sm_reply.text, sm_rfp == NULL ? "no pipe opened"
1573             : sm_alarmed ? "read from pipe timed out"
1574             : feof (sm_rfp) ? "premature end-of-file on pipe"
1575             : "error reading from pipe"));
1576 #endif  /* not SMTP */
1577
1578     return (sm_reply.code = NOTOK);
1579 }
1580
1581 /* \f */
1582
1583 /* ARGSUSED */
1584
1585 static  TYPESIG alrmser (i)
1586 int     i;
1587 {
1588 #ifndef BSD42
1589     signal (SIGALRM, alrmser);
1590 #endif  /* BSD42 */
1591     sm_alarmed++;
1592
1593     if (sm_debug) {
1594         printf ("timed out...\n");
1595         (void) fflush (stdout);
1596     }
1597 }
1598
1599 /* \f */
1600
1601 char   *rp_string (code)
1602 register int     code;
1603 {
1604     register char  *text;
1605     static char buffer[BUFSIZ];
1606
1607     switch (sm_reply.code != NOTOK ? code : NOTOK) {
1608         case RP_AOK:
1609             text = "AOK";
1610             break;
1611
1612         case RP_MOK:
1613             text = "MOK";
1614             break;
1615
1616         case RP_OK: 
1617             text = "OK";
1618             break;
1619
1620         case RP_RPLY: 
1621             text = "RPLY";
1622             break;
1623
1624         case RP_BHST: 
1625         default: 
1626             text = "BHST";
1627             (void) sprintf (buffer, "[%s] %s", text, sm_reply.text);
1628             return buffer;
1629
1630         case RP_PARM: 
1631             text = "PARM";
1632             break;
1633
1634         case RP_NO: 
1635             text = "NO";
1636             break;
1637
1638         case RP_USER: 
1639             text = "USER";
1640             break;
1641
1642         case RP_NDEL: 
1643             text = "NDEL";
1644             break;
1645     }
1646
1647     (void) sprintf (buffer, "[%s] %3d %s", text, sm_reply.code, sm_reply.text);
1648     return buffer;
1649 }
1650
1651 /* \f */
1652
1653 #ifdef  SMTP
1654 static char *broken[MAXARGS + 1];
1655
1656
1657 static char **brkstring (strg, brksep, brkterm)
1658 register char  *strg;
1659 register char  *brksep,
1660                *brkterm;
1661 {
1662     register int    bi;
1663     register char   c,
1664                    *sp;
1665
1666     sp = strg;
1667
1668     for (bi = 0; bi < MAXARGS; bi++) {
1669         while (brkany (c = *sp, brksep))
1670             *sp++ = 0;
1671         if (!c || brkany (c, brkterm)) {
1672             *sp = 0;
1673             broken[bi] = 0;
1674             return broken;
1675         }
1676
1677         broken[bi] = sp;
1678         while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm))
1679             continue;
1680     }
1681     broken[MAXARGS] = 0;
1682
1683     return broken;
1684 }
1685
1686
1687 static  brkany (chr, strg)
1688 register char   chr,
1689                *strg;
1690 {
1691     register char  *sp;
1692
1693     if (strg)
1694         for (sp = strg; *sp; sp++)
1695             if (chr == *sp)
1696                 return 1;
1697     return 0;
1698 }
1699
1700
1701 static char **copyip (p, q)
1702 register char **p,
1703               **q;
1704 {
1705     while (*p)
1706         *q++ = *p++;
1707     *q = 0;
1708
1709     return q;
1710 }
1711 #endif
1712
1713 /* \f */
1714
1715 char *EHLOset (s)
1716 char *s;
1717 {
1718     int     len = strlen (s);
1719     register char  *ep,
1720                  **ehlo;
1721
1722     for (ehlo = EHLOkeys; ep = *ehlo; ehlo++)
1723         if (strncmp (ep, s, len) == 0) {
1724             for (ep += len; *ep == ' '; ep++)
1725                 continue;
1726             return ep;
1727         }
1728
1729     return 0;
1730 }
1731 @
1732
1733
1734 1.29
1735 log
1736 @64bit fix
1737 @
1738 text
1739 @d3 1
1740 a3 1
1741 static char ident[] = "@@(#)$Id: smail.c,v 1.28 1994/03/23 23:24:51 jromine Exp jromine $";
1742 a120 1
1743 extern  char  **brkstring (), **copyip (), *getcpy ();
1744 a122 1
1745
1746 d130 8
1747 d297 3
1748 d301 5
1749 d331 7
1750 a337 1
1751     if ((sd1 = rclient (server, "tcp", "smtp")) == NOTOK)
1752 d380 1
1753 a380 1
1754         default: 
1755 d382 4
1756 a418 4
1757 #ifdef  MPOP
1758 #define MAXARGS 1000
1759 #endif /* MPOP */
1760
1761 a1485 1
1762 #ifdef  MPOP
1763 a1544 1
1764 #endif /* MPOP */
1765 @
1766
1767
1768 1.28
1769 log
1770 @clientname fix
1771 @
1772 text
1773 @d3 1
1774 a3 1
1775 static char ident[] = "@@(#)$Id: smail.c,v 1.27 1993/12/01 03:50:31 jromine Exp jromine $";
1776 d1056 1
1777 @
1778
1779
1780 1.27
1781 log
1782 @fixes from mtr
1783 @
1784 text
1785 @d3 1
1786 a3 1
1787 static char ident[] = "@@(#)$Id: smail.c,v 1.26 1993/09/01 20:55:22 jromine Exp jromine $";
1788 d308 4
1789 a311 1
1790         client = clientname;
1791 a314 5
1792 #else
1793 #if     !defined(SENDMTS) || defined(MMDFII) || defined(SVR4)
1794     if (client == NULL || *client == 0)
1795         client = LocalName ();
1796 #endif
1797 @
1798
1799
1800 1.26
1801 log
1802 @add clientname tailor option
1803 @
1804 text
1805 @d3 1
1806 a3 1
1807 static char ident[] = "@@(#)$Id: smail.c,v 1.25 1993/08/25 17:17:29 jromine Exp jromine $";
1808 d116 1
1809 a116 1
1810 extern  int     errno
1811 @
1812
1813
1814 1.25
1815 log
1816 @off_t fixes for BSD44
1817 @
1818 text
1819 @d3 1
1820 a3 1
1821 static char ident[] = "@@(#)$Id: smail.c,v 1.24 1993/08/20 16:14:30 jromine Exp jromine $";
1822 d165 2
1823 d307 2
1824 @
1825
1826
1827 1.24
1828 log
1829 @don't use ONEX with ZMAILER
1830 @
1831 text
1832 @d3 1
1833 a3 1
1834 static char ident[] = "@@(#)$Id: smail.c,v 1.23 1993/08/20 15:47:14 jromine Exp jromine $";
1835 d116 3
1836 a118 1
1837 extern  int     errno, sys_nerr;
1838 d120 1
1839 @
1840
1841
1842 1.23
1843 log
1844 @fixes from mtr
1845 remove SMTP_ONEX
1846 @
1847 text
1848 @d3 1
1849 a3 1
1850 static char ident[] = "@@(#)$Id: smail.c,v 1.22 1993/08/19 23:35:31 jromine Exp jromine $";
1851 d260 1
1852 d263 1
1853 @
1854
1855
1856 1.22
1857 log
1858 @enable ONEX only with "options SMTP_ONEX"
1859 @
1860 text
1861 @d3 1
1862 a3 1
1863 static char ident[] = "@@(#)$Id: smail.c,v 1.21 1992/11/09 18:19:32 jromine Exp jromine $";
1864 d121 8
1865 d135 8
1866 a142 6
1867 int     sm_init (client, server, watch, verbose, debug)
1868 register char   *client;
1869 char   *server;
1870 register int     watch,
1871                  verbose,
1872                  debug;
1873 d161 1
1874 d199 1
1875 a199 1
1876             vec[vecp++] = watch ? "-odi" : "-odb";
1877 a240 9
1878 #ifdef SMTP_ONEX
1879             (void) smtalk(SM_HELO, "ONEX");
1880 #endif
1881             if (watch)
1882                 (void) smtalk(SM_HELO, "VERB on");
1883             if (client && *client)
1884                 switch (smtalk (SM_HELO, "HELO %s", client)) {
1885                     case 250: 
1886                         break;
1887 d242 13
1888 a254 1
1889                     default: 
1890 d258 7
1891 d272 8
1892 a279 6
1893 int     sm_init (client, server, watch, verbose, debug)
1894 register char   *client,
1895                 *server;
1896 register int     watch,
1897                  verbose,
1898                  debug;
1899 d286 3
1900 a288 1
1901 #if defined(SUN40) && !defined(MMDFII)
1902 a289 2
1903 #else
1904         verbose = TRUE;
1905 d293 4
1906 d298 2
1907 a299 1
1908         return RP_OK;
1909 d308 1
1910 a308 1
1911 #endif  /* ZMAILER */
1912 a309 4
1913 #ifdef  MPOP
1914     if (sm_ispool)
1915         goto all_done;
1916 #endif
1917 d357 10
1918 a366 9
1919 #ifdef  SMTP_ONEX
1920     (void) smtalk(SM_HELO, "ONEX");
1921 #endif
1922 #ifndef MMDFII
1923     if (watch)
1924         (void) smtalk(SM_HELO, "VERB on");
1925 #endif
1926     if (client && *client)
1927         switch (smtalk (SM_HELO, "HELO %s", client)) {
1928 d374 1
1929 d376 8
1930 d1238 2
1931 a1239 1
1932     char    buffer[BUFSIZ];
1933 d1241 15
1934 d1267 20
1935 d1334 1
1936 d1519 19
1937 @
1938
1939
1940 1.21
1941 log
1942 @force on -snoop under SUN40 only
1943 @
1944 text
1945 @d3 1
1946 a3 1
1947 static char ident[] = "@@(#)$Id: smail.c,v 1.20 1992/11/06 18:04:48 jromine Exp jromine $";
1948 d230 1
1949 a230 1
1950 #ifndef ZMAILER
1951 d232 1
1952 a232 1
1953 #endif /* not ZMAILER */
1954 d333 1
1955 a333 1
1956 #if     !(defined(ZMAILER) || defined(MMDFII))
1957 d335 1
1958 a335 1
1959 #endif /* not ZMAILER */
1960 @
1961
1962
1963 1.20
1964 log
1965 @have -watch imply -snoop under SendMail
1966 #endif sugar
1967 @
1968 text
1969 @d3 1
1970 a3 1
1971 static char ident[] = "@@(#)$Id: smail.c,v 1.19 1992/11/06 17:26:22 jromine Exp jromine $";
1972 d142 1
1973 a142 1
1974 #ifdef  notdef
1975 d263 3
1976 a265 1
1977 #ifdef  MMDFII
1978 a266 2
1979 #else
1980         debug = verbose = TRUE;
1981 @
1982
1983
1984 1.19
1985 log
1986 @define TYPESIG
1987 @
1988 text
1989 @d3 2
1990 a4 2
1991 static char ident[] = "@@(#)$Id: smail.c,v 1.18 1992/11/02 18:55:04 jromine Exp jromine $";
1992 #endif  lint
1993 d19 1
1994 a19 1
1995 #endif  BSD42
1996 d31 2
1997 a32 2
1998 #endif  not SENDMAIL
1999 #endif  SENDMAILBUG
2000 d37 1
2001 a37 1
2002 #endif hpux
2003 d41 1
2004 a41 1
2005 #endif  not BSD42 and not SOCKETS
2006 d44 1
2007 a44 1
2008 #endif  SMTP
2009 d90 1
2010 a90 1
2011 #endif  not SMTP
2012 d142 1
2013 d144 3
2014 d194 2
2015 a195 2
2016 #endif  not RAND
2017 #endif  not ZMAILER
2018 d247 1
2019 a247 1
2020 #else   SMTP
2021 d263 1
2022 d265 3
2023 d335 1
2024 a335 1
2025 #endif not ZMAILER
2026 d404 1
2027 a404 1
2028 #endif  SMTP
2029 d442 1
2030 a442 1
2031 #endif  BERK
2032 d448 1
2033 a448 1
2034 #endif  not BERK
2035 d456 1
2036 a456 1
2037 #else   BERK
2038 d458 1
2039 a458 1
2040 #endif  BERK
2041 d468 1
2042 a468 1
2043 #endif SENDMAILBUG
2044 d501 1
2045 a501 1
2046 #endif SENDMAILBUG
2047 d546 1
2048 a546 1
2049 #endif SENDMAILBUG
2050 d574 1
2051 a574 1
2052 #endif  not SMTP
2053 d594 1
2054 a594 1
2055 #else   SMTP
2056 d596 1
2057 a596 1
2058 #endif  not SMTP
2059 d632 1
2060 a632 1
2061 #else   SMTP
2062 d634 1
2063 a634 1
2064 #endif  SMTP
2065 d1305 1
2066 a1305 1
2067 #else   not SMTP
2068 d1310 1
2069 a1310 1
2070 #endif  not SMTP
2071 d1324 1
2072 a1324 1
2073 #endif  BSD42
2074 @
2075
2076
2077 1.18
2078 log
2079 @_AIX fixes from Bill Wohler
2080 @
2081 text
2082 @d3 1
2083 a3 1
2084 static char ident[] = "@@(#)$Id: smail.c,v 1.17 1992/10/26 22:42:56 jromine Exp jromine $";
2085 d53 4
2086 @
2087
2088
2089 1.17
2090 log
2091 @TYPESIG alrmser
2092 @
2093 text
2094 @d3 1
2095 a3 1
2096 static char ident[] = "@@(#)$Id: smail.c,v 1.16 1992/10/26 16:39:18 jromine Exp jromine $";
2097 d1151 11
2098 @
2099
2100
2101 1.16
2102 log
2103 @#ifdef MPOP reversed.
2104 @
2105 text
2106 @d3 1
2107 a3 1
2108 static char ident[] = "@@(#)$Id: smail.c,v 1.15 1992/10/21 03:27:12 jromine Exp jromine $";
2109 d80 1
2110 a80 1
2111 static int      alrmser ();
2112 d1296 1
2113 a1296 1
2114 static  int alrmser (i)
2115 @
2116
2117
2118 1.15
2119 log
2120 @-watch shows SMTP transaction, not -verbose
2121 @
2122 text
2123 @d3 1
2124 a3 1
2125 static char ident[] = "@@(#)$Id: smail.c,v 1.14 1992/10/21 03:26:43 jromine Exp jromine $";
2126 d111 1
2127 a111 1
2128 #ifndef MPOP
2129 @
2130
2131
2132 1.14
2133 log
2134 @fixup #ifdef's ZMAILER, MPOP
2135 @
2136 text
2137 @d3 1
2138 a3 1
2139 static char ident[] = "@@(#)$Id: smail.c,v 1.13 1992/10/20 15:36:40 jromine Exp jromine $";
2140 d225 1
2141 a225 1
2142             if (verbose)
2143 d325 1
2144 a325 1
2145     if (verbose)
2146 @
2147
2148
2149 1.13
2150 log
2151 @ifdef MPOP
2152 @
2153 text
2154 @d3 1
2155 a3 1
2156 static char ident[] = "@@(#)$Id: smail.c,v 1.12 1992/10/16 16:51:15 jromine Exp jromine $";
2157 d111 1
2158 a111 1
2159
2160 d115 1
2161 d260 4
2162 a266 5
2163 #else
2164 #ifdef ZMAILER
2165     if (client == NULL || *client == '\0')
2166         client = "localhost";
2167 #endif ZMAILER
2168 d268 1
2169 d273 1
2170 d276 1
2171 @
2172
2173
2174 1.12
2175 log
2176 @mobile pop ifdef's (MPOP)
2177 @
2178 text
2179 @d3 1
2180 a3 1
2181 static char ident[] = "@@(#)$Id: smail.c,v 1.11 1992/03/03 17:11:03 jromine Exp jromine $";
2182 d1154 1
2183 d1156 1
2184 d1158 1
2185 a1158 1
2186 #else   not SMTP
2187 d1162 1
2188 a1162 1
2189 #endif  not SMTP
2190 @
2191
2192
2193 1.11
2194 log
2195 @fix from mtr
2196 @
2197 text
2198 @d3 1
2199 a3 1
2200 static char ident[] = "@@(#)$Id: smail.c,v 1.10 1992/03/03 17:09:57 jromine Exp jromine $";
2201 d94 1
2202 d97 1
2203 d269 1
2204 d290 1
2205 d339 1
2206 d341 1
2207 d349 4
2208 a352 2
2209     char   *cp,
2210             response[BUFSIZ];
2211 d357 1
2212 d384 1
2213 d397 1
2214 d404 1
2215 d589 1
2216 d601 1
2217 d627 1
2218 d852 3
2219 d858 1
2220 d973 1
2221 d1010 1
2222 d1078 1
2223 d1359 1
2224 d1419 1
2225 @
2226
2227
2228 1.10
2229 log
2230 @fixes from mtr
2231 @
2232 text
2233 @d3 1
2234 a3 1
2235 static char ident[] = "@@(#)$Id: smail.c,v 1.9 1992/02/10 18:12:35 jromine Exp jromine $";
2236 d109 5
2237 a335 5
2238
2239 extern  int     errno, sys_nerr;
2240 extern  char   *sys_errlist[];
2241 extern  char  **brkstring (), **copyip (), *getcpy ();
2242
2243 @
2244
2245
2246 1.9
2247 log
2248 @some SVR4 changes
2249 add "localdomain" tailor option
2250 @
2251 text
2252 @d3 1
2253 a3 1
2254 static char ident[] = "@@(#)$Id: smail.c,v 1.8 1992/02/05 22:10:36 jromine Exp jromine $";
2255 d66 1
2256 d73 3
2257 a75 3
2258 #define SM_TEXT 120
2259 #define SM_DOT  120
2260 #define SM_QUIT  20
2261 d94 3
2262 d262 2
2263 d266 16
2264 d330 7
2265 d343 2
2266 a344 1
2267     char    response[BUFSIZ];
2268 d349 27
2269 d387 7
2270 d577 11
2271 d613 344
2272 d990 68
2273 d1077 1
2274 a1077 1
2275     fputs ("\r\n", sm_wfp);
2276 d1097 1
2277 a1097 1
2278             fputs ("\r\n", sm_wfp);
2279 d1132 1
2280 d1334 62
2281 @
2282
2283
2284 1.8
2285 log
2286 @add zmailer support
2287 @
2288 text
2289 @d3 1
2290 a3 1
2291 static char ident[] = "@@(#)$Id: smail.c,v 1.7 1992/01/31 21:40:09 jromine Exp jromine $";
2292 d212 1
2293 a212 1
2294 #endif not ZMAILER
2295 d248 2
2296 a249 2
2297 #if     !defined(SENDMTS) || defined(MMDFII)
2298     if (client == NULL || *client == NULL)
2299 d287 1
2300 a287 1
2301 #ifndef ZMAILER
2302 d290 1
2303 d293 1
2304 @
2305
2306
2307 1.7
2308 log
2309 @kerberos
2310 @
2311 text
2312 @d3 1
2313 a3 1
2314 static char ident[] = "@@(#)$Id: smail.c,v 1.6 1990/04/05 15:30:07 sources Exp jromine $";
2315 d131 4
2316 d167 1
2317 d175 1
2318 d210 5
2319 d251 5
2320 d287 5
2321 @
2322
2323
2324 1.6
2325 log
2326 @add ID
2327 @
2328 text
2329 @d3 1
2330 a3 1
2331 static char ident[] = "@@(#)$Id:$";
2332 d580 1
2333 a580 1
2334     static char lc = NULL;
2335 d588 1
2336 a588 1
2337         lc = NULL;
2338 d647 1
2339 a647 1
2340     sm_reply.text[sm_reply.length = 0] = NULL;
2341 d718 1
2342 a718 1
2343     buffer[*len = 0] = NULL;
2344 d730 1
2345 a730 1
2346     buffer[*len - 1] = NULL;
2347 @
2348
2349
2350 1.5
2351 log
2352 @add ID
2353 @
2354 text
2355 @d3 1
2356 a3 1
2357 static char ident[] = "$Id:";
2358 @
2359
2360
2361 1.4
2362 log
2363 @ANSI Compilance
2364 @
2365 text
2366 @d2 3
2367 @
2368
2369
2370 1.3
2371 log
2372 @SOCKETS
2373 @
2374 text
2375 @d76 1
2376 a76 1
2377 int     alrmser ();
2378 d98 3
2379 @
2380
2381
2382 1.2
2383 log
2384 @raise SMTP open timeout to 90 secs for slow systems
2385 #define BSD42 #ifdef hpux, so HPUX systems can use SMTP
2386 #ifdef SENDMAILBUG consider 451 SMTP reply codes the same as 250.
2387 @
2388 text
2389 @d36 1
2390 a36 1
2391 #ifndef BSD42
2392 d38 1
2393 a38 1
2394 #endif  not BSD42
2395 @
2396
2397
2398 1.1
2399 log
2400 @Initial revision
2401 @
2402 text
2403 @d17 13
2404 d31 5
2405 d63 1
2406 a63 1
2407 #define SM_OPEN  30
2408 d344 5
2409 a350 1
2410         case 451: 
2411 d377 5
2412 a382 1
2413         case 451: 
2414 d424 3
2415 @