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

📄 main.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	/*XXX should probably add equivalents for all short macros here XXX*/
}
/*
**  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 /dev/null.
**			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.
*/

void
disconnect(droplev, e)
	int droplev;
	register ENVELOPE *e;
{
	int fd;

	if (tTd(52, 1))
		dprintf("disconnect: In %d Out %d, e=%lx\n",
			fileno(InChannel), fileno(OutChannel), (u_long) e);
	if (tTd(52, 100))
	{
		dprintf("don't\n");
		return;
	}
	if (LogLevel > 93)
		sm_syslog(LOG_DEBUG, e->e_id,
			  "disconnect level %d",
			  droplev);

	/* be sure we don't get nasty signals */
	(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 = 0;
	DisConnected = TRUE;

	/* all input from /dev/null */
	if (InChannel != stdin)
	{
		(void) fclose(InChannel);
		InChannel = stdin;
	}
	if (freopen("/dev/null", "r", stdin) == NULL)
		sm_syslog(LOG_ERR, e->e_id,
			  "disconnect: freopen(\"/dev/null\") failed: %s",
			  errstring(errno));

	/* output to the transcript */
	if (OutChannel != stdout)
	{
		(void) fclose(OutChannel);
		OutChannel = stdout;
	}
	if (droplev > 0)
	{
		fd = open("/dev/null", O_WRONLY, 0666);
		if (fd == -1)
			sm_syslog(LOG_ERR, e->e_id,
				  "disconnect: open(\"/dev/null\") failed: %s",
				  errstring(errno));
		(void) fflush(stdout);
		(void) dup2(fd, STDOUT_FILENO);
		(void) dup2(fd, STDERR_FILENO);
		(void) close(fd);
	}

	/* drop our controlling TTY completely if possible */
	if (droplev > 1)
	{
		(void) setsid();
		errno = 0;
	}

#if XDEBUG
	checkfd012("disconnect");
#endif /* XDEBUG */

	if (LogLevel > 71)
		sm_syslog(LOG_DEBUG, e->e_id,
			  "in background, pid=%d",
			  getpid());

	errno = 0;
}

static void
obsolete(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' &&
#if defined(sony_news)
		    ap[1] != 'E' && ap[1] != 'J' &&
#endif /* defined(sony_news) */
		    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);
			(void) snprintf(argv[0], sizeof(__DEFPATH) + 2, "-C%s",
					__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";

#if defined(sony_news)
		/* if -E doesn't have an argument, use -EC */
		if (ap[1] == 'E' && ap[2] == '\0')
			*argv = "-EC";

		/* if -J doesn't have an argument, use -JJ */
		if (ap[1] == 'J' && ap[2] == '\0')
			*argv = "-JJ";
#endif /* defined(sony_news) */
	}
}
/*
**  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, ...)
#else /* __STDC__ */
auth_warning(e, msg, va_alist)
	register ENVELOPE *e;
	const char *msg;
	va_dcl
#endif /* __STDC__ */
{
	char buf[MAXLINE];
	VA_LOCAL_DECL

	if (bitset(PRIV_AUTHWARNINGS, PrivacyFlags))
	{
		register char *p;
		static char hostbuf[48];

		if (hostbuf[0] == '\0')
			(void) myhostname(hostbuf, sizeof hostbuf);

		(void) snprintf(buf, sizeof buf, "%s: ", hostbuf);
		p = &buf[strlen(buf)];
		VA_START(msg);
		vsnprintf(p, SPACELEFT(buf, p), msg, ap);
		VA_END;
		addheader("X-Authentication-Warning", buf, 0, &e->e_header);
		if (LogLevel > 3)
			sm_syslog(LOG_INFO, e->e_id,
				  "Authentication-Warning: %.400s",
				  buf);
	}
}
/*
**  GETEXTENV -- get from external environment
**
**	Parameters:
**		envar -- the name of the variable to retrieve
**
**	Returns:
**		The value, if any.
*/

char *
getextenv(envar)
	const char *envar;
{
	char **envp;
	int l;

	l = strlen(envar);
	for (envp = ExternalEnviron; *envp != NULL; envp++)
	{
		if (strncmp(*envp, envar, l) == 0 && (*envp)[l] == '=')
			return &(*envp)[l + 1];
	}
	return NULL;
}
/*
**  SETUSERENV -- set an environment in the propogated environment
**
**	Parameters:
**		envar -- the name of the environment variable.
**		value -- the value to which it should be set.  If
**			null, this is extracted from the incoming
**			environment.  If that is not set, the call
**			to setuserenv is ignored.
**
**	Returns:
**		none.
*/

