* nis/nss_nisplus/nisplus-pwd.c (_nss_pwd_create_tablename):
[glibc.git] / nis / nss_nisplus / nisplus-pwd.c
bloba1c53f74a6e6f8749bb1521b55c57e18eb662c81
1 /* Copyright (C) 1997,1999,2001,2002,2003,2005 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
5 The GNU C Library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the License, or (at your option) any later version.
10 The GNU C Library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 02111-1307 USA. */
20 #include <atomic.h>
21 #include <nss.h>
22 #include <errno.h>
23 #include <pwd.h>
24 #include <string.h>
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/nis.h>
28 #include "nss-nisplus.h"
29 #include "nisplus-parser.h"
31 __libc_lock_define_initialized (static, lock)
33 static nis_result *result;
34 nis_name pwd_tablename_val attribute_hidden;
35 size_t pwd_tablename_len attribute_hidden;
37 enum nss_status
38 _nss_pwd_create_tablename (int *errnop)
40 if (pwd_tablename_val == NULL)
42 const char *local_dir = nis_local_directory ();
43 size_t local_dir_len = strlen (local_dir);
44 static const char prefix[] = "passwd.org_dir.";
46 char *p = malloc (sizeof (prefix) + local_dir_len);
47 if (pwd_tablename_val == NULL)
49 *errnop = errno;
50 return NSS_STATUS_TRYAGAIN;
53 memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
55 pwd_tablename_len = sizeof (prefix) - 1 + local_dir_len;
57 atomic_write_barrier ();
59 pwd_tablename_val = p;
62 return NSS_STATUS_SUCCESS;
66 enum nss_status
67 _nss_nisplus_setpwent (int stayopen)
69 enum nss_status status = NSS_STATUS_SUCCESS;
71 __libc_lock_lock (lock);
73 if (result != NULL)
75 nis_freeresult (result);
76 result = NULL;
79 if (pwd_tablename_val == NULL)
81 int err;
82 status = _nss_pwd_create_tablename (&err);
85 __libc_lock_unlock (lock);
87 return status;
90 enum nss_status
91 _nss_nisplus_endpwent (void)
93 __libc_lock_lock (lock);
95 if (result != NULL)
97 nis_freeresult (result);
98 result = NULL;
101 __libc_lock_unlock (lock);
103 return NSS_STATUS_SUCCESS;
106 static enum nss_status
107 internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen,
108 int *errnop)
110 int parse_res;
112 /* Get the next entry until we found a correct one. */
115 nis_result *saved_res;
117 if (result == NULL)
119 saved_res = NULL;
120 if (pwd_tablename_val == NULL)
122 enum nss_status status = _nss_pwd_create_tablename (errnop);
124 if (status != NSS_STATUS_SUCCESS)
125 return status;
128 result = nis_first_entry (pwd_tablename_val);
129 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
130 return niserr2nss (result->status);
132 else
134 saved_res = result;
135 result = nis_next_entry (pwd_tablename_val, &result->cookie);
136 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
138 nis_freeresult (saved_res);
139 return niserr2nss (result->status);
143 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer,
144 buflen, errnop);
145 if (__builtin_expect (parse_res == -1, 0))
147 nis_freeresult (result);
148 result = saved_res;
149 *errnop = ERANGE;
150 return NSS_STATUS_TRYAGAIN;
153 if (saved_res)
154 nis_freeresult (saved_res);
156 while (!parse_res);
158 return NSS_STATUS_SUCCESS;
161 enum nss_status
162 _nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
163 int *errnop)
165 int status;
167 __libc_lock_lock (lock);
169 status = internal_nisplus_getpwent_r (result, buffer, buflen, errnop);
171 __libc_lock_unlock (lock);
173 return status;
176 enum nss_status
177 _nss_nisplus_getpwnam_r (const char *name, struct passwd *pw,
178 char *buffer, size_t buflen, int *errnop)
180 int parse_res;
182 if (pwd_tablename_val == NULL)
184 __libc_lock_lock (lock);
186 enum nss_status status = _nss_pwd_create_tablename (errnop);
188 __libc_lock_unlock (lock);
190 if (status != NSS_STATUS_SUCCESS)
191 return status;
194 if (name == NULL)
196 *errnop = EINVAL;
197 return NSS_STATUS_UNAVAIL;
200 nis_result *result;
201 char buf[strlen (name) + 9 + pwd_tablename_len];
202 int olderr = errno;
204 snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
206 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
208 if (result == NULL)
210 *errnop = ENOMEM;
211 return NSS_STATUS_TRYAGAIN;
214 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
216 enum nss_status status = niserr2nss (result->status);
218 __set_errno (olderr);
220 nis_freeresult (result);
221 return status;
224 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
226 nis_freeresult (result);
228 if (__builtin_expect (parse_res < 1, 0))
230 if (parse_res == -1)
232 *errnop = ERANGE;
233 return NSS_STATUS_TRYAGAIN;
235 else
237 __set_errno (olderr);
238 return NSS_STATUS_NOTFOUND;
242 return NSS_STATUS_SUCCESS;
245 enum nss_status
246 _nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
247 char *buffer, size_t buflen, int *errnop)
249 if (pwd_tablename_val == NULL)
251 __libc_lock_lock (lock);
253 enum nss_status status = _nss_pwd_create_tablename (errnop);
255 __libc_lock_unlock (lock);
257 if (status != NSS_STATUS_SUCCESS)
258 return status;
261 int parse_res;
262 nis_result *result;
263 char buf[8 + 3 * sizeof (unsigned long int) + pwd_tablename_len];
264 int olderr = errno;
266 snprintf (buf, sizeof (buf), "[uid=%lu],%s",
267 (unsigned long int) uid, pwd_tablename_val);
269 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
271 if (result == NULL)
273 *errnop = ENOMEM;
274 return NSS_STATUS_TRYAGAIN;
277 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
279 enum nss_status status = niserr2nss (result->status);
281 __set_errno (olderr);
283 nis_freeresult (result);
284 return status;
287 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
289 nis_freeresult (result);
291 if (__builtin_expect (parse_res < 1, 0))
293 if (parse_res == -1)
295 *errnop = ERANGE;
296 return NSS_STATUS_TRYAGAIN;
298 else
300 __set_errno (olderr);
301 return NSS_STATUS_NOTFOUND;
305 return NSS_STATUS_SUCCESS;