summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/syscalls.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/syscalls.cc')
-rw-r--r--winsup/cygwin/syscalls.cc66
1 files changed, 66 insertions, 0 deletions
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 8dd659ab4..d15384260 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -30,6 +30,8 @@ details. */
#include <process.h>
#include <utmp.h>
#include <sys/uio.h>
+#include <errno.h>
+#include <ctype.h>
#include <limits.h>
#include <unistd.h>
#include <setjmp.h>
@@ -2897,3 +2899,67 @@ long gethostid(void)
return hostid;
}
+
+#define ETC_SHELLS "/etc/shells"
+static int shell_index;
+static FILE *shell_fp;
+
+extern "C" char *
+getusershell ()
+{
+ /* List of default shells if no /etc/shells exists, defined as on Linux.
+ FIXME: SunOS has a far longer list, containing all shells which
+ might be shipped with the OS. Should we do the same for the Cygwin
+ distro, adding bash, tcsh, ksh, pdksh and zsh? */
+ static NO_COPY const char *def_shells[] = {
+ "/bin/sh",
+ "/bin/csh",
+ "/usr/bin/sh",
+ "/usr/bin/csh",
+ NULL
+ };
+ static char buf[MAX_PATH];
+ int ch, buf_idx;
+
+ if (!shell_fp && !(shell_fp = fopen (ETC_SHELLS, "rt")))
+ {
+ if (def_shells[shell_index])
+ return strcpy (buf, def_shells[shell_index++]);
+ return NULL;
+ }
+ /* Skip white space characters. */
+ while ((ch = getc (shell_fp)) != EOF && isspace (ch))
+ ;
+ /* Get each non-whitespace character as part of the shell path as long as
+ it fits in buf. */
+ for (buf_idx = 0;
+ ch != EOF && !isspace (ch) && buf_idx < MAX_PATH;
+ buf_idx++, ch = getc (shell_fp))
+ buf[buf_idx] = ch;
+ /* Skip any trailing non-whitespace character not fitting in buf. If the
+ path is longer than MAX_PATH, it's invalid anyway. */
+ while (ch != EOF && !isspace (ch))
+ ch = getc (shell_fp);
+ if (buf_idx)
+ {
+ buf[buf_idx] = '\0';
+ return buf;
+ }
+ return NULL;
+}
+
+extern "C" void
+setusershell ()
+{
+ if (shell_fp)
+ fseek (shell_fp, 0L, SEEK_SET);
+ shell_index = 0;
+}
+
+extern "C" void
+endusershell ()
+{
+ if (shell_fp)
+ fclose (shell_fp);
+ shell_index = 0;
+}