confirm results
[tridge/junkcode.git] / nistest.c
1 /************************************************
2 nss_funcs.c
3 -------------------------------------------------
4 based on nsstest.c by a. tridgell
5 expanded by j. trostel
6 -------------------------------------------------
7 get user and group info for different nss modules
8 ************************************************/
9 #define _GNU_SOURCE
10 #include <stdio.h>
11 #include <nss.h>
12 #include <dlfcn.h>
13 #include <pwd.h>
14 #include <grp.h>
15 #include <stdlib.h>
16
17 typedef enum nss_status NSS_STATUS;
18 int nss_errno;
19
20 void *find_fn(const char *nss_name, const char *funct_name)
21 {
22         char *so_path, *s;
23         void *h;
24         void *res;
25
26         // create the library name
27         asprintf(&so_path, "libnss_%s.so.2", nss_name);
28         h = dlopen(so_path, RTLD_LAZY);
29
30         if (!h){
31                 free(so_path);
32                 exit(1);
33         }
34
35         // create the function name
36         asprintf(&s, "_nss_%s_%s", nss_name, funct_name);
37
38         // and find it in the library
39         res = dlsym(h, s);
40
41         if (!res) {
42                 free(so_path);
43                 free(s);
44                 return NULL;
45         }
46
47         // free the strings from asprintf
48         free(so_path);
49         free(s);
50         return res;
51 }
52
53 struct passwd *nss_getpwent(const char *nss_name)
54 {
55         NSS_STATUS (*_nss_getpwent_r)(struct passwd *, char *, 
56                                       size_t , int *) = find_fn(nss_name, "getpwent_r");
57         static struct passwd pwd;
58         static char buf[1000];
59         NSS_STATUS status;
60
61         status = _nss_getpwent_r(&pwd, buf, sizeof(buf), &nss_errno);
62
63         if (status != NSS_STATUS_SUCCESS)
64                 return NULL;
65
66         return &pwd;
67 }
68
69 struct passwd *nss_getpwnam(const char *nss_name, const char *name)
70 {
71         NSS_STATUS (*_nss_getpwnam_r)(const char *, struct passwd *, char *, 
72                                       size_t , int *) = find_fn(nss_name, "getpwnam_r");
73         static struct passwd pwd;
74         static char buf[1000];
75         NSS_STATUS status;
76
77         status = _nss_getpwnam_r(name, &pwd, buf, sizeof(buf), &nss_errno);
78
79         if (status != NSS_STATUS_SUCCESS) 
80                 return NULL;
81
82         return &pwd;
83 }
84
85 struct passwd *nss_getpwuid(const char *nss_name, uid_t uid)
86 {
87         NSS_STATUS (*_nss_getpwuid_r)(uid_t, struct passwd *, char *, 
88                                       size_t , int *) = find_fn(nss_name, "getpwuid_r");
89         static struct passwd pwd;
90         static char buf[1000];
91         NSS_STATUS status;
92
93         status = _nss_getpwuid_r(uid, &pwd, buf, sizeof(buf), &nss_errno);
94
95         if (status != NSS_STATUS_SUCCESS) 
96                 return NULL;
97
98         return &pwd;
99 }
100
101 NSS_STATUS nss_setpwent(const char *nss_name)
102 {
103         NSS_STATUS (*_nss_setpwent)(void) = find_fn(nss_name, "setpwent");
104         return( _nss_setpwent() );
105 }
106
107 NSS_STATUS nss_endpwent(const char *nss_name)
108 {
109         NSS_STATUS (*_nss_endpwent)(void) = find_fn(nss_name, "endpwent");
110         return( _nss_endpwent() );
111 }
112
113 struct group *nss_getgrent(const char *nss_name)
114 {
115         NSS_STATUS (*_nss_getgrent_r)(struct group *, char *, 
116                                       size_t , int *) = find_fn(nss_name, "getgrent_r");
117         static struct group grp;
118         int my_errno = 0;
119         static char *buf = NULL;
120         static int buflen = 1024;
121         NSS_STATUS status;
122         
123         if(!buf) {
124                 if((buf = malloc(buflen)) == NULL)
125                 return NULL;
126         }
127         
128 again:
129         status = _nss_getgrent_r(&grp, buf, buflen, &my_errno);
130         if (status == NSS_STATUS_TRYAGAIN) {
131                 buflen *= 2;
132                 free(buf);
133                 if( (buf = malloc(buflen)) == NULL) {
134                         buflen = 1024;
135                         return NULL;
136                 }
137                 goto again;
138         }
139
140         if (status != NSS_STATUS_SUCCESS) {
141                 free(buf);
142                 buf = NULL;
143                 return NULL;
144         }
145
146         return &grp;
147 }
148
149 struct group *nss_getgrnam(const char *nss_name, const char *name)
150 {
151         NSS_STATUS (*_nss_getgrnam_r)(const char *, struct group *, char *, 
152                                       size_t , int *) = find_fn(nss_name, "getgrnam_r");
153         static struct group grp;
154         static char *buf = NULL;
155         static int buflen = 1024;
156         NSS_STATUS status;
157
158         if (!buf) {
159                 if( (buf = malloc(buflen)) == NULL)
160                         return NULL;
161         }
162         
163 again:
164         status = _nss_getgrnam_r(name, &grp, buf, buflen, &nss_errno);
165         if (status == NSS_STATUS_TRYAGAIN) {
166                 buflen *= 2;
167                 free(buf);
168                 if ( (buf = malloc(buflen)) == NULL) {
169                         buflen = 1024;
170                         return NULL;
171                 }
172                 goto again;
173         }
174
175         if (status != NSS_STATUS_SUCCESS) {
176                 free(buf);
177                 buf = NULL;
178                 return NULL;
179         }
180
181         return &grp;
182 }
183
184 struct group *nss_getgrgid(const char *nss_name, gid_t gid)
185 {
186         NSS_STATUS (*_nss_getgrgid_r)(gid_t, struct group *, char *, 
187                                       size_t , int *) = find_fn(nss_name, "getgrgid_r");
188         static struct group grp;
189         static char *buf = NULL;
190         static int buflen = 1024;
191         NSS_STATUS status;
192         
193         if (!buf) {
194                 if( (buf = malloc(buflen)) == NULL)
195                         return NULL;
196         }
197         
198 again:
199         status = _nss_getgrgid_r(gid, &grp, buf, buflen, &nss_errno);
200         if (status ==  NSS_STATUS_TRYAGAIN) {
201                 buflen *= 2;
202                 free(buf);
203                 if( (buf = malloc(buflen)) == NULL) {
204                         buflen = 1024;
205                         return NULL;
206                 }
207                 goto again;
208         }
209         
210         if (status != NSS_STATUS_SUCCESS) {
211                 free(buf);
212                 buf = NULL;
213                 return NULL;
214         }
215
216         return &grp;
217 }
218         
219
220 NSS_STATUS nss_setgrent(const char *nss_name)
221 {
222         NSS_STATUS (*_nss_setgrent)(void) = find_fn(nss_name, "setgrent");
223         return( _nss_setgrent() );
224 }
225
226 NSS_STATUS nss_endgrent(const char *nss_name)
227 {
228         NSS_STATUS (*_nss_endgrent)(void) = find_fn(nss_name, "endgrent");
229         return( _nss_endgrent() );
230 }
231
232 /*
233   this trick resets the internal glibc cached copy of the NIS domain name
234   read the glibc nis code (in particular the __ypdomain[] static array) to
235   understand whats going on
236  */
237 static void nis_reset_domain(void)
238 {
239         void (*fn_yp_get_default_domain)(char **);
240         void *h = dlopen("libnss_nis.so.2", RTLD_LAZY);
241         char *domain = NULL;
242
243         fn_yp_get_default_domain = dlsym(h, "yp_get_default_domain");
244         
245         if (!fn_yp_get_default_domain) return;
246
247         fn_yp_get_default_domain(&domain);
248         if (domain) {
249                 domain[0] = 0;
250         }
251 }
252
253 int main(void)
254 {
255         while (1) {
256                 struct passwd *pwd;
257                 int i;
258
259                 sleep(1);
260
261                 nis_reset_domain();
262
263                 nss_setpwent("nis");
264                 i=0;
265                 while (nss_getpwent("nis")) i++;
266                 printf("i=%d\n", i);
267                 nss_endpwent("nis");
268         }
269         return 0;
270 }