Home | History | Annotate | Download | only in gen
      1 /*
      2  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
      7 /*	  All Rights Reserved  	*/
      8 
      9 /*
     10  * Copyright (c) 1985 Regents of the University of California.
     11  * All rights reserved.  The Berkeley software License Agreement
     12  * specifies the terms and conditions for redistribution.
     13  */
     14 
     15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16 
     17 #include "lint.h"
     18 #include <sys/types.h>
     19 #include <sys/param.h>
     20 #include <sys/stat.h>
     21 #include <ctype.h>
     22 #include <stdio.h>
     23 #include <limits.h>
     24 #include <stdlib.h>
     25 #include <sys/file.h>
     26 #include "libc.h"
     27 #include <unistd.h>
     28 
     29 #define	SHELLS "/etc/shells"
     30 
     31 /*
     32  * Do not add local shells here.  They should be added in /etc/shells
     33  *
     34  * Do not add restricted shells:
     35  * Shells returned by getusershell traditionally allow:
     36  * - users to change away from (i.e., if you have an rksh in
     37  *   getusershell(), then users can change their shell to ksh)
     38  * - by default, ftp in is allowed only for shells returned by
     39  *   getusershell(); since FTP has no restrictions on directory
     40  *   movement, adding rksh to getusershell() would defeat that
     41  *   protection.
     42  */
     43 const char *okshells[] = {
     44 	"/usr/bin/sh",
     45 	"/usr/bin/csh",
     46 	"/usr/bin/ksh",
     47 	"/usr/bin/ksh93",
     48 	"/usr/bin/jsh",
     49 	"/bin/sh",
     50 	"/bin/csh",
     51 	"/bin/ksh",
     52 	"/bin/ksh93",
     53 	"/bin/jsh",
     54 	"/sbin/sh",
     55 	"/sbin/jsh",
     56 	"/usr/bin/pfsh",
     57 	"/usr/bin/pfcsh",
     58 	"/usr/bin/pfksh",
     59 	"/usr/bin/bash",
     60 	"/usr/bin/tcsh",
     61 	"/usr/bin/zsh",
     62 	"/bin/pfsh",
     63 	"/bin/pfcsh",
     64 	"/bin/pfksh",
     65 	"/bin/bash",
     66 	"/bin/tcsh",
     67 	"/bin/zsh",
     68 	"/usr/xpg4/bin/sh",
     69 	"/sbin/pfsh",
     70 	"/usr/sfw/bin/zsh",
     71 	NULL
     72 };
     73 
     74 static char **shells, *strings;
     75 static char **curshell;
     76 static char **initshells(void);
     77 
     78 /*
     79  * Get a list of shells from SHELLS, if it exists.
     80  */
     81 char *
     82 getusershell(void)
     83 {
     84 	char *ret;
     85 
     86 	if (curshell == NULL)
     87 		curshell = initshells();
     88 	ret = *curshell;
     89 	if (ret != NULL)
     90 		curshell++;
     91 	return (ret);
     92 }
     93 
     94 void
     95 endusershell(void)
     96 {
     97 
     98 	if (shells != NULL)
     99 		(void) free((char *)shells);
    100 	shells = NULL;
    101 	if (strings != NULL)
    102 		(void) free(strings);
    103 	strings = NULL;
    104 	curshell = NULL;
    105 }
    106 
    107 void
    108 setusershell(void)
    109 {
    110 
    111 	curshell = initshells();
    112 }
    113 
    114 static char **
    115 initshells(void)
    116 {
    117 	char **sp, *cp;
    118 	FILE *fp;
    119 	struct stat statb;
    120 
    121 	if (shells != NULL)
    122 		(void) free((char *)shells);
    123 	shells = NULL;
    124 	if (strings != NULL)
    125 		(void) free(strings);
    126 	strings = NULL;
    127 	if ((fp = fopen(SHELLS, "rF")) == (FILE *)0)
    128 		return ((char **)okshells);
    129 	/*
    130 	 * The +1 in the malloc() below is needed to handle the final
    131 	 * fgets() NULL terminator.  From fgets(3S):
    132 	 *
    133 	 * char *fgets(char *s, int n, FILE *stream);
    134 	 *
    135 	 * The  fgets()  function reads characters from the stream into
    136 	 * the array pointed to by s, until n-1 characters are read, or
    137 	 * a newline character is read and transferred to s, or an end-
    138 	 * of-file condition is encountered.  The string is then termi-
    139 	 * nated with a null character.
    140 	 */
    141 	if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) ||
    142 	    ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) {
    143 		(void) fclose(fp);
    144 		return ((char **)okshells);
    145 	}
    146 	shells = calloc((size_t)statb.st_size / 3, sizeof (char *));
    147 	if (shells == NULL) {
    148 		(void) fclose(fp);
    149 		(void) free(strings);
    150 		strings = NULL;
    151 		return ((char **)okshells);
    152 	}
    153 	sp = shells;
    154 	cp = strings;
    155 	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
    156 		while (*cp != '#' && *cp != '/' && *cp != '\0')
    157 			cp++;
    158 		if (*cp == '#' || *cp == '\0')
    159 			continue;
    160 		*sp++ = cp;
    161 		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
    162 			cp++;
    163 		*cp++ = '\0';
    164 	}
    165 	*sp = (char *)0;
    166 	(void) fclose(fp);
    167 	return (shells);
    168 }
    169