⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 deliver.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:

# if NETINET6
			if (*mxhosts[hostnum] == '[')
			{
				endp = strchr(mxhosts[hostnum] + 1, ']');
				if (endp != NULL)
					endp = strpbrk(endp + 1, ":,");
			}
			else
				endp = strpbrk(mxhosts[hostnum], ":,");
# else /* NETINET6 */
			endp = strpbrk(mxhosts[hostnum], ":,");
# endif /* NETINET6 */
			if (endp != NULL)
			{
				sep = *endp;
				*endp = '\0';
			}

			if (*mxhosts[hostnum] == '\0')
			{
				syserr("deliver: null host name in signature");
				hostnum++;
				if (endp != NULL)
					*endp = sep;
				continue;
			}
			(void) strlcpy(hostbuf, mxhosts[hostnum],
				       sizeof hostbuf);
			hostnum++;
			if (endp != NULL)
				*endp = sep;

			/* see if we already know that this host is fried */
			CurHostName = hostbuf;
			mci = mci_get(hostbuf, m);
			if (mci->mci_state != MCIS_CLOSED)
			{
				if (tTd(11, 1))
				{
					dprintf("openmailer: ");
					mci_dump(mci, FALSE);
				}
				CurHostName = mci->mci_host;
				message("Using cached %sSMTP connection to %s via %s...",
					bitset(MCIF_ESMTP, mci->mci_flags) ? "E" : "",
					hostbuf, m->m_name);
				mci->mci_deliveries++;
				break;
			}
			mci->mci_mailer = m;
			if (mci->mci_exitstat != EX_OK)
			{
				if (mci->mci_exitstat == EX_TEMPFAIL)
					goodmxfound = TRUE;
				continue;
			}

			if (mci_lock_host(mci) != EX_OK)
			{
				mci_setstat(mci, EX_TEMPFAIL, "4.4.5", NULL);
				goodmxfound = TRUE;
				continue;
			}

			/* try the connection */
			sm_setproctitle(TRUE, e, "%s %s: %s",
					qid_printname(e),
					hostbuf, "user open");
# if NETUNIX
			if (mux_path != NULL)
			{
				message("Connecting to %s via %s...",
					mux_path, m->m_name);
				i = makeconnection_ds(mux_path, mci);
			}
			else
# endif /* NETUNIX */
			{
				if (port == 0)
					message("Connecting to %s via %s...",
						hostbuf, m->m_name);
				else
					message("Connecting to %s port %d via %s...",
						hostbuf, ntohs(port),
						m->m_name);
				i = makeconnection(hostbuf, port, mci, e);
			}
			mci->mci_lastuse = curtime();
			mci->mci_deliveries = 0;
			mci->mci_exitstat = i;
			mci->mci_errno = errno;
# if NAMED_BIND
			mci->mci_herrno = h_errno;
# endif /* NAMED_BIND */
			if (i == EX_OK)
			{
				goodmxfound = TRUE;
				mci->mci_state = MCIS_OPENING;
				mci_cache(mci);
				if (TrafficLogFile != NULL)
					fprintf(TrafficLogFile, "%05d === CONNECT %s\n",
						(int) getpid(), hostbuf);
				break;
			}
			else
			{
				if (tTd(11, 1))
					dprintf("openmailer: makeconnection => stat=%d, errno=%d\n",
						i, errno);
				if (i == EX_TEMPFAIL)
					goodmxfound = TRUE;
				mci_unlock_host(mci);
			}

			/* enter status of this host */
			setstat(i);

			/* should print some message here for -v mode */
		}
		if (mci == NULL)
		{
			syserr("deliver: no host name");
			rcode = EX_SOFTWARE;
			goto give_up;
		}
		mci->mci_pid = 0;
#else /* DAEMON */
		syserr("554 5.3.5 openmailer: no IPC");
		if (tTd(11, 1))
			dprintf("openmailer: NULL\n");
		rcode = EX_UNAVAILABLE;
		goto give_up;
