📄 main.c
字号:
}
if (uname(&utsname) >= 0)
p = utsname.nodename;
else
{
if (tTd(0, 22))
dprintf("uname failed (%s)\n",
errstring(errno));
makelower(jbuf);
p = jbuf;
}
if (tTd(0, 4))
dprintf(" UUCP nodename: %s\n", p);
p = newstr(p);
define('k', p, CurEnv);
setclass('k', p);
setclass('w', p);
}
if (hp != NULL)
{
for (av = hp->h_aliases; av != NULL && *av != NULL; av++)
{
if (tTd(0, 4))
dprintf("\ta.k.a.: %s\n", *av);
setclass('w', *av);
}
#if NETINET || NETINET6
for (i = 0; hp->h_addr_list[i] != NULL; i++)
{
# if NETINET6
char *addr;
char buf6[INET6_ADDRSTRLEN];
struct in6_addr ia6;
# endif /* NETINET6 */
# if NETINET
struct in_addr ia;
# endif /* NETINET */
char ipbuf[103];
ipbuf[0] = '\0';
switch (hp->h_addrtype)
{
# if NETINET
case AF_INET:
if (hp->h_length != INADDRSZ)
break;
memmove(&ia, hp->h_addr_list[i], INADDRSZ);
(void) snprintf(ipbuf, sizeof ipbuf,
"[%.100s]", inet_ntoa(ia));
break;
# endif /* NETINET */
# if NETINET6
case AF_INET6:
if (hp->h_length != IN6ADDRSZ)
break;
memmove(&ia6, hp->h_addr_list[i], IN6ADDRSZ);
addr = anynet_ntop(&ia6, buf6, sizeof buf6);
if (addr != NULL)
(void) snprintf(ipbuf, sizeof ipbuf,
"[%.100s]", addr);
break;
# endif /* NETINET6 */
}
if (ipbuf[0] == '\0')
break;
if (tTd(0, 4))
dprintf("\ta.k.a.: %s\n", ipbuf);
setclass('w', ipbuf);
}
#endif /* NETINET || NETINET6 */
}
/* current time */
define('b', arpadate((char *) NULL), CurEnv);
/* current load average */
CurrentLA = sm_getla(CurEnv);
QueueLimitRecipient = (QUEUE_CHAR *) NULL;
QueueLimitSender = (QUEUE_CHAR *) NULL;
QueueLimitId = (QUEUE_CHAR *) NULL;
/*
** Crack argv.
*/
av = argv;
p = strrchr(*av, '/');
if (p++ == NULL)
p = *av;
if (strcmp(p, "newaliases") == 0)
OpMode = MD_INITALIAS;
else if (strcmp(p, "mailq") == 0)
OpMode = MD_PRINT;
else if (strcmp(p, "smtpd") == 0)
OpMode = MD_DAEMON;
else if (strcmp(p, "hoststat") == 0)
OpMode = MD_HOSTSTAT;
else if (strcmp(p, "purgestat") == 0)
OpMode = MD_PURGESTAT;
optind = 1;
while ((j = getopt(argc, argv, OPTIONS)) != -1)
{
switch (j)
{
case 'b': /* operations mode */
switch (j = *optarg)
{
case MD_DAEMON:
case MD_FGDAEMON:
#if !DAEMON
usrerr("Daemon mode not implemented");
ExitStat = EX_USAGE;
break;
#endif /* !DAEMON */
case MD_SMTP:
#if !SMTP
usrerr("I don't speak SMTP");
ExitStat = EX_USAGE;
break;
#endif /* !SMTP */
case MD_INITALIAS:
case MD_DELIVER:
case MD_VERIFY:
case MD_TEST:
case MD_PRINT:
case MD_HOSTSTAT:
case MD_PURGESTAT:
case MD_ARPAFTP:
OpMode = j;
break;
case MD_FREEZE:
usrerr("Frozen configurations unsupported");
ExitStat = EX_USAGE;
break;
default:
usrerr("Invalid operation mode %c", j);
ExitStat = EX_USAGE;
break;
}
break;
case 'B': /* body type */
CurEnv->e_bodytype = newstr(optarg);
break;
case 'C': /* select configuration file (already done) */
if (RealUid != 0)
warn_C_flag = TRUE;
ConfFile = newstr(optarg);
dp = drop_privileges(TRUE);
setstat(dp);
safecf = FALSE;
break;
case 'd': /* debugging -- already done */
break;
case 'f': /* from address */
case 'r': /* obsolete -f flag */
if (from != NULL)
{
usrerr("More than one \"from\" person");
ExitStat = EX_USAGE;
break;
}
from = newstr(denlstring(optarg, TRUE, TRUE));
if (strcmp(RealUserName, from) != 0)
warn_f_flag = j;
break;
case 'F': /* set full name */
FullName = newstr(optarg);
break;
case 'G': /* relay (gateway) submission */
/* already set */
break;
case 'h': /* hop count */
CurEnv->e_hopcount = (short) strtol(optarg, &ep, 10);
if (*ep)
{
usrerr("Bad hop count (%s)", optarg);
ExitStat = EX_USAGE;
}
break;
case 'L': /* program label */
/* already set */
break;
case 'n': /* don't alias */
NoAlias = TRUE;
break;
case 'N': /* delivery status notifications */
DefaultNotify |= QHASNOTIFY;
define(macid("{dsn_notify}", NULL),
newstr(optarg), CurEnv);
if (strcasecmp(optarg, "never") == 0)
break;
for (p = optarg; p != NULL; optarg = p)
{
p = strchr(p, ',');
if (p != NULL)
*p++ = '\0';
if (strcasecmp(optarg, "success") == 0)
DefaultNotify |= QPINGONSUCCESS;
else if (strcasecmp(optarg, "failure") == 0)
DefaultNotify |= QPINGONFAILURE;
else if (strcasecmp(optarg, "delay") == 0)
DefaultNotify |= QPINGONDELAY;
else
{
usrerr("Invalid -N argument");
ExitStat = EX_USAGE;
}
}
break;
case 'o': /* set option */
setoption(*optarg, optarg + 1, FALSE, TRUE, CurEnv);
break;
case 'O': /* set option (long form) */
setoption(' ', optarg, FALSE, TRUE, CurEnv);
break;
case 'p': /* set protocol */
p = strchr(optarg, ':');
if (p != NULL)
{
*p++ = '\0';
if (*p != '\0')
{
ep = xalloc(strlen(p) + 1);
cleanstrcpy(ep, p, MAXNAME);
define('s', ep, CurEnv);
}
}
if (*optarg != '\0')
{
ep = xalloc(strlen(optarg) + 1);
cleanstrcpy(ep, optarg, MAXNAME);
define('r', ep, CurEnv);
}
break;
case 'q': /* run queue files at intervals */
#if QUEUE
/* sanity check */
if (OpMode != MD_DELIVER &&
OpMode != MD_DAEMON &&
OpMode != MD_FGDAEMON &&
OpMode != MD_PRINT &&
OpMode != MD_QUEUERUN)
{
usrerr("Can not use -q with -b%c", OpMode);
ExitStat = EX_USAGE;
break;
}
/* don't override -bd, -bD or -bp */
if (OpMode == MD_DELIVER)
OpMode = MD_QUEUERUN;
FullName = NULL;
switch (optarg[0])
{
case 'I':
new = (QUEUE_CHAR *) xalloc(sizeof *new);
new->queue_match = newstr(&optarg[1]);
new->queue_next = QueueLimitId;
QueueLimitId = new;
break;
case 'R':
new = (QUEUE_CHAR *) xalloc(sizeof *new);
new->queue_match = newstr(&optarg[1]);
new->queue_next = QueueLimitRecipient;
QueueLimitRecipient = new;
break;
case 'S':
new = (QUEUE_CHAR *) xalloc(sizeof *new);
new->queue_match = newstr(&optarg[1]);
new->queue_next = QueueLimitSender;
QueueLimitSender = new;
break;
default:
i = Errors;
QueueIntvl = convtime(optarg, 'm');
/* check for bad conversion */
if (i < Errors)
ExitStat = EX_USAGE;
break;
}
#else /* QUEUE */
usrerr("I don't know about queues");
ExitStat = EX_USAGE;
#endif /* QUEUE */
break;
case 'R': /* DSN RET: what to return */
if (bitset(EF_RET_PARAM, CurEnv->e_flags))
{
usrerr("Duplicate -R flag");
ExitStat = EX_USAGE;
break;
}
CurEnv->e_flags |= EF_RET_PARAM;
if (strcasecmp(optarg, "hdrs") == 0)
CurEnv->e_flags |= EF_NO_BODY_RETN;
else if (strcasecmp(optarg, "full") != 0)
{
usrerr("Invalid -R value");
ExitStat = EX_USAGE;
}
define(macid("{dsn_ret}", NULL),
newstr(optarg), CurEnv);
break;
case 't': /* read recipients from message */
GrabTo = TRUE;
break;
case 'U': /* initial (user) submission */
/* already set */
break;
case 'V': /* DSN ENVID: set "original" envelope id */
if (!xtextok(optarg))
{
usrerr("Invalid syntax in -V flag");
ExitStat = EX_USAGE;
}
else
{
CurEnv->e_envid = newstr(optarg);
define(macid("{dsn_envid}", NULL),
newstr(optarg), CurEnv);
}
break;
case 'X': /* traffic log file */
dp = drop_privileges(TRUE);
setstat(dp);
if (stat(optarg, &traf_st) == 0 &&
S_ISFIFO(traf_st.st_mode))
TrafficLogFile = fopen(optarg, "w");
else
TrafficLogFile = fopen(optarg, "a");
if (TrafficLogFile == NULL)
{
syserr("cannot open %s", optarg);
ExitStat = EX_CANTCREAT;
break;
}
#if HASSETVBUF
(void) setvbuf(TrafficLogFile, NULL, _IOLBF, 0);
#else /* HASSETVBUF */
(void) setlinebuf(TrafficLogFile);
#endif /* HASSETVBUF */
break;
/* compatibility flags */
case 'c': /* connect to non-local mailers */
case 'i': /* don't let dot stop me */
case 'm': /* send to me too */
case 'T': /* set timeout interval */
case 'v': /* give blow-by-blow description */
setoption(j, "T", FALSE, TRUE, CurEnv);
break;
case 'e': /* error message disposition */
case 'M': /* define macro */
setoption(j, optarg, FALSE, TRUE, CurEnv);
break;
case 's': /* save From lines in headers */
setoption('f', "T", FALSE, TRUE, CurEnv);
break;
#ifdef DBM
case 'I': /* initialize alias DBM file */
OpMode = MD_INITALIAS;
break;
#endif /* DBM */
#if defined(__osf__) || defined(_AIX3)
case 'x': /* random flag that OSF/1 & AIX mailx passes */
break;
#endif /* defined(__osf__) || defined(_AIX3) */
#if defined(sony_news)
case 'E':
case 'J': /* ignore flags for Japanese code conversion
implemented on Sony NEWS */
break;
#endif /* defined(sony_news) */
default:
finis(TRUE, EX_USAGE);
break;
}
}
av += optind;
if (bitset(SUBMIT_MTA, SubmitMode) &&
bitset(SUBMIT_MSA, SubmitMode))
{
/* sanity check */
errno = 0; /* reset to avoid bogus error messages */
syserr("Cannot use both -G and -U together");
}
else if (bitset(SUBMIT_MTA, SubmitMode))
define(macid("{daemon_flags}", NULL), "CC f", CurEnv);
else if (bitset(SUBMIT_MSA, SubmitMode))
{
define(macid("{daemon_flags}", NULL), "c u", CurEnv);
/* check for wrong OpMode */
if (OpMode != MD_DELIVER && OpMode != MD_SMTP)
{
errno = 0; /* reset to avoid bogus error msgs */
syserr("Cannot use -U and -b%c", OpMode);
}
}
else
{
#if _FFR_DEFAULT_SUBMIT_TO_MSA
define(macid("{daemon_flags}", NULL), "c u", CurEnv);
#else /* _FFR_DEFAULT_SUBMIT_TO_MSA */
/* EMPTY */
#endif /* _FFR_DEFAULT_SUBMIT_TO_MSA */
}
/*
** Do basic initialization.
** Read system control file.
** Extract special fields for local use.
*/
/* set up ${opMode} for use in config file */
{
char mbuf[2];
mbuf[0] = OpMode;
mbuf[1] = '\0';
define(MID_OPMODE, newstr(mbuf), CurEnv);
}
#if XDEBUG
checkfd012("before readcf");
#endif /* XDEBUG */
vendor_pre_defaults(CurEnv);
readcf(getcfname(), safecf, CurEnv);
ConfigFileRead = TRUE;
vendor_post_defaults(CurEnv);
/* Enforce use of local time (null string overrides this) */
if (TimeZoneSpec == NULL)
unsetenv("TZ");
else if (TimeZoneSpec[0] != '\0')
setuserenv("TZ", TimeZoneSpec);
else
setuserenv("TZ", NULL);
tzset();
/* avoid denial-of-service attacks */
resetlimits();
if (OpMode != MD_DAEMON && OpMode != MD_FGDAEMON)
{
/* drop privileges -- daemon mode done after socket/bind */
dp = drop_privileges(FALSE);
setstat(dp);
}
#if NAMED_BIND
_res.retry = TimeOuts.res_retry[RES_TO_DEFAULT];
_res.retrans = TimeOuts.res_retrans[RES_TO_DEFAULT];
#endif /* NAMED_BIND */
/*
** Find our real host name for future logging.
*/
authinfo = getauthinfo(STDIN_FILENO, &forged);
define('_', authinfo, CurEnv);
/* suppress error printing if errors mailed back or whatever */
if (CurEnv->e_errormode != EM_PRINT)
HoldErrs = TRUE;
/* set up the $=m class now, after .cf has a chance to redefine $m */
expand("\201m", jbuf, sizeof jbuf, CurEnv);
setclass('m', jbuf);
/* probe interfaces and locate any additional names */
if (!DontProbeInterfaces)
load_if_names();
if (tTd(0, 1))
{
dprintf("\n============ SYSTEM IDENTITY (after readcf) ============");
dprintf("\n (short domain name) $w = ");
xputs(macvalue('w', CurEnv));
dprintf("\n (canonical domain name) $j = ");
xputs(macvalue('j', CurEnv));
dprintf("\n (subdomain name) $m = ");
xputs(macvalue('m', CurEnv));
dprintf("\n (node name) $k = ");
xputs(macvalue('k', CurEnv));
dprintf("\n========================================================\n\n");
}
/*
** Do more command line checking -- these are things that
** have to modify the results of reading the config file.
*/
/* process authorization warnings from command line */
if (warn_C_flag)
auth_warning(CurEnv, "Processed by %s with -C %s",
RealUserName, ConfFile);
if (Warn_Q_option && !wordinclass(RealUserName, 't'))
auth_warning(CurEnv, "Processed from queue %s", QueueDir);
/* check body type for legality */
if (CurEnv->e_bodytype == NULL)
/* EMPTY */
/* nothing */ ;
else if (strcasecmp(CurEnv->e_bodytype, "7BIT") == 0)
SevenBitInput = TRUE;
else if (strcasecmp(CurEnv->e_bodytype, "8BITMIME") == 0)
SevenBitInput = FALSE;
else
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -