📄 smail.c
字号:
/* smail.c - MH interface to SendMail/SMTP */#ifndef lintstatic char ident[] = "@(#)$Id: smail.c,v 1.28 1994/03/23 23:24:51 jromine Exp $";#endif/* LINTLIBRARY *//* This module implements an interface to SendMail very similar to the MMDF mm_(3) routines. The sm_() routines herein talk SMTP to a sendmail process, mapping SMTP reply codes into RP_-style codes. */#ifdef BSD42/* Under 4.2BSD, the alarm handing stuff for time-outs will NOT work due to the way syscalls get restarted. This really is not crucial, since we expect SendMail to be well-behaved and not hang on us. The only time I've ever seen Sendmail hang was with a bogus configuration file... */#endif /* BSD42 */#ifdef SENDMAILBUG/* * It appears that some versions of Sendmail will return Code 451 * when they don't really want to indicate a failure. * "Code 451 almost always means sendmail has deferred; we don't * really want bomb out at this point since sendmail will rectify * things later." So, if you define SENDMAILBUG, Code 451 is * considered the same as Code 250. Yuck! */#ifndef SENDMAIL#undef SENDMAILBUG#endif /* not SENDMAIL */#endif /* SENDMAILBUG */#ifdef hpux /* HP-UX has this capability. It also handles (some) signals. */#define BSD42 #endif /* hpux */#if !defined(BSD42) && !defined(SOCKETS)#undef SMTP#endif /* not BSD42 and not SOCKETS */#ifdef SMTP#undef SENDMAIL#endif /* SMTP */#include "../h/strings.h"#include <stdio.h>#include "smail.h"#include "../zotnet/mts.h"#include <ctype.h>#include <signal.h>#ifndef TYPESIG#define TYPESIG int#endif#define NOTOK (-1)#define OK 0#define DONE 1#define TRUE 1#define FALSE 0#define NBITS ((sizeof (int)) * 8)#define min(a,b) ((a) < (b) ? (a) : (b)) /* these codes must all be different! */#define SM_OPEN 90 /* Changed from 30 in case of nameserver flakiness */#define SM_HELO 20#define SM_RSET 15#define SM_MAIL 40#define SM_RCPT 120#define SM_DATA 20#define SM_TEXT 150#define SM_DOT 180#define SM_QUIT 30#define SM_CLOS 10/* */static TYPESIG alrmser ();static int sm_addrs = 0;static int sm_alarmed = 0;#ifndef SMTPstatic int sm_child = NOTOK;#endif /* not SMTP */static int sm_debug = 0;static int sm_nl = TRUE;static int sm_verbose = 0;static FILE * sm_rfp = NULL;static FILE * sm_wfp = NULL;#ifdef MPOPstatic int sm_ispool = 0;static char sm_tmpfil[BUFSIZ];#endif /* MPOP */static char *sm_noreply = "No reply text given";static char *sm_moreply = "; ";struct smtp sm_reply; /* global... */void discard ();char *r1bindex ();static int rclient(), sm_ierror(), smtalk(), sm_wrecord(), sm_wstream();static int sm_werror(), smhear(), sm_rrecord(), sm_rerror();#ifdef MPOPextern int errno;#ifndef BSD44extern int sys_nerr;extern char *sys_errlist[];#endifextern char **brkstring (), **copyip (), *getcpy ();#endifstatic int doingEHLO;#define MAXEHLO 10char *EHLOkeys[MAXEHLO + 1];char *EHLOset ();/* */#ifndef SMTP/* ARGSUSED */int sm_init (client, server, watch, verbose, debug, onex, queued)char *client, *server;int watch, verbose, debug, onex, queued;{ register int i, result, vecp; int pdi[2], pdo[2]; char *vec[15]; if (watch)#ifndef SUN40 verbose = TRUE;#else /* to show the transaction, -watch must imply -snoop */ debug = verbose = TRUE;#endif sm_verbose = verbose; sm_debug = debug; if (sm_rfp != NULL && sm_wfp != NULL) return RP_OK; if (client == NULL || *client == '\0') client = clientname;#ifdef ZMAILER if (client == NULL || *client == '\0') client = "localhost";#endif if (pipe (pdi) == NOTOK) return sm_ierror ("no pipes"); if (pipe (pdo) == NOTOK) { (void) close (pdi[0]); (void) close (pdi[1]); return sm_ierror ("no pipes"); } for (i = 0; (sm_child = fork ()) == NOTOK && i < 5; i++) sleep (5); switch (sm_child) { case NOTOK: (void) close (pdo[0]); (void) close (pdo[1]); (void) close (pdi[0]); (void) close (pdi[1]); return sm_ierror ("unable to fork"); case OK: if (pdo[0] != fileno (stdin)) (void) dup2 (pdo[0], fileno (stdin)); if (pdi[1] != fileno (stdout)) (void) dup2 (pdi[1], fileno (stdout)); if (pdi[1] != fileno (stderr)) (void) dup2 (pdi[1], fileno (stderr)); for (i = fileno (stderr) + 1; i < NBITS; i++) (void) close (i); vecp = 0; vec[vecp++] = r1bindex (sendmail, '/'); vec[vecp++] = "-bs";#ifndef ZMAILER vec[vecp++] = watch ? "-odi" : queued ? "-odq" : "-odb"; vec[vecp++] = "-oem"; vec[vecp++] = "-om";#ifndef RAND if (verbose) vec[vecp++] = "-ov";#endif /* not RAND */#endif /* not ZMAILER */ vec[vecp++] = NULL; (void) setgid (getegid ()); (void) setuid (geteuid ()); execvp (sendmail, vec); fprintf (stderr, "unable to exec "); perror (sendmail); _exit (-1); /* NOTREACHED */ default: (void) signal (SIGALRM, alrmser); (void) signal (SIGPIPE, SIG_IGN); (void) close (pdi[1]); (void) close (pdo[0]); if ((sm_rfp = fdopen (pdi[0], "r")) == NULL || (sm_wfp = fdopen (pdo[1], "w")) == NULL) { (void) close (pdi[0]); (void) close (pdo[1]); sm_rfp = sm_wfp = NULL; return sm_ierror ("unable to fdopen"); } sm_alarmed = 0; (void) alarm (SM_OPEN); result = smhear (); (void) alarm (0); switch (result) { case 220: break; default: (void) sm_end (NOTOK); return RP_RPLY; } if (client && *client) { doingEHLO = 1; result = smtalk (SM_HELO, "EHLO %s", client); doingEHLO = 0; if (500 <= result && result <= 599) result = smtalk (SM_HELO, "HELO %s", client); switch (result) { case 250: break; default: (void) sm_end (NOTOK); return RP_RPLY; } }#ifndef ZMAILER if (onex) (void) smtalk (SM_HELO, "ONEX");#endif if (watch) (void) smtalk (SM_HELO, "VERB on"); return RP_OK; }}#else /* SMTP *//* */int sm_init (client, server, watch, verbose, debug, onex, queued)char *client, *server;int watch, verbose, debug, onex, queued;{ register int result, sd1, sd2; if (watch)#if !defined(SUN40) || defined(MMDFII) verbose = TRUE;#else /* to show the transaction, -watch must imply -snoop */ debug = verbose = TRUE;#endif sm_verbose = verbose; sm_debug = debug;#ifdef MPOP if (sm_ispool) goto all_done;#endif if (sm_rfp != NULL && sm_wfp != NULL) goto send_options; if (client == NULL || *client == '\0') if (clientname) client = clientname; else client = LocalName (); /* no clientname -> LocalName */#ifdef ZMAILER if (client == NULL || *client == '\0') client = "localhost";#endif /* not ZMAILER */ if ((sd1 = rclient (server, "tcp", "smtp")) == NOTOK) return RP_BHST;#ifdef MPOP if (sm_ispool) { if (sm_rfp) { (void) alarm (SM_CLOS); (void) fclose (sm_rfp); (void) alarm (0); sm_rfp = NULL; } if ((sm_wfp = fdopen (sd1, "w")) == NULL) { (void) unlink (sm_tmpfil); (void) close (sd1); return sm_ierror ("unable to fdopen"); }all_done: ; sm_reply.text[sm_reply.length = 0] = NULL; return (sm_reply.code = RP_OK); }#endif /* MPOP */ if ((sd2 = dup (sd1)) == NOTOK) { (void) close (sd1); return sm_ierror ("unable to dup"); } (void) signal (SIGALRM, alrmser); (void) signal (SIGPIPE, SIG_IGN); if ((sm_rfp = fdopen (sd1, "r")) == NULL || (sm_wfp = fdopen (sd2, "w")) == NULL) { (void) close (sd1); (void) close (sd2); sm_rfp = sm_wfp = NULL; return sm_ierror ("unable to fdopen"); } sm_alarmed = 0; (void) alarm (SM_OPEN); result = smhear (); (void) alarm (0); switch (result) { case 220: break; default: (void) sm_end (NOTOK); return RP_RPLY; } if (client && *client) { doingEHLO = 1; result = smtalk (SM_HELO, "EHLO %s", client); doingEHLO = 0; if (500 <= result && result <= 599) result = smtalk (SM_HELO, "HELO %s", client); switch (result) { case 250: break; default: (void) sm_end (NOTOK); return RP_RPLY; } }send_options: ; if (watch && EHLOset ("XVRB")) (void) smtalk (SM_HELO, "VERB on"); if (onex && EHLOset ("XONE")) (void) smtalk (SM_HELO, "ONEX"); if (queued && EHLOset ("XQUE")) (void) smtalk (SM_HELO, "QUED"); return RP_OK;}#ifdef MPOP#define MAXARGS 1000#endif /* MPOP */static int rclient (server, protocol, service)char *server, *protocol, *service;{ int sd; char response[BUFSIZ];#ifdef MPOP char *cp;#endif /* MPOP */ if ((sd = client (server, protocol, service, FALSE, response)) != NOTOK) return sd;#ifdef MPOP if (!server && servers && (cp = index (servers, '/'))) { register char **ap; char *arguments[MAXARGS]; (void) copyip (brkstring (cp = getcpy (servers), " ", "\n"), arguments); for (ap = arguments; *ap; ap++) if (**ap == '/') { register char *dp; if ((dp = rindex (*ap, '/')) && *++dp == NULL) *--dp = NULL; (void) sprintf (sm_tmpfil, "%s/smtpXXXXXX", *ap); (void) mktemp (sm_tmpfil); if ((sd = creat (sm_tmpfil, 0600)) != NOTOK) { sm_ispool = 1; break; } } free (cp); if (sd != NOTOK) return sd; }#endif /* MPOP */ (void) sm_ierror ("%s", response); return NOTOK;}#endif /* SMTP *//* */int sm_winit (mode, from)register int mode;register char *from;{#ifdef MPOP if (sm_ispool && !sm_wfp) { (void) strlen (strcpy (sm_reply.text, "unable to create new spool file")); sm_reply.code = NOTOK; return RP_BHST; }#endif /* MPOP */ switch (smtalk (SM_MAIL, "%s FROM:<%s>", mode == S_SEND ? "SEND" : mode == S_SOML ? "SOML" : mode == S_SAML ? "SAML" : "MAIL", from)) { case 250: sm_addrs = 0; return RP_OK; case 500: case 501: case 552: return RP_PARM; default: return RP_RPLY; }}/* */#ifdef BERK/* ARGUSED */#endif /* BERK */int sm_wadr (mbox, host, path)register char *mbox;#ifndef BERKregister#endif /* not BERK */ char *host, *path;{#ifndef BERK switch (smtalk (SM_RCPT, host && *host ? "RCPT TO:<%s%s@%s>" : "RCPT TO:<%s%s>", path ? path : "", mbox, host)) {#else /* BERK */ switch (smtalk (SM_RCPT, "RCPT TO:%s", mbox)) {#endif /* BERK */ case 250: case 251: sm_addrs++; return RP_OK; case 451: #ifdef SENDMAILBUG sm_addrs++; return RP_OK;#endif /* SENDMAILBUG */ case 421: case 450: case 452: return RP_NO; case 500:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -