Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/passwd.cc')
-rw-r--r--winsup/cygwin/passwd.cc275
1 files changed, 275 insertions, 0 deletions
diff --git a/winsup/cygwin/passwd.cc b/winsup/cygwin/passwd.cc
new file mode 100644
index 000000000..51c5450b4
--- /dev/null
+++ b/winsup/cygwin/passwd.cc
@@ -0,0 +1,275 @@
+/* passwd.cc: getpwnam () and friends
+
+ Copyright 1996, 1997, 1998 Cygnus Solutions.
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include <stdlib.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <errno.h>
+#include "winsup.h"
+
+/* Read /etc/passwd only once for better performance. This is done
+ on the first call that needs information from it. */
+
+static struct passwd *passwd_buf = NULL; /* passwd contents in memory */
+static int curr_lines = 0;
+static int max_lines = 0;
+
+/* Set to 1 when /etc/passwd has been read in by read_etc_passwd (). */
+/* Functions in this file need to check the value of passwd_in_memory_p
+ and read in the password file if it isn't set. */
+static int passwd_in_memory_p = 0;
+
+/* Position in the passwd cache */
+#ifdef _MT_SAFE
+#define pw_pos _reent_winsup()->_pw_pos
+#else
+static int pw_pos = 0;
+#endif
+
+/* Remove a : teminated string from the buffer, and increment the pointer */
+static char *
+grab_string (char **p)
+{
+ char *src = *p;
+ char *res = src;
+
+ while (*src && *src != ':' && *src != '\n')
+ src++;
+
+ if (*src == ':')
+ {
+ *src = 0;
+ src++;
+ }
+ *p = src;
+ return res;
+}
+
+/* same, for ints */
+static int
+grab_int (char **p)
+{
+ char *src = *p;
+ int val = atoi (src);
+ while (*src && *src != ':' && *src != '\n')
+ src++;
+ if (*src == ':')
+ src++;
+ *p = src;
+ return val;
+}
+
+/* Parse /etc/passwd line into passwd structure. */
+void
+parse_pwd (struct passwd &res, char *buf)
+{
+ /* Allocate enough room for the passwd struct and all the strings
+ in it in one go */
+ size_t len = strlen (buf);
+ char *mybuf = (char *) malloc (len + 1);
+ (void) memcpy (mybuf, buf, len + 1);
+ if (mybuf[--len] == '\n')
+ mybuf[len] = '\0';
+
+ res.pw_name = strlwr(grab_string (&mybuf));
+ res.pw_passwd = grab_string (&mybuf);
+ res.pw_uid = grab_int (&mybuf);
+ res.pw_gid = grab_int (&mybuf);
+ res.pw_comment = 0;
+ res.pw_gecos = grab_string (&mybuf);
+ res.pw_dir = grab_string (&mybuf);
+ res.pw_shell = grab_string (&mybuf);
+}
+
+/* Add one line from /etc/passwd into the password cache */
+static void
+add_pwd_line (char *line)
+{
+ if (curr_lines >= max_lines)
+ {
+ max_lines += 10;
+ passwd_buf = (struct passwd *) realloc (passwd_buf, max_lines * sizeof (struct passwd));
+ }
+ parse_pwd (passwd_buf[curr_lines++], line);
+}
+
+/* Read in /etc/passwd and save contents in the password cache.
+ This sets passwd_in_memory_p to 1 so functions in this file can
+ tell that /etc/passwd has been read in */
+static void
+read_etc_passwd ()
+{
+ extern int passwd_sem;
+ char linebuf[1024];
+ ++passwd_sem;
+ FILE *f = fopen ("/etc/passwd", "r");
+ --passwd_sem;
+
+ if (f)
+ {
+ while (fgets (linebuf, sizeof (linebuf), f) != NULL)
+ {
+ if (strlen (linebuf))
+ add_pwd_line (linebuf);
+ }
+
+ fclose (f);
+ }
+ else
+ {
+ debug_printf ("Emulating /etc/passwd");
+ char user_name [ MAX_USER_NAME ];
+ DWORD user_name_len = MAX_USER_NAME;
+ if (! GetUserNameA (user_name, &user_name_len))
+ {
+ strncpy (user_name, "Administrator", MAX_USER_NAME);
+ debug_printf ("Failed to get current user name. %E");
+ }
+ snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", user_name,
+ DEFAULT_UID, DEFAULT_GID, getenv ("HOME") ?: "/");
+ add_pwd_line (linebuf);
+ }
+ passwd_in_memory_p = 1;
+}
+
+/* Cygwin internal */
+static struct passwd *
+search_for (uid_t uid, const char *name)
+{
+ struct passwd *res = 0;
+ struct passwd *default_pw = 0;
+
+ for (int i = 0; i < curr_lines; i++)
+ {
+ res = passwd_buf + i;
+ if (res->pw_uid == DEFAULT_UID)
+ default_pw = res;
+ /* on Windows NT user names are case-insensitive */
+ if (name)
+ {
+ if (strcasematch (name, res->pw_name))
+ return res;
+ }
+ else if (uid == res->pw_uid)
+ return res;
+ }
+
+ return default_pw;
+}
+
+extern "C"
+struct passwd *
+getpwuid (uid_t uid)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ return search_for (uid, 0);
+}
+
+extern "C"
+struct passwd *
+getpwnam (const char *name)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ return search_for (0, name);
+}
+
+extern "C"
+struct passwd *
+getpwent (void)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ if (pw_pos < curr_lines)
+ return passwd_buf + pw_pos++;
+
+ return NULL;
+}
+
+extern "C"
+struct passwd *
+getpwduid (uid_t uid)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ return NULL;
+}
+
+extern "C"
+void
+setpwent (void)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ pw_pos = 0;
+}
+
+extern "C"
+void
+endpwent (void)
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ pw_pos = 0;
+}
+
+extern "C"
+int
+setpassent ()
+{
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ return 0;
+}
+
+extern "C"
+char *
+getpass (const char * prompt)
+{
+#ifdef _MT_SAFE
+ char *pass=_reent_winsup()->_pass;
+#else
+ static char pass[_PASSWORD_LEN];
+#endif
+ struct termios ti, newti;
+
+ if (!passwd_in_memory_p)
+ read_etc_passwd();
+
+ if (dtable.not_open (0))
+ {
+ set_errno (EBADF);
+ pass[0] = '\0';
+ }
+ else
+ {
+ fhandler_base *fhstdin = dtable[0];
+ fhstdin->tcgetattr (&ti);
+ newti = ti;
+ newti.c_lflag &= ~ECHO;
+ fhstdin->tcsetattr (TCSANOW, &newti);
+ fputs (prompt, stderr);
+ fgets (pass, _PASSWORD_LEN, stdin);
+ fprintf (stderr, "\n");
+ for (int i=0; pass[i]; i++)
+ if (pass[i] == '\r' || pass[i] == '\n')
+ pass[i] = '\0';
+ fhstdin->tcsetattr (TCSANOW, &ti);
+ }
+ return pass;
+}