1 /* 2 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 9 /* All Rights Reserved */ 10 11 12 /* 13 * Copyright (c) 1985 Regents of the University of California. 14 * All rights reserved. The Berkeley software License Agreement 15 * specifies the terms and conditions for redistribution. 16 */ 17 18 #include "synonyms.h" 19 #include <sys/types.h> 20 #include <sys/param.h> 21 #include <sys/stat.h> 22 #include <ctype.h> 23 #include <stdio.h> 24 #include <limits.h> 25 #include <stdlib.h> 26 #include <sys/file.h> 27 #include "libc.h" 28 #include <unistd.h> 29 30 #define SHELLS "/etc/shells" 31 32 /* 33 * Do not add local shells here. They should be added in /etc/shells 34 */ 35 const char *okshells[] = { 36 "/usr/bin/sh", 37 "/usr/bin/csh", 38 "/usr/bin/ksh", 39 "/usr/bin/jsh", 40 "/bin/sh", 41 "/bin/csh", 42 "/bin/ksh", 43 "/bin/jsh", 44 "/sbin/sh", 45 "/sbin/jsh", 46 "/usr/bin/pfsh", 47 "/usr/bin/pfcsh", 48 "/usr/bin/pfksh", 49 "/usr/bin/bash", 50 "/usr/bin/tcsh", 51 "/usr/bin/zsh", 52 "/bin/pfsh", 53 "/bin/pfcsh", 54 "/bin/pfksh", 55 "/bin/bash", 56 "/bin/tcsh", 57 "/bin/zsh", 58 "/usr/xpg4/bin/sh", 59 "/sbin/pfsh", 60 "/usr/sfw/bin/zsh", 61 NULL 62 }; 63 64 static char **shells, *strings; 65 static char **curshell; 66 static char **initshells(void); 67 68 /* 69 * Get a list of shells from SHELLS, if it exists. 70 */ 71 char * 72 getusershell(void) 73 { 74 char *ret; 75 76 if (curshell == NULL) 77 curshell = initshells(); 78 ret = *curshell; 79 if (ret != NULL) 80 curshell++; 81 return (ret); 82 } 83 84 void 85 endusershell(void) 86 { 87 88 if (shells != NULL) 89 (void) free((char *)shells); 90 shells = NULL; 91 if (strings != NULL) 92 (void) free(strings); 93 strings = NULL; 94 curshell = NULL; 95 } 96 97 void 98 setusershell(void) 99 { 100 101 curshell = initshells(); 102 } 103 104 static char ** 105 initshells(void) 106 { 107 char **sp, *cp; 108 FILE *fp; 109 struct stat statb; 110 111 if (shells != NULL) 112 (void) free((char *)shells); 113 shells = NULL; 114 if (strings != NULL) 115 (void) free(strings); 116 strings = NULL; 117 if ((fp = fopen(SHELLS, "rF")) == (FILE *)0) 118 return ((char **)okshells); 119 /* 120 * The +1 in the malloc() below is needed to handle the final 121 * fgets() NULL terminator. From fgets(3S): 122 * 123 * char *fgets(char *s, int n, FILE *stream); 124 * 125 * The fgets() function reads characters from the stream into 126 * the array pointed to by s, until n-1 characters are read, or 127 * a newline character is read and transferred to s, or an end- 128 * of-file condition is encountered. The string is then termi- 129 * nated with a null character. 130 */ 131 if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) || 132 ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) { 133 (void) fclose(fp); 134 return ((char **)okshells); 135 } 136 shells = calloc((size_t)statb.st_size / 3, sizeof (char *)); 137 if (shells == NULL) { 138 (void) fclose(fp); 139 (void) free(strings); 140 strings = NULL; 141 return ((char **)okshells); 142 } 143 sp = shells; 144 cp = strings; 145 while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { 146 while (*cp != '#' && *cp != '/' && *cp != '\0') 147 cp++; 148 if (*cp == '#' || *cp == '\0') 149 continue; 150 *sp++ = cp; 151 while (!isspace(*cp) && *cp != '#' && *cp != '\0') 152 cp++; 153 *cp++ = '\0'; 154 } 155 *sp = (char *)0; 156 (void) fclose(fp); 157 return (shells); 158 } 159