9 date 96.02.09.23.05.06; author jromine; state Exp;
14 date 95.12.06.22.29.38; author jromine; state Exp;
19 date 94.03.23.23.24.51; author jromine; state Exp;
24 date 93.12.01.03.50.31; author jromine; state Exp;
29 date 93.09.01.20.55.22; author jromine; state Exp;
34 date 93.08.25.17.17.29; author jromine; state Exp;
39 date 93.08.20.16.14.30; author jromine; state Exp;
44 date 93.08.20.15.47.14; author jromine; state Exp;
49 date 93.08.19.23.35.31; author jromine; state Exp;
54 date 92.11.09.18.19.32; author jromine; state Exp;
59 date 92.11.06.18.04.48; author jromine; state Exp;
64 date 92.11.06.17.26.22; author jromine; state Exp;
69 date 92.11.02.18.55.04; author jromine; state Exp;
74 date 92.10.26.22.42.56; author jromine; state Exp;
79 date 92.10.26.16.39.18; author jromine; state Exp;
84 date 92.10.21.03.27.12; author jromine; state Exp;
89 date 92.10.21.03.26.43; author jromine; state Exp;
94 date 92.10.20.15.36.40; author jromine; state Exp;
99 date 92.10.16.16.51.15; author jromine; state Exp;
104 date 92.03.03.17.11.03; author jromine; state Exp;
109 date 92.03.03.17.09.57; author jromine; state Exp;
114 date 92.02.10.18.12.35; author jromine; state Exp;
119 date 92.02.05.22.10.36; author jromine; state Exp;
124 date 92.01.31.21.40.09; author jromine; state Exp;
129 date 90.04.05.15.30.07; author sources; state Exp;
134 date 90.04.05.14.43.29; author sources; state Exp;
139 date 90.02.06.12.58.44; author sources; state Exp;
144 date 90.02.05.14.56.10; author sources; state Exp;
149 date 90.02.01.14.00.49; author sources; state Exp;
154 date 90.02.01.13.39.06; author sources; state Exp;
165 @loop over servers when initial response is bad
168 @/* smail.c - MH interface to SendMail/SMTP */
170 static char ident[] = "@@(#)$Id: smail.c,v 1.29 1995/12/06 22:29:38 jromine Exp jromine $";
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.
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...
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!
198 #endif /* not SENDMAIL */
199 #endif /* SENDMAILBUG */
202 /* HP-UX has this capability. It also handles (some) signals. */
206 #if !defined(BSD42) && !defined(SOCKETS)
208 #endif /* not BSD42 and not SOCKETS */
214 #include "../h/strings.h"
217 #include "../zotnet/mts.h"
232 #define NBITS ((sizeof (int)) * 8)
234 #define min(a,b) ((a) < (b) ? (a) : (b))
237 /* these codes must all be different! */
238 #define SM_OPEN 90 /* Changed from 30 in case of nameserver flakiness */
251 static TYPESIG alrmser ();
253 static int sm_addrs = 0;
254 static int sm_alarmed = 0;
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;
262 static FILE * sm_rfp = NULL;
263 static FILE * sm_wfp = NULL;
266 static int sm_ispool = 0;
267 static char sm_tmpfil[BUFSIZ];
270 static char *sm_noreply = "No reply text given";
271 static char *sm_moreply = "; ";
273 struct smtp sm_reply; /* global... */
279 static int rclient(), sm_ierror(), smtalk(), sm_wrecord(), sm_wstream();
280 static int sm_werror(), smhear(), sm_rrecord(), sm_rerror();
286 extern char *sys_errlist[];
290 static int doingEHLO;
293 char *EHLOkeys[MAXEHLO + 1];
302 extern char **brkstring (), **copyip (), *getcpy ();
311 int sm_init (client, server, watch, verbose, debug, onex, queued)
330 #else /* to show the transaction, -watch must imply -snoop */
331 debug = verbose = TRUE;
333 sm_verbose = verbose;
335 if (sm_rfp != NULL && sm_wfp != NULL)
338 if (client == NULL || *client == '\0')
341 if (client == NULL || *client == '\0')
342 client = "localhost";
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");
353 for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++)
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");
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++)
374 vec[vecp++] = r1bindex (sendmail, '/');
377 vec[vecp++] = watch ? "-odi" : queued ? "-odq" : "-odb";
378 vec[vecp++] = "-oem";
383 #endif /* not RAND */
384 #endif /* not ZMAILER */
387 (void) setgid (getegid ());
388 (void) setuid (geteuid ());
389 execvp (sendmail, vec);
390 fprintf (stderr, "unable to exec ");
392 _exit (-1); /* NOTREACHED */
395 (void) signal (SIGALRM, alrmser);
396 (void) signal (SIGPIPE, SIG_IGN);
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");
408 (void) alarm (SM_OPEN);
416 (void) sm_end (NOTOK);
420 if (client && *client) {
422 result = smtalk (SM_HELO, "EHLO %s", client);
425 if (500 <= result && result <= 599)
426 result = smtalk (SM_HELO, "HELO %s", client);
433 (void) sm_end (NOTOK);
440 (void) smtalk (SM_HELO, "ONEX");
443 (void) smtalk (SM_HELO, "VERB on");
452 int sm_init (client, server, watch, verbose, debug, onex, queued)
469 if (!server || !*server)
471 (void) copyip (brkstring (getcpy (server), " ", "\n"), ap);
474 #if !defined(SUN40) || defined(MMDFII)
476 #else /* to show the transaction, -watch must imply -snoop */
477 debug = verbose = TRUE;
479 sm_verbose = verbose;
485 if (sm_rfp != NULL && sm_wfp != NULL)
488 if (client == NULL || *client == '\0')
492 client = LocalName (); /* no clientname -> LocalName */
494 if (client == NULL || *client == '\0')
495 client = "localhost";
496 #endif /* not ZMAILER */
500 for (sd1 = NOTOK; *ap; ap++) {
501 if ((sd1 = rclient (*ap, "tcp", "smtp")) != NOTOK)
509 (void) alarm (SM_CLOS);
510 (void) fclose (sm_rfp);
514 if ((sm_wfp = fdopen (sd1, "w")) == NULL) {
515 (void) unlink (sm_tmpfil);
517 return sm_ierror ("unable to fdopen");
520 sm_reply.text[sm_reply.length = 0] = NULL;
521 return (sm_reply.code = RP_OK);
524 if ((sd2 = dup (sd1)) == NOTOK) {
526 return sm_ierror ("unable to dup");
529 (void) signal (SIGALRM, alrmser);
530 (void) signal (SIGPIPE, SIG_IGN);
532 if ((sm_rfp = fdopen (sd1, "r")) == NULL
533 || (sm_wfp = fdopen (sd2, "w")) == NULL) {
536 sm_rfp = sm_wfp = NULL;
537 return sm_ierror ("unable to fdopen");
540 (void) alarm (SM_OPEN);
548 (void) sm_end (NOTOK);
556 if (client && *client) {
558 result = smtalk (SM_HELO, "EHLO %s", client);
561 if (500 <= result && result <= 599)
562 result = smtalk (SM_HELO, "HELO %s", client);
569 (void) sm_end (NOTOK);
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");
586 static int rclient (server, protocol, service)
592 char response[BUFSIZ];
597 if ((sd = client (server, protocol, service, FALSE, response)) != NOTOK)
601 if (!server && servers && (cp = index (servers, '/'))) {
603 char *arguments[MAXARGS];
605 (void) copyip (brkstring (cp = getcpy (servers), " ", "\n"),
608 for (ap = arguments; *ap; ap++)
612 if ((dp = rindex (*ap, '/')) && *++dp == NULL)
614 (void) sprintf (sm_tmpfil, "%s/smtpXXXXXX", *ap);
615 (void) mktemp (sm_tmpfil);
617 if ((sd = creat (sm_tmpfil, 0600)) != NOTOK) {
629 (void) sm_ierror ("%s", response);
636 int sm_winit (mode, from)
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;
649 switch (smtalk (SM_MAIL, "%s FROM:<%s>",
650 mode == S_SEND ? "SEND" : mode == S_SOML ? "SOML"
651 : mode == S_SAML ? "SAML" : "MAIL", from)) {
672 int sm_wadr (mbox, host, path)
676 #endif /* not BERK */
681 switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@@%s>"
683 path ? path : "", mbox, host)) {
685 switch (smtalk (SM_RCPT, "RCPT TO:%s", mbox)) {
696 #endif /* SENDMAILBUG */
720 switch (smtalk (SM_DATA, "DATA")) {
729 #endif /* SENDMAILBUG */
746 int sm_wtxt (buffer, len)
747 register char *buffer;
753 (void) alarm (SM_TEXT);
754 result = sm_wstream (buffer, len);
757 return (result == NOTOK ? RP_BHST : RP_OK);
763 if (sm_wstream ((char *) NULL, 0) == NOTOK)
766 switch (smtalk (SM_DOT + 3 * sm_addrs, ".")) {
774 #endif /* SENDMAILBUG */
802 #endif /* not SMTP */
803 if (sm_rfp == NULL && sm_wfp == NULL)
808 (void) smtalk (SM_QUIT, "QUIT");
812 sm_note.code = sm_reply.code;
813 (void) strncpy (sm_note.text, sm_reply.text,
814 sm_note.length = sm_reply.length);/* fall */
816 if (smtalk (SM_RSET, "RSET") == 250 && type == DONE)
819 (void) kill (sm_child, SIGKILL);
823 (void) smtalk (SM_QUIT, "QUIT");
824 #endif /* not SMTP */
826 sm_reply.code = sm_note.code;
827 (void) strncpy (sm_reply.text, sm_note.text,
828 sm_reply.length = sm_note.length);
838 (void) unlink (sm_tmpfil);
839 (void) fclose (sm_wfp);
845 if (sm_rfp != NULL) {
846 (void) alarm (SM_CLOS);
847 (void) fclose (sm_rfp);
850 if (sm_wfp != NULL) {
851 (void) alarm (SM_CLOS);
852 (void) fclose (sm_wfp);
857 status = pidwait (sm_child);
863 sm_rfp = sm_wfp = NULL;
865 return (status ? RP_BHST : RP_OK);
872 #include <sys/types.h>
873 #include <sys/stat.h>
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);
898 if (errno > 0 && errno < sys_nerr)
899 (void) sprintf (bp, "%s", sys_errlist[errno]);
901 (void) sprintf (bp, "Error %d", errno);
902 sm_reply.length = strlen (sm_reply.text);
903 sm_reply.code = NOTOK;
907 printf ("reading file %s\n", file);
908 (void) fflush (stdout);
912 while (fgets (buffer, sizeof buffer, fp)) {
914 (void) strcpy (sender, buffer + sizeof "MAIL FROM:" - 1);
915 if (strcmp (buffer, "DATA\r\n") == 0) {
922 printf ("no DATA...\n");
923 (void) fflush (stdout);
926 (void) sprintf (buffer, "%s.bad", file);
927 (void) rename (file, buffer);
929 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
930 (void) unlink (buffer);
938 printf ("no %srecipients...\n", j < 1 ? "sender or " : "");
939 (void) fflush (stdout);
944 if ((cp = malloc ((unsigned) (cc = (pos = ftell (fp)) + 1))) == NULL) {
945 sm_reply.length = strlen (strcpy (sm_reply.text, "out of memory"));
947 sm_reply.code = NOTOK;
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"));
961 for (dp = cp, i = cc - 1; i > 0; dp += cc, i -= cc)
962 if ((cc = write (fileno (sm_wfp), dp, i)) == NOTOK) {
964 (void) strcpy (bp = sm_reply.text, "error writing to server: ");
966 if (errno > 0 && errno < sys_nerr)
967 (void) sprintf (bp, "%s", sys_errlist[errno]);
969 (void) sprintf (bp, "Error %d", errno);
970 sm_reply.length = strlen (sm_reply.text);
975 printf ("wrote %d octets to server\n", cc);
976 (void) fflush (stdout);
979 for (dp = cp, i = 0; i++ < j; dp = index (dp, '\n'), dp++) {
981 if (bp = index (dp, '\r'))
983 printf ("=> %s\n", dp);
984 (void) fflush (stdout);
989 switch (smhear () + (i == 1 ? 1000 : i != j ? 2000 : 3000)) {
1001 (void) smtalk (SM_RSET, "RSET");
1029 if (k <= 0 || strcmp (sender, "<>\r\n") == 0)
1033 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1034 if ((gp = fopen (buffer, "w+")) == NULL)
1036 fprintf (gp, "MAIL FROM:<>\r\nRCPT TO:%sDATA\r\n", sender);
1037 l = strlen (sender);
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 ());
1044 if (bp = index (dp, '\r'))
1046 fprintf (gp, "=> %s\r\n", dp);
1049 fprintf (gp, "<= %s\r\n", rp_string (result));
1067 (void) smtalk (SM_RSET, "RSET");
1070 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1071 (void) unlink (buffer);
1081 (void) smtalk (SM_RSET, "RSET");
1098 if (fstat (fileno (sm_wfp), &st) == NOTOK
1099 || (cc = st.st_blksize) < BUFSIZ)
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"));
1108 (void) fseek (fp, pos, 0);
1112 for (dp = cp, i = cc; i > 0; dp += j, i -= j)
1113 if ((j = fread (cp, sizeof *cp, i, fp)) == OK) {
1115 (void) sprintf (bp = sm_reply.text,
1116 "error reading %s: ", file);
1118 if (errno > 0 && errno < sys_nerr)
1119 (void) sprintf (bp, "%s", sys_errlist[errno]);
1121 (void) sprintf (bp, "Error %d", errno);
1122 sm_reply.length = strlen (sm_reply.text);
1130 for (dp = cp, i = cc; i > 0; dp += j, i -= j)
1131 if ((j = write (fileno (sm_wfp), dp, i)) == NOTOK)
1135 printf ("wrote %d octets to server\n", j);
1136 (void) fflush (stdout);
1144 switch (smhear ()) {
1151 (void) unlink (file);
1162 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1163 (void) unlink (buffer);
1173 if (k <= 0 || strcmp (sender, "<>\r\n") == 0) {
1174 (void) unlink (file);
1179 (void) ftruncate (fileno (gp), 0L);
1180 (void) fseek (gp, 0L, 0);
1183 (void) sprintf (buffer, "%*.*sA.bulk", k, k, file);
1184 if ((gp = fopen (buffer, "w")) == NULL)
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 ());
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);
1205 (void) fputs ("\r\n------- End Returned Message\r\n\r\n.\r\n", gp);
1208 (void) unlink (file);
1222 static int sm_ierror (fmt, a, b, c, d)
1229 (void) sprintf (sm_reply.text, fmt, a, b, c, d);
1230 sm_reply.length = strlen (sm_reply.text);
1231 sm_reply.code = NOTOK;
1240 static int smtalk (time, fmt, a, b, c, d)
1243 register char *a, *b, *c, *d;
1245 register int result;
1246 char buffer[BUFSIZ];
1248 (void) sprintf (buffer, fmt, a, b, c, d);
1250 printf ("=> %s\n", buffer);
1251 (void) fflush (stdout);
1258 if (strcmp (buffer, ".") == 0)
1260 fprintf (sm_wfp, "%s\r\n", buffer);
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) {
1270 (void) sprintf (bp = sm_reply.text,
1271 "error renaming %s to %s: ",
1274 if (errno > 0 && errno < sys_nerr)
1275 (void) sprintf (bp, "%s", sys_errlist[errno]);
1277 (void) sprintf (bp, "Error %d", errno);
1278 sm_reply.length = strlen (sm_reply.text);
1279 sm_reply.code = NOTOK;
1282 (void) fclose (sm_wfp);
1283 if (sm_wfp = fopen (sm_tmpfil, "w"))
1284 (void) chmod (sm_tmpfil, 0600);
1294 (void) fflush (sm_wfp);
1295 (void) ftruncate (fileno (sm_wfp), 0L);
1296 (void) fseek (sm_wfp, 0L, 0);
1305 (void) unlink (sm_tmpfil);
1315 printf ("<= %d\n", result);
1316 (void) fflush (stdout);
1319 sm_reply.text[sm_reply.length = 0] = NULL;
1320 return (sm_reply.code = result);
1325 (void) alarm ((unsigned) time);
1326 if ((result = sm_wrecord (buffer, strlen (buffer))) != NOTOK)
1335 static int sm_wrecord (buffer, len)
1336 register char *buffer;
1340 return sm_werror ();
1342 (void) fwrite (buffer, sizeof *buffer, len, sm_wfp);
1343 (void) fputs ("\r\n", sm_wfp);
1344 (void) fflush (sm_wfp);
1346 return (ferror (sm_wfp) ? sm_werror () : OK);
1351 static int sm_wstream (buffer, len)
1352 register char *buffer;
1359 return sm_werror ();
1361 if (buffer == NULL && len == 0) {
1363 (void) fputs ("\r\n", sm_wfp);
1365 return (ferror (sm_wfp) ? sm_werror () : OK);
1368 for (bp = buffer; len > 0; bp++, len--) {
1372 (void) fputc ('\r', sm_wfp);
1377 (void) fputc ('.', sm_wfp);/* FALL THROUGH */
1381 (void) fputc (*bp, sm_wfp);
1382 if (ferror (sm_wfp))
1383 return sm_werror ();
1388 return (ferror (sm_wfp) ? sm_werror () : OK);
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.
1404 static int sm_werror () {
1407 strlen (strcpy (sm_reply.text, sm_wfp == NULL ? "no socket opened"
1408 : sm_alarmed ? "write to socket timed out"
1410 : sm_ispool ? "error writing to spool file"
1412 : "error writing to socket"));
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"));
1419 return (sm_reply.code = NOTOK);
1424 static int smhear () {
1437 static int at_least_once = 0;
1439 if (at_least_once) {
1442 for (ehlo = EHLOkeys; ep = *ehlo; ehlo++)
1448 *(ehlo = EHLOkeys) = NULL;
1453 sm_reply.text[sm_reply.length = 0] = 0;
1455 rp = sm_reply.text, rc = sizeof sm_reply.text - 1;
1456 for (more = FALSE; sm_rrecord (bp = buffer, &bc) != NOTOK;) {
1458 printf ("<= %s\n", buffer);
1459 (void) fflush (stdout);
1463 && strncmp (buffer, "250", sizeof "250" - 1) == 0
1464 && (buffer[3] == '-' || doingEHLO == 2)
1466 if (doingEHLO == 2) {
1467 int len = strlen (buffer + 4);
1469 if (*ehlo = malloc ((unsigned) (strlen (buffer + 4) + 1))) {
1470 (void) strcpy (*ehlo++, buffer + 4);
1472 if (ehlo >= EHLOkeys + MAXEHLO)
1482 for (; bc > 0 && (!isascii (*bp) || !isdigit (*bp)); bp++, bc--)
1488 for (; bc > 0 && isspace (*bp); bp++, bc--)
1490 if (bc > 0 && *bp == '-') {
1493 for (; bc > 0 && isspace (*bp); bp++, bc--)
1498 if (code != sm_reply.code || cont)
1503 sm_reply.code = code;
1506 (void) strcpy (bp = buffer, sm_noreply);
1507 bc = strlen (sm_noreply);
1510 if ((i = min (bc, rc)) > 0) {
1511 (void) strncpy (rp, bp, i);
1513 if (more && rc > strlen (sm_moreply) + 1) {
1514 (void) strcpy (sm_reply.text + rc, sm_moreply);
1515 rc += strlen (sm_moreply);
1520 if (sm_reply.code < 100) {
1522 printf ("%s\n", sm_reply.text);
1523 (void) fflush (stdout);
1528 sm_reply.length = rp - sm_reply.text;
1530 return sm_reply.code;
1538 static int sm_rrecord (buffer, len)
1539 register char *buffer;
1543 return sm_rerror ();
1545 buffer[*len = 0] = 0;
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))
1555 if (buffer[*len - 2] == '\r')
1557 buffer[*len - 1] = 0;
1564 static int sm_rerror () {
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 */
1578 return (sm_reply.code = NOTOK);
1585 static TYPESIG alrmser (i)
1589 signal (SIGALRM, alrmser);
1594 printf ("timed out...\n");
1595 (void) fflush (stdout);
1601 char *rp_string (code)
1604 register char *text;
1605 static char buffer[BUFSIZ];
1607 switch (sm_reply.code != NOTOK ? code : NOTOK) {
1627 (void) sprintf (buffer, "[%s] %s", text, sm_reply.text);
1647 (void) sprintf (buffer, "[%s] %3d %s", text, sm_reply.code, sm_reply.text);
1654 static char *broken[MAXARGS + 1];
1657 static char **brkstring (strg, brksep, brkterm)
1658 register char *strg;
1659 register char *brksep,
1668 for (bi = 0; bi < MAXARGS; bi++) {
1669 while (brkany (c = *sp, brksep))
1671 if (!c || brkany (c, brkterm)) {
1678 while ((c = *++sp) && !brkany (c, brksep) && !brkany (c, brkterm))
1681 broken[MAXARGS] = 0;
1687 static brkany (chr, strg)
1694 for (sp = strg; *sp; sp++)
1701 static char **copyip (p, q)
1718 int len = strlen (s);
1722 for (ehlo = EHLOkeys; ep = *ehlo; ehlo++)
1723 if (strncmp (ep, s, len) == 0) {
1724 for (ep += len; *ep == ' '; ep++)
1741 static char ident[] = "@@(#)$Id: smail.c,v 1.28 1994/03/23 23:24:51 jromine Exp jromine $";
1743 extern char **brkstring (), **copyip (), *getcpy ();
1751 if ((sd1 = rclient (server, "tcp", "smtp")) == NOTOK)
1758 #define MAXARGS 1000
1775 static char ident[] = "@@(#)$Id: smail.c,v 1.27 1993/12/01 03:50:31 jromine Exp jromine $";
1787 static char ident[] = "@@(#)$Id: smail.c,v 1.26 1993/09/01 20:55:22 jromine Exp jromine $";
1790 client = clientname;
1793 #if !defined(SENDMTS) || defined(MMDFII) || defined(SVR4)
1794 if (client == NULL || *client == 0)
1795 client = LocalName ();
1802 @add clientname tailor option
1807 static char ident[] = "@@(#)$Id: smail.c,v 1.25 1993/08/25 17:17:29 jromine Exp jromine $";
1816 @off_t fixes for BSD44
1821 static char ident[] = "@@(#)$Id: smail.c,v 1.24 1993/08/20 16:14:30 jromine Exp jromine $";
1829 @don't use ONEX with ZMAILER
1834 static char ident[] = "@@(#)$Id: smail.c,v 1.23 1993/08/20 15:47:14 jromine Exp jromine $";
1837 extern int errno, sys_nerr;
1850 static char ident[] = "@@(#)$Id: smail.c,v 1.22 1993/08/19 23:35:31 jromine Exp jromine $";
1858 @enable ONEX only with "options SMTP_ONEX"
1863 static char ident[] = "@@(#)$Id: smail.c,v 1.21 1992/11/09 18:19:32 jromine Exp jromine $";
1867 int sm_init (client, server, watch, verbose, debug)
1868 register char *client;
1876 vec[vecp++] = watch ? "-odi" : "-odb";
1879 (void) smtalk(SM_HELO, "ONEX");
1882 (void) smtalk(SM_HELO, "VERB on");
1883 if (client && *client)
1884 switch (smtalk (SM_HELO, "HELO %s", client)) {
1893 int sm_init (client, server, watch, verbose, debug)
1894 register char *client,
1901 #if defined(SUN40) && !defined(MMDFII)
1911 #endif /* ZMAILER */
1920 (void) smtalk(SM_HELO, "ONEX");
1924 (void) smtalk(SM_HELO, "VERB on");
1926 if (client && *client)
1927 switch (smtalk (SM_HELO, "HELO %s", client)) {
1932 char buffer[BUFSIZ];
1942 @force on -snoop under SUN40 only
1947 static char ident[] = "@@(#)$Id: smail.c,v 1.20 1992/11/06 18:04:48 jromine Exp jromine $";
1953 #endif /* not ZMAILER */
1956 #if !(defined(ZMAILER) || defined(MMDFII))
1959 #endif /* not ZMAILER */
1965 @have -watch imply -snoop under SendMail
1971 static char ident[] = "@@(#)$Id: smail.c,v 1.19 1992/11/06 17:26:22 jromine Exp jromine $";
1980 debug = verbose = TRUE;
1991 static char ident[] = "@@(#)$Id: smail.c,v 1.18 1992/11/02 18:55:04 jromine Exp jromine $";
2005 #endif not BSD42 and not SOCKETS
2079 @_AIX fixes from Bill Wohler
2084 static char ident[] = "@@(#)$Id: smail.c,v 1.17 1992/10/26 22:42:56 jromine Exp jromine $";
2096 static char ident[] = "@@(#)$Id: smail.c,v 1.16 1992/10/26 16:39:18 jromine Exp jromine $";
2103 @#ifdef MPOP reversed.
2108 static char ident[] = "@@(#)$Id: smail.c,v 1.15 1992/10/21 03:27:12 jromine Exp jromine $";
2111 static int alrmser ();
2114 static int alrmser (i)
2120 @-watch shows SMTP transaction, not -verbose
2125 static char ident[] = "@@(#)$Id: smail.c,v 1.14 1992/10/21 03:26:43 jromine Exp jromine $";
2134 @fixup #ifdef's ZMAILER, MPOP
2139 static char ident[] = "@@(#)$Id: smail.c,v 1.13 1992/10/20 15:36:40 jromine Exp jromine $";
2156 static char ident[] = "@@(#)$Id: smail.c,v 1.12 1992/10/16 16:51:15 jromine Exp jromine $";
2165 if (client == NULL || *client == '\0')
2166 client = "localhost";
2176 @mobile pop ifdef's (MPOP)
2181 static char ident[] = "@@(#)$Id: smail.c,v 1.11 1992/03/03 17:11:03 jromine Exp jromine $";
2200 static char ident[] = "@@(#)$Id: smail.c,v 1.10 1992/03/03 17:09:57 jromine Exp jromine $";
2235 static char ident[] = "@@(#)$Id: smail.c,v 1.9 1992/02/10 18:12:35 jromine Exp jromine $";
2239 extern int errno, sys_nerr;
2240 extern char *sys_errlist[];
2241 extern char **brkstring (), **copyip (), *getcpy ();
2249 add "localdomain" tailor option
2254 static char ident[] = "@@(#)$Id: smail.c,v 1.8 1992/02/05 22:10:36 jromine Exp jromine $";
2267 char response[BUFSIZ];
2275 fputs ("\r\n", sm_wfp);
2278 fputs ("\r\n", sm_wfp);
2286 @add zmailer support
2291 static char ident[] = "@@(#)$Id: smail.c,v 1.7 1992/01/31 21:40:09 jromine Exp jromine $";
2297 #if !defined(SENDMTS) || defined(MMDFII)
2298 if (client == NULL || *client == NULL)
2314 static char ident[] = "@@(#)$Id: smail.c,v 1.6 1990/04/05 15:30:07 sources Exp jromine $";
2331 static char ident[] = "@@(#)$Id:$";
2334 static char lc = NULL;
2340 sm_reply.text[sm_reply.length = 0] = NULL;
2343 buffer[*len = 0] = NULL;
2346 buffer[*len - 1] = NULL;
2357 static char ident[] = "$Id:";
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.