1
0
mirror of https://git.savannah.gnu.org/git/emacs.git synced 2025-01-23 18:47:57 +00:00

Implement dynamic loading of GnuTLS on Windows.

* lisp/term/w32-win.el (dynamic-library-alist): Add `gnutls'.

* nt/INSTALL: Clarify GnuTLS support.

* src/callproc.c, src/emacs.c: Include lisp.h before src/w32.h, not after.

* src/gnutls.c (Qgnutls_dll): Define.
  (DEF_GNUTLS_FN, LOAD_GNUTLS_FN): New macros.
  (gnutls_*): Declare function pointers.
  (init_gnutls_functions): New function to initialize function pointers.
  (emacs_gnutls_handshake, Fgnutls_error_string, Fgnutls_deinit)
  (emacs_gnutls_global_init, Fgnutls_bye): Use function pointers.
  (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
  Wrappers for gnutls_record_check_pending and gnutls_transport_set_errno.
  (emacs_gnutls_write, emacs_gnutls_read)
  (emacs_gnutls_handle_error, Fgnutls_error_fatalp)
  (Fgnutls_available_p): New function.
  (Fgnutls_boot): Call Fgnutls_available_p.  Use function pointers.
  (syms_of_gnutls) <Qgnutls_dll>: Initialize and staticpro it.
  (syms_of_gnutls) <Sgnutls_available_p>: defsubr it.

* src/gnutls.h (GNUTLS_EMACS_ERROR_NOT_LOADED): New macro.
  (emacs_gnutls_write, emacs_gnutls_read): Mark as extern.
  (emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
  Declare.

* src/w32.c (QCloaded_from, Vlibrary_cache): Define.
  (w32_delayed_load): Move from image.c.  When loading a library, record
  its filename in the :loaded-from property of the library id.
  (globals_of_w32) <QCloaded_from, Vlibrary_cache>:
  Initialize and staticpro them.
  (emacs_gnutls_pull, emacs_gnutls_push): Call emacs_gnutls_* functions.

* src/image.c: Include w32.h.
  (Vimage_type_cache): Delete.
  (syms_of_image) <Vimage_type_cache>: Don't initialize and staticpro it.
  (CACHE_IMAGE_TYPE, Finit_image_library): Use Vlibrary_cache instead.
  (w32_delayed_load): Move to w32.c.

* src/process.c: Include lisp.h before src/w32.h, not after.
  (wait_reading_process_output): Call emacs_gnutls_record_check_pending
  instead of gnutls_record_check_pending.

* src/w32.h (VlibraryCache, QCloaded_from, w32_delayed_load): Declare.
This commit is contained in:
Juanma Barranquero 2011-05-04 16:03:16 +02:00
parent 67a2aecd40
commit 0898ca10c0
13 changed files with 420 additions and 112 deletions

View File

@ -1,3 +1,7 @@
2011-05-04 Juanma Barranquero <lekktu@gmail.com>
* term/w32-win.el (dynamic-library-alist): Add `gnutls'.
2011-05-04 Glenn Morris <rgm@gnu.org>
* calendar/diary-lib.el (diary-fancy-date-pattern): Turn it into a

View File

