| #include <errno.h> | 
 | #include <nss.h> | 
 | #include <pthread.h> | 
 | #include <string.h> | 
 |  | 
 |  | 
 | #define COPY_IF_ROOM(s) \ | 
 |   ({ size_t len_ = strlen (s) + 1;		\ | 
 |      char *start_ = cp;				\ | 
 |      buflen - (cp - buffer) < len_		\ | 
 |      ? NULL					\ | 
 |      : (cp = mempcpy (cp, s, len_), start_); }) | 
 |  | 
 |  | 
 | /* Password handling.  */ | 
 | #include <pwd.h> | 
 |  | 
 | static struct passwd pwd_data[] = | 
 |   { | 
 | #define PWD(u) \ | 
 |     { .pw_name = (char *) "name" #u, .pw_passwd = (char *) "*", .pw_uid = u,  \ | 
 |       .pw_gid = 100, .pw_gecos = (char *) "*", .pw_dir = (char *) "*",	      \ | 
 |       .pw_shell = (char *) "*" } | 
 |     PWD (100), | 
 |     PWD (30), | 
 |     PWD (200), | 
 |     PWD (60), | 
 |     PWD (20000) | 
 |   }; | 
 | #define npwd_data (sizeof (pwd_data) / sizeof (pwd_data[0])) | 
 |  | 
 | static size_t pwd_iter; | 
 | #define CURPWD pwd_data[pwd_iter] | 
 |  | 
 | static pthread_mutex_t pwd_lock = PTHREAD_MUTEX_INITIALIZER; | 
 |  | 
 |  | 
 | enum nss_status | 
 | _nss_test1_setpwent (int stayopen) | 
 | { | 
 |   pwd_iter = 0; | 
 |   return NSS_STATUS_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | enum nss_status | 
 | _nss_test1_endpwent (void) | 
 | { | 
 |   return NSS_STATUS_SUCCESS; | 
 | } | 
 |  | 
 |  | 
 | enum nss_status | 
 | _nss_test1_getpwent_r (struct passwd *result, char *buffer, size_t buflen, | 
 | 		       int *errnop) | 
 | { | 
 |   char *cp = buffer; | 
 |   int res = NSS_STATUS_SUCCESS; | 
 |  | 
 |   pthread_mutex_lock (&pwd_lock); | 
 |  | 
 |   if (pwd_iter >= npwd_data) | 
 |     res = NSS_STATUS_NOTFOUND; | 
 |   else | 
 |     { | 
 |       result->pw_name = COPY_IF_ROOM (CURPWD.pw_name); | 
 |       result->pw_passwd = COPY_IF_ROOM (CURPWD.pw_passwd); | 
 |       result->pw_uid = CURPWD.pw_uid; | 
 |       result->pw_gid = CURPWD.pw_gid; | 
 |       result->pw_gecos = COPY_IF_ROOM (CURPWD.pw_gecos); | 
 |       result->pw_dir = COPY_IF_ROOM (CURPWD.pw_dir); | 
 |       result->pw_shell = COPY_IF_ROOM (CURPWD.pw_shell); | 
 |  | 
 |       if (result->pw_name == NULL || result->pw_passwd == NULL | 
 | 	  || result->pw_gecos == NULL || result->pw_dir == NULL | 
 | 	  || result->pw_shell == NULL) | 
 | 	{ | 
 | 	  *errnop = ERANGE; | 
 | 	  res = NSS_STATUS_TRYAGAIN; | 
 | 	} | 
 |  | 
 |       ++pwd_iter; | 
 |     } | 
 |  | 
 |   pthread_mutex_unlock (&pwd_lock); | 
 |  | 
 |   return res; | 
 | } | 
 |  | 
 |  | 
 | enum nss_status | 
 | _nss_test1_getpwuid_r (uid_t uid, struct passwd *result, char *buffer, | 
 | 		       size_t buflen, int *errnop) | 
 | { | 
 |   for (size_t idx = 0; idx < npwd_data; ++idx) | 
 |     if (pwd_data[idx].pw_uid == uid) | 
 |       { | 
 | 	char *cp = buffer; | 
 | 	int res = NSS_STATUS_SUCCESS; | 
 |  | 
 | 	result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); | 
 | 	result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); | 
 | 	result->pw_uid = pwd_data[idx].pw_uid; | 
 | 	result->pw_gid = pwd_data[idx].pw_gid; | 
 | 	result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); | 
 | 	result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); | 
 | 	result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); | 
 |  | 
 | 	if (result->pw_name == NULL || result->pw_passwd == NULL | 
 | 	    || result->pw_gecos == NULL || result->pw_dir == NULL | 
 | 	    || result->pw_shell == NULL) | 
 | 	  { | 
 | 	    *errnop = ERANGE; | 
 | 	    res = NSS_STATUS_TRYAGAIN; | 
 | 	  } | 
 |  | 
 | 	return res; | 
 |       } | 
 |  | 
 |   return NSS_STATUS_NOTFOUND; | 
 | } | 
 |  | 
 |  | 
 | enum nss_status | 
 | _nss_test1_getpwnam_r (const char *name, struct passwd *result, char *buffer, | 
 | 		       size_t buflen, int *errnop) | 
 | { | 
 |   for (size_t idx = 0; idx < npwd_data; ++idx) | 
 |     if (strcmp (pwd_data[idx].pw_name, name) == 0) | 
 |       { | 
 | 	char *cp = buffer; | 
 | 	int res = NSS_STATUS_SUCCESS; | 
 |  | 
 | 	result->pw_name = COPY_IF_ROOM (pwd_data[idx].pw_name); | 
 | 	result->pw_passwd = COPY_IF_ROOM (pwd_data[idx].pw_passwd); | 
 | 	result->pw_uid = pwd_data[idx].pw_uid; | 
 | 	result->pw_gid = pwd_data[idx].pw_gid; | 
 | 	result->pw_gecos = COPY_IF_ROOM (pwd_data[idx].pw_gecos); | 
 | 	result->pw_dir = COPY_IF_ROOM (pwd_data[idx].pw_dir); | 
 | 	result->pw_shell = COPY_IF_ROOM (pwd_data[idx].pw_shell); | 
 |  | 
 | 	if (result->pw_name == NULL || result->pw_passwd == NULL | 
 | 	    || result->pw_gecos == NULL || result->pw_dir == NULL | 
 | 	    || result->pw_shell == NULL) | 
 | 	  { | 
 | 	    *errnop = ERANGE; | 
 | 	    res = NSS_STATUS_TRYAGAIN; | 
 | 	  } | 
 |  | 
 | 	return res; | 
 |       } | 
 |  | 
 |   return NSS_STATUS_NOTFOUND; | 
 | } |