getusershell.c revision 228922
1334592Sasomers/* 2334592Sasomers * Copyright (c) 1985, 1993 3334592Sasomers * The Regents of the University of California. All rights reserved. 4334592Sasomers * 5334592Sasomers * Redistribution and use in source and binary forms, with or without 6334592Sasomers * modification, are permitted provided that the following conditions 7334592Sasomers * are met: 8334592Sasomers * 1. Redistributions of source code must retain the above copyright 9334592Sasomers * notice, this list of conditions and the following disclaimer. 10334592Sasomers * 2. Redistributions in binary form must reproduce the above copyright 11334592Sasomers * notice, this list of conditions and the following disclaimer in the 12334592Sasomers * documentation and/or other materials provided with the distribution. 13334592Sasomers * 4. Neither the name of the University nor the names of its contributors 14334592Sasomers * may be used to endorse or promote products derived from this software 15334592Sasomers * without specific prior written permission. 16334592Sasomers * 17334592Sasomers * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18334592Sasomers * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19334592Sasomers * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20334592Sasomers * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21334592Sasomers * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22334592Sasomers * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23334592Sasomers * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24334592Sasomers * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25334592Sasomers * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26334592Sasomers * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27334592Sasomers * SUCH DAMAGE. 28334592Sasomers */ 29334592Sasomers 30334592Sasomers#if defined(LIBC_SCCS) && !defined(lint) 31334592Sasomersstatic char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93"; 32334592Sasomers#endif /* LIBC_SCCS and not lint */ 33334592Sasomers/* $NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $ */ 34334592Sasomers#include <sys/cdefs.h> 35334592Sasomers__FBSDID("$FreeBSD: head/lib/libc/gen/getusershell.c 228922 2011-12-27 23:35:10Z jilles $"); 36334592Sasomers 37334592Sasomers#include "namespace.h" 38334592Sasomers#include <sys/param.h> 39334592Sasomers#include <sys/file.h> 40334592Sasomers 41334592Sasomers#include <ctype.h> 42334592Sasomers#include <errno.h> 43339087Sasomers#include <nsswitch.h> 44334592Sasomers#include <paths.h> 45334592Sasomers#include <stdio.h> 46334592Sasomers#include <stdlib.h> 47334592Sasomers#include <string.h> 48334592Sasomers#include <stringlist.h> 49334592Sasomers#include <unistd.h> 50334592Sasomers 51334592Sasomers#ifdef HESIOD 52334592Sasomers#include <hesiod.h> 53334592Sasomers#endif 54334592Sasomers#ifdef YP 55334592Sasomers#include <rpc/rpc.h> 56334592Sasomers#include <rpcsvc/ypclnt.h> 57334592Sasomers#include <rpcsvc/yp_prot.h> 58334592Sasomers#endif 59334592Sasomers#include "un-namespace.h" 60334592Sasomers 61334592Sasomersstatic const char *const *curshell; 62334592Sasomersstatic StringList *sl; 63334592Sasomers 64334592Sasomersstatic const char *const *initshells(void); 65334592Sasomers 66334592Sasomers/* 67334592Sasomers * Get a list of shells from "shells" nsswitch database 68334592Sasomers */ 69334592Sasomerschar * 70334592Sasomersgetusershell(void) 71334592Sasomers{ 72334592Sasomers char *ret; 73334592Sasomers 74334592Sasomers if (curshell == NULL) 75334592Sasomers curshell = initshells(); 76334592Sasomers /*LINTED*/ 77334592Sasomers ret = (char *)*curshell; 78334592Sasomers if (ret != NULL) 79334592Sasomers curshell++; 80334592Sasomers return (ret); 81334592Sasomers} 82334592Sasomers 83334592Sasomersvoid 84334592Sasomersendusershell(void) 85334592Sasomers{ 86334592Sasomers if (sl) { 87334592Sasomers sl_free(sl, 1); 88334592Sasomers sl = NULL; 89334592Sasomers } 90334592Sasomers curshell = NULL; 91334592Sasomers} 92334592Sasomers 93334592Sasomersvoid 94334592Sasomerssetusershell(void) 95334592Sasomers{ 96334592Sasomers 97334592Sasomers curshell = initshells(); 98334592Sasomers} 99334592Sasomers 100334592Sasomers 101334592Sasomersstatic int _local_initshells(void *, void *, va_list); 102334592Sasomers 103334592Sasomers/*ARGSUSED*/ 104334592Sasomersstatic int 105334592Sasomers_local_initshells(rv, cb_data, ap) 106334592Sasomers void *rv; 107334592Sasomers void *cb_data; 108334592Sasomers va_list ap; 109334592Sasomers{ 110334592Sasomers char *sp, *cp; 111334592Sasomers FILE *fp; 112334592Sasomers char line[MAXPATHLEN + 2]; 113334592Sasomers 114334592Sasomers if (sl) 115334592Sasomers sl_free(sl, 1); 116334592Sasomers sl = sl_init(); 117334592Sasomers 118334592Sasomers if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) 119334592Sasomers return NS_UNAVAIL; 120334592Sasomers 121334592Sasomers cp = line; 122334592Sasomers while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { 123334592Sasomers while (*cp != '#' && *cp != '/' && *cp != '\0') 124334592Sasomers cp++; 125334592Sasomers if (*cp == '#' || *cp == '\0') 126334592Sasomers continue; 127334592Sasomers sp = cp; 128334592Sasomers while (!isspace(*cp) && *cp != '#' && *cp != '\0') 129334592Sasomers cp++; 130334592Sasomers *cp++ = '\0'; 131334592Sasomers sl_add(sl, strdup(sp)); 132334592Sasomers } 133334592Sasomers (void)fclose(fp); 134334592Sasomers return NS_SUCCESS; 135334592Sasomers} 136334592Sasomers 137334592Sasomers#ifdef HESIOD 138334592Sasomersstatic int _dns_initshells(void *, void *, va_list); 139334592Sasomers 140334592Sasomers/*ARGSUSED*/ 141334592Sasomersstatic int 142334592Sasomers_dns_initshells(rv, cb_data, ap) 143334592Sasomers void *rv; 144334592Sasomers void *cb_data; 145334592Sasomers va_list ap; 146334592Sasomers{ 147334592Sasomers char shellname[] = "shells-XXXXX"; 148334592Sasomers int hsindex, hpi, r; 149334592Sasomers char **hp; 150334592Sasomers void *context; 151334592Sasomers 152334592Sasomers if (sl) 153334592Sasomers sl_free(sl, 1); 154334592Sasomers sl = sl_init(); 155334592Sasomers r = NS_UNAVAIL; 156334592Sasomers if (hesiod_init(&context) == -1) 157334592Sasomers return (r); 158334592Sasomers 159334592Sasomers for (hsindex = 0; ; hsindex++) { 160334592Sasomers snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex); 161334592Sasomers hp = hesiod_resolve(context, shellname, "shells"); 162334592Sasomers if (hp == NULL) { 163334592Sasomers if (errno == ENOENT) { 164334592Sasomers if (hsindex == 0) 165334592Sasomers r = NS_NOTFOUND; 166334592Sasomers else 167334592Sasomers r = NS_SUCCESS; 168334592Sasomers } 169334592Sasomers break; 170334592Sasomers } else { 171334592Sasomers for (hpi = 0; hp[hpi]; hpi++) 172334592Sasomers sl_add(sl, hp[hpi]); 173334592Sasomers free(hp); 174334592Sasomers } 175334592Sasomers } 176334592Sasomers hesiod_end(context); 177334592Sasomers return (r); 178334592Sasomers} 179334592Sasomers#endif /* HESIOD */ 180334592Sasomers 181334592Sasomers#ifdef YP 182334592Sasomersstatic int _nis_initshells(void *, void *, va_list); 183334592Sasomers 184334592Sasomers/*ARGSUSED*/ 185334592Sasomersstatic int 186334592Sasomers_nis_initshells(rv, cb_data, ap) 187334592Sasomers void *rv; 188334592Sasomers void *cb_data; 189334592Sasomers va_list ap; 190339087Sasomers{ 191334592Sasomers static char *ypdomain; 192334592Sasomers char *key, *data; 193334592Sasomers char *lastkey; 194334592Sasomers int keylen, datalen; 195334592Sasomers int r; 196334592Sasomers 197334592Sasomers if (sl) 198334592Sasomers sl_free(sl, 1); 199334592Sasomers sl = sl_init(); 200334592Sasomers 201334592Sasomers if (ypdomain == NULL) { 202334592Sasomers switch (yp_get_default_domain(&ypdomain)) { 203334592Sasomers case 0: 204334592Sasomers break; 205334592Sasomers case YPERR_RESRC: 206334592Sasomers return NS_TRYAGAIN; 207334592Sasomers default: 208334592Sasomers return NS_UNAVAIL; 209334592Sasomers } 210334592Sasomers } 211334592Sasomers 212334592Sasomers /* 213334592Sasomers * `key' and `data' point to strings dynamically allocated by 214334592Sasomers * the yp_... functions. 215334592Sasomers * `data' is directly put into the stringlist of shells. 216334592Sasomers */ 217334592Sasomers key = data = NULL; 218334592Sasomers if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen)) 219334592Sasomers return NS_UNAVAIL; 220334592Sasomers do { 221334592Sasomers data[datalen] = '\0'; /* clear trailing \n */ 222334592Sasomers sl_add(sl, data); 223334592Sasomers 224334592Sasomers lastkey = key; 225334592Sasomers r = yp_next(ypdomain, "shells", lastkey, keylen, 226334592Sasomers &key, &keylen, &data, &datalen); 227334592Sasomers free(lastkey); 228334592Sasomers } while (r == 0); 229334592Sasomers 230334592Sasomers if (r == YPERR_NOMORE) { 231334592Sasomers /* 232334592Sasomers * `data' and `key' ought to be NULL - do not try to free them. 233334592Sasomers */ 234 return NS_SUCCESS; 235 } 236 237 return NS_UNAVAIL; 238} 239#endif /* YP */ 240 241static const char *const * 242initshells() 243{ 244 static const ns_dtab dtab[] = { 245 NS_FILES_CB(_local_initshells, NULL) 246 NS_DNS_CB(_dns_initshells, NULL) 247 NS_NIS_CB(_nis_initshells, NULL) 248 { 0 } 249 }; 250 if (sl) 251 sl_free(sl, 1); 252 sl = sl_init(); 253 254 if (_nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc) 255 != NS_SUCCESS) { 256 if (sl) 257 sl_free(sl, 1); 258 sl = sl_init(); 259 /* 260 * Local shells should NOT be added here. They should be 261 * added in /etc/shells. 262 */ 263 sl_add(sl, strdup(_PATH_BSHELL)); 264 sl_add(sl, strdup(_PATH_CSHELL)); 265 } 266 sl_add(sl, NULL); 267 268 return (const char *const *)(sl->sl_str); 269} 270