]>
sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/passwd.cc
1 /* passwd.cc: getpwnam () and friends
3 Copyright 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008,
4 2009, 2010, 2011, 2012 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
23 #include "shared_info.h"
25 /* Read /etc/passwd only once for better performance. This is done
26 on the first call that needs information from it. */
29 static pwdgrp
pr (passwd_buf
);
31 /* Parse /etc/passwd line into passwd structure. */
33 pwdgrp::parse_passwd ()
35 passwd
&res
= (*passwd_buf
)[curr_lines
];
36 res
.pw_name
= next_str (':');
37 res
.pw_passwd
= next_str (':');
38 if (!next_num (res
.pw_uid
))
40 if (!next_num (res
.pw_gid
))
42 res
.pw_comment
= NULL
;
43 res
.pw_gecos
= next_str (':');
44 res
.pw_dir
= next_str (':');
45 res
.pw_shell
= next_str (':');
49 /* Read in /etc/passwd and save contents in the password cache.
50 This sets pr to loaded or emulated so functions in this file can
51 tell that /etc/passwd has been read in or will be emulated. */
53 pwdgrp::read_passwd ()
55 load (L
"\\etc\\passwd");
57 char strbuf
[128] = "";
58 bool searchentry
= true;
61 static char NO_COPY pretty_ls
[] = "????????:*:-1:-1:::";
64 cygsid tu
= cygheap
->user
.sid ();
66 if (!user_shared
->cb
|| myself
->uid
== ILLEGAL_UID
)
67 searchentry
= !internal_getpwsid (tu
);
69 && (!(pw
= internal_getpwnam (cygheap
->user
.name ()))
71 || (myself
->uid
!= ILLEGAL_UID
72 && myself
->uid
!= (__uid32_t
) pw
->pw_uid
73 && !internal_getpwuid (myself
->uid
))))
75 static char linebuf
[1024]; // must be static and
76 // should not be NO_COPY
77 snprintf (linebuf
, sizeof (linebuf
), "%s:*:%lu:%lu:,%s:%s:/bin/sh",
78 cygheap
->user
.name (),
79 (!user_shared
->cb
|| myself
->uid
== ILLEGAL_UID
)
80 ? UNKNOWN_UID
: myself
->uid
,
81 !user_shared
->cb
? UNKNOWN_GID
: myself
->gid
,
82 strbuf
, getenv ("HOME") ?: "");
83 debug_printf ("Completing /etc/passwd: %s", linebuf
);
89 internal_getpwsid (cygpsid
&sid
)
92 char *ptr1
, *ptr2
, *endptr
;
93 char sid_string
[128] = {0,','};
97 if (sid
.string (sid_string
+ 2))
99 endptr
= strchr (sid_string
+ 2, 0) - 1;
100 for (int i
= 0; i
< pr
.curr_lines
; i
++)
103 if (pw
->pw_dir
> pw
->pw_gecos
+ 8)
104 for (ptr1
= endptr
, ptr2
= pw
->pw_dir
- 2;
105 *ptr1
== *ptr2
; ptr2
--)
114 internal_getpwuid (__uid32_t uid
, bool check
)
118 for (int i
= 0; i
< pr
.curr_lines
; i
++)
119 if (uid
== (__uid32_t
) passwd_buf
[i
].pw_uid
)
120 return passwd_buf
+ i
;
125 internal_getpwnam (const char *name
, bool check
)
129 for (int i
= 0; i
< pr
.curr_lines
; i
++)
130 /* on Windows NT user names are case-insensitive */
131 if (strcasematch (name
, passwd_buf
[i
].pw_name
))
132 return passwd_buf
+ i
;
137 extern "C" struct passwd
*
138 getpwuid32 (__uid32_t uid
)
140 struct passwd
*temppw
= internal_getpwuid (uid
, true);
141 pthread_testcancel ();
145 extern "C" struct passwd
*
146 getpwuid (__uid16_t uid
)
148 return getpwuid32 (uid16touid32 (uid
));
152 getpwuid_r32 (__uid32_t uid
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
159 struct passwd
*temppw
= internal_getpwuid (uid
, true);
160 pthread_testcancel ();
164 /* check needed buffer size. */
165 size_t needsize
= strlen (temppw
->pw_name
) + strlen (temppw
->pw_passwd
)
166 + strlen (temppw
->pw_gecos
) + strlen (temppw
->pw_dir
)
167 + strlen (temppw
->pw_shell
) + 5;
168 if (needsize
> bufsize
)
171 /* make a copy of temppw */
173 pwd
->pw_uid
= temppw
->pw_uid
;
174 pwd
->pw_gid
= temppw
->pw_gid
;
175 buffer
= stpcpy (pwd
->pw_name
= buffer
, temppw
->pw_name
);
176 buffer
= stpcpy (pwd
->pw_passwd
= buffer
+ 1, temppw
->pw_passwd
);
177 buffer
= stpcpy (pwd
->pw_gecos
= buffer
+ 1, temppw
->pw_gecos
);
178 buffer
= stpcpy (pwd
->pw_dir
= buffer
+ 1, temppw
->pw_dir
);
179 stpcpy (pwd
->pw_shell
= buffer
+ 1, temppw
->pw_shell
);
180 pwd
->pw_comment
= NULL
;
185 getpwuid_r (__uid16_t uid
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
187 return getpwuid_r32 (uid16touid32 (uid
), pwd
, buffer
, bufsize
, result
);
190 extern "C" struct passwd
*
191 getpwnam (const char *name
)
193 struct passwd
*temppw
= internal_getpwnam (name
, true);
194 pthread_testcancel ();
199 /* the max size buffer we can expect to
200 * use is returned via sysconf with _SC_GETPW_R_SIZE_MAX.
201 * This may need updating! - Rob Collins April 2001.
204 getpwnam_r (const char *nam
, struct passwd
*pwd
, char *buffer
, size_t bufsize
, struct passwd
**result
)
208 if (!pwd
|| !buffer
|| !nam
)
211 struct passwd
*temppw
= internal_getpwnam (nam
, true);
212 pthread_testcancel ();
217 /* check needed buffer size. */
218 size_t needsize
= strlen (temppw
->pw_name
) + strlen (temppw
->pw_passwd
)
219 + strlen (temppw
->pw_gecos
) + strlen (temppw
->pw_dir
)
220 + strlen (temppw
->pw_shell
) + 5;
221 if (needsize
> bufsize
)
224 /* make a copy of temppw */
226 pwd
->pw_uid
= temppw
->pw_uid
;
227 pwd
->pw_gid
= temppw
->pw_gid
;
228 buffer
= stpcpy (pwd
->pw_name
= buffer
, temppw
->pw_name
);
229 buffer
= stpcpy (pwd
->pw_passwd
= buffer
+ 1, temppw
->pw_passwd
);
230 buffer
= stpcpy (pwd
->pw_gecos
= buffer
+ 1, temppw
->pw_gecos
);
231 buffer
= stpcpy (pwd
->pw_dir
= buffer
+ 1, temppw
->pw_dir
);
232 stpcpy (pwd
->pw_shell
= buffer
+ 1, temppw
->pw_shell
);
233 pwd
->pw_comment
= NULL
;
237 extern "C" struct passwd
*
240 if (_my_tls
.locals
.pw_pos
== 0)
242 if (_my_tls
.locals
.pw_pos
< pr
.curr_lines
)
243 return passwd_buf
+ _my_tls
.locals
.pw_pos
++;
248 extern "C" struct passwd
*
249 getpwduid (__uid16_t
)
257 _my_tls
.locals
.pw_pos
= 0;
263 _my_tls
.locals
.pw_pos
= 0;
273 _getpass_close_fd (void *arg
)
276 fclose ((FILE *) arg
);
280 getpass (const char * prompt
)
282 char *pass
= _my_tls
.locals
.pass
;
283 struct termios ti
, newti
;
286 /* Try to use controlling tty in the first place. Use stdin and stderr
288 FILE *in
= stdin
, *err
= stderr
;
289 FILE *tty
= fopen ("/dev/tty", "w+b");
290 pthread_cleanup_push (_getpass_close_fd
, tty
);
293 /* Set close-on-exec for obvious reasons. */
294 fcntl (fileno (tty
), F_SETFD
, fcntl (fileno (tty
), F_GETFD
) | FD_CLOEXEC
);
298 /* Make sure to notice if stdin is closed. */
299 if (fileno (in
) >= 0)
302 /* Change tty attributes if possible. */
303 if (!tcgetattr (fileno (in
), &ti
))
306 newti
.c_lflag
&= ~(ECHO
| ISIG
); /* No echo, no signal handling. */
307 if (!tcsetattr (fileno (in
), TCSANOW
, &newti
))
312 fgets (pass
, _PASSWORD_LEN
, in
);
315 tcsetattr (fileno (in
), TCSANOW
, &ti
);
317 char *crlf
= strpbrk (pass
, "\r\n");
321 pthread_cleanup_pop (1);
This page took 0.050247 seconds and 5 git commands to generate.