diff options
author | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
---|---|---|
committer | nectar <nectar@FreeBSD.org> | 2000-09-06 18:16:48 +0000 |
commit | 748554442d0ac4467fdac2ce9d42006588fd4481 (patch) | |
tree | aed2ddbcac97f46f60ee9c2063a3345553f6a1ee /lib/libc/gen/getusershell.c | |
parent | 59ffb36b778f8e629622726f6bd32dfa4fda7e35 (diff) | |
download | FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.zip FreeBSD-src-748554442d0ac4467fdac2ce9d42006588fd4481.tar.gz |
Add nsswitch support. By creating an /etc/nsswitch.conf file, you can
configure FreeBSD so that various databases such as passwd and group can be
looked up using flat files, NIS, or Hesiod.
= Hesiod has been added to libc (see hesiod(3)).
= A library routine for parsing nsswitch.conf and invoking callback
functions as specified has been added to libc (see nsdispatch(3)).
= The following C library functions have been modified to use nsdispatch:
. getgrent, getgrnam, getgrgid
. getpwent, getpwnam, getpwuid
. getusershell
. getaddrinfo
. gethostbyname, gethostbyname2, gethostbyaddr
. getnetbyname, getnetbyaddr
. getipnodebyname, getipnodebyaddr, getnodebyname, getnodebyaddr
= host.conf has been removed from src/etc. rc.network has been modified
to warn that host.conf is no longer used at boot time. In addition, if
there is a host.conf but no nsswitch.conf, the latter is created at boot
time from the former.
Obtained from: NetBSD
Diffstat (limited to 'lib/libc/gen/getusershell.c')
-rw-r--r-- | lib/libc/gen/getusershell.c | 249 |
1 files changed, 194 insertions, 55 deletions
diff --git a/lib/libc/gen/getusershell.c b/lib/libc/gen/getusershell.c index be1a77a..a852421 100644 --- a/lib/libc/gen/getusershell.c +++ b/lib/libc/gen/getusershell.c @@ -1,3 +1,5 @@ +/* $NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $ */ + /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. @@ -29,111 +31,248 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include <sys/cdefs.h> #if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93"; +static char rcsid[] = + "$FreeBSD$"; #endif /* LIBC_SCCS and not lint */ #include <sys/param.h> #include <sys/file.h> -#include <sys/stat.h> -#include <stdio.h> + #include <ctype.h> +#include <errno.h> +#include <nsswitch.h> +#include <paths.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h> +#include <stringlist.h> #include <unistd.h> -#include <paths.h> + +#ifdef HESIOD +#include <hesiod.h> +#endif +#ifdef YP +#include <rpc/rpc.h> +#include <rpcsvc/ypclnt.h> +#include <rpcsvc/yp_prot.h> +#endif /* * Local shells should NOT be added here. They should be added in * /etc/shells. */ -static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; -static char **curshell, **shells, *strings; -static char **initshells __P((void)); +static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; +static const char *const *curshell; +static StringList *sl; + +static const char *const *initshells __P((void)); /* - * Get a list of shells from _PATH_SHELLS, if it exists. + * Get a list of shells from "shells" nsswitch database */ char * -getusershell() +getusershell(void) { char *ret; if (curshell == NULL) curshell = initshells(); - ret = *curshell; + /*LINTED*/ + ret = (char *)*curshell; if (ret != NULL) curshell++; return (ret); } void -endusershell() +endusershell(void) { - - if (shells != NULL) - free(shells); - shells = NULL; - if (strings != NULL) - free(strings); - strings = NULL; + if (sl) + sl_free(sl, 1); + sl = NULL; curshell = NULL; } void -setusershell() +setusershell(void) { curshell = initshells(); } -static char ** -initshells() + +static int _local_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_local_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; { - register char **sp, *cp; - register FILE *fp; - struct stat statb; - - if (shells != NULL) - free(shells); - shells = NULL; - if (strings != NULL) - free(strings); - strings = NULL; + char *sp, *cp; + FILE *fp; + char line[MAXPATHLEN + 2]; + + if (sl) + sl_free(sl, 1); + sl = sl_init(); + if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) - return (okshells); - if (fstat(fileno(fp), &statb) == -1) { - (void)fclose(fp); - return (okshells); - } - if ((strings = malloc((u_int)statb.st_size)) == NULL) { - (void)fclose(fp); - return (okshells); - } - shells = calloc((unsigned)statb.st_size / 3, sizeof (char *)); - if (shells == NULL) { - (void)fclose(fp); - free(strings); - strings = NULL; - return (okshells); - } - sp = shells; - cp = strings; + return NS_UNAVAIL; + + sp = cp = line; while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { while (*cp != '#' && *cp != '/' && *cp != '\0') cp++; if (*cp == '#' || *cp == '\0') continue; - *sp++ = cp; - while (!isspace((unsigned char)*cp) && *cp != '#' && *cp != '\0') + sp = cp; + while (!isspace(*cp) && *cp != '#' && *cp != '\0') cp++; *cp++ = '\0'; + sl_add(sl, strdup(sp)); } - *sp = NULL; (void)fclose(fp); - return (shells); + return NS_SUCCESS; +} + +#ifdef HESIOD +static int _dns_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_dns_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + char shellname[] = "shells-XXXXX"; + int hsindex, hpi, r; + char **hp; + void *context; + + if (sl) + sl_free(sl, 1); + sl = sl_init(); + r = NS_UNAVAIL; + if (hesiod_init(&context) == -1) + return (r); + + for (hsindex = 0; ; hsindex++) { + snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex); + hp = hesiod_resolve(context, shellname, "shells"); + if (hp == NULL) { + if (errno == ENOENT) { + if (hsindex == 0) + r = NS_NOTFOUND; + else + r = NS_SUCCESS; + } + break; + } else { + for (hpi = 0; hp[hpi]; hpi++) + sl_add(sl, hp[hpi]); + free(hp); + } + } + hesiod_end(context); + return (r); +} +#endif /* HESIOD */ + +#ifdef YP +static int _nis_initshells __P((void *, void *, va_list)); + +/*ARGSUSED*/ +static int +_nis_initshells(rv, cb_data, ap) + void *rv; + void *cb_data; + va_list ap; +{ + static char *ypdomain; + + if (sl) + sl_free(sl, 1); + sl = sl_init(); + + if (ypdomain == NULL) { + switch (yp_get_default_domain(&ypdomain)) { + case 0: + break; + case YPERR_RESRC: + return NS_TRYAGAIN; + default: + return NS_UNAVAIL; + } + } + + for (;;) { + char *ypcur = NULL; + int ypcurlen = 0; /* XXX: GCC */ + char *key, *data; + int keylen, datalen; + int r; + + key = data = NULL; + if (ypcur) { + r = yp_next(ypdomain, "shells", ypcur, ypcurlen, + &key, &keylen, &data, &datalen); + free(ypcur); + switch (r) { + case 0: + break; + case YPERR_NOMORE: + free(key); + free(data); + return NS_SUCCESS; + default: + free(key); + free(data); + return NS_UNAVAIL; + } + ypcur = key; + ypcurlen = keylen; + } else { + if (yp_first(ypdomain, "shells", &ypcur, + &ypcurlen, &data, &datalen)) { + free(data); + return NS_UNAVAIL; + } + } + data[datalen] = '\0'; /* clear trailing \n */ + sl_add(sl, data); + } +} +#endif /* YP */ + +static const char *const * +initshells() +{ + static const ns_dtab dtab[] = { + NS_FILES_CB(_local_initshells, NULL) + NS_DNS_CB(_dns_initshells, NULL) + NS_NIS_CB(_nis_initshells, NULL) + { 0 } + }; + if (sl) + sl_free(sl, 1); + sl = sl_init(); + + if (nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc) + != NS_SUCCESS) { + if (sl) + sl_free(sl, 1); + sl = NULL; + return (okshells); + } + sl_add(sl, NULL); + + return (const char *const *)(sl->sl_str); } |