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

📄 queue.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 5 页
字号:
		(void) strlcpy(qd, ".", sizeof qd);
		(void) strlcpy(qddf, ".", sizeof qddf);
	}
	else
	{
		(void) snprintf(qd, sizeof qd, "%s%s",
				QPaths[queuedir].qp_name,
				(bitset(QP_SUBQF, QPaths[queuedir].qp_subdirs) ? "/qf" : ""));
		(void) snprintf(qddf, sizeof qddf, "%s%s",
				QPaths[queuedir].qp_name,
				(bitset(QP_SUBDF, QPaths[queuedir].qp_subdirs) ? "/df" : ""));
	}

	/*
	**  Check for permission to print the queue
	*/

	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
	{
		struct stat st;
# ifdef NGROUPS_MAX
		int n;
		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
# endif /* NGROUPS_MAX */

		if (stat(qd, &st) < 0)
		{
			syserr("Cannot stat %s", qid_printqueue(queuedir));
			return 0;
		}
# ifdef NGROUPS_MAX
		n = NGROUPS_MAX;
		while (--n >= 0)
		{
			if (InitialGidSet[n] == st.st_gid)
				break;
		}
		if (n < 0 && RealGid != st.st_gid)
# else /* NGROUPS_MAX */
		if (RealGid != st.st_gid)
# endif /* NGROUPS_MAX */
		{
			usrerr("510 You are not permitted to see the queue");
			setstat(EX_NOPERM);
			return 0;
		}
	}

	/*
	**  Read and order the queue.
	*/

	nrequests = orderq(queuedir, TRUE);

	/*
	**  Print the work list that we have read.
	*/

	/* first see if there is anything */
	if (nrequests <= 0)
	{
		printf("%s is empty\n", qid_printqueue(queuedir));
		return 0;
	}

	CurrentLA = sm_getla(NULL);	/* get load average */

	printf("\t\t%s (%d request%s", qid_printqueue(queuedir), nrequests,
	       nrequests == 1 ? "" : "s");
	if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
		printf(", only %d printed", MaxQueueRun);
	if (Verbose)
		printf(")\n----Q-ID---- --Size-- -Priority- ---Q-Time--- ---------Sender/Recipient--------\n");
	else
		printf(")\n----Q-ID---- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
	for (w = WorkQ; w != NULL; w = w->w_next)
	{
		struct stat st;
		auto time_t submittime = 0;
		long dfsize;
		int flags = 0;
		int qfver;
		char statmsg[MAXLINE];
		char bodytype[MAXNAME + 1];
		char qf[MAXPATHLEN];

		printf("%12s", w->w_name + 2);
		(void) snprintf(qf, sizeof qf, "%s/%s", qd, w->w_name);
		f = fopen(qf, "r");
		if (f == NULL)
		{
			printf(" (job completed)\n");
			errno = 0;
			continue;
		}
		w->w_name[0] = 'd';
		(void) snprintf(qf, sizeof qf, "%s/%s", qddf, w->w_name);
		if (stat(qf, &st) >= 0)
			dfsize = st.st_size;
		else
			dfsize = -1;
		if (w->w_lock)
			printf("*");
		else if (w->w_tooyoung)
			printf("-");
		else if (shouldqueue(w->w_pri, w->w_ctime))
			printf("X");
		else
			printf(" ");
		errno = 0;

		statmsg[0] = bodytype[0] = '\0';
		qfver = 0;
		while (fgets(buf, sizeof buf, f) != NULL)
		{
			register int i;
			register char *p;

			fixcrlf(buf, TRUE);
			switch (buf[0])
			{
			  case 'V':	/* queue file version */
				qfver = atoi(&buf[1]);
				break;

			  case 'M':	/* error message */
				if ((i = strlen(&buf[1])) >= sizeof statmsg)
					i = sizeof statmsg - 1;
				memmove(statmsg, &buf[1], i);
				statmsg[i] = '\0';
				break;

			  case 'B':	/* body type */
				if ((i = strlen(&buf[1])) >= sizeof bodytype)
					i = sizeof bodytype - 1;
				memmove(bodytype, &buf[1], i);
				bodytype[i] = '\0';
				break;

			  case 'S':	/* sender name */
				if (Verbose)
				{
					printf("%8ld %10ld%c%.12s ",
					       dfsize,
					       w->w_pri,
					       bitset(EF_WARNING, flags) ? '+' : ' ',
					       ctime(&submittime) + 4);
					prtstr(&buf[1], 78);
				}
				else
				{
					printf("%8ld %.16s ", dfsize,
					    ctime(&submittime));
					prtstr(&buf[1], 40);
				}
				if (statmsg[0] != '\0' || bodytype[0] != '\0')
				{
					printf("\n    %10.10s", bodytype);
					if (statmsg[0] != '\0')
						printf("   (%.*s)",
						       Verbose ? 100 : 60,
						       statmsg);
				}
				break;

			  case 'C':	/* controlling user */
				if (Verbose)
					printf("\n\t\t\t\t      (---%.74s---)",
					       &buf[1]);
				break;

			  case 'R':	/* recipient name */
				p = &buf[1];
				if (qfver >= 1)
				{
					p = strchr(p, ':');
					if (p == NULL)
						break;
					p++;
				}
				if (Verbose)
				{
					printf("\n\t\t\t\t\t      ");
					prtstr(p, 73);
				}
				else
				{
					printf("\n\t\t\t\t       ");
					prtstr(p, 40);
				}
				break;

			  case 'T':	/* creation time */
				submittime = atol(&buf[1]);
				break;

			  case 'F':	/* flag bits */
				for (p = &buf[1]; *p != '\0'; p++)
				{
					switch (*p)
					{
					  case 'w':
						flags |= EF_WARNING;
						break;
					}
				}
			}
		}
		if (submittime == (time_t) 0)
			printf(" (no control file)");
		printf("\n");
		(void) fclose(f);
	}
	return nrequests;
}
/*
**  QUEUENAME -- build a file name in the queue directory for this envelope.
**
**	Parameters:
**		e -- envelope to build it in/from.
**		type -- the file type, used as the first character
**			of the file name.
**
**	Returns:
**		a pointer to the queue name (in a static buffer).
**
**	Side Effects:
**		If no id code is already assigned, queuename() will
**		assign an id code with assign_queueid().  If no queue
**		directory is assigned, one will be set with setnewqueue().
*/

