1 /* passwd.cc: getpwnam () and friends
3 Copyright 1996, 1997, 1998 Cygnus Solutions.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 /* Read /etc/passwd only once for better performance. This is done
18 on the first call that needs information from it. */
20 static struct passwd *passwd_buf = NULL; /* passwd contents in memory */
21 static int curr_lines = 0;
22 static int max_lines = 0;
24 /* Set to 1 when /etc/passwd has been read in by read_etc_passwd (). */
25 /* Functions in this file need to check the value of passwd_in_memory_p
26 and read in the password file if it isn't set. */
27 static int passwd_in_memory_p = 0;
29 /* Position in the passwd cache */
31 #define pw_pos _reent_winsup()->_pw_pos
33 static int pw_pos = 0;
36 /* Remove a : teminated string from the buffer, and increment the pointer */
38 grab_string (char **p)
43 while (*src && *src != ':' && *src != '\n')
61 while (*src && *src != ':' && *src != '\n')
69 /* Parse /etc/passwd line into passwd structure. */
71 parse_pwd (struct passwd &res, char *buf)
73 /* Allocate enough room for the passwd struct and all the strings
75 size_t len = strlen (buf);
76 char *mybuf = (char *) malloc (len + 1);
77 (void) memcpy (mybuf, buf, len + 1);
78 if (mybuf[--len] == '\n')
81 res.pw_name = strlwr(grab_string (&mybuf));
82 res.pw_passwd = grab_string (&mybuf);
83 res.pw_uid = grab_int (&mybuf);
84 res.pw_gid = grab_int (&mybuf);
86 res.pw_gecos = grab_string (&mybuf);
87 res.pw_dir = grab_string (&mybuf);
88 res.pw_shell = grab_string (&mybuf);
91 /* Add one line from /etc/passwd into the password cache */
93 add_pwd_line (char *line)
95 if (curr_lines >= max_lines)
98 passwd_buf = (struct passwd *) realloc (passwd_buf, max_lines * sizeof (struct passwd));
100 parse_pwd (passwd_buf[curr_lines++], line);
103 /* Read in /etc/passwd and save contents in the password cache.
104 This sets passwd_in_memory_p to 1 so functions in this file can
105 tell that /etc/passwd has been read in */
109 extern int passwd_sem;
112 FILE *f = fopen ("/etc/passwd", "r");
117 while (fgets (linebuf, sizeof (linebuf), f) != NULL)
119 if (strlen (linebuf))
120 add_pwd_line (linebuf);
127 debug_printf ("Emulating /etc/passwd");
128 char user_name [ MAX_USER_NAME ];
129 DWORD user_name_len = MAX_USER_NAME;
130 if (! GetUserNameA (user_name, &user_name_len))
132 strncpy (user_name, "Administrator", MAX_USER_NAME);
133 debug_printf ("Failed to get current user name. %E");
135 snprintf (linebuf, sizeof (linebuf), "%s::%u:%u::%s:/bin/sh", user_name,
136 DEFAULT_UID, DEFAULT_GID, getenv ("HOME") ?: "/");
137 add_pwd_line (linebuf);
139 passwd_in_memory_p = 1;
142 /* Cygwin internal */
143 static struct passwd *
144 search_for (uid_t uid, const char *name)
146 struct passwd *res = 0;
147 struct passwd *default_pw = 0;
149 for (int i = 0; i < curr_lines; i++)
151 res = passwd_buf + i;
152 if (res->pw_uid == DEFAULT_UID)
154 /* on Windows NT user names are case-insensitive */
157 if (strcasematch (name, res->pw_name))
160 else if (uid == res->pw_uid)
171 if (!passwd_in_memory_p)
174 return search_for (uid, 0);
179 getpwnam (const char *name)
181 if (!passwd_in_memory_p)
184 return search_for (0, name);
191 if (!passwd_in_memory_p)
194 if (pw_pos < curr_lines)
195 return passwd_buf + pw_pos++;
202 getpwduid (uid_t uid)
204 if (!passwd_in_memory_p)
214 if (!passwd_in_memory_p)
224 if (!passwd_in_memory_p)
234 if (!passwd_in_memory_p)
242 getpass (const char * prompt)
245 char *pass=_reent_winsup()->_pass;
247 static char pass[_PASSWORD_LEN];
249 struct termios ti, newti;
251 if (!passwd_in_memory_p)
254 if (dtable.not_open (0))
261 fhandler_base *fhstdin = dtable[0];
262 fhstdin->tcgetattr (&ti);
264 newti.c_lflag &= ~ECHO;
265 fhstdin->tcsetattr (TCSANOW, &newti);
266 fputs (prompt, stderr);
267 fgets (pass, _PASSWORD_LEN, stdin);
268 fprintf (stderr, "\n");
269 for (int i=0; pass[i]; i++)
270 if (pass[i] == '\r' || pass[i] == '\n')
272 fhstdin->tcsetattr (TCSANOW, &ti);