DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T m

⟦a0fdcbbc4⟧ TextFile

    Length: 40150 (0x9cd6)
    Types: TextFile
    Names: »main.c,v«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« 
        └─⟦f9e35cd84⟧ 
            └─⟦this⟧ »sendmail/src/RCS/main.c,v« 

TextFile

head	5.29;
branch	5.29.0;
access;
symbols
	UICSO:5.29.0
	VANILLA:5.29;
locks; strict;
comment	@ * @;


5.29
date	90.06.20.08.36.02;	author paul;	state Exp;
branches
	5.29.0.1;
next	;

5.29.0.1
date	90.06.20.09.43.09;	author paul;	state Exp;
branches;
next	5.29.0.2;

5.29.0.2
date	90.06.25.09.20.57;	author paul;	state Exp;
branches;
next	5.29.0.3;

5.29.0.3
date	90.07.08.17.46.26;	author paul;	state Exp;
branches;
next	5.29.0.4;

5.29.0.4
date	90.07.12.08.01.34;	author paul;	state Exp;
branches;
next	5.29.0.5;

5.29.0.5
date	90.08.27.17.15.45;	author paul;	state Exp;
branches;
next	5.29.0.6;

5.29.0.6
date	90.09.21.14.48.32;	author paul;	state Exp;
branches;
next	5.29.0.7;

5.29.0.7
date	90.10.01.23.07.21;	author paul;	state Exp;
branches;
next	5.29.0.8;

5.29.0.8
date	90.10.13.18.42.53;	author paul;	state Exp;
branches;
next	5.29.0.9;

5.29.0.9
date	90.10.16.22.49.27;	author paul;	state Exp;
branches;
next	5.29.0.10;

5.29.0.10
date	90.10.25.20.19.27;	author paul;	state Exp;
branches;
next	5.29.0.11;

5.29.0.11
date	90.11.01.16.45.01;	author paul;	state Exp;
branches;
next	5.29.0.12;

5.29.0.12
date	90.11.07.13.55.16;	author paul;	state Exp;
branches;
next	5.29.0.13;

5.29.0.13
date	90.11.11.10.37.03;	author paul;	state Exp;
branches;
next	5.29.0.14;

5.29.0.14
date	90.11.13.15.29.28;	author paul;	state Exp;
branches;
next	5.29.0.15;

5.29.0.15
date	90.11.29.13.59.43;	author paul;	state Exp;
branches;
next	5.29.0.16;

5.29.0.16
date	90.12.18.14.57.22;	author paul;	state Exp;
branches;
next	5.29.0.17;

5.29.0.17
date	90.12.21.23.52.24;	author paul;	state Exp;
branches;
next	5.29.0.18;

5.29.0.18
date	91.01.19.19.26.02;	author paul;	state Exp;
branches;
next	5.29.0.19;

5.29.0.19
date	91.02.15.20.20.13;	author paul;	state Exp;
branches;
next	5.29.0.20;

5.29.0.20
date	91.02.17.04.30.19;	author paul;	state Exp;
branches;
next	5.29.0.21;

5.29.0.21
date	91.03.06.15.17.14;	author paul;	state Exp;
branches;
next	;


desc
@@


5.29
log
@5.64 Berkeley release
@
text
@/*
 * Copyright (c) 1983 Eric P. Allman
 * Copyright (c) 1988 Regents of the University of California.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms are permitted provided
 * that: (1) source distributions retain this entire copyright notice and
 * comment, and (2) distributions including binaries display the following
 * acknowledgement:  ``This product includes software developed by the
 * University of California, Berkeley and its contributors'' in the
 * documentation or other materials provided with the distribution and in
 * all advertising materials mentioning features or use of this software.
 * Neither the name of the University nor the names of its contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

#ifndef lint
char copyright[] =
"@@(#) Copyright (c) 1988 Regents of the University of California.\n\
 All rights reserved.\n";
#endif /* not lint */

#ifndef lint
static char sccsid[] = "@@(#)main.c	5.29 (Berkeley) 6/1/90";
#endif /* not lint */

#define	_DEFINE

#include <sys/file.h>
#include <signal.h>
#include <sgtty.h>
#include "sendmail.h"
#include <arpa/nameser.h>
#include <resolv.h>

# ifdef lint
char	edata, end;
# endif lint

/*
**  SENDMAIL -- Post mail to a set of destinations.
**
**	This is the basic mail router.  All user mail programs should
**	call this routine to actually deliver mail.  Sendmail in
**	turn calls a bunch of mail servers that do the real work of
**	delivering the mail.
**
**	Sendmail is driven by tables read in from /usr/lib/sendmail.cf
**	(read by readcf.c).  Some more static configuration info,
**	including some code that you may want to tailor for your
**	installation, is in conf.c.  You may also want to touch
**	daemon.c (if you have some other IPC mechanism), acct.c
**	(to change your accounting), names.c (to adjust the name
**	server mechanism).
**
**	Usage:
**		/usr/lib/sendmail [flags] addr ...
**
**		See the associated documentation for details.
**
**	Author:
**		Eric Allman, UCB/INGRES (until 10/81)
**			     Britton-Lee, Inc., purveyors of fine
**				database computers (from 11/81)
**		The support of the INGRES Project and Britton-Lee is
**			gratefully acknowledged.  Britton-Lee in
**			particular had absolutely nothing to gain from
**			my involvement in this project.
*/


int		NextMailer;	/* "free" index into Mailer struct */
char		*FullName;	/* sender's full name */
ENVELOPE	BlankEnvelope;	/* a "blank" envelope */
ENVELOPE	MainEnvelope;	/* the envelope around the basic letter */
ADDRESS		NullAddress =	/* a null address */
		{ "", "", "" };

/*
**  Pointers for setproctitle.
**	This allows "ps" listings to give more useful information.
**	These must be kept out of BSS for frozen configuration files
**		to work.
*/

# ifdef SETPROCTITLE
char		**Argv = NULL;		/* pointer to argument vector */
char		*LastArgv = NULL;	/* end of argv */
# endif SETPROCTITLE

#ifdef DAEMON
#ifndef SMTP
ERROR %%%%   Cannot have daemon mode without SMTP   %%%% ERROR
#endif SMTP
#endif DAEMON

