Back to index

glibc  2.9
getusershell.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1985, 1993
00003  *     The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 4. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 #if defined(LIBC_SCCS) && !defined(lint)
00031 static char sccsid[] = "@(#)getusershell.c       8.1 (Berkeley) 6/4/93";
00032 #endif /* LIBC_SCCS and not lint */
00033 
00034 #include <sys/param.h>
00035 #include <sys/file.h>
00036 #include <sys/stat.h>
00037 #include <stdio.h>
00038 #include <stdio_ext.h>
00039 #include <ctype.h>
00040 #include <stdlib.h>
00041 #include <unistd.h>
00042 #include <paths.h>
00043 
00044 /*
00045  * Local shells should NOT be added here.  They should be added in
00046  * /etc/shells.
00047  */
00048 
00049 /* NB: we do not initialize okshells here.  The initialization needs
00050    relocations.  These interfaces are used so rarely that this is not
00051    justified.  Instead explicitly initialize the array when it is
00052    used.  */
00053 #if 0
00054 static const char *const okshells[] = { _PATH_BSHELL, _PATH_CSHELL, NULL };
00055 #else
00056 static const char *okshells[3];
00057 #endif
00058 static char **curshell, **shells, *strings;
00059 static char **initshells (void) __THROW;
00060 
00061 /*
00062  * Get a list of shells from _PATH_SHELLS, if it exists.
00063  */
00064 char *
00065 getusershell()
00066 {
00067        char *ret;
00068 
00069        if (curshell == NULL)
00070               curshell = initshells();
00071        ret = *curshell;
00072        if (ret != NULL)
00073               curshell++;
00074        return (ret);
00075 }
00076 
00077 void
00078 endusershell()
00079 {
00080 
00081        free(shells);
00082        shells = NULL;
00083        free(strings);
00084        strings = NULL;
00085        curshell = NULL;
00086 }
00087 
00088 void
00089 setusershell()
00090 {
00091 
00092        curshell = initshells();
00093 }
00094 
00095 static char **
00096 initshells()
00097 {
00098        register char **sp, *cp;
00099        register FILE *fp;
00100        struct stat64 statb;
00101        size_t flen;
00102 
00103        free(shells);
00104        shells = NULL;
00105        free(strings);
00106        strings = NULL;
00107        if ((fp = fopen(_PATH_SHELLS, "rc")) == NULL)
00108               goto init_okshells_noclose;
00109        if (fstat64(fileno(fp), &statb) == -1) {
00110        init_okshells:
00111               (void)fclose(fp);
00112        init_okshells_noclose:
00113               okshells[0] = _PATH_BSHELL;
00114               okshells[1] = _PATH_CSHELL;
00115               return (char **) okshells;
00116        }
00117        if (statb.st_size > ~(size_t)0 / sizeof (char *) * 3)
00118               goto init_okshells;
00119        if ((strings = malloc(statb.st_size + 2)) == NULL)
00120               goto init_okshells;
00121        shells = malloc(statb.st_size / 3 * sizeof (char *));
00122        if (shells == NULL) {
00123               free(strings);
00124               strings = NULL;
00125               goto init_okshells;
00126        }
00127        sp = shells;
00128        cp = strings;
00129        flen = statb.st_size + 2;
00130        while (fgets_unlocked(cp, flen - (cp - strings), fp) != NULL) {
00131               while (*cp != '#' && *cp != '/' && *cp != '\0')
00132                      cp++;
00133               if (*cp == '#' || *cp == '\0' || cp[1] == '\0')
00134                      continue;
00135               *sp++ = cp;
00136               while (!isspace(*cp) && *cp != '#' && *cp != '\0')
00137                      cp++;
00138               *cp++ = '\0';
00139        }
00140        *sp = NULL;
00141        (void)fclose(fp);
00142        return (shells);
00143 }