]> git.ipfire.org Git - thirdparty/glibc.git/blame - nis/nss_nisplus/nisplus-pwd.c
* sysdeps/unix/sysv/linux/sparc/bits/poll.h: Add POLLMSG,
[thirdparty/glibc.git] / nis / nss_nisplus / nisplus-pwd.c
CommitLineData
48b29391 1/* Copyright (C) 1997,1999,2001,2002,2003,2005 Free Software Foundation, Inc.
e61abf83
UD
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997.
4
5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
e61abf83
UD
9
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
41bdb6e2 13 Lesser General Public License for more details.
e61abf83 14
41bdb6e2
AJ
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. */
e61abf83 19
48b29391 20#include <atomic.h>
e61abf83
UD
21#include <nss.h>
22#include <errno.h>
23#include <pwd.h>
24#include <string.h>
5107cf1d 25#include <bits/libc-lock.h>
e61abf83 26#include <rpcsvc/nis.h>
e61abf83
UD
27
28#include "nss-nisplus.h"
7d1de115 29#include "nisplus-parser.h"
e61abf83
UD
30
31__libc_lock_define_initialized (static, lock)
32
a334319f 33static nis_result *result;
48b29391
UD
34nis_name pwd_tablename_val attribute_hidden;
35size_t pwd_tablename_len attribute_hidden;
0ecb606c 36
48b29391
UD
37enum nss_status
38_nss_pwd_create_tablename (int *errnop)
e61abf83 39{
48b29391 40 if (pwd_tablename_val == NULL)
e61abf83 41 {
48b29391
UD
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.";
2d7da676 45
48b29391
UD
46 char *p = malloc (sizeof (prefix) + local_dir_len);
47 if (pwd_tablename_val == NULL)
d71b808a
UD
48 {
49 *errnop = errno;
50 return NSS_STATUS_TRYAGAIN;
51 }
48b29391
UD
52
53 memcpy (__stpcpy (p, prefix), local_dir, local_dir_len + 1);
54
55 pwd_tablename_len = sizeof (prefix) - 1 + local_dir_len;
56
57 atomic_write_barrier ();
58
8e64faef
UD
59 if (atomic_compare_and_exchange_bool_acq (&pwd_tablename_val, p, NULL))
60 {
61 /* Another thread already installed the value. */
62 free (p);
63 pwd_tablename_len = strlen (pwd_tablename_val);
64 }
e61abf83 65 }
48b29391 66
2d7da676 67 return NSS_STATUS_SUCCESS;
e61abf83
UD
68}
69
2d7da676 70
e61abf83 71enum nss_status
51eecc4a 72_nss_nisplus_setpwent (int stayopen)
e61abf83 73{
a334319f 74 enum nss_status status = NSS_STATUS_SUCCESS;
2d7da676 75
e61abf83
UD
76 __libc_lock_lock (lock);
77
48b29391
UD
78 if (result != NULL)
79 {
80 nis_freeresult (result);
81 result = NULL;
82 }
2d7da676 83
48b29391
UD
84 if (pwd_tablename_val == NULL)
85 {
86 int err;
87 status = _nss_pwd_create_tablename (&err);
88 }
e61abf83
UD
89
90 __libc_lock_unlock (lock);
91
2d7da676 92 return status;
e61abf83
UD
93}
94
95enum nss_status
96_nss_nisplus_endpwent (void)
97{
98 __libc_lock_lock (lock);
99
48b29391
UD
100 if (result != NULL)
101 {
102 nis_freeresult (result);
103 result = NULL;
104 }
e61abf83
UD
105
106 __libc_lock_unlock (lock);
107
108 return NSS_STATUS_SUCCESS;
109}
110
111static enum nss_status
d71b808a
UD
112internal_nisplus_getpwent_r (struct passwd *pw, char *buffer, size_t buflen,
113 int *errnop)
e61abf83 114{
a334319f 115 int parse_res;
e61abf83
UD
116
117 /* Get the next entry until we found a correct one. */
118 do
119 {
a334319f 120 nis_result *saved_res;
8f2ece69 121
a334319f 122 if (result == NULL)
e61abf83 123 {
a334319f 124 saved_res = NULL;
48b29391 125 if (pwd_tablename_val == NULL)
d71b808a 126 {
48b29391 127 enum nss_status status = _nss_pwd_create_tablename (errnop);
a334319f
UD
128
129 if (status != NSS_STATUS_SUCCESS)
130 return status;
d71b808a 131 }
e61abf83 132
48b29391 133 result = nis_first_entry (pwd_tablename_val);
a334319f
UD
134 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
135 return niserr2nss (result->status);
e61abf83
UD
136 }
137 else
138 {
a334319f 139 saved_res = result;
48b29391 140 result = nis_next_entry (pwd_tablename_val, &result->cookie);
a334319f
UD
141 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
142 {
143 nis_freeresult (saved_res);
144 return niserr2nss (result->status);
145 }
e61abf83
UD
146 }
147
a334319f 148 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer,
d71b808a 149 buflen, errnop);
48b29391 150 if (__builtin_expect (parse_res == -1, 0))
60c96635 151 {
a334319f
UD
152 nis_freeresult (result);
153 result = saved_res;
d71b808a 154 *errnop = ERANGE;
a334319f 155 return NSS_STATUS_TRYAGAIN;
60c96635 156 }
48b29391
UD
157
158 if (saved_res)
159 nis_freeresult (saved_res);
160 }
161 while (!parse_res);
e61abf83 162
a334319f 163 return NSS_STATUS_SUCCESS;
e61abf83
UD
164}
165
166enum nss_status
d71b808a
UD
167_nss_nisplus_getpwent_r (struct passwd *result, char *buffer, size_t buflen,
168 int *errnop)
e61abf83
UD
169{
170 int status;
171
172 __libc_lock_lock (lock);
173
d71b808a 174 status = internal_nisplus_getpwent_r (result, buffer, buflen, errnop);
e61abf83
UD
175
176 __libc_lock_unlock (lock);
177
178 return status;
179}
180
181enum nss_status
182_nss_nisplus_getpwnam_r (const char *name, struct passwd *pw,
d71b808a 183 char *buffer, size_t buflen, int *errnop)
e61abf83
UD
184{
185 int parse_res;
186
48b29391 187 if (pwd_tablename_val == NULL)
d71b808a 188 {
48b29391
UD
189 enum nss_status status = _nss_pwd_create_tablename (errnop);
190
d71b808a
UD
191 if (status != NSS_STATUS_SUCCESS)
192 return status;
193 }
2d7da676 194
ac9f45cf
UD
195 if (name == NULL)
196 {
197 *errnop = EINVAL;
198 return NSS_STATUS_UNAVAIL;
199 }
e61abf83 200
48b29391
UD
201 nis_result *result;
202 char buf[strlen (name) + 9 + pwd_tablename_len];
203 int olderr = errno;
e61abf83 204
48b29391 205 snprintf (buf, sizeof (buf), "[name=%s],%s", name, pwd_tablename_val);
e61abf83 206
48b29391 207 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
e61abf83 208
48b29391
UD
209 if (result == NULL)
210 {
211 *errnop = ENOMEM;
212 return NSS_STATUS_TRYAGAIN;
213 }
34816665 214
48b29391
UD
215 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
216 {
217 enum nss_status status = niserr2nss (result->status);
e61abf83 218
48b29391 219 __set_errno (olderr);
e61abf83
UD
220
221 nis_freeresult (result);
48b29391
UD
222 return status;
223 }
224
225 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
e61abf83 226
48b29391
UD
227 nis_freeresult (result);
228
229 if (__builtin_expect (parse_res < 1, 0))
230 {
231 if (parse_res == -1)
0ecb606c 232 {
48b29391
UD
233 *errnop = ERANGE;
234 return NSS_STATUS_TRYAGAIN;
235 }
236 else
237 {
238 __set_errno (olderr);
239 return NSS_STATUS_NOTFOUND;
d71b808a 240 }
e61abf83 241 }
48b29391
UD
242
243 return NSS_STATUS_SUCCESS;
e61abf83
UD
244}
245
246enum nss_status
247_nss_nisplus_getpwuid_r (const uid_t uid, struct passwd *pw,
d71b808a 248 char *buffer, size_t buflen, int *errnop)
e61abf83 249{
48b29391 250 if (pwd_tablename_val == NULL)
d71b808a 251 {
48b29391
UD
252 enum nss_status status = _nss_pwd_create_tablename (errnop);
253
d71b808a
UD
254 if (status != NSS_STATUS_SUCCESS)
255 return status;
256 }
257
48b29391
UD
258 int parse_res;
259 nis_result *result;
260 char buf[8 + 3 * sizeof (unsigned long int) + pwd_tablename_len];
261 int olderr = errno;
e61abf83 262
48b29391
UD
263 snprintf (buf, sizeof (buf), "[uid=%lu],%s",
264 (unsigned long int) uid, pwd_tablename_val);
e61abf83 265
48b29391 266 result = nis_list (buf, FOLLOW_PATH | FOLLOW_LINKS, NULL, NULL);
e61abf83 267
48b29391
UD
268 if (result == NULL)
269 {
270 *errnop = ENOMEM;
271 return NSS_STATUS_TRYAGAIN;
272 }
e61abf83 273
48b29391
UD
274 if (__builtin_expect (niserr2nss (result->status) != NSS_STATUS_SUCCESS, 0))
275 {
276 enum nss_status status = niserr2nss (result->status);
34816665 277
48b29391
UD
278 __set_errno (olderr);
279
280 nis_freeresult (result);
281 return status;
282 }
283
284 parse_res = _nss_nisplus_parse_pwent (result, pw, buffer, buflen, errnop);
285
286 nis_freeresult (result);
287
288 if (__builtin_expect (parse_res < 1, 0))
289 {
290 if (parse_res == -1)
291 {
292 *errnop = ERANGE;
293 return NSS_STATUS_TRYAGAIN;
294 }
295 else
296 {
297 __set_errno (olderr);
298 return NSS_STATUS_NOTFOUND;
299 }
300 }
301
302 return NSS_STATUS_SUCCESS;
e61abf83 303}