diff -Naur nssov.orig/alias.c nssov/alias.c
--- nssov.orig/alias.c	2009-08-16 15:55:25.000000000 -0500
+++ nssov/alias.c	2010-03-06 20:49:08.380209582 -0600
@@ -83,7 +83,7 @@
 	/* for each name, write an entry */
 	for (i=0;!BER_BVISNULL(&names[i]);i++)
 	{
-		WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+		WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 		WRITE_BERVAL(cbp->fp,&names[i]);
 		WRITE_BVARRAY(cbp->fp,members);
 	}
@@ -97,7 +97,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_alias_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/ether.c nssov/ether.c
--- nssov.orig/ether.c	2009-08-16 15:55:25.000000000 -0500
+++ nssov/ether.c	2010-03-06 20:49:10.720143987 -0600
@@ -111,7 +111,7 @@
 	for (i=0;!BER_BVISNULL(&names[i]);i++)
 		for (j=0;!BER_BVISNULL(&ethers[j]);j++)
 		{
-			WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+			WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 			WRITE_BERVAL(cbp->fp,&names[i]);
 			WRITE_ETHER(cbp->fp,ethers[j]);
 		}
@@ -126,7 +126,7 @@
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
 	BER_BVZERO(&cbp.addr);
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_ether_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/group.c nssov/group.c
--- nssov.orig/group.c	2009-08-16 15:55:25.000000000 -0500
+++ nssov/group.c	2010-03-06 20:49:08.217323311 -0600
@@ -248,7 +248,7 @@
 						names[i].bv_val);
 					continue;
 				}
-				WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+				WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 				WRITE_BERVAL(cbp->fp,&names[i]);
 				WRITE_BERVAL(cbp->fp,&passwd);
 				WRITE_TYPE(cbp->fp,gid,gid_t);
