Minor cleanups
[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  * GnuPG is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * GnuPG is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <config.h>
21
22 #ifdef WITHOUT_GNU_PTH /* Give the Makefile a chance to build without Pth.  */
23 #undef HAVE_PTH
24 #undef USE_GNU_PTH
25 #endif
26
27 #ifdef HAVE_W32_SYSTEM
28 #include <windows.h>
29 #endif
30 #ifdef HAVE_PTH      
31 #include <pth.h>
32 #endif
33
34 #include "util.h"
35
36 #ifdef HAVE_W32CE_SYSTEM
37 #include <assuan.h>
38 static void parse_std_file_handles (int *argcp, char ***argvp);
39 static void
40 sleep_on_exit (void)
41 {
42   /* The sshd on CE swallows some of the command output.  Sleeping a
43      while usually helps.  */
44   Sleep (400);
45 }
46 #endif /*HAVE_W32CE_SYSTEM*/
47
48
49 /* This function is to be used early at program startup to make sure
50    that some subsystems are initialized.  This is in particular
51    important for W32 to initialize the sockets so that our socket
52    emulation code used directly as well as in libassuan may be used.
53    It should best be called before any I/O is done so that setup
54    required for logging is ready.  ARGCP and ARGVP are the addresses
55    of the parameters given to main.  This function may modify them.
56
57    CAUTION: This might be called while running suid(root).  */
58 void
59 init_common_subsystems (int *argcp, char ***argvp)
60 {
61   /* Try to auto set the character set.  */
62   set_native_charset (NULL); 
63
64 #ifdef HAVE_W32_SYSTEM
65   /* For W32 we need to initialize the socket layer.  This is because
66      we use recv and send in libassuan as well as at some other
67      places.  If we are building with PTH we let pth_init do it.  We
68      can't do much on error so we ignore them.  An error would anyway
69      later pop up if one of the socket functions is used. */
70 # ifdef HAVE_PTH
71   pth_init ();
72 # else
73  {
74    WSADATA wsadat;
75
76    WSAStartup (0x202, &wsadat);
77  }
78 # endif /*!HAVE_PTH*/
79 #endif
80
81   /* Initialize the Estream library. */
82   es_init ();
83
84   /* Special hack for Windows CE: We extract some options from arg
85      to setup the standard handles.  */
86 #ifdef HAVE_W32CE_SYSTEM
87   atexit (sleep_on_exit);
88   parse_std_file_handles (argcp, argvp);
89 #else
90   (void)argcp;
91   (void)argvp;
92 #endif
93 }
94
95
96
97 /* WindowsCE uses a very strange way of handling the standard streams.
98    There is a function SetStdioPath to associate a standard stream
99    with a file or a device but what we really want is to use pipes as
100    standard streams.  Despite that we implement pipes using a device,
101    we would have some limitations on the number of open pipes due to
102    the 3 character limit of device file name.  Thus we don't take this
103    path.  Another option would be to install a file system driver with
104    support for pipes; this would allow us to get rid of the device
105    name length limitation.  However, with GnuPG we can get away be
106    redefining the standard streams and passing the handles to be used
107    on the command line.  This has also the advantage that it makes
108    creating a process much easier and does not require the
109    SetStdioPath set and restore game.  The caller needs to pass the
110    rendezvous ids using up to three options:
111
112      -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
113
114    They are all optional but they must be the first arguments on the
115    command line.  Parsing stops as soon as an invalid option is found.
116    These rendezvous ids are then used to finish the pipe creation.*/
117 #ifdef HAVE_W32CE_SYSTEM
118 static void
119 parse_std_file_handles (int *argcp, char ***argvp)
120 {
121   int argc = *argcp;
122   char **argv = *argvp;
123   const char *s;
124   assuan_fd_t fd;
125   int i;
126   int fixup = 0;
127
128   if (!argc)
129     return;
130
131   for (argc--, argv++; argc; argc--, argv++)
132     {
133       s = *argv;
134       if (*s == '-' && s[1] == '&' && s[2] == 'S'
135           && (s[3] == '0' || s[3] == '1' || s[3] == '2')
136           && s[4] == '=' 
137           && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
138         {
139           if (s[5] == 'n')
140             fd = ASSUAN_INVALID_FD;
141           else
142             fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
143           _es_set_std_fd (s[3] - '0', (int)fd);
144           fixup++;
145         }
146       else
147         break;
148     }
149
150   if (fixup)
151     {
152       argc = *argcp;
153       argc -= fixup;
154       *argcp = argc;
155
156       argv = *argvp;
157       for (i=1; i < argc; i++)
158         argv[i] = argv[i + fixup];
159       for (; i < argc + fixup; i++)
160         argv[i] = NULL;
161     }
162
163
164 }
165 #endif /*HAVE_W32CE_SYSTEM*/