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