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

📄 mail.local.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
				if (strncasecmp(buf+5, "from:", 5) != 0 ||
				    ((return_path = parseaddr(buf + 10,
							      FALSE)) == NULL))
				{
					printf("501 5.5.4 Syntax error in parameters\r\n");
					continue;
				}
				printf("250 2.5.0 ok\r\n");
				continue;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'n':
		  case 'N':
			if (strcasecmp(buf, "noop") == 0)
			{
				printf("250 2.0.0 ok\r\n");
				continue;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'q':
		  case 'Q':
			if (strcasecmp(buf, "quit") == 0)
			{
				printf("221 2.0.0 bye\r\n");
				exit(EX_OK);
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'r':
		  case 'R':
			if (strncasecmp(buf, "rcpt ", 5) == 0)
			{
				if (return_path == NULL)
				{
					printf("503 5.5.1 Need MAIL command\r\n");
					continue;
				}
				if (rcpt_num >= rcpt_alloc)
				{
					rcpt_alloc += RCPT_GROW;
					rcpt_addr = (char **)
						REALLOC((char *) rcpt_addr,
							rcpt_alloc *
							sizeof(char **));
					if (rcpt_addr == NULL)
					{
						printf("421 4.3.0 memory exhausted\r\n");
						exit(EX_TEMPFAIL);
					}
				}
				if (strncasecmp(buf + 5, "to:", 3) != 0 ||
				    ((rcpt_addr[rcpt_num] = parseaddr(buf + 8,
								      TRUE)) == NULL))
				{
					printf("501 5.5.4 Syntax error in parameters\r\n");
					continue;
				}
				if ((err = process_recipient(rcpt_addr[rcpt_num])) != NULL)
				{
					printf("%s\r\n", err);
					continue;
				}
				rcpt_num++;
				printf("250 2.1.5 ok\r\n");
				continue;
			}
			else if (strcasecmp(buf, "rset") == 0)
			{
				printf("250 2.0.0 ok\r\n");

rset:
				while (rcpt_num)
					free(rcpt_addr[--rcpt_num]);
				if (return_path != NULL)
					free(return_path);
				return_path = NULL;
				continue;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'v':
		  case 'V':
			if (strncasecmp(buf, "vrfy ", 5) == 0)
			{
				printf("252 2.3.3 try RCPT to attempt delivery\r\n");
				continue;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  default:
  syntaxerr:
			printf("500 5.5.2 Syntax error\r\n");
			continue;
			/* NOTREACHED */
			break;
		}
	}
}

int
store(from, lmtprcpts)
	char *from;
	int lmtprcpts;
{
	FILE *fp = NULL;
	time_t tval;
	bool eline;
	bool fullline = TRUE;	/* current line is terminated */
	bool prevfl;		/* previous line was terminated */
	char line[2048];
	int fd;
	char tmpbuf[sizeof _PATH_LOCTMP + 1];

	(void) umask(0077);
	(void) strlcpy(tmpbuf, _PATH_LOCTMP, sizeof tmpbuf);
	if ((fd = mkstemp(tmpbuf)) == -1 || (fp = fdopen(fd, "w+")) == NULL)
	{
		if (lmtprcpts)
		{
			printf("451 4.3.0 unable to open temporary file\r\n");
			return -1;
		}
		else
		{
			mailerr("451 4.3.0", "unable to open temporary file");
			exit(ExitVal);
		}
	}
	(void) unlink(tmpbuf);

	if (LMTPMode)
	{
		printf("354 go ahead\r\n");
		(void) fflush(stdout);
	}

	(void) time(&tval);
	(void) fprintf(fp, "From %s %s", from, ctime(&tval));

#ifdef CONTENTLENGTH
	HeaderLength = 0;
	BodyLength = -1;
#endif /* CONTENTLENGTH */

	line[0] = '\0';
	eline = TRUE;
	while (fgets(line, sizeof(line), stdin) != (char *)NULL)
	{
		size_t line_len = 0;
		int peek;

		prevfl = fullline;	/* preserve state of previous line */
		while (line[line_len] != '\n' && line_len < sizeof(line) - 2)
			line_len++;
		line_len++;

		/* Check for dot-stuffing */
		if (prevfl && lmtprcpts && line[0] == '.')
		{
			if (line[1] == '\n' ||
			    (line[1] == '\r' && line[2] == '\n'))
				goto lmtpdot;
			memcpy(line, line + 1, line_len);
			line_len--;
		}

		/* Check to see if we have the full line from fgets() */
		fullline = FALSE;
		if (line_len > 0)
		{
			if (line[line_len - 1] == '\n')
			{
				if (line_len >= 2 &&
				    line[line_len - 2] == '\r')
				{
					line[line_len - 2] = '\n';
					line[line_len - 1] = '\0';
					line_len--;
				}
				fullline = TRUE;
			}
			else if (line[line_len - 1] == '\r')
			{
				/* Did we just miss the CRLF? */
				peek = fgetc(stdin);
				if (peek == '\n')
				{
					line[line_len - 1] = '\n';
					fullline = TRUE;
				}
				else
					(void) ungetc(peek, stdin);
			}
		}
		else
			fullline = TRUE;

#ifdef CONTENTLENGTH
		if (prevfl && line[0] == '\n' && HeaderLength == 0)
		{
			eline = FALSE;
			HeaderLength = ftell(fp);
			if (HeaderLength <= 0)
			{
				/*
				**  shouldn't happen, unless ftell() is
				**  badly broken
				*/

				HeaderLength = -1;
			}
		}
#else /* CONTENTLENGTH */
		if (prevfl && line[0] == '\n')
			eline = TRUE;
#endif /* CONTENTLENGTH */
		else
		{
			if (eline && line[0] == 'F' &&
			    !memcmp(line, "From ", 5))
				(void) putc('>', fp);
			eline = FALSE;
#ifdef CONTENTLENGTH
			/* discard existing "Content-Length:" headers */
			if (prevfl && HeaderLength == 0 &&
			    (line[0] == 'C' || line[0] == 'c') &&
			    strncasecmp(line, ContentHdr, 15) == 0)
			{
				/*
				**  be paranoid: clear the line
				**  so no "wrong matches" may occur later
				*/
				line[0] = '\0';
				continue;
			}
#endif /* CONTENTLENGTH */

		}
		(void) fwrite(line, sizeof(char), line_len, fp);
		if (ferror(fp))
		{
			if (lmtprcpts)
			{
				while (lmtprcpts--)
					printf("451 4.3.0 temporary file write error\r\n");
				(void) fclose(fp);
				return -1;
			}
			else
			{
				mailerr("451 4.3.0",
					"temporary file write error");
				(void) fclose(fp);
				exit(ExitVal);
			}
		}
	}

	if (lmtprcpts)
	{
		/* Got a premature EOF -- toss message and exit */
		exit(EX_OK);
	}

	/* If message not newline terminated, need an extra. */
	if (strchr(line, '\n') == NULL)
		(void) putc('\n', fp);

  lmtpdot:

#ifdef CONTENTLENGTH
	BodyLength = ftell(fp);
	if (HeaderLength == 0 && BodyLength > 0)	/* empty body */
	{
		HeaderLength = BodyLength;
		BodyLength = 0;
	}
	else
		BodyLength = BodyLength - HeaderLength - 1 ;

	if (HeaderLength > 0 && BodyLength >= 0)
	{
		extern char *quad_to_string();

		if (sizeof BodyLength > sizeof(long))
			snprintf(line, sizeof line, "%s\n",
				 quad_to_string(BodyLength));
		else
			snprintf(line, sizeof line, "%ld\n",
				 (long) BodyLength);
		strlcpy(&ContentHdr[16], line, sizeof(ContentHdr) - 16);
	}
	else
		BodyLength = -1;	/* Something is wrong here */
#endif /* CONTENTLENGTH */

	/* Output a newline; note, empty messages are allowed. */
	(void) putc('\n', fp);

	if (fflush(fp) == EOF || ferror(fp) != 0)
	{
		if (lmtprcpts)
		{
			while (lmtprcpts--)
				printf("451 4.3.0 temporary file write error\r\n");
			(void) fclose(fp);
			return -1;
		}
		else
		{
			mailerr("451 4.3.0", "temporary file write error");
			(void) fclose(fp);
			exit(ExitVal);
		}
	}
	return fd;
}

void
deliver(fd, name, bouncequota)
	int fd;
	char *name;
	bool bouncequota;
{
	struct stat fsb;
	struct stat sb;
	struct passwd *pw;
	char path[MAXPATHLEN];
	int mbfd, nr = 0, nw, off;
	char *p;
	off_t curoff;
#ifdef CONTENTLENGTH
	off_t headerbytes;
	int readamount;
#endif /* CONTENTLENGTH */
	char biffmsg[100], buf[8*1024];
	extern char *quad_to_string();


	/*
	**  Disallow delivery to unknown names -- special mailboxes can be
	**  handled in the sendmail aliases file.
	*/
	if ((pw = getpwnam(name)) == NULL)
	{
		if (ExitVal != EX_TEMPFAIL)
			ExitVal = EX_UNAVAILABLE;
		if (LMTPMode)
		{
			if (ExitVal == EX_TEMPFAIL)
				printf("451 4.3.0 cannot lookup name: %s\r\n",
				       name);
			else
				printf("550 5.1.1 unknown name: %s\r\n", name);
		}
		else
		{
			char *errcode = NULL;

			if (ExitVal == EX_TEMPFAIL)
				errcode = "451 4.3.0";
			else
				errcode = "550 5.1.1";
			mailerr(errcode, "unknown name: %s", name);
		}
		return;
	}
	endpwent();

	/*
	**  Keep name reasonably short to avoid buffer overruns.
	**	This isn't necessary on BSD because of the proper
	**	definition of snprintf(), but it can cause problems
	**	on other systems.
	**  Also, clear out any bogus characters.
	*/

	if (strlen(name) > 40)
		name[40] = '\0';
	for (p = name; *p != '\0'; p++)
	{
		if (!isascii(*p))
			*p &= 0x7f;
		else if (!isprint(*p))
			*p = '.';
	}


	(void) snprintf(path, sizeof(path), "%s/%s", _PATH_MAILDIR, name);


	/*
	**  If the mailbox is linked or a symlink, fail.  There's an obvious
	**  race here, that the file was replaced with a symbolic link after
	**  the lstat returned, but before the open.  We attempt to detect
	**  this by comparing the original stat information and information
	**  returned by an fstat of the file descriptor returned by the open.
	**
	**  NB: this is a symptom of a larger problem, that the mail spooling
	**  directory is writeable by the wrong users.  If that directory is
	**  writeable, system security is compromised for other reasons, and
	**  it cannot be fixed here.
	**
	**  If we created the mailbox, set the owner/group.  If that fails,
	**  just return.  Another process may have already opened it, so we
	**  can't unlink it.  Historically, binmail set the owner/group at
	**  each mail delivery.  We no longer do this, assuming that if the
	**  ownership or permissions were changed there was a reason.
	**
	**  XXX
	**  open(2) should support flock'ing the file.
	*/

tryagain:
#ifdef MAILLOCK
	p = name;
#else /* MAILLOCK */
	p = path;
#endif /* MAILLOCK */
	if ((off = lockmbox(p)) != 0)
	{
		if (off == EX_TEMPFAIL || e_to_sys(off) == EX_TEMPFAIL)
		{
			ExitVal = EX_TEMPFAIL;
			mailerr("451 4.3.0",
				"lockmailbox %s failed; error code %d %s",
				p, off, errno > 0 ? errstring(errno) : "");
		}
		else
		{
			mailerr("551 5.3.0",
				"lockmailbox %s failed; error code %d %s",
				p, off, errno > 0 ? errstring(errno) : "");
		}
		return;
	}

	if (lstat(path, &sb) < 0)
	{
		int save_errno;
		int mode = S_IRUSR|S_IWUSR;
		gid_t gid = U_GID;

#ifdef MAILGID
		(void) umask(0007);
		gid = MAILGID;
		mode |= S_IRGRP|S_IWGRP;
#endif /* MAILGID */

		mbfd = open(path, O_APPEND|O_CREAT|O_EXCL|O_WRONLY|EXTRA_MODE,
			    mode);
		save_errno = errno;

		if (lstat(path, &sb) < 0)
		{
			ExitVal = EX_CANTCREAT;
			mailerr("550 5.2.0",
				"%s: lstat: file changed after open", path);
			goto err1;
		}
		if (mbfd == -1)
		{
			if (save_errno == EEXIST)
				goto tryagain;

			/* open failed, don't try again */
			mailerr("450 4.2.0", "%s: %s", path,
				errstring(save_errno));
			goto err0;
		}
		else if (fchown(mbfd, U_UID, gid) < 0)
		{
			mailerr("451 4.3.0", "chown %u.%u: %s",
				U_UID, gid, name);
			goto err1;
		}
		else
		{
			/*
			**  open() was successful, now close it so can
			**  be opened as the right owner again.
			**  Paranoia: reset mbdf since the file descriptor
			**  is no longer valid; better safe than sorry.
			*/

			sb.st_uid = U_UID;
			(void) close(mbfd);
			mbfd = -1;
		}
	}
	else if (sb.st_nlink != 1 || !S_ISREG(sb.st_mode))
	{
		mailerr("550 5.2.0", "%s: irregular file", path);
		goto err0;
	}
	else if (sb.st_uid != U_UID)
	{
		ExitVal = EX_CANTCREAT;
		mailerr("550 5.2.0", "%s: wrong ownership (%d)",
			path, sb.st_uid);
		goto err0;
	}

	/* change UID for quota checks */
	if (setreuid(0, U_UID) < 0)
	{
		mailerr("450 4.2.0", "setreuid(0, %d): %s (r=%d, e=%d)",
			U_UID, errstring(errno), getuid(), geteuid());
		goto err1;
	}
#ifdef DEBUG
	fprintf(stderr, "new euid = %d\n", geteuid());
#endif /* DEBUG */
	mbfd = open(path, O_APPEND|O_WRONLY|EXTRA_MODE, 0);
	if (mbfd < 0)
	{
		mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
		goto err0;
	}
	else if (fstat(mbfd, &fsb) < 0 ||
		 fsb.st_nlink != 1 ||
		 sb.st_nlink != 1 ||
		 !S_ISREG(fsb.st_mode) ||
		 sb.st_dev != fsb.st_dev ||
		 sb.st_ino != fsb.st_ino ||
# if HAS_ST_GEN && 0		/* AFS returns random values for st_gen */
		 sb.st_gen != fsb.st_gen ||
# endif /* HAS_ST_GEN && 0 */
		 sb.st_uid != fsb.st_uid)
	{
		ExitVal = EX_TEMPFAIL;
		mailerr("550 5.2.0", "%s: fstat: file changed after open",
			path);
		goto err1;
	}


	/* Wait until we can get a lock on the file. */
	if (flock(mbfd, LOCK_EX) < 0)
	{
		mailerr("450 4.2.0", "%s: %s", path, errstring(errno));
		goto err1;
	}

	/* Get the starting offset of the new message for biff. */
	curoff = lseek(mbfd, (off_t)0, SEEK_END);
	if (sizeof curoff > sizeof(long))
		(void) snprintf(biffmsg, sizeof(biffmsg), "%s@%s\n",
				name, quad_to_string(curoff));
	else
		(void) snprintf(biffmsg, sizeof(biffmsg), "%s@%ld\n",
				name, (long) curoff);

	/* Copy the message into the file. */
	if (lseek(fd, (off_t)0, SEEK_SET) == (off_t)-1)
	{
		mailerr("450 4.2.0", "temporary file: %s",
			errstring(errno));
		goto err1;
	}
#ifdef DEBUG

⌨️ 快捷键说明

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