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

📄 mail.local.c

📁 < linux网络编程工具>>配套源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.
 *	All rights reserved.
 * Copyright (c) 1990, 1993, 1994
 *	The Regents of the University of California.  All rights reserved.
 *
 * By using this file, you agree to the terms and conditions set
 * forth in the LICENSE file which can be found at the top level of
 * the sendmail distribution.
 *
 */

#ifndef lint
static char copyright[] =
"@(#) Copyright (c) 1998-2000 Sendmail, Inc. and its suppliers.\n\
	All rights reserved.\n\
     Copyright (c) 1990, 1993, 1994\n\
	The Regents of the University of California.  All rights reserved.\n";
#endif /* ! lint */

#ifndef lint
static char id[] = "@(#)$Id: mail.local.c,v 8.143.4.37 2000/09/22 00:49:10 doug Exp $";
#endif /* ! lint */

/*
**  This is not intended to work on System V derived systems
**  such as Solaris or HP-UX, since they use a totally different
**  approach to mailboxes (essentially, they have a setgid program
**  rather than setuid, and they rely on the ability to "give away"
**  files to do their work).  IT IS NOT A BUG that this doesn't
**  work on such architectures.
*/


/* additional mode for open() */
# define EXTRA_MODE 0

# include <sys/types.h>
# include <sys/param.h>
# include <sys/stat.h>
# include <sys/socket.h>
# include <sys/file.h>

# include <netinet/in.h>
# include <arpa/nameser.h>

# include <fcntl.h>
# include <netdb.h>
#  include <pwd.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <syslog.h>
# include <time.h>
# include <unistd.h>
# ifdef EX_OK
#  undef EX_OK		/* unistd.h may have another use for this */
# endif /* EX_OK */
# include <sysexits.h>
# include <ctype.h>

# ifndef __P
#  include "sendmail/cdefs.h"
# endif /* ! __P */
# include "sendmail/useful.h"

extern size_t	strlcpy __P((char *, const char *, size_t));
extern size_t	strlcat __P((char *, const char *, size_t));

# if defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6)
#  ifndef HASSTRERROR
#   define HASSTRERROR	1
#  endif /* ! HASSTRERROR */
# endif /* defined(BSD4_4) || defined(__osf__) || defined(__GNU_LIBRARY__) || defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */

# include "sendmail/errstring.h"

# ifndef LOCKTO_RM
#  define LOCKTO_RM	300	/* timeout for stale lockfile removal */
# endif /* ! LOCKTO_RM */
# ifndef LOCKTO_GLOB
#  define LOCKTO_GLOB	400	/* global timeout for lockfile creation */
# endif /* ! LOCKTO_GLOB */

# ifdef __STDC__
#  include <stdarg.h>
#  define REALLOC(ptr, size)	realloc(ptr, size)
# else /* __STDC__ */
#  include <varargs.h>
/* define a realloc() which works for NULL pointers */
#  define REALLOC(ptr, size)	(((ptr) == NULL) ? malloc(size) : realloc(ptr, size))
# endif /* __STDC__ */

# if (defined(sun) && defined(__svr4__)) || defined(__SVR4)
#  define USE_LOCKF	1
#  define USE_SETEUID	1
#   define _PATH_MAILDIR	"/var/mail"
# endif /* (defined(sun) && defined(__svr4__)) || defined(__SVR4) */

# ifdef NCR_MP_RAS3
#  define USE_LOCKF	1
#  define HASSNPRINTF	1
#   define _PATH_MAILDIR	"/var/mail"
# endif /* NCR_MP_RAS3 */

# if defined(_AIX)
#  define USE_LOCKF	1
#  define USE_SETEUID	1
#  define USE_VSYSLOG	0
# endif /* defined(_AIX) */

# if defined(__hpux)
#  define USE_LOCKF	1
#  define USE_SETRESUID	1
#  define USE_VSYSLOG	0
# endif /* defined(__hpux) */

# ifdef DGUX
#  define HASSNPRINTF	1
#  define USE_LOCKF	1
#  define USE_VSYSLOG	0
# endif /* DGUX */

