📄 main.c
字号:
#ifdef LOG syslog(LOG_INFO, "starting daemon (%s): %s", Version, dtype + 1);#endif#ifdef XLA xla_create_file();#endif# ifdef QUEUE if (queuemode) { runqueue(TRUE); if (OpMode != MD_DAEMON) for (;;) pause(); }# endif /* QUEUE */ dropenvelope(CurEnv);#ifdef DAEMON getrequests(); /* at this point we are in a child: reset state */ (void) newenvelope(CurEnv, CurEnv); /* ** Get authentication data */ p = getauthinfo(fileno(InChannel)); define('_', p, CurEnv);#endif /* DAEMON */ } # ifdef SMTP /* ** If running SMTP protocol, start collecting and executing ** commands. This will never return. */ if (OpMode == MD_SMTP || OpMode == MD_DAEMON) smtp(CurEnv);# endif /* SMTP */ if (OpMode == MD_VERIFY) { CurEnv->e_sendmode = SM_VERIFY; CurEnv->e_errormode = EM_QUIET; } else { /* interactive -- all errors are global */ CurEnv->e_flags |= EF_GLOBALERRS; } /* ** Do basic system initialization and set the sender */ initsys(CurEnv); setsender(from, CurEnv, NULL, FALSE); if (macvalue('s', CurEnv) == NULL) define('s', RealHostName, CurEnv); if (*av == NULL && !GrabTo) { CurEnv->e_flags |= EF_GLOBALERRS; usrerr("Recipient names must be specified"); /* collect body for UUCP return */ if (OpMode != MD_VERIFY) collect(FALSE, FALSE, CurEnv); finis(); } /* ** Scan argv and deliver the message to everyone. */ sendtoargv(av, CurEnv); /* if we have had errors sofar, arrange a meaningful exit stat */ if (Errors > 0 && ExitStat == EX_OK) ExitStat = EX_USAGE; /* ** Read the input mail. */ CurEnv->e_to = NULL; if (OpMode != MD_VERIFY || GrabTo) { CurEnv->e_flags |= EF_GLOBALERRS; collect(FALSE, FALSE, CurEnv); } errno = 0; if (tTd(1, 1)) printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr); /* ** Actually send everything. ** If verifying, just ack. */ CurEnv->e_from.q_flags |= QDONTSEND; if (tTd(1, 5)) { printf("main: QDONTSEND "); printaddr(&CurEnv->e_from, FALSE); } CurEnv->e_to = NULL; sendall(CurEnv, SM_DEFAULT); /* ** All done. ** Don't send return error message if in VERIFY mode. */ finis();}/*** FINIS -- Clean up and exit.**** Parameters:** none**** Returns:** never**** Side Effects:** exits sendmail*/finis(){ if (tTd(2, 1)) printf("\n====finis: stat %d e_flags %o, e_id=%s\n", ExitStat, CurEnv->e_flags, CurEnv->e_id == NULL ? "NOQUEUE" : CurEnv->e_id); if (tTd(2, 9)) printopenfds(FALSE); /* clean up temp files */ CurEnv->e_to = NULL; dropenvelope(CurEnv); /* flush any cached connections */ mci_flush(TRUE, NULL);# ifdef XLA /* clean up extended load average stuff */ xla_all_end();# endif /* and exit */# ifdef LOG if (LogLevel > 78) syslog(LOG_DEBUG, "finis, pid=%d", getpid());# endif /* LOG */ if (ExitStat == EX_TEMPFAIL) ExitStat = EX_OK; /* reset uid for process accounting */ setuid(RealUid); exit(ExitStat);}/*** INTSIG -- clean up on interrupt**** This just arranges to exit. It pessimises in that it** may resend a message.**** Parameters:** none.**** Returns:** none.**** Side Effects:** Unlocks the current job.*/voidintsig(){ FileName = NULL; unlockqueue(CurEnv);#ifdef XLA xla_all_end();#endif /* reset uid for process accounting */ setuid(RealUid); exit(EX_OK);}/*** INITMACROS -- initialize the macro system**** This just involves defining some macros that are actually** used internally as metasymbols to be themselves.**** Parameters:** none.**** Returns:** none.**** Side Effects:** initializes several macros to be themselves.*/struct metamac MetaMacros[] ={ /* LHS pattern matching characters */ '*', MATCHZANY, '+', MATCHANY, '-', MATCHONE, '=', MATCHCLASS, '~', MATCHNCLASS, /* these are RHS metasymbols */ '#', CANONNET, '@', CANONHOST, ':', CANONUSER, '>', CALLSUBR, /* the conditional operations */ '?', CONDIF, '|', CONDELSE, '.', CONDFI, /* the hostname lookup characters */ '[', HOSTBEGIN, ']', HOSTEND, '(', LOOKUPBEGIN, ')', LOOKUPEND, /* miscellaneous control characters */ '&', MACRODEXPAND, '\0'};initmacros(e) register ENVELOPE *e;{ register struct metamac *m; char buf[5]; register int c; for (m = MetaMacros; m->metaname != '\0'; m++) { buf[0] = m->metaval; buf[1] = '\0'; define(m->metaname, newstr(buf), e); } buf[0] = MATCHREPL; buf[2] = '\0'; for (c = '0'; c <= '9'; c++) { buf[1] = c; define(c, newstr(buf), e); } /* set defaults for some macros sendmail will use later */ define('e', "\201j Sendmail \201v ready at \201b", e); define('l', "From \201g \201d", e); define('n', "MAILER-DAEMON", e); define('o', ".:@[]", e); define('q', "<\201g>", e);}/*** DISCONNECT -- remove our connection with any foreground process**** Parameters:** droplev -- how "deeply" we should drop the line.** 0 -- ignore signals, mail back errors, make sure** output goes to stdout.** 1 -- also, make stdout go to transcript.** 2 -- also, disconnect from controlling terminal** (only for daemon mode).** e -- the current envelope.**** Returns:** none**** Side Effects:** Trys to insure that we are immune to vagaries of** the controlling tty.*/disconnect(droplev, e) int droplev; register ENVELOPE *e;{ int fd; if (tTd(52, 1)) printf("disconnect: In %d Out %d, e=%x\n", fileno(InChannel), fileno(OutChannel), e); if (tTd(52, 5)) { printf("don't\n"); return; } /* be sure we don't get nasty signals */ (void) setsignal(SIGHUP, SIG_IGN); (void) setsignal(SIGINT, SIG_IGN); (void) setsignal(SIGQUIT, SIG_IGN); /* we can't communicate with our caller, so.... */ HoldErrs = TRUE; CurEnv->e_errormode = EM_MAIL; Verbose = FALSE; DisConnected = TRUE; /* all input from /dev/null */ if (InChannel != stdin) { (void) fclose(InChannel); InChannel = stdin; } (void) freopen("/dev/null", "r", stdin); /* output to the transcript */ if (OutChannel != stdout) { (void) fclose(OutChannel); OutChannel = stdout; } if (droplev > 0) { if (e->e_xfp == NULL) fd = open("/dev/null", O_WRONLY, 0666); else fd = fileno(e->e_xfp); (void) fflush(stdout); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (e->e_xfp == NULL) close(fd); } /* drop our controlling TTY completely if possible */ if (droplev > 1) { (void) setsid(); errno = 0; }#ifdef XDEBUG checkfd012("disconnect");#endif# ifdef LOG if (LogLevel > 71) syslog(LOG_DEBUG, "in background, pid=%d", getpid());# endif /* LOG */ errno = 0;}static voidobsolete(argv) char *argv[];{ register char *ap; register char *op; while ((ap = *++argv) != NULL) { /* Return if "--" or not an option of any form. */ if (ap[0] != '-' || ap[1] == '-') return; /* skip over options that do have a value */ op = strchr(OPTIONS, ap[1]); if (op != NULL && *++op == ':' && ap[2] == '\0' && ap[1] != 'd' && argv[1] != NULL && argv[1][0] != '-') { argv++; continue; } /* If -C doesn't have an argument, use sendmail.cf. */#define __DEFPATH "sendmail.cf" if (ap[1] == 'C' && ap[2] == '\0') { *argv = xalloc(sizeof(__DEFPATH) + 2); argv[0][0] = '-'; argv[0][1] = 'C'; (void)strcpy(&argv[0][2], __DEFPATH); } /* If -q doesn't have an argument, run it once. */ if (ap[1] == 'q' && ap[2] == '\0') *argv = "-q0"; /* if -d doesn't have an argument, use 0-99.1 */ if (ap[1] == 'd' && ap[2] == '\0') *argv = "-d0-99.1"; }}/*** AUTH_WARNING -- specify authorization warning**** Parameters:** e -- the current envelope.** msg -- the text of the message.** args -- arguments to the message.**** Returns:** none.*/void#ifdef __STDC__auth_warning(register ENVELOPE *e, const char *msg, ...)#elseauth_warning(e, msg, va_alist) register ENVELOPE *e; const char *msg; va_dcl#endif{ char buf[MAXLINE]; VA_LOCAL_DECL if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags)) { register char *p; static char hostbuf[48]; extern char **myhostname(); if (hostbuf[0] == '\0') (void) myhostname(hostbuf, sizeof hostbuf); (void) sprintf(buf, "%s: ", hostbuf); p = &buf[strlen(buf)]; VA_START(msg); vsprintf(p, msg, ap); VA_END; addheader("X-Authentication-Warning", buf, e); }}/*** DUMPSTATE -- dump state**** For debugging.*/voiddumpstate(when) char *when;{#ifdef LOG register char *j = macvalue('j', CurEnv); register STAB *s; syslog(LOG_DEBUG, "--- dumping state on %s: $j = %s ---", when, j == NULL ? "<NULL>" : j); if (j != NULL) { s = stab(j, ST_CLASS, ST_FIND); if (s == NULL || !bitnset('w', s->s_class)) syslog(LOG_DEBUG, "*** $j not in $=w ***"); } syslog(LOG_DEBUG, "--- open file descriptors: ---"); printopenfds(TRUE); syslog(LOG_DEBUG, "--- connection cache: ---"); mci_dump_all(TRUE); if (RewriteRules[89] != NULL) { int stat; register char **pvp; char *pv[MAXATOM + 1]; pv[0] = NULL; stat = rewrite(pv, 89, 0, CurEnv); syslog(LOG_DEBUG, "--- ruleset 89 returns stat %d, pv: ---", stat); for (pvp = pv; *pvp != NULL; pvp++) syslog(LOG_DEBUG, "%s", *pvp); } syslog(LOG_DEBUG, "--- end of state dump ---");#endif}voidsigusr1(){ dumpstate("user signal");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -