diff options
| -rw-r--r-- | libc/unistd/usershell.c | 172 | 
1 files changed, 56 insertions, 116 deletions
diff --git a/libc/unistd/usershell.c b/libc/unistd/usershell.c index 10c5bf1a5..2a6b66504 100644 --- a/libc/unistd/usershell.c +++ b/libc/unistd/usershell.c @@ -1,134 +1,74 @@ -/* - * Copyright (c) 1985, 1993 - *	The Regents of the University of California.  All rights reserved. +/* setusershell(), getusershell(), endusershell() for uClibc.   * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - *    notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - *    notice, this list of conditions and the following disclaimer in the - *    documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - *    may be used to endorse or promote products derived from this software - *    without specific prior written permission. + * Copyright (C) 2010 Bernhard Reutner-Fischer <uclibc@uclibc.org>   * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * This version has been hevily modified for use with uClibc - * November 2002, Erik Andersen <andersen@codepoet.org> + * Licensed under the LGPL v2.1 or later, see the file COPYING.LIB in + * this tarball. + */ +/* My manpage reads: + * The  getusershell() function returns the next line from the file + * /etc/shells, opening the file if necessary. The line should contain + * the pathname of a valid user shell.  If /etc/shells does not exist + * or is unreadable, getusershell() behaves as if /bin/sh and /bin/csh + * were listed in the file. + * The getusershell() function returns a NULL pointer on end-of-file.   */ - -#include <sys/param.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <stdio.h> -#include <stdio_ext.h> -#include <ctype.h> -#include <stdlib.h>  #include <unistd.h> +#include <stdlib.h>  #include <paths.h> +#include <string.h> +#include "internal/parse_config.h"  #if defined __USE_BSD || (defined __USE_XOPEN && !defined __USE_UNIX98) -/* - * Local shells should NOT be added here.  They should be added in - * /etc/shells. - */ - -static const char * const validsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL }; -static char **curshell, **shells, *strings; -static char **initshells __P((void)); - -/* - * Get a list of shells from _PATH_SHELLS, if it exists. - */ -char * getusershell(void) -{ -    char *ret; - -    if (curshell == NULL) -	curshell = initshells(); -    ret = *curshell; -    if (ret != NULL) -	curshell++; -    return (ret); -} - -static void __free_initshell_memory(void) -{ -    free(shells); -    shells = NULL; -    free(strings); -    strings = NULL; -} +static const char * const defaultsh[] = { _PATH_BSHELL, _PATH_CSHELL, NULL}; +static char *shellb, **shells; +static parser_t *shellp;  void endusershell(void)  { -    __free_initshell_memory(); -    curshell = NULL; +	if (shellp) { +		shells = (char**) shellb; +		while (shells && *shells) { +			char*xxx = *shells++; +			free(xxx); +		} +		config_close(shellp); +		shellp = NULL; +	} +	free(shellb); +	shellb = NULL; +	shells = NULL;  } -  void setusershell(void)  { -    curshell = initshells(); -} +	endusershell(); +	shellp = config_open(_PATH_SHELLS); +	if (shellp == NULL) +		shells = (char **)defaultsh; +	else { +		char **shell = NULL; +		int pos = 0; -static char ** initshells(void) -{ -    register char **sp, *cp; -    register FILE *fp; -    struct stat statb; -    int flen; +		while (config_read(shellp, &shell, 1, 1, "# \t", PARSE_NORMAL)) +		{ +			shellb = realloc(shellb, (pos + 2) * sizeof(char*)); +			shells = (char**) shellb + pos++; +			*shells++ = strdup(*shell); +			*shells = NULL; -    __free_initshell_memory(); - -    if ((fp = fopen(_PATH_SHELLS, "r")) == NULL) -	return (char **) validsh; -    if (fstat(fileno(fp), &statb) == -1) { -	goto cleanup; -    } -    if ((strings = malloc((unsigned)statb.st_size + 1)) == NULL) { -	goto cleanup; -    } -    if ((shells = calloc((unsigned)statb.st_size / 3, sizeof (char *))) == NULL) { -	goto cleanup; -    } -    /* No threads using this stream.  */ -#ifdef __UCLIBC_HAS_THREADS__ -    __fsetlocking (fp, FSETLOCKING_BYCALLER); -#endif -    sp = shells; -    cp = strings; -    flen = statb.st_size; -    while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) { -	while (*cp != '#' && *cp != '/' && *cp != '\0') -	    cp++; -	if (*cp == '#' || *cp == '\0') -	    continue; -	*sp++ = cp; -	while (!isspace(*cp) && *cp != '#' && *cp != '\0') -	    cp++; -	*cp++ = '\0'; -    } -    *sp = NULL; -    fclose(fp); -    return (shells); - -cleanup: -    __free_initshell_memory(); -    fclose(fp); -    return (char **) validsh; +		} +		shells = (char **)shellb; +	} +} +char *getusershell(void) +{ +	char *sh; +	if (shells == NULL) +		setusershell(); +	sh = *shells; +	if (sh) +		shells++; +	return sh;  }  #endif  | 