@@ -277,7 +277,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;
 	if (!isvalidgroupname(&cbp.name)) {
@@ -316,7 +316,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.user.bv_len = tmpint32;
 	cbp.user.bv_val = cbp.buf;
 	if (!isvalidusername(&cbp.user)) {
diff -Naur nssov.orig/host.c nssov/host.c
--- nssov.orig/host.c	2009-08-21 17:33:26.000000000 -0500
+++ nssov/host.c	2010-03-06 20:49:14.707383568 -0600
@@ -91,7 +91,7 @@
 	addrs = a->a_vals;
 	numaddr = a->a_numvals;
 	/* write the entry */
-	WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(cbp->fp,&name);
 	if ( dupname >= 0 ) {
 		WRITE_INT32(cbp->fp,numname-1);
@@ -118,7 +118,7 @@
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
 	BER_BVZERO(&cbp.addr);
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_host_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/Makefile nssov/Makefile
--- nssov.orig/Makefile	2009-08-31 19:28:10.000000000 -0500
+++ nssov/Makefile	2010-03-06 20:49:06.681026723 -0600
@@ -24,7 +24,7 @@
 CC=gcc
 
 LDAP_INC=-I$(LDAPOBJ)/include -I$(LDAPSRC)/include -I$(LDAPSRC)/servers/slapd
-NLDAPD_INC=-Inss-ldapd
+NLDAPD_INC=-Inss-pam-ldapd
 INCS=$(LDAP_INC) $(NLDAPD_INC)
 
 LDAP_LIB=-lldap_r -llber
@@ -40,7 +40,7 @@
 sysconfdir = $(prefix)/etc$(ldap_subdir)
 schemadir = $(sysconfdir)/schema
 
-all:	install
+all:	nssov.la
 
 XOBJS = tio.lo
 
@@ -52,8 +52,8 @@
 .c.lo:
 	$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $<
 
-tio.lo:	nss-ldapd/common/tio.c
-	$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(NLDAPD_INC) -c $?
+tio.lo:	nss-pam-ldapd/tio.c
+	$(LIBTOOL) --mode=compile $(CC) $(OPT) $(DEFS) $(INCS) -c $?
 
 $(OBJS):	nssov.h
 
@@ -68,3 +68,4 @@
 
 clean:
 	rm -f *.*o *.la .libs/*
+	rm -rf .libs
diff -Naur nssov.orig/netgroup.c nssov/netgroup.c
--- nssov.orig/netgroup.c	2009-08-16 15:55:25.000000000 -0500
+++ nssov/netgroup.c	2010-03-06 20:49:10.230144280 -0600
@@ -140,8 +140,8 @@
 		return 0;
 	}
 	/* write strings */
-	WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
-	WRITE_INT32(fp,NETGROUP_TYPE_TRIPLE);
+	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
+	WRITE_INT32(fp,NSLCD_NETGROUP_TYPE_TRIPLE);
 	WRITE_STRING_STRIPSPACE_LEN(fp,triple+hostb,hoste-hostb)
 	WRITE_STRING_STRIPSPACE_LEN(fp,triple+userb,usere-userb)
 	WRITE_STRING_STRIPSPACE_LEN(fp,triple+domainb,domaine-domainb)
@@ -171,9 +171,9 @@
 		for (i=0;i<a->a_numvals;i++)
 		{
 			/* write the result code */
-			WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+			WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 			/* write triple indicator */
-			WRITE_INT32(cbp->fp,NETGROUP_TYPE_NETGROUP);
+			WRITE_INT32(cbp->fp,NSLCD_NETGROUP_TYPE_NETGROUP);
 			/* write netgroup name */
 			if (write_string_stripspace_len(cbp->fp,a->a_vals[i].bv_val,a->a_vals[i].bv_len))
 				return -1;
@@ -190,7 +190,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));,
+	READ_STRING(fp,cbp.buf);,
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;
 	Debug(LDAP_DEBUG_TRACE,"nssov_netgroup_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/network.c nssov/network.c
--- nssov.orig/network.c	2009-08-21 17:33:26.000000000 -0500
+++ nssov/network.c	2010-03-06 20:49:07.770144060 -0600
@@ -91,7 +91,7 @@
 	addrs = a->a_vals;
 	numaddr = a->a_numvals;
 	/* write the entry */
-	WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(cbp->fp,&name);
 	if ( dupname >= 0 ) {
 		WRITE_INT32(cbp->fp,numname-1);
@@ -118,7 +118,7 @@
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
 	BER_BVZERO(&cbp.addr);
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_network_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/nssov.h nssov/nssov.h
--- nssov.orig/nssov.h	2009-09-14 17:59:57.000000000 -0500
+++ nssov/nssov.h	2010-03-06 20:49:09.742554796 -0600
@@ -29,9 +29,9 @@
 #include <stdio.h>
 
 #include "nslcd.h"
-#include "nslcd-common.h"
-#include "common/tio.h"
-#include "compat/attrs.h"
+#include "nslcd-prot.h"
+#include "tio.h"
+#include "attrs.h"
 
 #undef PACKAGE_BUGREPORT
 #undef PACKAGE_NAME
diff -Naur nssov.orig/nss-pam-ldapd/attrs.h nssov/nss-pam-ldapd/attrs.h
--- nssov.orig/nss-pam-ldapd/attrs.h	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/attrs.h	2010-03-06 20:49:14.390522830 -0600
@@ -0,0 +1,91 @@
+/*
+   attrs.h - wrapper macros for the gcc __attribute__(()) directive
+
+   Copyright (C) 2007, 2008 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+#ifndef _COMPAT_ATTRS_H
+#define _COMPAT_ATTRS_H 1
+
+/* macro for testing the version of GCC */
+#define GCC_VERSION(major,minor) \
+  ((__GNUC__ > (major)) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))
+
+/* These are macros to use some gcc-specific flags in case the're available
+   and otherwise define them to empty strings. This allows us to give
+   the compiler some extra information.
+   See http://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html
+   for a list of attributes supported by gcc */
+
+/* this is used to flag function parameters that are not used in the function
+   body. */
+#if GCC_VERSION(3,0)
+#define UNUSED(x)   x __attribute__((__unused__))
+#else
+#define UNUSED(x)   x
+#endif
+
+/* this is used to add extra format checking to the function calls as if this
+   was a printf()-like function */
+#if GCC_VERSION(3,0)
+#define LIKE_PRINTF(format_idx,arg_idx) \
+                    __attribute__((__format__(__printf__,format_idx,arg_idx)))
+#else
+#define LIKE_PRINTF(format_idx,arg_idx) /* no attribute */
+#endif
+
+/* indicates that the function is "pure": it's result is purely based on
+   the parameters and has no side effects or used static data */
+#if GCC_VERSION(3,0)
+#define PURE        __attribute__((__pure__))
+#else
+#define PURE        /* no attribute */
+#endif
+
+/* the function returns a new data structure that has been freshly
+   allocated */
+#if GCC_VERSION(3,0)
+#define LIKE_MALLOC __attribute__((__malloc__))
+#else
+#define LIKE_MALLOC /* no attribute */
+#endif
+
+/* the function's return value should be used by the caller */
+#if GCC_VERSION(3,4)
+#define MUST_USE    __attribute__((__warn_unused_result__))
+#else
+#define MUST_USE    /* no attribute */
+#endif
+
+/* the function's return value should be used by the caller */
+#if GCC_VERSION(2,5)
+#define NORETURN    __attribute__((__noreturn__))
+#else
+#define NORETURN    /* no attribute */
+#endif
+
+/* define __STRING if it's not yet defined */
+#ifndef __STRING
+#ifdef __STDC__
+#define __STRING(x) #x
+#else /* __STDC__ */
+#define __STRING(x) "x"
+#endif /* not __STDC__ */
+#endif /* not __STRING */
+
+#endif /* not _COMPAT_ATTRS_H */
diff -Naur nssov.orig/nss-pam-ldapd/nslcd.h nssov/nss-pam-ldapd/nslcd.h
--- nssov.orig/nss-pam-ldapd/nslcd.h	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/nslcd.h	2010-03-06 20:49:12.832643761 -0600
@@ -0,0 +1,256 @@
+/*
+   nslcd.h - file describing client/server protocol
+
+   Copyright (C) 2006 West Consulting
+   Copyright (C) 2006, 2007, 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+#ifndef _NSLCD_H
+#define _NSLCD_H 1
+
+/*
+   The protocol used between the nslcd client and server is a simple binary
+   protocol. It is request/response based where the client initiates a
+   connection, does a single request and closes the connection again. Any
+   mangled or not understood messages will be silently ignored by the server.
+
+   A request looks like:
+     INT32  NSLCD_VERSION
+     INT32  NSLCD_ACTION_*
+     [request parameters if any]
+   A response looks like:
+     INT32  NSLCD_VERSION
+     INT32  NSLCD_ACTION_* (the original request type)
+     [result(s)]
+     INT32  NSLCD_RESULT_END
+   A single result entry looks like:
+     INT32  NSLCD_RESULT_BEGIN
+     [result value(s)]
+   If a response would return multiple values (e.g. for NSLCD_ACTION_*_ALL
+   functions) each return value will be preceded by a NSLCD_RESULT_BEGIN
+   value. After the last returned result the server sends
+   NSLCD_RESULT_END. If some error occurs (e.g. LDAP server unavailable,
+   error in the request, etc) the server terminates the connection to signal
+   an error condition (breaking the protocol).
+
+   These are the available basic data types:
+     INT32  - 32-bit integer value
+     TYPE   - a typed field that is transferred using sizeof()
+     STRING - a string length (32bit) followed by the string value (not
+              null-terminted) the string itself is assumed to be UTF-8
+     STRINGLIST - a 32-bit number noting the number of strings followed by
+                  the strings one at a time
+
+   Furthermore the ADDRESS compound data type is defined as:
+     INT32  type of address: e.g. AF_INET or AF_INET6
+     INT32  lenght of address
+     RAW    the address itself in network byte order
+   With the ADDRESSLIST using the same construct as with STRINGLIST.
+
+   The protocol uses host-byte order for all types (except in the raw
+   address above).
+*/
+
+/* The current version of the protocol. Note that version 1
+   is experimental and this version will be used until a
+   1.0 release of nss-pam-ldapd is made. */
+#define NSLCD_VERSION 1
+
+/* Email alias (/etc/aliases) NSS requests. The result values for a
+   single entry are:
+     STRING      alias name
+     STRINGLIST  alias rcpts */
+#define NSLCD_ACTION_ALIAS_BYNAME       4001
+#define NSLCD_ACTION_ALIAS_ALL          4002
+
+/* Ethernet address/name mapping NSS requests. The result values for a
+   single entry are:
+     STRING            ether name
+     TYPE(uint8_t[6])  ether address */
+#define NSLCD_ACTION_ETHER_BYNAME       3001
+#define NSLCD_ACTION_ETHER_BYETHER      3002
+#define NSLCD_ACTION_ETHER_ALL          3005
+
+/* Group and group membership related NSS requests. The result values
+   for a single entry are:
+     STRING       group name
+     STRING       group password
+     TYPE(gid_t)  group id
+     STRINGLIST   members (usernames) of the group
+     (not that the BYMEMER call returns an emtpy members list) */
+#define NSLCD_ACTION_GROUP_BYNAME       5001
+#define NSLCD_ACTION_GROUP_BYGID        5002
+#define NSLCD_ACTION_GROUP_BYMEMBER     5003
+#define NSLCD_ACTION_GROUP_ALL          5004
+
+/* Hostname (/etc/hosts) lookup NSS requests. The result values
+   for an entry are:
+     STRING       host name
+     STRINGLIST   host aliases
+     ADDRESSLIST  host addresses */
+#define NSLCD_ACTION_HOST_BYNAME        6001
+#define NSLCD_ACTION_HOST_BYADDR        6002
+#define NSLCD_ACTION_HOST_ALL           6005
+
+/* Netgroup NSS request return a number of results. Result values
+   can be either a reference to another netgroup:
+     INT32   NSLCD_NETGROUP_TYPE_NETGROUP
+     STRING  other netgroup name
+   or a netgroup triple:
+     INT32   NSLCD_NETGROUP_TYPE_TRIPLE
+     STRING  host
+     STRING  user
+     STRING  domain */
+#define NSLCD_ACTION_NETGROUP_BYNAME   12001
+#define NSLCD_NETGROUP_TYPE_NETGROUP 123
+#define NSLCD_NETGROUP_TYPE_TRIPLE   456
+
+/* Network name (/etc/networks) NSS requests. Result values for a single
+   entry are:
+     STRING       network name
+     STRINGLIST   network aliases
+     ADDRESSLIST  network addresses */
+#define NSLCD_ACTION_NETWORK_BYNAME     8001
+#define NSLCD_ACTION_NETWORK_BYADDR     8002
+#define NSLCD_ACTION_NETWORK_ALL        8005
+
+/* User account (/etc/passwd) NSS requests. Result values are:
+     STRING       user name
+     STRING       user password
+     TYPE(uid_t)  user id
+     TYPE(gid_t)  group id
+     STRING       gecos information
+     STRING       home directory
+     STRING       login shell */
+#define NSLCD_ACTION_PASSWD_BYNAME      1001
+#define NSLCD_ACTION_PASSWD_BYUID       1002
+#define NSLCD_ACTION_PASSWD_ALL         1004
+
+/* Protocol information requests. Result values are:
+     STRING      protocol name
+     STRINGLIST  protocol aliases
+     INT32       protocol number */
+#define NSLCD_ACTION_PROTOCOL_BYNAME    9001
+#define NSLCD_ACTION_PROTOCOL_BYNUMBER  9002
+#define NSLCD_ACTION_PROTOCOL_ALL       9003
+
+/* RPC information requests. Result values are:
+     STRING      rpc name
+     STRINGLIST  rpc aliases
+     INT32       rpc number */
+#define NSLCD_ACTION_RPC_BYNAME        10001
+#define NSLCD_ACTION_RPC_BYNUMBER      10002
+#define NSLCD_ACTION_RPC_ALL           10003
+
+/* Service (/etc/services) information requests. Result values are:
+     STRING      service name
+     STRINGLIST  service aliases
+     INT32       service (port) number
+     STRING      service protocol */
+#define NSLCD_ACTION_SERVICE_BYNAME    11001
+#define NSLCD_ACTION_SERVICE_BYNUMBER  11002
+#define NSLCD_ACTION_SERVICE_ALL       11005
+
+/* Extended user account (/etc/shadow) information requests. Result
+   values for a single entry are:
+     STRING  user name
+     STRING  user password
+     INT32   last password change
+     INT32   mindays
+     INT32   maxdays
+     INT32   warn
+     INT32   inact
+     INT32   expire
+     INT32   flag */
+#define NSLCD_ACTION_SHADOW_BYNAME      2001
+#define NSLCD_ACTION_SHADOW_ALL         2005
+
+/* PAM-related requests. The request parameters for all these requests
+   begin with:
+     STRING  user name
+     STRING  DN (if value is known already, otherwise empty)
+     STRING  service name
+   all requests, except the SESSION requests start the result value with:
+     STRING  user name (cannonical name)
+     STRING  DN (can be used to speed up requests) */
+
+/* PAM authentication check request. The extra request values are:
+     STRING  password
+   and the result value ends with:
+     INT32   authc NSLCD_PAM_* result code
+     INT32   authz NSLCD_PAM_* result code
+     STRING  authorisation error message
+   If the username is empty in this request an attempt is made to
+   authenticate as the administrator (set using rootpwmoddn). The returned DN
+   is that of the administrator. */
+#define NSLCD_ACTION_PAM_AUTHC         20001
+
+/* PAM authorisation check request. The extra request values are:
+     STRING ruser
+     STRING rhost
+     STRING tty
+   and the result value ends with:
+     INT32   authz NSLCD_PAM_* result code
+     STRING  authorisation error message */
+#define NSLCD_ACTION_PAM_AUTHZ         20002
+
+/* PAM session open and close requests. These requests have the following
+   extra request values:
+     STRING tty
+     STRING rhost
+     STRING ruser
+     INT32 session id (ignored for SESS_O)
+   and these calls only return the session ID:
+     INT32 session id
+   The SESS_C must contain the ID that is retured by SESS_O to close the
+   correct session. */
+#define NSLCD_ACTION_PAM_SESS_O        20003
+#define NSLCD_ACTION_PAM_SESS_C        20004
+
+/* PAM password modification request. This requests has the following extra
+   request values:
+     STRING old password
+     STRING new password
+   and returns there extra result values:
+     INT32   authz NSLCD_PAM_* result code
+     STRING  authorisation error message
+   In this request the DN may be set to the administrator's DN. In this
+   case old password should be the administrator's password. This allows
+   the administrator to change any user's password. */
+#define NSLCD_ACTION_PAM_PWMOD         20005
+
+/* Request result codes. */
+#define NSLCD_RESULT_BEGIN                 0
+#define NSLCD_RESULT_END                   3
+
+/* Partial list of PAM result codes. */
+#define NSLCD_PAM_SUCCESS             0 /* everything ok */
+#define NSLCD_PAM_PERM_DENIED         6 /* Permission denied */
+#define NSLCD_PAM_AUTH_ERR            7 /* Authc failure */
+#define NSLCD_PAM_CRED_INSUFFICIENT   8 /* Cannot access authc data */
+#define NSLCD_PAM_AUTHINFO_UNAVAIL    9 /* Cannot retrieve authc info */
+#define NSLCD_PAM_USER_UNKNOWN       10 /* User not known */
+#define NSLCD_PAM_MAXTRIES           11 /* Retry limit reached */
+#define NSLCD_PAM_NEW_AUTHTOK_REQD   12 /* Password expired */
+#define NSLCD_PAM_ACCT_EXPIRED       13 /* Account expired */
+#define NSLCD_PAM_SESSION_ERR        14 /* Cannot make/remove session record */
+#define NSLCD_PAM_AUTHTOK_DISABLE_AGING 23 /* Password aging disabled */
+#define NSLCD_PAM_IGNORE             25 /* Ignore module */
+#define NSLCD_PAM_ABORT              26 /* Fatal error */
+
+#endif /* not _NSLCD_H */
diff -Naur nssov.orig/nss-pam-ldapd/nslcd-prot.h nssov/nss-pam-ldapd/nslcd-prot.h
--- nssov.orig/nss-pam-ldapd/nslcd-prot.h	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/nslcd-prot.h	2010-03-06 20:49:13.485065012 -0600
@@ -0,0 +1,356 @@
+/*
+   nslcd-prot.h - helper macros for reading and writing in protocol streams
+
+   Copyright (C) 2006 West Consulting
+   Copyright (C) 2006, 2007, 2009 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+#ifndef _NSLCD_PROT_H
+#define _NSLCD_PROT_H 1
+
+#include "tio.h"
+
+/* If you use these macros you should define the following macros to
+   handle error conditions (these marcos should clean up and return from the
+   function):
+     ERROR_OUT_WRITEERROR(fp)
+     ERROR_OUT_READERROR(fp)
+     ERROR_OUT_BUFERROR(fp)
+     ERROR_OUT_NOSUCCESS(fp) */
+
+
+/* Debugging marcos that can be used to enable detailed protocol logging,
+   pass -DDEBUG_PROT to do overall protocol debugging, and -DDEBUG_PROT_DUMP
+   to dump the actual bytestream. */
+
+#ifdef DEBUG_PROT
+/* define a debugging macro to output logging */
+#include <string.h>
+#include <errno.h>
+#define DEBUG_PRINT(fmt,arg) \
+  fprintf(stderr,"%s:%d:%s: " fmt "\n",__FILE__,__LINE__,__PRETTY_FUNCTION__,arg);
+#else /* DEBUG_PROT */
+/* define an empty debug macro to disable logging */
+#define DEBUG_PRINT(fmt,arg)
+#endif /* not DEBUG_PROT */
+
+#ifdef DEBUG_PROT_DUMP
+/* define a debugging macro to output detailed logging */
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif /* HAVE_STDINT_H */
+static void debug_dump(const void *ptr,size_t size)
+{
+  int i;
+  for (i=0;i<size;i++)
+    fprintf(stderr," %02x",((const uint8_t *)ptr)[i]);
+  fprintf(stderr,"\n");
+}
+#define DEBUG_DUMP(ptr,size) \
+  fprintf(stderr,"%s:%d:%s:",__FILE__,__LINE__,__PRETTY_FUNCTION__); \
+  debug_dump(ptr,size);
+#else /* DEBUG_PROT_DUMP */
+/* define an empty debug macro to disable logging */
+#define DEBUG_DUMP(ptr,size)
+#endif /* not DEBUG_PROT_DUMP */
+
+
+/* WRITE marcos, used for writing data, on write error they will
+   call the ERROR_OUT_WRITEERROR macro
+   these macros may require the availability of the following
+   variables:
+   int32_t tmpint32; - temporary variable
+   */
+
+#define WRITE(fp,ptr,size) \
+  DEBUG_PRINT("WRITE       : var="__STRING(ptr)" size=%d",(int)size); \
+  DEBUG_DUMP(ptr,size); \
+  if (tio_write(fp,ptr,(size_t)size)) \
+  { \
+    DEBUG_PRINT("WRITE       : var="__STRING(ptr)" error: %s",strerror(errno)); \
+    ERROR_OUT_WRITEERROR(fp); \
+  }
+
+#define WRITE_TYPE(fp,field,type) \
+  WRITE(fp,&(field),sizeof(type))
+
+#define WRITE_INT32(fp,i) \
+  DEBUG_PRINT("WRITE_INT32 : var="__STRING(i)" int32=%d",(int)i); \
+  tmpint32=(int32_t)(i); \
+  WRITE_TYPE(fp,tmpint32,int32_t)
+
+#define WRITE_STRING(fp,str) \
+  DEBUG_PRINT("WRITE_STRING: var="__STRING(str)" string=\"%s\"",(str)); \
+  if ((str)==NULL) \
+  { \
+    WRITE_INT32(fp,0); \
+  } \
+  else \
+  { \
+    WRITE_INT32(fp,strlen(str)); \
+    if (tmpint32>0) \
+      { WRITE(fp,(str),tmpint32); } \
+  }
+
+#define WRITE_STRINGLIST(fp,arr) \
+  if ((arr)==NULL) \
+  { \
+    DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",0); \
+    WRITE_INT32(fp,0); \
+  } \
+  else \
+  { \
+    /* first determin length of array */ \
+    for (tmp3int32=0;(arr)[tmp3int32]!=NULL;tmp3int32++) \
+      /*noting*/ ; \
+    /* write number of strings */ \
+    DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
+    WRITE_TYPE(fp,tmp3int32,int32_t); \
+    /* write strings */ \
+    for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
+    { \
+      WRITE_STRING(fp,(arr)[tmp2int32]); \
+    } \
+  }
+
+#define WRITE_STRINGLIST_EXCEPT(fp,arr,not) \
+  /* first determin length of array */ \
+  tmp3int32=0; \
+  for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
+    if (strcmp((arr)[tmp2int32],(not))!=0) \
+      tmp3int32++; \
+  /* write number of strings (mius one because we intend to skip one) */ \
+  DEBUG_PRINT("WRITE_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
+  WRITE_TYPE(fp,tmp3int32,int32_t); \
+  /* write strings */ \
+  for (tmp2int32=0;(arr)[tmp2int32]!=NULL;tmp2int32++) \
+  { \
+    if (strcmp((arr)[tmp2int32],(not))!=0) \
+    { \
+      WRITE_STRING(fp,(arr)[tmp2int32]); \
+    } \
+  }
+
+
+/* READ macros, used for reading data, on read error they will
+   call the ERROR_OUT_READERROR or ERROR_OUT_BUFERROR macro
+   these macros may require the availability of the following
+   variables:
+   int32_t tmpint32; - temporary variable
+   */
+
+#define READ(fp,ptr,size) \
+  if (tio_read(fp,ptr,(size_t)size)) \
+  { \
+    DEBUG_PRINT("READ       : var="__STRING(ptr)" error: %s",strerror(errno)); \
+    ERROR_OUT_READERROR(fp); \
+  } \
+  DEBUG_PRINT("READ       : var="__STRING(ptr)" size=%d",(int)size); \
+  DEBUG_DUMP(ptr,size);
+
+#define READ_TYPE(fp,field,type) \
+  READ(fp,&(field),sizeof(type))
+
+#define READ_INT32(fp,i) \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  i=tmpint32; \
+  DEBUG_PRINT("READ_INT32 : var="__STRING(i)" int32=%d",(int)i);
+
+/* read a string in a fixed-size "normal" buffer */
+#define READ_STRING(fp,buffer) \
+  /* read the size of the string */ \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" strlen=%d",tmpint32); \
+  /* check if read would fit */ \
+  if (((size_t)tmpint32)>=sizeof(buffer)) \
+  { \
+    /* will not fit */ \
+    DEBUG_PRINT("READ       : buffer error: %d bytes too large",(tmpint32-sizeof(buffer))+1); \
+    ERROR_OUT_BUFERROR(fp); \
+  } \
+  /* read string from the stream */ \
+  if (tmpint32>0) \
+    { READ(fp,buffer,(size_t)tmpint32); } \
+  /* null-terminate string in buffer */ \
+  buffer[tmpint32]='\0'; \
+  DEBUG_PRINT("READ_STRING: var="__STRING(buffer)" string=\"%s\"",buffer);
+
+
+/* READ BUF macros that read data into a pre-allocated buffer.
+   these macros may require the availability of the following
+   variables:
+   int32_t tmpint32; - temporary variable
+   char *buffer;     - pointer to a buffer for reading strings
+   size_t buflen;    - the size of the buffer
+   size_t bufptr;    - the current position in the buffer
+   */
+
+/* current position in the buffer */
+#define BUF_CUR \
+  (buffer+bufptr)
+
+/* check that the buffer has sz bytes left in it */
+#define BUF_CHECK(fp,sz) \
+  if ((bufptr+(size_t)(sz))>buflen) \
+  { \
+    /* will not fit */ \
+    DEBUG_PRINT("READ       : buffer error: %d bytes too small",(bufptr+(sz)-(buflen))); \
+    ERROR_OUT_BUFERROR(fp); \
+  }
+
+/* move the buffer pointer */
+#define BUF_SKIP(sz) \
+  bufptr+=(size_t)(sz);
+
+/* move BUF_CUR foreward so that it is aligned to the specified
+   type width */
+#define BUF_ALIGN(fp,type) \
+  /* figure out number of bytes to skip foreward */ \
+  tmp2int32=(sizeof(type)-((BUF_CUR-(char *)NULL)%sizeof(type)))%sizeof(type); \
+  /* check and skip */ \
+  BUF_CHECK(fp,tmp2int32); \
+  BUF_SKIP(tmp2int32);
+
+/* allocate a piece of the buffer to store an array in */
+#define BUF_ALLOC(fp,ptr,type,num) \
+  /* align to the specified type width */ \
+  BUF_ALIGN(fp,type); \
+  /* check that we have enough room */ \
+  BUF_CHECK(fp,(size_t)(num)*sizeof(type)); \
+  /* store the pointer */ \
+  (ptr)=(type *)BUF_CUR; \
+  /* reserve the space */ \
+  BUF_SKIP((size_t)(num)*sizeof(type));
+
+/* read a binary blob into the buffer */
+#define READ_BUF(fp,ptr,sz) \
+  /* check that there is enough room and read */ \
+  BUF_CHECK(fp,sz); \
+  READ(fp,BUF_CUR,(size_t)sz); \
+  /* store pointer and skip */ \
+  (ptr)=BUF_CUR; \
+  BUF_SKIP(sz);
+
+/* read string in the buffer (using buffer, buflen and bufptr)
+   and store the actual location of the string in field */
+#define READ_BUF_STRING(fp,field) \
+  /* read the size of the string */ \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" strlen=%d",tmpint32); \
+  /* check if read would fit */ \
+  BUF_CHECK(fp,tmpint32+1); \
+  /* read string from the stream */ \
+  if (tmpint32>0) \
+    { READ(fp,BUF_CUR,(size_t)tmpint32); } \
+  /* null-terminate string in buffer */ \
+  BUF_CUR[tmpint32]='\0'; \
+  DEBUG_PRINT("READ_BUF_STRING: var="__STRING(field)" string=\"%s\"",BUF_CUR); \
+  /* prepare result */ \
+  (field)=BUF_CUR; \
+  BUF_SKIP(tmpint32+1);
+
+/* read an array from a stram and store it as a null-terminated
+   array list (size for the array is allocated) */
+#define READ_BUF_STRINGLIST(fp,arr) \
+  /* read the number of entries */ \
+  READ_TYPE(fp,tmp3int32,int32_t); \
+  DEBUG_PRINT("READ_STRLST: var="__STRING(arr)" num=%d",(int)tmp3int32); \
+  /* allocate room for *char[num+1] */ \
+  BUF_ALLOC(fp,arr,char *,tmp3int32+1); \
+  /* read all entries */ \
+  for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
+  { \
+    READ_BUF_STRING(fp,(arr)[tmp2int32]); \
+  } \
+  /* set last entry to NULL */ \
+  (arr)[tmp2int32]=NULL;
+
+
+/* SKIP macros for skipping over certain parts of the protocol stream. */
+
+/* skip a number of bytes foreward */
+#define SKIP(fp,sz) \
+  DEBUG_PRINT("READ       : skip %d bytes",(int)(sz)); \
+  /* read (skip) the specified number of bytes */ \
+  if (tio_skip(fp,sz)) \
+  { \
+    DEBUG_PRINT("READ       : skip error: %s",strerror(errno)); \
+    ERROR_OUT_READERROR(fp); \
+  }
+
+/* read a string from the stream but don't do anything with the result */
+#define SKIP_STRING(fp) \
+  /* read the size of the string */ \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  DEBUG_PRINT("READ_STRING: skip %d bytes",(int)tmpint32); \
+  /* read (skip) the specified number of bytes */ \
+  SKIP(fp,tmpint32);
+
+/* skip a list of strings */
+#define SKIP_STRINGLIST(fp) \
+  /* read the number of entries */ \
+  READ_TYPE(fp,tmp3int32,int32_t); \
+  DEBUG_PRINT("READ_STRLST: skip %d strings",(int)tmp3int32); \
+  /* read all entries */ \
+  for (tmp2int32=0;tmp2int32<tmp3int32;tmp2int32++) \
+  { \
+    SKIP_STRING(fp); \
+  }
+
+
+/* These are functions and macors for performing common operations in
+   the nslcd request/response protocol. */
+
+/* returns a socket to the server or NULL on error (see errno),
+   socket should be closed with tio_close() */
+TFILE *nslcd_client_open(void)
+  MUST_USE;
+
+/* generic request code */
+#define NSLCD_REQUEST(fp,action,writefn) \
+  /* open a client socket */ \
+  if ((fp=nslcd_client_open())==NULL) \
+    { ERROR_OUT_OPENERROR } \
+  /* write a request header with a request code */ \
+  WRITE_INT32(fp,(int32_t)NSLCD_VERSION) \
+  WRITE_INT32(fp,(int32_t)action) \
+  /* write the request parameters (if any) */ \
+  writefn; \
+  /* flush the stream */ \
+  if (tio_flush(fp)<0) \
+  { \
+    DEBUG_PRINT("WRITE_FLUSH : error: %s",strerror(errno)); \
+    ERROR_OUT_WRITEERROR(fp); \
+  } \
+  /* read and check response version number */ \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  if (tmpint32!=(int32_t)NSLCD_VERSION) \
+    { ERROR_OUT_READERROR(fp) } \
+  /* read and check response request number */ \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  if (tmpint32!=(int32_t)(action)) \
+    { ERROR_OUT_READERROR(fp) }
+
+/* Read the response code (the result code of the query) from
+   the stream. */
+#define READ_RESPONSE_CODE(fp) \
+  READ_TYPE(fp,tmpint32,int32_t); \
+  if (tmpint32!=(int32_t)NSLCD_RESULT_BEGIN) \
+    { ERROR_OUT_NOSUCCESS(fp) }
+
+#endif /* not _NSLCD_PROT_H */
diff -Naur nssov.orig/nss-pam-ldapd/README nssov/nss-pam-ldapd/README
--- nssov.orig/nss-pam-ldapd/README	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/README	2010-03-06 20:49:13.631495570 -0600
@@ -0,0 +1,7 @@
+These files were pulled from the nss-pam-ldapd project version 0.7.3.  Copyright notices are in the individual files.
+
+This is not the full distribution of nss-pam-ldapd, and does not
+include the client-side stub libraries.  Get the latest release of
+nss-pam-ldapd from http://arthurdejong.org/nss-pam-ldapd/ to use
+this overlay.
+
diff -Naur nssov.orig/nss-pam-ldapd/tio.c nssov/nss-pam-ldapd/tio.c
--- nssov.orig/nss-pam-ldapd/tio.c	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/tio.c	2010-03-06 20:49:14.226963772 -0600
@@ -0,0 +1,508 @@
+/*
+   tio.c - timed io functions
+   This file is part of the nss-pam-ldapd library.
+
+   Copyright (C) 2007, 2008 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+//#include "config.h"
+#include "portable.h"
+
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif /* HAVE_STDINT_H */
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <string.h>
+#include <signal.h>
+#include <stdio.h>
+
+#include "tio.h"
+
+/* for platforms that don't have ETIME use ETIMEDOUT */
+#ifndef ETIME
+#define ETIME ETIMEDOUT
+#endif /* ETIME */
+
+/* structure that holds a buffer
+   the buffer contains the data that is between the application and the
+   file descriptor that is used for efficient transfer
+   the buffer is built up as follows:
+   |.....********......|
+         ^start        ^size
+         ^--len--^           */
+struct tio_buffer {
+  uint8_t *buffer;
+  size_t size;      /* the size of the buffer */
+  size_t maxsize;   /* the maximum size of the buffer */
+  size_t start;     /* the start of the data (before start is unused) */
+  size_t len;       /* size of the data (from the start) */
+};
+
+/* structure that holds all the state for files */
+struct tio_fileinfo {
+  int fd;
+  struct tio_buffer readbuffer;
+  struct tio_buffer writebuffer;
+  struct timeval readtimeout;
+  struct timeval writetimeout;
+  int read_resettable; /* whether the tio_reset() function can be called */
+#ifdef DEBUG_TIO_STATS
+  /* this is used to collect statistics on the use of the streams
+     and can be used to tune the buffer sizes */
+  size_t byteswritten;
+  size_t bytesread;
+#endif /* DEBUG_TIO_STATS */
+};
+
+/* add the second timeval to the first modifing the first */
+static inline void tio_tv_add(struct timeval *tv1, const struct timeval *tv2)
+{
+  /* BUG: we hope that this does not overflow */
+  tv1->tv_usec+=tv2->tv_usec;
+  if (tv1->tv_usec>1000000)
+  {
+    tv1->tv_usec-=1000000;
+    tv1->tv_sec+=1;
+  }
+  tv1->tv_sec+=tv2->tv_sec;
+}
+
+/* build a timeval for comparison to when the operation should be finished */
+static inline void tio_tv_prepare(struct timeval *deadline, const struct timeval *timeout)
+{
+  if (gettimeofday(deadline,NULL))
+  {
+    /* just blank it in case of errors */
+    deadline->tv_sec=0;
+    deadline->tv_usec=0;
+    return;
+  }
+  tio_tv_add(deadline,timeout);
+}
+
+/* update the timeval to the value that is remaining before deadline
+   returns non-zero if there is no more time before the deadline */
+static inline int tio_tv_remaining(struct timeval *tv, const struct timeval *deadline)
+{
+  /* get the current time */
+  if (gettimeofday(tv,NULL))
+  {
+    /* 1 second default if gettimeofday() is broken */
+    tv->tv_sec=1;
+    tv->tv_usec=0;
+    return 0;
+  }
+  /* check if we're too late */
+  if ( (tv->tv_sec>deadline->tv_sec) ||
+       ( (tv->tv_sec==deadline->tv_sec) && (tv->tv_usec>deadline->tv_usec) ) )
+    return -1;
+  /* update tv */
+  tv->tv_sec=deadline->tv_sec-tv->tv_sec;
+  if (tv->tv_usec<deadline->tv_usec)
+    tv->tv_usec=deadline->tv_usec-tv->tv_usec;
+  else
+  {
+    tv->tv_sec--;
+    tv->tv_usec=1000000+deadline->tv_usec-tv->tv_usec;
+  }
+  return 0;
+}
+
+/* open a new TFILE based on the file descriptor */
+TFILE *tio_fdopen(int fd,struct timeval *readtimeout,struct timeval *writetimeout,
+                  size_t initreadsize,size_t maxreadsize,
+                  size_t initwritesize,size_t maxwritesize)
+{
+  struct tio_fileinfo *fp;
+  fp=(struct tio_fileinfo *)malloc(sizeof(struct tio_fileinfo));
+  if (fp==NULL)
+    return NULL;
+  fp->fd=fd;
+  /* initialize read buffer */
+  fp->readbuffer.buffer=(uint8_t *)malloc(initreadsize);
+  if (fp->readbuffer.buffer==NULL)
+  {
+    free(fp);
+    return NULL;
+  }
+  fp->readbuffer.size=initreadsize;
+  fp->readbuffer.maxsize=maxreadsize;
+  fp->readbuffer.start=0;
+  fp->readbuffer.len=0;
+  /* initialize write buffer */
+  fp->writebuffer.buffer=(uint8_t *)malloc(initwritesize);
+  if (fp->writebuffer.buffer==NULL)
+  {
+    free(fp->readbuffer.buffer);
+    free(fp);
+    return NULL;
+  }
+  fp->writebuffer.size=initwritesize;
+  fp->writebuffer.maxsize=maxwritesize;
+  fp->writebuffer.start=0;
+  fp->writebuffer.len=0;
+  /* initialize other attributes */
+  fp->readtimeout.tv_sec=readtimeout->tv_sec;
+  fp->readtimeout.tv_usec=readtimeout->tv_usec;
+  fp->writetimeout.tv_sec=writetimeout->tv_sec;
+  fp->writetimeout.tv_usec=writetimeout->tv_usec;
+  fp->read_resettable=0;
+#ifdef DEBUG_TIO_STATS
+  fp->byteswritten=0;
+  fp->bytesread=0;
+#endif /* DEBUG_TIO_STATS */
+  return fp;
+}
+
+/* wait for any activity on the specified file descriptor using
+   the specified deadline */
+static int tio_select(TFILE *fp, int readfd, const struct timeval *deadline)
+{
+  struct timeval tv;
+  fd_set fdset;
+  int rv;
+  while (1)
+  {
+    /* prepare our filedescriptorset */
+    FD_ZERO(&fdset);
+    FD_SET(fp->fd,&fdset);
+    /* figure out the time we need to wait */
+    if (tio_tv_remaining(&tv,deadline))
+    {
+      errno=ETIME;
+      return -1;
+    }
+    /* wait for activity */
+    if (readfd)
+    {
+      /* santiy check for moving clock */
+      if (tv.tv_sec>fp->readtimeout.tv_sec)
+        tv.tv_sec=fp->readtimeout.tv_sec;
+      rv=select(FD_SETSIZE,&fdset,NULL,NULL,&tv);
+    }
+    else
+    {
+      /* santiy check for moving clock */
+      if (tv.tv_sec>fp->writetimeout.tv_sec)
+        tv.tv_sec=fp->writetimeout.tv_sec;
+      rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
+    }
+    if (rv>0)
+      return 0; /* we have activity */
+    else if (rv==0)
+    {
+      /* no file descriptors were available within the specified time */
+      errno=ETIME;
+      return -1;
+    }
+    else if (errno!=EINTR)
+      /* some error ocurred */
+      return -1;
+    /* we just try again on EINTR */
+  }
+}
+
+/* do a read on the file descriptor, returning the data in the buffer
+   if no data was read in the specified time an error is returned */
+int tio_read(TFILE *fp, void *buf, size_t count)
+{
+  struct timeval deadline;
+  int rv;
+  uint8_t *tmp;
+  size_t newsz;
+  /* have a more convenient storage type for the buffer */
+  uint8_t *ptr=(uint8_t *)buf;
+  /* build a time by which we should be finished */
+  /* TODO: probably only set up deadline if we have to do select() */
+  tio_tv_prepare(&deadline,&(fp->readtimeout));
+  /* loop until we have returned all the needed data */
+  while (1)
+  {
+    /* check if we have enough data in the buffer */
+    if (fp->readbuffer.len >= count)
+    {
+      if (count>0)
+      {
+        if (ptr!=NULL)
+          memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,count);
+        /* adjust buffer position */
+        fp->readbuffer.start+=count;
+        fp->readbuffer.len-=count;
+      }
+      return 0;
+    }
+    /* empty what we have and continue from there */
+    if (fp->readbuffer.len>0)
+    {
+      if (ptr!=NULL)
+      {
+        memcpy(ptr,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
+        ptr+=fp->readbuffer.len;
+      }
+      count-=fp->readbuffer.len;
+      fp->readbuffer.start+=fp->readbuffer.len;
+      fp->readbuffer.len=0;
+    }
+    /* after this point until the read fp->readbuffer.len is 0 */
+    if (!fp->read_resettable)
+    {
+      /* the stream is not resettable, re-use the buffer */
+      fp->readbuffer.start=0;
+    }
+    else if (fp->readbuffer.start>=(fp->readbuffer.size-4))
+    {
+      /* buffer is running empty, try to grow buffer */
+      if (fp->readbuffer.size<fp->readbuffer.maxsize)
+      {
+        newsz=fp->readbuffer.size*2;
+        if (newsz>fp->readbuffer.maxsize)
+          newsz=fp->readbuffer.maxsize;
+        tmp=realloc(fp->readbuffer.buffer,newsz);
+        if (tmp!=NULL)
+        {
+          fp->readbuffer.buffer=tmp;
+          fp->readbuffer.size=newsz;
+        }
+      }
+      /* if buffer still does not contain enough room, clear resettable */
+      if (fp->readbuffer.start>=(fp->readbuffer.size-4))
+      {
+        fp->readbuffer.start=0;
+        fp->read_resettable=0;
+      }
+    }
+    /* wait until we have input */
+    if (tio_select(fp,1,&deadline))
+      return -1;
+    /* read the input in the buffer */
+    rv=read(fp->fd,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.size-fp->readbuffer.start);
+    /* check for errors */
+    if ((rv==0)||((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN)))
+      return -1; /* something went wrong with the read */
+    /* skip the read part in the buffer */
+    fp->readbuffer.len=rv;
+#ifdef DEBUG_TIO_STATS
+    fp->bytesread+=rv;
+#endif /* DEBUG_TIO_STATS */
+  }
+}
+
+/* Read and discard the specified number of bytes from the stream. */
+int tio_skip(TFILE *fp, size_t count)
+{
+  return tio_read(fp,NULL,count);
+}
+
+/* the caller has assured us that we can write to the file descriptor
+   and we give it a shot */
+static int tio_writebuf(TFILE *fp)
+{
+  int rv;
+  /* write the buffer */
+#ifdef MSG_NOSIGNAL
+  rv=send(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len,MSG_NOSIGNAL);
+#else /* not MSG_NOSIGNAL */
+  /* on platforms that cannot use send() with masked signals, we change the
+     signal mask and change it back after the write (note that there is a
+     race condition here) */
+  struct sigaction act,oldact;
+  /* set up sigaction */
+  memset(&act,0,sizeof(struct sigaction));
+  act.sa_sigaction=NULL;
+  act.sa_handler=SIG_IGN;
+  sigemptyset(&act.sa_mask);
+  act.sa_flags=SA_RESTART;
+  /* ignore SIGPIPE */
+  if (sigaction(SIGPIPE,&act,&oldact)!=0)
+    return -1; /* error setting signal handler */
+  /* write the buffer */
+  rv=write(fp->fd,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
+  /* restore the old handler for SIGPIPE */
+  if (sigaction(SIGPIPE,&oldact,NULL)!=0)
+    return -1; /* error restoring signal handler */
+#endif
+  /* check for errors */
+  if ((rv==0)||((rv<0)&&(errno!=EINTR)&&(errno!=EAGAIN)))
+    return -1; /* something went wrong with the write */
+  /* skip the written part in the buffer */
+  if (rv>0)
+  {
+    fp->writebuffer.start+=rv;
+    fp->writebuffer.len-=rv;
+#ifdef DEBUG_TIO_STATS
+    fp->byteswritten+=rv;
+#endif /* DEBUG_TIO_STATS */
+    /* reset start if len is 0 */
+    if (fp->writebuffer.len==0)
+      fp->writebuffer.start=0;
+    /* move contents of the buffer to the front if it will save enough room */
+    if (fp->writebuffer.start>=(fp->writebuffer.size/4))
+    {
+      memmove(fp->writebuffer.buffer,fp->writebuffer.buffer+fp->writebuffer.start,fp->writebuffer.len);
+      fp->writebuffer.start=0;
+    }
+  }
+  return 0;
+}
+
+/* write all the data in the buffer to the stream */
+int tio_flush(TFILE *fp)
+{
+  struct timeval deadline;
+  /* build a time by which we should be finished */
+  tio_tv_prepare(&deadline,&(fp->writetimeout));
+  /* loop until we have written our buffer */
+  while (fp->writebuffer.len > 0)
+  {
+    /* wait until we can write */
+    if (tio_select(fp,0,&deadline))
+      return -1;
+    /* write one block */
+    if (tio_writebuf(fp))
+      return -1;
+  }
+  return 0;
+}
+
+/* try a single write of data in the buffer if the file descriptor
+   will accept data */
+static int tio_flush_nonblock(TFILE *fp)
+{
+  struct timeval tv;
+  fd_set fdset;
+  int rv;
+  /* prepare our filedescriptorset */
+  FD_ZERO(&fdset);
+  FD_SET(fp->fd,&fdset);
+  /* set the timeout to 0 to poll */
+  tv.tv_sec=0;
+  tv.tv_usec=0;
+  /* wait for activity */
+  rv=select(FD_SETSIZE,NULL,&fdset,NULL,&tv);
+  /* check if any file descriptors were ready (timeout) or we were
+     interrupted */
+  if ((rv==0)||((rv<0)&&(errno==EINTR)))
+    return 0;
+  /* any other errors? */
+  if (rv<0)
+    return -1;
+  /* so file descriptor will accept writes */
+  return tio_writebuf(fp);
+}
+
+int tio_write(TFILE *fp, const void *buf, size_t count)
+{
+  size_t fr;
+  uint8_t *tmp;
+  size_t newsz;
+  const uint8_t *ptr=(const uint8_t *)buf;
+  /* keep filling the buffer until we have bufferred everything */
+  while (count>0)
+  {
+    /* figure out free size in buffer */
+    fr=fp->writebuffer.size-(fp->writebuffer.start+fp->writebuffer.len);
+    if (count <= fr)
+    {
+      /* the data fits in the buffer */
+      memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,count);
+      fp->writebuffer.len+=count;
+      return 0;
+    }
+    else if (fr > 0)
+    {
+      /* fill the buffer with data that will fit */
+      memcpy(fp->writebuffer.buffer+fp->writebuffer.start+fp->writebuffer.len,ptr,fr);
+      fp->writebuffer.len+=fr;
+      ptr+=fr;
+      count-=fr;
+    }
+    /* try to flush some of the data that is in the buffer */
+    if (tio_flush_nonblock(fp))
+      return -1;
+    /* if we have room now, try again */
+    if (fp->writebuffer.size>(fp->writebuffer.start+fp->writebuffer.len))
+      continue;
+    /* try to grow the buffer */
+    if (fp->writebuffer.size<fp->writebuffer.maxsize)
+    {
+      newsz=fp->writebuffer.size*2;
+      if (newsz>fp->writebuffer.maxsize)
+        newsz=fp->writebuffer.maxsize;
+      tmp=realloc(fp->writebuffer.buffer,newsz);
+      if (tmp!=NULL)
+      {
+        fp->writebuffer.buffer=tmp;
+        fp->writebuffer.size=newsz;
+        continue; /* try again */
+      }
+    }
+    /* write the buffer to the stream */
+    if (tio_flush(fp))
+      return -1;
+  }
+  return 0;
+}
+
+int tio_close(TFILE *fp)
+{
+  int retv;
+  /* write any buffered data */
+  retv=tio_flush(fp);
+#ifdef DEBUG_TIO_STATS
+  /* dump statistics to stderr */
+  fprintf(stderr,"DEBUG_TIO_STATS READ=%d WRITTEN=%d\n",fp->bytesread,fp->byteswritten);
+#endif /* DEBUG_TIO_STATS */
+  /* close file descriptor */
+  if (close(fp->fd))
+    retv=-1;
+  /* free any allocated buffers */
+  free(fp->readbuffer.buffer);
+  free(fp->writebuffer.buffer);
+  /* free the tio struct itself */
+  free(fp);
+  /* return the result of the earlier operations */
+  return retv;
+}
+
+void tio_mark(TFILE *fp)
+{
+  /* move any data in the buffer to the start of the buffer */
+  if ((fp->readbuffer.start>0)&&(fp->readbuffer.len>0))
+  {
+    memmove(fp->readbuffer.buffer,fp->readbuffer.buffer+fp->readbuffer.start,fp->readbuffer.len);
+    fp->readbuffer.start=0;
+  }
+  /* mark the stream as resettable */
+  fp->read_resettable=1;
+}
+
+int tio_reset(TFILE *fp)
+{
+  /* check if the stream is (still) resettable */
+  if (!fp->read_resettable)
+    return -1;
+  /* reset the buffer */
+  fp->readbuffer.len+=fp->readbuffer.start;
+  fp->readbuffer.start=0;
+  return 0;
+}
diff -Naur nssov.orig/nss-pam-ldapd/tio.h nssov/nss-pam-ldapd/tio.h
--- nssov.orig/nss-pam-ldapd/tio.h	1969-12-31 18:00:00.000000000 -0600
+++ nssov/nss-pam-ldapd/tio.h	2010-03-06 20:49:12.992644125 -0600
@@ -0,0 +1,81 @@
+/*
+   tio.h - timed io functions
+   This file is part of the nss-pam-ldapd library.
+
+   Copyright (C) 2007, 2008 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
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301 USA
+*/
+
+/*
+
+   TODO: Add some documentation here.
+
+   the SIGPIPE signal should be ignored (is ignored in this code)
+
+   This library is not thread safe. You cannot share TFILE objects between
+   threads and expect to be able to read and write from them in different
+   threads. All the state is in the TFILE object so calls to this library on
+   different objects can be done in parallel.
+
+*/
+
+#ifndef _TIO_H
+#define _TIO_H
+
+#include <sys/time.h>
+#include <sys/types.h>
+
+#include "attrs.h"
+
+/* This is a generic file handle used for reading and writing
+   (something like FILE from stdio.h). */
+typedef struct tio_fileinfo TFILE;
+
+/* Open a new TFILE based on the file descriptor. The timeout is set for any
+   operation. The timeout value is copied so may be dereferenced after the
+   call. */
+TFILE *tio_fdopen(int fd,struct timeval *readtimeout,struct timeval *writetimeout,
+                  size_t initreadsize,size_t maxreadsize,
+                  size_t initwritesize,size_t maxwritesize)
+  LIKE_MALLOC MUST_USE;
+
+/* Read the specified number of bytes from the stream. */
+int tio_read(TFILE *fp,void *buf,size_t count);
+
+/* Read and discard the specified number of bytes from the stream. */
+int tio_skip(TFILE *fp,size_t count);
+
+/* Write the specified buffer to the stream. */
+int tio_write(TFILE *fp,const void *buf,size_t count);
+
+/* Write out all buffered data to the stream. */
+int tio_flush(TFILE *fp);
+
+/* Flush the streams and closes the underlying file descriptor. */
+int tio_close(TFILE *fp);
+
+/* Store the current position in the stream so that we can jump back to it
+   with the tio_reset() function. */
+void tio_mark(TFILE *fp);
+
+/* Rewinds the stream to the point set by tio_mark(). Note that this only
+   resets the read stream and not the write stream. This function returns
+   whether the reset was successful (this function may fail if the buffers
+   were full). */
+int tio_reset(TFILE *fp);
+
+#endif /* _TIO_H */
diff -Naur nssov.orig/pam.c nssov/pam.c
--- nssov.orig/pam.c	2010-03-03 12:30:58.000000000 -0600
+++ nssov/pam.c	2010-03-06 20:49:07.360143972 -0600
@@ -215,16 +215,16 @@
 	struct paminfo pi;
 
 
-	READ_STRING_BUF2(fp,uidc,sizeof(uidc));
+	READ_STRING(fp,uidc);
 	pi.uid.bv_val = uidc;
 	pi.uid.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,dnc,sizeof(dnc));
+	READ_STRING(fp,dnc);
 	pi.dn.bv_val = dnc;
 	pi.dn.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,svcc,sizeof(svcc));
