dmake: do not set MAKEFLAGS=k
[unleashed/tickless.git] / usr / src / cmd / fs.d / autofs / ns_nis.c
blobaa85eb15a3471861a7d93ae1cbe3b5a9661e3711
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * ns_nis.c
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <syslog.h>
32 #include <string.h>
33 #include <ctype.h>
34 #include <nsswitch.h>
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/systeminfo.h>
38 #include <rpc/rpc.h>
39 #include <rpcsvc/nfs_prot.h>
40 #include <rpcsvc/ypclnt.h>
41 #include <rpcsvc/yp_prot.h>
42 #include <sys/errno.h>
43 #include "automount.h"
45 #define KEY 0
46 #define CONTENTS 1
48 static int replace_undscr_by_dot(char *);
49 static int nis_err(int);
51 static char nis_mydomain[YPMAXDOMAIN];
53 struct dir_cbdata {
54 struct dir_entry **list;
55 struct dir_entry *last;
56 int error;
59 static int readdir_callback(int, char *, int, const char *,
60 int, struct dir_cbdata *);
62 void
63 init_nis(char **stack, char ***stkptr)
66 (void) sysinfo(SI_SRPC_DOMAIN, nis_mydomain, sizeof (nis_mydomain));
69 /*ARGSUSED*/
70 int
71 getmapent_nis(key, map, ml, stack, stkptr, iswildcard, isrestricted)
72 char *key, *map;
73 struct mapline *ml;
74 char **stack;
75 char ***stkptr;
76 bool_t *iswildcard;
77 bool_t isrestricted;
79 char *nisline = NULL;
80 char *my_map = NULL;
81 char *lp, *lq;
82 int nislen, len;
83 int nserr;
85 if (iswildcard)
86 *iswildcard = FALSE;
87 nserr = yp_match(nis_mydomain, map, key, strlen(key),
88 &nisline, &nislen);
89 if (nserr == YPERR_MAP) {
90 my_map = strdup(map);
91 if (my_map == NULL) {
92 syslog(LOG_ERR,
93 "getmapent_nis: memory alloc failed: %m");
94 return (__NSW_UNAVAIL);
96 if (replace_undscr_by_dot(my_map))
97 nserr = yp_match(nis_mydomain, my_map, key,
98 strlen(key), &nisline, &nislen);
101 if (nserr) {
102 if (nserr == YPERR_KEY) {
104 * Try the default entry "*"
106 if (my_map == NULL)
107 nserr = yp_match(nis_mydomain, map, "*", 1,
108 &nisline, &nislen);
109 else
110 nserr = yp_match(nis_mydomain, my_map, "*", 1,
111 &nisline, &nislen);
112 if (!nserr && iswildcard)
113 *iswildcard = TRUE;
114 } else {
115 if (verbose)
116 syslog(LOG_ERR, "%s: %s",
117 map, yperr_string(nserr));
118 nserr = 1;
121 free(my_map);
123 nserr = nis_err(nserr);
124 if (nserr)
125 goto done;
128 * at this point we are sure that yp_match succeeded
129 * so massage the entry by
130 * 1. ignoring # and beyond
131 * 2. trim the trailing whitespace
133 if (lp = strchr(nisline, '#'))
134 *lp = '\0';
135 len = strlen(nisline);
136 if (len == 0) {
137 nserr = __NSW_NOTFOUND;
138 goto done;
140 lp = &nisline[len - 1];
141 while (lp > nisline && isspace(*lp))
142 *lp-- = '\0';
143 if (lp == nisline) {
144 nserr = __NSW_NOTFOUND;
145 goto done;
147 (void) strcpy(ml->linebuf, nisline);
148 lp = ml->linebuf;
149 lq = ml->lineqbuf;
150 unquote(lp, lq);
151 /* now we have the correct line */
153 nserr = __NSW_SUCCESS;
154 done:
155 if (nisline)
156 free((char *)nisline);
157 return (nserr);
162 loadmaster_nis(mapname, defopts, stack, stkptr)
163 char *mapname, *defopts;
164 char **stack;
165 char ***stkptr;
167 int first, err;
168 char *key, *nkey, *val;
169 int kl, nkl, vl;
170 char dir[256], map[256], qbuff[256];
171 char *pmap, *opts, *my_mapname;
172 int count = 0;
174 first = 1;
175 key = NULL; kl = 0;
176 nkey = NULL; nkl = 0;
177 val = NULL; vl = 0;
180 * need a private copy of mapname, because we may change
181 * the underscores by dots. We however do not want the
182 * orignal to be changed, as we may want to use the
183 * original name in some other name service
185 my_mapname = strdup(mapname);
186 if (my_mapname == NULL) {
187 syslog(LOG_ERR, "loadmaster_yp: memory alloc failed: %m");
188 /* not the name svc's fault but ... */
189 return (__NSW_UNAVAIL);
191 for (;;) {
192 if (first) {
193 first = 0;
194 err = yp_first(nis_mydomain, my_mapname,
195 &nkey, &nkl, &val, &vl);
197 if ((err == YPERR_MAP) &&
198 (replace_undscr_by_dot(my_mapname)))
199 err = yp_first(nis_mydomain, my_mapname,
200 &nkey, &nkl, &val, &vl);
202 if ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) {
203 syslog(LOG_ERR,
204 "can't read nis map %s: %s - retrying",
205 my_mapname, yperr_string(err));
206 while ((err == YPERR_DOMAIN) ||
207 (err == YPERR_YPBIND)) {
208 (void) sleep(20);
209 err = yp_first(nis_mydomain, my_mapname,
210 &nkey, &nkl, &val, &vl);
212 syslog(LOG_ERR,
213 "nis map %s: read OK.", my_mapname);
215 } else {
216 err = yp_next(nis_mydomain, my_mapname, key, kl,
217 &nkey, &nkl, &val, &vl);
219 if (err) {
220 if (err != YPERR_NOMORE && err != YPERR_MAP)
221 if (verbose)
222 syslog(LOG_ERR, "%s: %s",
223 my_mapname, yperr_string(err));
224 break;
226 free(key);
227 key = nkey;
228 kl = nkl;
231 if (kl >= 256 || vl >= 256)
232 break;
233 if (kl < 2 || vl < 1)
234 break;
235 if (isspace(*key) || *key == '#')
236 break;
237 (void) strncpy(dir, key, kl);
238 dir[kl] = '\0';
239 if (macro_expand("", dir, qbuff, sizeof (dir))) {
240 syslog(LOG_ERR,
241 "%s in NIS map %s: entry too long (max %d chars)",
242 dir, my_mapname, sizeof (dir) - 1);
243 break;
245 (void) strncpy(map, val, vl);
246 map[vl] = '\0';
247 if (macro_expand(dir, map, qbuff, sizeof (map))) {
248 syslog(LOG_ERR,
249 "%s in NIS map %s: entry too long (max %d chars)",
250 map, my_mapname, sizeof (map) - 1);
251 break;
253 pmap = map;
254 while (*pmap && isspace(*pmap))
255 pmap++; /* skip blanks in front of map */
256 opts = pmap;
257 while (*opts && !isspace(*opts))
258 opts++;
259 if (*opts) {
260 *opts++ = '\0';
261 while (*opts && isspace(*opts))
262 opts++;
263 if (*opts == '-')
264 opts++;
265 else
266 opts = defopts;
268 free(val);
271 * Check for no embedded blanks.
273 if (strcspn(opts, " ") == strlen(opts)) {
274 dirinit(dir, pmap, opts, 0, stack, stkptr);
275 count++;
276 } else {
277 pr_msg("Warning: invalid entry for %s in NIS map %s ignored.\n", dir, mapname);
281 free(my_mapname);
284 * In the context of a master map, if no entry is
285 * found, it is like NOTFOUND
287 if (count > 0 && err == YPERR_NOMORE)
288 return (__NSW_SUCCESS);
289 else {
290 if (err)
291 return (nis_err(err));
292 else
294 * This case will happen if map is empty
295 * or none of the entries is valid
297 return (__NSW_NOTFOUND);
302 loaddirect_nis(nismap, localmap, opts, stack, stkptr)
303 char *nismap, *localmap, *opts;
304 char **stack;
305 char ***stkptr;
307 int first, err, count;
308 char *key, *nkey, *val, *my_nismap;
309 int kl, nkl, vl;
310 char dir[100];
312 first = 1;
313 key = NULL; kl = 0;
314 nkey = NULL; nkl = 0;
315 val = NULL; vl = 0;
316 count = 0;
317 my_nismap = NULL;
319 my_nismap = strdup(nismap);
320 if (my_nismap == NULL) {
321 syslog(LOG_ERR, "loadmaster_yp: memory alloc failed: %m");
322 return (__NSW_UNAVAIL);
324 for (;;) {
325 if (first) {
326 first = 0;
327 err = yp_first(nis_mydomain, my_nismap, &nkey, &nkl,
328 &val, &vl);
330 if ((err == YPERR_MAP) &&
331 (replace_undscr_by_dot(my_nismap)))
332 err = yp_first(nis_mydomain, my_nismap,
333 &nkey, &nkl, &val, &vl);
335 if ((err == YPERR_DOMAIN) || (err == YPERR_YPBIND)) {
336 syslog(LOG_ERR,
337 "can't read nis map %s: %s - retrying",
338 my_nismap, yperr_string(err));
339 while ((err == YPERR_DOMAIN) ||
340 (err == YPERR_YPBIND)) {
341 (void) sleep(20);
342 err = yp_first(nis_mydomain, my_nismap,
343 &nkey, &nkl, &val, &vl);
345 syslog(LOG_ERR,
346 "nis map %s: read OK.", my_nismap);
348 } else {
349 err = yp_next(nis_mydomain, my_nismap, key, kl,
350 &nkey, &nkl, &val, &vl);
352 if (err) {
353 if (err != YPERR_NOMORE && err != YPERR_MAP)
354 syslog(LOG_ERR, "%s: %s",
355 my_nismap, yperr_string(err));
356 break;
358 free(key);
359 key = nkey;
360 kl = nkl;
362 if (kl < 2 || kl >= 100)
363 continue;
364 if (isspace(*key) || *key == '#')
365 continue;
366 (void) strncpy(dir, key, kl);
367 dir[kl] = '\0';
369 dirinit(dir, localmap, opts, 1, stack, stkptr);
370 count++;
371 free(val);
374 free(my_nismap);
376 if (count > 0 && err == YPERR_NOMORE)
377 return (__NSW_SUCCESS);
378 else
379 return (nis_err(err));
383 static int
384 replace_undscr_by_dot(map)
385 char *map;
387 int ret_val = 0;
389 while (*map) {
390 if (*map == '_') {
391 ret_val = 1;
392 *map = '.';
394 map++;
396 return (ret_val);
399 static int
400 nis_err(err)
401 int err;
403 switch (err) {
404 case 0:
405 return (__NSW_SUCCESS);
406 case YPERR_KEY:
407 return (__NSW_NOTFOUND);
408 case YPERR_MAP:
409 return (__NSW_UNAVAIL);
410 default:
411 return (__NSW_UNAVAIL);
416 getmapkeys_nis(nsmap, list, error, cache_time, stack, stkptr)
417 char *nsmap;
418 struct dir_entry **list;
419 int *error;
420 int *cache_time;
421 char **stack;
422 char ***stkptr;
424 int nserr;
425 struct dir_cbdata readdir_cbdata;
426 struct ypall_callback cback;
427 char *my_map = NULL;
429 char *key = NULL, *val = NULL;
430 int nkl, vl;
433 *cache_time = RDDIR_CACHE_TIME;
436 * XXX Hack to determine if we need to replace '_' with '.'
437 * Have to use yp_first() since yp_all() simply fails if
438 * the map is not present
440 my_map = strdup(nsmap);
441 if (my_map == NULL) {
442 syslog(LOG_ERR,
443 "getmapkeys_nis: memory alloc failed: %m");
444 *error = ENOMEM;
445 return (__NSW_UNAVAIL);
447 nserr = yp_first(nis_mydomain, my_map, &key, &nkl, &val, &vl);
448 if (nserr == YPERR_MAP) {
449 if (replace_undscr_by_dot(my_map)) {
450 nserr = yp_first(nis_mydomain, my_map,
451 &key, &nkl, &val, &vl);
453 if (nserr == YPERR_MAP) {
455 * map not found
457 *error = 0; /* return an empty list */
458 if (verbose) {
459 syslog(LOG_ERR, "%s: %s",
460 nsmap, yperr_string(nserr));
462 free(my_map);
463 return (nis_err(nserr));
466 free(key);
467 free(val);
469 readdir_cbdata.list = list;
470 readdir_cbdata.last = NULL;
471 readdir_cbdata.error = 0;
473 cback.foreach = readdir_callback;
474 cback.data = (char *)&readdir_cbdata;
477 * after all this song and dance we finally
478 * ask for the list of entries
480 nserr = yp_all(nis_mydomain, my_map, &cback);
482 free(my_map);
483 *error = readdir_cbdata.error;
484 if (nserr) {
485 if (verbose)
486 syslog(LOG_ERR, "%s: %s", nsmap, yperr_string(nserr));
487 nserr = 1;
488 if (*error == 0)
489 *error = ENOENT;
491 return (nis_err(nserr));
494 return (__NSW_SUCCESS);
497 static int
498 readdir_callback(instatus, inkey, inkeylen, inval, invallen, indata)
499 int instatus;
500 char *inkey;
501 int inkeylen;
502 const char *inval;
503 int invallen;
504 struct dir_cbdata *indata;
506 struct dir_entry **list = indata->list;
507 struct dir_entry *last = indata->last;
508 char key[MAXPATHLEN];
511 if (instatus != YP_TRUE)
512 return (0); /* next entry. yp_all may decide otherwise... */
514 if (inkeylen == 0 || isspace(*inkey) || *inkey == '#')
515 return (0);
518 * yp_all allocates inkey with two extra bytes which contain
519 * NEWLINE and null but these two bytes are not reflected in
520 * inkeylen.
522 strncpy(key, inkey, inkeylen);
523 key[inkeylen] = '\0';
526 * Wildcard entry should be ignored - following entries should continue
527 * to be read to corroborate with the way we search for entries in yp,
528 * i.e., first for an exact key match and then a wildcard, if there's
529 * no exact key match.
531 if (key[0] == '*' && key[1] == '\0')
532 return (0);
534 if (add_dir_entry(key, list, &last)) {
535 indata->error = ENOMEM;
536 return (1); /* get no more entries */
539 indata->last = last;
540 indata->error = 0;
542 return (0);