void
setuserenv(envar, value)
	const char *envar;
	const char *value;
{
	int i, l;
	char **evp = UserEnviron;
	char *p;

	if (value == NULL)
	{
		value = getextenv(envar);
		if (value == NULL)
			return;
	}

	i = strlen(envar) + 1;
	l = strlen(value) + i + 1;
	p = (char *) xalloc(l);
	(void) snprintf(p, l, "%s=%s", envar, value);

	while (*evp != NULL && strncmp(*evp, p, i) != 0)
		evp++;
	if (*evp != NULL)
	{
		*evp++ = p;
	}
	else if (evp < &UserEnviron[MAXUSERENVIRON])
	{
		*evp++ = p;
		*evp = NULL;
	}

	/* make sure it is in our environment as well */
	if (putenv(p) < 0)
		syserr("setuserenv: putenv(%s) failed", p);
}
/*
**  DUMPSTATE -- dump state
**
**	For debugging.
*/

void
dumpstate(when)
	char *when;
{
	register char *j = macvalue('j', CurEnv);
	int rs;
	extern int NextMacroId;

	sm_syslog(LOG_DEBUG, CurEnv->e_id,
		  "--- dumping state on %s: $j = %s ---",
		  when,
		  j == NULL ? "<NULL>" : j);
	if (j != NULL)
	{
		if (!wordinclass(j, 'w'))
			sm_syslog(LOG_DEBUG, CurEnv->e_id,
				  "*** $j not in $=w ***");
	}
	sm_syslog(LOG_DEBUG, CurEnv->e_id, "CurChildren = %d", CurChildren);
	sm_syslog(LOG_DEBUG, CurEnv->e_id, "NextMacroId = %d (Max %d)\n",
		  NextMacroId, MAXMACROID);
	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- open file descriptors: ---");
	printopenfds(TRUE);
	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- connection cache: ---");
	mci_dump_all(TRUE);
	rs = strtorwset("debug_dumpstate", NULL, ST_FIND);
	if (rs > 0)
	{
		int status;
		register char **pvp;
		char *pv[MAXATOM + 1];

		pv[0] = NULL;
		status = rewrite(pv, rs, 0, CurEnv);
		sm_syslog(LOG_DEBUG, CurEnv->e_id,
			  "--- ruleset debug_dumpstate returns stat %d, pv: ---",
			  status);
		for (pvp = pv; *pvp != NULL; pvp++)
			sm_syslog(LOG_DEBUG, CurEnv->e_id, "%s", *pvp);
	}
	sm_syslog(LOG_DEBUG, CurEnv->e_id, "--- end of state dump ---");
}


/* ARGSUSED */
SIGFUNC_DECL
sigusr1(sig)
	int sig;
{
	dumpstate("user signal");
	return SIGFUNC_RETURN;
}