+	READ_STRING(fp,svcc);
 	pi.svc.bv_val = svcc;
 	pi.svc.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,pwdc,sizeof(pwdc));
+	READ_STRING(fp,pwdc);
 	pi.pwd.bv_val = pwdc;
 	pi.pwd.bv_len = tmpint32;
 
@@ -235,7 +235,7 @@
 finish:
 	WRITE_INT32(fp,NSLCD_VERSION);
 	WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
-	WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(fp,&pi.uid);
 	WRITE_BERVAL(fp,&pi.dn);
 	WRITE_INT32(fp,rc);
@@ -277,22 +277,22 @@
 	SlapReply rs = {REP_RESULT};
 	slap_callback cb = {0};
 
-	READ_STRING_BUF2(fp,uidc,sizeof(uidc));
+	READ_STRING(fp,uidc);
 	uid.bv_val = uidc;
 	uid.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,dnc,sizeof(dnc));
+	READ_STRING(fp,dnc);
 	dn.bv_val = dnc;
 	dn.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,svcc,sizeof(svcc));
+	READ_STRING(fp,svcc);
 	svc.bv_val = svcc;
 	svc.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,ruserc,sizeof(ruserc));
+	READ_STRING(fp,ruserc);
 	ruser.bv_val = ruserc;
 	ruser.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,rhostc,sizeof(rhostc));
