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. */
25 #include <bits/libc-lock.h>
26 #include <rpcsvc/yp.h>
27 #include <rpcsvc/ypclnt.h>
32 /* Get the declaration of the parser function. */
33 #define ENTNAME servent
35 #include <nss/nss_files/files-parse.c>
37 __libc_lock_define_initialized (static, lock
)
42 struct response_t
*next
;
47 struct response_t
*start
;
48 struct response_t
*next
;
50 typedef struct intern_t intern_t
;
52 static intern_t intern
= { NULL
, NULL
};
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
)
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
;
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';
90 static enum nss_status
91 internal_nis_setservent (intern_t
*intern
)
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
;
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
;
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
);
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
;
142 intern
->start
= NULL
;
144 return NSS_STATUS_SUCCESS
;
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
);
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
;
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
)
178 return NSS_STATUS_NOTFOUND
;
180 p
= strncpy (buffer
, data
->next
->val
, buflen
);
184 parse_res
= _nss_files_parse_servent (p
, serv
, pdata
, buflen
, errnop
);
186 return NSS_STATUS_TRYAGAIN
;
187 data
->next
= data
->next
->next
;
191 return NSS_STATUS_SUCCESS
;
195 _nss_nis_getservent_r (struct servent
*serv
, char *buffer
, size_t buflen
,
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
);
210 _nss_nis_getservbyname_r (const char *name
, const char *protocol
,
211 struct servent
*serv
, char *buffer
, size_t buflen
,
214 intern_t data
= { NULL
, NULL
};
215 enum nss_status status
;
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
;
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
);
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
;
252 if ((size_t) (len
+ 1) > buflen
)
256 return NSS_STATUS_TRYAGAIN
;
259 p
= strncpy (buffer
, result
, len
);
264 parse_res
= _nss_files_parse_servent (p
, serv
, pdata
,
269 return NSS_STATUS_TRYAGAIN
;
273 return NSS_STATUS_NOTFOUND
;
277 return NSS_STATUS_SUCCESS
;
281 status
= internal_nis_setservent (&data
);
282 if (status
!= NSS_STATUS_SUCCESS
)
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)
294 if (strcmp (serv
->s_name
, name
) == 0)
297 for (cp
= serv
->s_aliases
; *cp
; cp
++)
298 if (strcmp (name
, *cp
) == 0)
303 internal_nis_endservent (&data
);
305 if (!found
&& status
== NSS_STATUS_SUCCESS
)
308 return NSS_STATUS_NOTFOUND
;
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
;
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
;
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
));
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
;
349 if ((size_t) (len
+ 1) > buflen
)
353 return NSS_STATUS_TRYAGAIN
;
356 p
= strncpy (buffer
, result
, len
);
361 parse_res
= _nss_files_parse_servent (p
, serv
, pdata
,
366 return NSS_STATUS_TRYAGAIN
;
370 return NSS_STATUS_NOTFOUND
;
374 return NSS_STATUS_SUCCESS
;
378 status
= internal_nis_setservent (&data
);
379 if (status
!= NSS_STATUS_SUCCESS
)
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))
390 internal_nis_endservent (&data
);
392 if (!found
&& status
== NSS_STATUS_SUCCESS
)
395 return NSS_STATUS_NOTFOUND
;