diff options
Diffstat (limited to 'nss/nss_test1.c')
-rw-r--r-- | nss/nss_test1.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/nss/nss_test1.c b/nss/nss_test1.c new file mode 100644 index 0000000000..3beb488fcf --- /dev/null +++ b/nss/nss_test1.c @@ -0,0 +1,154 @@ +#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; +} |