From d2b29ac7a035467e406d0a61847580d80b5fa041 Mon Sep 17 00:00:00 2001 From: Bernhard Reutner-Fischer Date: Mon, 1 Feb 2010 00:07:07 +0100 Subject: usershell: switch to config parser Signed-off-by: Bernhard Reutner-Fischer --- libc/unistd/usershell.c | 172 ++++++++++++++++-------------------------------- 1 file 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 * - * 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 + * 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 -#include -#include -#include -#include -#include -#include #include +#include #include +#include +#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 -- cgit v1.2.3