source: trunk/libs/newlib/src/newlib/libc/sys/linux/net/getnssent_r.c

Last change on this file was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 5.8 KB
Line 
1/* Copyright (C) 2000, 2002, 2004 Free Software Foundation, Inc.
2   This file is part of the GNU C Library.
3
4   The GNU C Library is free software; you can redistribute it and/or
5   modify it under the terms of the GNU Lesser General Public
6   License as published by the Free Software Foundation; either
7   version 2.1 of the License, or (at your option) any later version.
8
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   Lesser General Public License for more details.
13
14   You should have received a copy of the GNU Lesser General Public
15   License along with the GNU C Library; if not, write to the Free
16   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
17   02111-1307 USA.  */
18
19#include <errno.h>
20#include <netdb.h>
21#include "nsswitch.h"
22
23/* Set up NIP to run through the services.  If ALL is zero, use NIP's
24   current location if it's not nil.  Return nonzero if there are no
25   services (left).  */
26static int
27setup (const char *func_name, db_lookup_function lookup_fct,
28       void **fctp, service_user **nip, service_user **startp, int all)
29{
30  int no_more;
31  if (*startp == NULL)
32    {
33      no_more = lookup_fct (nip, func_name, fctp);
34      *startp = no_more ? (service_user *) -1l : *nip;
35    }
36  else if (*startp == (service_user *) -1l)
37    /* No services at all.  */
38    return 1;
39  else
40    {
41      if (all || !*nip)
42        /* Reset to the beginning of the service list.  */
43        *nip = *startp;
44      /* Look up the first function.  */
45      no_more = __nss_lookup (nip, func_name, fctp);
46    }
47  return no_more;
48}
49
50void
51__nss_setent (const char *func_name, db_lookup_function lookup_fct,
52              service_user **nip, service_user **startp,
53              service_user **last_nip, int stayopen, int *stayopen_tmp,
54              int res)
55{
56  union
57  {
58    setent_function f;
59    void *ptr;
60  } fct;
61  int no_more;
62
63  if (res && __res_maybe_init (&_res, 0) == -1)
64    {
65      h_errno = (NETDB_INTERNAL);
66      return;
67    }
68
69  /* Cycle through the services and run their `setXXent' functions until
70     we find an available service.  */
71  no_more = setup (func_name, lookup_fct, &fct.ptr, nip,
72                   startp, 1);
73  while (! no_more)
74    {
75      int is_last_nip = *nip == *last_nip;
76      enum nss_status status;
77
78      if (stayopen_tmp)
79        status = DL_CALL_FCT (fct.f, (*stayopen_tmp));
80      else
81        status = DL_CALL_FCT (fct.f, (0));
82
83      no_more = __nss_next (nip, func_name, &fct.ptr,
84                            status, 0);
85      if (is_last_nip)
86        *last_nip = *nip;
87    }
88
89  if (stayopen_tmp)
90    *stayopen_tmp = stayopen;
91}
92
93
94void
95__nss_endent (const char *func_name, db_lookup_function lookup_fct,
96              service_user **nip, service_user **startp,
97              service_user **last_nip, int res)
98{
99  union
100  {
101    endent_function f;
102    void *ptr;
103  } fct;
104  int no_more;
105
106  if (res && __res_maybe_init (&_res, 0) == -1)
107    {
108      h_errno = (NETDB_INTERNAL);
109      return;
110    }
111
112  /* Cycle through all the services and run their endXXent functions.  */
113  no_more = setup (func_name, lookup_fct, &fct.ptr, nip, startp, 1);
114  while (! no_more)
115    {
116      /* Ignore status, we force check in __NSS_NEXT.  */
117      DL_CALL_FCT (fct.f, ());
118
119      if (*nip == *last_nip)
120        /* We have processed all services which were used.  */
121        break;
122
123      no_more = __nss_next (nip, func_name, &fct.ptr, 0, 1);
124    }
125  *last_nip = *nip = NULL;
126}
127
128
129int
130__nss_getent_r (const char *getent_func_name,
131                const char *setent_func_name,
132                db_lookup_function lookup_fct,
133                service_user **nip, service_user **startp,
134                service_user **last_nip, int *stayopen_tmp, int res,
135                void *resbuf, char *buffer, size_t buflen,
136                void **result, int *h_errnop)
137{
138  union
139  {
140    getent_function f;
141    void *ptr;
142  } fct;
143  int no_more;
144  enum nss_status status;
145
146  if (res && __res_maybe_init (&_res, 0) == -1)
147    {
148      *h_errnop = NETDB_INTERNAL;
149      *result = NULL;
150      return errno;
151    }
152
153  /* Initialize status to return if no more functions are found.  */
154  status = NSS_STATUS_NOTFOUND;
155
156  /* Run through available functions, starting with the same function last
157     run.  We will repeat each function as long as it succeeds, and then go
158     on to the next service action.  */
159  no_more = setup (getent_func_name, lookup_fct, &fct.ptr, nip,
160                   startp, 0);
161  while (! no_more)
162    {
163      int is_last_nip = *nip == *last_nip;
164
165      status = DL_CALL_FCT (fct.f,
166                            (resbuf, buffer, buflen, &errno, &h_errno));
167
168      /* The the status is NSS_STATUS_TRYAGAIN and errno is ERANGE the
169         provided buffer is too small.  In this case we should give
170         the user the possibility to enlarge the buffer and we should
171         not simply go on with the next service (even if the TRYAGAIN
172         action tells us so).  */
173      if (status == NSS_STATUS_TRYAGAIN
174          && (h_errnop == NULL || *h_errnop == NETDB_INTERNAL)
175          && errno == ERANGE)
176        break;
177
178      do
179        {
180          no_more = __nss_next (nip, getent_func_name, &fct.ptr,
181                                status, 0);
182
183          if (is_last_nip)
184            *last_nip = *nip;
185
186          if (! no_more)
187            {
188              /* Call the `setXXent' function.  This wasn't done before.  */
189              union
190              {
191                setent_function f;
192                void *ptr;
193              } sfct;
194
195              no_more = __nss_lookup (nip, setent_func_name,
196                                      &sfct.ptr);
197
198              if (! no_more)
199                {
200                  if (stayopen_tmp)
201                    status = DL_CALL_FCT (sfct.f, (*stayopen_tmp));
202                  else
203                    status = DL_CALL_FCT (sfct.f, (0));
204                }
205              else
206                status = NSS_STATUS_NOTFOUND;
207            }
208        }
209      while (! no_more && status != NSS_STATUS_SUCCESS);
210    }
211
212  *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
213  return (status == NSS_STATUS_SUCCESS ? 0
214          : status != NSS_STATUS_TRYAGAIN ? ENOENT
215          /* h_errno functions only set errno if h_errno is NETDB_INTERNAL.  */
216          : (h_errnop == NULL || *h_errnop == NETDB_INTERNAL) ? errno
217          : EAGAIN);
218}
Note: See TracBrowser for help on using the repository browser.