Change license for some files in common to LGPLv3+/GPLv2+.
[gnupg.git] / common / init.c
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 #include <windows.h>
39 #endif
40 #ifdef HAVE_NPTH
41 #include <npth.h>
42 #endif
43 #ifdef HAVE_W32CE_SYSTEM
44 # include <assuan.h> /* For _assuan_w32ce_finish_pipe. */
45 #endif
46
47 #include "util.h"
48
49
50 /* The default error source of the application.  This is different
51    from GPG_ERR_SOURCE_DEFAULT in that it does not depend on the
52    source file and thus is usable in code shared by applications.  */
53 gpg_err_source_t default_errsource;
54
55
56 #ifdef HAVE_W32CE_SYSTEM
57 static void parse_std_file_handles (int *argcp, char ***argvp);
58 static void
59 sleep_on_exit (void)
60 {
61   /* The sshd on CE swallows some of the command output.  Sleeping a
62      while usually helps.  */
63   Sleep (400);
64 }
65 #endif /*HAVE_W32CE_SYSTEM*/
66
67
68 /* If STRING is not NULL write string to es_stdout or es_stderr.  MODE
69    must be 1 or 2.  If STRING is NULL flush the respective stream.  */
70 static int
71 writestring_via_estream (int mode, const char *string)
72 {
73   if (mode == 1 || mode == 2)
74     {
75       if (string)
76         return es_fputs (string, mode == 1? es_stdout : es_stderr);
77       else
78         return es_fflush (mode == 1? es_stdout : es_stderr);
79     }
80   else
81     return -1;
82 }
83
84
85 /* This function is to be used early at program startup to make sure
86    that some subsystems are initialized.  This is in particular
87    important for W32 to initialize the sockets so that our socket
88    emulation code used directly as well as in libassuan may be used.
89    It should best be called before any I/O is done so that setup
90    required for logging is ready.  ARGCP and ARGVP are the addresses
91    of the parameters given to main.  This function may modify them.
92
93    This function should be called only via the macro
94    init_common_subsystems.
95
96    CAUTION: This might be called while running suid(root).  */
97 void
98 _init_common_subsystems (gpg_err_source_t errsource, int *argcp, char ***argvp)
99 {
100   /* Store the error source in a gloabl variable. */
101   default_errsource = errsource;
102
103   /* Try to auto set the character set.  */
104   set_native_charset (NULL);
105
106 #ifdef HAVE_W32_SYSTEM
107   /* For W32 we need to initialize the socket layer.  This is because
108      we use recv and send in libassuan as well as at some other
109      places.  If we are building with PTH we let pth_init do it.  We
110      can't do much on error so we ignore them.  An error would anyway
111      later pop up if one of the socket functions is used. */
112 # ifdef HAVE_NPTH
113   pth_init ();
114 # else
115   {
116     WSADATA wsadat;
117
118     WSAStartup (0x202, &wsadat);
119   }
120 # endif /*!HAVE_NPTH*/
121 #endif
122
123 #ifdef HAVE_W32CE_SYSTEM
124   /* Register the sleep exit function before the estream init so that
125      the sleep will be called after the estream registered atexit
126      function which flushes the left open estream streams and in
127      particular es_stdout.  */
128   atexit (sleep_on_exit);
129 #endif
130
131   /* Initialize the Estream library. */
132   es_init ();
133
134   /* Special hack for Windows CE: We extract some options from arg
135      to setup the standard handles.  */
136 #ifdef HAVE_W32CE_SYSTEM
137   parse_std_file_handles (argcp, argvp);
138 #else
139   (void)argcp;
140   (void)argvp;
141 #endif
142
143   /* Access the standard estreams as early as possible.  If we don't
144      do this the original stdio streams may have been closed when
145      _es_get_std_stream is first use and in turn it would connect to
146      the bit bucket.  */
147   {
148     int i;
149     for (i=0; i < 3; i++)
150       (void)_es_get_std_stream (i);
151   }
152
153   /* --version et al shall use estream as well.  */
154   argparse_register_outfnc (writestring_via_estream);
155 }
156
157
158
159 /* WindowsCE uses a very strange way of handling the standard streams.
160    There is a function SetStdioPath to associate a standard stream
161    with a file or a device but what we really want is to use pipes as
162    standard streams.  Despite that we implement pipes using a device,
163    we would have some limitations on the number of open pipes due to
164    the 3 character limit of device file name.  Thus we don't take this
165    path.  Another option would be to install a file system driver with
166    support for pipes; this would allow us to get rid of the device
167    name length limitation.  However, with GnuPG we can get away be
168    redefining the standard streams and passing the handles to be used
169    on the command line.  This has also the advantage that it makes
170    creating a process much easier and does not require the
171    SetStdioPath set and restore game.  The caller needs to pass the
172    rendezvous ids using up to three options:
173
174      -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
175
176    They are all optional but they must be the first arguments on the
177    command line.  Parsing stops as soon as an invalid option is found.
178    These rendezvous ids are then used to finish the pipe creation.*/
179 #ifdef HAVE_W32CE_SYSTEM
180 static void
181 parse_std_file_handles (int *argcp, char ***argvp)
182 {
183   int argc = *argcp;
184   char **argv = *argvp;
185   const char *s;
186   assuan_fd_t fd;
187   int i;
188   int fixup = 0;
189
190   if (!argc)
191     return;
192
193   for (argc--, argv++; argc; argc--, argv++)
194     {
195       s = *argv;
196       if (*s == '-' && s[1] == '&' && s[2] == 'S'
197           && (s[3] == '0' || s[3] == '1' || s[3] == '2')
198           && s[4] == '='
199           && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
200         {
201           if (s[5] == 'n')
202             fd = ASSUAN_INVALID_FD;
203           else
204             fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
205           _es_set_std_fd (s[3] - '0', (int)fd);
206           fixup++;
207         }
208       else
209         break;
210     }
211
212   if (fixup)
213     {
214       argc = *argcp;
215       argc -= fixup;
216       *argcp = argc;
217
218       argv = *argvp;
219       for (i=1; i < argc; i++)
220         argv[i] = argv[i + fixup];
221       for (; i < argc + fixup; i++)
222         argv[i] = NULL;
223     }
224
225
226 }
227 #endif /*HAVE_W32CE_SYSTEM*/