summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2010-10-15 10:58:46 +0000
committerArthur de Jong <arthur@arthurdejong.org>2010-10-15 10:58:46 +0000
commit1fab81db27cbe228d576ce5bda756d3af42e3817 (patch)
tree45db8e81253e07a9ecf3a9051c6f4e65e91a4499
parent6c1fd9d223e14b80db18058a720a61be415c1936 (diff)
parentf6bbbc5da9d72ec6637ef8fea58c73686abdace1 (diff)
merge changes from trunk
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd-solaris@1280 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r--common/dict.c22
-rw-r--r--common/dict.h16
-rw-r--r--common/set.c15
-rw-r--r--common/set.h13
-rw-r--r--nslcd/myldap.c42
-rw-r--r--tests/test_dict.c16
-rw-r--r--tests/test_set.c29
7 files changed, 102 insertions, 51 deletions
diff --git a/common/dict.c b/common/dict.c
index 128321d..c42b8b4 100644
--- a/common/dict.c
+++ b/common/dict.c
@@ -2,7 +2,7 @@
dict.c - dictionary functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008, 2009 Arthur de Jong
+ Copyright (C) 2007, 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -69,13 +69,12 @@ struct dictionary {
struct dict_entry **table; /* the hashtable */
};
-/* Simple hash function that computes the hash value of a lower-cased
- string. */
+/* Simple hash function that computes the hash value of a string. */
static uint32_t stringhash(const char *str)
{
uint32_t hash=0;
while (*str!='\0')
- hash=3*hash+tolower(*str++);
+ hash=3*hash+*str++;
return hash;
}
@@ -170,13 +169,24 @@ void *dict_get(DICT *dict,const char *key)
for (entry=dict->table[hash%dict->size];entry!=NULL;entry=entry->next)
{
if ( (entry->hash==hash) &&
- (strcasecmp(entry->key,key)==0) )
+ (strcmp(entry->key,key)==0) )
return entry->value;
}
/* no matches found */
return NULL;
}
+const char *dict_getany(DICT *dict)
+{
+ int i;
+ /* loop over the linked list in the hashtable */
+ for (i=0;i<dict->size;i++)
+ if (dict->table[i])
+ return dict->table[i]->key;
+ /* no matches found */
+ return NULL;
+}
+
int dict_put(DICT *dict,const char *key,void *value)
{
uint32_t hash;
@@ -196,7 +206,7 @@ int dict_put(DICT *dict,const char *key,void *value)
prev=entry,entry=entry->next)
{
if ( (entry->hash==hash) &&
- (strcasecmp(entry->key,key)==0) )
+ (strcmp(entry->key,key)==0) )
{
/* check if we should unset the entry */
if (value==NULL)
diff --git a/common/dict.h b/common/dict.h
index ee231e1..bb244f0 100644
--- a/common/dict.h
+++ b/common/dict.h
@@ -2,7 +2,7 @@
dict.h - dictionary functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008, 2009 Arthur de Jong
+ Copyright (C) 2007, 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -26,8 +26,7 @@
#include "compat/attrs.h"
/*
- These functions provide a mapping between a case insensitive
- string and a pointer.
+ These functions provide a mapping between a string and a pointer.
*/
typedef struct dictionary DICT;
@@ -40,17 +39,22 @@ DICT *dict_new(void)
and can be reused by the caller. The pointer is just stored.
This function returns non-0 in case of memory allocation
errors. If the key was previously in use the value
- is replaced. All key comparisons are case insensitive. */
+ is replaced. All key comparisons are case sensitive. */
int dict_put(DICT *dict,const char *key,void *value);
/* Look up a key in the dictionary and return the associated
value. NULL is returned if the key is not found in the dictionary.
- All key comparisons are case insensitive. */
+ All key comparisons are case sensitive. */
void *dict_get(DICT *dict,const char *key)
MUST_USE;
+/* Get a key from the dictionary that has a value set. The caller does
+ not need to free the returned value (it is freed when dict_free()
+ is called). */
+const char *dict_getany(DICT *dict);
+
/* Delete a key-value association from the dictionary.
- All key comparisons are case insensitive. */
+ All key comparisons are case sensitive. */
/*void dict_del(DICT *dict,const char *key);*/
/* Remove the dictionary from memory. All allocated storage
diff --git a/common/set.c b/common/set.c
index d36ce2d..aec7e83 100644
--- a/common/set.c
+++ b/common/set.c
@@ -2,7 +2,7 @@
set.c - set functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2008, 2009 Arthur de Jong
+ Copyright (C) 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -46,6 +46,19 @@ int set_add(SET *set,const char *value)
return dict_put((DICT *)set,value,set);
}
+char *set_pop(SET *set)
+{
+ const char *key;
+ char *value;
+ key=dict_getany((DICT *)set);
+ if (key==NULL)
+ return NULL; /* no more entries in set */
+ /* remove the entry from the dict and return a copy */
+ value=strdup(key);
+ dict_put((DICT *)set,key,NULL);
+ return value;
+}
+
int set_contains(SET *set,const char *value)
{
return dict_get((DICT *)set,value)!=NULL;
diff --git a/common/set.h b/common/set.h
index 5824bfc..d57c3db 100644
--- a/common/set.h
+++ b/common/set.h
@@ -2,7 +2,7 @@
set.h - set functions
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2008, 2009 Arthur de Jong
+ Copyright (C) 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -26,7 +26,7 @@
#include "compat/attrs.h"
/*
- These functions provide a set of string in an unordered
+ These functions provide a set of strings in an unordered
collection.
*/
typedef struct set SET;
@@ -39,14 +39,19 @@ SET *set_new(void)
/* Add a string in the set. The value is duplicated
and can be reused by the caller.
This function returns non-0 in case of memory allocation
- errors. All value comparisons are case insensitive. */
+ errors. All value comparisons are case sensitive. */
int set_add(SET *set,const char *value);
/* Return non-zero if the value is in the set.
- All value comparisons are case insensitive. */
+ All value comparisons are case sensitive. */
int set_contains(SET *set,const char *value)
MUST_USE;
+/* Get an element from the set and removes it from the set.
+ Returns NULL on an empty set. A copy of the string in the set
+ is returned, the caller should use free() to free it. */
+char *set_pop(SET *set);
+
/* Remove the set from memory. All allocated storage
for the set and the values is freed. */
void set_free(SET *set);
diff --git a/nslcd/myldap.c b/nslcd/myldap.c
index afbc898..902adbc 100644
--- a/nslcd/myldap.c
+++ b/nslcd/myldap.c
@@ -547,6 +547,20 @@ static void do_close(MYLDAP_SESSION *session)
{
int i;
int rc;
+ int sd=-1;
+ struct timeval tv;
+ /* set timeout options on socket to avoid hang in some cases
+ (we set a short timeout because we don't care too much about properly
+ shutting down the connection) */
+ if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
+ {
+ /* ignore errors */
+ tv.tv_sec=nslcd_cfg->ldc_timelimit/2;
+ if (!tv.tv_sec) tv.tv_sec=1;
+ tv.tv_usec=0;
+ (void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
+ (void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
+ }
/* if we had reachability problems with the server close the connection */
if (session->ld!=NULL)
{
@@ -621,7 +635,7 @@ static void myldap_session_check(MYLDAP_SESSION *session)
and binds to the server. This returns an LDAP status code. */
static int do_open(MYLDAP_SESSION *session)
{
- int rc,rc2;
+ int rc;
int sd=-1;
struct timeval tv;
/* check if the idle time for the connection has expired */
@@ -644,13 +658,7 @@ static int do_open(MYLDAP_SESSION *session)
ldap_err2string(rc),(errno==0)?"":": ",
(errno==0)?"":strerror(errno));
if (session->ld!=NULL)
- {
- log_log(LOG_DEBUG,"ldap_unbind()");
- rc2=ldap_unbind(session->ld);
- session->ld=NULL;
- if (rc2!=LDAP_SUCCESS)
- log_log(LOG_WARNING,"ldap_unbind() failed: %s",ldap_err2string(rc2));
- }
+ do_close(session);
return rc;
}
else if (session->ld==NULL)
@@ -662,10 +670,7 @@ static int do_open(MYLDAP_SESSION *session)
rc=do_set_options(session);
if (rc!=LDAP_SUCCESS)
{
- rc2=ldap_unbind(session->ld);
- session->ld=NULL;
- if (rc2!=LDAP_SUCCESS)
- log_log(LOG_WARNING,"ldap_unbind() failed: %s",ldap_err2string(rc2));
+ do_close(session);
return rc;
}
/* bind to the server */
@@ -679,18 +684,17 @@ static int do_open(MYLDAP_SESSION *session)
nslcd_cfg->ldc_uris[session->current_uri].uri,
ldap_err2string(rc),(errno==0)?"":": ",
(errno==0)?"":strerror(errno));
- rc2=ldap_unbind(session->ld);
- session->ld=NULL;
- if (rc2!=LDAP_SUCCESS)
- log_log(LOG_WARNING,"ldap_unbind() failed: %s",ldap_err2string(rc2));
+ do_close(session);
return rc;
}
- /* set timeout options on socket to avoid hang in some cases */
+ /* set timeout options on socket to avoid hang in some cases
+ (twice the normal timeout so this should only be triggered in cases
+ where the library behaves incorrectly) */
if (ldap_get_option(session->ld,LDAP_OPT_DESC,&sd)==LDAP_SUCCESS)
{
/* ignore errors */
- tv.tv_sec=nslcd_cfg->ldc_timelimit;
- tv.tv_usec=500;
+ tv.tv_sec=nslcd_cfg->ldc_timelimit*2;
+ tv.tv_usec=0;
(void)setsockopt(sd,SOL_SOCKET,SO_RCVTIMEO,(void *)&tv,sizeof(tv));
(void)setsockopt(sd,SOL_SOCKET,SO_SNDTIMEO,(void *)&tv,sizeof(tv));
}
diff --git a/tests/test_dict.c b/tests/test_dict.c
index 4e0adf9..05d54eb 100644
--- a/tests/test_dict.c
+++ b/tests/test_dict.c
@@ -2,7 +2,7 @@
test_dict.c - simple test for the dict module
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008, 2009 Arthur de Jong
+ Copyright (C) 2007, 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -47,19 +47,21 @@ static void test_simple(void)
dict_put(dict,"key1",value1);
dict_put(dict,"key2",value2);
dict_put(dict,"key3",dict);
- dict_put(dict,"KEY2",replace2);
+ dict_put(dict,"key2",replace2);
/* check dictionary contents */
- val=dict_get(dict,"KeY1");
+ val=dict_get(dict,"key1");
assert(val==value1);
- val=dict_get(dict,"kEy2");
+ val=dict_get(dict,"key2");
assert(val==replace2);
- val=dict_get(dict,"KeY3");
+ val=dict_get(dict,"key3");
assert(val==dict);
val=dict_get(dict,"key4");
assert(val==NULL);
+ val=dict_get(dict,"KEY1");
+ assert(val==NULL);
/* remove a key */
- dict_put(dict,"kEy3",NULL);
- val=dict_get(dict,"keY3");
+ dict_put(dict,"key3",NULL);
+ val=dict_get(dict,"key3");
assert(val==NULL);
/* loop over dictionary contents */
keys=dict_keys(dict);
diff --git a/tests/test_set.c b/tests/test_set.c
index 2623906..6f72b4d 100644
--- a/tests/test_set.c
+++ b/tests/test_set.c
@@ -2,7 +2,7 @@
test_set.c - simple test for the set module
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2008, 2009 Arthur de Jong
+ Copyright (C) 2008, 2009, 2010 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
@@ -30,6 +30,14 @@
#include "common/set.h"
#include "compat/attrs.h"
+static int isknownvalue(const char *value)
+{
+ return value!=NULL && (
+ (strcmp(value,"key1")==0) ||
+ (strcmp(value,"key2")==0) ||
+ (strcmp(value,"key3")==0) );
+}
+
/* the main program... */
int main(int UNUSED(argc),char UNUSED(*argv[]))
{
@@ -44,23 +52,28 @@ int main(int UNUSED(argc),char UNUSED(*argv[]))
set_add(set,"key1");
set_add(set,"key2");
set_add(set,"key3");
- set_add(set,"KEY2");
+ set_add(set,"key2");
/* check set contents */
- assert(set_contains(set,"KeY1"));
- assert(set_contains(set,"kEy2"));
- assert(set_contains(set,"KeY3"));
+ assert(set_contains(set,"key1"));
+ assert(set_contains(set,"key2"));
+ assert(set_contains(set,"key3"));
assert(!set_contains(set,"key4"));
+ assert(!set_contains(set,"KEY1"));
/* loop over set contents */
list=set_tolist(set);
for (i=0;list[i]!=NULL;i++)
{
- assert( (strcasecmp(list[i],"key1")==0) ||
- (strcasecmp(list[i],"key2")==0) ||
- (strcasecmp(list[i],"key3")==0) );
+ assert(isknownvalue(list[i]));
}
+ /* remove keys from the set */
+ assert(isknownvalue(set_pop(set)));
+ assert(isknownvalue(set_pop(set)));
+ assert(isknownvalue(set_pop(set)));
+ assert(set_pop(set)==NULL);
+
/* free set */
set_free(set);
free(list);