]>
Commit | Line | Data |
---|---|---|
a68b0d31 UD |
1 | /* Netgroup file parser in nss_files modules. |
2 | Copyright (C) 1996 Free Software Foundation, Inc. | |
3 | This file is part of the GNU C Library. | |
4 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. | |
5 | ||
6 | The GNU C Library is free software; you can redistribute it and/or | |
7 | modify it under the terms of the GNU Library General Public License as | |
8 | published by the Free Software Foundation; either version 2 of the | |
9 | License, or (at your option) any later version. | |
10 | ||
11 | The GNU C Library is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
14 | Library General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU Library General Public | |
17 | License along with the GNU C Library; see the file COPYING.LIB. If | |
18 | not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
19 | Boston, MA 02111-1307, USA. */ | |
20 | ||
21 | #include <ctype.h> | |
22 | #include <errno.h> | |
23 | #include <libc-lock.h> | |
24 | #include <netdb.h> | |
25 | #include <stdio.h> | |
26 | #include <stdlib.h> | |
27 | #include <string.h> | |
28 | #include "nsswitch.h" | |
29 | #include "netgroup.h" | |
30 | ||
31 | #define DATAFILE "/etc/netgroup" | |
32 | ||
33 | ||
34 | /* Locks the static variables in this file. */ | |
35 | __libc_lock_define_initialized (static, lock) | |
36 | \f | |
37 | /* We share a single place where we store the data for the current | |
38 | netgroup. This buffer is allocated by `setnetgrent' and freed on | |
39 | the next call of this function or when calling `endnetgrent'. */ | |
40 | static char *data; | |
41 | static size_t data_size; | |
42 | static char *cursor; | |
43 | static int first; | |
44 | ||
45 | ||
46 | #define EXPAND(needed) \ | |
47 | do \ | |
48 | { \ | |
49 | size_t old_cursor = cursor - data; \ | |
50 | \ | |
51 | data_size += 512 > 2 * needed ? 512 : 2 * needed; \ | |
52 | data = realloc (data, data_size); \ | |
53 | \ | |
54 | if (data == NULL) \ | |
55 | { \ | |
56 | status = NSS_STATUS_UNAVAIL; \ | |
57 | goto the_end; \ | |
58 | } \ | |
59 | \ | |
60 | cursor = data + old_cursor; \ | |
61 | } \ | |
62 | while (0) | |
63 | ||
64 | ||
65 | enum nss_status | |
66 | _nss_files_setnetgrent (const char *group) | |
67 | { | |
68 | FILE *fp; | |
69 | enum nss_status status; | |
70 | ||
71 | if (group[0] == '\0') | |
72 | return NSS_STATUS_UNAVAIL; | |
73 | ||
74 | __libc_lock_lock (lock); | |
75 | ||
76 | /* Find the netgroups file and open it. */ | |
77 | fp = fopen (DATAFILE, "r"); | |
78 | if (fp == NULL) | |
79 | status = errno == EAGAIN ? NSS_STATUS_TRYAGAIN : NSS_STATUS_UNAVAIL; | |
80 | else | |
81 | { | |
82 | /* Read the file line by line and try to find the description | |
83 | GROUP. We must take care for long lines. */ | |
84 | char *line = NULL; | |
85 | size_t line_len = 0; | |
86 | const ssize_t group_len = strlen (group); | |
87 | ||
88 | status = NSS_STATUS_NOTFOUND; | |
89 | cursor = data; | |
90 | ||
91 | while (!feof (fp)) | |
92 | { | |
93 | ssize_t curlen = getline (&line, &line_len, fp); | |
94 | int found; | |
95 | ||
96 | if (curlen < 0) | |
97 | { | |
98 | status = NSS_STATUS_NOTFOUND; | |
99 | break; | |
100 | } | |
101 | ||
102 | found = (curlen > group_len && strncmp (line, group, group_len) == 0 | |
103 | && isspace (line[group_len])); | |
104 | ||
105 | /* Read the whole line (including continuation) and store it | |
106 | if FOUND in nonzero. Otherwise we don't need it. */ | |
107 | if (found) | |
108 | { | |
109 | /* Store the data from the first line. */ | |
110 | EXPAND (curlen - group_len); | |
111 | memcpy (cursor, &line[group_len + 1], curlen - group_len); | |
112 | cursor += (curlen - group_len) - 1; | |
113 | } | |
114 | ||
115 | while (line[curlen - 1] == '\n' && line[curlen - 2] == '\\') | |
116 | { | |
117 | /* Yes, we have a continuation line. */ | |
118 | if (found) | |
119 | /* Remove these characters from the stored line. */ | |
120 | cursor -= 2; | |
121 | ||
122 | /* Get netxt line. */ | |
123 | curlen = getline (&line, &line_len, fp); | |
124 | if (curlen <= 0) | |
125 | break; | |
126 | ||
127 | if (found) | |
128 | { | |
129 | /* Make sure we have enough room. */ | |
130 | EXPAND (1 + curlen + 1); | |
131 | ||
132 | /* Add separator in case next line starts immediately. */ | |
133 | *cursor++ = ' '; | |
134 | ||
135 | /* Copy new line. */ | |
136 | memcpy (cursor, line, curlen + 1); | |
137 | cursor += curlen; | |
138 | } | |
139 | } | |
140 | ||
141 | if (found) | |
142 | { | |
143 | /* Now we have read the line. */ | |
144 | status = NSS_STATUS_SUCCESS; | |
145 | cursor = data; | |
146 | first = 1; | |
147 | break; | |
148 | } | |
149 | } | |
150 | ||
151 | the_end: | |
152 | /* We don't need the file and the line buffer anymore. */ | |
153 | free (line); | |
154 | fclose (fp); | |
155 | } | |
156 | ||
157 | __libc_lock_unlock (lock); | |
158 | ||
159 | return status; | |
160 | } | |
161 | ||
162 | ||
163 | int | |
164 | _nss_files_endnetgrent (void) | |
165 | { | |
166 | __libc_lock_lock (lock); | |
167 | ||
168 | /* Free allocated memory for data if some is present. */ | |
169 | if (data != NULL) | |
170 | { | |
171 | free (data); | |
172 | data = NULL; | |
173 | data_size = 0; | |
174 | cursor = NULL; | |
175 | } | |
176 | ||
177 | __libc_lock_unlock (lock); | |
178 | ||
179 | return NSS_STATUS_SUCCESS; | |
180 | } | |
181 | ||
182 | ||
183 | enum nss_status | |
184 | _nss_netgroup_parseline (char **cursor, struct __netgrent *result, | |
185 | char *buffer, int buflen) | |
186 | { | |
187 | enum nss_status status; | |
188 | const char *host, *user, *domain; | |
189 | char *cp = *cursor; | |
190 | ||
191 | /* First skip leading spaces. */ | |
192 | while (isspace (*cp)) | |
193 | ++cp; | |
194 | ||
195 | if (*cp != '(') | |
11336c16 UD |
196 | { |
197 | /* We have a list of other netgroups. */ | |
198 | char *name = cp; | |
199 | ||
200 | while (*cp != '\0' && ! isspace (*cp)) | |
201 | ++cp; | |
202 | ||
203 | if (name != cp) | |
204 | { | |
205 | /* It is another netgroup name. */ | |
206 | int last = *cp == '\0'; | |
207 | ||
208 | result->type = group_val; | |
209 | result->val.group = name; | |
210 | *cp = '\0'; | |
211 | if (! last) | |
212 | ++cp; | |
213 | *cursor = cp; | |
214 | first = 0; | |
215 | ||
216 | return NSS_STATUS_SUCCESS; | |
217 | } | |
218 | ||
219 | return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; | |
220 | } | |
a68b0d31 UD |
221 | |
222 | /* Match host name. */ | |
223 | host = ++cp; | |
224 | while (*cp != ',') | |
225 | if (*cp++ == '\0') | |
226 | return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; | |
227 | ||
228 | /* Match user name. */ | |
229 | user = ++cp; | |
230 | while (*cp != ',') | |
231 | if (*cp++ == '\0') | |
232 | return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; | |
233 | ||
234 | /* Match domain name. */ | |
235 | domain = ++cp; | |
236 | while (*cp != ')') | |
237 | if (*cp++ == '\0') | |
238 | return first ? NSS_STATUS_NOTFOUND : NSS_STATUS_RETURN; | |
239 | ++cp; | |
240 | ||
241 | ||
242 | /* When we got here we have found an entry. Before we can copy it | |
243 | to the private buffer we have to make sure it is big enough. */ | |
244 | if (cp - host > buflen) | |
245 | { | |
246 | __set_errno (ERANGE); | |
247 | status = NSS_STATUS_UNAVAIL; | |
248 | } | |
249 | else | |
250 | { | |
251 | memcpy (buffer, host, cp - host); | |
11336c16 | 252 | result->type = triple_val; |
a68b0d31 UD |
253 | |
254 | buffer[(user - host) - 1] = '\0'; | |
11336c16 | 255 | result->val.triple.host = *host == ',' ? NULL : buffer; |
a68b0d31 UD |
256 | |
257 | buffer[(domain - host) - 1] = '\0'; | |
11336c16 | 258 | result->val.triple.user = *user == ',' ? NULL : buffer + (user - host); |
a68b0d31 UD |
259 | |
260 | buffer[(cp - host) - 1] = '\0'; | |
11336c16 UD |
261 | result->val.triple.domain = |
262 | *domain == ')' ? NULL : buffer + (domain - host); | |
a68b0d31 UD |
263 | |
264 | status = NSS_STATUS_SUCCESS; | |
265 | ||
266 | /* Rememember where we stopped reading. */ | |
267 | *cursor = cp; | |
268 | ||
269 | first = 0; | |
270 | } | |
271 | ||
272 | return status; | |
273 | } | |
274 | ||
275 | ||
276 | enum nss_status | |
277 | _nss_files_getnetgrent_r (struct __netgrent *result, char *buffer, int buflen) | |
278 | { | |
279 | enum nss_status status; | |
280 | ||
281 | __libc_lock_lock (lock); | |
282 | ||
283 | status = _nss_netgroup_parseline (&cursor, result, buffer, buflen); | |
284 | ||
285 | __libc_lock_unlock (lock); | |
286 | ||
287 | return status; | |
288 | } |