/* ARGSUSED */
SIGFUNC_DECL
sighup(sig)
	int sig;
{
	int i;
	extern int DtableSize;

	clear_events();
	(void) alarm(0);
	if (SaveArgv[0][0] != '/')
	{
		if (LogLevel > 3)
			sm_syslog(LOG_INFO, NOQID,
				  "could not restart: need full path");
		finis(FALSE, EX_OSFILE);
	}
	if (LogLevel > 3)
		sm_syslog(LOG_INFO, NOQID, "restarting %s %s",
			  sig == 0 ? "due to control command" : "on signal",
			  SaveArgv[0]);

	/* Control socket restart? */
	if (sig != 0)
		(void) releasesignal(SIGHUP);

	closecontrolsocket(TRUE);
	if (drop_privileges(TRUE) != EX_OK)
	{
		if (LogLevel > 0)
			sm_syslog(LOG_ALERT, NOQID,
				  "could not set[ug]id(%d, %d): %m",
				  RunAsUid, RunAsGid);
		finis(FALSE, EX_OSERR);
	}

	/* 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);
	}

	(void) execve(SaveArgv[0], (ARGV_T) SaveArgv, (ARGV_T) ExternalEnviron);
	if (LogLevel > 0)
		sm_syslog(LOG_ALERT, NOQID, "could not exec %s: %m",
			  SaveArgv[0]);
	finis(FALSE, EX_OSFILE);
}
/*
**  DROP_PRIVILEGES -- reduce privileges to those of the RunAsUser option
**
**	Parameters:
**		to_real_uid -- if set, drop to the real uid instead
**			of the RunAsUser.
**
**	Returns:
**		EX_OSERR if the setuid failed.
**		EX_OK otherwise.
*/

int
drop_privileges(to_real_uid)
	bool to_real_uid;
{
	int rval = EX_OK;
	GIDSET_T emptygidset[1];

	if (tTd(47, 1))
		dprintf("drop_privileges(%d): Real[UG]id=%d:%d, RunAs[UG]id=%d:%d\n",
			(int)to_real_uid, (int)RealUid,
			(int)RealGid, (int)RunAsUid, (int)RunAsGid);

	if (to_real_uid)
	{
		RunAsUserName = RealUserName;
		RunAsUid = RealUid;
		RunAsGid = RealGid;
	}

	/* make sure no one can grab open descriptors for secret files */
	endpwent();

	/* reset group permissions; these can be set later */
	emptygidset[0] = (to_real_uid || RunAsGid != 0) ? RunAsGid : getegid();
	if (setgroups(1, emptygidset) == -1 && geteuid() == 0)
	{
		syserr("drop_privileges: setgroups(1, %d) failed",
		       (int)emptygidset[0]);
		rval = EX_OSERR;
	}

	/* reset primary group and user id */
	if ((to_real_uid || RunAsGid != 0) && setgid(RunAsGid) < 0)
	{
		syserr("drop_privileges: setgid(%d) failed", (int)RunAsGid);
		rval = EX_OSERR;
	}
	if (to_real_uid || RunAsUid != 0)
	{
		uid_t euid = geteuid();

		if (setuid(RunAsUid) < 0)
		{
			syserr("drop_privileges: setuid(%d) failed",
			       (int)RunAsUid);
			rval = EX_OSERR;
		}
		else if (RunAsUid != 0 && setuid(0) == 0)
		{
			/*
			**  Believe it or not, the Linux capability model
			**  allows a non-root process to override setuid()
			**  on a process running as root and prevent that
			**  process from dropping privileges.
			*/

			syserr("drop_privileges: setuid(0) succeeded (when it should not)");
			rval = EX_OSERR;
		}
		else if (RunAsUid != euid && setuid(euid) == 0)
		{
			/*
			**  Some operating systems will keep the saved-uid
			**  if a non-root effective-uid calls setuid(real-uid)
			**  making it possible to set it back again later.
			*/

			syserr("drop_privileges: Unable to drop non-root set-user-id privileges");
			rval = EX_OSERR;
		}
	}
	if (tTd(47, 5))
	{
		dprintf("drop_privileges: e/ruid = %d/%d e/rgid = %d/%d\n",
			(int)geteuid(), (int)getuid(),
			(int)getegid(), (int)getgid());
		dprintf("drop_privileges: RunAsUser = %d:%d\n",
			(int)RunAsUid, (int)RunAsGid);
		if (tTd(47, 10))
			dprintf("drop_privileges: rval = %d\n", rval);
	}
	return rval;
}
/*
**  FILL_FD -- make sure a file descriptor has been properly allocated
**
**	Used to make sure that stdin/out/err are allocated on startup
**
**	Parameters:
**		fd -- the file descriptor to be filled.
**		where -- a string used for logging.  If NULL, this is
**			being called on startup, and logging should
**			not be done.
**
**	Returns:
**		none
*/

void
fill_fd(fd, where)
	int fd;
	char *where;
{
	int i;
	struct stat stbuf;

	if (fstat(fd, &stbuf) >= 0 || errno != EBADF)
		return;

	if (where != NULL)
		syserr("fill_fd: %s: fd %d not open", where, fd);
	else
		MissingFds |= 1 << fd;
	i = open("/dev/null", fd == 0 ? O_RDONLY : O_WRONLY, 0666);
	if (i < 0)
	{
		syserr("!fill_fd: %s: cannot open /dev/null",
			where == NULL ? "startup" : where);
	}
	if (fd != i)
	{
		(void) dup2(i, fd);
		(void) close(i);
	}
}
/*
**  TESTMODELINE -- process a test mode input line
**
**	Parameters:
**		line -- the input line.
**		e -- the current environment.
**	Syntax:
**		#  a comment
**		.X process X as a configuration line
**		=X dump a configuration item (such as mailers)
**		$X dump a macro or class
**		/X try an activity
**		X  normal process through rule set X
*/

static void
testmodeline(line, e)
	char *line;
	ENVELOPE *e;
{
	register char *p;
	char *q;
	auto char *delimptr;
	int mi

⌨️ 快捷键说明

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