+	READ_STRING(fp,rhostc);
 	rhost.bv_val = rhostc;
 	rhost.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,ttyc,sizeof(ttyc));
+	READ_STRING(fp,ttyc);
 	tty.bv_val = ttyc;
 	tty.bv_len = tmpint32;
 
@@ -470,7 +470,7 @@
 finish:
 	WRITE_INT32(fp,NSLCD_VERSION);
 	WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
-	WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(fp,&uid);
 	WRITE_BERVAL(fp,&dn);
 	WRITE_INT32(fp,rc);
@@ -498,22 +498,22 @@
 	time_t stamp;
 	Modifications mod;
 
-	READ_STRING_BUF2(fp,uidc,sizeof(uidc));
+	READ_STRING(fp,uidc);
 	uid.bv_val = uidc;
 	uid.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,dnc,sizeof(dnc));
+	READ_STRING(fp,dnc);
 	dn.bv_val = dnc;
 	dn.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,svcc,sizeof(svcc));
+	READ_STRING(fp,svcc);
 	svc.bv_val = svcc;
 	svc.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,ttyc,sizeof(ttyc));
+	READ_STRING(fp,ttyc);
 	tty.bv_val = ttyc;
 	tty.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,rhostc,sizeof(rhostc));
+	READ_STRING(fp,rhostc);
 	rhost.bv_val = rhostc;
 	rhost.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,ruserc,sizeof(ruserc));
