1 /* 2 * Copyright 2004 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 NULL 61 }; 62 63 static char **shells, *strings; 64 static char **curshell; 65 static char **initshells(void); 66 67 /* 68 * Get a list of shells from SHELLS, if it exists. 69 */ 70 char * 71 getusershell(void) 72 { 73 char *ret; 74 75 if (curshell == NULL) 76 curshell = initshells(); 77 ret = *curshell; 78 if (ret != NULL) 79 curshell++; 80 return (ret); 81 } 82 83 void 84 endusershell(void) 85 { 86 87 if (shells != NULL) 88 (void) free((char *)shells); 89 shells = NULL; 90 if (strings != NULL) 91 (void) free(strings); 92 strings = NULL; 93 curshell = NULL; 94 } 95 96 void 97 setusershell(void) 98 { 99 100 curshell = initshells(); 101 } 102 103 static char ** 104 initshells(void) 105 { 106 char **sp, *cp; 107 FILE *fp; 108 struct stat statb; 109 110 if (shells != NULL) 111 (void) free((char *)shells); 112 shells = NULL; 113 if (strings != NULL) 114 (void) free(strings); 115 strings = NULL; 116 if ((fp = fopen(SHELLS, "r")) == (FILE *)0) 117 return ((char **)okshells); 118 /* 119 * The +1 in the malloc() below is needed to handle the final 120 * fgets() NULL terminator. From fgets(3S): 121 * 122 * char *fgets(char *s, int n, FILE *stream); 123 * 124 * The fgets() function reads characters from the stream into 125 * the array pointed to by s, until n-1 characters are read, or 126 * a newline character is read and transferred to s, or an end- 127 * of-file condition is encountered. The string is then termi- 128 * nated with a null character. 129 */ 130 if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) || 131 ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) { 132 (void) fclose(fp); 133 return ((char **)okshells); 134 } 135 shells = calloc((size_t)statb.st_size / 3, sizeof (char *)); 136 if (shells == NULL) { 137 (void) fclose(fp); 138 (void) free(strings); 139 strings = NULL; 140 return ((char **)okshells); 141 } 142 sp = shells; 143 cp = strings; 144 while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) { 145 while (*cp != '#' && *cp != '/' && *cp != '\0') 146 cp++; 147 if (*cp == '#' || *cp == '\0') 148 continue; 149 *sp++ = cp; 150 while (!isspace(*cp) && *cp != '#' && *cp != '\0') 151 cp++; 152 *cp++ = '\0'; 153 } 154 *sp = (char *)0; 155 (void) fclose(fp); 156 return (shells); 157 } 158