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

📄 mci.c

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


void
mci_dump(mci, logit)
	register MCI *mci;
	bool logit;
{
	register char *p;
	char *sep;
	char buf[4000];

	sep = logit ? " " : "\n\t";
	p = buf;
	snprintf(p, SPACELEFT(buf, p), "MCI@%lx: ", (u_long) mci);
	p += strlen(p);
	if (mci == NULL)
	{
		snprintf(p, SPACELEFT(buf, p), "NULL");
		goto printit;
	}
	snprintf(p, SPACELEFT(buf, p), "flags=%lx", mci->mci_flags);
	p += strlen(p);
	if (mci->mci_flags != 0)
	{
		struct mcifbits *f;

		*p++ = '<';
		for (f = MciFlags; f->mcif_bit != 0; f++)
		{
			if (!bitset(f->mcif_bit, mci->mci_flags))
				continue;
			snprintf(p, SPACELEFT(buf, p), "%s,", f->mcif_name);
			p += strlen(p);
		}
		p[-1] = '>';
	}
	snprintf(p, SPACELEFT(buf, p),
		",%serrno=%d, herrno=%d, exitstat=%d, state=%d, pid=%d,%s",
		sep, mci->mci_errno, mci->mci_herrno,
		mci->mci_exitstat, mci->mci_state, (int) mci->mci_pid, sep);
	p += strlen(p);
	snprintf(p, SPACELEFT(buf, p),
		"maxsize=%ld, phase=%s, mailer=%s,%s",
		mci->mci_maxsize,
		mci->mci_phase == NULL ? "NULL" : mci->mci_phase,
		mci->mci_mailer == NULL ? "NULL" : mci->mci_mailer->m_name,
		sep);
	p += strlen(p);
	snprintf(p, SPACELEFT(buf, p),
		"status=%s, rstatus=%s,%s",
		mci->mci_status == NULL ? "NULL" : mci->mci_status,
		mci->mci_rstatus == NULL ? "NULL" : mci->mci_rstatus,
		sep);
	p += strlen(p);
	snprintf(p, SPACELEFT(buf, p),
		"host=%s, lastuse=%s",
		mci->mci_host == NULL ? "NULL" : mci->mci_host,
		ctime(&mci->mci_lastuse));
printit:
	if (logit)
		sm_syslog(LOG_DEBUG, CurEnv->e_id, "%.1000s", buf);
	else
		printf("%s\n", buf);
}
/*
**  MCI_DUMP_ALL -- print the entire MCI cache
**
**	Parameters:
**		logit -- if set, log the result instead of printing
**			to stdout.
**
**	Returns:
**		none.
*/

void
mci_dump_all(logit)
	bool logit;
{
	register int i;

	if (MciCache == NULL)
		return;

	for (i = 0; i < MaxMciCache; i++)
		mci_dump(MciCache[i], logit);
}
/*
**  MCI_LOCK_HOST -- Lock host while sending.
**
**	If we are contacting a host, we'll need to
**	update the status information in the host status
**	file, and if we want to do that, we ought to have
**	locked it. This has the (according to some)
**	desirable effect of serializing connectivity with
**	remote hosts -- i.e.: one connection to a give
**	host at a time.
**
**	Parameters:
**		mci -- containing the host we want to lock.
**
**	Returns:
**		EX_OK	    -- got the lock.
**		EX_TEMPFAIL -- didn't get the lock.
*/

int
mci_lock_host(mci)
	MCI *mci;
{
	if (mci == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_lock_host: NULL mci\n");
		return EX_OK;
	}

	if (!SingleThreadDelivery)
		return EX_OK;

	return mci_lock_host_statfile(mci);
}

