diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index 3a83a5981..63ae0433c 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,22 @@
+2004-05-17  Corinna Vinschen  <corinna@vinschen.de>
+
+	* cygwin.din: Add symbols flockfile, ftrylockfile, funlockfile,
+	getgrgid_r, getgrnam_r and getlogin_r.
+	* grp.cc (getgrgid_r): New function.
+	(getgrnam_r): Ditto.
+	* syscalls.cc (flockfile): Ditto.
+	(ftrylockfile): Ditto.
+	(funlockfile): Ditto.
+	* sysconf.cc (sysconf): Return LOGIN_NAME_MAX in case of
+	_SC_LOGIN_NAME_MAX.
+	* thread.cc (__cygwin_lock_trylock): Define int.  Return value from
+	call to pthread_mutex_trylock.
+	* uinfo.cc (getlogin_r): New function.
+	* include/limits.h: Define LOGIN_NAME_MAX.
+	* include/cygwin/version.h: Bump API minor number.
+	* include/sys/lock.h: Add declarations for __cygwin_lock_xxx functions.
+	* include/sys/stdio.h: Add define for _ftrylockfile.
+
 2004-05-17  Christopher Faylor  <cgf@alum.bu.edu>
 
 	* tty.cc (tty_list::init): Move hmaster initialization earlier to
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index dd8cbee58..f31906248 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -503,6 +503,9 @@ _finitef = finitef NOSIGFE
 fiprintf SIGFE
 _fiprintf = fiprintf SIGFE
 flock SIGFE
+flockfile SIGFE
+ftrylockfile SIGFE
+funlockfile SIGFE
 floor NOSIGFE
 _floor = floor NOSIGFE
 floorf NOSIGFE
@@ -614,9 +617,11 @@ _getgid32 = getgid32 NOSIGFE
 getgrent SIGFE
 _getgrent = getgrent SIGFE
 _getgrent32 = getgrent32 SIGFE
+getgrgid_r SIGFE
 getgrgid SIGFE
 _getgrgid = getgrgid SIGFE
 _getgrgid32 = getgrgid32 SIGFE
+getgrnam_r SIGFE
 getgrnam SIGFE
 _getgrnam = getgrnam SIGFE
 _getgrnam32 = getgrnam32 SIGFE
@@ -625,6 +630,7 @@ _getgroups = getgroups SIGFE
 _getgroups32 = getgroups32 SIGFE
 gethostid SIGFE
 getitimer SIGFE
+getlogin_r NOSIGFE
 getlogin NOSIGFE
 _getlogin = getlogin NOSIGFE
 getmntent SIGFE
diff --git a/winsup/cygwin/grp.cc b/winsup/cygwin/grp.cc
index ab0ef5738..39de15136 100644
--- a/winsup/cygwin/grp.cc
+++ b/winsup/cygwin/grp.cc
@@ -175,6 +175,49 @@ grp32togrp16 (struct __group16 *gp16, struct __group32 *gp32)
   return gp16;
 }
 
+extern "C" int
+getgrgid_r (__gid32_t gid, struct group *grp, char *buffer, size_t bufsize,
+	    struct group **result)
+{
+  *result = NULL;
+
+  if (!grp || !buffer)
+    return ERANGE;
+
+  struct __group32 *tempgr = internal_getgrgid (gid, true);
+  pthread_testcancel (); 
+  if (!tempgr)
+    return 0;
+
+  /* check needed buffer size. */
+  int i;
+  size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+		    + 2 + sizeof (char *);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
+  if (needsize > bufsize)
+    return ERANGE;
+
+  /* make a copy of tempgr */
+  *result = grp;
+  grp->gr_gid = tempgr->gr_gid;
+  grp->gr_name = buffer;
+  grp->gr_passwd = grp->gr_name + strlen (tempgr->gr_name) + 1;
+  grp->gr_mem = (char **) (grp->gr_passwd + strlen (tempgr->gr_passwd) + 1);
+  char *mem = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    {
+      grp->gr_mem[i] = mem;
+      mem += strlen (tempgr->gr_mem[i]) + 1;
+    }
+  grp->gr_mem[i] = NULL;
+  strcpy (grp->gr_name, tempgr->gr_name);
+  strcpy (grp->gr_passwd, tempgr->gr_passwd);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    strcpy (grp->gr_mem[i], tempgr->gr_mem[i]);
+  return 0;
+}
+
 extern "C" struct __group32 *
 getgrgid32 (__gid32_t gid)
 {
@@ -189,6 +232,49 @@ getgrgid (__gid16_t gid)
   return grp32togrp16 (&g16, getgrgid32 (gid16togid32 (gid)));
 }
 
