1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21: #include <string.h>
22: #include <rpcsvc/nis.h>
23: #include "nis_xdr.h"
24: #include "nis_intern.h"
25: #include <libnsl.h>
26:
27:
28: nis_result *
29: nis_lookup (const_nis_name name, const unsigned int flags)
30: {
31: nis_result *res = calloc (1, sizeof (nis_result));
32: struct ns_request req;
33: nis_name *names;
34: nis_error status;
35: int link_first_try = 0;
36: int count_links = 0;
37: int done = 0;
38: int name_nr = 0;
39: nis_name namebuf[2] = {NULL, NULL};
40:
41: if (res == NULL)
42: return NULL;
43:
44: if ((flags & EXPAND_NAME) && (name[strlen (name) - 1] != '.'))
45: {
46: names = nis_getnames (name);
47: if (names == NULL)
48: {
49: NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
50: return res;
51: }
52: }
53: else
54: {
55: names = namebuf;
56: names[0] = (nis_name)name;
57: }
58:
59: req.ns_name = names[0];
60: while (!done)
61: {
62: dir_binding bptr;
63: directory_obj *dir = NULL;
64: req.ns_object.ns_object_len = 0;
65: req.ns_object.ns_object_val = NULL;
66:
67: status = __prepare_niscall (req.ns_name, &dir, &bptr, flags);
68: if (__builtin_expect (status != NIS_SUCCESS, 0))
69: {
70: NIS_RES_STATUS (res) = status;
71: goto out;
72: }
73:
74: do
75: {
76: static const struct timeval RPCTIMEOUT = {10, 0};
77: enum clnt_stat result;
78:
79: again:
80: result = clnt_call (bptr.clnt, NIS_LOOKUP,
81: (xdrproc_t) _xdr_ns_request,
82: (caddr_t) &req, (xdrproc_t) _xdr_nis_result,
83: (caddr_t) res, RPCTIMEOUT);
84:
85: if (result != RPC_SUCCESS)
86: status = NIS_RPCERROR;
87: else
88: {
89: status = NIS_SUCCESS;
90:
91: if (NIS_RES_STATUS (res) == NIS_SUCCESS)
92: {
93: if (__type_of (NIS_RES_OBJECT (res)) == NIS_LINK_OBJ
94: && (flags & FOLLOW_LINKS))
95: {
96:
97: if (count_links > NIS_MAXLINKS)
98: {
99: NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
100: break;
101: }
102: ++count_links;
103: req.ns_name =
104: strdupa (NIS_RES_OBJECT (res)->LI_data.li_name);
105:
106:
107:
108:
109:
110:
111: xdr_free ((xdrproc_t) _xdr_nis_result, (char *) res);
112: memset (res, '\0', sizeof (*res));
113:
114: link_first_try = 1;
115: goto again;
116: }
117: }
118: else
119: if (NIS_RES_STATUS (res) == NIS_SYSTEMERROR
120: || NIS_RES_STATUS (res) == NIS_NOSUCHNAME
121: || NIS_RES_STATUS (res) == NIS_NOT_ME)
122: {
123: if (link_first_try)
124: {
125: __nisbind_destroy (&bptr);
126: nis_free_directory (dir);
127:
128: dir = NULL;
129:
130: if (__nisfind_server (req.ns_name, 1, &dir, &bptr,
131: flags & ~MASTER_ONLY)
132: != NIS_SUCCESS)
133: goto out;
134: }
135: else
136: if (__nisbind_next (&bptr) != NIS_SUCCESS)
137: {
138:
139: const char *ndomain = __nis_domain_of (req.ns_name);
140: req.ns_name = strdupa (ndomain);
141: if (strcmp (req.ns_name, ".") == 0)
142: {
143: NIS_RES_STATUS (res) = NIS_NAMEUNREACHABLE;
144: goto out;
145: }
146:
147: __nisbind_destroy (&bptr);
148: nis_free_directory (dir);
149: dir = NULL;
150: status = __prepare_niscall (req.ns_name, &dir,
151: &bptr, flags);
152: if (__builtin_expect (status != NIS_SUCCESS, 0))
153: {
154: NIS_RES_STATUS (res) = status;
155: goto out;
156: }
157: goto again;
158: }
159:
160: while (__nisbind_connect (&bptr) != NIS_SUCCESS)
161: {
162: if (__nisbind_next (&bptr) != NIS_SUCCESS)
163: {
164: nis_free_directory (dir);
165: goto out;
166: }
167: }
168: goto again;
169: }
170: break;
171: }
172: link_first_try = 0;
173: }
174: while ((flags & HARD_LOOKUP) && status == NIS_RPCERROR);
175:
176: __nisbind_destroy (&bptr);
177: nis_free_directory (dir);
178:
179: if (status != NIS_SUCCESS)
180: {
181: NIS_RES_STATUS (res) = status;
182: goto out;
183: }
184:
185: switch (NIS_RES_STATUS (res))
186: {
187: case NIS_PARTIAL:
188: case NIS_SUCCESS:
189: case NIS_S_SUCCESS:
190: case NIS_LINKNAMEERROR:
191: case NIS_UNAVAIL:
192: ++done;
193: break;
194: default:
195:
196: if (count_links)
197: {
198: free (req.ns_name);
199: NIS_RES_STATUS (res) = NIS_LINKNAMEERROR;
200: ++done;
201: break;
202: }
203: ++name_nr;
204: if (names[name_nr] == NULL)
205: {
206: ++done;
207: break;
208: }
209: req.ns_name = names[name_nr];
210: break;
211: }
212: }
213:
214: out:
215: if (names != namebuf)
216: nis_freenames (names);
217:
218: return res;
219: }
220: libnsl_hidden_def (nis_lookup)