Update.
[glibc.git] / nis / nss_nisplus / nisplus-grp.c
blob1c73ca555b62b07b1692fb9afc86aab00783ecf6
1 /* Copyright (C) 1997 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 Library General Public License as
7 published by the Free Software Foundation; either version 2 of the
8 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 Library General Public License for more details.
15 You should have received a copy of the GNU Library General Public
16 License along with the GNU C Library; see the file COPYING.LIB. If not,
17 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA. */
20 #include <nss.h>
21 #include <grp.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <libc-lock.h>
26 #include <rpcsvc/nis.h>
27 #include <rpcsvc/nislib.h>
29 #include "nss-nisplus.h"
31 __libc_lock_define_initialized (static, lock);
33 static nis_result *result = NULL;
34 static nis_name *names = NULL;
36 #define NISENTRYVAL(idx,col,res) \
37 ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
39 #define NISENTRYLEN(idx,col,res) \
40 ((res)->objects.objects_val[(idx)].zo_data.objdata_u.en_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
42 int
43 _nss_nisplus_parse_grent (nis_result * result, struct group *gr,
44 char *buffer, size_t buflen)
46 char *first_unused = buffer;
47 size_t room_left = buflen;
48 char *line;
49 int count;
51 if (result == NULL)
52 return 0;
54 if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
55 result->objects.objects_len != 1 ||
56 result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
57 strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
58 "group_tbl") != 0 ||
59 result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
60 return 0;
62 if (NISENTRYLEN (0, 0, result) >= room_left)
64 /* The line is too long for our buffer. */
65 no_more_room:
66 __set_errno (ERANGE);
67 return 0;
70 strncpy (first_unused, NISENTRYVAL (0, 0, result),
71 NISENTRYLEN (0, 0, result));
72 first_unused[NISENTRYLEN (0, 0, result)] = '\0';
73 gr->gr_name = first_unused;
74 room_left -= (strlen (first_unused) + 1);
75 first_unused += strlen (first_unused) + 1;
77 if (NISENTRYLEN (0, 1, result) >= room_left)
78 goto no_more_room;
80 strncpy (first_unused, NISENTRYVAL (0, 1, result),
81 NISENTRYLEN (0, 1, result));
82 first_unused[NISENTRYLEN (0, 1, result)] = '\0';
83 gr->gr_passwd = first_unused;
84 room_left -= (strlen (first_unused) + 1);
85 first_unused += strlen (first_unused) + 1;
87 if (NISENTRYLEN (0, 2, result) >= room_left)
88 goto no_more_room;
90 strncpy (first_unused, NISENTRYVAL (0, 2, result),
91 NISENTRYLEN (0, 2, result));
92 first_unused[NISENTRYLEN (0, 2, result)] = '\0';
93 gr->gr_gid = atoi (first_unused);
94 room_left -= (strlen (first_unused) + 1);
95 first_unused += strlen (first_unused) + 1;
97 if (NISENTRYLEN (0, 3, result) >= room_left)
98 goto no_more_room;
100 strncpy (first_unused, NISENTRYVAL (0, 3, result),
101 NISENTRYLEN (0, 3, result));
102 first_unused[NISENTRYLEN (0, 3, result)] = '\0';
103 line = first_unused;
104 room_left -= (strlen (line) + 1);
105 first_unused += strlen (line) + 1;
106 /* Adjust the pointer so it is aligned for
107 storing pointers. */
108 first_unused += __alignof__ (char *) - 1;
109 first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
110 gr->gr_mem = (char **) first_unused;
112 count = 0;
113 while (*line != '\0')
115 /* Skip leading blanks. */
116 while (isspace (*line))
117 ++line;
119 if (*line == '\0')
120 break;
122 if (room_left < sizeof (char *))
123 goto no_more_room;
124 room_left -= sizeof (char *);
125 gr->gr_mem[count] = line;
127 while (*line != '\0' && *line != ',' && !isspace(*line))
128 ++line;
130 if (line != gr->gr_mem[count])
132 if (*line != '\0')
134 *line = '\0';
135 ++line;
137 ++count;
139 else
140 gr->gr_mem[count] = NULL;
142 if (room_left < sizeof (char *))
143 goto no_more_room;
144 room_left -= sizeof (char *);
145 gr->gr_mem[count] = NULL;
147 return 1;
150 enum nss_status
151 _nss_nisplus_setgrent (void)
153 __libc_lock_lock (lock);
155 if (result)
156 nis_freeresult (result);
157 result = NULL;
158 if (names)
160 nis_freenames (names);
161 names = NULL;
164 __libc_lock_unlock (lock);
166 return NSS_STATUS_SUCCESS;
169 enum nss_status
170 _nss_nisplus_endgrent (void)
172 __libc_lock_lock (lock);
174 if (result)
175 nis_freeresult (result);
176 result = NULL;
177 if (names)
179 nis_freenames (names);
180 names = NULL;
183 __libc_lock_unlock (lock);
185 return NSS_STATUS_SUCCESS;
188 static enum nss_status
189 internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen)
191 int parse_res;
193 /* Get the next entry until we found a correct one. */
196 if (result == NULL)
198 names = nis_getnames ("group.org_dir");
199 if (names == NULL || names[0] == NULL)
200 return NSS_STATUS_UNAVAIL;
202 result = nis_first_entry (names[0]);
203 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
204 return niserr2nss (result->status);
206 else
208 nis_result *res;
210 res = nis_next_entry (names[0], &result->cookie);
211 nis_freeresult (result);
212 result = res;
213 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
214 return niserr2nss (result->status);
217 parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
219 while (!parse_res);
221 return NSS_STATUS_SUCCESS;
224 enum nss_status
225 _nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen)
227 int status;
229 __libc_lock_lock (lock);
231 status = internal_nisplus_getgrent_r (result, buffer, buflen);
233 __libc_lock_unlock (lock);
235 return status;
238 enum nss_status
239 _nss_nisplus_getgrnam_r (const char *name, struct group *gr,
240 char *buffer, size_t buflen)
242 int parse_res;
244 if (name == NULL || strlen (name) > 8)
245 return NSS_STATUS_NOTFOUND;
246 else
248 nis_result *result;
249 char buf[strlen (name) + 24];
251 sprintf (buf, "[name=%s],group.org_dir", name);
253 result = nis_list (buf, EXPAND_NAME, NULL, NULL);
255 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
257 enum nss_status status = niserr2nss (result->status);
259 nis_freeresult (result);
260 return status;
263 parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
265 nis_freeresult (result);
267 if (parse_res)
268 return NSS_STATUS_SUCCESS;
270 if (!parse_res && errno == ERANGE)
271 return NSS_STATUS_TRYAGAIN;
272 else
273 return NSS_STATUS_NOTFOUND;
277 enum nss_status
278 _nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
279 char *buffer, size_t buflen)
281 int parse_res;
282 nis_result *result;
283 char buf[36];
285 sprintf (buf, "[gid=%d],group.org_dir", gid);
287 result = nis_list (buf, EXPAND_NAME, NULL, NULL);
289 if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
291 enum nss_status status = niserr2nss (result->status);
293 nis_freeresult (result);
294 return status;
297 parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
299 nis_freeresult (result);
301 if (parse_res)
302 return NSS_STATUS_SUCCESS;
304 if (!parse_res && errno == ERANGE)
305 return NSS_STATUS_TRYAGAIN;
306 else
307 return NSS_STATUS_NOTFOUND;