* sysdeps/m68k/bits/byteswap.h (__bswap_32): Add cast to avoid
[glibc/pb-stable.git] / nis / nss_nis / nis-service.c
blobea1e06eab38e60f9fe4f13dc4f6ad1e6d7638873
1 /* Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Thorsten Kukuk <kukuk@suse.de>, 1996.
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 <netdb.h>
22 #include <ctype.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
29 #include "nss-nis.h"
32 /* Get the declaration of the parser function. */
33 #define ENTNAME servent
34 #define EXTERN_PARSER
35 #include <nss/nss_files/files-parse.c>
37 __libc_lock_define_initialized (static, lock)
39 struct response_t
41 char *val;
42 struct response_t *next;
45 struct intern_t
47 struct response_t *start;
48 struct response_t *next;
50 typedef struct intern_t intern_t;
52 static intern_t intern = { NULL, NULL };
54 static int
55 saveit (int instatus, char *inkey, int inkeylen, char *inval,
56 int invallen, char *indata)
58 intern_t *intern = (intern_t *) indata;
60 if (instatus != YP_TRUE)
61 return instatus;
63 if (inkey && inkeylen > 0 && inval && invallen > 0)
65 if (intern->start == NULL)
67 intern->start = malloc (sizeof (struct response_t));
68 if (intern->start == NULL)
69 return YP_FALSE; /* We have no error code for out of memory */
70 intern->next = intern->start;
72 else
74 intern->next->next = malloc (sizeof (struct response_t));
75 if (intern->next->next == NULL)
76 return YP_FALSE; /* We have no error code for out of memory */
77 intern->next = intern->next->next;
79 intern->next->next = NULL;
80 intern->next->val = malloc (invallen + 1);
81 if (intern->next->val == NULL)
82 return YP_FALSE; /* We have no error code for out of memory */
83 strncpy (intern->next->val, inval, invallen);
84 intern->next->val[invallen] = '\0';
87 return 0;
90 static enum nss_status
91 internal_nis_setservent (intern_t *intern)
93 char *domainname;
94 struct ypall_callback ypcb;
95 enum nss_status status;
97 if (yp_get_default_domain (&domainname))
98 return NSS_STATUS_UNAVAIL;
100 while (intern->start != NULL)
102 if (intern->start->val != NULL)
103 free (intern->start->val);
104 intern->next = intern->start;
105 intern->start = intern->start->next;
106 free (intern->next);
108 intern->start = NULL;
110 ypcb.foreach = saveit;
111 ypcb.data = (char *) intern;
112 status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
113 intern->next = intern->start;
115 return status;
117 enum nss_status
118 _nss_nis_setservent (int stayopen)
120 enum nss_status status;
122 __libc_lock_lock (lock);
124 status = internal_nis_setservent (&intern);
126 __libc_lock_unlock (lock);
128 return status;
131 static enum nss_status
132 internal_nis_endservent (intern_t * intern)
134 while (intern->start != NULL)
136 if (intern->start->val != NULL)
137 free (intern->start->val);
138 intern->next = intern->start;
139 intern->start = intern->start->next;
140 free (intern->next);
142 intern->start = NULL;
144 return NSS_STATUS_SUCCESS;
147 enum nss_status
148 _nss_nis_endservent (void)
150 enum nss_status status;
152 __libc_lock_lock (lock);
154 status = internal_nis_endservent (&intern);
156 __libc_lock_unlock (lock);
158 return status;
161 static enum nss_status
162 internal_nis_getservent_r (struct servent *serv, char *buffer,
163 size_t buflen, int *errnop, intern_t *data)
165 struct parser_data *pdata = (void *) buffer;
166 int parse_res;
167 char *p;
169 if (data->start == NULL)
170 internal_nis_setservent (data);
172 /* Get the next entry until we found a correct one. */
175 if (data->next == NULL)
177 *errnop = ENOENT;
178 return NSS_STATUS_NOTFOUND;
180 p = strncpy (buffer, data->next->val, buflen);
181 while (isspace (*p))
182 ++p;
184 parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
185 if (parse_res == -1)
186 return NSS_STATUS_TRYAGAIN;
187 data->next = data->next->next;
189 while (!parse_res);
191 return NSS_STATUS_SUCCESS;
194 enum nss_status
195 _nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
196 int *errnop)
198 enum nss_status status;
200 __libc_lock_lock (lock);
202 status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
204 __libc_lock_unlock (lock);
206 return status;
209 enum nss_status
210 _nss_nis_getservbyname_r (const char *name, const char *protocol,
211 struct servent *serv, char *buffer, size_t buflen,
212 int *errnop)
214 intern_t data = { NULL, NULL };
215 enum nss_status status;
216 int found;
218 if (name == NULL)
220 *errnop = EINVAL;
221 return NSS_STATUS_UNAVAIL;
224 /* If the protocol is given, we could try if our NIS server knows
225 about services.byservicename map. If yes, we only need one query */
226 if (protocol != NULL)
228 char key[strlen (name) + strlen (protocol) + 2];
229 char *cp, *domain, *result;
230 size_t keylen, len;
232 /* If this fails, the other solution will also fail. */
233 if (yp_get_default_domain (&domain))
234 return NSS_STATUS_UNAVAIL;
236 /* key is: "name/protocol" */
237 cp = stpcpy (key, name);
238 *cp++ = '/';
239 stpcpy (cp, protocol);
240 keylen = strlen (key);
241 status = yperr2nss (yp_match (domain, "services.byservicename", key,
242 keylen, &result, &len));
244 /* If we found the key, it's ok and parse the result. If not,
245 fall through and parse the complete table. */
246 if (status == NSS_STATUS_SUCCESS)
248 struct parser_data *pdata = (void *) buffer;
249 int parse_res;
250 char *p;
252 if ((size_t) (len + 1) > buflen)
254 free (result);
255 *errnop = ERANGE;
256 return NSS_STATUS_TRYAGAIN;
259 p = strncpy (buffer, result, len);
260 buffer[len] = '\0';
261 while (isspace (*p))
262 ++p;
263 free (result);
264 parse_res = _nss_files_parse_servent (p, serv, pdata,
265 buflen, errnop);
266 if (parse_res < 0)
268 if (parse_res == -1)
269 return NSS_STATUS_TRYAGAIN;
270 else
272 *errnop = ENOENT;
273 return NSS_STATUS_NOTFOUND;
276 else
277 return NSS_STATUS_SUCCESS;
281 status = internal_nis_setservent (&data);
282 if (status != NSS_STATUS_SUCCESS)
283 return status;
285 found = 0;
286 while (!found &&
287 ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
288 &data)) == NSS_STATUS_SUCCESS))
290 if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)
292 char **cp;
294 if (strcmp (serv->s_name, name) == 0)
295 found = 1;
296 else
297 for (cp = serv->s_aliases; *cp; cp++)
298 if (strcmp (name, *cp) == 0)
299 found = 1;
303 internal_nis_endservent (&data);
305 if (!found && status == NSS_STATUS_SUCCESS)
307 *errnop = ENOENT;
308 return NSS_STATUS_NOTFOUND;
310 else
311 return status;
314 enum nss_status
315 _nss_nis_getservbyport_r (int port, const char *protocol,
316 struct servent *serv, char *buffer,
317 size_t buflen, int *errnop)
319 intern_t data = { NULL, NULL };
320 enum nss_status status;
321 int found;
323 /* If the protocol is given, we only need one query */
324 if (protocol != NULL)
326 char key[100 + strlen (protocol) + 2];
327 char *domain, *result;
328 size_t keylen, len;
329 int int_len;
331 /* If this fails, the other solution will also fail. */
332 if (yp_get_default_domain (&domain))
333 return NSS_STATUS_UNAVAIL;
335 /* key is: "port/protocol" */
336 keylen = snprintf (key, sizeof (key), "%d/%s", port, protocol);
337 status = yperr2nss (yp_match (domain, "services.byname", key,
338 keylen, &result, &int_len));
339 len = int_len;
341 /* If we found the key, it's ok and parse the result. If not,
342 fall through and parse the complete table. */
343 if (status == NSS_STATUS_SUCCESS)
345 struct parser_data *pdata = (void *) buffer;
346 int parse_res;
347 char *p;
349 if ((size_t) (len + 1) > buflen)
351 free (result);
352 *errnop = ERANGE;
353 return NSS_STATUS_TRYAGAIN;
356 p = strncpy (buffer, result, len);
357 buffer[len] = '\0';
358 while (isspace (*p))
359 ++p;
360 free (result);
361 parse_res = _nss_files_parse_servent (p, serv, pdata,
362 buflen, errnop);
363 if (parse_res < 0)
365 if (parse_res == -1)
366 return NSS_STATUS_TRYAGAIN;
367 else
369 *errnop = ENOENT;
370 return NSS_STATUS_NOTFOUND;
373 else
374 return NSS_STATUS_SUCCESS;
378 status = internal_nis_setservent (&data);
379 if (status != NSS_STATUS_SUCCESS)
380 return status;
382 found = 0;
383 while (!found &&
384 ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
385 &data)) == NSS_STATUS_SUCCESS))
386 if (serv->s_port == port &&
387 (protocol == NULL || strcmp (serv->s_proto, protocol) == 0))
388 found = 1;
390 internal_nis_endservent (&data);
392 if (!found && status == NSS_STATUS_SUCCESS)
394 *errnop = ENOENT;
395 return NSS_STATUS_NOTFOUND;
397 else
398 return status;