static int
mci_lock_host_statfile(mci)
	MCI *mci;
{
	int save_errno = errno;
	int retVal = EX_OK;
	char fname[MAXPATHLEN + 1];

	if (HostStatDir == NULL || mci->mci_host == NULL)
		return EX_OK;

	if (tTd(56, 2))
		dprintf("mci_lock_host: attempting to lock %s\n",
			mci->mci_host);

	if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, TRUE) < 0)
	{
		/* of course this should never happen */
		if (tTd(56, 2))
			dprintf("mci_lock_host: Failed to generate host path for %s\n",
				mci->mci_host);

		retVal = EX_TEMPFAIL;
		goto cleanup;
	}

	mci->mci_statfile = safefopen(fname, O_RDWR, FileMode,
				      SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH|SFF_CREAT);

	if (mci->mci_statfile == NULL)
	{
		syserr("mci_lock_host: cannot create host lock file %s",
			       fname);
		goto cleanup;
	}

	if (!lockfile(fileno(mci->mci_statfile), fname, "", LOCK_EX|LOCK_NB))
	{
		if (tTd(56, 2))
			dprintf("mci_lock_host: couldn't get lock on %s\n",
				fname);
		(void) fclose(mci->mci_statfile);
		mci->mci_statfile = NULL;
		retVal = EX_TEMPFAIL;
		goto cleanup;
	}

	if (tTd(56, 12) && mci->mci_statfile != NULL)
		dprintf("mci_lock_host: Sanity check -- lock is good\n");

cleanup:
	errno = save_errno;
	return retVal;
}
/*
**  MCI_UNLOCK_HOST -- unlock host
**
**	Clean up the lock on a host, close the file, let
**	someone else use it.
**
**	Parameters:
**		mci -- us.
**
**	Returns:
**		nothing.
*/

void
mci_unlock_host(mci)
	MCI *mci;
{
	int save_errno = errno;

	if (mci == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_unlock_host: NULL mci\n");
		return;
	}

	if (HostStatDir == NULL || mci->mci_host == NULL)
		return;

	if (!SingleThreadDelivery && mci_lock_host_statfile(mci) == EX_TEMPFAIL)
	{
		if (tTd(56, 1))
			dprintf("mci_unlock_host: stat file already locked\n");
	}
	else
	{
		if (tTd(56, 2))
			dprintf("mci_unlock_host: store prior to unlock\n");

		mci_store_persistent(mci);
	}

	if (mci->mci_statfile != NULL)
	{
		(void) fclose(mci->mci_statfile);
		mci->mci_statfile = NULL;
	}

	errno = save_errno;
}
/*
**  MCI_LOAD_PERSISTENT -- load persistent host info
**
**	Load information about host that is kept
**	in common for all running sendmails.
**
**	Parameters:
**		mci -- the host/connection to load persistent info
**			   for.
**
**	Returns:
**		TRUE -- lock was successful
**		FALSE -- lock failed
*/

static bool
mci_load_persistent(mci)
	MCI *mci;
{
	int save_errno = errno;
	bool locked = TRUE;
	FILE *fp;
	char fname[MAXPATHLEN + 1];

	if (mci == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_load_persistent: NULL mci\n");
		return TRUE;
	}

	if (IgnoreHostStatus || HostStatDir == NULL || mci->mci_host == NULL)
		return TRUE;

	/* Already have the persistent information in memory */
	if (SingleThreadDelivery && mci->mci_statfile != NULL)
		return TRUE;

	if (tTd(56, 1))
		dprintf("mci_load_persistent: Attempting to load persistent information for %s\n",
			mci->mci_host);

	if (mci_generate_persistent_path(mci->mci_host, fname, sizeof fname, FALSE) < 0)
	{
		/* Not much we can do if the file isn't there... */
		if (tTd(56, 1))
			dprintf("mci_load_persistent: Couldn't generate host path\n");
		goto cleanup;
	}

	fp = safefopen(fname, O_RDONLY, FileMode,
		       SFF_NOLOCK|SFF_NOLINK|SFF_OPENASROOT|SFF_REGONLY|SFF_SAFEDIRPATH);
	if (fp == NULL)
	{
		/* I can't think of any reason this should ever happen */
		if (tTd(56, 1))
			dprintf("mci_load_persistent: open(%s): %s\n",
				fname, errstring(errno));
		goto cleanup;
	}

	FileName = fname;
	locked = lockfile(fileno(fp), fname, "", LOCK_SH|LOCK_NB);
	if (locked)
	{
		(void) mci_read_persistent(fp, mci);
		(void) lockfile(fileno(fp), fname, "", LOCK_UN);
	}
	FileName = NULL;
	(void) fclose(fp);

cleanup:
	errno = save_errno;
	return locked;
}
/*
**  MCI_READ_PERSISTENT -- read persistent host status file
**
**	Parameters:
**		fp -- the file pointer to read.
**		mci -- the pointer to fill in.
**
**	Returns:
**		-1 -- if the file was corrupt.
**		0 -- otherwise.
**
**	Warning:
**		This code makes the assumption that this data
**		will be read in an atomic fashion, and that the data
**		was written in an atomic fashion.  Any other functioning
**		may lead to some form of insanity.  This should be
**		perfectly safe due to underlying stdio buffering.
*/

