Added some comments and prepared for W32 support
[gpgme.git] / gpgme / w32-io.c
1 /* w32-io.c - W32 API I/O functions
2  *      Copyright (C) 2000 Werner Koch (dd9jn)
3  *
4  * This file is part of GPGME.
5  *
6  * GPGME 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 2 of the License, or
9  * (at your option) any later version.
10  *
11  * GPGME 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, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
19  */
20
21 #include <config.h>
22 #ifdef HAVE_DOSISH_SYSTEM
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include <errno.h>
29 #include <sys/time.h>
30 #include <sys/types.h>
31 #include <unistd.h>
32 #include <signal.h>
33 #include <fcntl.h>
34 #include <windows.h>
35
36 #include "io.h"
37
38 /* 
39  * We assume that a HANDLE can be represented by an int which should be true
40  * for all i386 systems (HANDLE is defined as void *) and these are the only
41  * systems for which Windows is available.
42  * Further we assume that -1 denotes an invalid handle.
43  */
44
45 #define fd_to_handle(a)  ((HANDLE)(a))
46 #define handle_to_fd(a)  ((int)(a))
47 #define pid_to_handle(a) ((HANDLE)(a))
48 #define handle_to_pid(a) ((pid_t)(a))
49
50
51 int
52 _gpgme_io_read ( int fd, void *buffer, size_t count )
53 {
54     int nread = 0;
55     HANDLE h = fd_to_handle (fd);
56
57     if ( !ReadFile ( h, buffer, count, &nread, NULL) ) {
58         fprintf (stderr, "** ReadFile failed: ec=%d\n", (int)GetLastError ());
59         return -1;
60     }
61
62     return nread;
63 }
64
65
66 int
67 _gpgme_io_write ( int fd, const void *buffer, size_t count )
68 {
69     int nwritten;
70     HANDLE h = fd_to_handle (fd);
71
72     if ( !WriteFile ( h, buffer, count, &nwritten, NULL) ) {
73         fprintf (stderr, "** WriteFile failed: ec=%d\n", (int)GetLastError ());
74         return -1;
75     }
76
77     return nwritten;
78 }
79
80 int
81 _gpgme_io_pipe ( int filedes[2] )
82 {
83     HANDLE r, w;
84     
85     if (!CreatePipe ( &r, &w, NULL, 0))
86         return -1;
87     filedes[0] = handle_to_fd (r);
88     filedes[1] = handle_to_fd (w);
89     return 0
90 }
91
92 int
93 _gpgme_io_set_nonblocking ( int fd )
94 {
95     return 0;
96 }
97
98
99 static char *
100 build_commandline ( char **argv );
101 {
102     int i, n = 0;
103     char *buf, *p;
104
105     /* FIXME: we have to quote some things because under Windows the 
106      * program parses the commandline and does some unquoting */
107     for (i=0; argv[i]; i++)
108         n += strlen (argv[i]) + 1;
109     n += 5;                     /* "gpg " */
110     buf = p = xtrymalloc (n);
111     if ( !buf )
112         return NULL;
113     p = stpcpy (p, "gpg");
114     for (i = 0; argv[i]; i++)
115         p = stpcpy (stpcpy (p, " "), argv[i]);
116
117     return buf;
118 }
119
120
121 pid_t
122 _gpgme_io_spawn ( const char *path, char **argv,
123                   struct spawn_fd_item_s *fd_child_list,
124                   struct spawn_fd_item_s *fd_parent_list )
125 {
126     SECURITY_ATTRIBUTES sec_attr;
127     PROCESS_INFORMATION pi = {
128         NULL,      /* returns process handle */
129         0,         /* returns primary thread handle */
130         0,         /* returns pid */
131         0         /* returns tid */
132     };
133     STARTUPINFO si = {
134         0, NULL, NULL, NULL,
135         0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
136         NULL, NULL, NULL, NULL
137     };
138     char *envblock = NULL;
139     int cr_flags = CREATE_DEFAULT_ERROR_MODE
140                  | GetPriorityClass (GetCurrentProcess ());
141     int rc;
142     HANDLE save_stdout;
143     HANDLE outputfd[2], statusfd[2], inputfd[2];
144
145     sec_attr.nLength = sizeof (sec_attr);
146     sec_attr.bInheritHandle = FALSE;
147     sec_attr.lpSecurityDescriptor = NULL;
148
149
150     arg_string = build_commandline ( argv );
151     if (!arg_string )
152         return -1; 
153
154     si.cb = sizeof (si);
155     si.dwFlags = STARTF_USESTDHANDLES;
156     si.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
157     si.hStdOutput = GetStdHandle (STD_OUTPUT_HANDLE);
158     si.hStdError = GetStdHandle (STD_ERROR_HANDLE);
159     if (!SetHandleInformation (si.hStdOutput,
160                                HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
161         fprintf (stderr, "** SHI 1 failed: ec=%d\n", (int) GetLastError ());
162     }
163     if (!SetHandleInformation (si.hStdError,
164                                HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
165         fprintf (stderr, "** SHI 2 failed: ec=%d\n", (int) GetLastError ());
166     }
167     
168
169     fputs ("** CreateProcess ...\n", stderr);
170     fprintf (stderr, "** args=`%s'\n", arg_string);
171     fflush (stderr);
172     if ( !CreateProcessA (GPG_PATH,
173                           arg_string,
174                           &sec_attr,     /* process security attributes */
175                           &sec_attr,     /* thread security attributes */
176                           TRUE,          /* inherit handles */
177                           cr_flags,      /* creation flags */
178                           envblock,      /* environment */
179                           NULL,          /* use current drive/directory */
180                           &si,           /* startup information */
181                           &pi            /* returns process information */
182         ) ) {
183         fprintf (stderr, "** CreateProcess failed: ec=%d\n",
184                  (int) GetLastError ());
185         fflush (stderr);
186         xfree (arg_string);
187         return -1;
188     }
189
190     /* .dup_to is not used in the parent list */
191     for (i=0; fd_parent_list[i].fd != -1; i++ ) {
192         CloseHandle ( fd_to_handle (fd_parent_list[i].fd) );
193     }
194
195     fprintf (stderr, "** CreateProcess ready\n");
196     fprintf (stderr, "**   hProcess=%p  hThread=%p\n",
197              pi.hProcess, pi.hThread);
198     fprintf (stderr, "**   dwProcessID=%d dwThreadId=%d\n",
199              (int) pi.dwProcessId, (int) pi.dwThreadId);
200     fflush (stderr);
201
202     return handle_to_pid (pi.hProcess);
203 }
204
205
206 int
207 _gpgme_io_waitpid ( pid_t pid, int hang, int *r_status, int *r_signal )
208 {
209     return 0;
210 }
211
212
213 /*
214  * Select on the list of fds.
215  * Returns: -1 = error
216  *           0 = timeout or nothing to select
217  *          >0 = number of signaled fds
218  */
219 int
220 _gpgme_io_select ( struct io_select_fd_s *fds, size_t nfds )
221 {
222     return -1;
223 }
224
225
226
227
228
229
230 #endif /*HAVE_DOSISH_SYSTEM*/
231
232
233
234
235
236
237
238
239