main(argc, argv, envp)
	int argc;
	char **argv;
	char **envp;
{
	register char *p;
	char **av;
	extern int finis();
	extern char Version[];
	char *from;
	typedef int (*fnptr)();
	STAB *st;
	register int i;
	bool readconfig = TRUE;
	bool queuemode = FALSE;		/* process queue requests */
	bool nothaw;
	static bool reenter = FALSE;
	char jbuf[30];			/* holds MyHostName */
	extern bool safefile();
	extern time_t convtime();
	extern putheader(), putbody();
	extern ENVELOPE *newenvelope();
	extern intsig();
	extern char **myhostname();
	extern char *arpadate();
	extern char **environ;

	/*
	**  Check to see if we reentered.
	**	This would normally happen if e_putheader or e_putbody
	**	were NULL when invoked.
	*/

	if (reenter)
	{
		syserr("main: reentered!");
		abort();
	}
	reenter = TRUE;

	/* Enforce use of local time */
	unsetenv("TZ");

	/*
	**  Be sure we have enough file descriptors.
	**	But also be sure that 0, 1, & 2 are open.
	*/

	i = open("/dev/null", O_RDWR);
	while (i >= 0 && i < 2)
		i = dup(i);
	for (i = getdtablesize(); i > 2; --i)
		(void) close(i);
	errno = 0;

#ifdef LOG_MAIL
	openlog("sendmail", LOG_PID, LOG_MAIL);
#else 
	openlog("sendmail", LOG_PID);
#endif 

	/*
	**  Set default values for variables.
	**	These cannot be in initialized data space.
	*/

	setdefaults();

	/* set up the blank envelope */
	BlankEnvelope.e_puthdr = putheader;
	BlankEnvelope.e_putbody = putbody;
	BlankEnvelope.e_xfp = NULL;
	STRUCTCOPY(NullAddress, BlankEnvelope.e_from);
	CurEnv = &BlankEnvelope;
	STRUCTCOPY(NullAddress, MainEnvelope.e_from);

	/*
	**  Do a quick prescan of the argument list.
	**	We do this to find out if we can potentially thaw the
	**	configuration file.  If not, we do the thaw now so that
	**	the argument processing applies to this run rather than
	**	to the run that froze the configuration.
	*/

	argv[argc] = NULL;
	av = argv;
	nothaw = FALSE;
	while ((p = *++av) != NULL)
	{
		if (strncmp(p, "-C", 2) == 0)
		{
			ConfFile = &p[2];
			if (ConfFile[0] == '\0')
				ConfFile = "sendmail.cf";
			(void) setgid(getrgid());
			(void) setuid(getruid());
			nothaw = TRUE;
		}
		else if (strncmp(p, "-bz", 3) == 0)
			nothaw = TRUE;
		else if (strncmp(p, "-d", 2) == 0)
		{
			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
			tTflag(&p[2]);
			setbuf(stdout, (char *) NULL);
			printf("Version %s\n", Version);
		}
	}

	InChannel = stdin;
	OutChannel = stdout;

	if (!nothaw)
		readconfig = !thaw(FreezeFile);

	/* reset the environment after the thaw */
	for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)
		UserEnviron[i] = newstr(envp[i]);
	UserEnviron[i] = NULL;
	environ = UserEnviron;

# ifdef SETPROCTITLE
	/*
	**  Save start and extent of argv for setproctitle.
	*/

	Argv = argv;
	if (i > 0)
		LastArgv = envp[i - 1] + strlen(envp[i - 1]);
	else
		LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
