Index: cygwin.din =================================================================== RCS file: /cvs/src/src/winsup/cygwin/cygwin.din,v retrieving revision 1.26 diff -u -p -r1.26 cygwin.din --- cygwin.din 2001/04/13 15:28:20 1.26 +++ cygwin.din 2001/04/16 11:01:15 @@ -933,8 +933,10 @@ getpwduid _getpwduid = getpwduid getpwnam _getpwnam = getpwnam +getpwnam_r getpwuid _getpwuid = getpwuid +getpwuid_r getpgrp _getpgrp = getpgrp getgrent Index: passwd.cc =================================================================== RCS file: /cvs/src/src/winsup/cygwin/passwd.cc,v retrieving revision 1.17 diff -u -p -r1.17 passwd.cc --- passwd.cc 2001/01/28 05:51:14 1.17 +++ passwd.cc 2001/04/16 11:01:15 @@ -122,6 +122,20 @@ read_etc_passwd () { extern int passwd_sem; char linebuf[1024]; + /* A mutex is ok for speed here - pthreads will use critical sections not mutex's + * for non-shared mutexs in the future. Also, this function will at most be called + * once from each thread, after that the passwd_state test will succeed + */ + static pthread_mutex_t etc_passwd_mutex = (pthread_mutex_t) PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_lock(&etc_passwd_mutex); + + /* if we got blocked by the mutex, then etc_passwd may have been processed */ + if (!(passwd_state == uninitialized)) + { + pthread_mutex_unlock(&etc_passwd_mutex); + return; + } + ++passwd_sem; FILE *f = fopen ("/etc/passwd", "rt"); --passwd_sem; @@ -145,9 +159,11 @@ read_etc_passwd () add_pwd_line (linebuf); passwd_state = emulated; } + pthread_mutex_unlock(&etc_passwd_mutex); } /* Cygwin internal */ +/* If this ever becomes non-reentrant, update all the getpw*_r functions */ static struct passwd * search_for (uid_t uid, const char *name) { @@ -188,6 +204,40 @@ getpwuid (uid_t uid) return search_for (uid, 0); } +extern "C" int +getpwuid_r (uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +{ + *result = NULL; + + if (!pwd || !buffer) + return ERANGE; + + if (passwd_state == uninitialized) + read_etc_passwd (); + + struct passwd *temppw = search_for (uid, 0); + + if (!temppw) + return 0; + + /* check needed buffer size. */ + size_t needsize = strlen (temppw->pw_name) + strlen (temppw->pw_dir) + strlen (temppw->pw_shell); + if (needsize > bufsize) + return ERANGE; + + /* make a copy of temppw */ + *result = pwd; + pwd->pw_uid = temppw->pw_uid; + pwd->pw_gid = temppw->pw_gid; + pwd->pw_name = buffer; + pwd->pw_dir = buffer + strlen (temppw->pw_name); + pwd->pw_shell = buffer + strlen (temppw->pw_name) + strlen (temppw->pw_dir); + strcpy (pwd->pw_name, temppw->pw_name); + strcpy (pwd->pw_dir, temppw->pw_dir); + strcpy (pwd->pw_shell, temppw->pw_shell); + return 0; +} + extern "C" struct passwd * getpwnam (const char *name) { @@ -195,6 +245,45 @@ getpwnam (const char *name) read_etc_passwd (); return search_for (0, name); +} + + +/* the max size buffer we can expect to + * use is returned via sysconf with _SC_GETPW_R_SIZE_MAX. + * This may need updating! - Rob Collins April 2001. + */ +extern "C" int +getpwnam_r (const char *nam, struct passwd *pwd, char *buffer, size_t bufsize, struct passwd **result) +{ + *result = NULL; + + if (!pwd || !buffer || !nam) + return ERANGE; + + if (passwd_state == uninitialized) + read_etc_passwd (); + + struct passwd *temppw = search_for (0, nam); + + if (!temppw) + return 0; + + /* check needed buffer size. */ + size_t needsize = strlen (temppw->pw_name) + strlen (temppw->pw_dir) + strlen (temppw->pw_shell); + if (needsize > bufsize) + return ERANGE; + + /* make a copy of temppw */ + *result = pwd; + pwd->pw_uid = temppw->pw_uid; + pwd->pw_gid = temppw->pw_gid; + pwd->pw_name = buffer; + pwd->pw_dir = buffer + strlen (temppw->pw_name); + pwd->pw_shell = buffer + strlen (temppw->pw_name) + strlen (temppw->pw_dir); + strcpy (pwd->pw_name, temppw->pw_name); + strcpy (pwd->pw_dir, temppw->pw_dir); + strcpy (pwd->pw_shell, temppw->pw_shell); + return 0; } extern "C" struct passwd *