xref: /titanic_44/usr/src/lib/libc/port/gen/getusershell.c (revision 134a1f4e3289b54e0f980e9cf05352e419a60bee)
17c478bd9Sstevel@tonic-gate /*
2*134a1f4eSCasper H.S. Dik  * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate  */
47c478bd9Sstevel@tonic-gate 
57c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
67c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
77c478bd9Sstevel@tonic-gate 
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate  * Copyright (c) 1985 Regents of the University of California.
107c478bd9Sstevel@tonic-gate  * All rights reserved.  The Berkeley software License Agreement
117c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
127c478bd9Sstevel@tonic-gate  */
137c478bd9Sstevel@tonic-gate 
147257d1b4Sraf #include "lint.h"
157c478bd9Sstevel@tonic-gate #include <sys/types.h>
167c478bd9Sstevel@tonic-gate #include <sys/param.h>
177c478bd9Sstevel@tonic-gate #include <sys/stat.h>
187c478bd9Sstevel@tonic-gate #include <ctype.h>
197c478bd9Sstevel@tonic-gate #include <stdio.h>
207c478bd9Sstevel@tonic-gate #include <limits.h>
217c478bd9Sstevel@tonic-gate #include <stdlib.h>
227c478bd9Sstevel@tonic-gate #include <sys/file.h>
237c478bd9Sstevel@tonic-gate #include "libc.h"
247c478bd9Sstevel@tonic-gate #include <unistd.h>
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #define	SHELLS "/etc/shells"
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * Do not add local shells here.  They should be added in /etc/shells
30da2e3ebdSchin  *
31da2e3ebdSchin  * Do not add restricted shells:
32da2e3ebdSchin  * Shells returned by getusershell traditionally allow:
33da2e3ebdSchin  * - users to change away from (i.e., if you have an rksh in
34da2e3ebdSchin  *   getusershell(), then users can change their shell to ksh)
35da2e3ebdSchin  * - by default, ftp in is allowed only for shells returned by
36da2e3ebdSchin  *   getusershell(); since FTP has no restrictions on directory
37da2e3ebdSchin  *   movement, adding rksh to getusershell() would defeat that
38da2e3ebdSchin  *   protection.
397c478bd9Sstevel@tonic-gate  */
407c478bd9Sstevel@tonic-gate const char *okshells[] = {
417c478bd9Sstevel@tonic-gate 	"/usr/bin/sh",
427c478bd9Sstevel@tonic-gate 	"/usr/bin/csh",
437c478bd9Sstevel@tonic-gate 	"/usr/bin/ksh",
44da2e3ebdSchin 	"/usr/bin/ksh93",
457c478bd9Sstevel@tonic-gate 	"/usr/bin/jsh",
467c478bd9Sstevel@tonic-gate 	"/bin/sh",
477c478bd9Sstevel@tonic-gate 	"/bin/csh",
487c478bd9Sstevel@tonic-gate 	"/bin/ksh",
49da2e3ebdSchin 	"/bin/ksh93",
507c478bd9Sstevel@tonic-gate 	"/bin/jsh",
517c478bd9Sstevel@tonic-gate 	"/sbin/sh",
527c478bd9Sstevel@tonic-gate 	"/sbin/jsh",
537c478bd9Sstevel@tonic-gate 	"/usr/bin/pfsh",
547c478bd9Sstevel@tonic-gate 	"/usr/bin/pfcsh",
557c478bd9Sstevel@tonic-gate 	"/usr/bin/pfksh",
56*134a1f4eSCasper H.S. Dik 	"/usr/bin/pfksh93",
577c478bd9Sstevel@tonic-gate 	"/usr/bin/bash",
587c478bd9Sstevel@tonic-gate 	"/usr/bin/tcsh",
597c478bd9Sstevel@tonic-gate 	"/usr/bin/zsh",
60*134a1f4eSCasper H.S. Dik 	"/usr/bin/pfbash",
61*134a1f4eSCasper H.S. Dik 	"/usr/bin/pftcsh",
62*134a1f4eSCasper H.S. Dik 	"/usr/bin/pfzsh",
637c478bd9Sstevel@tonic-gate 	"/bin/pfsh",
647c478bd9Sstevel@tonic-gate 	"/bin/pfcsh",
657c478bd9Sstevel@tonic-gate 	"/bin/pfksh",
66*134a1f4eSCasper H.S. Dik 	"/bin/pfksh93",
677c478bd9Sstevel@tonic-gate 	"/bin/bash",
687c478bd9Sstevel@tonic-gate 	"/bin/tcsh",
697c478bd9Sstevel@tonic-gate 	"/bin/zsh",
70*134a1f4eSCasper H.S. Dik 	"/bin/pfbash",
71*134a1f4eSCasper H.S. Dik 	"/bin/pftcsh",
72*134a1f4eSCasper H.S. Dik 	"/bin/pfzsh",
737c478bd9Sstevel@tonic-gate 	"/usr/xpg4/bin/sh",
74*134a1f4eSCasper H.S. Dik 	"/usr/xpg4/bin/pfsh",
757c478bd9Sstevel@tonic-gate 	"/sbin/pfsh",
7660c80770Scraigm 	"/usr/sfw/bin/zsh",
777c478bd9Sstevel@tonic-gate 	NULL
787c478bd9Sstevel@tonic-gate };
797c478bd9Sstevel@tonic-gate 
807c478bd9Sstevel@tonic-gate static char **shells, *strings;
817c478bd9Sstevel@tonic-gate static char **curshell;
827c478bd9Sstevel@tonic-gate static char **initshells(void);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate /*
857c478bd9Sstevel@tonic-gate  * Get a list of shells from SHELLS, if it exists.
867c478bd9Sstevel@tonic-gate  */
877c478bd9Sstevel@tonic-gate char *
getusershell(void)887c478bd9Sstevel@tonic-gate getusershell(void)
897c478bd9Sstevel@tonic-gate {
907c478bd9Sstevel@tonic-gate 	char *ret;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 	if (curshell == NULL)
937c478bd9Sstevel@tonic-gate 		curshell = initshells();
947c478bd9Sstevel@tonic-gate 	ret = *curshell;
957c478bd9Sstevel@tonic-gate 	if (ret != NULL)
967c478bd9Sstevel@tonic-gate 		curshell++;
977c478bd9Sstevel@tonic-gate 	return (ret);
987c478bd9Sstevel@tonic-gate }
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate void
endusershell(void)1017c478bd9Sstevel@tonic-gate endusershell(void)
1027c478bd9Sstevel@tonic-gate {
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	if (shells != NULL)
1057c478bd9Sstevel@tonic-gate 		(void) free((char *)shells);
1067c478bd9Sstevel@tonic-gate 	shells = NULL;
1077c478bd9Sstevel@tonic-gate 	if (strings != NULL)
1087c478bd9Sstevel@tonic-gate 		(void) free(strings);
1097c478bd9Sstevel@tonic-gate 	strings = NULL;
1107c478bd9Sstevel@tonic-gate 	curshell = NULL;
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate void
setusershell(void)1147c478bd9Sstevel@tonic-gate setusershell(void)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	curshell = initshells();
1187c478bd9Sstevel@tonic-gate }
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate static char **
initshells(void)1217c478bd9Sstevel@tonic-gate initshells(void)
1227c478bd9Sstevel@tonic-gate {
1237c478bd9Sstevel@tonic-gate 	char **sp, *cp;
1247c478bd9Sstevel@tonic-gate 	FILE *fp;
1257c478bd9Sstevel@tonic-gate 	struct stat statb;
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	if (shells != NULL)
1287c478bd9Sstevel@tonic-gate 		(void) free((char *)shells);
1297c478bd9Sstevel@tonic-gate 	shells = NULL;
1307c478bd9Sstevel@tonic-gate 	if (strings != NULL)
1317c478bd9Sstevel@tonic-gate 		(void) free(strings);
1327c478bd9Sstevel@tonic-gate 	strings = NULL;
133004388ebScasper 	if ((fp = fopen(SHELLS, "rF")) == (FILE *)0)
1347c478bd9Sstevel@tonic-gate 		return ((char **)okshells);
1357c478bd9Sstevel@tonic-gate 	/*
1367c478bd9Sstevel@tonic-gate 	 * The +1 in the malloc() below is needed to handle the final
1377c478bd9Sstevel@tonic-gate 	 * fgets() NULL terminator.  From fgets(3S):
1387c478bd9Sstevel@tonic-gate 	 *
1397c478bd9Sstevel@tonic-gate 	 * char *fgets(char *s, int n, FILE *stream);
1407c478bd9Sstevel@tonic-gate 	 *
1417c478bd9Sstevel@tonic-gate 	 * The  fgets()  function reads characters from the stream into
1427c478bd9Sstevel@tonic-gate 	 * the array pointed to by s, until n-1 characters are read, or
1437c478bd9Sstevel@tonic-gate 	 * a newline character is read and transferred to s, or an end-
1447c478bd9Sstevel@tonic-gate 	 * of-file condition is encountered.  The string is then termi-
1457c478bd9Sstevel@tonic-gate 	 * nated with a null character.
1467c478bd9Sstevel@tonic-gate 	 */
1477c478bd9Sstevel@tonic-gate 	if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) ||
1487c478bd9Sstevel@tonic-gate 	    ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) {
1497c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
1507c478bd9Sstevel@tonic-gate 		return ((char **)okshells);
1517c478bd9Sstevel@tonic-gate 	}
1527c478bd9Sstevel@tonic-gate 	shells = calloc((size_t)statb.st_size / 3, sizeof (char *));
1537c478bd9Sstevel@tonic-gate 	if (shells == NULL) {
1547c478bd9Sstevel@tonic-gate 		(void) fclose(fp);
1557c478bd9Sstevel@tonic-gate 		(void) free(strings);
1567c478bd9Sstevel@tonic-gate 		strings = NULL;
1577c478bd9Sstevel@tonic-gate 		return ((char **)okshells);
1587c478bd9Sstevel@tonic-gate 	}
1597c478bd9Sstevel@tonic-gate 	sp = shells;
1607c478bd9Sstevel@tonic-gate 	cp = strings;
1617c478bd9Sstevel@tonic-gate 	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
1627c478bd9Sstevel@tonic-gate 		while (*cp != '#' && *cp != '/' && *cp != '\0')
1637c478bd9Sstevel@tonic-gate 			cp++;
1647c478bd9Sstevel@tonic-gate 		if (*cp == '#' || *cp == '\0')
1657c478bd9Sstevel@tonic-gate 			continue;
1667c478bd9Sstevel@tonic-gate 		*sp++ = cp;
1677c478bd9Sstevel@tonic-gate 		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
1687c478bd9Sstevel@tonic-gate 			cp++;
1697c478bd9Sstevel@tonic-gate 		*cp++ = '\0';
1707c478bd9Sstevel@tonic-gate 	}
1717c478bd9Sstevel@tonic-gate 	*sp = (char *)0;
1727c478bd9Sstevel@tonic-gate 	(void) fclose(fp);
1737c478bd9Sstevel@tonic-gate 	return (shells);
1747c478bd9Sstevel@tonic-gate }
175