# endif SETPROCTITLE

	if (signal(SIGINT, SIG_IGN) != SIG_IGN)
		(void) signal(SIGINT, intsig);
	if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
		(void) signal(SIGHUP, intsig);
	(void) signal(SIGTERM, intsig);
	(void) signal(SIGPIPE, SIG_IGN);
	OldUmask = umask(0);
	OpMode = MD_DELIVER;
	MotherPid = getpid();
	FullName = getenv("NAME");

	errno = 0;
	from = NULL;

	if (readconfig)
	{
		/* initialize some macros, etc. */
		initmacros();

		/* hostname */
		av = myhostname(jbuf, sizeof jbuf);
		if (jbuf[0] != '\0')
		{
			if (tTd(0, 4))
				printf("canonical name: %s\n", jbuf);
			p = newstr(jbuf);
			define('w', p, CurEnv);
			setclass('w', p);
		}
		while (av != NULL && *av != NULL)
		{
			if (tTd(0, 4))
				printf("\ta.k.a.: %s\n", *av);
			setclass('w', *av++);
		}

		/* version */
		define('v', Version, CurEnv);
	}

	/* current time */
	define('b', arpadate((char *) NULL), CurEnv);

	/*
	** Crack argv.
	*/

	av = argv;
	p = rindex(*av, '/');
	if (p++ == NULL)
		p = *av;
	if (strcmp(p, "newaliases") == 0)
		OpMode = MD_INITALIAS;
	else if (strcmp(p, "mailq") == 0)
		OpMode = MD_PRINT;
	else if (strcmp(p, "smtpd") == 0)
		OpMode = MD_DAEMON;
	while ((p = *++av) != NULL && p[0] == '-')
	{
		switch (p[1])
		{
		  case 'b':	/* operations mode */
			switch (p[2])
			{
			  case MD_DAEMON:
# ifdef DAEMON
				if (getuid() != 0) {
					usrerr("Permission denied");
					exit (EX_USAGE);
				}
				(void) unsetenv("HOSTALIASES");
# else
				usrerr("Daemon mode not implemented");
				ExitStat = EX_USAGE;
				break;
# endif DAEMON
			  case MD_SMTP:
# ifndef SMTP
				usrerr("I don't speak SMTP");
				ExitStat = EX_USAGE;
				break;
# endif SMTP
			  case MD_ARPAFTP:
			  case MD_DELIVER:
			  case MD_VERIFY:
			  case MD_TEST:
			  case MD_INITALIAS:
			  case MD_PRINT:
			  case MD_FREEZE:
				OpMode = p[2];
				break;

			  default:
				usrerr("Invalid operation mode %c", p[2]);
				ExitStat = EX_USAGE;
				break;
			}
			break;

		  case 'C':	/* select configuration file (already done) */
			break;

		  case 'd':	/* debugging -- redo in case frozen */
			tTsetup(tTdvect, sizeof tTdvect, "0-99.1");
			tTflag(&p[2]);
			setbuf(stdout, (char *) NULL);
#ifdef NAMED_BIND
			_res.options |= RES_DEBUG;
#endif
			break;

		  case 'f':	/* from address */
		  case 'r':	/* obsolete -f flag */
			p += 2;
			if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
			{
				p = *++av;
				if (p == NULL || *p == '-')
				{
					usrerr("No \"from\" person");
					ExitStat = EX_USAGE;
					av--;
					break;
				}
			}
			if (from != NULL)
			{
				usrerr("More than one \"from\" person");
				ExitStat = EX_USAGE;
				break;
			}
			from = newstr(p);
			break;

		  case 'F':	/* set full name */
			p += 2;
			if (*p == '\0' && ((p = *++av) == NULL || *p == '-'))
			{
				usrerr("Bad -F flag");
				ExitStat = EX_USAGE;
				av--;
				break;
			}
			FullName = newstr(p);
			break;

		  case 'h':	/* hop count */
			p += 2;
			if (*p == '\0' && ((p = *++av) == NULL || !isdigit(*p)))
			{
				usrerr("Bad hop count (%s)", p);
				ExitStat = EX_USAGE;
				av--;
				break;
			}
			CurEnv->e_hopcount = atoi(p);
			break;
		
		  case 'n':	/* don't alias */
			NoAlias = TRUE;
			break;

		  case 'o':	/* set option */
			setoption(p[2], &p[3], FALSE, TRUE);
			break;

		  case 'q':	/* run queue files at intervals */
# ifdef QUEUE
			if (getuid() != 0) {
				usrerr("Permission denied");
				exit (EX_USAGE);
			}
			(void) unsetenv("HOSTALIASES");
			queuemode = TRUE;
			QueueIntvl = convtime(&p[2]);
# else QUEUE
			usrerr("I don't know about queues");
			ExitStat = EX_USAGE;
# endif QUEUE
			break;

		  case 't':	/* read recipients from message */
			GrabTo = TRUE;
			break;

			/* compatibility flags */
		  case 'c':	/* connect to non-local mailers */
		  case 'e':	/* error message disposition */
		  case 'i':	/* don't let dot stop me */
		  case 'm':	/* send to me too */
		  case 'T':	/* set timeout interval */
		  case 'v':	/* give blow-by-blow description */
			setoption(p[1], &p[2], FALSE, TRUE);
			break;

		  case 's':	/* save From lines in headers */
			setoption('f', &p[2], FALSE, TRUE);
			break;

# ifdef DBM
		  case 'I':	/* initialize alias DBM file */
			OpMode = MD_INITALIAS;
			break;
# endif DBM
		}
	}

	/*
	**  Do basic initialization.
	**	Read system control file.
	**	Extract special fields for local use.
	*/

	if (OpMode == MD_FREEZE || readconfig)
		readcf(ConfFile);

	switch (OpMode)
	{
	  case MD_FREEZE:
		/* this is critical to avoid forgeries of the frozen config */
		(void) setgid(getgid());
		(void) setuid(getuid());

		/* freeze the configuration */
		freeze(FreezeFile);
		exit(EX_OK);

	  case MD_INITALIAS:
		Verbose = TRUE;
		break;
	}

	/* do heuristic mode adjustment */
	if (Verbose)
	{
		/* turn off noconnect option */
		setoption('c', "F", TRUE, FALSE);

		/* turn on interactive delivery */
		setoption('d', "", TRUE, FALSE);
	}

	/* our name for SMTP codes */
	expand("\001j", jbuf, &jbuf[sizeof jbuf - 1], CurEnv);
	MyHostName = jbuf;

	/* the indices of local and program mailers */
	st = stab("local", ST_MAILER, ST_FIND);
	if (st == NULL)
		syserr("No local mailer defined");
	else
		LocalMailer = st->s_mailer;
	st = stab("prog", ST_MAILER, ST_FIND);
	if (st == NULL)
		syserr("No prog mailer defined");
	else
		ProgMailer = st->s_mailer;

	/* operate in queue directory */
	if (chdir(QueueDir) < 0)
	{
		syserr("cannot chdir(%s)", QueueDir);
		exit(EX_SOFTWARE);
	}

	/*
	**  Do operation-mode-dependent initialization.
	*/

	switch (OpMode)
	{
	  case MD_PRINT:
		/* print the queue */
#ifdef QUEUE
		dropenvelope(CurEnv);
		printqueue();
		exit(EX_OK);
#else QUEUE
		usrerr("No queue to print");
		finis();
#endif QUEUE

	  case MD_INITALIAS:
		/* initialize alias database */
		initaliases(AliasFile, TRUE);
		exit(EX_OK);

	  case MD_DAEMON:
		/* don't open alias database -- done in srvrsmtp */
		break;

	  default:
		/* open the alias database */
		initaliases(AliasFile, FALSE);
		break;
	}

	if (tTd(0, 15))
	{
		/* print configuration table (or at least part of it) */
		printrules();
		for (i = 0; i < MAXMAILERS; i++)
		{
			register struct mailer *m = Mailer[i];
			int j;

			if (m == NULL)
				continue;
			printf("mailer %d (%s): P=%s S=%d R=%d M=%ld F=", i, m->m_name,
				m->m_mailer, m->m_s_rwset, m->m_r_rwset,
				m->m_maxsize);
			for (j = '\0'; j <= '\177'; j++)
				if (bitnset(j, m->m_flags))
					(void) putchar(j);
			printf(" E=");
			xputs(m->m_eol);
			printf("\n");
		}
	}

	/*
	**  Switch to the main envelope.
	*/

	CurEnv = newenvelope(&MainEnvelope);
	MainEnvelope.e_flags = BlankEnvelope.e_flags;

	/*
	**  If test mode, read addresses from stdin and process.
	*/

	if (OpMode == MD_TEST)
	{
		char buf[MAXLINE];

		printf("ADDRESS TEST MODE\nEnter <ruleset> <address>\n");
		for (;;)
		{
			register char **pvp;
			char *q;
			extern char *DelimChar;

			printf("> ");
			(void) fflush(stdout);
			if (fgets(buf, sizeof buf, stdin) == NULL)
				finis();
			for (p = buf; isspace(*p); p++)
				continue;
			q = p;
			while (*p != '\0' && !isspace(*p))
				p++;
			if (*p == '\0')
				continue;
			*p = '\0';
			do
			{
				extern char **prescan();
				char pvpbuf[PSBUFSIZE];

				pvp = prescan(++p, ',', pvpbuf);
				if (pvp == NULL)
					continue;
				rewrite(pvp, 3);
				p = q;
				while (*p != '\0')
				{
					rewrite(pvp, atoi(p));
					while (*p != '\0' && *p++ != ',')
						continue;
				}
			} while (*(p = DelimChar) != '\0');
		}
	}

