Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!caip!brl-adm!brl-smoke!smoke!ron@BRL.ARPA From: ron@BRL.ARPA Newsgroups: net.unix-wizards Subject: brl-vgr Bug Report Message-ID: <4573@brl-smoke.ARPA> Date: Mon, 13-Oct-86 18:53:07 EDT Article-I.D.: brl-smok.4573 Posted: Mon Oct 13 18:53:07 1986 Date-Received: Tue, 14-Oct-86 06:53:57 EDT Sender: news@brl-smoke.ARPA Lines: 127 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 #include #include #include #include #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); }