1248aee62SJacques Vidrine /* $NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $ */ 2248aee62SJacques Vidrine 358f0484fSRodney W. Grimes /* 458f0484fSRodney W. Grimes * Copyright (c) 1985, 1993 558f0484fSRodney W. Grimes * The Regents of the University of California. All rights reserved. 658f0484fSRodney W. Grimes * 758f0484fSRodney W. Grimes * Redistribution and use in source and binary forms, with or without 858f0484fSRodney W. Grimes * modification, are permitted provided that the following conditions 958f0484fSRodney W. Grimes * are met: 1058f0484fSRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 1158f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer. 1258f0484fSRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 1358f0484fSRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 1458f0484fSRodney W. Grimes * documentation and/or other materials provided with the distribution. 1558f0484fSRodney W. Grimes * 3. All advertising materials mentioning features or use of this software 1658f0484fSRodney W. Grimes * must display the following acknowledgement: 1758f0484fSRodney W. Grimes * This product includes software developed by the University of 1858f0484fSRodney W. Grimes * California, Berkeley and its contributors. 1958f0484fSRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 2058f0484fSRodney W. Grimes * may be used to endorse or promote products derived from this software 2158f0484fSRodney W. Grimes * without specific prior written permission. 2258f0484fSRodney W. Grimes * 2358f0484fSRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2458f0484fSRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2558f0484fSRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2658f0484fSRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2758f0484fSRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2858f0484fSRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2958f0484fSRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3058f0484fSRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3158f0484fSRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3258f0484fSRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3358f0484fSRodney W. Grimes * SUCH DAMAGE. 3458f0484fSRodney W. Grimes */ 3558f0484fSRodney W. Grimes 36ec4c2e36SDavid E. O'Brien #if 0 3758f0484fSRodney W. Grimes #if defined(LIBC_SCCS) && !defined(lint) 38135b57f9SDavid E. O'Brien static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93"; 3958f0484fSRodney W. Grimes #endif /* LIBC_SCCS and not lint */ 40ec4c2e36SDavid E. O'Brien #endif 41ec4c2e36SDavid E. O'Brien #include <sys/cdefs.h> 42135b57f9SDavid E. O'Brien __FBSDID("$FreeBSD$"); 4358f0484fSRodney W. Grimes 4458f0484fSRodney W. Grimes #include <sys/param.h> 4558f0484fSRodney W. Grimes #include <sys/file.h> 46248aee62SJacques Vidrine 4758f0484fSRodney W. Grimes #include <ctype.h> 48248aee62SJacques Vidrine #include <errno.h> 49248aee62SJacques Vidrine #include <nsswitch.h> 5058f0484fSRodney W. Grimes #include <paths.h> 51248aee62SJacques Vidrine #include <stdio.h> 52248aee62SJacques Vidrine #include <stdlib.h> 53248aee62SJacques Vidrine #include <string.h> 54248aee62SJacques Vidrine #include <stringlist.h> 55248aee62SJacques Vidrine #include <unistd.h> 56248aee62SJacques Vidrine 57248aee62SJacques Vidrine #ifdef HESIOD 58248aee62SJacques Vidrine #include <hesiod.h> 59248aee62SJacques Vidrine #endif 60248aee62SJacques Vidrine #ifdef YP 61248aee62SJacques Vidrine #include <rpc/rpc.h> 62248aee62SJacques Vidrine #include <rpcsvc/ypclnt.h> 63248aee62SJacques Vidrine #include <rpcsvc/yp_prot.h> 64248aee62SJacques Vidrine #endif 6558f0484fSRodney W. Grimes 6658f0484fSRodney W. Grimes /* 6758f0484fSRodney W. Grimes * Local shells should NOT be added here. They should be added in 6858f0484fSRodney W. Grimes * /etc/shells. 6958f0484fSRodney W. Grimes */ 7058f0484fSRodney W. Grimes 71248aee62SJacques Vidrine static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; 72248aee62SJacques Vidrine static const char *const *curshell; 73248aee62SJacques Vidrine static StringList *sl; 74248aee62SJacques Vidrine 75248aee62SJacques Vidrine static const char *const *initshells __P((void)); 7658f0484fSRodney W. Grimes 7758f0484fSRodney W. Grimes /* 78248aee62SJacques Vidrine * Get a list of shells from "shells" nsswitch database 7958f0484fSRodney W. Grimes */ 8058f0484fSRodney W. Grimes char * 81248aee62SJacques Vidrine getusershell(void) 8258f0484fSRodney W. Grimes { 8358f0484fSRodney W. Grimes char *ret; 8458f0484fSRodney W. Grimes 8558f0484fSRodney W. Grimes if (curshell == NULL) 8658f0484fSRodney W. Grimes curshell = initshells(); 87248aee62SJacques Vidrine /*LINTED*/ 88248aee62SJacques Vidrine ret = (char *)*curshell; 8958f0484fSRodney W. Grimes if (ret != NULL) 9058f0484fSRodney W. Grimes curshell++; 9158f0484fSRodney W. Grimes return (ret); 9258f0484fSRodney W. Grimes } 9358f0484fSRodney W. Grimes 9458f0484fSRodney W. Grimes void 95248aee62SJacques Vidrine endusershell(void) 9658f0484fSRodney W. Grimes { 97248aee62SJacques Vidrine if (sl) 98248aee62SJacques Vidrine sl_free(sl, 1); 99248aee62SJacques Vidrine sl = NULL; 10058f0484fSRodney W. Grimes curshell = NULL; 10158f0484fSRodney W. Grimes } 10258f0484fSRodney W. Grimes 10358f0484fSRodney W. Grimes void 104248aee62SJacques Vidrine setusershell(void) 10558f0484fSRodney W. Grimes { 10658f0484fSRodney W. Grimes 10758f0484fSRodney W. Grimes curshell = initshells(); 10858f0484fSRodney W. Grimes } 10958f0484fSRodney W. Grimes 11058f0484fSRodney W. Grimes 111248aee62SJacques Vidrine static int _local_initshells __P((void *, void *, va_list)); 112248aee62SJacques Vidrine 113248aee62SJacques Vidrine /*ARGSUSED*/ 114248aee62SJacques Vidrine static int 115248aee62SJacques Vidrine _local_initshells(rv, cb_data, ap) 116248aee62SJacques Vidrine void *rv; 117248aee62SJacques Vidrine void *cb_data; 118248aee62SJacques Vidrine va_list ap; 119248aee62SJacques Vidrine { 120248aee62SJacques Vidrine char *sp, *cp; 121248aee62SJacques Vidrine FILE *fp; 122248aee62SJacques Vidrine char line[MAXPATHLEN + 2]; 123248aee62SJacques Vidrine 124248aee62SJacques Vidrine if (sl) 125248aee62SJacques Vidrine sl_free(sl, 1); 126248aee62SJacques Vidrine sl = sl_init(); 127248aee62SJacques Vidrine 12858f0484fSRodney W. Grimes if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) 129248aee62SJacques Vidrine return NS_UNAVAIL; 130248aee62SJacques Vidrine 131248aee62SJacques Vidrine sp = cp = line; 13258f0484fSRodney W. Grimes while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { 13358f0484fSRodney W. Grimes while (*cp != '#' && *cp != '/' && *cp != '\0') 13458f0484fSRodney W. Grimes cp++; 13558f0484fSRodney W. Grimes if (*cp == '#' || *cp == '\0') 13658f0484fSRodney W. Grimes continue; 137248aee62SJacques Vidrine sp = cp; 138248aee62SJacques Vidrine while (!isspace(*cp) && *cp != '#' && *cp != '\0') 13958f0484fSRodney W. Grimes cp++; 14058f0484fSRodney W. Grimes *cp++ = '\0'; 141248aee62SJacques Vidrine sl_add(sl, strdup(sp)); 14258f0484fSRodney W. Grimes } 14358f0484fSRodney W. Grimes (void)fclose(fp); 144248aee62SJacques Vidrine return NS_SUCCESS; 145248aee62SJacques Vidrine } 146248aee62SJacques Vidrine 147248aee62SJacques Vidrine #ifdef HESIOD 148248aee62SJacques Vidrine static int _dns_initshells __P((void *, void *, va_list)); 149248aee62SJacques Vidrine 150248aee62SJacques Vidrine /*ARGSUSED*/ 151248aee62SJacques Vidrine static int 152248aee62SJacques Vidrine _dns_initshells(rv, cb_data, ap) 153248aee62SJacques Vidrine void *rv; 154248aee62SJacques Vidrine void *cb_data; 155248aee62SJacques Vidrine va_list ap; 156248aee62SJacques Vidrine { 157248aee62SJacques Vidrine char shellname[] = "shells-XXXXX"; 158248aee62SJacques Vidrine int hsindex, hpi, r; 159248aee62SJacques Vidrine char **hp; 160248aee62SJacques Vidrine void *context; 161248aee62SJacques Vidrine 162248aee62SJacques Vidrine if (sl) 163248aee62SJacques Vidrine sl_free(sl, 1); 164248aee62SJacques Vidrine sl = sl_init(); 165248aee62SJacques Vidrine r = NS_UNAVAIL; 166248aee62SJacques Vidrine if (hesiod_init(&context) == -1) 167248aee62SJacques Vidrine return (r); 168248aee62SJacques Vidrine 169248aee62SJacques Vidrine for (hsindex = 0; ; hsindex++) { 170248aee62SJacques Vidrine snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex); 171248aee62SJacques Vidrine hp = hesiod_resolve(context, shellname, "shells"); 172248aee62SJacques Vidrine if (hp == NULL) { 173248aee62SJacques Vidrine if (errno == ENOENT) { 174248aee62SJacques Vidrine if (hsindex == 0) 175248aee62SJacques Vidrine r = NS_NOTFOUND; 176248aee62SJacques Vidrine else 177248aee62SJacques Vidrine r = NS_SUCCESS; 178248aee62SJacques Vidrine } 179248aee62SJacques Vidrine break; 180248aee62SJacques Vidrine } else { 181248aee62SJacques Vidrine for (hpi = 0; hp[hpi]; hpi++) 182248aee62SJacques Vidrine sl_add(sl, hp[hpi]); 183248aee62SJacques Vidrine free(hp); 184248aee62SJacques Vidrine } 185248aee62SJacques Vidrine } 186248aee62SJacques Vidrine hesiod_end(context); 187248aee62SJacques Vidrine return (r); 188248aee62SJacques Vidrine } 189248aee62SJacques Vidrine #endif /* HESIOD */ 190248aee62SJacques Vidrine 191248aee62SJacques Vidrine #ifdef YP 192248aee62SJacques Vidrine static int _nis_initshells __P((void *, void *, va_list)); 193248aee62SJacques Vidrine 194248aee62SJacques Vidrine /*ARGSUSED*/ 195248aee62SJacques Vidrine static int 196248aee62SJacques Vidrine _nis_initshells(rv, cb_data, ap) 197248aee62SJacques Vidrine void *rv; 198248aee62SJacques Vidrine void *cb_data; 199248aee62SJacques Vidrine va_list ap; 200248aee62SJacques Vidrine { 201248aee62SJacques Vidrine static char *ypdomain; 202248aee62SJacques Vidrine 203248aee62SJacques Vidrine if (sl) 204248aee62SJacques Vidrine sl_free(sl, 1); 205248aee62SJacques Vidrine sl = sl_init(); 206248aee62SJacques Vidrine 207248aee62SJacques Vidrine if (ypdomain == NULL) { 208248aee62SJacques Vidrine switch (yp_get_default_domain(&ypdomain)) { 209248aee62SJacques Vidrine case 0: 210248aee62SJacques Vidrine break; 211248aee62SJacques Vidrine case YPERR_RESRC: 212248aee62SJacques Vidrine return NS_TRYAGAIN; 213248aee62SJacques Vidrine default: 214248aee62SJacques Vidrine return NS_UNAVAIL; 215248aee62SJacques Vidrine } 216248aee62SJacques Vidrine } 217248aee62SJacques Vidrine 218248aee62SJacques Vidrine for (;;) { 219248aee62SJacques Vidrine char *ypcur = NULL; 220248aee62SJacques Vidrine int ypcurlen = 0; /* XXX: GCC */ 221248aee62SJacques Vidrine char *key, *data; 222248aee62SJacques Vidrine int keylen, datalen; 223248aee62SJacques Vidrine int r; 224248aee62SJacques Vidrine 225248aee62SJacques Vidrine key = data = NULL; 226248aee62SJacques Vidrine if (ypcur) { 227248aee62SJacques Vidrine r = yp_next(ypdomain, "shells", ypcur, ypcurlen, 228248aee62SJacques Vidrine &key, &keylen, &data, &datalen); 229248aee62SJacques Vidrine free(ypcur); 230248aee62SJacques Vidrine switch (r) { 231248aee62SJacques Vidrine case 0: 232248aee62SJacques Vidrine break; 233248aee62SJacques Vidrine case YPERR_NOMORE: 234248aee62SJacques Vidrine free(key); 235248aee62SJacques Vidrine free(data); 236248aee62SJacques Vidrine return NS_SUCCESS; 237248aee62SJacques Vidrine default: 238248aee62SJacques Vidrine free(key); 239248aee62SJacques Vidrine free(data); 240248aee62SJacques Vidrine return NS_UNAVAIL; 241248aee62SJacques Vidrine } 242248aee62SJacques Vidrine ypcur = key; 243248aee62SJacques Vidrine ypcurlen = keylen; 244248aee62SJacques Vidrine } else { 245248aee62SJacques Vidrine if (yp_first(ypdomain, "shells", &ypcur, 246248aee62SJacques Vidrine &ypcurlen, &data, &datalen)) { 247248aee62SJacques Vidrine free(data); 248248aee62SJacques Vidrine return NS_UNAVAIL; 249248aee62SJacques Vidrine } 250248aee62SJacques Vidrine } 251248aee62SJacques Vidrine data[datalen] = '\0'; /* clear trailing \n */ 252248aee62SJacques Vidrine sl_add(sl, data); 253248aee62SJacques Vidrine } 254248aee62SJacques Vidrine } 255248aee62SJacques Vidrine #endif /* YP */ 256248aee62SJacques Vidrine 257248aee62SJacques Vidrine static const char *const * 258248aee62SJacques Vidrine initshells() 259248aee62SJacques Vidrine { 260248aee62SJacques Vidrine static const ns_dtab dtab[] = { 261248aee62SJacques Vidrine NS_FILES_CB(_local_initshells, NULL) 262248aee62SJacques Vidrine NS_DNS_CB(_dns_initshells, NULL) 263248aee62SJacques Vidrine NS_NIS_CB(_nis_initshells, NULL) 264248aee62SJacques Vidrine { 0 } 265248aee62SJacques Vidrine }; 266248aee62SJacques Vidrine if (sl) 267248aee62SJacques Vidrine sl_free(sl, 1); 268248aee62SJacques Vidrine sl = sl_init(); 269248aee62SJacques Vidrine 270248aee62SJacques Vidrine if (nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc) 271248aee62SJacques Vidrine != NS_SUCCESS) { 272248aee62SJacques Vidrine if (sl) 273248aee62SJacques Vidrine sl_free(sl, 1); 274248aee62SJacques Vidrine sl = NULL; 275248aee62SJacques Vidrine return (okshells); 276248aee62SJacques Vidrine } 277248aee62SJacques Vidrine sl_add(sl, NULL); 278248aee62SJacques Vidrine 279248aee62SJacques Vidrine return (const char *const *)(sl->sl_str); 28058f0484fSRodney W. Grimes } 281