# if defined(_CRAY)
#  if !defined(MAXPATHLEN)
#   define MAXPATHLEN PATHSIZE
#  endif /* !defined(MAXPATHLEN) */
#  define USE_VSYSLOG   0
#   define _PATH_MAILDIR	"/usr/spool/mail"
# endif /* defined(_CRAY) */

# if defined(ultrix)
#  define USE_VSYSLOG	0
# endif /* defined(ultrix) */

# if defined(__osf__)
#  define USE_VSYSLOG	0
# endif /* defined(__osf__) */

# if defined(NeXT) && !defined(__APPLE__)
#  include <libc.h>
#   define _PATH_MAILDIR	"/usr/spool/mail"
#  define S_IRUSR	S_IREAD
#  define S_IWUSR	S_IWRITE
# endif /* defined(NeXT) && !defined(__APPLE__) */

# if defined(IRIX64) || defined(IRIX5) || defined(IRIX6)
#   include <paths.h>
# endif /* defined(IRIX64) || defined(IRIX5) || defined(IRIX6) */

/*
 * If you don't have flock, you could try using lockf instead.
 */

# ifdef USE_LOCKF
#  define flock(a, b)	lockf(a, b, 0)
#  ifdef LOCK_EX
#   undef LOCK_EX
#  endif /* LOCK_EX */
#  define LOCK_EX	F_LOCK
# endif /* USE_LOCKF */

# ifndef USE_VSYSLOG
#  define USE_VSYSLOG	1
# endif /* ! USE_VSYSLOG */

# ifndef LOCK_EX
#  include <sys/file.h>
# endif /* ! LOCK_EX */

# if defined(BSD4_4) || defined(__GLIBC__)
#   include <paths.h>
#  define _PATH_LOCTMP	"/tmp/local.XXXXXX"
# endif /* defined(BSD4_4) || defined(__GLIBC__) */

# ifdef BSD4_4
#  define HAS_ST_GEN	1
# else /* BSD4_4 */
#  ifndef _BSD_VA_LIST_
#   define _BSD_VA_LIST_	va_list
#  endif /* ! _BSD_VA_LIST_ */
# endif /* BSD4_4 */

# if defined(BSD4_4) || defined(linux)
#  define HASSNPRINTF	1
# else /* defined(BSD4_4) || defined(linux) */
#  ifndef ultrix
extern FILE	*fdopen __P((int, const char *));
#  endif /* ! ultrix */
# endif /* defined(BSD4_4) || defined(linux) */

# if SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203)
#  define CONTENTLENGTH	1	/* Needs the Content-Length header */
# endif /* SOLARIS >= 20300 || (SOLARIS < 10000 && SOLARIS >= 203) */

# if SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206)
#  define HASSNPRINTF	1		/* has snprintf starting in 2.6 */
# endif /* SOLARIS >= 20600 || (SOLARIS < 10000 && SOLARIS >= 206) */

# ifdef HPUX11
#  define HASSNPRINTF	1		/* has snprintf starting in 11.X */
# endif /* HPUX11 */

# if _AIX4 >= 40300
#  define HASSNPRINTF	1		/* has snprintf starting in 4.3 */
# endif /* _AIX4 >= 40300 */

# if !HASSNPRINTF
extern int	snprintf __P((char *, size_t, const char *, ...));
#  ifndef _CRAY
extern int	vsnprintf __P((char *, size_t, const char *, ...));
#  endif /* ! _CRAY */
# endif /* !HASSNPRINTF */

/*
**  If you don't have setreuid, and you have saved uids, and you have
**  a seteuid() call that doesn't try to emulate using setuid(), then
**  you can try defining USE_SETEUID.
*/
# ifdef USE_SETEUID
#  define setreuid(r, e)		seteuid(e)
# endif /* USE_SETEUID */

/*
**  And of course on hpux you have setresuid()
*/
# ifdef USE_SETRESUID
#  define setreuid(r, e)		setresuid(-1, e, -1)
# endif /* USE_SETRESUID */

# ifndef _PATH_LOCTMP
#  define _PATH_LOCTMP	"/tmp/local.XXXXXX"
# endif /* ! _PATH_LOCTMP */
#  ifndef _PATH_MAILDIR
#   define _PATH_MAILDIR	"/var/spool/mail"
#  endif /* ! _PATH_MAILDIR */