static int
mci_read_persistent(fp, mci)
	FILE *fp;
	register MCI *mci;
{
	int ver;
	register char *p;
	int saveLineNumber = LineNumber;
	char buf[MAXLINE];

	if (fp == NULL)
		syserr("mci_read_persistent: NULL fp");
	if (mci == NULL)
		syserr("mci_read_persistent: NULL mci");
	if (tTd(56, 93))
	{
		dprintf("mci_read_persistent: fp=%lx, mci=", (u_long) fp);
		mci_dump(mci, FALSE);
	}

	mci->mci_status = NULL;
	if (mci->mci_rstatus != NULL)
		free(mci->mci_rstatus);
	mci->mci_rstatus = NULL;

	rewind(fp);
	ver = -1;
	LineNumber = 0;
	while (fgets(buf, sizeof buf, fp) != NULL)
	{
		LineNumber++;
		p = strchr(buf, '\n');
		if (p != NULL)
			*p = '\0';
		switch (buf[0])
		{
		  case 'V':		/* version stamp */
			ver = atoi(&buf[1]);
			if (ver < 0 || ver > 0)
				syserr("Unknown host status version %d: %d max",
					ver, 0);
			break;

		  case 'E':		/* UNIX error number */
			mci->mci_errno = atoi(&buf[1]);
			break;

		  case 'H':		/* DNS error number */
			mci->mci_herrno = atoi(&buf[1]);
			break;

		  case 'S':		/* UNIX exit status */
			mci->mci_exitstat = atoi(&buf[1]);
			break;

		  case 'D':		/* DSN status */
			mci->mci_status = newstr(&buf[1]);
			break;

		  case 'R':		/* SMTP status */
			mci->mci_rstatus = newstr(&buf[1]);
			break;

		  case 'U':		/* last usage time */
			mci->mci_lastuse = atol(&buf[1]);
			break;

		  case '.':		/* end of file */
			return 0;

		  default:
			sm_syslog(LOG_CRIT, NOQID,
				  "%s: line %d: Unknown host status line \"%s\"",
				  FileName == NULL ? mci->mci_host : FileName,
				  LineNumber, buf);
			LineNumber = saveLineNumber;
			return -1;
		}
	}
	LineNumber = saveLineNumber;
	if (ver < 0)
		return -1;
	return 0;
}
/*
**  MCI_STORE_PERSISTENT -- Store persistent MCI information
**
**	Store information about host that is kept
**	in common for all running sendmails.
**
**	Parameters:
**		mci -- the host/connection to store persistent info for.
**
**	Returns:
**		none.
*/

void
mci_store_persistent(mci)
	MCI *mci;
{
	int save_errno = errno;

	if (mci == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_store_persistent: NULL mci\n");
		return;
	}

	if (HostStatDir == NULL || mci->mci_host == NULL)
		return;

	if (tTd(56, 1))
		dprintf("mci_store_persistent: Storing information for %s\n",
			mci->mci_host);

	if (mci->mci_statfile == NULL)
	{
		if (tTd(56, 1))
			dprintf("mci_store_persistent: no statfile\n");
		return;
	}

	rewind(mci->mci_statfile);
#if !NOFTRUNCATE
	(void) ftruncate(fileno(mci->mci_statfile), (off_t) 0);
#endif /* !NOFTRUNCATE */

	fprintf(mci->mci_statfile, "V0\n");
	fprintf(mci->mci_statfile, "E%d\n", mci->mci_errno);
	fprintf(mci->mci_statfile, "H%d\n", mci->mci_herrno);
	fprintf(mci->mci_statfile, "S%d\n", mci->mci_exitstat);
	if (mci->mci_status != NULL)
		fprintf(mci->mci_statfile, "D%.80s\n",
			denlstring(mci->mci_status, TRUE, FALSE));
	if (mci->mci_rstatus != NULL)
		fprintf(mci->mci_statfile, "R%.80s\n",
			denlstring(mci->mci_rstatus, TRUE, FALSE));
	fprintf(mci->mci_statfile, "U%ld\n", (long)(mci->mci_lastuse));
	fprintf(mci->mci_statfile, ".\n");

	(void) fflush(mci->mci_statfile);

⌨️ 快捷键说明

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