104
111
static GIOChannel *
105
find_channel (int fd, int create)
112
find_channel (int fd)
107
114
if (fd < 0 || fd >= MAX_SLAFD)
110
if (create && !giochannel_table[fd].chan)
112
giochannel_table[fd].chan = g_io_channel_win32_new_fd (fd);
113
giochannel_table[fd].primary = 1;
114
g_io_channel_set_encoding (giochannel_table[fd].chan, NULL, NULL);
115
g_io_channel_set_buffered (giochannel_table[fd].chan, FALSE);
118
117
return giochannel_table[fd].chan;
121
/* Returns the FD or -1 on resource limit. */
123
new_dummy_channel_from_fd (int cfd)
127
for (idx = 0; idx < MAX_SLAFD; idx++)
128
if (! giochannel_table[idx].used)
131
if (idx == MAX_SLAFD)
137
giochannel_table[idx].used = 1;
138
giochannel_table[idx].chan = NULL;
139
giochannel_table[idx].fd = cfd;
140
giochannel_table[idx].socket = INVALID_SOCKET;
141
giochannel_table[idx].primary = 1;
147
/* Returns the FD or -1 on resource limit. */
149
new_channel_from_fd (int cfd)
153
for (idx = 0; idx < MAX_SLAFD; idx++)
154
if (! giochannel_table[idx].used)
157
if (idx == MAX_SLAFD)
163
giochannel_table[idx].used = 1;
164
giochannel_table[idx].chan = g_io_channel_win32_new_fd (cfd);
165
giochannel_table[idx].fd = cfd;
166
giochannel_table[idx].socket = INVALID_SOCKET;
167
giochannel_table[idx].primary = 1;
169
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
170
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
176
/* Returns the FD or -1 on resource limit. */
178
new_channel_from_socket (int sock)
182
for (idx = 0; idx < MAX_SLAFD; idx++)
183
if (! giochannel_table[idx].used)
186
if (idx == MAX_SLAFD)
192
giochannel_table[idx].used = 1;
193
giochannel_table[idx].chan = g_io_channel_win32_new_socket (sock);
194
giochannel_table[idx].fd = -1;
195
giochannel_table[idx].socket = sock;
196
giochannel_table[idx].primary = 1;
198
g_io_channel_set_encoding (giochannel_table[idx].chan, NULL, NULL);
199
g_io_channel_set_buffered (giochannel_table[idx].chan, FALSE);
122
205
/* Compatibility interface. Obsolete. */
124
207
gpgme_get_giochannel (int fd)
126
return find_channel (fd, 0);
209
return find_channel (fd);
142
225
_gpgme_io_fd2str (char *buf, int buflen, int fd)
144
229
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_fd2str", fd, "fd=%d", fd);
145
TRACE_SUC1 ("syshd=%p", _get_osfhandle (fd));
146
return snprintf (buf, buflen, "%d", (int) _get_osfhandle (fd));
230
if (giochannel_table[fd].fd != -1)
231
hndl = (HANDLE) _get_osfhandle (giochannel_table[fd].fd);
233
hndl = (HANDLE) giochannel_table[fd].socket;
235
TRACE_SUC1 ("syshd=%p", hndl);
237
return snprintf (buf, buflen, "%d", (int) hndl);
242
352
_gpgme_io_pipe (int filedes[2], int inherit_idx)
245
356
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_pipe", filedes,
246
357
"inherit_idx=%i (GPGME uses it for %s)",
247
358
inherit_idx, inherit_idx ? "reading" : "writing");
249
360
#define PIPEBUF_SIZE 4096
250
if (_pipe (filedes, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
361
if (_pipe (fds, PIPEBUF_SIZE, O_NOINHERIT | O_BINARY) == -1)
251
362
return TRACE_SYSRES (-1);
253
364
/* Make one end inheritable. */
272
new_write = _dup (filedes[1]);
274
filedes[1] = new_write;
383
new_write = _dup (fds[1]);
276
387
if (new_write < 0)
279
390
return TRACE_SYSRES (-1);
283
/* Now we have a pipe with the right end inheritable. The other end
394
/* For _gpgme_io_close. */
395
filedes[inherit_idx] = new_dummy_channel_from_fd (fds[inherit_idx]);
396
if (filedes[inherit_idx] < 0)
398
int saved_errno = errno;
403
return TRACE_SYSRES (-1);
406
/* Now we have a pipe with the correct end inheritable. The other end
284
407
should have a giochannel. */
285
chan = find_channel (filedes[1 - inherit_idx], 1);
408
filedes[1 - inherit_idx] = new_channel_from_fd (fds[1 - inherit_idx]);
409
if (filedes[1 - inherit_idx] < 0)
288
411
int saved_errno = errno;
413
_gpgme_io_close (fds[inherit_idx]);
414
_close (fds[1 - inherit_idx]);
291
415
errno = saved_errno;
292
416
return TRACE_SYSRES (-1);
295
419
return TRACE_SUC5 ("read=0x%x/%p, write=0x%x/%p, channel=%p",
296
filedes[0], (HANDLE) _get_osfhandle (filedes[0]),
297
filedes[1], (HANDLE) _get_osfhandle (filedes[1]),
421
(HANDLE) _get_osfhandle (giochannel_table[filedes[0]].fd),
423
(HANDLE) _get_osfhandle (giochannel_table[filedes[1]].fd),
424
giochannel_table[1 - inherit_idx].chan);
318
446
notify_table[fd].value = NULL;
321
/* Then do the close. */
449
/* Then do the close. */
322
450
if (giochannel_table[fd].chan)
324
452
if (giochannel_table[fd].primary)
325
453
g_io_channel_shutdown (giochannel_table[fd].chan, 1, NULL);
329
455
g_io_channel_unref (giochannel_table[fd].chan);
330
giochannel_table[fd].chan = NULL;
459
/* Dummy entry, just close. */
460
assert (giochannel_table[fd].fd != -1);
461
_close (giochannel_table[fd].fd);
464
giochannel_table[fd].used = 0;
465
giochannel_table[fd].fd = -1;
466
giochannel_table[fd].socket = INVALID_SOCKET;
467
giochannel_table[fd].chan = NULL;
468
giochannel_table[fd].primary = 0;
366
501
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_set_nonblocking", fd);
368
chan = find_channel (fd, 0);
503
chan = find_channel (fd);
372
507
return TRACE_SYSRES (-1);
375
status = g_io_channel_set_flags (chan,
510
status = g_io_channel_set_flags (chan,
376
511
g_io_channel_get_flags (chan) |
377
512
G_IO_FLAG_NONBLOCK, NULL);
378
514
if (status != G_IO_STATUS_NORMAL)
544
680
free (arg_string);
682
if (flags & IOSPAWN_FLAG_ALLOW_SET_FG)
683
_gpgme_allow_set_foreground_window ((pid_t)pi.dwProcessId);
546
685
/* Insert the inherited handles. */
547
686
for (i = 0; fd_list[i].fd != -1; i++)
551
690
/* Make it inheritable for the wrapper process. */
552
if (!DuplicateHandle (GetCurrentProcess(), _get_osfhandle (fd_list[i].fd),
691
if (!DuplicateHandle (GetCurrentProcess(),
692
_get_osfhandle (giochannel_table[fd_list[i].fd].fd),
553
693
pi.hProcess, &hd, 0, TRUE, DUPLICATE_SAME_ACCESS))
555
695
TRACE_LOG1 ("DuplicateHandle failed: ec=%d", (int) GetLastError ());
788
930
GIOChannel *chan;
932
TRACE_BEG (DEBUG_SYSIO, "_gpgme_io_dup", fd);
934
if (fd < 0 || fd >= MAX_SLAFD || !giochannel_table[fd].used)
937
return TRACE_SYSRES (-1);
940
for (newfd = 0; newfd < MAX_SLAFD; newfd++)
941
if (! giochannel_table[newfd].used)
943
if (newfd == MAX_SLAFD)
946
return TRACE_SYSRES (-1);
790
TRACE_BEG1 (DEBUG_SYSIO, "_gpgme_io_dup", fd, "dup (%d)", fd);
794
return TRACE_SYSRES (-1);
795
if (newfd < 0 || newfd >= MAX_SLAFD)
797
/* New FD won't fit into our table. */
800
return TRACE_SYSRES (-1);
802
assert (giochannel_table[newfd].chan == NULL);
804
chan = find_channel (fd, 0);
949
chan = giochannel_table[fd].chan;
807
950
g_io_channel_ref (chan);
951
giochannel_table[newfd].used = 1;
808
952
giochannel_table[newfd].chan = chan;
953
giochannel_table[newfd].fd = -1;
954
giochannel_table[newfd].socket = INVALID_SOCKET;
809
955
giochannel_table[newfd].primary = 0;
811
957
return TRACE_SYSRES (newfd);
973
case ERROR_BROKEN_PIPE:
975
case WSANOTINITIALISED:
984
_gpgme_io_socket (int domain, int type, int proto)
989
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_socket", domain,
990
"type=%i, protp=%i", type, proto);
992
res = socket (domain, type, proto);
993
if (res == INVALID_SOCKET)
995
errno = wsa2errno (WSAGetLastError ());
996
return TRACE_SYSRES (-1);
999
fd = new_channel_from_socket (res);
1002
int saved_errno = errno;
1004
errno = saved_errno;
1005
return TRACE_SYSRES (-1);
1008
TRACE_SUC2 ("fd=%i, socket=0x%x", fd, res);
1015
_gpgme_io_connect (int fd, struct sockaddr *addr, int addrlen)
1024
TRACE_BEG2 (DEBUG_SYSIO, "_gpgme_io_connect", fd,
1025
"addr=%p, addrlen=%i", addr, addrlen);
1027
chan = find_channel (fd);
1031
return TRACE_SYSRES (-1);
1034
flags = g_io_channel_get_flags (chan);
1035
if (flags & G_IO_FLAG_NONBLOCK)
1037
status = g_io_channel_set_flags (chan, flags & ~G_IO_FLAG_NONBLOCK, &err);
1040
TRACE_LOG1 ("setting flags error: %s", err->message);
1044
if (status != G_IO_STATUS_NORMAL)
1047
return TRACE_SYSRES (-1);
1051
sockfd = giochannel_table[fd].socket;
1052
if (sockfd == INVALID_SOCKET)
1055
return TRACE_SYSRES (-1);
1058
TRACE_LOG1 ("connect sockfd=0x%x", sockfd);
1059
res = connect (sockfd, addr, addrlen);
1061
/* FIXME: Error ignored here. */
1062
if (! (flags & G_IO_FLAG_NONBLOCK))
1063
g_io_channel_set_flags (chan, flags, NULL);
1067
TRACE_LOG2 ("connect failed: %i %i", res, WSAGetLastError ());
1069
errno = wsa2errno (WSAGetLastError ());
1070
return TRACE_SYSRES (-1);
1073
return TRACE_SUC ();