/*
* 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: passwd.c,v 1.15 2006/10/05 04:27:38 ca Exp $")
#include "sm/assert.h"
#include "sm/error.h"
#include "sm/memops.h"
#include "sm/heap.h"
#include "sm/types.h"
#include "map.h"
#include "sm/map.h"
#include "sm/maps.h"
#include "sm/mapc.h"
#include "sm/mapclasses.h"
#include "sm/pwd.h"
#if 0
#include "sm/io.h"
#endif /* 0 */
/* static sm_map_open_F sm_passwd_open; */
/* static sm_map_close_F sm_passwd_close; */
static sm_map_alloc_F sm_passwd_alloc;
static sm_map_free_F sm_passwd_free;
static sm_map_locate_F sm_passwd_locate;
static sm_map_first_F sm_passwd_first;
static sm_map_next_F sm_passwd_next;
/*
** MAP_SETOPT -- set options for map
**
** Parameters:
** map -- map
** ap -- options
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_setopt(sm_map_P map, va_list ap)
{
SM_IS_MAP(map);
return SM_SUCCESS;
}
/*
** MAP_GETOPT -- get options for map
**
** Parameters:
** map -- map
** which -- which option?
** valp -- pointer to place where result should be stored
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_getopt(sm_map_P map, int which, void *valp)
{
SM_IS_MAP(map);
return SM_SUCCESS;
}
/*
** MAP_CLOSE -- close map
** XXX more parameters...
**
** Parameters:
** map -- map
** flags -- flags
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_close(sm_map_P map, uint32_t flags)
{
return SM_SUCCESS;
}
/*
** MAP_CREATE -- create map
**
** Parameters:
** pmap -- pointer to map (output)
** flags -- flags
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_create(sm_mapc_P mapc, const sm_cstr_P type, uint32_t flags, sm_map_P map)
{
SM_IS_MAPC(mapc);
SM_REQUIRE(map != NULL);
map->sm_map_caps = SMMAP_CAPS_LOCALPART;
return SM_SUCCESS;
}
/*
** MAP_OPEN -- open map
**
** Parameters:
** mapc -- map context
** type -- type of map (currently ignored)
** flags -- flags for map (currently ignored)
** path -- path of map (currently ignored)
** mode -- open mode (currently ignored)
** map -- map
** ap -- additional argument
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_open(sm_mapc_P mapc, const sm_cstr_P type, uint32_t flags, const char *path, int mode, sm_map_P map, va_list ap)
{
SM_IS_MAPC(mapc);
SM_REQUIRE(map != NULL);
#if 0
db = map->sm_map_db;
for (;;)
{
k = va_arg(ap, uint);
if (k == SMPO_END)
break;
switch (k)
{
case SMPO_MAX_ELEM:
u = va_arg(ap, uint);
db->passwd_limit = u;
break;
case SMPO_HASH_NELEM:
u = va_arg(ap, uint);
db->passwd_size = u;
break;
default:
/* silently ignore bogus options? */
break;
}
}
ret = passwd_open(&db);
if (sm_is_err(ret))
goto error;
#endif /* 0 */
return SM_SUCCESS;
#if 0
error:
if (db != NULL)
{
(void) passwd_destroy(db, NULL, NULL);
db = NULL;
}
return ret;
#endif /* 0 */
}
/*
** SM_PASSWD_LOOKUP -- lookup a key in PASSWD, return data if found
**
** Parameters:
** map -- map context
** flags -- flags
** key -- key
** data -- data (output)
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_lookup(sm_map_P map, uint32_t flags, sm_map_key_P key, sm_map_data_P data)
{
sm_ret_T ret;
int r;
sm_mapc_P mapc;
struct passwd *pwent;
#if MTA_USE_PTHREADS && HAVE_GETPWNAM_R
struct passwd pwentb;
char buf[1024];
#endif
SM_IS_MAP(map);
SM_IS_KEY(key);
SM_IS_DATA(data);
mapc = map->sm_map_class;
SM_IS_MAPC(mapc);
ret = SM_SUCCESS;
if (!SMMAP_IS_FL(map, SMMAP_FL_OPEN))
{
/* map closed but can be reopened? */
if (mapc->sm_mapc_reopenf != NULL)
ret = mapc->sm_mapc_reopenf(map, 0);
else
ret = sm_error_perm(SM_EM_MAP, SM_E_CLOSEDMAP);
if (sm_is_err(ret))
return ret;
}
/* XXX WARNING: changes key inplace! */
if (SM_IS_FLAG(flags, SMMAP_FL_LWR_KEY))
sm_str2lower(key);
r = 0;
#if MTA_USE_PTHREADS && HAVE_GETPWNAM_R
# if POSIX_GETPWNAM_R
r = getpwnam_r((const char *) sm_str_getdata(key),
&pwentb, buf, sizeof(buf), &pwent);
# else
pwent = getpwnam_r((const char *) sm_str_getdata(key),
&pwentb, buf, sizeof(buf));
# endif
#else /* MTA_USE_PTHREADS && HAVE_GETPWNAM_R */
pwent = getpwnam((const char *) sm_str_getdata(key));
#endif /* MTA_USE_PTHREADS && HAVE_GETPWNAM_R */
ret = (pwent == NULL || r != 0) ? sm_error_perm(SM_EM_MAP, SM_E_NOTFOUND)
: SM_SUCCESS;
if (ret == SM_SUCCESS && data != NULL)
{
/* WARNING: must be NUL terminated string! */
ret = sm_str_scat(data, (const char *) pwent->pw_gecos);
if (sm_is_err(ret))
return ret;
}
return ret;
}
#if 0
/*
** SM_PASSWD_ADD -- add key/data to PASSWD
**
** Parameters:
** map -- map context
** key -- key
** data -- data
** flags -- flags
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_add(sm_map_P map, sm_map_key_P key, sm_map_data_P data, uint flags)
{
return sm_error_perm(SM_EM_MAP, EINVAL);
}
/*
** SM_PASSWD_RM -- remove key/data from PASSWD
**
** Parameters:
** map -- map context
** key -- key
**
** Returns:
** usual sm_error code
*/
static sm_ret_T
sm_passwd_rm(sm_map_P map, sm_map_key_P key)
{
return sm_error_perm(SM_EM_MAP, EINVAL);
}
#endif /* 0 */
/*
** SM_PASSWD_CLASS_CREATE -- create PASSWD map class
**
** Parameters:
** maps -- map system context
**
** Returns:
** usual sm_error code
*/
sm_ret_T
sm_passwd_class_create(sm_maps_P maps)
{
sm_ret_T ret;
sm_mapc_P mapc;
sm_cstr_P htype;
#define PASSWD_TYPE "passwd"
ret = SM_SUCCESS;
mapc = NULL;
htype = sm_cstr_scpyn0((const uchar *)PASSWD_TYPE, strlen(PASSWD_TYPE));
if (htype == NULL)
goto error;
/* is getpasswd() thread safe? */
ret = sm_mapc_create(maps, htype,
#if MTA_USE_PTHREADS && HAVE_GETPWNAM_R
0,
#else
SMMAPC_FL_LCK_FULL,
#endif
sm_passwd_create,
sm_passwd_open,
sm_passwd_close,
NULL, /* reopen XXX FIX! */
NULL, /* destroy */
NULL /*sm_passwd_add*/,
NULL /*sm_passwd_rm*/,
sm_passwd_alloc,
sm_passwd_free,
sm_passwd_lookup,
sm_passwd_locate,
sm_passwd_first,
sm_passwd_next,
sm_passwd_setopt,
sm_passwd_getopt,
&mapc);
SM_CSTR_FREE(htype);
return ret;
error:
if (ret == SM_SUCCESS)
ret = sm_error_temp(SM_EM_MAP, ENOMEM);
/* cleanup mapc? */
return ret;
}
syntax highlighted by Code2HTML, v. 0.9.1