* sysdeps/ia64/fpu/e_logl.c: File removed.
[glibc.git] / nis / nss_nis / nis-service.c
blob1e879d04e350ab62dbb13b1cbbb432224d07ed04
1 /* Copyright (C) 1996-2001, 2002, 2003, 2004 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 Lesser General Public
7 License as published by the Free Software Foundation; either
8 version 2.1 of the 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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
18 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 struct response_t *next;
42 char val[0];
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 struct search_t
56 const char *name;
57 const char *proto;
58 int port;
59 enum nss_status status;
60 struct servent *serv;
61 char *buffer;
62 size_t buflen;
63 int *errnop;
66 static int
67 saveit (int instatus, char *inkey, int inkeylen, char *inval,
68 int invallen, char *indata)
70 intern_t *intern = (intern_t *) indata;
72 if (instatus != YP_TRUE)
73 return 1;
75 if (inkey && inkeylen > 0 && inval && invallen > 0)
77 struct response_t *newp = malloc (sizeof (struct response_t)
78 + invallen + 1);
79 if (newp == NULL)
80 return 1; /* We have no error code for out of memory */
82 if (intern->start == NULL)
83 intern->start = newp;
84 else
85 intern->next->next = newp;
86 intern->next = newp;
88 newp->next = NULL;
89 *((char *) mempcpy (newp->val, inval, invallen)) = '\0';
92 return 0;
95 static int
96 dosearch (int instatus, char *inkey, int inkeylen, char *inval,
97 int invallen, char *indata)
99 struct search_t *req = (struct search_t *) indata;
101 if (instatus != YP_TRUE)
102 return 1;
104 if (inkey && inkeylen > 0 && inval && invallen > 0)
106 struct parser_data *pdata = (void *) req->buffer;
107 int parse_res;
108 char *p;
110 if ((size_t) (invallen + 1) > req->buflen)
112 *req->errnop = ERANGE;
113 req->status = NSS_STATUS_TRYAGAIN;
114 return 1;
117 p = strncpy (req->buffer, inval, invallen);
118 req->buffer[invallen] = '\0';
119 while (isspace (*p))
120 ++p;
122 parse_res = _nss_files_parse_servent (p, req->serv, pdata, req->buflen,
123 req->errnop);
124 if (parse_res == -1)
126 req->status = NSS_STATUS_TRYAGAIN;
127 return 1;
130 if (!parse_res)
131 return 0;
133 if (req->proto != NULL && strcmp (req->serv->s_proto, req->proto) != 0)
134 return 0;
136 if (req->port != -1 && req->serv->s_port != req->port)
137 return 0;
139 if (req->name != NULL && strcmp (req->serv->s_name, req->name) != 0)
141 char **cp;
142 for (cp = req->serv->s_aliases; *cp; cp++)
143 if (strcmp (req->name, *cp) == 0)
144 break;
146 if (*cp == NULL)
147 return 0;
150 req->status = NSS_STATUS_SUCCESS;
151 return 1;
154 return 0;
157 static enum nss_status
158 internal_nis_endservent (intern_t * intern)
160 while (intern->start != NULL)
162 intern->next = intern->start;
163 intern->start = intern->start->next;
164 free (intern->next);
167 return NSS_STATUS_SUCCESS;
170 enum nss_status
171 _nss_nis_endservent (void)
173 enum nss_status status;
175 __libc_lock_lock (lock);
177 status = internal_nis_endservent (&intern);
179 __libc_lock_unlock (lock);
181 return status;
184 static enum nss_status
185 internal_nis_setservent (intern_t *intern)
187 char *domainname;
188 struct ypall_callback ypcb;
189 enum nss_status status;
191 if (yp_get_default_domain (&domainname))
192 return NSS_STATUS_UNAVAIL;
194 (void) internal_nis_endservent (intern);
196 ypcb.foreach = saveit;
197 ypcb.data = (char *) intern;
198 status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
199 intern->next = intern->start;
201 return status;
204 enum nss_status
205 _nss_nis_setservent (int stayopen)
207 enum nss_status status;
209 __libc_lock_lock (lock);
211 status = internal_nis_setservent (&intern);
213 __libc_lock_unlock (lock);
215 return status;
218 static enum nss_status
219 internal_nis_getservent_r (struct servent *serv, char *buffer,
220 size_t buflen, int *errnop, intern_t *data)
222 struct parser_data *pdata = (void *) buffer;
223 int parse_res;
224 char *p;
226 if (data->start == NULL)
227 internal_nis_setservent (data);
229 /* Get the next entry until we found a correct one. */
232 if (data->next == NULL)
233 return NSS_STATUS_NOTFOUND;
235 p = strncpy (buffer, data->next->val, buflen);
236 while (isspace (*p))
237 ++p;
239 parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
240 if (parse_res == -1)
241 return NSS_STATUS_TRYAGAIN;
242 data->next = data->next->next;
244 while (!parse_res);
246 return NSS_STATUS_SUCCESS;
249 enum nss_status
250 _nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
251 int *errnop)
253 enum nss_status status;
255 __libc_lock_lock (lock);
257 status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
259 __libc_lock_unlock (lock);
261 return status;
264 enum nss_status
265 _nss_nis_getservbyname_r (const char *name, const char *protocol,
266 struct servent *serv, char *buffer, size_t buflen,
267 int *errnop)
269 enum nss_status status;
270 char *domain;
272 if (name == NULL)
274 *errnop = EINVAL;
275 return NSS_STATUS_UNAVAIL;
278 if (yp_get_default_domain (&domain))
279 return NSS_STATUS_UNAVAIL;
281 /* If the protocol is given, we could try if our NIS server knows
282 about services.byservicename map. If yes, we only need one query. */
283 char key[strlen (name) + (protocol ? strlen (protocol) : 0) + 2];
284 char *cp, *result;
285 size_t keylen, len;
286 int int_len;
288 /* key is: "name/proto" */
289 cp = stpcpy (key, name);
290 if (protocol)
292 *cp++ = '/';
293 strcpy (cp, protocol);
295 keylen = strlen (key);
296 status = yperr2nss (yp_match (domain, "services.byservicename", key,
297 keylen, &result, &int_len));
298 len = int_len;
300 /* If we found the key, it's ok and parse the result. If not,
301 fall through and parse the complete table. */
302 if (status == NSS_STATUS_SUCCESS)
304 struct parser_data *pdata = (void *) buffer;
305 int parse_res;
306 char *p;
308 if ((size_t) (len + 1) > buflen)
310 free (result);
311 *errnop = ERANGE;
312 return NSS_STATUS_TRYAGAIN;
315 p = strncpy (buffer, result, len);
316 buffer[len] = '\0';
317 while (isspace (*p))
318 ++p;
319 free (result);
320 parse_res = _nss_files_parse_servent (p, serv, pdata,
321 buflen, errnop);
322 if (parse_res < 0)
324 if (parse_res == -1)
325 return NSS_STATUS_TRYAGAIN;
326 else
327 return NSS_STATUS_NOTFOUND;
329 else
330 return NSS_STATUS_SUCCESS;
333 /* Check if it is safe to rely on services.byservicename. */
334 if (_nis_default_nss () & NSS_FLAG_SERVICES_AUTHORITATIVE)
335 return status;
337 struct ypall_callback ypcb;
338 struct search_t req;
340 ypcb.foreach = dosearch;
341 ypcb.data = (char *) &req;
342 req.name = name;
343 req.proto = protocol;
344 req.port = -1;
345 req.serv = serv;
346 req.buffer = buffer;
347 req.buflen = buflen;
348 req.errnop = errnop;
349 req.status = NSS_STATUS_NOTFOUND;
350 status = yperr2nss (yp_all (domain, "services.byname", &ypcb));
352 if (status != NSS_STATUS_SUCCESS)
353 return status;
355 return req.status;
358 enum nss_status
359 _nss_nis_getservbyport_r (int port, const char *protocol,
360 struct servent *serv, char *buffer,
361 size_t buflen, int *errnop)
363 enum nss_status status;
364 char *domain;
366 if (yp_get_default_domain (&domain))
367 return NSS_STATUS_UNAVAIL;
369 /* If the protocol is given, we only need one query.
370 Otherwise try first port/tcp, then port/udp and then fallback
371 to sequential scanning of services.byname. */
372 const char *proto = protocol != NULL ? protocol : "tcp";
375 char key[sizeof (int) * 3 + strlen (proto) + 2];
376 char *result;
377 size_t keylen, len;
378 int int_len;
380 /* key is: "port/proto" */
381 keylen = snprintf (key, sizeof (key), "%d/%s", ntohs (port), proto);
382 status = yperr2nss (yp_match (domain, "services.byname", key,
383 keylen, &result, &int_len));
384 len = int_len;
386 /* If we found the key, it's ok and parse the result. If not,
387 fall through and parse the complete table. */
388 if (status == NSS_STATUS_SUCCESS)
390 struct parser_data *pdata = (void *) buffer;
391 int parse_res;
392 char *p;
394 if ((size_t) (len + 1) > buflen)
396 free (result);
397 *errnop = ERANGE;
398 return NSS_STATUS_TRYAGAIN;
401 p = strncpy (buffer, result, len);
402 buffer[len] = '\0';
403 while (isspace (*p))
404 ++p;
405 free (result);
406 parse_res = _nss_files_parse_servent (p, serv, pdata,
407 buflen, errnop);
408 if (parse_res < 0)
410 if (parse_res == -1)
411 return NSS_STATUS_TRYAGAIN;
412 else
413 return NSS_STATUS_NOTFOUND;
415 else
416 return NSS_STATUS_SUCCESS;
419 while (protocol == NULL && (proto[0] == 't' ? (proto = "udp") : NULL));
421 if (port == -1)
422 return NSS_STATUS_NOTFOUND;
424 struct ypall_callback ypcb;
425 struct search_t req;
427 ypcb.foreach = dosearch;
428 ypcb.data = (char *) &req;
429 req.name = NULL;
430 req.proto = protocol;
431 req.port = port;
432 req.serv = serv;
433 req.buffer = buffer;
434 req.buflen = buflen;
435 req.errnop = errnop;
436 req.status = NSS_STATUS_NOTFOUND;
437 status = yperr2nss (yp_all (domain, "services.byname", &ypcb));
439 if (status != NSS_STATUS_SUCCESS)
440 return status;
442 return req.status;