+	READ_STRING(fp,ruserc);
 	ruser.bv_val = ruserc;
 	ruser.bv_len = tmpint32;
 	READ_INT32(fp,stamp);
@@ -577,7 +577,7 @@
 
 	WRITE_INT32(fp,NSLCD_VERSION);
 	WRITE_INT32(fp,action);
-	WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
 	WRITE_INT32(fp,op->o_time);
 	return 0;
 }
@@ -604,19 +604,19 @@
 	struct paminfo pi;
 	int rc;
 
-	READ_STRING_BUF2(fp,uidc,sizeof(uidc));
+	READ_STRING(fp,uidc);
 	pi.uid.bv_val = uidc;
 	pi.uid.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,dnc,sizeof(dnc));
+	READ_STRING(fp,dnc);
 	pi.dn.bv_val = dnc;
 	pi.dn.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,svcc,sizeof(svcc));
+	READ_STRING(fp,svcc);
 	pi.svc.bv_val = svcc;
 	pi.svc.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,opwc,sizeof(opwc));
+	READ_STRING(fp,opwc);
 	pi.pwd.bv_val = opwc;
 	pi.pwd.bv_len = tmpint32;
-	READ_STRING_BUF2(fp,npwc,sizeof(npwc));
+	READ_STRING(fp,npwc);
 	npw.bv_val = npwc;
 	npw.bv_len = tmpint32;
 