# ifdef QUEUE
	/*
	**  If collecting stuff from the queue, go start doing that.
	*/

	if (queuemode && OpMode != MD_DAEMON && QueueIntvl == 0)
	{
		runqueue(FALSE);
		finis();
	}
# endif QUEUE

	/*
	**  If a daemon, wait for a request.
	**	getrequests will always return in a child.
	**	If we should also be processing the queue, start
	**		doing it in background.
	**	We check for any errors that might have happened
	**		during startup.
	*/

	if (OpMode == MD_DAEMON || QueueIntvl != 0)
	{
		if (!tTd(0, 1))
		{
			/* put us in background */
			i = fork();
			if (i < 0)
				syserr("daemon: cannot fork");
			if (i != 0)
				exit(0);

			/* get our pid right */
			MotherPid = getpid();

			/* disconnect from our controlling tty */
			disconnect(TRUE);
		}

# ifdef QUEUE
		if (queuemode)
		{
			runqueue(TRUE);
			if (OpMode != MD_DAEMON)
				for (;;)
					pause();
		}
# endif QUEUE
		dropenvelope(CurEnv);

#ifdef DAEMON
		getrequests();

		/* at this point we are in a child: reset state */
		OpMode = MD_SMTP;
		(void) newenvelope(CurEnv);
		openxscript(CurEnv);
#endif DAEMON
	}
	
# ifdef SMTP
	/*
	**  If running SMTP protocol, start collecting and executing
	**  commands.  This will never return.
	*/

	if (OpMode == MD_SMTP)
		smtp();
# endif SMTP

	/*
	**  Do basic system initialization and set the sender
	*/

	initsys();
	setsender(from);

	if (OpMode != MD_ARPAFTP && *av == NULL && !GrabTo)
	{
		usrerr("Recipient names must be specified");

		/* collect body for UUCP return */
		if (OpMode != MD_VERIFY)
			collect(FALSE);
		finis();
	}
	if (OpMode == MD_VERIFY)
		SendMode = SM_VERIFY;

	/*
	**  Scan argv and deliver the message to everyone.
	*/

	sendtoargv(av);

	/* if we have had errors sofar, arrange a meaningful exit stat */
	if (Errors > 0 && ExitStat == EX_OK)
		ExitStat = EX_USAGE;

	/*
	**  Read the input mail.
	*/

	CurEnv->e_to = NULL;
	if (OpMode != MD_VERIFY || GrabTo)
		collect(FALSE);
	errno = 0;

	/* collect statistics */
	if (OpMode != MD_VERIFY)
		markstats(CurEnv, (ADDRESS *) NULL);

	if (tTd(1, 1))
		printf("From person = \"%s\"\n", CurEnv->e_from.q_paddr);

	/*
	**  Actually send everything.
	**	If verifying, just ack.
	*/

	CurEnv->e_from.q_flags |= QDONTSEND;
	CurEnv->e_to = NULL;
	sendall(CurEnv, SM_DEFAULT);

	/*
	** All done.
	*/

	finis();
}
\f

/*
**  FINIS -- Clean up and exit.
**
**	Parameters:
**		none
**
**	Returns:
**		never
**
**	Side Effects:
**		exits sendmail
*/

finis()
{
	if (tTd(2, 1))
		printf("\n====finis: stat %d e_flags %o\n", ExitStat, CurEnv->e_flags);

	/* clean up temp files */
	CurEnv->e_to = NULL;
	dropenvelope(CurEnv);

	/* post statistics */
	poststats(StatFile);

	/* and exit */
# ifdef LOG
	if (LogLevel > 11)
		syslog(LOG_DEBUG, "finis, pid=%d", getpid());
# endif LOG
	if (ExitStat == EX_TEMPFAIL)
		ExitStat = EX_OK;
	exit(ExitStat);
}
\f

/*
**  INTSIG -- clean up on interrupt
**
**	This just arranges to exit.  It pessimises in that it
**	may resend a message.
**
**	Parameters:
**		none.
**
**	Returns:
**		none.
**
**	Side Effects:
**		Unlocks the current job.
*/

intsig()
{
	FileName = NULL;
	unlockqueue(CurEnv);
	exit(EX_OK);
}
\f

/*
**  INITMACROS -- initialize the macro system
**
**	This just involves defining some macros that are actually
**	used internally as metasymbols to be themselves.
**
**	Parameters:
**		none.
**
**	Returns:
**		none.
**
**	Side Effects:
**		initializes several macros to be themselves.
*/

struct metamac
{
	char	metaname;
	char	metaval;
};

struct metamac	MetaMacros[] =
{
	/* LHS pattern matching characters */
	'*', MATCHZANY,	'+', MATCHANY,	'-', MATCHONE,	'=', MATCHCLASS,
	'~', MATCHNCLASS,

	/* these are RHS metasymbols */
	'#', CANONNET,	'@@', CANONHOST,	':', CANONUSER,	'>', CALLSUBR,

	/* the conditional operations */
	'?', CONDIF,	'|', CONDELSE,	'.', CONDFI,

	/* and finally the hostname lookup characters */
	'[', HOSTBEGIN,	']', HOSTEND,

	'\0'
};

initmacros()
{
	register struct metamac *m;
	char buf[5];
	register int c;

	for (m = MetaMacros; m->metaname != '\0'; m++)
	{
		buf[0] = m->metaval;
		buf[1] = '\0';
		define(m->metaname, newstr(buf), CurEnv);
	}
	buf[0] = MATCHREPL;
	buf[2] = '\0';
	for (c = '0'; c <= '9'; c++)
	{
		buf[1] = c;
		define(c, newstr(buf), CurEnv);
	}
}
\f

/*
**  FREEZE -- freeze BSS & allocated memory
**
**	This will be used to efficiently load the configuration file.
**
**	Parameters:
**		freezefile -- the name of the file to freeze to.
**
**	Returns:
**		none.
**
**	Side Effects:
**		Writes BSS and malloc'ed memory to freezefile
*/

union frz
{
	char		frzpad[BUFSIZ];	/* insure we are on a BUFSIZ boundary */
	struct
	{
		time_t	frzstamp;	/* timestamp on this freeze */
		char	*frzbrk;	/* the current break */
		char	*frzedata;	/* address of edata */
		char	*frzend;	/* address of end */
		char	frzver[252];	/* sendmail version */
	} frzinfo;
};

