LCOV - code coverage report
Current view: top level - src - init.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 20 76 26.3 %
Date: 2017-03-02 16:37:58 Functions: 5 13 38.5 %

          Line data    Source code
       1             : /* init.c - Initialize the GnuPG error library.
       2             :    Copyright (C) 2005, 2010 g10 Code GmbH
       3             : 
       4             :    This file is part of libgpg-error.
       5             : 
       6             :    libgpg-error is free software; you can redistribute it and/or
       7             :    modify it under the terms of the GNU Lesser General Public License
       8             :    as published by the Free Software Foundation; either version 2.1 of
       9             :    the License, or (at your option) any later version.
      10             : 
      11             :    libgpg-error is distributed in the hope that it will be useful, but
      12             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :    Lesser General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU Lesser General Public
      17             :    License along with this program; if not, see <https://www.gnu.org/licenses/>.
      18             :  */
      19             : 
      20             : #if HAVE_CONFIG_H
      21             : #include <config.h>
      22             : #endif
      23             : 
      24             : #include <stdlib.h>
      25             : #include <stdio.h>
      26             : #include <string.h>
      27             : #include <errno.h>
      28             : 
      29             : #include "gpgrt-int.h"
      30             : #include "gettext.h"
      31             : #include "init.h"
      32             : 
      33             : #ifdef HAVE_W32CE_SYSTEM
      34             : # include "mkw32errmap.map.c"  /* Generated map_w32codes () */
      35             : # ifndef TLS_OUT_OF_INDEXES
      36             : #  define TLS_OUT_OF_INDEXES 0xFFFFFFFF
      37             : # endif
      38             : # ifndef __MINGW32CE__
      39             : #  /* Replace the Mingw32CE provided abort function.  */
      40             : #  define abort() do { TerminateProcess (GetCurrentProcess(), 8); } while (0)
      41             : # endif
      42             : #endif
      43             : 
      44             : 
      45             : /* Locale directory support.  */
      46             : 
      47             : #if HAVE_W32_SYSTEM
      48             : 
      49             : #include <windows.h>
      50             : 
      51             : static int tls_index = TLS_OUT_OF_INDEXES;  /* Index for the TLS functions.  */
      52             : 
      53             : static char *get_locale_dir (void);
      54             : static void drop_locale_dir (char *locale_dir);
      55             : 
      56             : #else /*!HAVE_W32_SYSTEM*/
      57             : 
      58             : #define get_locale_dir() LOCALEDIR
      59             : #define drop_locale_dir(dir)
      60             : 
      61             : #endif /*!HAVE_W32_SYSTEM*/
      62             : 
      63             : 
      64             : /* The realloc function as set by gpgrt_set_alloc_func.  */
      65             : static void *(*custom_realloc)(void *a, size_t n);
      66             : 
      67             : 
      68             : 
      69             : static void
      70             : real_init (void)
      71             : {
      72             : #ifdef ENABLE_NLS
      73             :   char *locale_dir;
      74             : 
      75             :   /* We only have to bind our locale directory to our text domain.  */
      76             :   locale_dir = get_locale_dir ();
      77             :   if (locale_dir)
      78             :     {
      79           7 :       bindtextdomain (PACKAGE, locale_dir);
      80             :       drop_locale_dir (locale_dir);
      81             :     }
      82             : #endif
      83           7 :   _gpgrt_estream_init ();
      84             : }
      85             : 
      86             : /* Initialize the library.  This function should be run early.  */
      87             : gpg_error_t
      88           7 : _gpg_err_init (void)
      89             : {
      90             : #ifdef HAVE_W32_SYSTEM
      91             : # ifdef DLL_EXPORT
      92             :   /* We always have a constructor and thus this function is called
      93             :      automatically.  Due to the way the C init code of mingw works,
      94             :      the constructors are called before our DllMain function is
      95             :      called.  The problem with that is that the TLS has not been setup
      96             :      and w32-gettext.c requires TLS.  To solve this we do nothing here
      97             :      but call the actual init code from our DllMain.  */
      98             : # else /*!DLL_EXPORT*/
      99             :   /* Note that if the TLS is actually used, we can't release the TLS
     100             :      as there is no way to know when a thread terminates (i.e. no
     101             :      thread-specific-atexit).  You are really better off to use the
     102             :      DLL! */
     103             :   if (tls_index == TLS_OUT_OF_INDEXES)
     104             :     {
     105             :       tls_index = TlsAlloc ();
     106             :       if (tls_index == TLS_OUT_OF_INDEXES)
     107             :         {
     108             :           /* No way to continue - commit suicide.  */
     109             :           abort ();
     110             :         }
     111             :       _gpg_w32__init_gettext_module ();
     112             :       real_init ();
     113             :     }
     114             : # endif /*!DLL_EXPORT*/
     115             : #else
     116             :   real_init ();
     117             : #endif
     118           7 :   return 0;
     119             : }
     120             : 
     121             : 
     122             : /* Deinitialize libgpg-error.  This function is only used in special
     123             :    circumstances.  No gpg-error function should be used after this
     124             :    function has been called.  A value of 0 passed for MODE
     125             :    deinitializes the entire libgpg-error, a value of 1 releases
     126             :    resources allocated for the current thread and only that thread may
     127             :    not anymore access libgpg-error after such a call.  Under Windows
     128             :    this function may be called from the DllMain function of a DLL
     129             :    which statically links to libgpg-error.  */
     130             : void
     131           0 : _gpg_err_deinit (int mode)
     132             : {
     133             : #if defined (HAVE_W32_SYSTEM) && !defined(DLL_EXPORT)
     134             :   struct tls_space_s *tls;
     135             : 
     136             :   tls = TlsGetValue (tls_index);
     137             :   if (tls)
     138             :     {
     139             :       TlsSetValue (tls_index, NULL);
     140             :       LocalFree (tls);
     141             :     }
     142             : 
     143             :   if (mode == 0)
     144             :     {
     145             :       TlsFree (tls_index);
     146             :       tls_index = TLS_OUT_OF_INDEXES;
     147             :     }
     148             : #else
     149             :   (void)mode;
     150             : #endif
     151           0 : }
     152             : 
     153             : 
     154             : 
     155             : 
     156             : /* Register F as allocation function.  This function is used for all
     157             :    APIs which return an allocated buffer.  F needs to have standard
     158             :    realloc semantics.  It should be called as early as possible and
     159             :    not changed later. */
     160             : void
     161           0 : _gpgrt_set_alloc_func (void *(*f)(void *a, size_t n))
     162             : {
     163           0 :   custom_realloc = f;
     164           0 : }
     165             : 
     166             : 
     167             : /* The realloc to be used for data returned by the public API.  */
     168             : void *
     169         501 : _gpgrt_realloc (void *a, size_t n)
     170             : {
     171         501 :   if (custom_realloc)
     172           0 :     return custom_realloc (a, n);
     173             : 
     174         501 :   if (!n)
     175             :     {
     176         171 :       free (a);
     177         171 :       return NULL;
     178             :     }
     179             : 
     180         330 :   if (!a)
     181         330 :     return malloc (n);
     182             : 
     183           0 :   return realloc (a, n);
     184             : }
     185             : 
     186             : 
     187             : /* The malloc to be used for data returned by the public API.  */
     188             : void *
     189          24 : _gpgrt_malloc (size_t n)
     190             : {
     191          24 :   if (!n)
     192           0 :     n++;
     193          24 :   return _gpgrt_realloc (NULL, n);
     194             : }
     195             : 
     196             : 
     197             : /* The free to be used for data returned by the public API.  */
     198             : void
     199         171 : _gpgrt_free (void *a)
     200             : {
     201         171 :   _gpgrt_realloc (a, 0);
     202         171 : }
     203             : 
     204             : 
     205             : void
     206           1 : _gpg_err_set_errno (int err)
     207             : {
     208             : #ifdef HAVE_W32CE_SYSTEM
     209             :   SetLastError (err);
     210             : #else /*!HAVE_W32CE_SYSTEM*/
     211           1 :   errno = err;
     212             : #endif /*!HAVE_W32CE_SYSTEM*/
     213           1 : }
     214             : 
     215             : 
     216             : 
     217             : /* Internal tracing functions.  Except for TARCE_FP we use flockfile
     218             :  * and funlockfile to protect their use. */
     219             : static FILE *trace_fp;
     220             : static int trace_save_errno;
     221             : static int trace_with_errno;
     222             : static const char *trace_arg_module;
     223             : static const char *trace_arg_file;
     224             : static int trace_arg_line;
     225             : static int trace_missing_lf;
     226             : static int trace_prefix_done;
     227             : 
     228             : void
     229           0 : _gpgrt_internal_trace_begin (const char *module, const char *file, int line,
     230             :                              int with_errno)
     231             : {
     232           0 :   int save_errno = errno;
     233             : 
     234           0 :   if (!trace_fp)
     235             :     {
     236             :       FILE *fp;
     237           0 :       const char *s = getenv ("GPGRT_TRACE_FILE");
     238             : 
     239           0 :       if (!s || !(fp = fopen (s, "wb")))
     240           0 :         fp = stderr;
     241           0 :       trace_fp = fp;
     242             :     }
     243             : 
     244             : #ifdef HAVE_FLOCKFILE
     245           0 :   flockfile (trace_fp);
     246             : #endif
     247           0 :   trace_save_errno = save_errno;
     248           0 :   trace_with_errno = with_errno;
     249           0 :   trace_arg_module = module;
     250           0 :   trace_arg_file = file;
     251           0 :   trace_arg_line = line;
     252           0 :   trace_missing_lf = 0;
     253           0 :   trace_prefix_done = 0;
     254           0 : }
     255             : 
     256             : static void
     257           0 : print_internal_trace_prefix (void)
     258             : {
     259           0 :   if (!trace_prefix_done)
     260             :     {
     261           0 :       trace_prefix_done = 1;
     262           0 :       fprintf (trace_fp, "%s:%s:%d: ",
     263             :                trace_arg_module,/* npth_is_protected ()?"":"^",*/
     264             :                trace_arg_file, trace_arg_line);
     265             :     }
     266           0 : }
     267             : 
     268             : static void
     269           0 : do_internal_trace (const char *format, va_list arg_ptr)
     270             : {
     271           0 :   print_internal_trace_prefix ();
     272           0 :   vfprintf (trace_fp, format, arg_ptr);
     273           0 :   if (trace_with_errno)
     274           0 :     fprintf (trace_fp, " errno=%s", strerror (trace_save_errno));
     275           0 :   if (*format && format[strlen(format)-1] != '\n')
     276           0 :     fputc ('\n', trace_fp);
     277           0 : }
     278             : 
     279             : void
     280           0 : _gpgrt_internal_trace_printf (const char *format, ...)
     281             : {
     282             :   va_list arg_ptr;
     283             : 
     284           0 :   print_internal_trace_prefix ();
     285           0 :   va_start (arg_ptr, format) ;
     286           0 :   vfprintf (trace_fp, format, arg_ptr);
     287           0 :   va_end (arg_ptr);
     288           0 :   trace_missing_lf = (*format && format[strlen(format)-1] != '\n');
     289           0 : }
     290             : 
     291             : 
     292             : void
     293           0 : _gpgrt_internal_trace (const char *format, ...)
     294             : {
     295             :   va_list arg_ptr;
     296             : 
     297           0 :   va_start (arg_ptr, format) ;
     298           0 :   do_internal_trace (format, arg_ptr);
     299           0 :   va_end (arg_ptr);
     300           0 : }
     301             : 
     302             : 
     303             : void
     304           0 : _gpgrt_internal_trace_end (void)
     305             : {
     306           0 :   int save_errno = trace_save_errno;
     307             : 
     308           0 :   if (trace_missing_lf)
     309           0 :     fputc ('\n', trace_fp);
     310             : #ifdef HAVE_FLOCKFILE
     311           0 :   funlockfile (trace_fp);
     312             : #endif
     313           0 :   errno = save_errno;
     314           0 : }
     315             : 
     316             : 
     317             : 
     318             : #ifdef HAVE_W32_SYSTEM
     319             : /*****************************************
     320             :  ******** Below is only Windows code. ****
     321             :  *****************************************/
     322             : 
     323             : static char *
     324             : get_locale_dir (void)
     325             : {
     326             :   static wchar_t moddir[MAX_PATH+5];
     327             :   char *result, *p;
     328             :   int nbytes;
     329             : 
     330             :   if (!GetModuleFileNameW (NULL, moddir, MAX_PATH))
     331             :     *moddir = 0;
     332             : 
     333             : #define SLDIR "\\share\\locale"
     334             :   if (*moddir)
     335             :     {
     336             :       nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1, NULL, 0, NULL, NULL);
     337             :       if (nbytes < 0)
     338             :         return NULL;
     339             : 
     340             :       result = malloc (nbytes + strlen (SLDIR) + 1);
     341             :       if (result)
     342             :         {
     343             :           nbytes = WideCharToMultiByte (CP_UTF8, 0, moddir, -1,
     344             :                                         result, nbytes, NULL, NULL);
     345             :           if (nbytes < 0)
     346             :             {
     347             :               free (result);
     348             :               result = NULL;
     349             :             }
     350             :           else
     351             :             {
     352             :               p = strrchr (result, '\\');
     353             :               if (p)
     354             :                 *p = 0;
     355             :               /* If we are installed below "bin" strip that part and
     356             :                  use the top directory instead.
     357             : 
     358             :                  Background: Under Windows we don't install GnuPG
     359             :                  below bin/ but in the top directory with only share/,
     360             :                  lib/, and etc/ below it.  One of the reasons is to
     361             :                  keep the the length of the filenames at bay so not to
     362             :                  increase the limited length of the PATH envvar.
     363             :                  Another and more important reason, however, is that
     364             :                  the very first GPG versions on W32 were installed
     365             :                  into a flat directory structure and for best
     366             :                  compatibility with these versions we didn't changed
     367             :                  that later.  For WindowsCE we can right away install
     368             :                  it under bin, though.  The hack with detection of the
     369             :                  bin directory part allows us to eventually migrate to
     370             :                  such a directory layout under plain Windows without
     371             :                  the need to change libgpg-error.  */
     372             :               p = strrchr (result, '\\');
     373             :               if (p && !strcmp (p+1, "bin"))
     374             :                 *p = 0;
     375             :               /* Append the static part.  */
     376             :               strcat (result, SLDIR);
     377             :             }
     378             :         }
     379             :     }
     380             :   else /* Use the old default value.  */
     381             :     {
     382             :       result = malloc (10 + strlen (SLDIR) + 1);
     383             :       if (result)
     384             :         {
     385             :           strcpy (result, "c:\\gnupg");
     386             :           strcat (result, SLDIR);
     387             :         }
     388             :     }
     389             : #undef SLDIR
     390             :   return result;
     391             : }
     392             : 
     393             : 
     394             : static void
     395             : drop_locale_dir (char *locale_dir)
     396             : {
     397             :   free (locale_dir);
     398             : }
     399             : 
     400             : 
     401             : /* Return the tls object.  This function is guaranteed to return a
     402             :    valid non-NULL object.  */
     403             : struct tls_space_s *
     404             : get_tls (void)
     405             : {
     406             :   struct tls_space_s *tls;
     407             : 
     408             :   tls = TlsGetValue (tls_index);
     409             :   if (!tls)
     410             :     {
     411             :       /* Called by a thread which existed before this DLL was loaded.
     412             :          Allocate the space.  */
     413             :       tls = LocalAlloc (LPTR, sizeof *tls);
     414             :       if (!tls)
     415             :         {
     416             :           /* No way to continue - commit suicide.  */
     417             :           abort ();
     418             :         }
     419             :       tls->gt_use_utf8 = 0;
     420             :       TlsSetValue (tls_index, tls);
     421             :     }
     422             : 
     423             :   return tls;
     424             : }
     425             : 
     426             : 
     427             : /* Return the value of the ERRNO variable.  This needs to be a
     428             :    function so that we can have a per-thread ERRNO.  This is used only
     429             :    on WindowsCE because that OS misses an errno.   */
     430             : #ifdef HAVE_W32CE_SYSTEM
     431             : int
     432             : _gpg_w32ce_get_errno (void)
     433             : {
     434             :   return map_w32codes ( GetLastError () );
     435             : }
     436             : #endif /*HAVE_W32CE_SYSTEM*/
     437             : 
     438             : 
     439             : /* Replacement strerror function for WindowsCE.  */
     440             : #ifdef HAVE_W32CE_SYSTEM
     441             : char *
     442             : _gpg_w32ce_strerror (int err)
     443             : {
     444             :   struct tls_space_s *tls = get_tls ();
     445             :   wchar_t tmpbuf[STRBUFFER_SIZE];
     446             :   int n;
     447             : 
     448             :   if (err == -1)
     449             :     err = _gpg_w32ce_get_errno ();
     450             : 
     451             :   /* Note: On a German HTC Touch Pro2 device I also tried
     452             :      LOCALE_USER_DEFAULT and LOCALE_SYSTEM_DEFAULT - both returned
     453             :      English messages.  */
     454             :   if (FormatMessageW (FORMAT_MESSAGE_FROM_SYSTEM, NULL, err,
     455             :                       MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),
     456             :                       tmpbuf, STRBUFFER_SIZE -1,
     457             :                       NULL))
     458             :     {
     459             :       n = WideCharToMultiByte (CP_UTF8, 0, tmpbuf, -1,
     460             :                                tls->strerror_buffer,
     461             :                                sizeof tls->strerror_buffer -1,
     462             :                                NULL, NULL);
     463             :     }
     464             :   else
     465             :     n = -1;
     466             : 
     467             :   if (n < 0)
     468             :     snprintf (tls->strerror_buffer, sizeof tls->strerror_buffer -1,
     469             :               "[w32err=%d]", err);
     470             :   return tls->strerror_buffer;
     471             : }
     472             : #endif /*HAVE_W32CE_SYSTEM*/
     473             : 
     474             : 
     475             : /* Entry point called by the DLL loader.  */
     476             : #ifdef DLL_EXPORT
     477             : int WINAPI
     478             : DllMain (HINSTANCE hinst, DWORD reason, LPVOID reserved)
     479             : {
     480             :   struct tls_space_s *tls;
     481             :   (void)reserved;
     482             :   (void)hinst;
     483             : 
     484             :   switch (reason)
     485             :     {
     486             :     case DLL_PROCESS_ATTACH:
     487             :       tls_index = TlsAlloc ();
     488             :       if (tls_index == TLS_OUT_OF_INDEXES)
     489             :         return FALSE;
     490             : #ifndef _GPG_ERR_HAVE_CONSTRUCTOR
     491             :       /* If we have not constructors (e.g. MSC) we call it here.  */
     492             :       _gpg_w32__init_gettext_module ();
     493             : #endif
     494             :       /* falltru.  */
     495             :     case DLL_THREAD_ATTACH:
     496             :       tls = LocalAlloc (LPTR, sizeof *tls);
     497             :       if (!tls)
     498             :         return FALSE;
     499             :       tls->gt_use_utf8 = 0;
     500             :       TlsSetValue (tls_index, tls);
     501             :       if (reason == DLL_PROCESS_ATTACH)
     502             :         {
     503             :           real_init ();
     504             :         }
     505             :       break;
     506             : 
     507             :     case DLL_THREAD_DETACH:
     508             :       tls = TlsGetValue (tls_index);
     509             :       if (tls)
     510             :         LocalFree (tls);
     511             :       break;
     512             : 
     513             :     case DLL_PROCESS_DETACH:
     514             :       tls = TlsGetValue (tls_index);
     515             :       if (tls)
     516             :         LocalFree (tls);
     517             :       TlsFree (tls_index);
     518             :       break;
     519             : 
     520             :     default:
     521             :       break;
     522             :     }
     523             : 
     524             :   return TRUE;
     525             : }
     526             : #endif /*DLL_EXPORT*/
     527             : 
     528             : #endif /*HAVE_W32_SYSTEM*/

Generated by: LCOV version 1.13