]> andersk Git - nss_nonlocal.git/blob - nonlocal-shadow.c
glibc uses regparms for internal functions on i386.
[nss_nonlocal.git] / nonlocal-shadow.c
1 /*
2  * nonlocal-shadow.c
3  * shadow database for nss_nonlocal proxy.
4  *
5  * Copyright © 2007 Anders Kaseorg <andersk@mit.edu>
6  *
7  * Permission is hereby granted, free of charge, to any person
8  * obtaining a copy of this software and associated documentation
9  * files (the "Software"), to deal in the Software without
10  * restriction, including without limitation the rights to use, copy,
11  * modify, merge, publish, distribute, sublicense, and/or sell copies
12  * of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be
16  * included in all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27
28 #define _GNU_SOURCE
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <stdlib.h>
32 #include <stdint.h>
33 #include <string.h>
34 #include <dlfcn.h>
35 #include <stdio.h>
36 #include <errno.h>
37 #include <shadow.h>
38 #include <nss.h>
39
40 #include "nsswitch-internal.h"
41 #include "nonlocal.h"
42
43
44 static service_user *
45 nss_shadow_nonlocal_database(void)
46 {
47     static service_user *nip = NULL;
48     if (nip == NULL)
49         __nss_database_lookup("shadow_nonlocal", NULL, "", &nip);
50
51     return nip;
52 }
53
54
55 static service_user *spent_nip = NULL;
56 static void *spent_fct_start;
57 static union {
58     enum nss_status (*l)(struct spwd *pwd, char *buffer, size_t buflen,
59                          int *errnop);
60     void *ptr;
61 } spent_fct;
62 static const char *spent_fct_name = "getspent_r";
63
64 enum nss_status
65 _nss_nonlocal_setspent(int stayopen)
66 {
67     static const char *fct_name = "setspent";
68     static void *fct_start = NULL;
69     enum nss_status status;
70     service_user *nip;
71     union {
72         enum nss_status (*l)(int stayopen);
73         void *ptr;
74     } fct;
75
76     nip = nss_shadow_nonlocal_database();
77     if (nip == NULL)
78         return NSS_STATUS_UNAVAIL;
79     if (fct_start == NULL)
80         fct_start = __nss_lookup_function(nip, fct_name);
81     fct.ptr = fct_start;
82     do {
83         if (fct.ptr == NULL)
84             status = NSS_STATUS_UNAVAIL;
85         else
86             status = DL_CALL_FCT(fct.l, (stayopen));
87     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
88     if (status != NSS_STATUS_SUCCESS)
89         return status;
90
91     spent_nip = nip;
92     if (spent_fct_start == NULL)
93         spent_fct_start = __nss_lookup_function(nip, spent_fct_name);
94     spent_fct.ptr = spent_fct_start;
95     return NSS_STATUS_SUCCESS;
96 }
97
98 enum nss_status
99 _nss_nonlocal_endspent(void)
100 {
101     static const char *fct_name = "endspent";
102     static void *fct_start = NULL;
103     enum nss_status status;
104     service_user *nip;
105     union {
106         enum nss_status (*l)(void);
107         void *ptr;
108     } fct;
109
110     spent_nip = NULL;
111
112     nip = nss_shadow_nonlocal_database();
113     if (nip == NULL)
114         return NSS_STATUS_UNAVAIL;
115     if (fct_start == NULL)
116         fct_start = __nss_lookup_function(nip, fct_name);
117     fct.ptr = fct_start;
118     do {
119         if (fct.ptr == NULL)
120             status = NSS_STATUS_UNAVAIL;
121         else
122             status = DL_CALL_FCT(fct.l, ());
123     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
124     return status;
125 }
126
127 enum nss_status
128 _nss_nonlocal_getspent_r(struct spwd *pwd, char *buffer, size_t buflen,
129                          int *errnop)
130 {
131     enum nss_status status;
132     if (spent_nip == NULL) {
133         status = _nss_nonlocal_setspent(0);
134         if (status != NSS_STATUS_SUCCESS)
135             return status;
136     }
137     do {
138         if (spent_fct.ptr == NULL)
139             status = NSS_STATUS_UNAVAIL;
140         else
141             status = DL_CALL_FCT(spent_fct.l, (pwd, buffer, buflen, errnop));   
142         if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
143             return status;
144
145         if (status == NSS_STATUS_SUCCESS)
146             return NSS_STATUS_SUCCESS;
147     } while (__nss_next(&spent_nip, spent_fct_name, &spent_fct.ptr, status, 0) == 0);
148
149     spent_nip = NULL;
150     return NSS_STATUS_NOTFOUND;
151 }
152
153
154 enum nss_status
155 _nss_nonlocal_getspnam_r(const char *name, struct spwd *pwd,
156                          char *buffer, size_t buflen, int *errnop)
157 {
158     static const char *fct_name = "getspnam_r";
159     static void *fct_start = NULL;
160     enum nss_status status;
161     service_user *nip;
162     union {
163         enum nss_status (*l)(const char *name, struct spwd *pwd,
164                              char *buffer, size_t buflen, int *errnop);
165         void *ptr;
166     } fct;
167
168     nip = nss_shadow_nonlocal_database();
169     if (nip == NULL)
170         return NSS_STATUS_UNAVAIL;
171     if (fct_start == NULL)
172         fct_start = __nss_lookup_function(nip, fct_name);
173     fct.ptr = fct_start;
174     do {
175         if (fct.ptr == NULL)
176             status = NSS_STATUS_UNAVAIL;
177         else
178             status = DL_CALL_FCT(fct.l, (name, pwd, buffer, buflen, errnop));
179         if (status == NSS_STATUS_TRYAGAIN && *errnop == ERANGE)
180             break;
181     } while (__nss_next(&nip, fct_name, &fct.ptr, status, 0) == 0);
182     return status;
183 }
This page took 0.133947 seconds and 5 git commands to generate.