getusershell.c revision 722:636b850d4ee9
1/*
2 * Copyright (c) 1985 Regents of the University of California.
3 * All rights reserved.  The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#pragma ident	"%Z%%M%	%I%	%E% SMI"
8
9#include <sys/param.h>
10#include <sys/file.h>
11#include <sys/stat.h>
12#include <ctype.h>
13#include <stdio.h>
14#include <malloc.h>
15
16#define SHELLS "/etc/shells"
17
18/*
19 * Do not add local shells here.  They should be added in /etc/shells
20 */
21static char *okshells[] =
22    { "/bin/sh", "/bin/csh", "/usr/bin/sh", "/usr/bin/csh", 0 };
23
24static char **shells, *strings;
25static char **curshell;
26
27static char **initshells(void);
28
29/*
30 * Get a list of shells from SHELLS, if it exists.
31 */
32char *
33getusershell(void)
34{
35	char *ret;
36
37	if (curshell == NULL)
38		curshell = initshells();
39	ret = *curshell;
40	if (ret != NULL)
41		curshell++;
42	return (ret);
43}
44
45void
46endusershell(void)
47{
48
49	if (shells != NULL)
50		free((char *)shells);
51	shells = NULL;
52	if (strings != NULL)
53		free(strings);
54	strings = NULL;
55	curshell = NULL;
56}
57
58void
59setusershell(void)
60{
61
62	curshell = initshells();
63}
64
65static char **
66initshells(void)
67{
68	char **sp, *cp;
69	FILE *fp;
70	struct stat statb;
71
72	if (shells != NULL)
73		free((char *)shells);
74	shells = NULL;
75	if (strings != NULL)
76		free(strings);
77	strings = NULL;
78	if ((fp = fopen(SHELLS, "r")) == (FILE *)0)
79		return (okshells);
80	if (fstat(fileno(fp), &statb) == -1) {
81		(void)fclose(fp);
82		return (okshells);
83	}
84	if ((strings = malloc((unsigned)statb.st_size + 1)) == NULL) {
85		(void)fclose(fp);
86		return (okshells);
87	}
88	shells = (char **)calloc((unsigned)statb.st_size / 3, sizeof (char *));
89	if (shells == NULL) {
90		(void)fclose(fp);
91		free(strings);
92		strings = NULL;
93		return (okshells);
94	}
95	sp = shells;
96	cp = strings;
97	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
98		while (*cp != '#' && *cp != '/' && *cp != '\0')
99			cp++;
100		if (*cp == '#' || *cp == '\0')
101			continue;
102		*sp++ = cp;
103		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
104			cp++;
105		*cp++ = '\0';
106	}
107	*sp = (char *)0;
108	(void)fclose(fp);
109	return (shells);
110}
111