/*
* Copyright (c) 2003-2006 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: t-mapaddr-0.c,v 1.21 2006/10/05 04:27:38 ca Exp $")
#include "sm/error.h"
#include "sm/heap.h"
#include "sm/memops.h"
#include "sm/sysexits.h"
#include "sm/string.h"
#include "sm/maps.h"
#include "sm/mapc.h"
#include "sm/map.h"
#include "sm/mapclasses.h"
#include "sm/bdb.h"
#include "sm/cdb_map.h"
#include "sm/test.h"
#include "sm/io.h"
/*
** Test program for sm_map_lookup_addr()
** Input: lines on stdin, each line has 4 fields separated by ':'
** tag:user:detail:domain
** If an element should be NULL replace it by 'N'.
*/
int Verbose = 0;
#define BUFLEN 512
#define MAXLEN 1024
#define MAPC_TYPE "hash"
#define MAPC_NAME "bdb3"
#define MAPC_FILE "./bdb3.db"
#define MAPC_STYPE "strmap"
#define MAPC_SNAME "str"
#define MAPC_SFILE "none"
/* put into libcheck? */
static int
stripcr(char *buf)
{
int n;
n = strlen(buf);
while (n > 0 && buf[n - 1] == '\n')
{
buf[n - 1] = '\0';
--n;
}
return n;
}
static void
usage(const char *prg)
{
sm_io_fprintf(smioerr,
"%s: usage: %s [options]\n"
"test address lookup in %s map %s\n"
"Input: lines on stdin, each line has 4 fields separated by ':'\n"
"tag:user:detail:domain\n"
"If an element should be NULL replace it by 'N'.\n"
"options:\n"
" -a alias lookup type\n"
" -d delim set delimiter\n"
" -F file name of db file [%s]\n"
" -f flags set lookup flags\n"
" -m set replace ${macro} flag\n"
" -n name name of map [%s]\n"
" -r set replace %%n flag\n"
" -s key use a str map with key\n"
" -T type map type [%s]\n"
" -v virtuser lookup\n"
, prg, prg
, MAPC_TYPE
, MAPC_FILE
, MAPC_FILE
, MAPC_NAME
, MAPC_TYPE
);
exit(EX_USAGE);
}
static sm_ret_T
init_mapc_test(sm_maps_P maps)
{
sm_ret_T ret;
SM_REQUIRE(maps != NULL);
ret = sm_bdb_class_create(maps);
SM_TEST(sm_is_success(ret));
#if MTA_USE_TINYCDB
ret = sm_cdb_class_create(maps);
SM_TEST(sm_is_success(ret));
#endif
return ret;
}
static sm_ret_T
db_map_open(sm_maps_P maps, sm_map_P *pmap, const char *mapname, const char *mapfile, const char *maptype)
{
sm_ret_T ret;
sm_map_P map;
sm_cstr_P mtype, mname;
mtype = mname = NULL;
ret = SM_SUCCESS;
mtype = sm_cstr_scpyn0((const uchar *)maptype, strlen(maptype));
SM_TEST(mtype != NULL);
if (mtype == NULL)
goto error;
mname = sm_cstr_scpyn0((const uchar *)mapname, strlen(mapname));
SM_TEST(mname != NULL);
if (mname == NULL)
goto error;
init_mapc_test(maps);
map = NULL;
ret = sm_map_open(maps, mname, mtype, 0, mapfile, SMAP_MODE_RDONLY,
&map, SMPO_END);
SM_CSTR_FREE(mtype);
SM_CSTR_FREE(mname);
SM_TEST(sm_is_success(ret));
*pmap = map;
return ret;
error:
SM_CSTR_FREE(mtype);
SM_CSTR_FREE(mname);
if (sm_is_success(ret))
ret = ENOMEM;
return ret;
}
static sm_ret_T
str_map_open(sm_str_P strmap, sm_maps_P maps, sm_map_P *pmap)
{
sm_ret_T ret;
sm_map_P map;
sm_cstr_P mtype, mname;
mtype = mname = NULL;
ret = SM_SUCCESS;
mtype = sm_cstr_scpyn0((const uchar *)MAPC_STYPE, strlen(MAPC_STYPE));
SM_TEST(mtype != NULL);
if (mtype == NULL)
goto error;
mname = sm_cstr_scpyn0((const uchar *)MAPC_SNAME, strlen(MAPC_SNAME));
SM_TEST(mname != NULL);
if (mname == NULL)
goto error;
ret = sm_strmap_class_create(maps);
SM_TEST(sm_is_success(ret));
map = NULL;
ret = sm_map_open(maps, mname, mtype, 0, MAPC_SFILE, SMAP_MODE_RDONLY,
&map, SMPO_STR, strmap, SMPO_END);
SM_CSTR_FREE(mtype);
SM_CSTR_FREE(mname);
SM_TEST(sm_is_success(ret));
*pmap = map;
return ret;
error:
SM_CSTR_FREE(mtype);
SM_CSTR_FREE(mname);
if (sm_is_success(ret))
ret = ENOMEM;
return ret;
}
int
main(int argc, char *argv[])
{
int n, c, list_mapc;
sm_ret_T ret;
uint32_t flags;
sm_maps_P maps;
sm_map_P map;
sm_str_P user, detail, domain, tag, rhs, strmap;
char *buf, *ap, *s, *sep;
uchar delim;
char *mapname, *mapfile, *maptype, *prg;
prg = argv[0];
mapname = MAPC_NAME;
mapfile = MAPC_FILE;
maptype = MAPC_TYPE;
sep = ":";
delim = (uchar) '+';
buf = NULL;
flags = SMMAP_LFL_ALL;
strmap = NULL;
list_mapc = -1;
while ((c = getopt(argc, argv, "ad:F:f:l:mn:rs:T:vV")) != -1)
{
switch (c)
{
case 'a':
flags = SMMAP_LFL_ALIAS;
break;
case 'd':
delim = (uchar) optarg[0];
break;
case 'F':
SM_STRDUP_OPT(mapfile, optarg);
break;
case 'f':
flags = (uint32_t) strtoul(optarg, NULL, 0);
break;
case 'l':
list_mapc = (int) strtol(optarg, NULL, 0);
break;
case 'm':
flags |= SMMAP_LFL_MCR_REPL;
break;
case 'n':
SM_STRDUP_OPT(mapname, optarg);
break;
case 'r':
flags |= SMMAP_LFL_REPL;
break;
case 's':
strmap = sm_str_scpy(NULL, optarg, 256);
break;
case 'T':
SM_STRDUP_OPT(maptype, optarg);
break;
case 'v':
flags = SMMAP_LFL_VIRTUSER;
break;
case 'V':
++Verbose;
break;
default:
usage(prg);
exit(EX_USAGE);
}
}
sm_test_begin(argc, argv, "test map address");
if (list_mapc >= 0)
{
sm_ret_T ret;
sm_maps_P maps;
maps = NULL;
ret = sm_maps_init(&maps);
if (NULL == maps)
exit(EX_OSERR);
ret = init_mapc_test(maps);
if (sm_is_err(ret))
exit(EX_OSERR);
c = sm_mapc_list(smioout, maps, list_mapc, 0);
return 0;
}
maps = NULL;
rhs = NULL;
user = NULL;
detail = NULL;
domain = NULL;
tag = NULL;
buf = sm_malloc(BUFLEN);
SM_TEST(buf != NULL);
if (buf == NULL)
goto error;
ret = sm_maps_init(&maps);
SM_TEST(maps != NULL);
if (maps == NULL)
goto error;
SM_TEST(sm_is_success(ret));
if (strmap != NULL)
ret = str_map_open(strmap, maps, &map);
else
ret = db_map_open(maps, &map, mapname, mapfile, maptype);
SM_TEST(sm_is_success(ret));
if (sm_is_err(ret))
goto error;
user = sm_str_new(NULL, 64, 1024);
SM_TEST(user != NULL);
if (user == NULL)
goto error;
detail = sm_str_new(NULL, 64, 1024);
SM_TEST(detail != NULL);
if (detail == NULL)
goto error;
domain = sm_str_new(NULL, 256, 1024);
SM_TEST(domain != NULL);
if (domain == NULL)
goto error;
tag = sm_str_new(NULL, 16, 1024);
SM_TEST(tag != NULL);
if (tag == NULL)
goto error;
rhs = sm_str_new(NULL, 256, 1024);
SM_TEST(rhs != NULL);
if (rhs == NULL)
goto error;
/* perform some operations ... */
while (fgets(buf, BUFLEN, stdin))
{
n = getc(stdin);
ungetc(n, stdin);
if (n == ' ' || n == '\t')
{
n = strlen(buf);
fgets(buf + n, BUFLEN - n, stdin);
}
n = stripcr(buf);
if (n <= 0)
goto error; /* bogus input, don't try to recover */
sm_str_clr(user);
sm_str_clr(detail);
sm_str_clr(domain);
sm_str_clr(tag);
s = buf;
#define GET_PART(string) \
do { \
ap = strsep(&s, sep); \
SM_TEST(ap != NULL); \
if (ap == NULL) \
break; \
ret = sm_str_scat(string, ap); \
SM_TEST(ret == SM_SUCCESS); \
if (ret != SM_SUCCESS) \
break; \
} while (0)
#define ISNULL(str) \
(sm_str_getlen(str) == 1 && sm_str_rd_elem(str, 0) == 'N')
#define MAYBENULL(str) (ISNULL(str) ? NULL : (str))
GET_PART(tag);
if (!ISNULL(tag))
{
ret = sm_str_put(tag, (uchar) ':');
SM_TEST(ret == SM_SUCCESS);
if (ret != SM_SUCCESS)
break;
}
GET_PART(user);
GET_PART(detail);
GET_PART(domain);
if (Verbose > 1)
{
sm_io_fprintf(smioerr, "tag='%S' ", tag);
sm_io_fprintf(smioerr, "user='%S' ", user);
sm_io_fprintf(smioerr, "detail='%S' ", detail);
sm_io_fprintf(smioerr, "domain='%S'\n", domain);
}
sm_str_clr(rhs);
ret = sm_map_lookup_addr(map,
MAYBENULL(user),
MAYBENULL(detail),
MAYBENULL(domain),
MAYBENULL(tag),
delim, flags, rhs);
sm_io_fprintf(smioerr, "ret=%x, rhs='%S'\n", ret, rhs);
}
ret = sm_map_close(map, 0);
SM_TEST(sm_is_success(ret));
ret = sm_maps_term(maps);
SM_TEST(sm_is_success(ret));
maps = NULL;
/* fallthrough for cleanup */
error:
if (maps != NULL)
sm_maps_term(maps);
SM_STR_FREE(user);
SM_STR_FREE(detail);
SM_STR_FREE(domain);
SM_STR_FREE(tag);
SM_STR_FREE(rhs);
SM_FREE(buf);
return sm_test_end();
}
syntax highlighted by Code2HTML, v. 0.9.1