1
0
mirror of https://https.git.savannah.gnu.org/git/gnulib.git synced 2026-06-15 23:35:50 +00:00
Files
gnulib/lib/getusershell.c
Paul Eggert 0632e11574 * _fpending.c: Include <config.h> unconditionally, since we no
longer worry about uses that don't define HAVE_CONFIG_H.
* acl.c, alloca.c, argmatch.c, atexit.c, backupfile.c:
* basename.c, c-stack.c, c-strtod.c, calloc.c, canon-host.c:
* canonicalize.c, chdir-long.c, chdir-safer.c, chown.c:
* cloexec.c, close-stream.c, closeout.c, creat-safer.c:
* cycle-check.c, diacrit.c, dirchownmod.c, dirfd.c, dirname.c:
* dup-safer.c, dup2.c, error.c, euidaccess.c, exclude.c:
* exitfail.c, fchmodat.c, fchown-stub.c, fd-safer.c:
* file-type.c, fileblocks.c, filemode.c, filenamecat.c:
* fnmatch.c, fopen-safer.c, fprintftime.c, free.c, fsusage.c:
* ftruncate.c, fts-cycle.c, fts.c, full-write.c, gai_strerror.c:
* getcwd.c, getdate.y, getdomainname.c, getgroups.c:
* gethostname.c, gethrxtime.c, getloadavg.c, getlogin_r.c:
* getndelim2.c, getnline.c, getopt.c, getopt1.c, getpass.c:
* gettime.c, gettimeofday.c, getugroups.c, getusershell.c:
* glob.c, group-member.c, hard-locale.c, hash-pjw.c, hash.c:
* human.c, idcache.c, inet_ntop.c, inet_pton.c, inttostr.c:
* isdir.c, lchown.c, linebuffer.c, long-options.c, lstat.c:
* malloc.c, md5.c, memcasecmp.c, memchr.c, memcmp.c, memcoll.c:
* memcpy.c, memmove.c, memrchr.c, mkancesdirs.c, mkdir-p.c:
* mkdir.c, mkdirat.c, mkstemp-safer.c, mkstemp.c, modechange.c:
* mountlist.c, nanosleep.c, obstack.c, open-safer.c:
* openat-die.c, openat.c, pagealign_alloc.c, physmem.c:
* pipe-safer.c, posixtm.c, posixver.c, putenv.c, quote.c:
* quotearg.c, raise.c, readtokens.c, readtokens0.c, readutmp.c:
* realloc.c, regex.c, rename.c, rmdir.c, rpmatch.c, safe-read.c:
* same.c, save-cwd.c, savedir.c, setenv.c, settime.c, sha1.c:
* sig2str.c, snprintf.c, strdup.c, strerror.c, strftime.c:
* stripslash.c, strndup.c, strnlen.c, strpbrk.c, strtod.c:
* strtoimax.c, strtol.c, strverscmp.c, tempname.c, time_r.c:
* timegm.c, tmpfile-safer.c, unlinkdir.c, userspec.c, utime.c:
* utimecmp.c, utimens.c, version-etc-fsf.c, version-etc.c:
* xalloc-die.c, xgetcwd.c, xgethostname.c, xmalloc.c:
* xmemcoll.c, xnanosleep.c, xreadlink.c, xstrtod.c:
* xstrtoimax.c, xstrtol.c, xstrtoumax.c, yesno.c:
Likewise.
2006-09-13 22:38:14 +00:00

172 lines
4.1 KiB
C

/* getusershell.c -- Return names of valid user shells.
Copyright (C) 1991, 1997, 2000, 2001, 2003, 2004, 2005, 2006 Free
Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
/* Written by David MacKenzie <djm@gnu.ai.mit.edu> */
#include <config.h>
#ifndef SHELLS_FILE
# ifndef __DJGPP__
/* File containing a list of nonrestricted shells, one per line. */
# define SHELLS_FILE "/etc/shells"
# else
/* This is a horrible kludge. Isn't there a better way? */
# define SHELLS_FILE "/dev/env/DJDIR/etc/shells"
# endif
#endif
#include <stdlib.h>
#include <ctype.h>
#include "stdio--.h"
#include "xalloc.h"
#if USE_UNLOCKED_IO
# include "unlocked-io.h"
#endif
static size_t readname (char **, size_t *, FILE *);
#if ! defined ADDITIONAL_DEFAULT_SHELLS && defined __MSDOS__
# define ADDITIONAL_DEFAULT_SHELLS \
"c:/dos/command.com", "c:/windows/command.com", "c:/command.com",
#else
# define ADDITIONAL_DEFAULT_SHELLS /* empty */
#endif
/* List of shells to use if the shells file is missing. */
static char const* const default_shells[] =
{
ADDITIONAL_DEFAULT_SHELLS
"/bin/sh", "/bin/csh", "/usr/bin/sh", "/usr/bin/csh", NULL
};
/* Index of the next shell in `default_shells' to return.
0 means we are not using `default_shells'. */
static size_t default_index = 0;
/* Input stream from the shells file. */
static FILE *shellstream = NULL;
/* Line of input from the shells file. */
static char *line = NULL;
/* Number of bytes allocated for `line'. */
static size_t line_size = 0;
/* Return an entry from the shells file, ignoring comment lines.
If the file doesn't exist, use the list in DEFAULT_SHELLS (above).
In any case, the returned string is in memory allocated through malloc.
Return NULL if there are no more entries. */
char *
getusershell (void)
{
if (default_index > 0)
{
if (default_shells[default_index])
/* Not at the end of the list yet. */
return xstrdup (default_shells[default_index++]);
return NULL;
}
if (shellstream == NULL)
{
shellstream = fopen (SHELLS_FILE, "r");
if (shellstream == NULL)
{
/* No shells file. Use the default list. */
default_index = 1;
return xstrdup (default_shells[0]);
}
}
while (readname (&line, &line_size, shellstream))
{
if (*line != '#')
return line;
}
return NULL; /* End of file. */
}
/* Rewind the shells file. */
void
setusershell (void)
{
default_index = 0;
if (shellstream)
rewind (shellstream);
}
/* Close the shells file. */
void
endusershell (void)
{
if (shellstream)
{
fclose (shellstream);
shellstream = NULL;
}
}
/* Read a line from STREAM, removing any newline at the end.
Place the result in *NAME, which is malloc'd
and/or realloc'd as necessary and can start out NULL,
and whose size is passed and returned in *SIZE.
Return the number of bytes placed in *NAME
if some nonempty sequence was found, otherwise 0. */
static size_t
readname (char **name, size_t *size, FILE *stream)
{
int c;
size_t name_index = 0;
/* Skip blank space. */
while ((c = getc (stream)) != EOF && isspace (c))
/* Do nothing. */ ;
for (;;)
{
if (*size <= name_index)
*name = x2nrealloc (*name, size, sizeof **name);
if (c == EOF || isspace (c))
break;
(*name)[name_index++] = c;
c = getc (stream);
}
(*name)[name_index] = '\0';
return name_index;
}
#ifdef TEST
int
main (void)
{
char *s;
while (s = getusershell ())
puts (s);
exit (0);
}
#endif