char *
queuename(e, type)
	register ENVELOPE *e;
	int type;
{
	char *sub = "";
	static char buf[MAXPATHLEN];

	/* Assign an ID if needed */
	if (e->e_id == NULL)
		assign_queueid(e);

	/* Assign a queue directory if needed */
	if (e->e_queuedir == NOQDIR)
		setnewqueue(e);

	if (e->e_queuedir == NOQDIR)
		(void) snprintf(buf, sizeof buf, "%cf%s",
				type, e->e_id);
	else
	{
		switch (type)
		{
		  case 'd':
			if (bitset(QP_SUBDF, QPaths[e->e_queuedir].qp_subdirs))
				sub = "/df";
			break;

		  case 'T':
		  case 't':
		  case 'Q':
		  case 'q':
			if (bitset(QP_SUBQF, QPaths[e->e_queuedir].qp_subdirs))
				sub = "/qf";
			break;

		  case 'x':
			if (bitset(QP_SUBXF, QPaths[e->e_queuedir].qp_subdirs))
				sub = "/xf";
			break;
		}

		(void) snprintf(buf, sizeof buf, "%s%s/%cf%s",
				QPaths[e->e_queuedir].qp_name,
				sub, type, e->e_id);
	}

	if (tTd(7, 2))
		dprintf("queuename: %s\n", buf);
	return buf;
}
/*
**  ASSIGN_QUEUEID -- assign a queue ID for this envelope.
**
**	Assigns an id code if one does not already exist.
**	This code assumes that nothing will remain in the queue for
**	longer than 60 years.  It is critical that files with the given
**	name not already exist in the queue.
**	Also initializes e_queuedir to NOQDIR.
**
**	Parameters:
**		e -- envelope to set it in.
**
**	Returns:
**		none.
*/

