1 /* 2 * Copyright (c) 1985, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifdef HAVE_CONFIG_H 35 #include <config.h> 36 #endif 37 38 RCSID("$Id: getusershell.c,v 1.10 2000/05/22 09:11:59 joda Exp $"); 39 40 #ifndef HAVE_GETUSERSHELL 41 42 #include <stdio.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #ifdef HAVE_PATHS_H 46 #include <paths.h> 47 #endif 48 #ifdef HAVE_SYS_TYPES_H 49 #include <sys/types.h> 50 #endif 51 #ifdef HAVE_SYS_STAT_H 52 #include <sys/stat.h> 53 #endif 54 #ifdef HAVE_SYS_PARAM_H 55 #include <sys/param.h> 56 #endif 57 58 #ifdef HAVE_USERSEC_H 59 struct aud_rec; 60 #include <usersec.h> 61 #endif 62 #ifdef HAVE_USERCONF_H 63 #include <userconf.h> 64 #endif 65 66 #ifndef _PATH_SHELLS 67 #define _PATH_SHELLS "/etc/shells" 68 #endif 69 70 #ifndef _PATH_BSHELL 71 #define _PATH_BSHELL "/bin/sh" 72 #endif 73 74 #ifndef _PATH_CSHELL 75 #define _PATH_CSHELL "/bin/csh" 76 #endif 77 78 /* 79 * Local shells should NOT be added here. They should be added in 80 * /etc/shells. 81 */ 82 83 static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; 84 static char **curshell, **shells, *strings; 85 static char **initshells (void); 86 87 /* 88 * Get a list of shells from _PATH_SHELLS, if it exists. 89 */ 90 char * 91 getusershell() 92 { 93 char *ret; 94 95 if (curshell == NULL) 96 curshell = initshells(); 97 ret = *curshell; 98 if (ret != NULL) 99 curshell++; 100 return (ret); 101 } 102 103 void 104 endusershell() 105 { 106 if (shells != NULL) 107 free(shells); 108 shells = NULL; 109 if (strings != NULL) 110 free(strings); 111 strings = NULL; 112 curshell = NULL; 113 } 114 115 void 116 setusershell() 117 { 118 curshell = initshells(); 119 } 120 121 static char ** 122 initshells() 123 { 124 char **sp, *cp; 125 #ifdef HAVE_GETCONFATTR 126 char *tmp; 127 int nsh; 128 #else 129 FILE *fp; 130 #endif 131 struct stat statb; 132 133 free(shells); 134 shells = NULL; 135 free(strings); 136 strings = NULL; 137 #ifdef HAVE_GETCONFATTR 138 if(getconfattr(SC_SYS_LOGIN, SC_SHELLS, &tmp, SEC_LIST) != 0) 139 return okshells; 140 141 for(cp = tmp, nsh = 0; *cp; cp += strlen(cp) + 1, nsh++); 142 143 shells = calloc(nsh + 1, sizeof(*shells)); 144 if(shells == NULL) 145 return okshells; 146 147 strings = malloc(cp - tmp); 148 if(strings == NULL) { 149 free(shells); 150 shells = NULL; 151 return okshells; 152 } 153 memcpy(strings, tmp, cp - tmp); 154 for(sp = shells, cp = strings; *cp; cp += strlen(cp) + 1, sp++) 155 *sp = cp; 156 #else 157 if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) 158 return (okshells); 159 if (fstat(fileno(fp), &statb) == -1) { 160 fclose(fp); 161 return (okshells); 162 } 163 if ((strings = malloc((u_int)statb.st_size)) == NULL) { 164 fclose(fp); 165 return (okshells); 166 } 167 shells = calloc((unsigned)statb.st_size / 3, sizeof (char *)); 168 if (shells == NULL) { 169 fclose(fp); 170 free(strings); 171 strings = NULL; 172 return (okshells); 173 } 174 sp = shells; 175 cp = strings; 176 while (fgets(cp, MaxPathLen + 1, fp) != NULL) { 177 while (*cp != '#' && *cp != '/' && *cp != '\0') 178 cp++; 179 if (*cp == '#' || *cp == '\0') 180 continue; 181 *sp++ = cp; 182 while (!isspace(*cp) && *cp != '#' && *cp != '\0') 183 cp++; 184 *cp++ = '\0'; 185 } 186 fclose(fp); 187 #endif 188 *sp = NULL; 189 return (shells); 190 } 191 #endif /* HAVE_GETUSERSHELL */ 192