9c38539de835094123e30ea6f5110b5ef0785d06
[platform/upstream/glibc.git] / nis / nss_nisplus / nisplus-netgrp.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 <errno.h>
22 #include <ctype.h>
23 #include <netdb.h>
24 #include <string.h>
25 #include <netgroup.h>
26 #include <bits/libc-lock.h>
27 #include <rpcsvc/nis.h>
28 #include <rpcsvc/nislib.h>
29
30 #include "nss-nisplus.h"
31
32 __libc_lock_define_initialized (static, lock)
33
34 static nis_result *data = NULL;
35 static unsigned long data_size = 0;
36 static unsigned long position = 0;
37
38 #define NISENTRYVAL(idx,col,res) \
39         ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_val)
40
41 #define NISENTRYLEN(idx,col,res) \
42         ((res)->objects.objects_val[(idx)].EN_data.en_cols.en_cols_val[(col)].ec_value.ec_value_len)
43
44 static enum nss_status
45 _nss_nisplus_parse_netgroup (struct __netgrent *result, char *buffer,
46                              size_t buflen)
47 {
48   enum nss_status status;
49
50   /* Some sanity checks.  */
51   if (data == NULL || data_size == 0)
52     return NSS_STATUS_NOTFOUND;
53
54   if (position == data_size)
55     return result->first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN;
56
57   if (NISENTRYLEN (position, 1, data) > 0)
58     {
59       /* We have a list of other netgroups.  */
60
61       result->type = group_val;
62       if (NISENTRYLEN (position, 1, data) >= buflen)
63         {
64           __set_errno (ERANGE);
65           return NSS_STATUS_TRYAGAIN;
66         }
67       strncpy (buffer, NISENTRYVAL (position, 1, data),
68                NISENTRYLEN (position, 1, data));
69       buffer[NISENTRYLEN (position, 1, data)] = '\0';
70       result->val.group = buffer;
71       ++position;
72       result->first = 0;
73
74       return NSS_STATUS_SUCCESS;
75     }
76
77   /* Before we can copy the entry to the private buffer we have to make
78      sure it is big enough.  */
79   if (NISENTRYLEN (position, 2, data) + NISENTRYLEN (position, 3, data) +
80       NISENTRYLEN (position, 4, data) + 6 > buflen)
81     {
82       __set_errno (ERANGE);
83       status = NSS_STATUS_TRYAGAIN;
84     }
85   else
86     {
87       char *cp = buffer;
88
89       result->type = triple_val;
90
91       if (NISENTRYLEN (position, 2, data) == 0)
92         result->val.triple.host = NULL;
93       else
94         {
95           result->val.triple.host = cp;
96           cp = stpncpy (cp, NISENTRYVAL (position, 2, data),
97                         NISENTRYLEN (position, 2, data));
98           *cp = '\0';
99           ++cp;
100         }
101
102       if (NISENTRYLEN (position, 3, data) == 0)
103         result->val.triple.user = NULL;
104       else
105         {
106           result->val.triple.user = cp;
107           cp = stpncpy (cp, NISENTRYVAL (position, 3, data),
108                         NISENTRYLEN (position, 3, data));
109           *cp = '\0';
110           ++cp;
111         }
112
113       if (NISENTRYLEN (position, 4, data) == 0)
114         result->val.triple.domain = NULL;
115       else
116         {
117           result->val.triple.domain = cp;
118           cp = stpncpy (cp, NISENTRYVAL (position, 4, data),
119                         NISENTRYLEN (position, 4, data));
120           *cp = '\0';
121         }
122
123       status = NSS_STATUS_SUCCESS;
124
125       /* Remember where we stopped reading.  */
126       ++position;
127
128       result->first = 0;
129     }
130
131   return status;
132 }
133
134 enum nss_status
135 _nss_nisplus_setnetgrent (char *group)
136
137 {
138   enum nss_status status;
139   char buf[strlen (group) + 30];
140
141   if (group == NULL || group[0] == '\0')
142     return NSS_STATUS_UNAVAIL;
143
144   status = NSS_STATUS_SUCCESS;
145
146   __libc_lock_lock (lock);
147
148   if (data != NULL)
149     {
150       nis_freeresult (data);
151       data = NULL;
152       data_size = 0;
153       position = 0;
154     }
155
156   sprintf (buf, "[name=%s],netgroup.org_dir", group);
157
158   data = nis_list (buf, EXPAND_NAME, NULL, NULL);
159
160   if (niserr2nss (data->status) != NSS_STATUS_SUCCESS)
161     {
162       status = niserr2nss (data->status);
163       nis_freeresult (data);
164       data = NULL;
165     }
166   else
167     data_size = data->objects.objects_len;
168
169   __libc_lock_unlock (lock);
170
171   return status;
172 }
173
174 enum nss_status
175 _nss_nisplus_endnetgrent (void)
176 {
177   __libc_lock_lock (lock);
178
179   if (data != NULL)
180     {
181       nis_freeresult (data);
182       data = NULL;
183       data_size = 0;
184       position = 0;
185     }
186
187   __libc_lock_unlock (lock);
188
189   return NSS_STATUS_SUCCESS;
190 }
191
192 enum nss_status
193 _nss_nisplus_getnetgrent_r (struct __netgrent *result,
194                             char *buffer, size_t buflen)
195 {
196   enum nss_status status;
197
198   __libc_lock_lock (lock);
199
200   status = _nss_nisplus_parse_netgroup (result, buffer, buflen);
201
202   __libc_lock_unlock (lock);
203
204   return status;
205 }