static char	Base60Code[] =	"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwx";

void
assign_queueid(e)
	register ENVELOPE *e;
{
	pid_t pid = getpid();
	static char cX = 0;
	static long random_offset;
	struct tm *tm;
	char idbuf[MAXQFNAME - 2];

	if (e->e_id != NULL)
		return;

	/* see if we need to get a new base time/pid */
	if (cX >= 60 || LastQueueTime == 0 || LastQueuePid != pid)
	{
		time_t then = LastQueueTime;

		/* if the first time through, pick a random offset */
		if (LastQueueTime == 0)
			random_offset = get_random();

		while ((LastQueueTime = curtime()) == then &&
		       LastQueuePid == pid)
		{
			(void) sleep(1);
		}
		LastQueuePid = getpid();
		cX = 0;
	}
	if (tTd(7, 50))
		dprintf("assign_queueid: random_offset = %ld (%d)\n",
			random_offset, (int)(cX + random_offset) % 60);

	tm = gmtime(&LastQueueTime);
	idbuf[0] = Base60Code[tm->tm_year % 60];
	idbuf[1] = Base60Code[tm->tm_mon];
	idbuf[2] = Base60Code[tm->tm_mday];
	idbuf[3] = Base60Code[tm->tm_hour];
	idbuf[4] = Base60Code[tm->tm_min];
	idbuf[5] = Base60Code[tm->tm_sec];
	idbuf[6] = Base60Code[((int)cX++ + random_offset) % 60];
	(void) snprintf(&idbuf[7], sizeof idbuf - 7, "%05d",
			(int) LastQueuePid);
	e->e_id = newstr(idbuf);
	define('i', e->e_id, e);
	e->e_queuedir = NOQDIR;
	if (tTd(7, 1))
		dprintf("assign_queueid: assigned id %s, e=%lx\n",
			e->e_id, (u_long) e);
	if (LogLevel > 93)
		sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
}
/*
**  SYNC_QUEUE_TIME -- Assure exclusive PID in any given second
**
**	Make sure one PID can't be used by two processes in any one second.
**
**		If the system rotates PIDs fast enough, may get the
**		same pid in the same second for two distinct processes.
**		This will interfere with the queue file naming system.
**
**	Parameters:
**		none
**
**	Returns:
**		none
*/
void
sync_queue_time()
{
# if FAST_PID_RECYCLE
	if (OpMode != MD_TEST &&
	    OpMode != MD_VERIFY &&
	    LastQueueTime > 0 &&
	    LastQueuePid == getpid() &&
	    curtime() == LastQueueTime)
		(void) sleep(1);
# endif /* FAST_PID_RECYCLE */
}
/*
**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
**
**	Parameters:
**		e -- the envelope to unlock.
**
**	Returns:
**		none
**
**	Side Effects:
**		unlocks the queue for `e'.
*/

void
unlockqueue(e)
	ENVELOPE *e;
{
	if (tTd(51, 4))
		dprintf("unlockqueue(%s)\n",
			e->e_id == NULL ? "NOQUEUE" : e->e_id);


	/* if there is a lock file in the envelope, close it */
	if (e->e_lockfp != NULL)
		(void) fclose(e->e_lockfp);
	e->e_lockfp = NULL;

	/* don't create a queue id if we don't already have one */
	if (e->e_id == NULL)
		return;

	/* remove the transcript */
	if (LogLevel > 87)
		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
	if (!tTd(51, 104))
		xunlink(queuename(e, 'x'));

}
/*
**  SETCTLUSER -- create a controlling address
**
**	Create a fake "address" given only a local login name; this is
**	used as a "controlling user" for future recipient addresses.
**
**	Parameters:
**		user -- the user name of the controlling user.
**		qfver -- the version stamp of this qf file.
**
**	Returns:
**		An address descriptor for the controlling user.
**
**	Side Effects:
**		none.
*/

