diff options
Diffstat (limited to 'libguile/posix.c')
-rw-r--r-- | libguile/posix.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/libguile/posix.c b/libguile/posix.c index 041b8b129..c39fc57b5 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -1,6 +1,6 @@ /* Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, * 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, - * 2014, 2016 Free Software Foundation, Inc. + * 2014, 2016, 2017 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -1935,26 +1935,43 @@ SCM_DEFINE (scm_crypt, "crypt", 2, 0, 0, "crypt(3) library call.") #define FUNC_NAME s_scm_crypt { + int err; SCM ret; char *c_key, *c_salt, *c_ret; scm_dynwind_begin (0); - scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); c_key = scm_to_locale_string (key); scm_dynwind_free (c_key); c_salt = scm_to_locale_string (salt); scm_dynwind_free (c_salt); + /* Take the lock because 'crypt' uses a static buffer. */ + scm_i_dynwind_pthread_mutex_lock (&scm_i_misc_mutex); + /* The Linux crypt(3) man page says crypt will return NULL and set errno on error. (Eg. ENOSYS if legal restrictions mean it cannot be implemented). */ c_ret = crypt (c_key, c_salt); + if (c_ret == NULL) - SCM_SYSERROR; + /* Note: Do not throw until we've released 'scm_i_misc_mutex' since + this would cause a deadlock down the path. */ + err = errno; + else + { + err = 0; + ret = scm_from_locale_string (c_ret); + } - ret = scm_from_locale_string (c_ret); scm_dynwind_end (); + + if (err != 0) + { + errno = err; + SCM_SYSERROR; + } + return ret; } #undef FUNC_NAME |