freeze(freezefile)
	char *freezefile;
{
	int f;
	union frz fhdr;
	extern char edata, end;
	extern char *sbrk();
	extern char Version[];

	if (freezefile == NULL)
		return;

	/* try to open the freeze file */
	f = creat(freezefile, FileMode);
	if (f < 0)
	{
		syserr("Cannot freeze %s", freezefile);
		errno = 0;
		return;
	}

	/* build the freeze header */
	fhdr.frzinfo.frzstamp = curtime();
	fhdr.frzinfo.frzbrk = sbrk(0);
	fhdr.frzinfo.frzedata = &edata;
	fhdr.frzinfo.frzend = &end;
	(void) strcpy(fhdr.frzinfo.frzver, Version);

	/* write out the freeze header */
	if (write(f, (char *) &fhdr, sizeof fhdr) != sizeof fhdr ||
	    write(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
					(int) (fhdr.frzinfo.frzbrk - &edata))
	{
		syserr("Cannot freeze %s", freezefile);
	}

	/* fine, clean up */
	(void) close(f);
}
\f

/*
**  THAW -- read in the frozen configuration file.
**
**	Parameters:
**		freezefile -- the name of the file to thaw from.
**
**	Returns:
**		TRUE if it successfully read the freeze file.
**		FALSE otherwise.
**
**	Side Effects:
**		reads freezefile in to BSS area.
*/

thaw(freezefile)
	char *freezefile;
{
	int f;
	union frz fhdr;
	extern char edata, end;
	extern char Version[];
	extern caddr_t brk();

	if (freezefile == NULL)
		return (FALSE);

	/* open the freeze file */
	f = open(freezefile, 0);
	if (f < 0)
	{
		syslog(LOG_WARNING, "Cannot open frozen config file %s: %m",
			freezefile);
		errno = 0;
		return (FALSE);
	}

	/* read in the header */
	if (read(f, (char *) &fhdr, sizeof fhdr) < sizeof fhdr)
	{
		syserr("Cannot read frozen config file");
		(void) close(f);
		return (FALSE);
	}
	if ( fhdr.frzinfo.frzedata != &edata ||
	    fhdr.frzinfo.frzend != &end ||
	    strcmp(fhdr.frzinfo.frzver, Version) != 0)
	{
		syslog(LOG_WARNING, "Wrong version of frozen config file");
		(void) close(f);
		return (FALSE);
	}

	/* arrange to have enough space */
	if (brk(fhdr.frzinfo.frzbrk) == (caddr_t) -1)
	{
		syserr("Cannot break to %x", fhdr.frzinfo.frzbrk);
		(void) close(f);
		return (FALSE);
	}

	/* now read in the freeze file */
	if (read(f, (char *) &edata, (int) (fhdr.frzinfo.frzbrk - &edata)) !=
					(int) (fhdr.frzinfo.frzbrk - &edata))
	{
		syserr("Cannot read frozen config file");
		/* oops!  we have trashed memory..... */
		(void) write(2, "Cannot read freeze file\n", 24);
		_exit(EX_SOFTWARE);
	}

	(void) close(f);
	return (TRUE);
}
\f

/*
**  DISCONNECT -- remove our connection with any foreground process
**
**	Parameters:
**		fulldrop -- if set, we should also drop the controlling
**			TTY if possible -- this should only be done when
**			setting up the daemon since otherwise UUCP can
**			leave us trying to open a dialin, and we will
**			wait for the carrier.
**
**	Returns:
**		none
**
**	Side Effects:
**		Trys to insure that we are immune to vagaries of
**		the controlling tty.
*/

disconnect(fulldrop)
	bool fulldrop;
{
	int fd;

	if (tTd(52, 1))
		printf("disconnect: In %d Out %d\n", fileno(InChannel),
						fileno(OutChannel));
	if (tTd(52, 5))
	{
		printf("don't\n");
		return;
	}

	/* be sure we don't get nasty signals */
	(void) signal(SIGHUP, SIG_IGN);
	(void) signal(SIGINT, SIG_IGN);
	(void) signal(SIGQUIT, SIG_IGN);

	/* we can't communicate with our caller, so.... */
	HoldErrs = TRUE;
	ErrorMode = EM_MAIL;
	Verbose = FALSE;

	/* all input from /dev/null */
	if (InChannel != stdin)
	{
		(void) fclose(InChannel);
		InChannel = stdin;
	}
	(void) freopen("/dev/null", "r", stdin);

	/* output to the transcript */
	if (OutChannel != stdout)
	{
		(void) fclose(OutChannel);
		OutChannel = stdout;
	}
	if (CurEnv->e_xfp == NULL)
		CurEnv->e_xfp = fopen("/dev/null", "w");
	(void) fflush(stdout);
	(void) close(1);
	(void) close(2);
	while ((fd = dup(fileno(CurEnv->e_xfp))) < 2 && fd > 0)
		continue;

#ifdef TIOCNOTTY
	/* drop our controlling TTY completely if possible */
	if (fulldrop)
	{
		fd = open("/dev/tty", 2);
		if (fd >= 0)
		{
			(void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
			(void) close(fd);
		}
		(void) setpgrp(0, 0);
		errno = 0;
	}
#endif TIOCNOTTY

# ifdef LOG
	if (LogLevel > 11)
		syslog(LOG_DEBUG, "in background, pid=%d", getpid());
# endif LOG

	errno = 0;
}
@


5.29.0.1
log
@IDA patches
@
text
@d118 1
a118 1
	char jbuf[60];			/* holds MyHostName */
a125 1
	extern char *index();
d142 1
a142 1
	(void) unsetenv("TZ");
a143 3
	/* Make mail act uniformly (resolver recursion disabled elsewhere) */
	(void) unsetenv("HOSTALIASES");

a200 8
		else if (strncmp(p, "-Z", 2) == 0)
		{
			FreezeFile = &p[2];
			if (FreezeFile[0] == '\0')
				FreezeFile = "sendmail.fc";
			(void) setgid(getrgid());
			(void) setuid(getruid());
		}
d205 1
a205 1
			setlinebuf(stdout);
a261 4
			if ((p = index(jbuf, '.')) != NULL)
				*p = '\0';
			makelower(jbuf);
			define('k', newstr(jbuf), CurEnv);
a290 2
	else if (strcmp(p, "bsmtp") == 0)
		OpMode = MD_BSMTP;
d304 1
a310 1
			  case MD_BSMTP:
a335 3
		  case 'Z':	/* select frozen config file (already done) */
			break;

d339 1
a339 1
			setlinebuf(stdout);
a340 1
			if (tTd(8, 8))
d406 1
d518 1
a518 1
		initaliases(TRUE);
d527 1
a527 1
		initaliases(FALSE);
d542 3
a544 4
			printf("mailer %d (%s): P=%s S=%d/%d R=%d/%d M=%ld F=",
				i, m->m_name, m->m_mailer,
				m->m_se_rwset, m->m_sh_rwset,
				m->m_re_rwset, m->m_rh_rwset, m->m_maxsize);
a569 1
		printf("[Note: No initial ruleset 3 call]\n");
d596 1
a596 1
				/* rewrite(pvp, 3); */
d674 2
a675 11
	if (OpMode == MD_SMTP || OpMode == MD_BSMTP) {
		bool batched = (OpMode == MD_BSMTP);
		OpMode = MD_SMTP;
#ifdef notdef
/* test without this first */
		/* have to run unbuffered or else will lose synchronization */
		if (batched)
			setbuf(InChannel, (char *) NULL);
#endif notdef
		smtp(batched);
	}
d810 6
d828 1
a828 1
	/* and finally the hostname and database lookup characters */
a829 1
	'(', KEYBEGIN,	')', KEYEND,
a830 7
#ifdef MACVALUE
	/* run-time macro expansion, not at freeze time */
	'&', MACVALUE,
#endif
#ifdef QUOTE822
	'!', QUOTE822,	/* quote next macro if RFC822 requires it */
#endif
a878 1
		char	frzdatecompiled[64];	/* sendmail compilation date */
a889 1
	extern char datecompiled[];
a908 1
	(void) strcpy(fhdr.frzinfo.frzdatecompiled, datecompiled);
a941 1
	extern char datecompiled[];
d966 1
a966 2
	    strcmp(fhdr.frzinfo.frzver, Version) != 0 ||
	    strcmp(fhdr.frzinfo.frzdatecompiled, datecompiled) != 0)
d1033 1
a1033 1
	setoption('e', "m", TRUE, TRUE);
@


5.29.0.2
log
@Patches for HP-UX from Andy Linton <root@@comp.vuw.ac.nz>.  Thanks Andy!
@
text
@a141 1
#if !defined(hpux)
a143 1
#endif /* hpux */
a216 3
#if defined(hpux)
			setvbuf(stdout, (char *) NULL, _IOLBF, BUFSIZ);
#else
a217 1
#endif /* hpux */
a359 4
			tTflag(&p[2]);
#if defined(hpux)
		        setvbuf(stdout, (char *) NULL, _IOLBF, BUFSIZ);
#else
a360 1
#endif /* hpux */
@


5.29.0.3
log
@Some syslog() and the openlog() calls were not #ifdef LOG.
@
text
@a161 1
#ifdef LOG
a166 1
#endif /* LOG */
a999 1
#ifdef LOG
a1001 1
#endif /* LOG */
a1017 1
#ifdef LOG
a1018 1
#endif /* LOG */
@


5.29.0.4
log
@From: kessler@@hacketorium.Eng.Sun.COM (Tom Kessler)
Newsgroups: comp.bugs.4bsd,comp.mail.sendmail
Subject: bug in sendmail 5.64
Date: 11 Jul 90 20:52:35 GMT
Organization: Rocket Scientists Anonymous

In sendmail 5.64 a new field name q_ruser was added to the address structure
(found in sendmail.h).  The initialization of the variable NullAddress
(in main.c) was not updated to reflect this.  This can cause some problems
when you go to look at the q_host field or expect the q_ruser field to be
NULL.
@
text
@d81 1
a81 1
		{ "", "", NULL, "" };
@


5.29.0.5
log
@Use MAXHOSTNAMELEN from sys/param.h instead of a hardwired 64.  Provide
a default value for older systems.  Don't set FullName in either daemon
(-bd) or queue-run (-q) mode.  Unsetenv(LOCALDOMAIN) as well as
HOSTALIASES.  From suggestions by Charles Seeger, Neil Rickert, and
Mark D. Baushke.
@
text
@a38 4
#include <sys/param.h>
#ifndef MAXHOSTNAMELEN
# define MAXHOSTNAMELEN	64
#endif /* !MAXHOSTNAMELEN */
a115 1
	bool NoName = FALSE;
d118 1
a118 1
	char jbuf[MAXHOSTNAMELEN+1];	/* holds MyHostName */
a148 1
	(void) unsetenv("LOCALDOMAIN");
a208 2
		else if (strncmp(p, "-bd", 3) == 0 || strncmp(p, "-q", 2) == 0)
			NoName = TRUE;
d263 1
a263 1
	FullName = (NoName) ? NULL : getenv("NAME");
@


5.29.0.6
log
@Changed delimiter character in prescan() call during address test mode (-bt)
to '\0' from ','.  Otherwise checking internal rulesets with comma
separated pieces becomes dicey.
@
text
@d637 1
a637 1
				pvp = prescan(++p, '\0', pvpbuf);
@


5.29.0.7
log
@Changes from Berkeley's 5.64 to 5.65 release (main.c, savemail.c, and
version.c)
@
text
@d28 1
a28 1
static char sccsid[] = "@@(#)main.c	5.31 (Berkeley) 7/20/90";
a32 1
#include <sys/param.h>
d46 1
a46 1
# endif /* lint */
d97 1
a97 1
# endif /* SETPROCTITLE */
d102 2
a103 2
#endif /* SMTP */
#endif /* DAEMON */
d173 1
a173 1
#endif /* LOG_MAIL */
d260 1
a260 1
# endif /* SETPROCTITLE */
d342 1
a342 1
# endif /* DAEMON */
d349 1
a349 1
# endif /* SMTP */
d385 1
a385 1
#endif /* NAMED_BIND */
d451 1
a451 1
# else /* !QUEUE */
d454 1
a454 1
# endif /* QUEUE */
d479 1
a479 1
# endif /* DBM */
d553 1
a553 1
#else /* !QUEUE */
d556 1
a556 1
#endif /* QUEUE */
d662 1
a662 1
# endif /* QUEUE */
d699 1
a699 1
# endif /* QUEUE */
d709 1
a709 1
#endif /* DAEMON */
d726 1
a726 1
#endif /* notdef */
d729 1
a729 1
# endif /* SMTP */
d820 1
a820 1
# endif /* LOG */
d882 1
a882 1
#endif /* MACVALUE */
d885 1
a885 1
#endif /* QUOTE822 */
d1122 1
a1125 4
#if BSD > 43
		daemon(1, 1);