@ -202,13 +202,14 @@ See the documentation of `create-fontset-from-fontset-spec' for the format.")
'(png "libpng12d.dll" "libpng12.dll" "libpng3.dll" "libpng.dll"
;; these are libpng 1.2.8 from GTK+
"libpng13d.dll" "libpng13.dll"))
'(jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll")
'(tiff "libtiff3.dll" "libtiff.dll")
'(gif "giflib4.dll" "libungif4.dll" "libungif.dll")
'(svg "librsvg-2-2.dll")
'(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
'(glib "libglib-2.0-0.dll")
'(gobject "libgobject-2.0-0.dll")))
'(jpeg "jpeg62.dll" "libjpeg.dll" "jpeg-62.dll" "jpeg.dll")
'(tiff "libtiff3.dll" "libtiff.dll")
'(gif "giflib4.dll" "libungif4.dll" "libungif.dll")
'(svg "librsvg-2-2.dll")
'(gdk-pixbuf "libgdk_pixbuf-2.0-0.dll")
'(glib "libglib-2.0-0.dll")
'(gobject "libgobject-2.0-0.dll")
'(gnutls "libgnutls-26.dll")))
;;; multi-tty support
(defvar w32-initialized nil

View File

@ -1,3 +1,7 @@
2011-05-04 Juanma Barranquero <lekktu@gmail.com>
* INSTALL: Clarify GnuTLS support.
2011-04-30 Eli Zaretskii <eliz@gnu.org>
* config.nt (HAVE_LONG_LONG_INT, HAVE_UNSIGNED_LONG_LONG_INT):

View File

@ -325,12 +325,17 @@
* Optional GnuTLS support
You can build Emacs with GnuTLS support. Put the gnutls/gnutls.h header in
the include path and link to the appropriate libraries (gnutls.dll and
gcrypt.dll) with the --lib option.
If configure.bat finds the gnutls/gnutls.h file in the include path,
Emacs is built with GnuTLS support by default; to avoid that you can
pass the argument --without-gnutls.
You can get pre-built binaries and an installer at
http://josefsson.org/gnutls4win/.
In order to support GnuTLS at runtime, a GnuTLS-enabled Emacs must
be able to find the relevant DLLs during startup; failure to do so
is not an error, but GnuTLS won't be available to the running
session.
You can get pre-built binaries (including any required DLL and the
gnutls.h file) and an installer at http://josefsson.org/gnutls4win/.
* Experimental SVG support

View File

@ -1,3 +1,48 @@
2011-05-04 Juanma Barranquero <lekktu@gmail.com>
Implement dynamic loading of GnuTLS on Windows.
* gnutls.h (GNUTLS_EMACS_ERROR_NOT_LOADED): New macro.
(emacs_gnutls_write, emacs_gnutls_read): Mark as extern.
(emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
Declare.
* gnutls.c (Qgnutls_dll): Define.
(DEF_GNUTLS_FN, LOAD_GNUTLS_FN): New macros.
(gnutls_*): Declare function pointers.
(init_gnutls_functions): New function to initialize function pointers.
(emacs_gnutls_handshake, Fgnutls_error_string, Fgnutls_deinit)
(emacs_gnutls_global_init, Fgnutls_bye): Use function pointers.
(emacs_gnutls_record_check_pending, emacs_gnutls_transport_set_errno):
Wrappers for gnutls_record_check_pending and gnutls_transport_set_errno.
(emacs_gnutls_write, emacs_gnutls_read)
(emacs_gnutls_handle_error, Fgnutls_error_fatalp)
(Fgnutls_available_p): New function.
(Fgnutls_boot): Call Fgnutls_available_p. Use function pointers.
(syms_of_gnutls) <Qgnutls_dll>: Initialize and staticpro it.
(syms_of_gnutls) <Sgnutls_available_p>: defsubr it.
* image.c: Include w32.h.
(Vimage_type_cache): Delete.
(syms_of_image) <Vimage_type_cache>: Don't initialize and staticpro it.
(CACHE_IMAGE_TYPE, Finit_image_library): Use Vlibrary_cache instead.
(w32_delayed_load): Move to w32.c.
* w32.h (VlibraryCache, QCloaded_from, w32_delayed_load): Declare.
* w32.c (QCloaded_from, Vlibrary_cache): Define.
(w32_delayed_load): Move from image.c. When loading a library, record
its filename in the :loaded-from property of the library id.
(globals_of_w32) <QCloaded_from, Vlibrary_cache>:
Initialize and staticpro them.
(emacs_gnutls_pull, emacs_gnutls_push): Call emacs_gnutls_* functions.
* process.c: Include lisp.h before w32.h, not after.
(wait_reading_process_output): Call emacs_gnutls_record_check_pending
instead of gnutls_record_check_pending.
* callproc.c, emacs.c: Include lisp.h before w32.h, not after.
2011-05-04 Teodor Zlatanov <tzz@lifelogs.com>
* gnutls.c (Fgnutls_boot): Support :keylist and :crlfiles options

View File

@ -29,6 +29,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/file.h>
#include <fcntl.h>
#include "lisp.h"
#ifdef WINDOWSNT
#define NOMINMAX
#include <windows.h>
@ -41,7 +43,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <sys/param.h>
#endif /* MSDOS */
#include "lisp.h"
#include "commands.h"
#include "buffer.h"
#include "character.h"

View File

@ -29,6 +29,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <setjmp.h>
#include <unistd.h>
#include "lisp.h"
#ifdef WINDOWSNT
#include <fcntl.h>
#include <windows.h> /* just for w32.h */
@ -41,7 +43,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <GNUstepBase/GSConfig.h>
#endif
#include "lisp.h"
#include "commands.h"
#include "intervals.h"
#include "buffer.h"

View File

@ -34,6 +34,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
static int
emacs_gnutls_handle_error (gnutls_session_t, int err);
static Lisp_Object Qgnutls_dll;
static Lisp_Object Qgnutls_log_level;
static Lisp_Object Qgnutls_code;
static Lisp_Object Qgnutls_anon, Qgnutls_x509pki;
@ -56,6 +57,181 @@ static Lisp_Object Qgnutls_bootprop_verify_hostname_error;
/* Callback keys for `gnutls-boot'. Unused currently. */
static Lisp_Object Qgnutls_bootprop_callbacks_verify;
static void gnutls_log_function (int, const char *);
static void gnutls_log_function2 (int, const char*, const char*);
#ifdef WINDOWSNT
/* Macro for defining functions that will be loaded from the GnuTLS DLL. */
#define DEF_GNUTLS_FN(rettype,func,args) rettype (FAR CDECL *fn_##func)args
/* Macro for loading GnuTLS functions from the library. */
#define LOAD_GNUTLS_FN(lib,func) { \
fn_##func = (void *) GetProcAddress (lib, #func); \
if (!fn_##func) return 0; \
}
DEF_GNUTLS_FN (gnutls_alert_description_t, gnutls_alert_get,
(gnutls_session_t));
DEF_GNUTLS_FN (const char *, gnutls_alert_get_name,
(gnutls_alert_description_t));
DEF_GNUTLS_FN (int, gnutls_alert_send_appropriate, (gnutls_session_t, int));
DEF_GNUTLS_FN (int, gnutls_anon_allocate_client_credentials,
(gnutls_anon_client_credentials_t *));
DEF_GNUTLS_FN (void, gnutls_anon_free_client_credentials,
(gnutls_anon_client_credentials_t));
DEF_GNUTLS_FN (int, gnutls_bye, (gnutls_session_t, gnutls_close_request_t));
DEF_GNUTLS_FN (int, gnutls_certificate_allocate_credentials,
(gnutls_certificate_credentials_t *));
DEF_GNUTLS_FN (void, gnutls_certificate_free_credentials,
(gnutls_certificate_credentials_t));
DEF_GNUTLS_FN (const gnutls_datum_t *, gnutls_certificate_get_peers,
(gnutls_session_t, unsigned int *));
DEF_GNUTLS_FN (void, gnutls_certificate_set_verify_flags,
(gnutls_certificate_credentials_t, unsigned int));
DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_crl_file,
(gnutls_certificate_credentials_t, const char *,
gnutls_x509_crt_fmt_t));
DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_key_file,
(gnutls_certificate_credentials_t, const char *, const char *,
gnutls_x509_crt_fmt_t));
DEF_GNUTLS_FN (int, gnutls_certificate_set_x509_trust_file,
(gnutls_certificate_credentials_t, const char *,
gnutls_x509_crt_fmt_t));
DEF_GNUTLS_FN (gnutls_certificate_type_t, gnutls_certificate_type_get,
(gnutls_session_t));
DEF_GNUTLS_FN (int, gnutls_certificate_verify_peers2,
(gnutls_session_t, unsigned int *));
DEF_GNUTLS_FN (int, gnutls_credentials_set,
(gnutls_session_t, gnutls_credentials_type_t, void *));
DEF_GNUTLS_FN (void, gnutls_deinit, (gnutls_session_t));
DEF_GNUTLS_FN (int, gnutls_error_is_fatal, (int));
DEF_GNUTLS_FN (int, gnutls_global_init, (void));
DEF_GNUTLS_FN (void, gnutls_global_set_log_function, (gnutls_log_func));
DEF_GNUTLS_FN (void, gnutls_global_set_log_level, (int));
DEF_GNUTLS_FN (int, gnutls_handshake, (gnutls_session_t));
DEF_GNUTLS_FN (int, gnutls_init, (gnutls_session_t *, gnutls_connection_end_t));
DEF_GNUTLS_FN (int, gnutls_priority_set_direct,
(gnutls_session_t, const char *, const char **));
DEF_GNUTLS_FN (size_t, gnutls_record_check_pending, (gnutls_session_t));
DEF_GNUTLS_FN (ssize_t, gnutls_record_recv, (gnutls_session_t, void *, size_t));
DEF_GNUTLS_FN (ssize_t, gnutls_record_send,
(gnutls_session_t, const void *, size_t));
DEF_GNUTLS_FN (const char *, gnutls_strerror, (int));
DEF_GNUTLS_FN (void, gnutls_transport_set_errno, (gnutls_session_t, int));
DEF_GNUTLS_FN (void, gnutls_transport_set_lowat, (gnutls_session_t, int));
DEF_GNUTLS_FN (void, gnutls_transport_set_ptr2,
(gnutls_session_t, gnutls_transport_ptr_t,
gnutls_transport_ptr_t));
DEF_GNUTLS_FN (void, gnutls_transport_set_pull_function,
(gnutls_session_t, gnutls_pull_func));
DEF_GNUTLS_FN (void, gnutls_transport_set_push_function,
(gnutls_session_t, gnutls_push_func));
DEF_GNUTLS_FN (int, gnutls_x509_crt_check_hostname,
(gnutls_x509_crt_t, const char *));
DEF_GNUTLS_FN (void, gnutls_x509_crt_deinit, (gnutls_x509_crt_t));
DEF_GNUTLS_FN (int, gnutls_x509_crt_import,
(gnutls_x509_crt_t, const gnutls_datum_t *,
gnutls_x509_crt_fmt_t));
DEF_GNUTLS_FN (int, gnutls_x509_crt_init, (gnutls_x509_crt_t *));
static int
init_gnutls_functions (Lisp_Object libraries)
{
HMODULE library;
if (!(library = w32_delayed_load (libraries, Qgnutls_dll)))
{
GNUTLS_LOG (1, 1, "GnuTLS library not found");
return 0;
}
LOAD_GNUTLS_FN (library, gnutls_alert_get);
LOAD_GNUTLS_FN (library, gnutls_alert_get_name);
LOAD_GNUTLS_FN (library, gnutls_alert_send_appropriate);
LOAD_GNUTLS_FN (library, gnutls_anon_allocate_client_credentials);
LOAD_GNUTLS_FN (library, gnutls_anon_free_client_credentials);
LOAD_GNUTLS_FN (library, gnutls_bye);
LOAD_GNUTLS_FN (library, gnutls_certificate_allocate_credentials);
LOAD_GNUTLS_FN (library, gnutls_certificate_free_credentials);
LOAD_GNUTLS_FN (library, gnutls_certificate_get_peers);
LOAD_GNUTLS_FN (library, gnutls_certificate_set_verify_flags);
LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_crl_file);
LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_key_file);
LOAD_GNUTLS_FN (library, gnutls_certificate_set_x509_trust_file);
LOAD_GNUTLS_FN (library, gnutls_certificate_type_get);
LOAD_GNUTLS_FN (library, gnutls_certificate_verify_peers2);
LOAD_GNUTLS_FN (library, gnutls_credentials_set);
LOAD_GNUTLS_FN (library, gnutls_deinit);
LOAD_GNUTLS_FN (library, gnutls_error_is_fatal);
LOAD_GNUTLS_FN (library, gnutls_global_init);
LOAD_GNUTLS_FN (library, gnutls_global_set_log_function);
LOAD_GNUTLS_FN (library, gnutls_global_set_log_level);
LOAD_GNUTLS_FN (library, gnutls_handshake);
LOAD_GNUTLS_FN (library, gnutls_init);
LOAD_GNUTLS_FN (library, gnutls_priority_set_direct);
LOAD_GNUTLS_FN (library, gnutls_record_check_pending);
LOAD_GNUTLS_FN (library, gnutls_record_recv);
LOAD_GNUTLS_FN (library, gnutls_record_send);
LOAD_GNUTLS_FN (library, gnutls_strerror);
LOAD_GNUTLS_FN (library, gnutls_transport_set_errno);
LOAD_GNUTLS_FN (library, gnutls_transport_set_lowat);
LOAD_GNUTLS_FN (library, gnutls_transport_set_ptr2);
LOAD_GNUTLS_FN (library, gnutls_transport_set_pull_function);
LOAD_GNUTLS_FN (library, gnutls_transport_set_push_function);
LOAD_GNUTLS_FN (library, gnutls_x509_crt_check_hostname);
LOAD_GNUTLS_FN (library, gnutls_x509_crt_deinit);
LOAD_GNUTLS_FN (library, gnutls_x509_crt_import);
LOAD_GNUTLS_FN (library, gnutls_x509_crt_init);
GNUTLS_LOG2 (1, 1, "GnuTLS library loaded:",
SDATA (Fget (Qgnutls_dll, QCloaded_from)));
return 1;
}
#else /* !WINDOWSNT */
#define fn_gnutls_alert_get gnutls_alert_get
#define fn_gnutls_alert_get_name gnutls_alert_get_name
#define fn_gnutls_alert_send_appropriate gnutls_alert_send_appropriate
#define fn_gnutls_anon_allocate_client_credentials gnutls_anon_allocate_client_credentials
#define fn_gnutls_anon_free_client_credentials gnutls_anon_free_client_credentials
#define fn_gnutls_bye gnutls_bye
#define fn_gnutls_certificate_allocate_credentials gnutls_certificate_allocate_credentials
#define fn_gnutls_certificate_free_credentials gnutls_certificate_free_credentials
#define fn_gnutls_certificate_get_peers gnutls_certificate_get_peers
#define fn_gnutls_certificate_set_verify_flags gnutls_certificate_set_verify_flags
#define fn_gnutls_certificate_set_x509_crl_file gnutls_certificate_set_x509_crl_file
#define fn_gnutls_certificate_set_x509_trust_file gnutls_certificate_set_x509_trust_file
#define fn_gnutls_certificate_type_get gnutls_certificate_type_get
#define fn_gnutls_certificate_verify_peers2 gnutls_certificate_verify_peers2
#define fn_gnutls_credentials_set gnutls_credentials_set
#define fn_gnutls_deinit gnutls_deinit
#define fn_gnutls_error_is_fatal gnutls_error_is_fatal
#define fn_gnutls_global_init gnutls_global_init
#define fn_gnutls_global_set_log_function gnutls_global_set_log_function
#define fn_gnutls_global_set_log_level gnutls_global_set_log_level
#define fn_gnutls_handshake gnutls_handshake
#define fn_gnutls_init gnutls_init
#define fn_gnutls_priority_set_direct gnutls_priority_set_direct
#define fn_gnutls_record_check_pending gnutls_record_check_pending
#define fn_gnutls_record_recv gnutls_record_recv
#define fn_gnutls_record_send gnutls_record_send
#define fn_gnutls_strerror gnutls_strerror
#define fn_gnutls_transport_set_errno gnutls_transport_set_errno
#define fn_gnutls_transport_set_lowat gnutls_transport_set_lowat
#define fn_gnutls_transport_set_ptr2 gnutls_transport_set_ptr2
#define fn_gnutls_transport_set_pull_function gnutls_transport_set_pull_function
#define fn_gnutls_transport_set_push_function gnutls_transport_set_push_function
#define fn_gnutls_x509_crt_check_hostname gnutls_x509_crt_check_hostname
#define fn_gnutls_x509_crt_deinit gnutls_x509_crt_deinit
#define fn_gnutls_x509_crt_import gnutls_x509_crt_import
#define fn_gnutls_x509_crt_init gnutls_x509_crt_init
#endif /* !WINDOWSNT */
static void
gnutls_log_function (int level, const char* string)
{
@ -83,11 +259,11 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
/* On W32 we cannot transfer socket handles between different runtime
libraries, so we tell GnuTLS to use our special push/pull
functions. */
gnutls_transport_set_ptr2 (state,
(gnutls_transport_ptr_t) proc,
(gnutls_transport_ptr_t) proc);
gnutls_transport_set_push_function (state, &emacs_gnutls_push);
gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
fn_gnutls_transport_set_ptr2 (state,
(gnutls_transport_ptr_t) proc,
(gnutls_transport_ptr_t) proc);
fn_gnutls_transport_set_push_function (state, &emacs_gnutls_push);
fn_gnutls_transport_set_pull_function (state, &emacs_gnutls_pull);
/* For non blocking sockets or other custom made pull/push
functions the gnutls_transport_set_lowat must be called, with
@ -96,14 +272,14 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
(Note: this is probably not strictly necessary as the lowat
value is only used when no custom pull/push functions are
set.) */
gnutls_transport_set_lowat (state, 0);
fn_gnutls_transport_set_lowat (state, 0);
#else
/* This is how GnuTLS takes sockets: as file descriptors passed
in. For an Emacs process socket, infd and outfd are the
same but we use this two-argument version for clarity. */
gnutls_transport_set_ptr2 (state,
(gnutls_transport_ptr_t) (long) proc->infd,
(gnutls_transport_ptr_t) (long) proc->outfd);
fn_gnutls_transport_set_ptr2 (state,
(gnutls_transport_ptr_t) (long) proc->infd,
(gnutls_transport_ptr_t) (long) proc->outfd);
#endif
proc->gnutls_initstage = GNUTLS_STAGE_TRANSPORT_POINTERS_SET;
@ -111,10 +287,10 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
do
{
ret = gnutls_handshake (state);
ret = fn_gnutls_handshake (state);
emacs_gnutls_handle_error (state, ret);
}
while (ret < 0 && gnutls_error_is_fatal (ret) == 0);
while (ret < 0 && fn_gnutls_error_is_fatal (ret) == 0);
proc->gnutls_initstage = GNUTLS_STAGE_HANDSHAKE_TRIED;
@ -125,11 +301,23 @@ emacs_gnutls_handshake (struct Lisp_Process *proc)
}
else
{
gnutls_alert_send_appropriate (state, ret);
fn_gnutls_alert_send_appropriate (state, ret);
}
return ret;
}
int
emacs_gnutls_record_check_pending (gnutls_session_t state)
{
return fn_gnutls_record_check_pending (state);
}
void
emacs_gnutls_transport_set_errno (gnutls_session_t state, int err)
{
fn_gnutls_transport_set_errno (state, err);
}
EMACS_INT
emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
EMACS_INT nbyte)
@ -152,7 +340,7 @@ emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
while (nbyte > 0)
{
rtnval = gnutls_write (state, buf, nbyte);
rtnval = fn_gnutls_record_send (state, buf, nbyte);
if (rtnval < 0)
{
@ -183,7 +371,7 @@ emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
emacs_gnutls_handshake (proc);
return -1;
}
rtnval = gnutls_read (state, buf, nbyte);
rtnval = fn_gnutls_record_recv (state, buf, nbyte);
if (rtnval >= 0)
return rtnval;
else if (emacs_gnutls_handle_error (state, rtnval) == 0)
@ -215,11 +403,11 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
/* TODO: use gnutls-error-fatalp and gnutls-error-string. */
str = gnutls_strerror (err);
str = fn_gnutls_strerror (err);
if (!str)
str = "unknown";
if (gnutls_error_is_fatal (err))
if (fn_gnutls_error_is_fatal (err))
{
ret = err;
GNUTLS_LOG2 (0, max_log_level, "fatal error:", str);
@ -234,9 +422,9 @@ emacs_gnutls_handle_error (gnutls_session_t session, int err)
if (err == GNUTLS_E_WARNING_ALERT_RECEIVED
|| err == GNUTLS_E_FATAL_ALERT_RECEIVED)
{
int alert = gnutls_alert_get (session);
int alert = fn_gnutls_alert_get (session);
int level = (err == GNUTLS_E_FATAL_ALERT_RECEIVED) ? 0 : 1;
str = gnutls_alert_get_name (alert);
str = fn_gnutls_alert_get_name (alert);
if (!str)
str = "unknown";
@ -314,7 +502,7 @@ usage: (gnutls-error-fatalp ERROR) */)
if (!NUMBERP (err))
error ("Not an error symbol or code");
if (0 == gnutls_error_is_fatal (XINT (err)))
if (0 == fn_gnutls_error_is_fatal (XINT (err)))
return Qnil;
return Qt;
@ -346,7 +534,7 @@ usage: (gnutls-error-string ERROR) */)
if (!NUMBERP (err))
return build_string ("Not an error symbol or code");
return build_string (gnutls_strerror (XINT (err)));
return build_string (fn_gnutls_strerror (XINT (err)));
}
DEFUN ("gnutls-deinit", Fgnutls_deinit, Sgnutls_deinit, 1, 1, 0,
@ -361,13 +549,34 @@ See also `gnutls-init'. */)
if (GNUTLS_INITSTAGE (proc) >= GNUTLS_STAGE_INIT)
{
gnutls_deinit (state);
fn_gnutls_deinit (state);
GNUTLS_INITSTAGE (proc) = GNUTLS_STAGE_INIT - 1;
}
return Qt;
}
DEFUN ("gnutls-available-p", Fgnutls_available_p, Sgnutls_available_p, 0, 0, 0,
doc: /* Return t if GnuTLS is available in this instance of Emacs. */)
(void)
{
#ifdef WINDOWSNT
Lisp_Object found = Fassq (Qgnutls_dll, Vlibrary_cache);
if (CONSP (found))
return XCDR (found);
else
{
Lisp_Object status;
status = init_gnutls_functions (Vdynamic_library_alist) ? Qt : Qnil;
Vlibrary_cache = Fcons (Fcons (Qgnutls_dll, status), Vlibrary_cache);
return status;
}
#else
return Qt;
#endif
}
/* Initializes global GnuTLS state to defaults.
Call `gnutls-global-deinit' when GnuTLS usage is no longer needed.
Returns zero on success. */
@ -377,8 +586,7 @@ emacs_gnutls_global_init (void)
int ret = GNUTLS_E_SUCCESS;
if (!gnutls_global_initialized)
ret = gnutls_global_init ();
ret = fn_gnutls_global_init ();
gnutls_global_initialized = 1;
return gnutls_make_error (ret);
@ -488,6 +696,12 @@ one trustfile (usually a CA bundle). */)
CHECK_SYMBOL (type);
CHECK_LIST (proplist);
if (NILP (Fgnutls_available_p ()))
{
error ("GnuTLS not available");
return gnutls_make_error (GNUTLS_EMACS_ERROR_NOT_LOADED);
}
hostname = Fplist_get (proplist, Qgnutls_bootprop_hostname);
priority_string = Fplist_get (proplist, Qgnutls_bootprop_priority);
trustfiles = Fplist_get (proplist, Qgnutls_bootprop_trustfiles);
@ -509,8 +723,8 @@ one trustfile (usually a CA bundle). */)
if (NUMBERP (loglevel))
{
gnutls_global_set_log_function (gnutls_log_function);
gnutls_global_set_log_level (XINT (loglevel));
fn_gnutls_global_set_log_function (gnutls_log_function);
fn_gnutls_global_set_log_level (XINT (loglevel));
max_log_level = XINT (loglevel);
XPROCESS (proc)->gnutls_log_level = max_log_level;
}
@ -529,13 +743,13 @@ one trustfile (usually a CA bundle). */)
{
GNUTLS_LOG (2, max_log_level, "deallocating x509 credentials");
x509_cred = XPROCESS (proc)->gnutls_x509_cred;
gnutls_certificate_free_credentials (x509_cred);
fn_gnutls_certificate_free_credentials (x509_cred);
}
else if (EQ (type, Qgnutls_anon))
{
GNUTLS_LOG (2, max_log_level, "deallocating anon credentials");
anon_cred = XPROCESS (proc)->gnutls_anon_cred;
gnutls_anon_free_client_credentials (anon_cred);
fn_gnutls_anon_free_client_credentials (anon_cred);
}
else
{
@ -558,7 +772,7 @@ one trustfile (usually a CA bundle). */)
{
GNUTLS_LOG (2, max_log_level, "allocating x509 credentials");
x509_cred = XPROCESS (proc)->gnutls_x509_cred;
if (gnutls_certificate_allocate_credentials (&x509_cred) < 0)
if (fn_gnutls_certificate_allocate_credentials (&x509_cred) < 0)
memory_full ();
if (NUMBERP (verify_flags))
@ -576,13 +790,13 @@ one trustfile (usually a CA bundle). */)
/* The default is already GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT. */
GNUTLS_LOG (2, max_log_level, "ignoring invalid verify-flags");
}
gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
fn_gnutls_certificate_set_verify_flags (x509_cred, gnutls_verify_flags);
}
else if (EQ (type, Qgnutls_anon))
{
GNUTLS_LOG (2, max_log_level, "allocating anon credentials");
anon_cred = XPROCESS (proc)->gnutls_anon_cred;
if (gnutls_anon_allocate_client_credentials (&anon_cred) < 0)
if (fn_gnutls_anon_allocate_client_credentials (&anon_cred) < 0)
memory_full ();
}
else
@ -605,7 +819,7 @@ one trustfile (usually a CA bundle). */)
{
GNUTLS_LOG2 (1, max_log_level, "setting the trustfile: ",
SSDATA (trustfile));
ret = gnutls_certificate_set_x509_trust_file
ret = fn_gnutls_certificate_set_x509_trust_file
(x509_cred,
SSDATA (trustfile),
file_format);
@ -627,7 +841,7 @@ one trustfile (usually a CA bundle). */)
{
GNUTLS_LOG2 (1, max_log_level, "setting the CRL file: ",
SSDATA (crlfile));
ret = gnutls_certificate_set_x509_crl_file
ret = fn_gnutls_certificate_set_x509_crl_file
(x509_cred,
SSDATA (crlfile),
file_format);
@ -652,7 +866,7 @@ one trustfile (usually a CA bundle). */)
SSDATA (keyfile));
GNUTLS_LOG2 (1, max_log_level, "setting the client cert file: ",
SSDATA (certfile));
ret = gnutls_certificate_set_x509_key_file
ret = fn_gnutls_certificate_set_x509_key_file
(x509_cred,
SSDATA (certfile),
SSDATA (keyfile),
@ -685,7 +899,7 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG (1, max_log_level, "gnutls_init");
ret = gnutls_init (&state, GNUTLS_CLIENT);
ret = fn_gnutls_init (&state, GNUTLS_CLIENT);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
@ -708,9 +922,9 @@ one trustfile (usually a CA bundle). */)
GNUTLS_LOG (1, max_log_level, "setting the priority string");
ret = gnutls_priority_set_direct (state,
priority_string_ptr,
NULL);
ret = fn_gnutls_priority_set_direct (state,
priority_string_ptr,
NULL);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
@ -719,11 +933,11 @@ one trustfile (usually a CA bundle). */)
if (EQ (type, Qgnutls_x509pki))
{
ret = gnutls_cred_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred);
ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_CERTIFICATE, x509_cred);
}
else if (EQ (type, Qgnutls_anon))
{
ret = gnutls_cred_set (state, GNUTLS_CRD_ANON, anon_cred);
ret = fn_gnutls_credentials_set (state, GNUTLS_CRD_ANON, anon_cred);
}
else
{
@ -751,7 +965,7 @@ one trustfile (usually a CA bundle). */)
check of the certificate's hostname with
gnutls_x509_crt_check_hostname() against :hostname. */
ret = gnutls_certificate_verify_peers2 (state, &peer_verification);
ret = fn_gnutls_certificate_verify_peers2 (state, &peer_verification);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
@ -802,15 +1016,15 @@ one trustfile (usually a CA bundle). */)
/* Up to here the process is the same for X.509 certificates and
OpenPGP keys. From now on X.509 certificates are assumed. This
can be easily extended to work with openpgp keys as well. */
if (gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
if (fn_gnutls_certificate_type_get (state) == GNUTLS_CRT_X509)
{
ret = gnutls_x509_crt_init (&gnutls_verify_cert);
ret = fn_gnutls_x509_crt_init (&gnutls_verify_cert);
if (ret < GNUTLS_E_SUCCESS)
return gnutls_make_error (ret);
gnutls_verify_cert_list =
gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
fn_gnutls_certificate_get_peers (state, &gnutls_verify_cert_list_size);
if (NULL == gnutls_verify_cert_list)
{
@ -818,17 +1032,17 @@ one trustfile (usually a CA bundle). */)
}
/* We only check the first certificate in the given chain. */
ret = gnutls_x509_crt_import (gnutls_verify_cert,
&gnutls_verify_cert_list[0],
GNUTLS_X509_FMT_DER);
ret = fn_gnutls_x509_crt_import (gnutls_verify_cert,
&gnutls_verify_cert_list[0],
GNUTLS_X509_FMT_DER);
if (ret < GNUTLS_E_SUCCESS)
{
gnutls_x509_crt_deinit (gnutls_verify_cert);
fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
return gnutls_make_error (ret);
}
if (!gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
if (!fn_gnutls_x509_crt_check_hostname (gnutls_verify_cert, c_hostname))
{
if (NILP (verify_hostname_error))
{
@ -837,13 +1051,13 @@ one trustfile (usually a CA bundle). */)
}
else
{
gnutls_x509_crt_deinit (gnutls_verify_cert);
fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
error ("The x509 certificate does not match \"%s\"",
c_hostname);
}
}
gnutls_x509_crt_deinit (gnutls_verify_cert);
fn_gnutls_x509_crt_deinit (gnutls_verify_cert);
}
return gnutls_make_error (ret);
@ -872,8 +1086,8 @@ This function may also return `gnutls-e-again', or
state = XPROCESS (proc)->gnutls_state;
ret = gnutls_bye (state,
NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
ret = fn_gnutls_bye (state,
NILP (cont) ? GNUTLS_SHUT_RDWR : GNUTLS_SHUT_WR);
return gnutls_make_error (ret);
}
@ -883,6 +1097,9 @@ syms_of_gnutls (void)
{
gnutls_global_initialized = 0;
Qgnutls_dll = intern_c_string ("gnutls");
staticpro (&Qgnutls_dll);
Qgnutls_log_level = intern_c_string ("gnutls-log-level");
staticpro (&Qgnutls_log_level);
@ -956,6 +1173,7 @@ syms_of_gnutls (void)
defsubr (&Sgnutls_boot);
defsubr (&Sgnutls_deinit);
defsubr (&Sgnutls_bye);
defsubr (&Sgnutls_available_p);
}
#endif /* HAVE_GNUTLS */

View File

@ -42,6 +42,7 @@ typedef enum
GNUTLS_STAGE_READY,
} gnutls_initstage_t;
#define GNUTLS_EMACS_ERROR_NOT_LOADED GNUTLS_E_APPLICATION_ERROR_MIN + 1
#define GNUTLS_EMACS_ERROR_INVALID_TYPE GNUTLS_E_APPLICATION_ERROR_MIN
#define GNUTLS_INITSTAGE(proc) (XPROCESS (proc)->gnutls_initstage)
@ -52,13 +53,16 @@ typedef enum
#define GNUTLS_LOG2(level, max, string, extra) if (level <= max) { gnutls_log_function2 (level, "(Emacs) " string, extra); }
EMACS_INT
extern EMACS_INT
emacs_gnutls_write (int fildes, struct Lisp_Process *proc, const char *buf,
EMACS_INT nbyte);
EMACS_INT
extern EMACS_INT
emacs_gnutls_read (int fildes, struct Lisp_Process *proc, char *buf,
EMACS_INT nbyte);
extern int emacs_gnutls_record_check_pending (gnutls_session_t state);
extern void emacs_gnutls_transport_set_errno (gnutls_session_t state, int err);
extern void syms_of_gnutls (void);
#endif

View File

@ -67,6 +67,7 @@ typedef struct x_bitmap_record Bitmap_Record;
#ifdef HAVE_NTGUI
#include "w32.h"
#include "w32term.h"
/* W32_TODO : Color tables on W32. */
@ -556,10 +557,6 @@ x_create_bitmap_mask (struct frame *f, int id)
static struct image_type *image_types;
/* Cache for delayed-loading image types. */
static Lisp_Object Vimage_type_cache;
/* The symbol `xbm' which is used as the type symbol for XBM images. */
static Lisp_Object Qxbm;
@ -589,7 +586,7 @@ static int x_build_heuristic_mask (struct frame *, struct image *,
Lisp_Object);
#define CACHE_IMAGE_TYPE(type, status) \
do { Vimage_type_cache = Fcons (Fcons (type, status), Vimage_type_cache); } while (0)
do { Vlibrary_cache = Fcons (Fcons (type, status), Vlibrary_cache); } while (0)
#define ADD_IMAGE_TYPE(type) \
do { Vimage_types = Fcons (type, Vimage_types); } while (0)
@ -1900,34 +1897,6 @@ mark_image_cache (struct image_cache *c)
if (!fn_##func) return 0; \
}
/* Load a DLL implementing an image type.
The argument LIBRARIES is usually the variable
`dynamic-library-alist', which associates a symbol, identifying
an external DLL library, to a list of possible filenames.
The function returns NULL if no library could be loaded for
the given symbol, or if the library was previously loaded;
else the handle of the DLL. */
static HMODULE
w32_delayed_load (Lisp_Object libraries, Lisp_Object type)
{
HMODULE library = NULL;
if (CONSP (libraries) && NILP (Fassq (type, Vimage_type_cache)))
{
Lisp_Object dlls = Fassq (type, libraries);
if (CONSP (dlls))
for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
{
CHECK_STRING_CAR (dlls);
if (library = LoadLibrary (SDATA (XCAR (dlls))))
break;
}
}
return library;
}
#endif /* HAVE_NTGUI */
static int x_create_x_image_and_pixmap (struct frame *, int, int, int,
@ -5452,7 +5421,6 @@ init_png_functions (Lisp_Object libraries)
{
HMODULE library;
/* Try loading libpng under probable names. */
if (!(library = w32_delayed_load (libraries, Qpng)))
return 0;
@ -8634,7 +8602,7 @@ of `dynamic-library-alist', which see). */)
Lisp_Object tested;
/* Don't try to reload the library. */
tested = Fassq (type, Vimage_type_cache);
tested = Fassq (type, Vlibrary_cache);
if (CONSP (tested))
return XCDR (tested);
@ -8714,9 +8682,6 @@ as a ratio to the frame height and width. If the value is
non-numeric, there is no explicit limit on the size of images. */);
Vmax_image_size = make_float (MAX_IMAGE_SIZE);
Vimage_type_cache = Qnil;
staticpro (&Vimage_type_cache);
Qpbm = intern_c_string ("pbm");
staticpro (&Qpbm);
ADD_IMAGE_TYPE (Qpbm);

View File

@ -33,6 +33,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#include <unistd.h>
#include <fcntl.h>
#include "lisp.h"
/* Only MS-DOS does not define `subprocesses'. */
#ifdef subprocesses
@ -77,7 +79,6 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
#endif /* subprocesses */
#include "lisp.h"
#include "systime.h"
#include "systty.h"
@ -4537,10 +4538,10 @@ wait_reading_process_output (int time_limit, int microsecs, int read_kbd,
some data in the TCP buffers so that select works, but
with custom pull/push functions we need to check if some
data is available in the buffers manually. */
if (nfds == 0 &&
if (nfds == 0 &&
wait_proc && wait_proc->gnutls_p /* Check for valid process. */
/* Do we have pending data? */
&& gnutls_record_check_pending (wait_proc->gnutls_state) > 0)
&& emacs_gnutls_record_check_pending (wait_proc->gnutls_state) > 0)
{
nfds = 1;
/* Set to Available. */

View File

@ -150,6 +150,8 @@ typedef struct _PROCESS_MEMORY_COUNTERS_EX {
typedef HRESULT (WINAPI * ShGetFolderPath_fn)
(IN HWND, IN int, IN HANDLE, IN DWORD, OUT char *);
Lisp_Object QCloaded_from;
void globals_of_w32 (void);
static DWORD get_rid (PSID);
@ -5712,6 +5714,54 @@ sys_localtime (const time_t *t)
return localtime (t);
}
/* Delayed loading of libraries. */
Lisp_Object Vlibrary_cache;
/* The argument LIBRARIES is an alist that associates a symbol
LIBRARY_ID, identifying an external DLL library known to Emacs, to
a list of filenames under which the library is usually found. In
most cases, the argument passed as LIBRARIES is the variable
`dynamic-library-alist', which is initialized to a list of common
library names. If the function loads the library successfully, it
returns the handle of the DLL, and records the filename in the
property :loaded-from of LIBRARY_ID; it returns NULL if the library
could not be found, or when it was already loaded (because the
handle is not recorded anywhere, and so is lost after use). It
would be trivial to save the handle too in :loaded-from, but
currently there's no use case for it. */
HMODULE
w32_delayed_load (Lisp_Object libraries, Lisp_Object library_id)
{
HMODULE library_dll = NULL;
CHECK_SYMBOL (library_id);
if (CONSP (libraries) && NILP (Fassq (library_id, Vlibrary_cache)))
{
Lisp_Object found = Qnil;
Lisp_Object dlls = Fassq (library_id, libraries);
if (CONSP (dlls))
for (dlls = XCDR (dlls); CONSP (dlls); dlls = XCDR (dlls))
{
CHECK_STRING_CAR (dlls);
if (library_dll = LoadLibrary (SDATA (XCAR (dlls))))
{
found = XCAR (dlls);
break;
}
}
Fput (library_id, QCloaded_from, found);
}
return library_dll;
}
static void
check_windows_init_file (void)
{
@ -5910,6 +5960,12 @@ globals_of_w32 (void)
get_process_times_fn = (GetProcessTimes_Proc)
GetProcAddress (kernel32, "GetProcessTimes");
QCloaded_from = intern_c_string (":loaded-from");
staticpro (&QCloaded_from);
Vlibrary_cache = Qnil;
staticpro (&Vlibrary_cache);
g_b_init_is_windows_9x = 0;
g_b_init_open_process_token = 0;
g_b_init_get_token_information = 0;
@ -6178,7 +6234,7 @@ emacs_gnutls_pull (gnutls_transport_ptr_t p, void* buf, size_t sz)
err = errno; /* Other errors are just passed on. */
}
gnutls_transport_set_errno (process->gnutls_state, err);
emacs_gnutls_transport_set_errno (process->gnutls_state, err);
return -1;
}
@ -6197,8 +6253,8 @@ emacs_gnutls_push (gnutls_transport_ptr_t p, const void* buf, size_t sz)
/* Negative bytes written means we got an error in errno.
Translate the WSAEWOULDBLOCK alias EWOULDBLOCK to EAGAIN. */
gnutls_transport_set_errno (process->gnutls_state,
errno == EWOULDBLOCK ? EAGAIN : errno);
emacs_gnutls_transport_set_errno (process->gnutls_state,
errno == EWOULDBLOCK ? EAGAIN : errno);
return -1;
}

View File

@ -143,6 +143,9 @@ extern void syms_of_fontset (void);
extern int _sys_read_ahead (int fd);
extern int _sys_wait_accept (int fd);
extern Lisp_Object Vlibrary_cache, QCloaded_from;
extern HMODULE w32_delayed_load (Lisp_Object, Lisp_Object);
#ifdef HAVE_GNUTLS
#include <gnutls/gnutls.h>