# ifndef S_ISREG
#  define S_ISREG(mode)	(((mode) & _S_IFMT) == S_IFREG)
# endif /* ! S_ISREG */

# ifdef MAILLOCK
#  include <maillock.h>
# endif /* MAILLOCK */

# define U_UID pw->pw_uid
# define U_GID pw->pw_gid

#ifndef INADDRSZ
# define INADDRSZ	4		/* size of an IPv4 address in bytes */
#endif /* ! INADDRSZ */

#ifndef MAILER_DAEMON
# define MAILER_DAEMON	"MAILER-DAEMON"
#endif /* ! MAILER_DAEMON */

#ifdef CONTENTLENGTH
char	ContentHdr[40] = "Content-Length: ";
off_t	HeaderLength;
off_t	BodyLength;
#endif /* CONTENTLENGTH */

bool	EightBitMime = TRUE;		/* advertise 8BITMIME in LMTP */
int	ExitVal = EX_OK;		/* sysexits.h error value. */
bool	LMTPMode = FALSE;
bool	bouncequota = FALSE;		/* permanent error when over quota */

void	deliver __P((int, char *, bool));
int	e_to_sys __P((int));
void	notifybiff __P((char *));
int	store __P((char *, int));
void	usage __P((void));
void	vwarn __P((const char *, _BSD_VA_LIST_));
int	lockmbox __P((char *));
void	unlockmbox __P((void));
void	mailerr __P((const char *, const char *, ...));