static ADDRESS *
setctluser(user, qfver)
	char *user;
	int qfver;
{
	register ADDRESS *a;
	struct passwd *pw;
	char *p;

	/*
	**  See if this clears our concept of controlling user.
	*/

	if (user == NULL || *user == '\0')
		return NULL;

	/*
	**  Set up addr fields for controlling user.
	*/

	a = (ADDRESS *) xalloc(sizeof *a);
	memset((char *) a, '\0', sizeof *a);

	if (*user == '\0')
	{
		p = NULL;
		a->q_user = newstr(DefUser);
	}
	else if (*user == ':')
	{
		p = &user[1];
		a->q_user = newstr(p);
	}
	else
	{
		p = strtok(user, ":");
		a->q_user = newstr(user);
		if (qfver >= 2)
		{
			if ((p = strtok(NULL, ":")) != NULL)
				a->q_uid = atoi(p);
			if ((p = strtok(NULL, ":")) != NULL)
				a->q_gid = atoi(p);
			if ((p = strtok(NULL, ":")) != NULL)
				a->q_flags |= QGOODUID;
		}
		else if ((pw = sm_getpwnam(user)) != NULL)
		{
			if (*pw->pw_dir == '\0')
				a->q_home = NULL;
			else if (strcmp(pw->pw_dir, "/") == 0)
				a->q_home = "";
			else
				a->q_home = newstr(pw->pw_dir);
			a->q_uid = pw->pw_uid;
			a->q_gid = pw->pw_gid;
			a->q_flags |= QGOODUID;
		}
	}

	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr" */
	a->q_mailer = LocalMailer;
	if (p == NULL)
		a->q_paddr = newstr(a->q_user);
	else
		a->q_paddr = newstr(p);
	return a;
}
/*
**  LOSEQFILE -- save the qf as Qf and try to let someone know
**
**	Parameters:
**		e -- the envelope (e->e_id will be used).
**		why -- reported to whomever can hear.
**
**	Returns:
**		none.
*/

# define LOSEQF_LETTER 'Q'

void
loseqfile(e, why)
	register ENVELOPE *e;
	char *why;
{
	char *p;
	char buf[MAXPATHLEN];

	if (e == NULL || e->e_id == NULL)
		return;
	p = queuename(e, 'q');
	if (strlen(p) >= (SIZE_T) sizeof buf)
		return;
	(void) strlcpy(buf, p, sizeof buf);
	p = queuename(e, LOSEQF_LETTER);
	if (rename(buf, p) < 0)
		syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
	else if (LogLevel > 0)
		sm_syslog(LOG_ALERT, e->e_id,
			  "Losing %s: %s", buf, why);
}
/*
**  QID_PRINTNAME -- create externally printable version of queue id
**
**	Parameters:
**		e -- the envelope.
**
**	Returns:
**		a printable version
*/

char *
qid_printname(e)
	ENVELOPE *e;
{
	char *id;
	static char idbuf[MAXQFNAME + 34];

	if (e == NULL)
		return "";

	if (e->e_id == NULL)
		id = "";
	else
		id = e->e_id;

	if (e->e_queuedir == NOQDIR)
		return id;

	(void) snprintf(idbuf, sizeof idbuf, "%.32s/%s",
			QPaths[e->e_queuedir].qp_name, id);
	return idbuf;
}
/*
**  QID_PRINTQUEUE -- create full version of queue directory for df files
**
**	Parameters:
**		queuedir -- the short version of the queue directory
**
**	Returns:
**		the full pathname to the queue (static)
*/

char *
qid_printqueue(queuedir)
	int queuedir;
{
	char *subdir;
	static char dir[MAXPATHLEN];

	if (

⌨️ 快捷键说明

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