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