update from main archive 961116
[platform/upstream/glibc.git] / nss / getXXbyYY_r.c
1 /* Copyright (C) 1996 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3    Contributed by Ulrich Drepper <drepper@cygnus.com>, 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 "nsswitch.h"
21
22 /*******************************************************************\
23 |* Here we assume several symbols to be defined:                   *|
24 |*                                                                 *|
25 |* LOOKUP_TYPE   - the return type of the function                 *|
26 |*                                                                 *|
27 |* FUNCTION_NAME - name of the non-reentrant function              *|
28 |*                                                                 *|
29 |* DATABASE_NAME - name of the database the function accesses      *|
30 |*                 (e.g., host, services, ...)                     *|
31 |*                                                                 *|
32 |* ADD_PARAMS    - additional parameter, can vary in number        *|
33 |*                                                                 *|
34 |* ADD_VARIABLES - names of additional parameter                   *|
35 |*                                                                 *|
36 |* Optionally the following vars can be defined:                   *|
37 |*                                                                 *|
38 |* NEED_H_ERRNO  - an extra parameter will be passed to point to   *|
39 |*                 the global `h_errno' variable.                  *|
40 |*                                                                 *|
41 |* NEED__RES     - the global _res variable might be used so we    *|
42 |*                 will have to initialize it if necessary         *|
43 |*                                                                 *|
44 \*******************************************************************/
45
46 /* To make the real sources a bit prettier.  */
47 #define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
48 #define APPEND_R(name) APPEND_R1 (name)
49 #define APPEND_R1(name) name##_r
50 #define INTERNAL(name) INTERNAL1 (name)
51 #define INTERNAL1(name) __##name
52
53 #define FUNCTION_NAME_STRING STRINGIZE (FUNCTION_NAME)
54 #define REENTRANT_NAME_STRING STRINGIZE (REENTRANT_NAME)
55 #define DATABASE_NAME_STRING STRINGIZE (DATABASE_NAME)
56 #define STRINGIZE(name) STRINGIZE1 (name)
57 #define STRINGIZE1(name) #name
58
59 #define DB_LOOKUP_FCT CONCAT3_1 (__nss_, DATABASE_NAME, _lookup)
60 #define CONCAT3_1(Pre, Name, Post) CONCAT3_2 (Pre, Name, Post)
61 #define CONCAT3_2(Pre, Name, Post) Pre##Name##Post
62
63 /* Sometimes we need to store error codes in the `h_errno' variable.  */
64 #ifdef NEED_H_ERRNO
65 # define H_ERRNO_PARM , int *h_errnop
66 # define H_ERRNO_VAR , h_errnop
67 #else
68 # define H_ERRNO_PARM
69 # define H_ERRNO_VAR
70 #endif
71
72
73 /* Type of the lookup function we need here.  */
74 typedef int (*lookup_function) (ADD_PARAMS, LOOKUP_TYPE *, char *, size_t
75                                 H_ERRNO_PARM);
76
77 /* Some usages of this file might use this variable.  */
78 extern struct __res_state _res;
79
80 /* The lookup function for the first entry of this service.  */
81 extern int DB_LOOKUP_FCT (service_user **nip, const char *name, void **fctp);
82
83
84
85 int
86 INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
87                            size_t buflen, LOOKUP_TYPE **result H_ERRNO_PARM)
88 {
89   static service_user *startp = NULL;
90   static lookup_function start_fct;
91   service_user *nip;
92   lookup_function fct;
93   int no_more;
94   enum nss_status status = NSS_STATUS_UNAVAIL;
95
96   if (startp == NULL)
97     {
98       no_more = DB_LOOKUP_FCT (&nip, REENTRANT_NAME_STRING, (void **) &fct);
99       if (no_more)
100         startp = (service_user *) -1;
101       else
102         {
103           startp = nip;
104           start_fct = fct;
105
106 #ifdef NEED__RES
107           /* The resolver code will really be used so we have to
108              initialize it.  */
109           if ((_res.options & RES_INIT) == 0 && res_init () == -1)
110             {
111               *h_errnop = NETDB_INTERNAL;
112               *result = NULL;
113               return -1;
114             }
115 #endif /* need _res */
116         }
117     }
118   else
119     {
120       fct = start_fct;
121       no_more = (nip = startp) == (service_user *) -1;
122     }
123
124   while (no_more == 0)
125     {
126       status = (*fct) (ADD_VARIABLES, resbuf, buffer, buflen H_ERRNO_VAR);
127
128       no_more = __nss_next (&nip, REENTRANT_NAME_STRING,
129                             (void **) &fct, status, 0);
130     }
131
132   *result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
133   return status == NSS_STATUS_SUCCESS ? 0 : -1;
134 }
135
136 #define do_weak_alias(n1, n2) weak_alias ((n1), (n2))
137 do_weak_alias (INTERNAL (REENTRANT_NAME), REENTRANT_NAME)