@@ -666,7 +666,7 @@
 	}
 	WRITE_INT32(fp,NSLCD_VERSION);
 	WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
-	WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(fp,&pi.uid);
 	WRITE_BERVAL(fp,&pi.dn);
 	WRITE_INT32(fp,rc);
diff -Naur nssov.orig/passwd.c nssov/passwd.c
--- nssov.orig/passwd.c	2009-08-16 15:55:26.000000000 -0500
+++ nssov/passwd.c	2010-03-06 20:49:08.976950711 -0600
@@ -375,7 +375,7 @@
 						names[i].bv_val);
 					continue;
 				}
-				WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+				WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 				WRITE_BERVAL(cbp->fp,&names[i]);
 				WRITE_BERVAL(cbp->fp,&passwd);
 				WRITE_TYPE(cbp->fp,uid,uid_t);
@@ -396,7 +396,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;
 	if (!isvalidusername(&cbp.name)) {
diff -Naur nssov.orig/protocol.c nssov/protocol.c
--- nssov.orig/protocol.c	2009-08-21 17:33:26.000000000 -0500
+++ nssov/protocol.c	2010-03-06 20:49:11.340143945 -0600
@@ -100,7 +100,7 @@
 		return 0;
 	}
 	/* write the entry */
-	WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(cbp->fp,&name);
 	if ( dupname >= 0 ) {
 		WRITE_INT32(cbp->fp,numname-1);
@@ -123,7 +123,7 @@
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
 	BER_BVZERO(&cbp.numb);
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+	READ_STRING(fp,cbp.buf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_protocol_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/README nssov/README
--- nssov.orig/README	2009-08-16 15:55:25.000000000 -0500
+++ nssov/README	2010-03-06 20:49:09.983418362 -0600
@@ -4,12 +4,15 @@
 copy of the nss-ldapd source is included here. It also handles
 PAM requests.
 
-To use this code, you will need the client-side stub library from
-nss-ldapd (which resides in nss-ldapd/nss). You will not need the
-nslcd daemon; this overlay replaces that part. You should already
-be familiar with the RFC2307 and RFC2307bis schema to use this
-overlay. See the nss-ldapd/README for more information on the
-schema and which features are supported.
+To use this code, you will need the client-side stuf library from
+nss-pam-ldapd.  You can get it from:
+http://arthurdejong.org/nss-pam-ldapd
+You will not need the nslcd daemon; this overlay replaces that part.
+To disable building of the nslcd daemon in nss-pam-ldapd, add the
+--disable-nslcd option to the nss-pam-ldapd configure script. You
+should already be familiar with the RFC2307 and RFC2307bis schema
+to use this overlay.  See the nss-pam-ldapd README for more information
+on the schema and which features are supported.
 
 To use the overlay, add:
 
diff -Naur nssov.orig/rpc.c nssov/rpc.c
--- nssov.orig/rpc.c	2009-08-21 17:33:26.000000000 -0500
+++ nssov/rpc.c	2010-03-06 20:49:10.480362806 -0600
@@ -102,7 +102,7 @@
 		return 0;
 	}
 	/* write the entry */
-	WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+	WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 	WRITE_BERVAL(cbp->fp,&name);
 	if ( dupname >= 0 ) {
 		WRITE_INT32(cbp->fp,numname-1);
@@ -125,7 +125,7 @@
     struct berval filter = {sizeof(fbuf)};
     filter.bv_val = fbuf;
     BER_BVZERO(&cbp.numb);
-    READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));
+    READ_STRING(fp,cbp.buf);
     cbp.name.bv_len = tmpint32;
     cbp.name.bv_val = cbp.buf;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_rpc_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/service.c nssov/service.c
