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$"); 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 611573Srgrimes/* 621573Srgrimes * Local shells should NOT be added here. They should be added in 631573Srgrimes * /etc/shells. 641573Srgrimes */ 651573Srgrimes 6665532Snectarstatic const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; 6765532Snectarstatic const char *const *curshell; 6865532Snectarstatic StringList *sl; 691573Srgrimes 7090045Sobrienstatic const char *const *initshells(void); 7165532Snectar 721573Srgrimes/* 7365532Snectar * Get a list of shells from "shells" nsswitch database 741573Srgrimes */ 751573Srgrimeschar * 7665532Snectargetusershell(void) 771573Srgrimes{ 781573Srgrimes char *ret; 791573Srgrimes 801573Srgrimes if (curshell == NULL) 811573Srgrimes curshell = initshells(); 8265532Snectar /*LINTED*/ 8365532Snectar ret = (char *)*curshell; 841573Srgrimes if (ret != NULL) 851573Srgrimes curshell++; 861573Srgrimes return (ret); 871573Srgrimes} 881573Srgrimes 891573Srgrimesvoid 9065532Snectarendusershell(void) 911573Srgrimes{ 92112407Srobert if (sl) { 9365532Snectar sl_free(sl, 1); 94112407Srobert sl = NULL; 95112407Srobert } 961573Srgrimes curshell = NULL; 971573Srgrimes} 981573Srgrimes 991573Srgrimesvoid 10065532Snectarsetusershell(void) 1011573Srgrimes{ 1021573Srgrimes 1031573Srgrimes curshell = initshells(); 1041573Srgrimes} 1051573Srgrimes 10665532Snectar 10790045Sobrienstatic int _local_initshells(void *, void *, va_list); 10865532Snectar 10965532Snectar/*ARGSUSED*/ 11065532Snectarstatic int 11165532Snectar_local_initshells(rv, cb_data, ap) 11265532Snectar void *rv; 11365532Snectar void *cb_data; 11465532Snectar va_list ap; 1151573Srgrimes{ 11665532Snectar char *sp, *cp; 11765532Snectar FILE *fp; 11865532Snectar char line[MAXPATHLEN + 2]; 1191573Srgrimes 12065532Snectar if (sl) 12165532Snectar sl_free(sl, 1); 12265532Snectar sl = sl_init(); 12365532Snectar 1241573Srgrimes if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) 12565532Snectar return NS_UNAVAIL; 12665532Snectar 127199784Swollman cp = line; 1281573Srgrimes while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { 1291573Srgrimes while (*cp != '#' && *cp != '/' && *cp != '\0') 1301573Srgrimes cp++; 1311573Srgrimes if (*cp == '#' || *cp == '\0') 1321573Srgrimes continue; 13365532Snectar sp = cp; 13465532Snectar while (!isspace(*cp) && *cp != '#' && *cp != '\0') 1351573Srgrimes cp++; 1361573Srgrimes *cp++ = '\0'; 13765532Snectar sl_add(sl, strdup(sp)); 1381573Srgrimes } 1391573Srgrimes (void)fclose(fp); 14065532Snectar return NS_SUCCESS; 1411573Srgrimes} 14265532Snectar 14365532Snectar#ifdef HESIOD 14490045Sobrienstatic int _dns_initshells(void *, void *, va_list); 14565532Snectar 14665532Snectar/*ARGSUSED*/ 14765532Snectarstatic int 14865532Snectar_dns_initshells(rv, cb_data, ap) 14965532Snectar void *rv; 15065532Snectar void *cb_data; 15165532Snectar va_list ap; 15265532Snectar{ 15365532Snectar char shellname[] = "shells-XXXXX"; 15465532Snectar int hsindex, hpi, r; 15565532Snectar char **hp; 15665532Snectar void *context; 15765532Snectar 15865532Snectar if (sl) 15965532Snectar sl_free(sl, 1); 16065532Snectar sl = sl_init(); 16165532Snectar r = NS_UNAVAIL; 16265532Snectar if (hesiod_init(&context) == -1) 16365532Snectar return (r); 16465532Snectar 16565532Snectar for (hsindex = 0; ; hsindex++) { 16665532Snectar snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex); 16765532Snectar hp = hesiod_resolve(context, shellname, "shells"); 16865532Snectar if (hp == NULL) { 16965532Snectar if (errno == ENOENT) { 17065532Snectar if (hsindex == 0) 17165532Snectar r = NS_NOTFOUND; 17265532Snectar else 17365532Snectar r = NS_SUCCESS; 17465532Snectar } 17565532Snectar break; 17665532Snectar } else { 17765532Snectar for (hpi = 0; hp[hpi]; hpi++) 17865532Snectar sl_add(sl, hp[hpi]); 17965532Snectar free(hp); 18065532Snectar } 18165532Snectar } 18265532Snectar hesiod_end(context); 18365532Snectar return (r); 18465532Snectar} 18565532Snectar#endif /* HESIOD */ 18665532Snectar 18765532Snectar#ifdef YP 18890045Sobrienstatic int _nis_initshells(void *, void *, va_list); 18965532Snectar 19065532Snectar/*ARGSUSED*/ 19165532Snectarstatic int 19265532Snectar_nis_initshells(rv, cb_data, ap) 19365532Snectar void *rv; 19465532Snectar void *cb_data; 19565532Snectar va_list ap; 19665532Snectar{ 19765532Snectar static char *ypdomain; 198112407Srobert char *key, *data; 199112407Srobert char *lastkey; 200112407Srobert int keylen, datalen; 201112407Srobert int r; 20265532Snectar 20365532Snectar if (sl) 20465532Snectar sl_free(sl, 1); 20565532Snectar sl = sl_init(); 20665532Snectar 20765532Snectar if (ypdomain == NULL) { 20865532Snectar switch (yp_get_default_domain(&ypdomain)) { 20965532Snectar case 0: 21065532Snectar break; 21165532Snectar case YPERR_RESRC: 21265532Snectar return NS_TRYAGAIN; 21365532Snectar default: 21465532Snectar return NS_UNAVAIL; 21565532Snectar } 21665532Snectar } 21765532Snectar 218112407Srobert /* 219112407Srobert * `key' and `data' point to strings dynamically allocated by 220112407Srobert * the yp_... functions. 221112407Srobert * `data' is directly put into the stringlist of shells. 222112407Srobert */ 223112407Srobert key = data = NULL; 224112407Srobert if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen)) 225112407Srobert return NS_UNAVAIL; 226112407Srobert do { 22765532Snectar data[datalen] = '\0'; /* clear trailing \n */ 22865532Snectar sl_add(sl, data); 229112407Srobert 230112407Srobert lastkey = key; 231112407Srobert r = yp_next(ypdomain, "shells", lastkey, keylen, 232112407Srobert &key, &keylen, &data, &datalen); 233112407Srobert free(lastkey); 234112407Srobert } while (r == 0); 235112407Srobert 236112407Srobert if (r == YPERR_NOMORE) { 237112407Srobert /* 238112407Srobert * `data' and `key' ought to be NULL - do not try to free them. 239112407Srobert */ 240112407Srobert return NS_SUCCESS; 24165532Snectar } 242112407Srobert 243112407Srobert return NS_UNAVAIL; 24465532Snectar} 24565532Snectar#endif /* YP */ 24665532Snectar 24765532Snectarstatic const char *const * 24865532Snectarinitshells() 24965532Snectar{ 25065532Snectar static const ns_dtab dtab[] = { 25165532Snectar NS_FILES_CB(_local_initshells, NULL) 25265532Snectar NS_DNS_CB(_dns_initshells, NULL) 25365532Snectar NS_NIS_CB(_nis_initshells, NULL) 25465532Snectar { 0 } 25565532Snectar }; 25665532Snectar if (sl) 25765532Snectar sl_free(sl, 1); 25865532Snectar sl = sl_init(); 25965532Snectar 260113984Snectar if (_nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc) 26165532Snectar != NS_SUCCESS) { 26265532Snectar if (sl) 26365532Snectar sl_free(sl, 1); 26465532Snectar sl = NULL; 26565532Snectar return (okshells); 26665532Snectar } 26765532Snectar sl_add(sl, NULL); 26865532Snectar 26965532Snectar return (const char *const *)(sl->sl_str); 27065532Snectar} 271