More changes for CE. gpgsm does now build and run a keylisting.
[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 #endif /*HAVE_W32CE_SYSTEM*/
40
41
42 /* This function is to be used early at program startup to make sure
43    that some subsystems are initialized.  This is in particular
44    important for W32 to initialize the sockets so that our socket
45    emulation code used directly as well as in libassuan may be used.
46    It should best be called before any I/O is done so that setup
47    required for logging is ready.  ARGCP and ARGVP are the addresses
48    of the parameters given to main.  This function may modify them.
49
50    CAUTION: This might be called while running suid(root).  */
51 void
52 init_common_subsystems (int *argcp, char ***argvp)
53 {
54   /* Try to auto set the character set.  */
55   set_native_charset (NULL); 
56
57 #ifdef HAVE_W32_SYSTEM
58   /* For W32 we need to initialize the socket layer.  This is because
59      we use recv and send in libassuan as well as at some other
60      places.  If we are building with PTH we let pth_init do it.  We
61      can't do much on error so we ignore them.  An error would anyway
62      later pop up if one of the socket functions is used. */
63 # ifdef HAVE_PTH
64   pth_init ();
65 # else
66  {
67    WSADATA wsadat;
68
69    WSAStartup (0x202, &wsadat);
70  }
71 # endif /*!HAVE_PTH*/
72 #endif
73
74   /* Initialize the Estream library. */
75   es_init ();
76
77   /* Special hack for Windows CE: We extract some options from arg
78      to setup the standard handles.  */
79 #ifdef HAVE_W32CE_SYSTEM
80   parse_std_file_handles (argcp, argvp);
81 #else
82   (void)argcp;
83   (void)argvp;
84 #endif
85 }
86
87
88
89 /* WindowsCE uses a very strange way of handling the standard streams.
90    There is a function SetStdioPath to associate a standard stream
91    with a file or a device but what we really want is to use pipes as
92    standard streams.  Despite that we implement pipes using a device,
93    we would have some limitations on the number of open pipes due to
94    the 3 character limit of device file name.  Thus we don't take this
95    path.  Another option would be to install a file system driver with
96    support for pipes; this would allow us to get rid of the device
97    name length limitation.  However, with GnuPG we can get away be
98    redefining the standard streams and passing the handles to be used
99    on the command line.  This has also the advantage that it makes
100    creating a process much easier and does not require the
101    SetStdioPath set and restore game.  The caller needs to pass the
102    rendezvous ids using up to three options:
103
104      -&S0=<rvid> -&S1=<rvid> -&S2=<rvid>
105
106    They are all optional but they must be the first arguments on the
107    command line.  Parsing stops as soon as an invalid option is found.
108    These rendezvous ids are then used to finish the pipe creation.*/
109 #ifdef HAVE_W32CE_SYSTEM
110 static void
111 parse_std_file_handles (int *argcp, char ***argvp)
112 {
113   int argc = *argcp;
114   char **argv = *argvp;
115   const char *s;
116   assuan_fd_t fd;
117   int i;
118   int fixup = 0;
119
120   if (!argc)
121     return;
122
123   for (argc--, argv++; argc; argc--, argv++)
124     {
125       s = *argv;
126       if (*s == '-' && s[1] == '&' && s[2] == 'S'
127           && (s[3] == '0' || s[3] == '1' || s[3] == '2')
128           && s[4] == '=' 
129           && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null")))
130         {
131           if (s[5] == 'n')
132             fd = ASSUAN_INVALID_FD;
133           else
134             fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0');
135           _es_set_std_fd (s[3] - '0', (int)fd);
136           fixup++;
137         }
138       else
139         break;
140     }
141
142   if (fixup)
143     {
144       argc = *argcp;
145       argc -= fixup;
146       *argcp = argc;
147
148       argv = *argvp;
149       for (i=1; i < argc; i++)
150         argv[i] = argv[i + fixup];
151       for (; i < argc + fixup; i++)
152         argv[i] = NULL;
153     }
154
155
156 }
157 #endif /*HAVE_W32CE_SYSTEM*/