--- nssov.orig/service.c	2009-08-21 17:33:26.000000000 -0500
+++ nssov/service.c	2010-03-06 20:49:11.080144699 -0600
@@ -187,7 +187,7 @@
 	for (i=0;i<numprot;i++)
 	{
 		int j;
-		WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+		WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 		WRITE_BERVAL(cbp->fp,&name);
 		if ( dupname >= 0 ) {
 			WRITE_INT32(cbp->fp,numname-1);
@@ -211,10 +211,10 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.nbuf,sizeof(cbp.nbuf));
+	READ_STRING(fp,cbp.nbuf);
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.nbuf;
-	READ_STRING_BUF2(fp,cbp.pbuf,sizeof(cbp.pbuf));
+	READ_STRING(fp,cbp.pbuf);
 	cbp.prot.bv_len = tmpint32;
 	cbp.prot.bv_val = tmpint32 ? cbp.pbuf : NULL;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_service_byname(%s,%s)\n",cbp.name.bv_val,cbp.prot.bv_val,0);,
@@ -231,7 +231,7 @@
 	READ_INT32(fp,number);
 	cbp.name.bv_val = cbp.nbuf;
 	cbp.name.bv_len = snprintf(cbp.nbuf,sizeof(cbp.nbuf),"%d",number);
-	READ_STRING_BUF2(fp,cbp.pbuf,sizeof(cbp.pbuf));
+	READ_STRING(fp,cbp.pbuf);
 	cbp.prot.bv_len = tmpint32;
 	cbp.prot.bv_val = tmpint32 ? cbp.pbuf : NULL;,
 	Debug(LDAP_DEBUG_TRACE,"nssov_service_bynumber(%s,%s)\n",cbp.name.bv_val,cbp.prot.bv_val,0);,
diff -Naur nssov.orig/shadow.c nssov/shadow.c
--- nssov.orig/shadow.c	2009-08-16 15:55:26.000000000 -0500
+++ nssov/shadow.c	2010-03-06 20:49:09.311494842 -0600
@@ -217,7 +217,7 @@
 	/* write the entries */
 	for (i=0;!BER_BVISNULL(&names[i]);i++)
 	{
-		WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
+		WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
 		WRITE_BERVAL(cbp->fp,&names[i]);
 		WRITE_BERVAL(cbp->fp,&passwd);
 		WRITE_INT32(cbp->fp,lastchangedate);
@@ -238,7 +238,7 @@
 	char fbuf[1024];
 	struct berval filter = {sizeof(fbuf)};
 	filter.bv_val = fbuf;
-	READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));,
+	READ_STRING(fp,cbp.buf);,
 	cbp.name.bv_len = tmpint32;
 	cbp.name.bv_val = cbp.buf;
 	Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)\n",cbp.name.bv_val,0,0);,
