1/*	$NetBSD: getusershell.c,v 1.1.1.1 2011/04/13 18:15:41 elric Exp $	*/
2
3/*
4 * Copyright (c) 1985, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <config.h>
33
34#ifndef HAVE_GETUSERSHELL
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <ctype.h>
40#ifdef HAVE_PATHS_H
41#include <paths.h>
42#endif
43#ifdef HAVE_SYS_TYPES_H
44#include <sys/types.h>
45#endif
46#ifdef HAVE_SYS_STAT_H
47#include <sys/stat.h>
48#endif
49#ifdef HAVE_SYS_PARAM_H
50#include <sys/param.h>
51#endif
52
53#ifdef HAVE_USERSEC_H
54struct aud_rec;
55#include <usersec.h>
56#endif
57#ifdef HAVE_USERCONF_H
58#include <userconf.h>
59#endif
60#include <krb5/roken.h>
61
62#ifndef _PATH_SHELLS
63#define _PATH_SHELLS "/etc/shells"
64#endif
65
66#ifndef _PATH_BSHELL
67#define _PATH_BSHELL "/bin/sh"
68#endif
69
70#ifndef _PATH_CSHELL
71#define _PATH_CSHELL "/bin/csh"
72#endif
73
74/*
75 * Local shells should NOT be added here.  They should be added in
76 * /etc/shells.
77 */
78
79static char *okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
80static char **curshell, **shells, *strings;
81static char **initshells (void);
82
83/*
84 * Get a list of shells from _PATH_SHELLS, if it exists.
85 */
86ROKEN_LIB_FUNCTION char * ROKEN_LIB_CALL
87getusershell()
88{
89    char *ret;
90
91    if (curshell == NULL)
92	curshell = initshells();
93    ret = *curshell;
94    if (ret != NULL)
95	curshell++;
96    return (ret);
97}
98
99ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
100endusershell()
101{
102    if (shells != NULL)
103	free(shells);
104    shells = NULL;
105    if (strings != NULL)
106	free(strings);
107    strings = NULL;
108    curshell = NULL;
109}
110
111ROKEN_LIB_FUNCTION void ROKEN_LIB_CALL
112setusershell()
113{
114    curshell = initshells();
115}
116
117static char **
118initshells()
119{
120    char **sp, *cp;
121#ifdef HAVE_GETCONFATTR
122    char *tmp;
123    int nsh;
124#else
125    FILE *fp;
126#endif
127    struct stat statb;
128
129    free(shells);
130    shells = NULL;
131    free(strings);
132    strings = NULL;
133#ifdef HAVE_GETCONFATTR
134    if(getconfattr(SC_SYS_LOGIN, SC_SHELLS, &tmp, SEC_LIST) != 0)
135	return okshells;
136
137    for(cp = tmp, nsh = 0; *cp; cp += strlen(cp) + 1, nsh++);
138
139    shells = calloc(nsh + 1, sizeof(*shells));
140    if(shells == NULL)
141	return okshells;
142
143    strings = malloc(cp - tmp);
144    if(strings == NULL) {
145	free(shells);
146	shells = NULL;
147	return okshells;
148    }
149    memcpy(strings, tmp, cp - tmp);
150    for(sp = shells, cp = strings; *cp; cp += strlen(cp) + 1, sp++)
151	*sp = cp;
152#else
153    if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
154	return (okshells);
155    if (fstat(fileno(fp), &statb) == -1) {
156	fclose(fp);
157	return (okshells);
158    }
159    if ((strings = malloc((u_int)statb.st_size)) == NULL) {
160	fclose(fp);
161	return (okshells);
162    }
163    shells = calloc((unsigned)statb.st_size / 3, sizeof (char *));
164    if (shells == NULL) {
165	fclose(fp);
166	free(strings);
167	strings = NULL;
168	return (okshells);
169    }
170    sp = shells;
171    cp = strings;
172    while (fgets(cp, MaxPathLen + 1, fp) != NULL) {
173	while (*cp != '#' && *cp != '/' && *cp != '\0')
174	    cp++;
175	if (*cp == '#' || *cp == '\0')
176	    continue;
177	*sp++ = cp;
178	while (!isspace((unsigned char)*cp) && *cp != '#' && *cp != '\0')
179	    cp++;
180	*cp++ = '\0';
181    }
182    fclose(fp);
183#endif
184    *sp = NULL;
185    return (shells);
186}
187#endif /* HAVE_GETUSERSHELL */
188