+extern "C" int
+getgrnam_r (const char *nam, struct group *grp, char *buffer, size_t bufsize,
+	    struct group **result)
+{
+  *result = NULL;
+
+  if (!grp || !buffer)
+    return ERANGE;
+
+  struct __group32 *tempgr = internal_getgrnam (nam, true);
+  pthread_testcancel (); 
+  if (!tempgr)
+    return 0;
+
+  /* check needed buffer size. */
+  int i;
+  size_t needsize = strlen (tempgr->gr_name) + strlen (tempgr->gr_passwd)
+		    + 2 + sizeof (char *);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    needsize += strlen (tempgr->gr_mem[i]) + 1 + sizeof (char *);
+  if (needsize > bufsize)
+    return ERANGE;
+
+  /* make a copy of tempgr */
+  *result = grp;
+  grp->gr_gid = tempgr->gr_gid;
+  grp->gr_name = buffer;
+  grp->gr_passwd = grp->gr_name + strlen (tempgr->gr_name) + 1;
+  grp->gr_mem = (char **) (grp->gr_passwd + strlen (tempgr->gr_passwd) + 1);
+  char *mem = (char *) grp->gr_mem + (i + 1) * sizeof (char *);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    {
+      grp->gr_mem[i] = mem;
+      mem += strlen (tempgr->gr_mem[i]) + 1;
+    }
+  grp->gr_mem[i] = NULL;
+  strcpy (grp->gr_name, tempgr->gr_name);
+  strcpy (grp->gr_passwd, tempgr->gr_passwd);
+  for (i = 0; tempgr->gr_mem[i]; ++i)
+    strcpy (grp->gr_mem[i], tempgr->gr_mem[i]);
+  return 0;
+}
+
 extern "C" struct __group32 *
 getgrnam32 (const char *name)
 {
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index b63fcc15b..cc669604d 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -241,12 +241,14 @@ details. */
       113: Again redefine some mtget fields.  Use mt_fileno and mt_blkno as
            on Linux.
       114: Export rand_r, ttyname_r.
+      115: Export flockfile, ftrylockfile, funlockfile, getgrgid_r, getgrnam_r,
+           getlogin_r.
      */
 
      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 114
+#define CYGWIN_VERSION_API_MINOR 115
 
      /* There is also a compatibity version number associated with the
 	shared memory regions.  It is incremented when incompatible
diff --git a/winsup/cygwin/include/limits.h b/winsup/cygwin/include/limits.h
index 579dc9c38..25136acdf 100644
--- a/winsup/cygwin/include/limits.h
+++ b/winsup/cygwin/include/limits.h
@@ -151,6 +151,10 @@ details. */
 #undef TIMER_MAX
 #define TIMER_MAX 32
 
+/* Maximum number of characters in a login name. */
+#undef LOGIN_NAME_MAX
+#define LOGIN_NAME_MAX 256	/* equal to UNLEN defined in w32api/lmcons.h */
+
 /* Maximum number of characters in a tty name. */
 #undef TTY_NAME_MAX
 #define TTY_NAME_MAX 12
diff --git a/winsup/cygwin/include/sys/lock.h b/winsup/cygwin/include/sys/lock.h
index c0cc6fac7..ad0980ab0 100644
--- a/winsup/cygwin/include/sys/lock.h
+++ b/winsup/cygwin/include/sys/lock.h
@@ -37,4 +37,18 @@ typedef void *_LOCK_T;
 #define __lock_release(__lock) __cygwin_lock_unlock(&__lock)
 #define __lock_release_recursive(__lock) __cygwin_lock_unlock(&__lock)
 
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+void __cygwin_lock_init(_LOCK_T *);
+void __cygwin_lock_init_recursive(_LOCK_T *);
+void __cygwin_lock_fini(_LOCK_T *);
+void __cygwin_lock_lock(_LOCK_T *);
+int __cygwin_lock_trylock(_LOCK_T *);
+void __cygwin_lock_unlock(_LOCK_T *);
+#ifdef __cplusplus
+}
+#endif
+
 #endif
