Include generated prototype for parser.
[kopensolaris-gnu/glibc.git] / nis / nss_nis / nis-service.c
1 /* Copyright (C) 1996, 1997, 1998 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1996.
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 <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>
28
29 #include "nss-nis.h"
30
31
32 /* Get the declaration of the parser function.  */
33 #define ENTNAME servent
34 #define EXTERN_PARSER
35 #include <nss/nss_files/files-parse.c>
36
37 __libc_lock_define_initialized (static, lock)
38
39 struct response_t
40 {
41   char *val;
42   struct response_t *next;
43 };
44
45 struct intern_t
46 {
47   struct response_t *start;
48   struct response_t *next;
49 };
50 typedef struct intern_t intern_t;
51
52 static intern_t intern = { NULL, NULL };
53
54 static int
55 saveit (int instatus, char *inkey, int inkeylen, char *inval,
56         int invallen, char *indata)
57 {
58   intern_t *intern = (intern_t *) indata;
59
60   if (instatus != YP_TRUE)
61     return instatus;
62
63   if (inkey && inkeylen > 0 && inval && invallen > 0)
64     {
65       if (intern->start == NULL)
66         {
67           intern->start = malloc (sizeof (struct response_t));
68           intern->next = intern->start;
69         }
70       else
71         {
72           intern->next->next = malloc (sizeof (struct response_t));
73           intern->next = intern->next->next;
74         }
75       intern->next->next = NULL;
76       intern->next->val = malloc (invallen + 1);
77       strncpy (intern->next->val, inval, invallen);
78       intern->next->val[invallen] = '\0';
79     }
80
81   return 0;
82 }
83
84 static enum nss_status
85 internal_nis_setservent (intern_t *intern)
86 {
87   char *domainname;
88   struct ypall_callback ypcb;
89   enum nss_status status;
90
91   if (yp_get_default_domain (&domainname))
92     return NSS_STATUS_UNAVAIL;
93
94   while (intern->start != NULL)
95     {
96       if (intern->start->val != NULL)
97         free (intern->start->val);
98       intern->next = intern->start;
99       intern->start = intern->start->next;
100       free (intern->next);
101     }
102   intern->start = NULL;
103
104   ypcb.foreach = saveit;
105   ypcb.data = (char *) intern;
106   status = yperr2nss (yp_all (domainname, "services.byname", &ypcb));
107   intern->next = intern->start;
108
109   return status;
110 }
111 enum nss_status
112 _nss_nis_setservent (void)
113 {
114   enum nss_status status;
115
116   __libc_lock_lock (lock);
117
118   status = internal_nis_setservent (&intern);
119
120   __libc_lock_unlock (lock);
121
122   return status;
123 }
124
125 static enum nss_status
126 internal_nis_endservent (intern_t * intern)
127 {
128   while (intern->start != NULL)
129     {
130       if (intern->start->val != NULL)
131         free (intern->start->val);
132       intern->next = intern->start;
133       intern->start = intern->start->next;
134       free (intern->next);
135     }
136   intern->start = NULL;
137
138   return NSS_STATUS_SUCCESS;
139 }
140
141 enum nss_status
142 _nss_nis_endservent (void)
143 {
144   enum nss_status status;
145
146   __libc_lock_lock (lock);
147
148   status = internal_nis_endservent (&intern);
149
150   __libc_lock_unlock (lock);
151
152   return status;
153 }
154
155 static enum nss_status
156 internal_nis_getservent_r (struct servent *serv, char *buffer,
157                            size_t buflen, int *errnop, intern_t *data)
158 {
159   struct parser_data *pdata = (void *) buffer;
160   int parse_res;
161   char *p;
162
163   if (data->start == NULL)
164     internal_nis_setservent (data);
165
166   /* Get the next entry until we found a correct one. */
167   do
168     {
169       if (data->next == NULL)
170         {
171           *errnop = ENOENT;
172           return NSS_STATUS_NOTFOUND;
173         }
174       p = strncpy (buffer, data->next->val, buflen);
175            while (isspace (*p))
176         ++p;
177
178       parse_res = _nss_files_parse_servent (p, serv, pdata, buflen, errnop);
179       if (parse_res == -1)
180         return NSS_STATUS_TRYAGAIN;
181       data->next = data->next->next;
182     }
183   while (!parse_res);
184
185   return NSS_STATUS_SUCCESS;
186 }
187
188 enum nss_status
189 _nss_nis_getservent_r (struct servent *serv, char *buffer, size_t buflen,
190                        int *errnop)
191 {
192   enum nss_status status;
193
194   __libc_lock_lock (lock);
195
196   status = internal_nis_getservent_r (serv, buffer, buflen, errnop, &intern);
197
198   __libc_lock_unlock (lock);
199
200   return status;
201 }
202
203 enum nss_status
204 _nss_nis_getservbyname_r (const char *name, char *protocol,
205                           struct servent *serv, char *buffer, size_t buflen,
206                           int *errnop)
207 {
208   intern_t data = { NULL, NULL };
209   enum nss_status status;
210   int found;
211
212   if (name == NULL)
213     {
214       *errnop = EINVAL;
215       return NSS_STATUS_UNAVAIL;
216     }
217
218   status = internal_nis_setservent (&data);
219   if (status != NSS_STATUS_SUCCESS)
220     return status;
221
222   found = 0;
223   while (!found &&
224          ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
225                                                &data)) == NSS_STATUS_SUCCESS))
226     {
227       if (protocol == NULL || strcmp (serv->s_proto, protocol) == 0)
228         {
229           char **cp;
230
231           if (strcmp (serv->s_name, name) == 0)
232             found = 1;
233           else
234             for (cp = serv->s_aliases; *cp; cp++)
235               if (strcmp (name, *cp) == 0)
236                 found = 1;
237         }
238     }
239
240   internal_nis_endservent (&data);
241
242   if (!found && status == NSS_STATUS_SUCCESS)
243     {
244       *errnop = ENOENT;
245       return NSS_STATUS_NOTFOUND;
246     }
247   else
248     return status;
249 }
250
251 enum nss_status
252 _nss_nis_getservbyport_r (int port, char *protocol, struct servent *serv,
253                           char *buffer, size_t buflen, int *errnop)
254 {
255   intern_t data = { NULL, NULL };
256   enum nss_status status;
257   int found;
258
259   if (protocol == NULL)
260     {
261       *errnop = EINVAL;
262       return NSS_STATUS_UNAVAIL;
263     }
264
265   status = internal_nis_setservent (&data);
266   if (status != NSS_STATUS_SUCCESS)
267     return status;
268
269   found = 0;
270   while (!found &&
271          ((status = internal_nis_getservent_r (serv, buffer, buflen, errnop,
272                                                &data)) == NSS_STATUS_SUCCESS))
273     if (htons (serv->s_port) == port
274         &&  strcmp (serv->s_proto, protocol) == 0)
275       found = 1;
276
277   internal_nis_endservent (&data);
278
279   if (!found && status == NSS_STATUS_SUCCESS)
280     {
281       *errnop = ENOENT;
282       return NSS_STATUS_NOTFOUND;
283     }
284   else
285     return status;
286 }