]> andersk Git - nss_nonlocal.git/blob - walk_nss.h
Move the repetitive NSS walking logic into an include file
[nss_nonlocal.git] / walk_nss.h
1 /*
2  * walk_nss.h
3  * NSS walking template for nss_nonlocal proxy
4  *
5  * Copyright © 2011 Anders Kaseorg <andersk@mit.edu> and Tim Abbott
6  * <tabbott@mit.edu>
7  *
8  * This file is part of nss_nonlocal.
9  *
10  * nss_nonlocal is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU Lesser General Public License
12  * as published by the Free Software Foundation; either version 2.1 of
13  * the License, or (at your option) any later version.
14  *
15  * nss_nonlocal is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * Lesser General Public License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public
21  * License along with nss_nonlocal; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23  * 02110-1301  USA
24  */
25
26 {
27     static service_user *startp = NULL;
28     static void *fct_start = NULL;
29
30     service_user *nip;
31     union {
32         __typeof__(self) l;
33         void *ptr;
34     } fct;
35     int old_errno = errno;
36
37     if (fct_start == NULL &&
38         w.lookup(&startp, w.fct_name, &fct_start) != 0) {
39         *w.status = NSS_STATUS_UNAVAIL;
40         goto walk_nss_out;
41     }
42
43     nip = startp;
44     fct.ptr = fct_start;
45
46     if (w.buf != NULL) {
47         *w.buf = malloc(*w.buflen);
48         errno = old_errno;
49         if (*w.buf == NULL) {
50             *w.status = NSS_STATUS_TRYAGAIN;
51             *w.errnop = ENOMEM;
52             goto walk_nss_out;
53         }
54     }
55
56     do {
57     walk_nss_morebuf:
58         if (fct.ptr == NULL)
59             *w.status = NSS_STATUS_UNAVAIL;
60         else if (self != NULL && fct.l == self)
61             *w.status = NSS_STATUS_NOTFOUND;
62         else
63             *w.status = DL_CALL_FCT(fct.l, args);
64         if (*w.status == NSS_STATUS_TRYAGAIN &&
65             w.errnop != NULL && *w.errnop == ERANGE) {
66             if (w.buf == NULL)
67                 break;
68             free(*w.buf);
69             *w.buflen *= 2;
70             *w.buf = malloc(*w.buflen);
71             errno = old_errno;
72             if (*w.buf == NULL) {
73                 *w.errnop = ENOMEM;
74                 goto walk_nss_out;
75             }
76             goto walk_nss_morebuf;
77         }
78     } while (__nss_next(&nip, w.fct_name, &fct.ptr, *w.status, 0) == 0);
79
80     if (w.buf != NULL && *w.status != NSS_STATUS_SUCCESS) {
81         free(*w.buf);
82         *w.buf = NULL;
83     }
84
85  walk_nss_out:
86     ;
87 }
This page took 0.509784 seconds and 5 git commands to generate.