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

📄 deliver.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
		usrerr(statmsg);	}	/*	**  Final cleanup.	**	Log a record of the transaction.  Compute the new	**	ExitStat -- if we already had an error, stick with	**	that. Save the new envelope message unless it is temporary	**	and we already have a permanent error.	*/	if (LogLevel > ((stat == 0 || stat == EX_TEMPFAIL) ? 3 : 2))		logdelivery(&statmsg[4]);	if (stat != EX_TEMPFAIL)		setstat(stat);	if (stat != EX_OK && (stat != EX_TEMPFAIL ||		 !bitset(EF_TIMEOUT|EF_FATALERRS, e->e_flags)))	{		if (e->e_message != NULL)			free(e->e_message);		e->e_message = newstr(&statmsg[4]);	}	errno = 0;}/***  LOGDELIVERY -- log the delivery in the system log****	Parameters:**		stat -- the message to print for the status****	Returns:**		none****	Side Effects:**		none*/logdelivery(stat)	char *stat;{	extern char *pintvl();# ifdef LOG	if (AlreadyKnown)		return;	/*	 * Syslog should really check boundaries instead but it doesn't.	 */#define MAX_TO_SYSLOG 800	if (strlen(CurEnv->e_to) > MAX_TO_SYSLOG)		CurEnv->e_to[MAX_TO_SYSLOG] = '\0';	syslog(LOG_INFO, "%s: to=%s, delay=%s, stat=%s", CurEnv->e_id,	       CurEnv->e_to, pintvl(curtime() - CurEnv->e_ctime, TRUE), stat);# endif LOG}/***  PUTFROMLINE -- output a UNIX-style from line (or whatever)****	This can be made an arbitrary message separator by changing $l****	One of the ugliest hacks seen by human eyes is contained herein:**	UUCP wants those stupid "remote from <host>" lines.  Why oh why**	does a well-meaning programmer such as myself have to deal with**	this kind of antique garbage????****	Parameters:**		fp -- the file to output to.**		m -- the mailer describing this entry.****	Returns:**		none****	Side Effects:**		outputs some text to fp.*/putfromline(fp, m)	register FILE *fp;	register MAILER *m;{	char *template = "\001l\n";	char buf[MAXLINE];	if (bitnset(M_NHDR, m->m_flags))		return;# ifdef UGLYUUCP	if (bitnset(M_UGLYUUCP, m->m_flags))	{		char *bang;		char xbuf[MAXLINE];		expand("\001g", buf, &buf[sizeof buf - 1], CurEnv);		bang = index(buf, '!');		if (bang == NULL)		{		    bang = index(buf, '@');		    if (bang == NULL)			(void) sprintf(xbuf, 			    "From %s  \001d remote from \001w\n", buf);		    else		    {			*bang++ = '\0';			(void) sprintf(xbuf, 			  "From %s!%s  \001d remote from \001w\n", bang, buf);		    }		}		else		{			*bang++ = '\0';			(void) sprintf(xbuf, 			  "From %s  \001d remote from %s\n", bang, buf);		}		template = xbuf;	}# endif UGLYUUCP	expand(template, buf, &buf[sizeof buf - 1], CurEnv);	putline(buf, fp, m);}/***  PUTBODY -- put the body of a message.****	Parameters:**		fp -- file to output onto.**		m -- a mailer descriptor to control output format.**		e -- the envelope to put out.****	Returns:**		none.****	Side Effects:**		The message is written onto fp.*/putbody(fp, m, e)	FILE *fp;	MAILER *m;	register ENVELOPE *e;{	char buf[MAXLINE];	/*	**  Output the body of the message	*/	if (e->e_dfp == NULL)	{		if (e->e_df != NULL)		{			e->e_dfp = fopen(e->e_df, "r");			if (e->e_dfp == NULL)				syserr("Cannot open %s", e->e_df);		}		else			putline("<<< No Message Collected >>>", fp, m);	}	if (e->e_dfp != NULL)	{		rewind(e->e_dfp);		while (!ferror(fp) && fgets(buf, sizeof buf, e->e_dfp) != NULL)		{			if (buf[0] == 'F' && bitnset(M_ESCFROM, m->m_flags) &&			    strncmp(buf, "From", 4) == 0)				(void) putc('>', fp);#ifdef INTER			putline_8bit(buf, fp, m);#else			putline(buf, fp, m);#endif		}		if (ferror(e->e_dfp))		{			syserr("putbody: read error");			ExitStat = EX_IOERR;		}	}	(void) fflush(fp);	if (ferror(fp) && errno != EPIPE)	{		syserr("putbody: write error");		ExitStat = EX_IOERR;	}	errno = 0;}/***  MAILFILE -- Send a message to a file.****	If the file has the setuid/setgid bits set, but NO execute**	bits, sendmail will try to become the owner of that file**	rather than the real user.  Obviously, this only works if**	sendmail runs as root.****	This could be done as a subordinate mailer, except that it**	is used implicitly to save messages in ~/dead.letter.  We**	view this as being sufficiently important as to include it**	here.  For example, if the system is dying, we shouldn't have**	to create another process plus some pipes to save the message.****	Parameters:**		filename -- the name of the file to send to.**		ctladdr -- the controlling address header -- includes**			the userid/groupid to be when sending.****	Returns:**		The exit code associated with the operation.****	Side Effects:**		none.*/mailfile(filename, ctladdr)	char *filename;	ADDRESS *ctladdr;{	register FILE *f;	register int pid;	ENVELOPE *e = CurEnv;	/*	**  Fork so we can change permissions here.	**	Note that we MUST use fork, not vfork, because of	**	the complications of calling subroutines, etc.	** Also, make sure the body file is open BEFORE we setuid to someone	** besides root.	*/		if (CurEnv->e_dfp == NULL && CurEnv->e_df != NULL)		CurEnv->e_dfp = fopen(CurEnv->e_df, "r");# ifdef SIGCHLD	(void) signal(SIGCHLD, SIG_DFL);# endif SIGCHLD	DOFORK(fork);	if (pid < 0)		return (EX_OSERR);	else if (pid == 0)	{		/* child -- actually write to file */		struct stat stb;		(void) signal(SIGINT, SIG_DFL);		(void) signal(SIGHUP, SIG_DFL);		(void) signal(SIGTERM, SIG_DFL);		(void) umask(OldUmask);		if (stat(filename, &stb) < 0)		{			errno = 0;			stb.st_mode = 0666;		}		if (bitset(0111, stb.st_mode))			exit(EX_CANTCREAT);		if (ctladdr == NULL)			ctladdr = &CurEnv->e_from;		if (!bitset(S_ISGID, stb.st_mode) || setgid(stb.st_gid) < 0)		{			if (ctladdr->q_uid == 0) {				(void) setgid(DefGid);				(void) initgroups(DefUser, DefGid);			} else {				(void) setgid(ctladdr->q_gid);				(void) initgroups(ctladdr->q_ruser?					ctladdr->q_ruser: ctladdr->q_user,					ctladdr->q_gid);			}		}		if (!bitset(S_ISUID, stb.st_mode) || setuid(stb.st_uid) < 0)		{			if (ctladdr->q_uid == 0)				(void) setuid(DefUid);			else				(void) setuid(ctladdr->q_uid);		}		f = dfopen(filename, "a");		if (f == NULL)			exit(EX_CANTCREAT);		putfromline(f, ProgMailer);		(*CurEnv->e_puthdr)(f, ProgMailer, CurEnv);		putline("\n", f, ProgMailer);		(*CurEnv->e_putbody)(f, ProgMailer, CurEnv);		putline("\n", f, ProgMailer);		(void) fclose(f);		(void) fflush(stdout);		/* reset ISUID & ISGID bits for paranoid systems */		(void) chmod(filename, (int) stb.st_mode);		exit(EX_OK);		/*NOTREACHED*/	}	else	{		/* parent -- wait for exit status */		int st;		st = waitfor(pid);		if ((st & 0377) != 0)			return (EX_UNAVAILABLE);		else			return ((st >> 8) & 0377);		/*NOTREACHED*/	}}/***  SENDALL -- actually send all the messages.****	Parameters:**		e -- the envelope to send.**		mode -- the delivery mode to use.  If SM_DEFAULT, use**			the current SendMode.****	Returns:**		none.****	Side Effects:**		Scans the send lists and sends everything it finds.**		Delivers any appropriate error messages.**		If we are running in a non-interactive mode, takes the**			appropriate action.*/sendall(e, mode)	ENVELOPE *e;	char mode;{	register ADDRESS *q;	bool oldverbose;	int pid;	int checkpointCount;#ifdef DEBUG	if (tTd(13, 1))	{		printf("\nSENDALL: mode %c, sendqueue:\n", mode);		printaddr(e->e_sendqueue, TRUE);	}#endif DEBUG	/*	**  Do any preprocessing necessary for the mode we are running.	**	Check to make sure the hop count is reasonable.	**	Delete sends to the sender in mailing lists.	*/	CurEnv = e;	if (e->e_hopcount > Maxhop)	{		extern char	Arpa_Usrerr[];		e->e_to = e->e_sendqueue->q_paddr;		message(Arpa_Usrerr,"Mail loop detected");		syserr("sendall: too many hops (%d max)", Maxhop);		return;	}	if (!MeToo)	{		extern ADDRESS *recipient();		e->e_from.q_flags |= QDONTSEND;		(void) recipient(&e->e_from, &e->e_sendqueue);	}	if (SendMode == SM_VERIFY)	  {	    mode = SM_VERIFY;	  }# ifdef QUEUE	else if (!bitset(EF_INQUEUE, e->e_flags))	      {		  /*		   * Add in extra penalty points for messages to lots of		   * recipients (like big mailing lists).		   */	    	checkpointCount = 0;		for (q = e->e_sendqueue; q != NULL; q = q->q_next)		  {		     if (!bitset(QDONTSEND, q->q_flags)) checkpointCount++;		  }		e->e_msgpriority += WKRECIPFACT*checkpointCount;		  /*		   * Determine actual delivery mode: 		   * if we are over the threshold and the message is too "big"		   * then we just queue it up.		   * If message is too "small" then complain.		   * Messages with no recipients are an error.		   */		if (RecipThreshold > 0 &&		    checkpointCount > RecipThreshold &&		    e->e_bodysize < REJECT_MIN)		    {		      syserr("Too many recipients for no message body");		      return;		    }		if (checkpointCount == 0 && !ForceMail && mode != SM_DELIVER)		  {		    e->e_to = e->e_sendqueue->q_paddr;		    message(Arpa_Usrerr,"Possible alias loop");		    syserr("No valid recipients");		    return;		  }		if (mode == SM_DEFAULT)		  {		    if (shouldqueue(e->e_msgpriority))				mode = SM_QUEUE;			else				mode = SendMode;		  }		queueup(e, TRUE, mode == SM_QUEUE);	      }#endif QUEUE	oldverbose = Verbose;	switch (mode)	{	  case SM_VERIFY:		Verbose = TRUE;		break;	  case SM_QUEUE:		e->e_flags |= EF_INQUEUE|EF_KEEPQUEUE;		return;	  case SM_FORK:		if (e->e_xfp != NULL)			(void) fflush(e->e_xfp);		pid = fork();		if (pid < 0)		{			mode = SM_DELIVER;			break;		}		else if (pid > 0)		{			/* be sure we leave the temp files to our child */			e->e_id = e->e_df = NULL;			return;		}		/* double fork to avoid zombies */		if (fork() > 0)			exit(EX_OK);		/* be sure we are immune from the terminal */		disconnect(FALSE);		break;	}	/*	**  Run through the list and send everything.	*/    	checkpointCount = 0;	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		if (mode == SM_VERIFY)		{			e->e_to = q->q_paddr;			if (!bitset(QDONTSEND|QBADADDR, q->q_flags))				message(Arpa_Info, "deliverable");		}		else			(void) deliver(e, q);		/*		 * Checkpoint the queue every once in a while,		 * so we don't get a lot of duplicate messages		 * if we crash during delivery of a big list.		 */		if (++checkpointCount >= CheckPointLimit)		  {		    checkpoint(e,q->q_next);		    checkpointCount = 0;		  }	}	Verbose = oldverbose;	/*	**  Now run through and check for errors.	*/	if (mode == SM_VERIFY)		return;	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		register ADDRESS *qq;# ifdef DEBUG		if (tTd(13, 3))		{			printf("Checking ");			printaddr(q, FALSE);		}# endif DEBUG		/* only send errors if the message failed */		if (!bitset(QBADADDR|QQUEUEUP, q->q_flags))			continue;		/* we have an address that failed -- find the parent */		for (qq = q; qq != NULL; qq = qq->q_alias)		{			char obuf[MAXNAME + 6];			extern char *aliaslookup();			/* we can only have owners for local addresses */			if (!bitnset(M_LOCAL, qq->q_mailer->m_flags))				continue;			/* see if the owner list exists */			(void) strcpy(obuf, "owner-");			if (strncmp(qq->q_user, "owner-", 6) == 0)				(void) strcat(obuf, "owner");			else				(void) strcat(obuf, qq->q_user);			if (aliaslookup(obuf) == NULL)				continue;# ifdef DEBUG			if (tTd(13, 4))				printf("Errors to %s\n", obuf);# endif DEBUG			/* owner list exists -- add it to the error queue */			sendtolist(obuf, (ADDRESS *) NULL, &e->e_errorqueue);			ErrorMode = EM_MAIL;			break;		}	}	if (mode == SM_FORK)		finis();}

⌨️ 快捷键说明

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