#else /* BSD <= 43 */
#ifdef TIOCNOTTY
a1132 2
#endif /* TIOCNOTTY */
#endif /* BSD */
d1135 1
d1140 1
a1140 1
# endif /* LOG */
@


5.29.0.8
log
@Neil Rickert's (rickert@@cs.niu.edu) res_init() fix.  Other bug fixes and
System 5 changes from Bruce Lilly (bruce%balilly@@sonyd1.broadcast.sony.com).
@
text
@d25 3
a28 3
# ifdef	__GNUC__
static	char	compiled[] = "@@(#)compiled by gcc version "__VERSION__;
# endif	/* __GNUC__ */
d33 2
d38 3
a40 5
#include <sys/file.h>
#ifdef NAMED_BIND
# include <arpa/nameser.h>
# include <resolv.h>
#endif /* NAMED_BIND */
d132 1
a250 5
#ifdef NAMED_BIND
	/* Make sure the resolver library is initialized */
	res_init();
#endif /* NAMED_BIND */

d770 4
a785 4
	/* collect statistics (done after sendall, since sendall may fork) */
	if (OpMode != MD_VERIFY)
		markstats(CurEnv, (ADDRESS *) NULL);

d1129 1
a1129 1
# ifdef TIOCNOTTY
d1137 1
a1137 1
# endif /* TIOCNOTTY */
a1138 5
#if !defined(BSD) && !defined(TIOCNOTTY) && defined(SYSTEM5)
		setpgrp();
		if (fork() != 0)
			exit(0);
