LCOV - code coverage report
Current view: top level - common - init.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 34 37 91.9 %
Date: 2016-11-29 15:00:56 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /* init.c - Various initializations
       2             :  *      Copyright (C) 2007 Free Software Foundation, Inc.
       3             :  *
       4             :  * This file is part of GnuPG.
       5             :  *
       6             :  * This file is free software; you can redistribute it and/or modify
       7             :  * it under the terms of either
       8             :  *
       9             :  *   - the GNU Lesser General Public License as published by the Free
      10             :  *     Software Foundation; either version 3 of the License, or (at
      11             :  *     your option) any later version.
      12             :  *
      13             :  * or
      14             :  *
      15             :  *   - the GNU General Public License as published by the Free
      16             :  *     Software Foundation; either version 2 of the License, or (at
      17             :  *     your option) any later version.
      18             :  *
      19             :  * or both in parallel, as here.
      20             :  *
      21             :  * This file is distributed in the hope that it will be useful,
      22             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      23             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      24             :  * GNU General Public License for more details.
      25             :  *
      26             :  * You should have received a copy of the GNU General Public License
      27             :  * along with this program; if not, see <https://www.gnu.org/licenses/>.
      28             :  */
      29             : 
      30             : #include <config.h>
      31             : 
      32             : #ifdef HAVE_W32_SYSTEM
      33             : # ifdef HAVE_WINSOCK2_H
      34             : #  include <winsock2.h>
      35             : # endif
      36             : # include <windows.h>
      37             : #endif
      38             : #ifdef HAVE_W32CE_SYSTEM
      39             : # include <assuan.h> /* For _assuan_w32ce_finish_pipe. */
      40             : #endif
      41             : 
      42             : #include <gcrypt.h>
      43             : #include "util.h"
      44             : #include "i18n.h"
      45             : 
      46             : /* This object is used to register memory cleanup functions.
      47             :    Technically they are not needed but they can avoid frequent
      48             :    questions about un-released memory.  Note that we use the system
      49             :    malloc and not any wrappers.  */
      50             : struct mem_cleanup_item_s;
      51             : typedef struct mem_cleanup_item_s *mem_cleanup_item_t;
      52             : 
      53             : struct mem_cleanup_item_s
      54             : {
      55             :   mem_cleanup_item_t next;
      56             :   void (*func) (void);
      57             : };
      58             : 
      59             : static mem_cleanup_item_t mem_cleanup_list;
      60             : 
      61             : 
      62             : /* The default error source of the application.  This is different
      63             :    from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
      64             :    source file and thus is usable in code shared by applications.
      65             :    Note that we need to initialize it because otherwise some linkers
      66             :    (OS X at least) won't find the symbol when linking the t-*.c
      67             :    files.  */
      68             : gpg_err_source_t default_errsource = 0;
      69             : 
      70             : 
      71             : #ifdef HAVE_W32CE_SYSTEM
      72             : static void parse_std_file_handles (int *argcp, char ***argvp);
      73             : static void
      74             : sleep_on_exit (void)
      75             : {
      76             :   /* The sshd on CE swallows some of the command output.  Sleeping a
      77             :      while usually helps.  */
      78             :   Sleep (400);
      79             : }
      80             : #endif /*HAVE_W32CE_SYSTEM*/
      81             : 
      82             : 
      83             : static void
      84        1768 : run_mem_cleanup (void)
      85             : {
      86             :   mem_cleanup_item_t next;
      87             : 
      88        4599 :   while (mem_cleanup_list)
      89             :     {
      90        1063 :       next = mem_cleanup_list->next;
      91        1063 :       mem_cleanup_list->func ();
      92        1063 :       free (mem_cleanup_list);
      93        1063 :       mem_cleanup_list = next;
      94             :     }
      95        1768 : }
      96             : 
      97             : 
      98             : void
      99        1065 : register_mem_cleanup_func (void (*func)(void))
     100             : {
     101             :   mem_cleanup_item_t item;
     102             : 
     103        1065 :   for (item = mem_cleanup_list; item; item = item->next)
     104           0 :     if (item->func == func)
     105        1065 :       return; /* Function has already been registered.  */
     106             : 
     107        1065 :   item = malloc (sizeof *item);
     108        1065 :   if (item)
     109             :     {
     110        1065 :       item->func = func;
     111        1065 :       item->next = mem_cleanup_list;
     112        1065 :       mem_cleanup_list = item;
     113             :     }
     114             : }
     115             : 
     116             : 
     117             : /* If STRING is not NULL write string to es_stdout or es_stderr.  MODE
     118             :    must be 1 or 2.  If STRING is NULL flush the respective stream.  */
     119             : static int
     120       52855 : writestring_via_estream (int mode, const char *string)
     121             : {
     122       52855 :   if (mode == 1 || mode == 2)
     123             :     {
     124       52855 :       if (string)
     125       52846 :         return es_fputs (string, mode == 1? es_stdout : es_stderr);
     126             :       else
     127           9 :         return es_fflush (mode == 1? es_stdout : es_stderr);
     128             :     }
     129             :   else
     130           0 :     return -1;
     131             : }
     132             : 
     133             : 
     134             : /* This function should be the first called after main.  */
     135             : void
     136        1600 : early_system_init (void)
     137             : {
     138        1600 : }
     139             : 
     140             : 
     141             : /* This function is to be used early at program startup to make sure
     142             :    that some subsystems are initialized.  This is in particular
     143             :    important for W32 to initialize the sockets so that our socket
     144             :    emulation code used directly as well as in libassuan may be used.
     145             :    It should best be called before any I/O is done so that setup
     146             :    required for logging is ready.  ARGCP and ARGVP are the addresses
     147             :    of the parameters given to main.  This function may modify them.
     148             : 
     149             :    This function should be called only via the macro
     150             :    init_common_subsystems.
     151             : 
     152             :    CAUTION: This might be called while running suid(root).  */
     153             : void
     154        1718 : _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
     155             : {
     156             :   /* Store the error source in a global variable. */
     157        1718 :   default_errsource = errsource;
     158             : 
     159        1718 :   atexit (run_mem_cleanup);
     160             : 
     161             :   /* Try to auto set the character set.  */
     162        1718 :   set_native_charset (NULL);
     163             : 
     164             : #ifdef HAVE_W32_SYSTEM
     165             :   /* For W32 we need to initialize the socket layer.  This is because
     166             :      we use recv and send in libassuan as well as at some other
     167             :      places.  */
     168             :   {
     169             :     WSADATA wsadat;
     170             : 
     171             :     WSAStartup (0x202, &wsadat);
     172             :   }
     173             : #endif
     174             : 
     175             : #ifdef HAVE_W32CE_SYSTEM
     176             :   /* Register the sleep exit function before the estream init so that
     177             :      the sleep will be called after the estream registered atexit
     178             :      function which flushes the left open estream streams and in
     179             :      particular es_stdout.  */
     180             :   atexit (sleep_on_exit);
     181             : #endif
     182             : 
     183        1718 :   if (!gcry_check_version (NEED_LIBGCRYPT_VERSION))
     184             :     {
     185           0 :       log_fatal (_("%s is too old (need %s, have %s)\n"), "libgcrypt",
     186             :                  NEED_LIBGCRYPT_VERSION, gcry_check_version (NULL));
     187             :     }
     188             : 
     189             :   /* Initialize the Estream library. */
     190        1718 :   gpgrt_init ();
     191        1718 :   gpgrt_set_alloc_func (gcry_realloc);
     192             : 
     193             :   /* Special hack for Windows CE: We extract some options from arg
     194             :      to setup the standard handles.  */
     195             : #ifdef HAVE_W32CE_SYSTEM
     196             :   parse_std_file_handles (argcp, argvp);
     197             : #else
     198             :   (void)argcp;
     199             :   (void)argvp;
     200             : #endif
     201             : 
     202             :   /* Access the standard estreams as early as possible.  If we don't
     203             :      do this the original stdio streams may have been closed when
     204             :      _es_get_std_stream is first use and in turn it would connect to
     205             :      the bit bucket.  */
     206             :   {
     207             :     int i;
     208        6872 :     for (i=0; i < 3; i++)
     209        5154 :       (void)_gpgrt_get_std_stream (i);
     210             :   }
     211             : 
     212             :   /* --version et al shall use estream as well.  */
     213        1718 :   argparse_register_outfnc (writestring_via_estream);
     214             : 
     215             :   /* Logging shall use the standard socket directory as fallback.  */
     216        1718 :   log_set_socket_dir_cb (gnupg_socketdir);
     217        1718 : }
     218             : 
     219             : 
     220             : 
     221             : /* WindowsCE uses a very strange way of handling the standard streams.
     222             :    There is a function SetStdioPath to associate a standard stream
     223             :    with a file or a device but what we really want is to use pipes as
     224             :    standard streams.  Despite that we implement pipes using a device,
     225             :    we would have some limitations on the number of open pipes due to
     226             :    the 3 character limit of device file name.  Thus we don't take this
     227             :    path.  Another option would be to install a file system driver with
     228             :    support for pipes; this would allow us to get rid of the device
     229             :    name length limitation.  However, with GnuPG we can get away be
     230             :    redefining the standard streams and passing the handles to be used
     231             :    on the command line.  This has also the advantage that it makes
     232             :    creating a process much easier and does not require the
     233             :    SetStdioPath set and restore game.  The caller needs to pass the
     234             :    rendezvous ids using up to three options:
     235             : 
     236             :      -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
     237             : 
     238             :    They are all optional but they must be the first arguments on the
     239             :    command line.  Parsing stops as soon as an invalid option is found.
     240             :    These rendezvous ids are then used to finish the pipe creation.*/
     241             : #ifdef HAVE_W32CE_SYSTEM
     242             : static void
     243             : parse_std_file_handles (int *argcp, char ***argvp)
     244             : {
     245             :   int argc = *argcp;
     246             :   char **argv = *argvp;
     247             :   const char *s;
     248             :   assuan_fd_t fd;
     249             :   int i;
     250             :   int fixup = 0;
     251             : 
     252             :   if (!argc)
     253             :     return;
     254             : 
     255             :   for (argc--, argv++; argc; argc--, argv++)
     256             :     {
     257             :       s = *argv;
     258             :       if (*s == '-' && s[1] == '&' && s[2] == 'S'
     259             :           && (s[3] == '0' || s[3] == '1' || s[3] == '2')
     260             :           && s[4] == '='
     261             :           && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
     262             :         {
     263             :           if (s[5] == 'n')
     264             :             fd = ASSUAN_INVALID_FD;
     265             :           else
     266             :             fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
     267             :           _es_set_std_fd (s[3] - '0', (int)fd);
     268             :           fixup++;
     269             :         }
     270             :       else
     271             :         break;
     272             :     }
     273             : 
     274             :   if (fixup)
     275             :     {
     276             :       argc = *argcp;
     277             :       argc -= fixup;
     278             :       *argcp = argc;
     279             : 
     280             :       argv = *argvp;
     281             :       for (i=1; i < argc; i++)
     282             :         argv[i] = argv[i + fixup];
     283             :       for (; i < argc + fixup; i++)
     284             :         argv[i] = NULL;
     285             :     }
     286             : 
     287             : 
     288             : }
     289             : #endif /*HAVE_W32CE_SYSTEM*/

Generated by: LCOV version 1.11