update from main archive 961001
[glibc.git] / inet / getnetgrent_r.c
blob52a90d055ce03fd073c1ce044309717705647d64
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If
16 not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
19 #include <libc-lock.h>
20 #include <netdb.h>
21 #include "netgroup.h"
22 #include "nsswitch.h"
25 /* Protect above variable against multiple uses at the same time. */
26 __libc_lock_define_initialized (static, lock)
28 /* This handle for the NSS data base is shared between all
29 set/get/endXXXent functions. */
30 static service_user *nip;
31 /* Remember the first service_entry, it's always the same. */
32 static service_user *startp;
35 /* The lookup function for the first entry of this service. */
36 extern int __nss_netgroup_lookup (service_user **nip, const char *name,
37 void **fctp);
39 /* Set up NIP to run through the services. If ALL is zero, use NIP's
40 current location if it's not nil. Return nonzero if there are no
41 services (left). */
42 static enum nss_status
43 setup (void **fctp, const char *func_name, int all)
45 int no_more;
46 if (startp == NULL)
48 no_more = __nss_netgroup_lookup (&nip, func_name, fctp);
49 startp = no_more ? (service_user *) -1 : nip;
51 else if (startp == (service_user *) -1)
52 /* No services at all. */
53 return 1;
54 else
56 if (all || !nip)
57 /* Reset to the beginning of the service list. */
58 nip = startp;
59 /* Look up the first function. */
60 no_more = __nss_lookup (&nip, func_name, fctp);
62 return no_more;
65 int
66 setnetgrent (const char *group)
68 enum nss_status (*fct) (const char *);
69 enum nss_status status = NSS_STATUS_UNAVAIL;
70 int no_more;
72 __libc_lock_lock (lock);
74 /* Cycle through all the services and run their setnetgrent functions. */
75 no_more = setup ((void **) &fct, "setnetgrent", 1);
76 while (! no_more)
78 /* Ignore status, we force check in __NSS_NEXT. */
79 status = (*fct) (group);
81 no_more = __nss_next (&nip, "setnetgrent", (void **) &fct, status, 0);
84 __libc_lock_unlock (lock);
86 return status == NSS_STATUS_SUCCESS;
90 void
91 endnetgrent (void)
93 service_user *old_nip;
94 enum nss_status (*fct) (void);
95 int no_more;
97 __libc_lock_lock (lock);
99 /* Remember which was the last used service. */
100 old_nip = nip;
102 /* Cycle through all the services and run their setnetgrent functions. */
103 no_more = setup ((void **) &fct, "endnetgrent", 1);
104 while (! no_more)
106 /* Ignore status, we force check in __NSS_NEXT. */
107 (void) (*fct) ();
109 no_more = (nip == old_nip
110 || __nss_next (&nip, "endnetgrent", (void **) &fct, 0, 1));
113 __libc_lock_unlock (lock);
118 __getnetgrent_r (char **hostp, char **userp, char **domainp,
119 char *buffer, int buflen)
121 enum nss_status (*fct) (struct __netgrent *, char *, int);
122 struct __netgrent result;
123 int no_more;
125 /* Initialize status to return if no more functions are found. */
126 enum nss_status status = NSS_STATUS_NOTFOUND;
128 __libc_lock_lock (lock);
130 /* Run through available functions, starting with the same function last
131 run. We will repeat each function as long as it succeeds, and then go
132 on to the next service action. */
133 no_more = setup ((void **) &fct, "getnetgrent_r", 0);
134 while (! no_more)
136 status = (*fct) (&result, buffer, buflen);
138 no_more = __nss_next (&nip, "getnetgrent_r", (void **) &fct, status, 0);
141 if (status == NSS_STATUS_SUCCESS)
143 *hostp = result.host;
144 *userp = result.user;
145 *domainp = result.domain;
148 __libc_lock_unlock (lock);
150 return status == NSS_STATUS_SUCCESS ? 1 : 0;
152 weak_alias (__getnetgrent_r, getnetgrent_r)
154 /* Test whether given (host,user,domain) triple is in NETGROUP. */
156 innetgr (const char *netgroup, const char *host, const char *user,
157 const char *domain)
159 int (*setfct) (const char *);
160 void (*endfct) (void);
161 int (*getfct) (struct __netgrent *, char *, int);
162 int result = 0;
163 int no_more;
165 __libc_lock_lock (lock);
167 /* Walk through the services until we found an answer or we shall
168 not work further. We can do some optimization here. Since all
169 services must provide the `setnetgrent' function we can do all
170 the work during one walk through the service list. */
171 no_more = setup ((void **) &setfct, "setnetgrent", 1);
172 while (! no_more)
174 enum nss_status status;
176 /* Open netgroup. */
177 status = (*setfct) (netgroup);
178 if (status == NSS_STATUS_SUCCESS
179 && __nss_lookup (&nip, "getnetgrent_r", (void **) &getfct) == 0)
181 char buffer[1024];
182 struct __netgrent entry;
184 while ((*getfct) (&entry, buffer, sizeof buffer)
185 == NSS_STATUS_SUCCESS)
187 if ((entry.host == NULL || host == NULL
188 || strcmp (entry.host, host) == 0)
189 && (entry.user == NULL || user == NULL
190 || strcmp (entry.user, user) == 0)
191 && (entry.domain == NULL || domain == NULL
192 || strcmp (entry.domain, domain) == 0))
194 result = 1;
195 break;
199 if (result != 0)
200 break;
202 /* If we found one service which does know the given
203 netgroup we don't try further. */
204 status = NSS_STATUS_RETURN;
207 /* Free all resources of the service. */
208 if (__nss_lookup (&nip, "endnetgrent", (void **) &endfct) == 0)
209 (*endfct) ();
211 /* Look for the next service. */
212 no_more = __nss_next (&nip, "setnetgrent", (void **) &setfct, status, 0);
215 __libc_lock_unlock (lock);
217 return result;