Merge branch 'vendor/DIFFUTILS'
[dragonfly.git] / contrib / amd / amd / info_nisplus.c
1 /*
2  * Copyright (c) 1997-1999 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  *      %W% (Berkeley) %G%
40  *
41  * $Id: info_nisplus.c,v 1.2 1999/01/10 21:53:46 ezk Exp $
42  *
43  */
44
45 /*
46  * Get info from NIS+ (version 3) map
47  */
48
49 #ifdef HAVE_CONFIG_H
50 # include <config.h>
51 #endif /* HAVE_CONFIG_H */
52 #include <am_defs.h>
53 #include <amd.h>
54
55 #define NISPLUS_KEY "key="
56 #define NISPLUS_ORGDIR ".org_dir"
57
58 struct nis_callback_data {
59   mnt_map *ncd_m;
60   char *ncd_map;
61   void (*ncd_fn)();
62 };
63
64 struct nisplus_search_callback_data {
65   nis_name key;
66   char *value;
67 };
68
69
70 static int
71 nisplus_callback(const nis_name key, const nis_object *value, voidp opaquedata)
72 {
73   char *kp = strnsave(ENTRY_VAL(value, 0), ENTRY_LEN(value, 0));
74   char *vp = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
75   struct nis_callback_data *data = (struct nis_callback_data *) opaquedata;
76
77 #ifdef DEBUG
78   dlog("NISplus callback for <%s,%s>", kp, vp);
79 #endif /* DEBUG */
80
81   (*data->ncd_fn) (data->ncd_m, kp, vp);
82
83   /*
84    * We want more ...
85    */
86   return FALSE;
87 }
88
89
90 int
91 nisplus_reload(mnt_map *m, char *map, void (*fn) ())
92 {
93   int error = 0;
94   struct nis_callback_data data;
95   nis_result *result;
96   char *org;            /* if map does not have ".org_dir" then append it */
97   nis_name map_name;
98
99   org = strstr(map, NISPLUS_ORGDIR);
100   if (org == NULL)
101     org = NISPLUS_ORGDIR;
102   else
103     org = "";
104
105   /* make some room for the NIS map_name */
106   map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
107   if (map_name == NULL) {
108     plog(XLOG_ERROR, "Unable to create map_name %s: %s",
109          map, strerror(ENOMEM));
110     return ENOMEM;
111   }
112   sprintf(map_name, "%s%s", map, org);
113
114   data.ncd_m = m;
115   data.ncd_map = map_name;
116   data.ncd_fn = fn;
117
118 #ifdef DEBUG
119   dlog("NISplus reload for %s", map);
120 #endif /* DEBUG */
121
122   result = nis_list(map_name,
123                     EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
124                     (int (*)()) nisplus_callback,
125                     &data);
126
127   /* free off the NIS map_name */
128   XFREE(map_name);
129
130   if (result->status != NIS_SUCCESS && result->status != NIS_CBRESULTS)
131     error = 1;
132
133   if (error)
134     plog(XLOG_ERROR, "error grabbing nisplus map of %s: %s",
135          map,
136          nis_sperrno(result->status));
137
138   nis_freeresult(result);
139   return error;
140 }
141
142
143 static int
144 nisplus_search_callback(const nis_name key, const nis_object *value, voidp opaquedata)
145 {
146   struct nisplus_search_callback_data *data = (struct nisplus_search_callback_data *) opaquedata;
147
148 #ifdef DEBUG
149   dlog("NISplus search callback for <%s>", ENTRY_VAL(value, 0));
150   dlog("NISplus search callback value <%s>", ENTRY_VAL(value, 1));
151 #endif /* DEBUG */
152
153   data->value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
154   return TRUE;
155 }
156
157
158 /*
159  * Try to locate a key using NIS+.
160  */
161 int
162 nisplus_search(mnt_map *m, char *map, char *key, char **val, time_t *tp)
163 {
164   nis_result *result;
165   int error = 0;
166   struct nisplus_search_callback_data data;
167   nis_name index;
168   char *org;            /* if map does not have ".org_dir" then append it */
169
170   org = strstr(map, NISPLUS_ORGDIR);
171   if (org == NULL)
172     org = NISPLUS_ORGDIR;
173   else
174     org = "";
175
176   /* make some room for the NIS index */
177   index = xmalloc(sizeof('[')   /* for opening selection criteria */
178                   +sizeof(NISPLUS_KEY)
179                   + strlen(key)
180                   + sizeof(']') /* for closing selection criteria */
181                   +sizeof(',')  /* + 1 for , separator */
182                   +strlen(map)
183                   + sizeof(NISPLUS_ORGDIR)
184                   );
185   if (index == NULL) {
186     plog(XLOG_ERROR,
187          "Unable to create index %s: %s",
188          map,
189          strerror(ENOMEM));
190     return ENOMEM;
191   }
192   sprintf(index, "[%s%s],%s%s", NISPLUS_KEY, key, map, org);
193
194   data.key = key;
195   data.value = NULL;
196
197 #ifdef DEBUG
198   dlog("NISplus search for %s", index);
199 #endif /* DEBUG */
200
201   result = nis_list(index,
202                     EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH,
203                     (int (*)()) nisplus_search_callback,
204                     &data);
205
206   /* free off the NIS index */
207   XFREE(index);
208
209   if (result == NULL) {
210     plog(XLOG_ERROR, "%s: %s", map, strerror(ENOMEM));
211     return ENOMEM;
212   }
213
214   /*
215    * Do something interesting with the return code
216    */
217   switch (result->status) {
218   case NIS_SUCCESS:
219   case NIS_CBRESULTS:
220
221     if (data.value == NULL) {
222       nis_object *value = result->objects.objects_val;
223 #ifdef DEBUG
224       dlog("NISplus search found <nothing>");
225       dlog("NISplus search for %s: %s(%d)",
226            map, nis_sperrno(result->status), result->status);
227 #endif /* DEBUG */
228
229       if (value != NULL)
230         data.value = strnsave(ENTRY_VAL(value, 1), ENTRY_LEN(value, 1));
231     }
232     *val = data.value;
233
234     if (*val) {
235       error = 0;
236 #ifdef DEBUG
237       dlog("NISplus search found %s", *val);
238 #endif /* DEBUG */
239     } else {
240       error = ENOENT;
241 #ifdef DEBUG
242       dlog("NISplus search found nothing");
243 #endif /* DEBUG */
244     }
245
246     *tp = 0;
247     break;
248
249   case NIS_NOSUCHNAME:
250 #ifdef DEBUG
251     dlog("NISplus search returned %d", result->status);
252 #endif /* DEBUG */
253     error = ENOENT;
254     break;
255
256   default:
257     plog(XLOG_ERROR, "%s: %s", map, nis_sperrno(result->status));
258     error = EIO;
259     break;
260   }
261   nis_freeresult(result);
262
263   return error;
264 }
265
266
267 int
268 nisplus_init(mnt_map *m, char *map, time_t *tp)
269 {
270   nis_result *result;
271   char *org;            /* if map does not have ".org_dir" then append it */
272   nis_name map_name;
273   int error = 0;
274
275   org = strstr(map, NISPLUS_ORGDIR);
276   if (org == NULL)
277     org = NISPLUS_ORGDIR;
278   else
279     org = "";
280
281   /* make some room for the NIS map_name */
282   map_name = xmalloc(strlen(map) + sizeof(NISPLUS_ORGDIR));
283   if (map_name == NULL) {
284     plog(XLOG_ERROR,
285          "Unable to create map_name %s: %s",
286          map,
287          strerror(ENOMEM));
288     return ENOMEM;
289   }
290   sprintf(map_name, "%s%s", map, org);
291
292   result = nis_lookup(map_name, (EXPAND_NAME | FOLLOW_LINKS | FOLLOW_PATH));
293
294   /* free off the NIS map_name */
295   XFREE(map_name);
296
297   if (result == NULL) {
298     plog(XLOG_ERROR, "NISplus init <%s>: %s", map, strerror(ENOMEM));
299     return ENOMEM;
300   }
301
302   if (result->status != NIS_SUCCESS) {
303 #ifdef DEBUG
304     dlog("NISplus init <%s>: %s (%d)",
305          map, nis_sperrno(result->status), result->status);
306 #endif /* DEBUG */
307
308     error = ENOENT;
309   }
310
311   *tp = 0;                      /* no time */
312   nis_freeresult(result);
313   return error;
314 }
315
316
317 int
318 nisplus_mtime(mnt_map *m, char *map, time_t *tp)
319 {
320   return nisplus_init(m,map, tp);
321 }