11573Srgrimes/*
21573Srgrimes * Copyright (c) 1985, 1993
31573Srgrimes *	The Regents of the University of California.  All rights reserved.
41573Srgrimes *
51573Srgrimes * Redistribution and use in source and binary forms, with or without
61573Srgrimes * modification, are permitted provided that the following conditions
71573Srgrimes * are met:
81573Srgrimes * 1. Redistributions of source code must retain the above copyright
91573Srgrimes *    notice, this list of conditions and the following disclaimer.
101573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111573Srgrimes *    notice, this list of conditions and the following disclaimer in the
121573Srgrimes *    documentation and/or other materials provided with the distribution.
131573Srgrimes * 4. Neither the name of the University nor the names of its contributors
141573Srgrimes *    may be used to endorse or promote products derived from this software
151573Srgrimes *    without specific prior written permission.
161573Srgrimes *
171573Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201573Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271573Srgrimes * SUCH DAMAGE.
281573Srgrimes */
291573Srgrimes
301573Srgrimes#if defined(LIBC_SCCS) && !defined(lint)
3189999Sobrienstatic char sccsid[] = "@(#)getusershell.c	8.1 (Berkeley) 6/4/93";
321573Srgrimes#endif /* LIBC_SCCS and not lint */
3390045Sobrien/*	$NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $	*/
3490030Sobrien#include <sys/cdefs.h>
3589999Sobrien__FBSDID("$FreeBSD: releng/10.3/lib/libc/gen/getusershell.c 244092 2012-12-10 17:56:51Z jilles $");
361573Srgrimes
37113984Snectar#include "namespace.h"
381573Srgrimes#include <sys/param.h>
391573Srgrimes#include <sys/file.h>
4065532Snectar
4165532Snectar#include <ctype.h>
4265532Snectar#include <errno.h>
4365532Snectar#include <nsswitch.h>
4465532Snectar#include <paths.h>
451573Srgrimes#include <stdio.h>
461573Srgrimes#include <stdlib.h>
4765532Snectar#include <string.h>
4865532Snectar#include <stringlist.h>
491573Srgrimes#include <unistd.h>
501573Srgrimes
5165532Snectar#ifdef HESIOD
5265532Snectar#include <hesiod.h>
5365532Snectar#endif
5465532Snectar#ifdef YP
5565532Snectar#include <rpc/rpc.h>
5665532Snectar#include <rpcsvc/ypclnt.h>
5765532Snectar#include <rpcsvc/yp_prot.h>
5865532Snectar#endif
59113984Snectar#include "un-namespace.h"
6065532Snectar
6165532Snectarstatic const char *const *curshell;
6265532Snectarstatic StringList	 *sl;
631573Srgrimes
6490045Sobrienstatic const char *const *initshells(void);
6565532Snectar
661573Srgrimes/*
6765532Snectar * Get a list of shells from "shells" nsswitch database
681573Srgrimes */
691573Srgrimeschar *
7065532Snectargetusershell(void)
711573Srgrimes{
721573Srgrimes	char *ret;
731573Srgrimes
741573Srgrimes	if (curshell == NULL)
751573Srgrimes		curshell = initshells();
7665532Snectar	/*LINTED*/
7765532Snectar	ret = (char *)*curshell;
781573Srgrimes	if (ret != NULL)
791573Srgrimes		curshell++;
801573Srgrimes	return (ret);
811573Srgrimes}
821573Srgrimes
831573Srgrimesvoid
8465532Snectarendusershell(void)
851573Srgrimes{
86112407Srobert	if (sl) {
8765532Snectar		sl_free(sl, 1);
88112407Srobert		sl = NULL;
89112407Srobert	}
901573Srgrimes	curshell = NULL;
911573Srgrimes}
921573Srgrimes
931573Srgrimesvoid
9465532Snectarsetusershell(void)
951573Srgrimes{
961573Srgrimes
971573Srgrimes	curshell = initshells();
981573Srgrimes}
991573Srgrimes
10065532Snectar
10190045Sobrienstatic int	_local_initshells(void *, void *, va_list);
10265532Snectar
10365532Snectar/*ARGSUSED*/
10465532Snectarstatic int
10565532Snectar_local_initshells(rv, cb_data, ap)
10665532Snectar	void	*rv;
10765532Snectar	void	*cb_data;
10865532Snectar	va_list	 ap;
1091573Srgrimes{
11065532Snectar	char	*sp, *cp;
11165532Snectar	FILE	*fp;
11265532Snectar	char	 line[MAXPATHLEN + 2];
1131573Srgrimes
11465532Snectar	if (sl)
11565532Snectar		sl_free(sl, 1);
11665532Snectar	sl = sl_init();
11765532Snectar
118244092Sjilles	if ((fp = fopen(_PATH_SHELLS, "re")) == NULL)
11965532Snectar		return NS_UNAVAIL;
12065532Snectar
121199784Swollman	cp = line;
1221573Srgrimes	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
1231573Srgrimes		while (*cp != '#' && *cp != '/' && *cp != '\0')
1241573Srgrimes			cp++;
1251573Srgrimes		if (*cp == '#' || *cp == '\0')
1261573Srgrimes			continue;
12765532Snectar		sp = cp;
12865532Snectar		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
1291573Srgrimes			cp++;
1301573Srgrimes		*cp++ = '\0';
13165532Snectar		sl_add(sl, strdup(sp));
1321573Srgrimes	}
1331573Srgrimes	(void)fclose(fp);
13465532Snectar	return NS_SUCCESS;
1351573Srgrimes}
13665532Snectar
13765532Snectar#ifdef HESIOD
13890045Sobrienstatic int	_dns_initshells(void *, void *, va_list);
13965532Snectar
14065532Snectar/*ARGSUSED*/
14165532Snectarstatic int
14265532Snectar_dns_initshells(rv, cb_data, ap)
14365532Snectar	void	*rv;
14465532Snectar	void	*cb_data;
14565532Snectar	va_list	 ap;
14665532Snectar{
14765532Snectar	char	  shellname[] = "shells-XXXXX";
14865532Snectar	int	  hsindex, hpi, r;
14965532Snectar	char	**hp;
15065532Snectar	void	 *context;
15165532Snectar
15265532Snectar	if (sl)
15365532Snectar		sl_free(sl, 1);
15465532Snectar	sl = sl_init();
15565532Snectar	r = NS_UNAVAIL;
15665532Snectar	if (hesiod_init(&context) == -1)
15765532Snectar		return (r);
15865532Snectar
15965532Snectar	for (hsindex = 0; ; hsindex++) {
16065532Snectar		snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex);
16165532Snectar		hp = hesiod_resolve(context, shellname, "shells");
16265532Snectar		if (hp == NULL) {
16365532Snectar			if (errno == ENOENT) {
16465532Snectar				if (hsindex == 0)
16565532Snectar					r = NS_NOTFOUND;
16665532Snectar				else
16765532Snectar					r = NS_SUCCESS;
16865532Snectar			}
16965532Snectar			break;
17065532Snectar		} else {
17165532Snectar			for (hpi = 0; hp[hpi]; hpi++)
17265532Snectar				sl_add(sl, hp[hpi]);
17365532Snectar			free(hp);
17465532Snectar		}
17565532Snectar	}
17665532Snectar	hesiod_end(context);
17765532Snectar	return (r);
17865532Snectar}
17965532Snectar#endif /* HESIOD */
18065532Snectar
18165532Snectar#ifdef YP
18290045Sobrienstatic int	_nis_initshells(void *, void *, va_list);
18365532Snectar
18465532Snectar/*ARGSUSED*/
18565532Snectarstatic int
18665532Snectar_nis_initshells(rv, cb_data, ap)
18765532Snectar	void	*rv;
18865532Snectar	void	*cb_data;
18965532Snectar	va_list	 ap;
19065532Snectar{
19165532Snectar	static char *ypdomain;
192112407Srobert	char	*key, *data;
193112407Srobert	char	*lastkey;
194112407Srobert	int	 keylen, datalen;
195112407Srobert	int	 r;
19665532Snectar
19765532Snectar	if (sl)
19865532Snectar		sl_free(sl, 1);
19965532Snectar	sl = sl_init();
20065532Snectar
20165532Snectar	if (ypdomain == NULL) {
20265532Snectar		switch (yp_get_default_domain(&ypdomain)) {
20365532Snectar		case 0:
20465532Snectar			break;
20565532Snectar		case YPERR_RESRC:
20665532Snectar			return NS_TRYAGAIN;
20765532Snectar		default:
20865532Snectar			return NS_UNAVAIL;
20965532Snectar		}
21065532Snectar	}
21165532Snectar
212112407Srobert	/*
213112407Srobert	 * `key' and `data' point to strings dynamically allocated by
214112407Srobert	 * the yp_... functions.
215112407Srobert	 * `data' is directly put into the stringlist of shells.
216112407Srobert	 */
217112407Srobert	key = data = NULL;
218112407Srobert	if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen))
219112407Srobert		return NS_UNAVAIL;
220112407Srobert	do {
22165532Snectar		data[datalen] = '\0';		/* clear trailing \n */
22265532Snectar		sl_add(sl, data);
223112407Srobert
224112407Srobert		lastkey = key;
225112407Srobert		r = yp_next(ypdomain, "shells", lastkey, keylen,
226112407Srobert		    &key, &keylen, &data, &datalen);
227112407Srobert		free(lastkey);
228112407Srobert	} while (r == 0);
229112407Srobert
230112407Srobert	if (r == YPERR_NOMORE) {
231112407Srobert		/*
232112407Srobert		 * `data' and `key' ought to be NULL - do not try to free them.
233112407Srobert		 */
234112407Srobert		return NS_SUCCESS;
23565532Snectar	}
236112407Srobert
237112407Srobert	return NS_UNAVAIL;
23865532Snectar}
23965532Snectar#endif /* YP */
24065532Snectar
24165532Snectarstatic const char *const *
24265532Snectarinitshells()
24365532Snectar{
24465532Snectar	static const ns_dtab dtab[] = {
24565532Snectar		NS_FILES_CB(_local_initshells, NULL)
24665532Snectar		NS_DNS_CB(_dns_initshells, NULL)
24765532Snectar		NS_NIS_CB(_nis_initshells, NULL)
24865532Snectar		{ 0 }
24965532Snectar	};
25065532Snectar	if (sl)
25165532Snectar		sl_free(sl, 1);
25265532Snectar	sl = sl_init();
25365532Snectar
254113984Snectar	if (_nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc)
25565532Snectar	    != NS_SUCCESS) {
25665532Snectar		if (sl)
25765532Snectar			sl_free(sl, 1);
258228922Sjilles		sl = sl_init();
259228922Sjilles		/*
260228922Sjilles		 * Local shells should NOT be added here.  They should be
261228922Sjilles		 * added in /etc/shells.
262228922Sjilles		 */
263228922Sjilles		sl_add(sl, strdup(_PATH_BSHELL));
264228922Sjilles		sl_add(sl, strdup(_PATH_CSHELL));
26565532Snectar	}
26665532Snectar	sl_add(sl, NULL);
26765532Snectar
26865532Snectar	return (const char *const *)(sl->sl_str);
26965532Snectar}
270