#endif /* !BSD && !TIOCNOTTY && SYSTEM5 */
@


5.29.0.9
log
@To: paul-pomes@@uiuc.edu
Subject: sendmail-5.65 incorrectly handles MX records with equal precedence
Date: Tue, 16 Oct 90 23:10:18 EDT
From: "David Edelsohn" <edelsohn@@nova.npac.syr.edu>

Description:

	I was just looking up the source to sendmail-5.61 to see why the
mail load is not being evenly distributed between my two hosts pointed to
by MX records with the same preference level.  In domain.c: getmxrr(), the
MX records are sorted by preference with a special case if the preferences
are identical.  The condition is as follows:

	if (prefer[i] > prefer[j] ||
		(prefer[i] == prefer[j] && rand() % 1 == 0)) {
			...SWAP ENTRIES...
	}

Should not the test be (rand() & 01) or (rand() % 2)?  (rand() % 1) is
always 0!  rand() is not guaranteed to be random in the lowest bits as
random() is suppose to be, but even regularly alternating between swapping
and not swapping would be better than always swapping when preferences are
equal.

	Not only does rand() % 1 always return 0, not only does rand() & 1
alternate between 0 and 1 regularly at each call (as long as the load is
balanced it doesn't really matter), but since sendmail is called directly
by Mail, the random number generator is reset to the same value each time
(for both rand() and random()), i.e there is no call to srandom() with the
PID or time-of-day or some other seed.
	This appears to be the only use of a random number generator within
sendmail so only one MX record of equal precedence will be used assuming
that the records are always returned in the same order at each DNS resolver
call.  The only saving grace would be if a queued message has the MX host
re-calculated by the daemonized sendmail if the message is ever queued, but
with (rand % 1) this is irrelevent in sendmail-5.61.

Fix:

	1) Change "rand % 1" to "rand & 1"
	2) No matter which random number generator is used (rand() or
random()), use the appropriate seed initializer call during the initial
startup (in main.c?).  The seed must be set post-thaw.
@
text
@a275 1
	srand(MotherPid);
@


5.29.0.10
log
@Added unixpc specific setbuf() call to unbuffer stdout.
@
text
@d231 1
a231 4
#else /* !hpux */
# if defined(unixpc)
			setbuf(stdout, (char *)NULL);
# else /* !unixpc */
a232 1
# endif /* unixpc */
d384 2
a385 5
			setvbuf(stdout, (char *) NULL, _IOLBF, BUFSIZ);
#else /* !hpux */
# if defined(unixpc)
			setbuf(stdout, (char *)NULL);
# else /* !unixpc */
a386 1
# endif /* unixpc */
@


5.29.0.11
log
@Systems like Next machines don't have brk()/sbrk() so freeze()/thaw()
become no-ops #ifdef NeXT.  Made signal() usage more baroque.
@
text
@d271 1
a271 1
	if (signal(SIGINT, SIG_IGN) != (SIG_TYPE (*)()) SIG_IGN)
d273 1
a273 1
	if (signal(SIGHUP, SIG_IGN) != (SIG_TYPE (*)()) SIG_IGN)
a954 5
#if defined(NeXT)
	syserr("Cannot freeze %s on systems w.o. brk/sbrk", freezefile);
	errno = 0;
	return;
#else /* !NeXT */
a991 1
#endif /* NeXT */
a1009 4
#if defined(NeXT)
	errno = 0;
	return (FALSE);
#else /* !NeXT */
a1070 1
#endif /* NeXT */
@


5.29.0.12
log
@Relocate IN_SCCS_ID
@
text
@a21 1
# define IN_SCCS_ID
d31 1
a31 1
#define _DEFINE
@


5.29.0.13
log
@From: forys@@snake.utah.edu (Jeff Forys)
Newsgroups: comp.mail.sendmail
Date: 10 Nov 90 01:48:40 MST
Organization: University of Utah CS Dept
Subject: Sendmail 5.65 can loop on certain addresses +FIX

Index:	usr.lib/sendmail/src/parseaddr.c 4.3BSD

This applies to all known versions of sendmail (through "5.65").

Description:
	Sendmail reserves characters in the range 020 - 036 for coding
	its rewrite rules.  If one of these characters shows up in an
	address, the results are unpredictable (from a user's point of
	view).  Specifically, an address containing a "replacement on
	RHS" rule can cause sendmail to go into an infinite loop while
	processing various rewrite rules.

	I suppose this could be used for a denial-of-service attack;
	if an evil-minded person fired off a bunch of these in your
	direction, you would end up with an equal number of sendmail
	processes churning endlessly away on your CPU.  Of course,
	whence such an "attack" originates would be painfully obvious!
@
text
@a646 2
			if (invalidaddr(p+1))
				continue;
@


5.29.0.14
log
@Changed hpux to XPG3 (X-Open Portability Guide 3) that's set in sendmail.h.
From Andy Linton (andy.linton@@comp.vuw.ac.nz).
@
text
@d37 1
a164 3
#if defined(XPG3)
	for (i = (int) sysconf (_SC_OPEN_MAX); i > 2; --i)
#else
a165 1
#endif /* XPG3 */
d230 1
a230 1
#if defined(XPG3)
d232 1
a232 1
#else /* !XPG3 */
d238 1
a238 1
#endif /* XPG3 */
d256 1
a256 4
	/*
	** Make sure the resolver library is initialized and that enough time
	** is allowed for non-local servers.
	*/
a257 1
	_res.retrans = 30;
d388 1
a388 1
#if defined(XPG3)
d390 1
a390 1
#else /* !XPG3 */
d396 1
a396 1
#endif /* XPG3 */
d1153 1
a1153 10
#if defined(XPG3)
	/*
	 * setsid will provide a new session w/o any tty associated at all.
	 * STANDARDS CONFORMANCE
	 *     setpgrp: SVID2, XPG2
	 *     setsid: XPG3, POSIX.1, FIPS 151-1
	 */
	(void) setsid();
#else /* !XPG3 */
# if BSD > 43
d1155 2
a1156 2
# else /* BSD <= 43 */
#  ifdef TIOCNOTTY
d1164 3
a1166 3
#  endif /* TIOCNOTTY */
# endif /* BSD */
# if !defined(BSD) && !defined(TIOCNOTTY) && defined(SYSV)
d1170 1
a1170 2
# endif /* !BSD && !TIOCNOTTY && SYSV */
#endif /* XPG3 */
@


5.29.0.15
log
@Freeze/thaw code now included only if _PATH_SENDMAILFC is #define'd in
pathnames.h .  Print the loadaverage for -d3.1.  Change intsig() declaration
to SIG_TYPE.
@
text
@d129 1
a129 1
	extern SIG_TYPE intsig();
a222 1
#ifdef _PATH_SENDMAILFC
a227 4
#else /* !_PATH_SENDMAILFC */
			/* Use printf since OutChannel isn't assigned yet */
			printf("Frozen configuration files not available\n");
#endif /* _PATH_SENDMAILFC */
a245 2
	if (tTd(3, 1))
		(void) getla();	/* prints load average in getla() */
a248 1
#ifdef _PATH_SENDMAILFC
a250 1
#endif /* _PATH_SENDMAILFC */
a516 1
#ifdef _PATH_SENDMAILFC
a523 4
#else /* !_PATH_SENDMAILFC */
		usrerr("Frozen configuration files not available");
		exit(EX_USAGE);
#endif /* _PATH_SENDMAILFC */
a864 1
SIG_TYPE
d933 1
a933 3
\f


#ifdef _PATH_SENDMAILFC
/*
d965 5
d1007 1
d1026 4
d1044 1
a1044 1
# ifdef LOG
d1047 1
a1047 1
# endif /* LOG */
d1064 1
a1064 1
# ifdef LOG
d1066 1
a1066 1
# endif /* LOG */
d1091 1
a1092 1
#endif /* _PATH_SENDMAILFC */
@


5.29.0.16
log
@NIS (nee YP) state is saved in the freeze, the readback of the freeze file
destroys similar information.  This causes strange results later due to the
unexpected closing of a file descriptor using a stale copy.

Roger D. Roles          rdr@@Alliant.COM
Rob McMahon		cudcv@@warwick.ac.uk
@
text
@a990 8
# ifdef YP
	{
		/*
		 * NIS (nee YP) state is saved in the freeze, the readback
		 * of the freeze file destroys similar information.  This
		 * causes strange results later due to the unexpected closing
		 * of a file descriptor using a stale copy.
		 */
a991 6
		char *domain;
		if (yp_get_default_domain(&domain) == 0)
			yp_unbind(domain);
	}
# endif /* YP */

a1057 14
# ifdef YP
	{
		/*
		 * NIS (nee YP) state is saved in the freeze, the readback
		 * of the freeze file destroys similar information.  This
		 * causes strange results later due to the unexpected closing
		 * of a file descriptor using a stale copy.
		 */

		char *domain;
		if (yp_get_default_domain(&domain) == 0)
			yp_unbind(domain);
	}
# endif /* YP */
@


5.29.0.17
log
@Only reset the environment after a successful thaw.  Previously the
environment was always reset which used a lot of newstr() calls and
inflated the size of sendmail.fc.  Found by Piet Beertema (piet@@mcsun.eu.net).
@
text
@d257 3
d261 5
a265 9
	/* Reset the environment only after a successful thaw() */
	if (!nothaw && (readconfig = !thaw(FreezeFile)) == FALSE)
	{
		for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)
			UserEnviron[i] = newstr(envp[i]);
		UserEnviron[i] = NULL;
		environ = UserEnviron;
	}
#endif /* _PATH_SENDMAILFC */
@


5.29.0.18
log
@Deleted #include <sys/types.h> as it's already included via sendmail.h from
useful.h.  #include "sendmail.h" relocated to top of #include list.
@
text
@a33 1
#include "sendmail.h"
d36 1
@


5.29.0.19
log
@End of environment incorrectly determined when frozen config file
not used.  Found by Piet Beertema.
@
text
@a265 3
	else
		for (i = 0; i < MAXUSERENVIRON && envp[i] != NULL; i++)
			;
@


5.29.0.20
log
@Added static keyword to declarations of intsig(), initmacros(), freeze(),
and thaw().
@
text
@d129 1
a129 2
	static SIG_TYPE intsig();
	static initmacros(), freeze(), thaw();
d883 1
a883 1
static SIG_TYPE
a931 1
static
a982 1
static
a1051 1
static
@


5.29.0.21
log
@ANSIfied
@
text
@a48 12
#ifdef __STDC__
static void intsig();
static void initmacros();
static void freeze(const char *);
static thaw(const char *);
#else /* !__STDC__ */
static void intsig();
static void initmacros();
static void freeze();
static thaw();
#endif /* __STDC__ */

d113 1
d125 8
d677 1
a846 1
void
d884 1
a884 1
static void
d933 1
a933 1
static void
d985 1
a985 1
static void
d987 1
a987 1
	const char *freezefile;
d1057 1
a1057 1
	const char *freezefile;
a1153 1
void
@