(getspnam_plususer): Preserve original return value.
[kopensolaris-gnu/glibc.git] / nis / nss_nis / nis-spwd.c
1 /* Copyright (C) 1996-1998, 2001, 2002, 2003 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
4
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.
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
13    Lesser General Public License for more details.
14
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.  */
19
20 #include <nss.h>
21 #include <ctype.h>
22 #include <errno.h>
23 #include <string.h>
24 /* The following is an ugly trick to avoid a prototype declaration for
25    _nss_nis_endspent.  */
26 #define _nss_nis_endspent _nss_nis_endspent_XXX
27 #include <shadow.h>
28 #undef _nss_nis_endspent
29 #include <bits/libc-lock.h>
30 #include <rpcsvc/yp.h>
31 #include <rpcsvc/ypclnt.h>
32
33 #include "nss-nis.h"
34
35 /* Get the declaration of the parser function.  */
36 #define ENTNAME spent
37 #define STRUCTURE spwd
38 #define EXTERN_PARSER
39 #include <nss/nss_files/files-parse.c>
40
41 /* Protect global state against multiple changers */
42 __libc_lock_define_initialized (static, lock)
43
44 static bool_t new_start = 1;
45 static char *oldkey;
46 static int oldkeylen;
47
48 enum nss_status
49 _nss_nis_setspent (int stayopen)
50 {
51   __libc_lock_lock (lock);
52
53   new_start = 1;
54   free (oldkey);
55   oldkey = NULL;
56   oldkeylen = 0;
57
58   __libc_lock_unlock (lock);
59
60   return NSS_STATUS_SUCCESS;
61 }
62 /* Make _nss_nis_endspent an alias of _nss_nis_setspent.  We do this
63    even though the prototypes don't match.  The argument of setspent
64    is not used so this makes no difference.  */
65 strong_alias (_nss_nis_setspent, _nss_nis_endspent)
66
67 static enum nss_status
68 internal_nis_getspent_r (struct spwd *sp, char *buffer, size_t buflen,
69                          int *errnop)
70 {
71   struct parser_data *data = (void *) buffer;
72   char *domain, *result, *outkey;
73   int len, keylen, parse_res;
74
75   if (yp_get_default_domain (&domain))
76     return NSS_STATUS_UNAVAIL;
77
78   /* Get the next entry until we found a correct one. */
79   do
80     {
81       enum nss_status retval;
82       char *p;
83
84       if (new_start)
85         retval = yperr2nss (yp_first (domain, "shadow.byname",
86                                       &outkey, &keylen, &result, &len));
87       else
88         retval = yperr2nss ( yp_next (domain, "shadow.byname",
89                                       oldkey, oldkeylen,
90                                       &outkey, &keylen, &result, &len));
91
92       if (retval != NSS_STATUS_SUCCESS)
93         {
94           if (retval == NSS_STATUS_TRYAGAIN)
95             *errnop = errno;
96           return retval;
97         }
98
99       if ((size_t) (len + 1) > buflen)
100         {
101           free (result);
102           *errnop = ERANGE;
103           return NSS_STATUS_TRYAGAIN;
104         }
105
106       p = strncpy (buffer, result, len);
107       buffer[len] = '\0';
108       while (isspace (*p))
109         ++p;
110       free (result);
111
112       parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop);
113       if (parse_res == -1)
114         {
115           free (outkey);
116           *errnop = ERANGE;
117           return NSS_STATUS_TRYAGAIN;
118         }
119
120       free (oldkey);
121       oldkey = outkey;
122       oldkeylen = keylen;
123       new_start = 0;
124     }
125   while (!parse_res);
126
127   return NSS_STATUS_SUCCESS;
128 }
129
130 enum nss_status
131 _nss_nis_getspent_r (struct spwd *result, char *buffer, size_t buflen,
132                      int *errnop)
133 {
134   int status;
135
136   __libc_lock_lock (lock);
137
138   status = internal_nis_getspent_r (result, buffer, buflen, errnop);
139
140   __libc_lock_unlock (lock);
141
142   return status;
143 }
144
145 enum nss_status
146 _nss_nis_getspnam_r (const char *name, struct spwd *sp,
147                      char *buffer, size_t buflen, int *errnop)
148 {
149   struct parser_data *data = (void *) buffer;
150   enum nss_status retval;
151   char *domain, *result, *p;
152   int len, parse_res;
153
154   if (name == NULL)
155     {
156       *errnop = EINVAL;
157       return NSS_STATUS_UNAVAIL;
158     }
159
160   if (yp_get_default_domain (&domain))
161     return NSS_STATUS_UNAVAIL;
162
163   retval = yperr2nss (yp_match (domain, "shadow.byname", name,
164                                 strlen (name), &result, &len));
165
166   if (retval != NSS_STATUS_SUCCESS)
167     {
168       if (retval == NSS_STATUS_TRYAGAIN)
169         *errnop = errno;
170       return retval;
171     }
172
173   if ((size_t) (len + 1) > buflen)
174     {
175       free (result);
176       *errnop = ERANGE;
177       return NSS_STATUS_TRYAGAIN;
178     }
179
180   p = strncpy (buffer, result, len);
181   buffer[len] = '\0';
182   while (isspace (*p))
183     ++p;
184   free (result);
185
186   parse_res = _nss_files_parse_spent (p, sp, data, buflen, errnop);
187   if (parse_res < 1)
188     {
189       if (parse_res == -1)
190         return NSS_STATUS_TRYAGAIN;
191       else
192         return NSS_STATUS_NOTFOUND;
193     }
194   return NSS_STATUS_SUCCESS;
195 }