brl-vgr Bug Report

ron at BRL.ARPA ron at BRL.ARPA
Tue Oct 14 08:53:07 AEST 1986


Subject: Short summary of the problem
Index:	lib/libc/gen/getusershell.c 4.3BSD

Description:
	Setusershell and endusershell are ineffective and
	sometimes dump core.

Repeat-By:
	Do a few getusershell calls with an interspersed setusershell
	and/or endusershell.
Fix:
	The problem is that getusershell.c is horrible.  Endusershell
	may free things that have not been malloced.  There are two
	separate instances of the shells pointer one local to getusershell.
	Setusershell sets a different one than the one getusershell uses.

	A fixed up version follows:
/*
 * Copyright (c) 1985 Regents of the University of California.
 * All rights reserved.  The Berkeley software License Agreement
 * specifies the terms and conditions for redistribution.
 */

#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)getusershell.c	5.2 (Berkeley) 3/9/86";
#endif LIBC_SCCS and not lint

#include <sys/param.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <ctype.h>
#include <stdio.h>

#define SHELLS "/etc/shells"

/*
 * Do not add local shells here.  They should be added in /etc/shells
 */
static char *okshells[] =
    { "/bin/sh", "/bin/csh", 0 };

static int inprogress;
static char **shells, *strings;
extern char **initshells();

/*
 * Get a list of shells from SHELLS, if it exists.
 */
char *
getusershell()
{
	char *ret;
	static char **shp;

	if (!inprogress)
		shp = initshells();
	ret = *shp;
	if (*shp != NULL)
		shp++;
	return (ret);
}

endusershell()
{
	
	if (shells != NULL)
		free((char *)shells);
	shells = NULL;
	if (strings != NULL)
		free(strings);
	strings = NULL;
	inprogress = 0;
}

setusershell()
{
	endusershell();
}

static char **
initshells()
{
	register char **sp, *cp;
	register FILE *fp;
	struct stat statb;
	extern char *malloc(), *calloc();

	inprogress = 1;
	if (shells != NULL)
		free((char *)shells);
	shells = NULL;
	if (strings != NULL)
		free(strings);
	strings = NULL;
	if ((fp = fopen(SHELLS, "r")) == (FILE *)0)
		return(okshells);
	if (fstat(fileno(fp), &statb) == -1) {
		(void)fclose(fp);
		return(okshells);
	}
	if ((strings = malloc((unsigned)statb.st_size)) == NULL) {
		(void)fclose(fp);
		return(okshells);
	}
	shells = (char **)calloc((unsigned)statb.st_size / 3, sizeof (char *));
	if (shells == NULL) {
		(void)fclose(fp);
		free(strings);
		strings = NULL;
		return(okshells);
	}
	sp = shells;
	cp = strings;
	while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
		while (!isspace(*cp) != '/' && *cp != '\0')
			cp++;
		if (*cp == '#' || *cp == '\0')
			continue;
		*sp++ = cp;
		while (!isspace(*cp) && *cp != '#' && *cp != '\0')
			cp++;
		*cp++ = '\0';
	}
	*sp = (char *)0;
	(void)fclose(fp);
	return (shells);
}



More information about the Comp.unix.wizards mailing list