(getspnam_plususer): Preserve original return value.
[kopensolaris-gnu/glibc.git] / nis / nss_nis / nis-grp.c
1 /* Copyright (C) 1996-1999, 2001-2003, 2004 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@suse.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 /* The following is an ugly trick to avoid a prototype declaration for
22    _nss_nis_endgrent.  */
23 #define _nss_nis_endgrent _nss_nis_endgrent_XXX
24 #include <grp.h>
25 #undef _nss_nis_endgrent
26 #include <ctype.h>
27 #include <errno.h>
28 #include <string.h>
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 grent
37 #define STRUCTURE group
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_setgrent (int stayopen)
50 {
51   __libc_lock_lock (lock);
52
53   new_start = 1;
54   if (oldkey != NULL)
55     {
56       free (oldkey);
57       oldkey = NULL;
58       oldkeylen = 0;
59     }
60
61   __libc_lock_unlock (lock);
62
63   return NSS_STATUS_SUCCESS;
64 }
65 /* Make _nss_nis_endgrent an alias of _nss_nis_setgrent.  We do this
66    even though the prototypes don't match.  The argument of setgrent
67    is not used so this makes no difference.  */
68 strong_alias (_nss_nis_setgrent, _nss_nis_endgrent)
69
70 static enum nss_status
71 internal_nis_getgrent_r (struct group *grp, char *buffer, size_t buflen,
72                          int *errnop)
73 {
74   struct parser_data *data = (void *) buffer;
75   char *domain, *result, *outkey;
76   int len, keylen, parse_res;
77
78   if (yp_get_default_domain (&domain))
79     return NSS_STATUS_UNAVAIL;
80
81   /* Get the next entry until we found a correct one. */
82   do
83     {
84       enum nss_status retval;
85       char *p;
86
87       if (new_start)
88         retval = yperr2nss (yp_first (domain, "group.byname",
89                                       &outkey, &keylen, &result, &len));
90       else
91         retval = yperr2nss ( yp_next (domain, "group.byname",
92                                       oldkey, oldkeylen,
93                                       &outkey, &keylen, &result, &len));
94
95       if (retval != NSS_STATUS_SUCCESS)
96         {
97           if (retval == NSS_STATUS_TRYAGAIN)
98             *errnop = errno;
99           return retval;
100         }
101
102       if ((size_t) (len + 1) > buflen)
103         {
104           free (result);
105           *errnop = ERANGE;
106           return NSS_STATUS_TRYAGAIN;
107         }
108
109       p = strncpy (buffer, result, len);
110       buffer[len] = '\0';
111       while (isspace (*p))
112         ++p;
113       free (result);
114
115       parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
116       if (parse_res == -1)
117         {
118           free (outkey);
119           *errnop = ERANGE;
120           return NSS_STATUS_TRYAGAIN;
121         }
122
123       free (oldkey);
124       oldkey = outkey;
125       oldkeylen = keylen;
126       new_start = 0;
127     }
128   while (parse_res < 1);
129
130   return NSS_STATUS_SUCCESS;
131 }
132
133 enum nss_status
134 _nss_nis_getgrent_r (struct group *result, char *buffer, size_t buflen,
135                      int *errnop)
136 {
137   int status;
138
139   __libc_lock_lock (lock);
140
141   status = internal_nis_getgrent_r (result, buffer, buflen, errnop);
142
143   __libc_lock_unlock (lock);
144
145   return status;
146 }
147
148 enum nss_status
149 _nss_nis_getgrnam_r (const char *name, struct group *grp,
150                      char *buffer, size_t buflen, int *errnop)
151 {
152   struct parser_data *data = (void *) buffer;
153   enum nss_status retval;
154   char *domain, *result, *p;
155   int len, parse_res;
156
157   if (name == NULL)
158     {
159       *errnop = EINVAL;
160       return NSS_STATUS_UNAVAIL;
161     }
162
163   if (yp_get_default_domain (&domain))
164     return NSS_STATUS_UNAVAIL;
165
166   retval = yperr2nss (yp_match (domain, "group.byname", name,
167                                 strlen (name), &result, &len));
168
169   if (retval != NSS_STATUS_SUCCESS)
170     {
171       if (retval == NSS_STATUS_TRYAGAIN)
172         *errnop = errno;
173       return retval;
174     }
175
176   if ((size_t) (len + 1) > buflen)
177     {
178       free (result);
179       *errnop = ERANGE;
180       return NSS_STATUS_TRYAGAIN;
181     }
182
183   p = strncpy (buffer, result, len);
184   buffer[len] = '\0';
185   while (isspace (*p))
186     ++p;
187   free (result);
188
189   parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
190   if (parse_res < 1)
191     {
192       if (parse_res == -1)
193         return NSS_STATUS_TRYAGAIN;
194       else
195         return NSS_STATUS_NOTFOUND;
196     }
197   return NSS_STATUS_SUCCESS;
198 }
199
200 enum nss_status
201 _nss_nis_getgrgid_r (gid_t gid, struct group *grp,
202                      char *buffer, size_t buflen, int *errnop)
203 {
204   struct parser_data *data = (void *) buffer;
205   enum nss_status retval;
206   char *domain, *result, *p;
207   int len, nlen, parse_res;
208   char buf[32];
209
210   if (yp_get_default_domain (&domain))
211     return NSS_STATUS_UNAVAIL;
212
213   nlen = sprintf (buf, "%lu", (unsigned long int) gid);
214
215   retval = yperr2nss (yp_match (domain, "group.bygid", buf,
216                                 nlen, &result, &len));
217
218   if (retval != NSS_STATUS_SUCCESS)
219     {
220       if (retval == NSS_STATUS_TRYAGAIN)
221         *errnop = errno;
222       return retval;
223     }
224
225   if ((size_t) (len + 1) > buflen)
226     {
227       free (result);
228       *errnop = ERANGE;
229       return NSS_STATUS_TRYAGAIN;
230     }
231
232   p = strncpy (buffer, result, len);
233   buffer[len] = '\0';
234   while (isspace (*p))
235     ++p;
236   free (result);
237
238   parse_res = _nss_files_parse_grent (p, grp, data, buflen, errnop);
239   if (parse_res < 1)
240     {
241       if (parse_res == -1)
242         return NSS_STATUS_TRYAGAIN;
243       else
244         return NSS_STATUS_NOTFOUND;
245     }
246   return NSS_STATUS_SUCCESS;
247 }