import less(1)
[unleashed/tickless.git] / usr / src / lib / libc / port / gen / getusershell.c
blobe4a9fc612019a510e9d150917781242c68df590f
1 /*
2 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
3 */
5 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
6 /* All Rights Reserved */
8 /*
9 * Copyright (c) 1985 Regents of the University of California.
10 * All rights reserved. The Berkeley software License Agreement
11 * specifies the terms and conditions for redistribution.
14 #include "lint.h"
15 #include <sys/types.h>
16 #include <sys/param.h>
17 #include <sys/stat.h>
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <limits.h>
21 #include <stdlib.h>
22 #include <sys/file.h>
23 #include "libc.h"
24 #include <unistd.h>
26 #define SHELLS "/etc/shells"
29 * Do not add local shells here. They should be added in /etc/shells
31 * Do not add restricted shells:
32 * Shells returned by getusershell traditionally allow:
33 * - users to change away from (i.e., if you have an rksh in
34 * getusershell(), then users can change their shell to ksh)
35 * - by default, ftp in is allowed only for shells returned by
36 * getusershell(); since FTP has no restrictions on directory
37 * movement, adding rksh to getusershell() would defeat that
38 * protection.
40 const char *okshells[] = {
41 "/usr/bin/sh",
42 "/usr/bin/csh",
43 "/usr/bin/ksh",
44 "/usr/bin/ksh93",
45 "/usr/bin/jsh",
46 "/bin/sh",
47 "/bin/csh",
48 "/bin/ksh",
49 "/bin/ksh93",
50 "/bin/jsh",
51 "/sbin/sh",
52 "/sbin/jsh",
53 "/usr/bin/pfsh",
54 "/usr/bin/pfcsh",
55 "/usr/bin/pfksh",
56 "/usr/bin/pfksh93",
57 "/usr/bin/bash",
58 "/usr/bin/tcsh",
59 "/usr/bin/zsh",
60 "/usr/bin/pfbash",
61 "/usr/bin/pftcsh",
62 "/usr/bin/pfzsh",
63 "/bin/pfsh",
64 "/bin/pfcsh",
65 "/bin/pfksh",
66 "/bin/pfksh93",
67 "/bin/bash",
68 "/bin/tcsh",
69 "/bin/zsh",
70 "/bin/pfbash",
71 "/bin/pftcsh",
72 "/bin/pfzsh",
73 "/sbin/pfsh",
74 "/usr/sfw/bin/zsh",
75 NULL
78 static char **shells, *strings;
79 static char **curshell;
80 static char **initshells(void);
83 * Get a list of shells from SHELLS, if it exists.
85 char *
86 getusershell(void)
88 char *ret;
90 if (curshell == NULL)
91 curshell = initshells();
92 ret = *curshell;
93 if (ret != NULL)
94 curshell++;
95 return (ret);
98 void
99 endusershell(void)
102 if (shells != NULL)
103 (void) free((char *)shells);
104 shells = NULL;
105 if (strings != NULL)
106 (void) free(strings);
107 strings = NULL;
108 curshell = NULL;
111 void
112 setusershell(void)
115 curshell = initshells();
118 static char **
119 initshells(void)
121 char **sp, *cp;
122 FILE *fp;
123 struct stat statb;
125 if (shells != NULL)
126 (void) free((char *)shells);
127 shells = NULL;
128 if (strings != NULL)
129 (void) free(strings);
130 strings = NULL;
131 if ((fp = fopen(SHELLS, "rF")) == (FILE *)0)
132 return ((char **)okshells);
134 * The +1 in the malloc() below is needed to handle the final
135 * fgets() NULL terminator. From fgets(3S):
137 * char *fgets(char *s, int n, FILE *stream);
139 * The fgets() function reads characters from the stream into
140 * the array pointed to by s, until n-1 characters are read, or
141 * a newline character is read and transferred to s, or an end-
142 * of-file condition is encountered. The string is then termi-
143 * nated with a null character.
145 if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) ||
146 ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) {
147 (void) fclose(fp);
148 return ((char **)okshells);
150 shells = calloc((size_t)statb.st_size / 3, sizeof (char *));
151 if (shells == NULL) {
152 (void) fclose(fp);
153 (void) free(strings);
154 strings = NULL;
155 return ((char **)okshells);
157 sp = shells;
158 cp = strings;
159 while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
160 while (*cp != '#' && *cp != '/' && *cp != '\0')
161 cp++;
162 if (*cp == '#' || *cp == '\0')
163 continue;
164 *sp++ = cp;
165 while (!isspace(*cp) && *cp != '#' && *cp != '\0')
166 cp++;
167 *cp++ = '\0';
169 *sp = NULL;
170 (void) fclose(fp);
171 return (shells);