Pretty print and little cleanups.
[kopensolaris-gnu/glibc.git] / nis / nss_nisplus / nisplus-grp.c
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.
4
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.
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    Library General Public License for more details.
14
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.  */
19
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>
28
29 #include "nss-nisplus.h"
30
31 __libc_lock_define_initialized (static, lock);
32
33 static nis_result *result = NULL;
34 static nis_name *names = NULL;
35
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)
38
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)
41
42 #define STRUCTURE       group
43 #define ENTNAME         grent
44 struct grent_data {};
45
46 #define TRAILING_LIST_MEMBER            gr_mem
47 #define TRAILING_LIST_SEPARATOR_P(c)    ((c) == ',')
48 #include "../../nss/nss_files/files-parse.c"
49 LINE_PARSER
50 (,
51  STRING_FIELD (result->gr_name, ISCOLON, 0);
52  if (line[0] == '\0'
53      && (result->gr_name[0] == '+' || result->gr_name[0] == '-'))
54    {
55      result->gr_passwd = NULL;
56      result->gr_gid = 0;
57    }
58  else
59    {
60      STRING_FIELD (result->gr_passwd, ISCOLON, 0);
61      if (result->gr_name[0] == '+' || result->gr_name[0] == '-')
62        INT_FIELD_MAYBE_NULL (result->gr_gid, ISCOLON, 0, 10, , 0)
63      else
64        INT_FIELD (result->gr_gid, ISCOLON, 0, 10,)
65    }
66  )
67
68 static int
69 _nss_nisplus_parse_grent (nis_result * result, struct group *gr,
70                           char *buffer, size_t buflen)
71 {
72 #if 0
73   /* XXX here is a bug, sometimes we get some special characters at the
74      end of a line */
75   char *first_unused = buffer;
76   size_t room_left = buflen;
77   char *line;
78   int count;
79
80   if (result == NULL)
81     return -1;
82
83   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
84       result->objects.objects_len != 1 ||
85       result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
86    strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
87            "group_tbl") != 0 ||
88       result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
89     return -1;
90
91   if (NISENTRYLEN (0, 0, result) >= room_left)
92     {
93       /* The line is too long for our buffer.  */
94     no_more_room:
95       __set_errno (ERANGE);
96       return -1;
97     }
98
99   strncpy (first_unused, NISENTRYVAL (0, 0, result),
100            NISENTRYLEN (0, 0, result));
101   first_unused[NISENTRYLEN (0, 0, result)] = '\0';
102   gr->gr_name = first_unused;
103   room_left -= (strlen (first_unused) + 1);
104   first_unused += strlen (first_unused) + 1;
105
106   if (NISENTRYLEN (0, 1, result) >= room_left)
107     goto no_more_room;
108
109   strncpy (first_unused, NISENTRYVAL (0, 1, result),
110            NISENTRYLEN (0, 1, result));
111   first_unused[NISENTRYLEN (0, 1, result)] = '\0';
112   gr->gr_passwd = first_unused;
113   room_left -= (strlen (first_unused) + 1);
114   first_unused += strlen (first_unused) + 1;
115
116   if (NISENTRYLEN (0, 2, result) >= room_left)
117     goto no_more_room;
118
119   strncpy (first_unused, NISENTRYVAL (0, 2, result),
120            NISENTRYLEN (0, 2, result));
121   first_unused[NISENTRYLEN (0, 2, result)] = '\0';
122   gr->gr_gid = atoi (first_unused);
123   room_left -= (strlen (first_unused) + 1);
124   first_unused += strlen (first_unused) + 1;
125
126   if (NISENTRYLEN (0, 3, result) >= room_left)
127     goto no_more_room;
128
129   strncpy (first_unused, NISENTRYVAL (0, 3, result),
130            NISENTRYLEN (0, 3, result));
131   first_unused[NISENTRYLEN (0, 3, result)] = '\0';
132   line = first_unused;
133   room_left -= (strlen (line) + 1);
134   first_unused += strlen (line) + 1;
135   /* Adjust the pointer so it is aligned for
136      storing pointers.  */
137   first_unused += __alignof__ (char *) - 1;
138   first_unused -= ((first_unused - (char *) 0) % __alignof__ (char *));
139   gr->gr_mem = (char **) first_unused;
140
141   count = 0;
142   while (*line != '\0')
143     {
144       /* Skip leading blanks.  */
145       while (isspace (*line))
146         ++line;
147
148       if (*line == '\0')
149         break;
150
151       if (room_left < sizeof (char *))
152           goto no_more_room;
153       room_left -= sizeof (char *);
154       gr->gr_mem[count] = line;
155
156       while (*line != '\0' && *line != ',' && !isspace(*line))
157         ++line;
158
159       if (line != gr->gr_mem[count])
160         {
161           *line = '\0';
162           ++line;
163           ++count;
164         }
165       else
166         gr->gr_mem[count] = NULL;
167     }
168   if (room_left < sizeof (char *))
169       goto no_more_room;
170   room_left -= sizeof (char *);
171   gr->gr_mem[count] = NULL;
172
173   return 1;
174 #else
175   char *p = buffer;
176   size_t room_left = buflen;
177   struct parser_data *data = (void *) buffer;
178
179   if (result == NULL)
180     return -1;
181
182   if ((result->status != NIS_SUCCESS && result->status != NIS_S_SUCCESS) ||
183       result->objects.objects_len != 1 ||
184       result->objects.objects_val[0].zo_data.zo_type != ENTRY_OBJ ||
185    strcmp (result->objects.objects_val[0].zo_data.objdata_u.en_data.en_type,
186            "group_tbl") != 0 ||
187       result->objects.objects_val[0].zo_data.objdata_u.en_data.en_cols.en_cols_len < 4)
188     return -1;
189
190   memset (p, '\0', room_left);
191
192   if (NISENTRYLEN (0, 0, result) + 1 > room_left)
193     {
194       __set_errno (ERANGE);
195       return -1;
196     }
197   strncpy (p, NISENTRYVAL (0, 0, result), NISENTRYLEN (0, 0, result));
198   room_left -= (NISENTRYLEN (0, 0, result) + 1);
199   strcat (p, ":");
200
201   if (NISENTRYLEN (0, 1, result) + 1 > room_left)
202     {
203       __set_errno (ERANGE);
204       return -1;
205     }
206   strncat (p, NISENTRYVAL (0, 1, result), NISENTRYLEN (0, 1, result));
207   room_left -= (NISENTRYLEN (0, 1, result) + 1);
208   strcat (p, ":");
209   if (NISENTRYLEN (0, 2, result) + 1 > room_left)
210     {
211       __set_errno (ERANGE);
212       return -1;
213     }
214   strncat (p, NISENTRYVAL (0, 2, result), NISENTRYLEN (0, 2, result));
215   room_left -= (NISENTRYLEN (0, 2, result) + 1);
216   strcat (p, ":");
217   if (NISENTRYLEN (0, 3, result) + 1 > room_left)
218     {
219       __set_errno (ERANGE);
220       return -1;
221     }
222   strncat (p, NISENTRYVAL (0, 3, result), NISENTRYLEN (0, 3, result));
223   room_left -= (NISENTRYLEN (0, 3, result) + 1);
224
225   return _nss_files_parse_grent (p, gr, data, buflen);
226 #endif
227 }
228
229 enum nss_status
230 _nss_nisplus_setgrent (void)
231 {
232   __libc_lock_lock (lock);
233
234   if (result)
235     nis_freeresult (result);
236   result = NULL;
237   if (names)
238     {
239       nis_freenames (names);
240       names = NULL;
241     }
242
243   __libc_lock_unlock (lock);
244
245   return NSS_STATUS_SUCCESS;
246 }
247
248 enum nss_status
249 _nss_nisplus_endgrent (void)
250 {
251   __libc_lock_lock (lock);
252
253   if (result)
254     nis_freeresult (result);
255   result = NULL;
256   if (names)
257     {
258       nis_freenames (names);
259       names = NULL;
260     }
261
262   __libc_lock_unlock (lock);
263
264   return NSS_STATUS_SUCCESS;
265 }
266
267 static enum nss_status
268 internal_nisplus_getgrent_r (struct group *gr, char *buffer, size_t buflen)
269 {
270   int parse_res;
271
272   /* Get the next entry until we found a correct one. */
273   do
274     {
275       if (result == NULL)
276         {
277           names = nis_getnames ("group.org_dir");
278           if (names == NULL || names[0] == NULL)
279             return NSS_STATUS_UNAVAIL;
280
281           result = nis_first_entry (names[0]);
282           if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
283             return niserr2nss (result->status);
284         }
285       else
286         {
287           nis_result *res;
288
289           res = nis_next_entry (names[0], &result->cookie);
290           nis_freeresult (result);
291           result = res;
292           if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
293             return niserr2nss (result->status);
294         }
295
296       parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
297     }
298   while (!parse_res);
299
300   return NSS_STATUS_SUCCESS;
301 }
302
303 enum nss_status
304 _nss_nisplus_getgrent_r (struct group *result, char *buffer, size_t buflen)
305 {
306   int status;
307
308   __libc_lock_lock (lock);
309
310   status = internal_nisplus_getgrent_r (result, buffer, buflen);
311
312   __libc_lock_unlock (lock);
313
314   return status;
315 }
316
317 enum nss_status
318 _nss_nisplus_getgrnam_r (const char *name, struct group *gr,
319                          char *buffer, size_t buflen)
320 {
321   int parse_res;
322
323   if (name == NULL || strlen (name) > 8)
324     return NSS_STATUS_NOTFOUND;
325   else
326     {
327       nis_result *result;
328       char buf[strlen (name) + 24];
329
330       sprintf (buf, "[name=%s],group.org_dir", name);
331
332       result = nis_list (buf, EXPAND_NAME, NULL, NULL);
333
334       if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
335         {
336           enum nss_status status = niserr2nss (result->status);
337
338           nis_freeresult (result);
339           return status;
340         }
341
342       parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
343
344       nis_freeresult (result);
345
346       if (parse_res)
347         return NSS_STATUS_SUCCESS;
348
349       if (!parse_res && errno == ERANGE)
350         return NSS_STATUS_TRYAGAIN;
351       else
352         return NSS_STATUS_NOTFOUND;
353     }
354 }
355
356 enum nss_status
357 _nss_nisplus_getgrgid_r (const gid_t gid, struct group *gr,
358                          char *buffer, size_t buflen)
359 {
360   int parse_res;
361   nis_result *result;
362   char buf[36];
363
364   sprintf (buf, "[gid=%d],group.org_dir", gid);
365
366   result = nis_list (buf, EXPAND_NAME, NULL, NULL);
367
368   if (niserr2nss (result->status) != NSS_STATUS_SUCCESS)
369     {
370       enum nss_status status = niserr2nss (result->status);
371
372       nis_freeresult (result);
373       return status;
374     }
375
376   parse_res = _nss_nisplus_parse_grent (result, gr, buffer, buflen);
377
378   nis_freeresult (result);
379
380   if (parse_res)
381     return NSS_STATUS_SUCCESS;
382
383   if (!parse_res && errno == ERANGE)
384     return NSS_STATUS_TRYAGAIN;
385   else
386     return NSS_STATUS_NOTFOUND;
387 }