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]
24 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
25 * Use is subject to license terms.
35 #include <sys/param.h>
36 #include <sys/types.h>
37 #include <sys/systeminfo.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"
48 static int replace_undscr_by_dot(char *);
49 static int nis_err(int);
51 static char nis_mydomain
[YPMAXDOMAIN
];
54 struct dir_entry
**list
;
55 struct dir_entry
*last
;
59 static int readdir_callback(int, char *, int, const char *,
60 int, struct dir_cbdata
*);
63 init_nis(char **stack
, char ***stkptr
)
66 (void) sysinfo(SI_SRPC_DOMAIN
, nis_mydomain
, sizeof (nis_mydomain
));
71 getmapent_nis(key
, map
, ml
, stack
, stkptr
, iswildcard
, isrestricted
)
87 nserr
= yp_match(nis_mydomain
, map
, key
, strlen(key
),
89 if (nserr
== YPERR_MAP
) {
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
);
102 if (nserr
== YPERR_KEY
) {
104 * Try the default entry "*"
107 nserr
= yp_match(nis_mydomain
, map
, "*", 1,
110 nserr
= yp_match(nis_mydomain
, my_map
, "*", 1,
112 if (!nserr
&& iswildcard
)
116 syslog(LOG_ERR
, "%s: %s",
117 map
, yperr_string(nserr
));
123 nserr
= nis_err(nserr
);
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
, '#'))
135 len
= strlen(nisline
);
137 nserr
= __NSW_NOTFOUND
;
140 lp
= &nisline
[len
- 1];
141 while (lp
> nisline
&& isspace(*lp
))
144 nserr
= __NSW_NOTFOUND
;
147 (void) strcpy(ml
->linebuf
, nisline
);
151 /* now we have the correct line */
153 nserr
= __NSW_SUCCESS
;
156 free((char *)nisline
);
162 loadmaster_nis(mapname
, defopts
, stack
, stkptr
)
163 char *mapname
, *defopts
;
168 char *key
, *nkey
, *val
;
170 char dir
[256], map
[256], qbuff
[256];
171 char *pmap
, *opts
, *my_mapname
;
176 nkey
= NULL
; nkl
= 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
);
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
)) {
204 "can't read nis map %s: %s - retrying",
205 my_mapname
, yperr_string(err
));
206 while ((err
== YPERR_DOMAIN
) ||
207 (err
== YPERR_YPBIND
)) {
209 err
= yp_first(nis_mydomain
, my_mapname
,
210 &nkey
, &nkl
, &val
, &vl
);
213 "nis map %s: read OK.", my_mapname
);
216 err
= yp_next(nis_mydomain
, my_mapname
, key
, kl
,
217 &nkey
, &nkl
, &val
, &vl
);
220 if (err
!= YPERR_NOMORE
&& err
!= YPERR_MAP
)
222 syslog(LOG_ERR
, "%s: %s",
223 my_mapname
, yperr_string(err
));
231 if (kl
>= 256 || vl
>= 256)
233 if (kl
< 2 || vl
< 1)
235 if (isspace(*key
) || *key
== '#')
237 (void) strncpy(dir
, key
, kl
);
239 if (macro_expand("", dir
, qbuff
, sizeof (dir
))) {
241 "%s in NIS map %s: entry too long (max %d chars)",
242 dir
, my_mapname
, sizeof (dir
) - 1);
245 (void) strncpy(map
, val
, vl
);
247 if (macro_expand(dir
, map
, qbuff
, sizeof (map
))) {
249 "%s in NIS map %s: entry too long (max %d chars)",
250 map
, my_mapname
, sizeof (map
) - 1);
254 while (*pmap
&& isspace(*pmap
))
255 pmap
++; /* skip blanks in front of map */
257 while (*opts
&& !isspace(*opts
))
261 while (*opts
&& isspace(*opts
))
271 * Check for no embedded blanks.
273 if (strcspn(opts
, " ") == strlen(opts
)) {
274 dirinit(dir
, pmap
, opts
, 0, stack
, stkptr
);
277 pr_msg("Warning: invalid entry for %s in NIS map %s ignored.\n", dir
, 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
);
291 return (nis_err(err
));
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
;
307 int first
, err
, count
;
308 char *key
, *nkey
, *val
, *my_nismap
;
314 nkey
= NULL
; nkl
= 0;
319 my_nismap
= strdup(nismap
);
320 if (my_nismap
== NULL
) {
321 syslog(LOG_ERR
, "loadmaster_yp: memory alloc failed: %m");
322 return (__NSW_UNAVAIL
);
327 err
= yp_first(nis_mydomain
, my_nismap
, &nkey
, &nkl
,
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
)) {
337 "can't read nis map %s: %s - retrying",
338 my_nismap
, yperr_string(err
));
339 while ((err
== YPERR_DOMAIN
) ||
340 (err
== YPERR_YPBIND
)) {
342 err
= yp_first(nis_mydomain
, my_nismap
,
343 &nkey
, &nkl
, &val
, &vl
);
346 "nis map %s: read OK.", my_nismap
);
349 err
= yp_next(nis_mydomain
, my_nismap
, key
, kl
,
350 &nkey
, &nkl
, &val
, &vl
);
353 if (err
!= YPERR_NOMORE
&& err
!= YPERR_MAP
)
354 syslog(LOG_ERR
, "%s: %s",
355 my_nismap
, yperr_string(err
));
362 if (kl
< 2 || kl
>= 100)
364 if (isspace(*key
) || *key
== '#')
366 (void) strncpy(dir
, key
, kl
);
369 dirinit(dir
, localmap
, opts
, 1, stack
, stkptr
);
376 if (count
> 0 && err
== YPERR_NOMORE
)
377 return (__NSW_SUCCESS
);
379 return (nis_err(err
));
384 replace_undscr_by_dot(map
)
405 return (__NSW_SUCCESS
);
407 return (__NSW_NOTFOUND
);
409 return (__NSW_UNAVAIL
);
411 return (__NSW_UNAVAIL
);
416 getmapkeys_nis(nsmap
, list
, error
, cache_time
, stack
, stkptr
)
418 struct dir_entry
**list
;
425 struct dir_cbdata readdir_cbdata
;
426 struct ypall_callback cback
;
429 char *key
= NULL
, *val
= NULL
;
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
) {
443 "getmapkeys_nis: memory alloc failed: %m");
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
) {
457 *error
= 0; /* return an empty list */
459 syslog(LOG_ERR
, "%s: %s",
460 nsmap
, yperr_string(nserr
));
463 return (nis_err(nserr
));
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
);
483 *error
= readdir_cbdata
.error
;
486 syslog(LOG_ERR
, "%s: %s", nsmap
, yperr_string(nserr
));
491 return (nis_err(nserr
));
494 return (__NSW_SUCCESS
);
498 readdir_callback(instatus
, inkey
, inkeylen
, inval
, invallen
, indata
)
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
== '#')
518 * yp_all allocates inkey with two extra bytes which contain
519 * NEWLINE and null but these two bytes are not reflected in
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')
534 if (add_dir_entry(key
, list
, &last
)) {
535 indata
->error
= ENOMEM
;
536 return (1); /* get no more entries */