diff -Naur nssov.orig/slapo-nssov.5 nssov/slapo-nssov.5
--- nssov.orig/slapo-nssov.5	2009-06-04 05:26:29.000000000 -0500
+++ nssov/slapo-nssov.5	2010-03-06 20:49:15.142376834 -0600
@@ -21,7 +21,7 @@
 all suffer from. Both the original nss-ldapd and this nssov solution
 are free from these library issues.
 .LP
-Unlike nss-ldapd, since this overlay executes inside slapd it allows for
+Unlike nss-pam-ldapd, since this overlay executes inside slapd it allows for
 the possibility of sophisticated caching, without any of the weaknesses of
 nscd and other related caching solutions. E.g., a remote LDAP database can
 be accessed using back-ldap with proxy caching (see
@@ -48,13 +48,15 @@
 leverages the slapd ACL engine, which offers much more power and flexibility 
 than the simple group/hostname checks in the old pam_ldap code.
 .LP
-To use this code, you will need the client-side stub library from
-nss-ldapd (which resides in nss-ldapd/nss). You will not need the
-nslcd daemon; this overlay replaces that part. You should already
-be familiar with the [RFC2307] and [RFC2307bis] schema to use this
-overlay. See the 
-.B nss-ldapd/README 
-for more information on the schema and which features are supported.
+To use this code, you will need the client-side stuf library from
+nss-pam-ldapd.  You can get it from:
+http://arthurdejong.org/nss-pam-ldapd
+You will not need the nslcd daemon; this overlay replaces that part.
+To disable building of the nslcd daemon in nss-pam-ldapd, add the
+--disable-nslcd option to the nss-pam-ldapd configure script. You
+should already be familiar with the RFC2307 and RFC2307bis schema
+to use this overlay.  See the nss-pam-ldapd README for more information
+on the schema and which features are supported.
 .LP
 You will also need to include the nis.schema in your slapd configuration
 for RFC2307 support. If you wish to use RFC2307bis you will need a slightly
