From Craig_Everhart@TRANSARC.COM Tue Feb  6 15:45:42 1990
Date: Tue,  6 Feb 90 10:26:06 -0500 (EST)
From: Craig_Everhart@TRANSARC.COM
Enclosure: ---- Enclosure ----
To: tytso@ATHENA.MIT.EDU
Subject: Re: Sendmail Flaw
In-Reply-To: <9002060005.AA06210@PORTNOY.MIT.EDU>
References: <9002060005.AA06210@PORTNOY.MIT.EDU>

Here are some diffs that embody the fix (of updating the qfXXX file
after each delivery).  Of course, the sendmail I started with is
different from yours, but you should be able to figure it out.

		Craig

---- Enclosure ----
*** deliver.c.old	Mon Jan  8 10:10:24 1990
--- deliver.c	Mon Jan  8 10:10:29 1990
***************
*** 1453,1459 ****
  	char mode;
  {
  	register ADDRESS *q;
! 	bool oldverbose;
  	int pid;
  
  	/* determine actual delivery mode */
--- 1453,1459 ----
  	char mode;
  {
  	register ADDRESS *q;
! 	bool oldverbose, DoingMore;
  	int pid;
  
  	/* determine actual delivery mode */
***************
*** 1503,1509 ****
  	if ((mode == SM_QUEUE || mode == SM_FORK ||
  	     (mode != SM_VERIFY && SuperSafe)) &&
  	    !bitset(EF_INQUEUE, e->e_flags))
! 		queueup(e, TRUE, mode == SM_QUEUE);
  #endif QUEUE
  
  	oldverbose = Verbose;
--- 1503,1509 ----
  	if ((mode == SM_QUEUE || mode == SM_FORK ||
  	     (mode != SM_VERIFY && SuperSafe)) &&
  	    !bitset(EF_INQUEUE, e->e_flags))
! 		queueup(e, TRUE, mode == SM_QUEUE, FALSE);
  #endif QUEUE
  
  	oldverbose = Verbose;
***************
*** 1547,1552 ****
--- 1547,1553 ----
  	**  Run through the list and send everything.
  	*/
  
+ 	DoingMore = FALSE;
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
  		if (mode == SM_VERIFY)
***************
*** 1555,1562 ****
  			if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
  				message(Arpa_Info, "deliverable");
  		}
! 		else
! 			(void) deliver(e, q);
  	}
  	Verbose = oldverbose;
  
--- 1556,1569 ----
  			if (!bitset(QDONTSEND|QBADADDR, q->q_flags))
  				message(Arpa_Info, "deliverable");
  		}
! 		else if (!bitset(QDONTSEND, q->q_flags))
! 		{
! 			int estat;
! 			if (DoingMore) queueup(e, TRUE, FALSE, TRUE);
! 			DoingMore = FALSE;
! 			estat = deliver(e, q);	/* Queueup if any delivered */
! 			if (estat == EX_OK) DoingMore = TRUE;
! 		}
  	}
  	Verbose = oldverbose;
  

*** envelope.c.old	Mon Jan  8 10:18:06 1990
--- envelope.c	Mon Jan  8 10:18:08 1990
***************
*** 147,153 ****
  	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
  	{
  #ifdef QUEUE
! 		queueup(e, FALSE, FALSE);
  #else QUEUE
  		syserr("dropenvelope: queueup");
  #endif QUEUE
--- 147,153 ----
  	else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
  	{
  #ifdef QUEUE
! 		queueup(e, FALSE, FALSE, FALSE);
  #else QUEUE
  		syserr("dropenvelope: queueup");
  #endif QUEUE

*** queue.c.old	Mon Jan  8 10:19:05 1990
--- queue.c	Mon Jan  8 10:19:08 1990
***************
*** 48,53 ****
--- 48,57 ----
  **		queueall -- if TRUE, queue all addresses, rather than
  **			just those with the QQUEUEUP flag set.
  **		announce -- if TRUE, tell when you are queueing up.
+ ** (CFE)		Checkpoint -- if TRUE, we're doing a checkpoint of a
+ **			list currently being delivered.  Write the
+ **			addresses not yet tried as well as the queued
+ **			addresses.
  **
  **	Returns:
  **		none.
***************
*** 56,65 ****
  **		The current request are saved in a control file.
  */
  
! queueup(e, queueall, announce)
  	register ENVELOPE *e;
  	bool queueall;
  	bool announce;
  {
  	char *tf;
  	char *qf;
--- 60,70 ----
  **		The current request are saved in a control file.
  */
  
! queueup(e, queueall, announce, Checkpoint)
  	register ENVELOPE *e;
  	bool queueall;
  	bool announce;
+ 	bool Checkpoint;
  {
  	char *tf;
  	char *qf;
***************
*** 139,148 ****
  	/* output list of recipient addresses */
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		if (queueall ? !bitset(QDONTSEND, q->q_flags) :
! 			       bitset(QQUEUEUP, q->q_flags))
  		{
! 			if (ValidateRuleSet > 0 || q->q_user != NULL || q->q_user[0] != '\0') {
  				fprintf(tfp, "R%s\n", q->q_user);
  			} else {
  				fprintf(tfp, "R%s\n", q->q_paddr);
--- 144,165 ----
  	/* output list of recipient addresses */
  	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
  	{
! 		int writeit;
! 
! /*		if (queueall ? !bitset(QDONTSEND, q->q_flags) :
! 			       bitset(QQUEUEUP, q->q_flags)) */
! 		if (Checkpoint) {	/* Just delete the already-sent addresses. */
! 			writeit = TRUE;
! 			if (bitset(QDONTSEND, q->q_flags)
! 			  && !bitset(QQUEUEUP, q->q_flags)
! 			  && !bitset(QBADADDR, q->q_flags)) writeit = FALSE;
! 		} else if (queueall)
! 			writeit = !bitset(QDONTSEND, q->q_flags);
! 		else
! 			writeit = bitset(QQUEUEUP, q->q_flags);
! 		if (writeit)
  		{
! 			if (ValidateRuleSet > 0 && q->q_user != NULL && q->q_user[0] != '\0') {
  				fprintf(tfp, "R%s\n", q->q_user);
  			} else {
  				fprintf(tfp, "R%s\n", q->q_paddr);
***************
*** 663,677 ****
  		if (link(w->w_name, queuename(CurEnv, 'l')) < 0)
  		{
  			/* being processed by another queuer */
- 			CurEnv->e_id = NULL;
  # ifdef LOG
  			if (LogLevel > 4)
  /*
  				syslog(LOG_DEBUG, "%s: locked", CurEnv->e_id);
  */
! 				Log(LOG_DISPLAY, "%s: locked", CurEnv->e_id);
  
  # endif LOG
  			if (ForkQueueRuns)
  				exit(EX_OK);
  			else
--- 680,695 ----
  		if (link(w->w_name, queuename(CurEnv, 'l')) < 0)
  		{
  			/* being processed by another queuer */
  # ifdef LOG
  			if (LogLevel > 4)
  /*
  				syslog(LOG_DEBUG, "%s: locked", CurEnv->e_id);
  */
! 				Log(LOG_DISPLAY, "%s: locked (%d)", CurEnv->e_id,
! 					errno);
  
  # endif LOG
+ 			CurEnv->e_id = NULL;
  			if (ForkQueueRuns)
  				exit(EX_OK);
  			else

---- Enclosure ----

