getusershell.c revision 1.5.10.5 1 /* $NetBSD: getusershell.c,v 1.5.10.5 1998/11/02 03:33:15 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1985, 1993
5 * The Regents of the University of California. All rights reserved.
6 * Portions Copyright (c) 1997
7 * Luke Mewburn <lukem (at) netbsd.org>. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the University of
20 * California, Berkeley and its contributors.
21 * 4. Neither the name of the University nor the names of its contributors
22 * may be used to endorse or promote products derived from this software
23 * without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * SUCH DAMAGE.
36 */
37
38 #include <sys/cdefs.h>
39 #if defined(LIBC_SCCS) && !defined(lint)
40 #if 0
41 static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93";
42 #else
43 __RCSID("$NetBSD: getusershell.c,v 1.5.10.5 1998/11/02 03:33:15 lukem Exp $");
44 #endif
45 #endif /* LIBC_SCCS and not lint */
46
47 #include "namespace.h"
48 #include <sys/param.h>
49 #include <sys/file.h>
50 #include <stdio.h>
51 #include <ctype.h>
52 #include <nsswitch.h>
53 #include <stdlib.h>
54 #include <unistd.h>
55 #include <paths.h>
56 #include <string.h>
57 #include <stringlist.h>
58 #ifdef HESIOD
59 #include <hesiod.h>
60 #endif
61 #ifdef YP
62 #include <rpc/rpc.h>
63 #include <rpcsvc/ypclnt.h>
64 #include <rpcsvc/yp_prot.h>
65 #endif
66
67 #ifdef __weak_alias
68 __weak_alias(endusershell,_endusershell);
69 __weak_alias(getusershell,_getusershell);
70 __weak_alias(setusershell,_setusershell);
71 #endif
72
73 /*
74 * Local shells should NOT be added here. They should be added in
75 * /etc/shells.
76 */
77
78 static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
79 static const char *const *curshell;
80 static StringList *sl;
81
82 static const char *const *initshells __P((void));
83
84 /*
85 * Get a list of shells from "shells" nsswitch database
86 */
87 __aconst char *
88 getusershell()
89 {
90 __aconst char *ret;
91
92 if (curshell == NULL)
93 curshell = initshells();
94 ret = (__aconst char *)*curshell;
95 if (ret != NULL)
96 curshell++;
97 return (ret);
98 }
99
100 void
101 endusershell()
102 {
103 if (sl)
104 sl_free(sl, 1);
105 sl = NULL;
106 curshell = NULL;
107 }
108
109 void
110 setusershell()
111 {
112
113 curshell = initshells();
114 }
115
116
117 static int _local_initshells __P((void *, void *, va_list));
118
119 static int
120 _local_initshells(rv, cb_data, ap)
121 void *rv;
122 void *cb_data;
123 va_list ap;
124 {
125 char *sp, *cp;
126 FILE *fp;
127 char line[MAXPATHLEN + 2];
128
129 if (sl)
130 sl_free(sl, 1);
131 sl = sl_init();
132
133 if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
134 return NS_UNAVAIL;
135
136 sp = cp = line;
137 while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
138 while (*cp != '#' && *cp != '/' && *cp != '\0')
139 cp++;
140 if (*cp == '#' || *cp == '\0')
141 continue;
142 sp = cp;
143 while (!isspace(*cp) && *cp != '#' && *cp != '\0')
144 cp++;
145 *cp++ = '\0';
146 sl_add(sl, strdup(sp));
147 }
148 (void)fclose(fp);
149 return NS_SUCCESS;
150 }
151
152 #ifdef HESIOD
153 static int _dns_initshells __P((void *, void *, va_list));
154
155 static int
156 _dns_initshells(rv, cb_data, ap)
157 void *rv;
158 void *cb_data;
159 va_list ap;
160 {
161 char shellname[] = "shells-XXXXX";
162 int hsindex, hpi;
163 char **hp;
164
165 if (sl)
166 sl_free(sl, 1);
167 sl = sl_init();
168
169 for (hsindex = 0; ; hsindex++) {
170 snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex);
171 hp = hes_resolve(shellname, "shells");
172 if (hp == NULL) {
173 switch(hes_error()) {
174 case HES_ER_OK:
175 break;
176 case HES_ER_NOTFOUND:
177 if (hsindex == 0)
178 return NS_NOTFOUND;
179 return NS_SUCCESS;
180 default:
181 return NS_UNAVAIL;
182 }
183 } else {
184 for (hpi = 0; hp[hpi]; hpi++)
185 sl_add(sl, hp[hpi]);
186 free(hp);
187 }
188 }
189 return NS_SUCCESS;
190 }
191 #endif /* HESIOD */
192
193 #ifdef YP
194 static int _nis_initshells __P((void *, void *, va_list));
195
196 static int
197 _nis_initshells(rv, cb_data, ap)
198 void *rv;
199 void *cb_data;
200 va_list ap;
201 {
202 static char *ypdomain;
203
204 if (sl)
205 sl_free(sl, 1);
206 sl = sl_init();
207
208 if (ypdomain == NULL) {
209 switch (yp_get_default_domain(&ypdomain)) {
210 case 0:
211 break;
212 case YPERR_RESRC:
213 return NS_TRYAGAIN;
214 default:
215 return NS_UNAVAIL;
216 }
217 }
218
219 for (;;) {
220 char *ypcur = NULL;
221 int ypcurlen;
222 char *key, *data;
223 int keylen, datalen;
224 int r;
225
226 key = data = NULL;
227 if (ypcur) {
228 r = yp_next(ypdomain, "shells", ypcur, ypcurlen,
229 &key, &keylen, &data, &datalen);
230 free(ypcur);
231 switch (r) {
232 case 0:
233 break;
234 case YPERR_NOMORE:
235 free(key);
236 free(data);
237 return NS_SUCCESS;
238 default:
239 free(key);
240 free(data);
241 return NS_UNAVAIL;
242 }
243 ypcur = key;
244 ypcurlen = keylen;
245 } else {
246 if (yp_first(ypdomain, "shells", &ypcur,
247 &ypcurlen, &data, &datalen)) {
248 free(data);
249 return NS_UNAVAIL;
250 }
251 }
252 data[datalen] = '\0'; /* clear trailing \n */
253 sl_add(sl, data);
254 }
255 return NS_SUCCESS;
256 }
257 #endif /* YP */
258
259 static const char *const *
260 initshells()
261 {
262 static ns_dtab dtab;
263
264 if (dtab[NS_FILES].cb == NULL) {
265 NS_FILES_CB(dtab, _local_initshells, NULL);
266 NS_DNS_CB(dtab, _dns_initshells, NULL);
267 NS_NIS_CB(dtab, _nis_initshells, NULL);
268 }
269
270 if (sl)
271 sl_free(sl, 1);
272 sl = sl_init();
273
274 if (nsdispatch(NULL, dtab, NSDB_SHELLS) != NS_SUCCESS) {
275 if (sl)
276 sl_free(sl, 1);
277 sl = NULL;
278 return (okshells);
279 }
280 sl_add(sl, NULL);
281
282 return (const char *const *)(sl->sl_str);
283 }
284