#endif /* DAEMON */
	}
	else
	{
		/* flush any expired connections */
		(void) mci_scan(NULL);
		mci = NULL;

#if SMTP
		if (bitnset(M_LMTP, m->m_flags))
		{
			/* try to get a cached connection */
			mci = mci_get(m->m_name, m);
			if (mci->mci_host == NULL)
				mci->mci_host = m->m_name;
			CurHostName = mci->mci_host;
			if (mci->mci_state != MCIS_CLOSED)
			{
				message("Using cached LMTP connection for %s...",
					m->m_name);
				mci->mci_deliveries++;
				goto do_transfer;
			}
		}
#endif /* SMTP */

		/* announce the connection to verbose listeners */
		if (host == NULL || host[0] == '\0')
			message("Connecting to %s...", m->m_name);
		else
			message("Connecting to %s via %s...", host, m->m_name);
		if (TrafficLogFile != NULL)
		{
			char **av;

			fprintf(TrafficLogFile, "%05d === EXEC", (int) getpid());
			for (av = pv; *av != NULL; av++)
				fprintf(TrafficLogFile, " %s", *av);
			fprintf(TrafficLogFile, "\n");
		}

#if XDEBUG
		checkfd012("before creating mail pipe");
#endif /* XDEBUG */

		/* create a pipe to shove the mail through */
		if (pipe(mpvect) < 0)
		{
			syserr("%s... openmailer(%s): pipe (to mailer)",
				shortenstring(e->e_to, MAXSHORTSTR), m->m_name);
			if (tTd(11, 1))
				dprintf("openmailer: NULL\n");
			rcode = EX_OSERR;
			goto give_up;
		}

#if XDEBUG
		/* make sure we didn't get one of the standard I/O files */
		if (mpvect[0] < 3 || mpvect[1] < 3)
		{
			syserr("%s... openmailer(%s): bogus mpvect %d %d",
				shortenstring(e->e_to, MAXSHORTSTR), m->m_name,
				mpvect[0], mpvect[1]);
			printopenfds(TRUE);
			if (tTd(11, 1))
				dprintf("openmailer: NULL\n");
			rcode = EX_OSERR;
			goto give_up;
		}

		/* make sure system call isn't dead meat */
		checkfdopen(mpvect[0], "mpvect[0]");
		checkfdopen(mpvect[1], "mpvect[1]");
		if (mpvect[0] == mpvect[1] ||
		    (e->e_lockfp != NULL &&
		     (mpvect[0] == fileno(e->e_lockfp) ||
		      mpvect[1] == fileno(e->e_lockfp))))
		{
			if (e->e_lockfp == NULL)
				syserr("%s... openmailer(%s): overlapping mpvect %d %d",
					shortenstring(e->e_to, MAXSHORTSTR),
					m->m_name, mpvect[0], mpvect[1]);
			else
				syserr("%s... openmailer(%s): overlapping mpvect %d %d, lockfp = %d",
					shortenstring(e->e_to, MAXSHORTSTR),
					m->m_name, mpvect[0], mpvect[1],
					fileno(e->e_lockfp));
		}
#endif /* XDEBUG */

		/* create a return pipe */
		if (pipe(rpvect) < 0)
		{
			syserr("%s... openmailer(%s): pipe (from mailer)",
				shortenstring(e->e_to, MAXSHORTSTR),
				m->m_name);
			(void) close(mpvect[0]);
			(void) close(mpvect[1]);
			if (tTd(11, 1))
				dprintf("openmailer: NULL\n");
			rcode = EX_OSERR;
			goto give_up;
		}
#if XDEBUG
		checkfdopen(rpvect[0], "rpvect[0]");
		checkfdopen(rpvect[1], "rpvect[1]");
#endif /* XDEBUG */

		/*
		**  Actually fork the mailer process.
		**	DOFORK is clever about retrying.
		**
		**	Dispose of SIGCHLD signal catchers that may be laying
		**	around so that endmailer will get it.
		*/

		if (e->e_xfp != NULL)
			(void) fflush(e->e_xfp);	/* for debugging */
		(void) fflush(stdout);
		(void) setsignal(SIGCHLD, SIG_DFL);


		DOFORK(FORK);
		/* pid is set by DOFORK */

		if (pid < 0)
		{
			/* failure */
			syserr("%s... openmailer(%s): cannot fork",
				shortenstring(e->e_to, MAXSHORTSTR), m->m_name);
			(void) close(mpvect[0]);
			(void) close(mpvect[1]);
			(void) close(rpvect[0]);
			(void) close(rpvect[1]);
			if (tTd(11, 1))
				dprintf("openmailer: NULL\n");
			rcode = EX_OSERR;
			goto give_up;
		}
		else if (pid == 0)
		{
			int i;
			int save_errno;
			int new_euid = NO_UID;
			int new_ruid = NO_UID;
			int new_gid = NO_GID;
			struct stat stb;
			extern int DtableSize;

			if (e->e_lockfp != NULL)
				(void) close(fileno(e->e_lockfp));

			/* child -- set up input & exec mailer */
			(void) setsignal(SIGINT, SIG_IGN);
			(void) setsignal(SIGHUP, SIG_IGN);
			(void) setsignal(SIGTERM, SIG_DFL);

			if (m != FileMailer || stat(tochain->q_user, &stb) < 0)
				stb.st_mode = 0;

# if HASSETUSERCONTEXT
			/*
			**  Set user resources.
			*/

			if (contextaddr != NULL)
			{
				struct passwd *pwd;

				if (contextaddr->q_ruser != NULL)
					pwd = sm_getpwnam(contextaddr->q_ruser);
				else
					pwd = sm_getpwnam(contextaddr->q_user);
				if (pwd != NULL)
					(void) setusercontext(NULL,
						pwd, pwd->pw_uid,
						LOGIN_SETRESOURCES|LOGIN_SETPRIORITY);
			}
# endif /* HASSETUSERCONTEXT */

			/* tweak niceness */
			if (m->m_nice != 0)
				(void) nice(m->m_nice);

			/* reset group id */
			if (bitnset(M_SPECIFIC_UID, m->m_flags))
				new_gid = m->m_gid;
			else if (bitset(S_ISGID, stb.st_mode))
				new_gid = stb.st_gid;
			else if (ctladdr != NULL && ctladdr->q_gid != 0)
			{
				if (!DontInitGroups)
				{
					char *u = ctladdr->q_ruser;

					if (u == NULL)
						u = ctladdr->q_user;

					if (initgroups(u, ctladdr->q_gid) == -1 && suidwarn)
					{
						syserr("openmailer: initgroups(%s, %d) failed",
							u, ctladdr->q_gid);
						exit(EX_TEMPFAIL);
					}
				}
				else
				{
					GIDSET_T gidset[1];

					gidset[0] = ctladdr->q_gid;
					if (setgroups(1, gidset) == -1 && suidwarn)
					{
						syserr("openmailer: setgroups() failed");
						exit(EX_TEMPFAIL);
					}
				}
				new_gid = ctladdr->q_gid;
			}
			else
			{
				if (!DontInitGroups)
				{
					if (initgroups(DefUser, DefGid) == -1 && suidwarn)
					{
						syserr("openmailer: initgroups(%s, %d) failed",
							DefUser, DefGid);
						exit(EX_TEMPFAIL);
					}
				}
				else
				{
					GIDSET_T gidset[1];

					gidset[0] = DefGid;
					if (setgroups(1, gidset) == -1 && suidwarn)
					{
						syserr("openmailer: setgroups() failed");
						exit(EX_TEMPFAIL);
					}
				}
				if (m->m_gid == 0)
					new_gid = DefGid;
				else
					new_gid = m->m_gid;
			}
			if (new_gid != NO_GID)
			{
				if (RunAsUid != 0 &&
				    bitnset(M_SPECIFIC_UID, m->m_flags) &&
				    new_gid != getgid() &&
				    new_gid != getegid())
				{
					/* Only root can change the gid */
					syserr("openmailer: insufficient privileges to change gid");
					exit(EX_TEMPFAIL);
				}

				if (setgid(new_gid) < 0 && suidwarn)
				{
					syserr("openmailer: setgid(%ld) failed",
					       (long) new_gid);
					exit(EX_TEMPFAIL);
				}
			}

			/* change root to some "safe" directory */
			if (m->m_rootdir != NULL)
			{
				expand(m->m_rootdir, buf, sizeof buf, e);
				if (tTd(11, 20))
					dprintf("openmailer: chroot %s\n",
						buf);
				if (chroot(buf) < 0)
				{
					syserr("openmailer: Cannot chroot(%s)",
					       buf);
					exit(EX_TEMPFAIL);
				}
				if (chdir("/") < 0)
				{
					syserr("openmailer: cannot chdir(/)");
					exit(EX_TEMPFAIL);
				}
			}

			/* reset user id */
			endpwent();
			if (bitnset(M_SPECIFIC_UID, m->m_flags))
				new_euid = m->m_uid;
			else if (bitset(S_ISUID, stb.st_mode))
				new_ruid = stb.st_uid;
			else if (ctladdr != NULL && ctladdr->q_uid != 0)
				new_ruid = ctladdr->q_uid;
			else if (m->m_uid != 0)
				new_ruid = m->m_uid;
			else
				new_ruid = DefUid;
			if (new_euid != NO_UID)
			{
				if (RunAsUid != 0 && new_euid != RunAsUid)
				{
					/* Only root can change the uid */
					syserr("openmailer: insufficient privileges to change uid");
					exit(EX_TEMPFAIL);
				}

				vendor_set_uid(new_euid);
# if MAILER_SETUID_METHOD == USE_SETEUID
				if (seteuid(new_euid) < 0 && suidwarn)
				{
					syserr("openmailer: seteuid(%ld) failed",
						(long) new_euid);
					exit(EX_TEMPFAIL);
				}
# endif /* MAILER_SETUID_METHOD == USE_SETEUID */
# if MAILER_SETUID_METHOD == USE_SETREUID
				if (setreuid(new_ruid, new_euid) < 0 && suidwarn)
				{
					syserr("openmailer: setreuid(%ld, %ld) failed",
						(long) new_ruid, (long) new_euid);
					exit(EX_TEMPFAIL);
				}
# endif /* MAILER_SETUID_METHOD == USE_SETREUID */
# if MAILER_SETUID_METHOD == USE_SETUID
				if (new_euid != geteuid() && setuid(new_euid) < 0 && suidwarn)
				{
					syserr("openmailer: setuid(%ld) failed",
						(long) new_euid);
					exit(EX_TEMPFAIL);
				}
# endif /* MAILER_SETUID_METHOD == USE_SETUID */
			}
			else if (new_ruid != NO_UID)
			{
				vendor_set_uid(new_ruid);
				if (setuid(new_ruid) < 0 && suidwarn)
				{
					syserr("openmailer: setuid(%ld) failed",
						(long) new_ruid);
					exit(EX_TEMPFAIL);
				}
			}

			if (tTd(11, 2))
				dprintf("openmailer: running as r/euid=%d/%d, r/egid=%d/%d\n",
					(int) getuid(), (int) geteuid(),
					(int) getgid(), (int) getegid());

			/* move into some "safe" directory */
			if (m->m_execdir != NULL)
			{
				char *q;

				for (p = m->m_execdir; p != NULL; p = q)
				{
					q = strchr(p, ':');
					if (q != NULL)
						*q = '\0';
					expand(p, buf, sizeof buf, e);
					if (q != NULL)
						*q++ = ':';
					if (tTd(11, 20))
						dprintf("openmailer: trydir %s\n",
							buf);
					if (buf[0] != '\0' && chdir(buf) >= 0)
						break;
				}
			}

			/* arrange to filter std & diag output of command */
			(void) close(rpvect[0]);
			if (dup2(rpvect[1], STDOUT_FILENO) < 0)
			{
				syserr("%s... openmailer(%s): cannot dup pipe %d for stdout",
				       shortenstring(e->e_to, MAXSHORTSTR),
				       m->m_name, rpvect[1]);
				_exit(EX_OSERR);
			}
			(void) close(rpvect[1]);

			if (dup2(STDOUT_FILENO, STDERR_FILENO) < 0)
			{
				syserr("%s... openmailer(%s): cannot dup stdout for stderr",
					shortenstring(e->e_to, MAXSHORTSTR),
					m->m_name);
				_exit(EX_OSERR);
			}

			/* arrange to get standard input */
			(void) close(mpvect[1]);
			if (dup2(mpvect[0], STDIN_FILENO) < 0)
			{
				syserr("%s... openmailer(%s): cannot dup pipe %d for stdin",
					shortenstring(e->e_to, MAXSHORTSTR),
					m->m_name, mpvect[0]);
				_exit(EX_OSERR);
			}
			(void) close(mpvect[0]);

			/* arrange for all the files to be closed */
			for (i = 3; i < DtableSize; i++)
			{
				register int j;

				if ((j = fcntl(i, F_GETFD, 0)) != -1)
					(void) fcntl(i, F_SETFD,
						     j | FD_CLOEXEC);
			}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -