/*
 * Copyright (c) 2004, 2005 Sendmail, Inc. and its suppliers.
 *	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.
 */

#include "sm/generic.h"
SM_RCSID("@(#)$Id: mtinit.c,v 1.19 2006/11/10 03:46:11 ca Exp $")
#include "sm/error.h"
#include "sm/assert.h"
#include "sm/ctype.h"
#include "sm/io.h"
#include "sm/net.h"
#include "sm/misc.h"
#include "sm/smardef.h"
#include "sm/confsetpath.h"
#include "smar.h"
#include "log.h"

/*
**  SMAR_MT_INIT -- initialize "mailertable". This is a hack.
**
**	Parameters:
**		smar_ctx -- SMAR context
**
**	Returns:
**		usual sm_error code
*/

sm_ret_T
smar_mt_init(smar_ctx_P smar_ctx)
{
	sm_ret_T ret;
	sm_file_T *fp;
	int c, i, hl;
	const char *mpath;
	char hn[256], *hna;
	char ipv4[128], *ipv4a, *addr, *eos;
	sm_str_T key, data;
	char confdir[PATH_MAX];

	SM_IS_SMAR_CTX(smar_ctx);
	ret = sm_dirname(smar_ctx->smar_cnf.smar_cnf_conffile, confdir,
			sizeof(confdir));
	if (sm_is_err(ret)) goto error;

	SM_GEN_MAP_PATH(mpath, smar_ctx->smar_cnf.smar_cnf_mt_path, confdir,
		smar_ctx->smar_cnf.smar_cnf_mt_fn, SMAR_MT_NAME, error);
	fp = NULL;
	ret = sm_io_open(SmStStdio, mpath, SM_IO_RDONLY, &fp, SM_IO_WHAT_END);
	if (sm_is_err(ret)) goto error;
	while (!sm_eof(fp))
	{
		i = 0;

		/* read hostname/domain literal */
		if (SMAR_MT_FULL_LOOKUP(smar_ctx))
		{
			/* note: this isn't correct: it could be a quoted space... */
			while ((c = sm_io_getc(fp)) != SM_IO_EOF && !ISSPACE(c))
			{
				hn[i++] = (char) c;
				if (i >= (int) sizeof(hn))
					goto syntax;
			}
		}
		else
		{
			while ((c = sm_io_getc(fp)) != SM_IO_EOF &&
				(ISALNUM(c) || c == '.' || c == '-'
				 || (c == '[' && i == 0) || (c == ']' && i > 0)))
			{
				hn[i++] = (char) c;
				if (i >= (int) sizeof(hn))
					goto syntax;
			}
		}
		if (c == SM_IO_EOF && i == 0)
			break;
		if (c == SM_IO_EOF || !ISSPACE(c)) goto syntax;
		hn[i++] = '\0';
		hna = (char *) sm_malloc(i + 1);
		if (hna == NULL) goto enomem;
		strlcpy(hna, hn, i);
		hl = i - 1;

		/* skip over whitespace */
		while ((c = sm_io_getc(fp)) != SM_IO_EOF && ISSPACE(c))
			;
		if (c != SM_IO_EOF)
			sm_io_ungetc(fp, c);

		/* read RHS and check syntax */
		i = 0;
		while ((c = sm_io_getc(fp)) != SM_IO_EOF &&
			(ISALNUM(c) ||
			 c == '.' || c == '-' || c == '[' || c == ']' ||
			 c == ':' ||
			 c == SMAR_RHS_SEP_C || c == SMAR_RHS_PORT_C ||
			 c == SMAR_RHS_PROT_C
			))
		{
			ipv4[i++] = (char) c;
			if (i >= (int) sizeof(ipv4))
				goto syntax;
		}
		ipv4[i++] = '\0';
		if (c == SM_IO_EOF || !ISSPACE(c)) {
			sm_log_write(smar_ctx->smar_lctx,
				AR_LCAT_INIT, AR_LMOD_CONFIG,
				SM_LOG_ERROR, 0,
				"sev=ERROR, func=smar_mt_init, syntax_error_rhs=\"%.256s\"",
				ipv4);
			goto syntax;
		}
		ipv4a = (char *) sm_malloc(i);
		if (ipv4a == NULL) goto enomem;

		strlcpy(ipv4a, ipv4, i);
		eos = ipv4a + i;
		for (addr = ipv4a; *addr != '\0' && addr < eos; ++addr)
		{
			if (*addr == '[') {
				ret = sm_inet_a2ipv4(addr, NULL, NULL);
				if (sm_is_err(ret)) {
					sm_log_write(smar_ctx->smar_lctx,
						AR_LCAT_INIT, AR_LMOD_CONFIG,
						SM_LOG_ERROR, 0,
						"sev=ERROR, func=smar_mt_init, not_an_IPv4_address=\"%.256s\", input=%.256s",
						addr, ipv4a);

					ret = sm_error_perm(SM_EM_AR, errno);
					goto error;
				}
			}

			/* skip to end of address */
			while (*addr != '\0' && *addr != SMAR_RHS_SEP_C &&
			       addr < eos)
				++addr;
			if (*addr == '\0')
				break;
		}
		sm_str_assign(key, NULL, (uchar *)hna, hl, hl + 2);
		sm_str_assign(data, NULL, (uchar *)ipv4a, i, i + 2);
		ret = sm_map_add(smar_ctx->smar_mt_map, &key, &data, SMMAP_AFL_UNIQUE);
		if (sm_is_err(ret)) goto error;
	}
	sm_io_close(fp, SM_IO_CF_NONE);
	return SM_SUCCESS;

  enomem:
	ret = sm_error_temp(SM_EM_AR, ENOMEM);
	goto error;
  syntax:
	ret = sm_error_perm(SM_EM_AR, SM_E_SYNTAX);
  error:
	if (fp != NULL)
		sm_io_close(fp, SM_IO_CF_NONE);
	return ret;
}


syntax highlighted by Code2HTML, v. 0.9.1