1 /*
2 * Copyright (c) 1985, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #if defined(LIBC_SCCS) && !defined(lint)
9 static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 06/04/93";
10 #endif /* LIBC_SCCS and not lint */
11
12 #include <sys/param.h>
13 #include <sys/file.h>
14 #include <sys/stat.h>
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <stdlib.h>
18 #include <unistd.h>
19 #include <paths.h>
20
21 /*
22 * Local shells should NOT be added here. They should be added in
23 * /etc/shells.
24 */
25
26 static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
27 static char **curshell, **shells, *strings;
28 static char **initshells __P((void));
29
30 /*
31 * Get a list of shells from _PATH_SHELLS, if it exists.
32 */
33 char *
getusershell()34 getusershell()
35 {
36 char *ret;
37
38 if (curshell == NULL)
39 curshell = initshells();
40 ret = *curshell;
41 if (ret != NULL)
42 curshell++;
43 return (ret);
44 }
45
46 void
endusershell()47 endusershell()
48 {
49
50 if (shells != NULL)
51 free(shells);
52 shells = NULL;
53 if (strings != NULL)
54 free(strings);
55 strings = NULL;
56 curshell = NULL;
57 }
58
59 void
setusershell()60 setusershell()
61 {
62
63 curshell = initshells();
64 }
65
66 static char **
initshells()67 initshells()
68 {
69 register char **sp, *cp;
70 register FILE *fp;
71 struct stat statb;
72
73 if (shells != NULL)
74 free(shells);
75 shells = NULL;
76 if (strings != NULL)
77 free(strings);
78 strings = NULL;
79 if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
80 return (okshells);
81 if (fstat(fileno(fp), &statb) == -1) {
82 (void)fclose(fp);
83 return (okshells);
84 }
85 if ((strings = malloc((u_int)statb.st_size)) == NULL) {
86 (void)fclose(fp);
87 return (okshells);
88 }
89 shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
90 if (shells == NULL) {
91 (void)fclose(fp);
92 free(strings);
93 strings = NULL;
94 return (okshells);
95 }
96 sp = shells;
97 cp = strings;
98 while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
99 while (*cp != '#' && *cp != '/' && *cp != '\0')
100 cp++;
101 if (*cp == '#' || *cp == '\0')
102 continue;
103 *sp++ = cp;
104 while (!isspace(*cp) && *cp != '#' && *cp != '\0')
105 cp++;
106 *cp++ = '\0';
107 }
108 *sp = NULL;
109 (void)fclose(fp);
110 return (shells);
111 }
112