Blame misc/getusershell.c

Packit 6c4009
/*
Packit 6c4009
 * Copyright (c) 1985, 1993
Packit 6c4009
 *	The Regents of the University of California.  All rights reserved.
Packit 6c4009
 *
Packit 6c4009
 * Redistribution and use in source and binary forms, with or without
Packit 6c4009
 * modification, are permitted provided that the following conditions
Packit 6c4009
 * are met:
Packit 6c4009
 * 1. Redistributions of source code must retain the above copyright
Packit 6c4009
 *    notice, this list of conditions and the following disclaimer.
Packit 6c4009
 * 2. Redistributions in binary form must reproduce the above copyright
Packit 6c4009
 *    notice, this list of conditions and the following disclaimer in the
Packit 6c4009
 *    documentation and/or other materials provided with the distribution.
Packit 6c4009
 * 4. Neither the name of the University nor the names of its contributors
Packit 6c4009
 *    may be used to endorse or promote products derived from this software
Packit 6c4009
 *    without specific prior written permission.
Packit 6c4009
 *
Packit 6c4009
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
Packit 6c4009
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
Packit 6c4009
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
Packit 6c4009
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
Packit 6c4009
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
Packit 6c4009
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
Packit 6c4009
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
Packit 6c4009
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
Packit 6c4009
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
Packit 6c4009
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
Packit 6c4009
 * SUCH DAMAGE.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
#if defined(LIBC_SCCS) && !defined(lint)
Packit 6c4009
static char sccsid[] = "@(#)getusershell.c	8.1 (Berkeley) 6/4/93";
Packit 6c4009
#endif /* LIBC_SCCS and not lint */
Packit 6c4009
Packit 6c4009
#include <sys/param.h>
Packit 6c4009
#include <sys/file.h>
Packit 6c4009
#include <sys/stat.h>
Packit 6c4009
#include <stdio.h>
Packit 6c4009
#include <stdio_ext.h>
Packit 6c4009
#include <ctype.h>
Packit 6c4009
#include <stdlib.h>
Packit 6c4009
#include <unistd.h>
Packit 6c4009
#include <paths.h>
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Local shells should NOT be added here.  They should be added in
Packit 6c4009
 * /etc/shells.
Packit 6c4009
 */
Packit 6c4009
Packit 6c4009
/* NB: we do not initialize okshells here.  The initialization needs
Packit 6c4009
   relocations.  These interfaces are used so rarely that this is not
Packit 6c4009
   justified.  Instead explicitly initialize the array when it is
Packit 6c4009
   used.  */
Packit 6c4009
#if 0
Packit 6c4009
static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
Packit 6c4009
#else
Packit 6c4009
static const char *okshells[3];
Packit 6c4009
#endif
Packit 6c4009
static char **curshell, **shells, *strings;
Packit 6c4009
static char **initshells (void) __THROW;
Packit 6c4009
Packit 6c4009
/*
Packit 6c4009
 * Get a list of shells from _PATH_SHELLS, if it exists.
Packit 6c4009
 */
Packit 6c4009
char *
Packit 6c4009
getusershell (void)
Packit 6c4009
{
Packit 6c4009
	char *ret;
Packit 6c4009
Packit 6c4009
	if (curshell == NULL)
Packit 6c4009
		curshell = initshells();
Packit 6c4009
	ret = *curshell;
Packit 6c4009
	if (ret != NULL)
Packit 6c4009
		curshell++;
Packit 6c4009
	return (ret);
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
endusershell (void)
Packit 6c4009
{
Packit 6c4009
Packit 6c4009
	free(shells);
Packit 6c4009
	shells = NULL;
Packit 6c4009
	free(strings);
Packit 6c4009
	strings = NULL;
Packit 6c4009
	curshell = NULL;
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
void
Packit 6c4009
setusershell (void)
Packit 6c4009
{
Packit 6c4009
Packit 6c4009
	curshell = initshells();
Packit 6c4009
}
Packit 6c4009
Packit 6c4009
static char **
Packit 6c4009
initshells (void)
Packit 6c4009
{
Packit 6c4009
	char **sp, *cp;
Packit 6c4009
	FILE *fp;
Packit 6c4009
	struct stat64 statb;
Packit 6c4009
	size_t flen;
Packit 6c4009
Packit 6c4009
	free(shells);
Packit 6c4009
	shells = NULL;
Packit 6c4009
	free(strings);
Packit 6c4009
	strings = NULL;
Packit 6c4009
	if ((fp = fopen(_PATH_SHELLS, "rce")) == NULL)
Packit 6c4009
		goto init_okshells_noclose;
Packit 6c4009
	if (fstat64(fileno(fp), &statb) == -1) {
Packit 6c4009
	init_okshells:
Packit 6c4009
		(void)fclose(fp);
Packit 6c4009
	init_okshells_noclose:
Packit 6c4009
		okshells[0] = _PATH_BSHELL;
Packit 6c4009
		okshells[1] = _PATH_CSHELL;
Packit 6c4009
		return (char **) okshells;
Packit 6c4009
	}
Packit 6c4009
	if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3)
Packit 6c4009
		goto init_okshells;
Packit 6c4009
	flen = statb.st_size + 3;
Packit 6c4009
	if ((strings = malloc(flen)) == NULL)
Packit 6c4009
		goto init_okshells;
Packit 6c4009
	shells = malloc(statb.st_size / 3 * sizeof (char *));
Packit 6c4009
	if (shells == NULL) {
Packit 6c4009
		free(strings);
Packit 6c4009
		strings = NULL;
Packit 6c4009
		goto init_okshells;
Packit 6c4009
	}
Packit 6c4009
	sp = shells;
Packit 6c4009
	cp = strings;
Packit 6c4009
	while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
Packit 6c4009
		while (*cp != '#' && *cp != '/' && *cp != '\0')
Packit 6c4009
			cp++;
Packit 6c4009
		if (*cp == '#' || *cp == '\0' || cp[1] == '\0')
Packit 6c4009
			continue;
Packit 6c4009
		*sp++ = cp;
Packit 6c4009
		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
Packit 6c4009
			cp++;
Packit 6c4009
		*cp++ = '\0';
Packit 6c4009
	}
Packit 6c4009
	*sp = NULL;
Packit 6c4009
	(void)fclose(fp);
Packit 6c4009
	return (shells);
Packit 6c4009
}