summaryrefslogtreecommitdiff
path: root/usr/src/lib/libc/port/gen/getusershell.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libc/port/gen/getusershell.c')
-rw-r--r--usr/src/lib/libc/port/gen/getusershell.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/usr/src/lib/libc/port/gen/getusershell.c b/usr/src/lib/libc/port/gen/getusershell.c
new file mode 100644
index 0000000000..b7edd9e4dd
--- /dev/null
+++ b/usr/src/lib/libc/port/gen/getusershell.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1985 Regents of the University of California.
+ * All rights reserved. The Berkeley software License Agreement
+ * specifies the terms and conditions for redistribution.
+ */
+
+#include "synonyms.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include "libc.h"
+#include <unistd.h>
+
+#define SHELLS "/etc/shells"
+
+/*
+ * Do not add local shells here. They should be added in /etc/shells
+ */
+const char *okshells[] = {
+ "/usr/bin/sh",
+ "/usr/bin/csh",
+ "/usr/bin/ksh",
+ "/usr/bin/jsh",
+ "/bin/sh",
+ "/bin/csh",
+ "/bin/ksh",
+ "/bin/jsh",
+ "/sbin/sh",
+ "/sbin/jsh",
+ "/usr/bin/pfsh",
+ "/usr/bin/pfcsh",
+ "/usr/bin/pfksh",
+ "/usr/bin/bash",
+ "/usr/bin/tcsh",
+ "/usr/bin/zsh",
+ "/bin/pfsh",
+ "/bin/pfcsh",
+ "/bin/pfksh",
+ "/bin/bash",
+ "/bin/tcsh",
+ "/bin/zsh",
+ "/usr/xpg4/bin/sh",
+ "/sbin/pfsh",
+ NULL
+};
+
+static char **shells, *strings;
+static char **curshell;
+static char **initshells(void);
+
+/*
+ * Get a list of shells from SHELLS, if it exists.
+ */
+char *
+getusershell(void)
+{
+ char *ret;
+
+ if (curshell == NULL)
+ curshell = initshells();
+ ret = *curshell;
+ if (ret != NULL)
+ curshell++;
+ return (ret);
+}
+
+void
+endusershell(void)
+{
+
+ if (shells != NULL)
+ (void) free((char *)shells);
+ shells = NULL;
+ if (strings != NULL)
+ (void) free(strings);
+ strings = NULL;
+ curshell = NULL;
+}
+
+void
+setusershell(void)
+{
+
+ curshell = initshells();
+}
+
+static char **
+initshells(void)
+{
+ char **sp, *cp;
+ FILE *fp;
+ struct stat statb;
+
+ if (shells != NULL)
+ (void) free((char *)shells);
+ shells = NULL;
+ if (strings != NULL)
+ (void) free(strings);
+ strings = NULL;
+ if ((fp = fopen(SHELLS, "r")) == (FILE *)0)
+ return ((char **)okshells);
+ /*
+ * The +1 in the malloc() below is needed to handle the final
+ * fgets() NULL terminator. From fgets(3S):
+ *
+ * char *fgets(char *s, int n, FILE *stream);
+ *
+ * The fgets() function reads characters from the stream into
+ * the array pointed to by s, until n-1 characters are read, or
+ * a newline character is read and transferred to s, or an end-
+ * of-file condition is encountered. The string is then termi-
+ * nated with a null character.
+ */
+ if ((fstat(fileno(fp), &statb) == -1) || (statb.st_size > LONG_MAX) ||
+ ((strings = malloc((size_t)statb.st_size + 1)) == NULL)) {
+ (void) fclose(fp);
+ return ((char **)okshells);
+ }
+ shells = calloc((size_t)statb.st_size / 3, sizeof (char *));
+ if (shells == NULL) {
+ (void) fclose(fp);
+ (void) free(strings);
+ strings = NULL;
+ return ((char **)okshells);
+ }
+ sp = shells;
+ cp = strings;
+ while (fgets(cp, MAXPATHLEN + 1, 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 = (char *)0;
+ (void) fclose(fp);
+ return (shells);
+}