int
main(argc, argv)
	int argc;
	char *argv[];
{
	struct passwd *pw;
	int ch, fd;
	uid_t uid;
	char *from;
	extern char *optarg;
	extern int optind;
	extern void dolmtp __P((bool));


	/* make sure we have some open file descriptors */
	for (fd = 10; fd < 30; fd++)
		(void) close(fd);

	/* use a reasonable umask */
	(void) umask(0077);

# ifdef LOG_MAIL
	openlog("mail.local", 0, LOG_MAIL);
# else /* LOG_MAIL */
	openlog("mail.local", 0);
# endif /* LOG_MAIL */

	from = NULL;
	while ((ch = getopt(argc, argv, "7bdf:r:l")) != -1)
	{
		switch(ch)
		{
		  case '7':		/* Do not advertise 8BITMIME */
			EightBitMime = FALSE;
			break;

		  case 'b':		/* bounce mail when over quota. */
			bouncequota = TRUE;
			break;

		  case 'd':		/* Backward compatible. */
			break;

		  case 'f':
		  case 'r':		/* Backward compatible. */
			if (from != NULL)
			{
				mailerr(NULL, "multiple -f options");
				usage();
			}
			from = optarg;
			break;

		  case 'l':
			LMTPMode = TRUE;
			break;

		  case '?':
		  default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	/* initialize biff structures */
	notifybiff(NULL);

	if (LMTPMode)
		dolmtp(bouncequota);

	if (*argv == '\0')
		usage();

	/*
	**  If from not specified, use the name from getlogin() if the
	**  uid matches, otherwise, use the name from the password file
	**  corresponding to the uid.
	*/
	uid = getuid();

	if (from == NULL && ((from = getlogin()) == NULL ||
			     (pw = getpwnam(from)) == NULL ||
			     pw->pw_uid != uid))
		from = (pw = getpwuid(uid)) != NULL ? pw->pw_name : "???";

	/*
	**  There is no way to distinguish the error status of one delivery
	**  from the rest of the deliveries.  So, if we failed hard on one
	**  or more deliveries, but had no failures on any of the others, we
	**  return a hard failure.  If we failed temporarily on one or more
	**  deliveries, we return a temporary failure regardless of the other
	**  failures.  This results in the delivery being reattempted later
	**  at the expense of repeated failures and multiple deliveries.
	*/
	for (fd = store(from, 0); *argv; ++argv)
		deliver(fd, *argv, bouncequota);
	exit(ExitVal);
	/* NOTREACHED */
	return ExitVal;
}

char *
parseaddr(s, rcpt)
	char *s;
	bool rcpt;
{
	char *p;
	int l;

	if (*s++ != '<')
		return NULL;

	p = s;

	/* at-domain-list */
	while (*p == '@')
	{
		p++;
		while (*p != ',' && *p != ':' && *p != '\0')
			p++;
		if (*p == '\0')
			return NULL;

		/* Skip over , or : */
		p++;
	}

	s = p;

	/* local-part */
	while (*p != '\0' && *p != '@' && *p != '>')
	{
		if (*p == '\\')
		{
			if (*++p == '\0')
				return NULL;
		}
		else if (*p == '\"')
		{
			p++;
			while (*p != '\0' && *p != '\"')
			{
				if (*p == '\\')
				{
					if (*++p == '\0')
						return NULL;
				}
				p++;
			}
			if (*p == '\0' || *(p + 1) == '\0')
				return NULL;
		}
		/* +detail ? */
		if (*p == '+' && rcpt)
			*p = '\0';
		p++;
	}

	/* @domain */
	if (*p == '@')
	{
		if (rcpt)
			*p++ = '\0';
		while (*p != '\0' && *p != '>')
			p++;
	}

	if (*p != '>')
		return NULL;
	else
		*p = '\0';
	p++;

	if (*p != '\0' && *p != ' ')
		return NULL;

	if (*s == '\0')
		s = MAILER_DAEMON;

	l = strlen(s) + 1;
	p = malloc(l);
	if (p == NULL)
	{
		printf("421 4.3.0 memory exhausted\r\n");
		exit(EX_TEMPFAIL);
	}

	(void) strlcpy(p, s, l);
	return p;
}

char *
process_recipient(addr)
	char *addr;
{
	if (getpwnam(addr) == NULL)
		return "550 5.1.1 user unknown";
	return NULL;
}

#define RCPT_GROW	30

void
dolmtp(bouncequota)
	bool bouncequota;
{
	char *return_path = NULL;
	char **rcpt_addr = NULL;
	int rcpt_num = 0;
	int rcpt_alloc = 0;
	bool gotlhlo = FALSE;
	char *err;
	int msgfd;
	char *p;
	int i;
	char myhostname[1024];
	char buf[4096];

	(void) gethostname(myhostname, sizeof myhostname - 1);

	printf("220 %s LMTP ready\r\n", myhostname);
	for (;;)
	{
		(void) fflush(stdout);
		if (fgets(buf, sizeof(buf) - 1, stdin) == NULL)
			exit(EX_OK);
		p = buf + strlen(buf) - 1;
		if (p >= buf && *p == '\n')
			*p-- = '\0';
		if (p >= buf && *p == '\r')
			*p-- = '\0';

		switch (buf[0])
		{
		  case 'd':
		  case 'D':
			if (strcasecmp(buf, "data") == 0)
			{
				if (rcpt_num == 0)
				{
					printf("503 5.5.1 No recipients\r\n");
					continue;
				}
				msgfd = store(return_path, rcpt_num);
				if (msgfd == -1)
					continue;

				for (i = 0; i < rcpt_num; i++)
				{
					p = strchr(rcpt_addr[i], '+');
					if (p != NULL)
						*p++ = '\0';
					deliver(msgfd, rcpt_addr[i],
						bouncequota);
				}
				(void) close(msgfd);
				goto rset;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'l':
		  case 'L':
			if (strncasecmp(buf, "lhlo ", 5) == 0)
			{
				/* check for duplicate per RFC 1651 4.2 */
				if (gotlhlo)
				{
					printf("503 %s Duplicate LHLO\r\n",
					       myhostname);
					continue;
				}
				gotlhlo = TRUE;
				printf("250-%s\r\n", myhostname);
				if (EightBitMime)
					printf("250-8BITMIME\r\n");
				printf("250-ENHANCEDSTATUSCODES\r\n");
				printf("250 PIPELINING\r\n");
				continue;
			}
			goto syntaxerr;
			/* NOTREACHED */
			break;

		  case 'm':
		  case 'M':
			if (strncasecmp(buf, "mail ", 5) == 0)
			{
				if (return_path != NULL)
				{
					printf("503 5.5.1 Nested MAIL command\r\n");
					continue;
				}

⌨️ 快捷键说明

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