]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/amd/amd/info_nisplus.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / amd / amd / info_nisplus.c
1 /*
2  * Copyright (c) 1997-2006 Erez Zadok
3  * Copyright (c) 1989 Jan-Simon Pendry
4  * Copyright (c) 1989 Imperial College of Science, Technology & Medicine
5  * Copyright (c) 1989 The Regents of the University of California.
6  * All rights reserved.
7  *
8  * This code is derived from software contributed to Berkeley by
9  * Jan-Simon Pendry at Imperial College, London.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  * 3. All advertising materials mentioning features or use of this software
20  *    must display the following acknowledgment:
21  *      This product includes software developed by the University of
22  *      California, Berkeley and its contributors.
23  * 4. Neither the name of the University nor the names of its contributors
24  *    may be used to endorse or promote products derived from this software
25  *    without specific prior written permission.
26  *
27  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37  * SUCH DAMAGE.
38  *
39  *
40  * File: am-utils/amd/info_nisplus.c
41  *
42  */
43
44 /*
45  * Get info from NIS+ (version 3) map
46  */
47
48 #ifdef HAVE_CONFIG_H
49 # include <config.h>
50 #endif /* HAVE_CONFIG_H */
51 #include <am_defs.h>
52 #include <amd.h>
53
54 #define NISPLUS_KEY "key="
55 #define NISPLUS_ORGDIR ".org_dir"
56
57 struct nis_callback_data {
58   mnt_map *ncd_m;
59   char *ncd_map;
60   void (*ncd_fn)();
61 };
62
63 struct nisplus_search_callback_data {
64   nis_name key;
65   char *value;
66 };
67
68
69 static int
70 nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
71 {
72   char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0));
73   char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
74   struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
75
76   dlog("NISplus callback for <%s,%s>", kp, vp);
77
78   (*data->ncd_fn) (data->ncd_m, kp, vp);
79
80   /*
81    * We want more ...
82    */
83   return FALSE;
84 }
85
86
87 int
88 nisplus_reload(mnt_map *m, char *map, void (*fn) ())
89 {
90   int error = 0;
91   struct nis_callback_data data;
92   nis_result *result;
93   char *org;            /* if map does not have ".org_dir" then append it */
94   nis_name map_name;
95   size_t l;
96
97   org = strstr(map, NISPLUS_ORGDIR);
98   if (org == NULL)
99     org = NISPLUS_ORGDIR;
100   else
101     org = "";
102
103   /* make some room for the NIS map_name */
104   l = strlen(map) + sizeof(NISPLUS_ORGDIR);
105   map_name = xmalloc(l);
106   if (map_name == NULL) {
107     plog(XLOG_ERROR, "Unable to create map_name %s: %s",
108          map, strerror(ENOMEM));
109     return ENOMEM;
110   }
111   xsnprintf(map_name, l, "%s%s", map, org);
112
113   data.ncd_m = m;
114   data.ncd_map = map_name;
115   data.ncd_fn = fn;
116
117   dlog("NISplus reload for %s", map);
118
119   result = nis_list(map_name,
120                     EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
121                     (int (*)()) nisplus_callback,
122                     &data);
123
124   /* free off the NIS map_name */
125   XFREE(map_name);
126
127   if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS)
128     error = 1;
129
130   if (error)
131     plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s",
132          map,
133          nis_sperrno(result->status));
134
135   nis_freeresult(result);
136   return error;
137 }
138
139
140 static int
141 nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata)
142 {
143   struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
144
145   dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
146   dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
147
148   data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
149   return TRUE;
150 }
151
152
153 /*
154  * Try to locate a key using NIS+.
155  */
156 int
157 nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
158 {
159   nis_result *result;
160   int error = 0;
161   struct nisplus_search_callback_data data;
162   nis_name index;
163   char *org;            /* if map does not have ".org_dir" then append it */
164   size_t l;
165
166   org = strstr(map, NISPLUS_ORGDIR);
167   if (org == NULL)
168     org = NISPLUS_ORGDIR;
169   else
170     org = "";
171
172   /* make some room for the NIS index */
173   l = sizeof('[')               /* for opening selection criteria */
174     + sizeof(NISPLUS_KEY)
175     + strlen(key)
176     + sizeof(']')               /* for closing selection criteria */
177     + sizeof(',')               /* + 1 for , separator */
178     + strlen(map)
179     + sizeof(NISPLUS_ORGDIR);
180   index = xmalloc(l);
181   if (index == NULL) {
182     plog(XLOG_ERROR,
183          "Unable to create index %s: %s",
184          map,
185          strerror(ENOMEM));
186     return ENOMEM;
187   }
188   xsnprintf(index, l, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
189
190   data.key = key;
191   data.value = NULL;
192
193   dlog("NISplus search for %s", index);
194
195   result = nis_list(index,
196                     EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
197                     (int (*)()) nisplus_search_callback,
198                     &data);
199
200   /* free off the NIS index */
201   XFREE(index);
202
203   if (result == NULL) {
204     plog(XLOG_ERROR, "nisplus_search: %s: %s", map, strerror(ENOMEM));
205     return ENOMEM;
206   }
207
208   /*
209    * Do something interesting with the return code
210    */
211   switch (result->status) {
212   case NIS_SUCCESS:
213   case NIS_CBRESULTS:
214
215     if (data.value == NULL) {
216       nis_object *value = result->objects.objects_val;
217       dlog("NISplus search found <nothing>");
218       dlog("NISplus search for %s: %s(%d)",
219            map, nis_sperrno(result->status), result->status);
220
221       if (value != NULL)
222         data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
223     }
224     *val = data.value;
225
226     if (*val) {
227       error = 0;
228       dlog("NISplus search found %s", *val);
229     } else {
230       error = ENOENT;
231       dlog("NISplus search found nothing");
232     }
233
234     *tp = 0;
235     break;
236
237   case NIS_NOSUCHNAME:
238     dlog("NISplus search returned %d", result->status);
239     error = ENOENT;
240     break;
241
242   default:
243     plog(XLOG_ERROR, "nisplus_search: %s: %s", map, nis_sperrno(result->status));
244     error = EIO;
245     break;
246   }
247   nis_freeresult(result);
248
249   return error;
250 }
251
252
253 int
254 nisplus_init(mnt_map *m, char *map, time_t *tp)
255 {
256   nis_result *result;
257   char *org;            /* if map does not have ".org_dir" then append it */
258   nis_name map_name;
259   int error = 0;
260   size_t l;
261
262   org = strstr(map, NISPLUS_ORGDIR);
263   if (org == NULL)
264     org = NISPLUS_ORGDIR;
265   else
266     org = "";
267
268   /* make some room for the NIS map_name */
269   l = strlen(map) + sizeof(NISPLUS_ORGDIR);
270   map_name = xmalloc(l);
271   if (map_name == NULL) {
272     plog(XLOG_ERROR,
273          "Unable to create map_name %s: %s",
274          map,
275          strerror(ENOMEM));
276     return ENOMEM;
277   }
278   xsnprintf(map_name, l, "%s%s", map, org);
279
280   result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
281
282   /* free off the NIS map_name */
283   XFREE(map_name);
284
285   if (result == NULL) {
286     plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM));
287     return ENOMEM;
288   }
289
290   if (result->status != NIS_SUCCESS) {
291     dlog("NISplus init <%s>: %s (%d)",
292          map, nis_sperrno(result->status), result->status);
293
294     error = ENOENT;
295   }
296
297   *tp = 0;                      /* no time */
298   nis_freeresult(result);
299   return error;
300 }
301
302
303 int
304 nisplus_mtime(mnt_map *m, char *map, time_t *tp)
305 {
306   return nisplus_init(m,map, tp);
307 }