/* * 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(); }