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

Generated by: LCOV version 1.11