diff --git a/winsup/cygwin/include/sys/stdio.h b/winsup/cygwin/include/sys/stdio.h
index 04d8ffcaf..686ad534f 100644
--- a/winsup/cygwin/include/sys/stdio.h
+++ b/winsup/cygwin/include/sys/stdio.h
@@ -17,6 +17,9 @@ details. */
 #  if !defined(_flockfile)
 #    define _flockfile(fp) __cygwin_lock_lock ((_LOCK_T *)&(fp)->_lock)
 #  endif
+#  if !defined(_ftrylockfile)
+#    define _ftrylockfile(fp) __cygwin_lock_trylock ((_LOCK_T *)&(fp)->_lock)
+#  endif
 #  if !defined(_funlockfile)
 #    define _funlockfile(fp) __cygwin_lock_unlock ((_LOCK_T *)&(fp)->_lock)
 #  endif
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index af2974413..e7a698bb7 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2840,3 +2840,21 @@ endusershell ()
     fclose (shell_fp);
   shell_index = 0;
 }
+
+extern "C" void
+flockfile (FILE *file)
+{
+  _flockfile (file);
+}
+
+extern "C" int
+ftrylockfile (FILE *file)
+{
+  return _ftrylockfile (file);
+}
+
+extern "C" void
+funlockfile (FILE *file)
+{
+  _funlockfile (file);
+}
diff --git a/winsup/cygwin/sysconf.cc b/winsup/cygwin/sysconf.cc
index 2f24cd213..4de8d8738 100644
--- a/winsup/cygwin/sysconf.cc
+++ b/winsup/cygwin/sysconf.cc
@@ -52,6 +52,7 @@ sysconf (int in)
       case _SC_SAVED_IDS:
 	return _POSIX_SAVED_IDS;
       case _SC_LOGIN_NAME_MAX:
+        return LOGIN_NAME_MAX;
       case _SC_GETPW_R_SIZE_MAX:
       case _SC_GETGR_R_SIZE_MAX:
 	return 16*1024;
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 7aac92ae0..8c36dfbce 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -82,10 +82,10 @@ __cygwin_lock_lock (_LOCK_T *lock)
   pthread_mutex_lock ((pthread_mutex_t*) lock);
 }
 
-extern "C" void
+extern "C" int
 __cygwin_lock_trylock (_LOCK_T *lock)
 {
-  pthread_mutex_trylock ((pthread_mutex_t*) lock);
+  return pthread_mutex_trylock ((pthread_mutex_t*) lock);
 }
 
 
diff --git a/winsup/cygwin/uinfo.cc b/winsup/cygwin/uinfo.cc
index 231347e1f..2bf164ff6 100644
--- a/winsup/cygwin/uinfo.cc
+++ b/winsup/cygwin/uinfo.cc
@@ -166,6 +166,20 @@ uinfo_init ()
   cygheap->user.set_saved_sid ();	/* Update the original sid */
 }
 
+extern "C" int
+getlogin_r (char *name, size_t namesize)
+{
+  char *login = getlogin ();
+  size_t len = strlen (login) + 1;
+  if (len > namesize)
+    return ERANGE;
+  int err = __check_null_invalid_struct (name, len);
+  if (err)
+    return err;
+  strncpy (name, login, len);
+  return 0;
+}
+
 extern "C" char *
 getlogin (void)
 {