Call libssh2_channel_close() before freeing it.
[libpwmd.git] / assuan / assuan-pipe-connect.c
blob05a3be985ed286f6541572debe1b751003eed487
1 /* assuan-pipe-connect.c - Establish a pipe connection (client)
2 * Copyright (C) 2001, 2002, 2003, 2005, 2006,
3 * 2007 Free Software Foundation, Inc.
5 * This file is part of Assuan.
7 * Assuan is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
12 * Assuan is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <signal.h>
29 #include <unistd.h>
30 #include <errno.h>
31 #include <fcntl.h>
32 #include <sys/types.h>
33 #ifndef HAVE_W32_SYSTEM
34 #include <sys/wait.h>
35 #else
36 #include <windows.h>
37 #endif
39 #include "assuan-defs.h"
41 /* Hacks for Slowaris. */
42 #ifndef PF_LOCAL
43 # ifdef PF_UNIX
44 # define PF_LOCAL PF_UNIX
45 # else
46 # define PF_LOCAL AF_UNIX
47 # endif
48 #endif
49 #ifndef AF_LOCAL
50 # define AF_LOCAL AF_UNIX
51 #endif
54 #ifdef _POSIX_OPEN_MAX
55 #define MAX_OPEN_FDS _POSIX_OPEN_MAX
56 #else
57 #define MAX_OPEN_FDS 20
58 #endif
61 /* This should be called to make sure that SIGPIPE gets ignored. */
62 static void
63 fix_signals (void)
65 #ifndef _ASSUAN_NO_FIXED_SIGNALS
66 #ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */
67 static int fixed_signals;
69 if (!fixed_signals)
71 struct sigaction act;
73 sigaction (SIGPIPE, NULL, &act);
74 if (act.sa_handler == SIG_DFL)
76 act.sa_handler = SIG_IGN;
77 sigemptyset (&act.sa_mask);
78 act.sa_flags = 0;
79 sigaction (SIGPIPE, &act, NULL);
81 fixed_signals = 1;
82 /* FIXME: This is not MT safe */
84 #endif /*HAVE_DOSISH_SYSTEM*/
85 #endif /*!_ASSUAN_NO_FIXED_SIGNALS*/
89 #ifndef HAVE_W32_SYSTEM
90 static int
91 writen (int fd, const char *buffer, size_t length)
93 while (length)
95 int nwritten = write (fd, buffer, length);
97 if (nwritten < 0)
99 if (errno == EINTR)
100 continue;
101 return -1; /* write error */
103 length -= nwritten;
104 buffer += nwritten;
106 return 0; /* okay */
108 #endif
110 static int
111 do_finish (assuan_context_t ctx)
113 if (ctx->inbound.fd != ASSUAN_INVALID_FD)
115 _assuan_close (ctx->inbound.fd);
116 if (ctx->inbound.fd == ctx->outbound.fd)
117 ctx->outbound.fd = ASSUAN_INVALID_FD;
118 ctx->inbound.fd = ASSUAN_INVALID_FD;
120 if (ctx->outbound.fd != ASSUAN_INVALID_FD)
122 _assuan_close (ctx->outbound.fd);
123 ctx->outbound.fd = ASSUAN_INVALID_FD;
125 if (ctx->pid != (pid_t)(-1) && ctx->pid)
127 #ifndef HAVE_W32_SYSTEM
128 #ifndef _ASSUAN_USE_DOUBLE_FORK
129 if (!ctx->flags.no_waitpid)
130 _assuan_waitpid (ctx->pid, NULL, 0);
131 ctx->pid =(pid_t)(-1);
132 #endif
133 #else /*!HAVE_W32_SYSTEM*/
134 CloseHandle ((HANDLE) ctx->pid);
135 ctx->pid = (pid_t) INVALID_HANDLE_VALUE;
136 #endif /*HAVE_W32_SYSTEM*/
138 return 0;
142 static void
143 do_deinit (assuan_context_t ctx)
145 do_finish (ctx);
149 /* Helper for pipe_connect. */
150 static assuan_error_t
151 initial_handshake (assuan_context_t *ctx)
153 int okay, off;
154 assuan_error_t err;
156 err = _assuan_read_from_server (*ctx, &okay, &off);
157 if (err)
158 _assuan_log_printf ("can't connect server: %s\n",
159 assuan_strerror (err));
160 else if (okay != 1)
162 _assuan_log_printf ("can't connect server: `%s'\n",
163 (*ctx)->inbound.line);
164 err = _assuan_error (ASSUAN_Connect_Failed);
167 if (err)
169 assuan_disconnect (*ctx);
170 *ctx = NULL;
172 return err;
176 #ifndef HAVE_W32_SYSTEM
177 #define pipe_connect pipe_connect_unix
178 /* Unix version of the pipe connection code. We use an extra macro to
179 make ChangeLog entries easier. */
180 static assuan_error_t
181 pipe_connect_unix (assuan_context_t *ctx,
182 const char *name, const char *const argv[],
183 int *fd_child_list,
184 void (*atfork) (void *opaque, int reserved),
185 void *atforkvalue, unsigned int flags)
187 assuan_error_t err;
188 int rp[2];
189 int wp[2];
190 char mypidstr[50];
192 (void)flags;
194 if (!ctx || !name || !argv || !argv[0])
195 return _assuan_error (ASSUAN_Invalid_Value);
197 fix_signals ();
199 sprintf (mypidstr, "%lu", (unsigned long)getpid ());
201 if (pipe (rp) < 0)
202 return _assuan_error (ASSUAN_General_Error);
204 if (pipe (wp) < 0)
206 close (rp[0]);
207 close (rp[1]);
208 return _assuan_error (ASSUAN_General_Error);
211 err = _assuan_new_context (ctx);
212 if (err)
214 close (rp[0]);
215 close (rp[1]);
216 close (wp[0]);
217 close (wp[1]);
218 return err;
220 (*ctx)->pipe_mode = 1;
221 (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
222 (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
223 (*ctx)->deinit_handler = do_deinit;
224 (*ctx)->finish_handler = do_finish;
226 /* FIXME: For GPGME we should better use _gpgme_io_spawn. The PID
227 stored here is actually soon useless. */
228 (*ctx)->pid = fork ();
229 if ((*ctx)->pid < 0)
231 close (rp[0]);
232 close (rp[1]);
233 close (wp[0]);
234 close (wp[1]);
235 _assuan_release_context (*ctx);
236 return _assuan_error (ASSUAN_General_Error);
239 if ((*ctx)->pid == 0)
241 #ifdef _ASSUAN_USE_DOUBLE_FORK
242 pid_t pid;
244 if ((pid = fork ()) == 0)
245 #endif
247 int i, n;
248 char errbuf[512];
249 int *fdp;
251 if (atfork)
252 atfork (atforkvalue, 0);
254 /* Dup handles to stdin/stdout. */
255 if (rp[1] != STDOUT_FILENO)
257 if (dup2 (rp[1], STDOUT_FILENO) == -1)
259 _assuan_log_printf ("dup2 failed in child: %s\n",
260 strerror (errno));
261 _exit (4);
264 if (wp[0] != STDIN_FILENO)
266 if (dup2 (wp[0], STDIN_FILENO) == -1)
268 _assuan_log_printf ("dup2 failed in child: %s\n",
269 strerror (errno));
270 _exit (4);
274 /* Dup stderr to /dev/null unless it is in the list of FDs to be
275 passed to the child. */
276 fdp = fd_child_list;
277 if (fdp)
279 for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
282 if (!fdp || *fdp == -1)
284 int fd = open ("/dev/null", O_WRONLY);
285 if (fd == -1)
287 _assuan_log_printf ("can't open `/dev/null': %s\n",
288 strerror (errno));
289 _exit (4);
291 if (dup2 (fd, STDERR_FILENO) == -1)
293 _assuan_log_printf ("dup2(dev/null, 2) failed: %s\n",
294 strerror (errno));
295 _exit (4);
300 /* Close all files which will not be duped and are not in the
301 fd_child_list. */
302 n = sysconf (_SC_OPEN_MAX);
303 if (n < 0)
304 n = MAX_OPEN_FDS;
305 for (i=0; i < n; i++)
307 if ( i == STDIN_FILENO || i == STDOUT_FILENO
308 || i == STDERR_FILENO)
309 continue;
310 fdp = fd_child_list;
311 if (fdp)
313 while (*fdp != -1 && *fdp != i)
314 fdp++;
317 if (!(fdp && *fdp != -1))
318 close(i);
320 errno = 0;
322 /* We store our parents pid in the environment so that the
323 execed assuan server is able to read the actual pid of the
324 client. The server can't use getppid because it might have
325 been double forked before the assuan server has been
326 initialized. */
327 setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
329 /* Make sure that we never pass a connection fd variable
330 when using a simple pipe. */
331 unsetenv ("_assuan_connection_fd");
333 execv (name, (char *const *) argv);
334 /* oops - use the pipe to tell the parent about it */
335 snprintf (errbuf, sizeof(errbuf)-1,
336 "ERR %d can't exec `%s': %.50s\n",
337 _assuan_error (ASSUAN_Problem_Starting_Server),
338 name, strerror (errno));
339 errbuf[sizeof(errbuf)-1] = 0;
340 writen (1, errbuf, strlen (errbuf));
341 _exit (4);
343 #ifdef _ASSUAN_USE_DOUBLE_FORK
344 if (pid == -1)
345 _exit (1);
346 else
347 _exit (0);
348 #endif
351 #ifdef _ASSUAN_USE_DOUBLE_FORK
352 _assuan_waitpid ((*ctx)->pid, NULL, 0);
353 (*ctx)->pid = -1;
354 #endif
356 close (rp[1]);
357 close (wp[0]);
359 return initial_handshake (ctx);
361 #endif /*!HAVE_W32_SYSTEM*/
364 #ifndef HAVE_W32_SYSTEM
365 /* This function is similar to pipe_connect but uses a socketpair and
366 sets the I/O up to use sendmsg/recvmsg. */
367 static assuan_error_t
368 socketpair_connect (assuan_context_t *ctx,
369 const char *name, const char *const argv[],
370 int *fd_child_list,
371 void (*atfork) (void *opaque, int reserved),
372 void *atforkvalue)
374 assuan_error_t err;
375 int fds[2];
376 char mypidstr[50];
378 if (!ctx
379 || (name && (!argv || !argv[0]))
380 || (!name && argv))
381 return _assuan_error (ASSUAN_Invalid_Value);
383 fix_signals ();
385 sprintf (mypidstr, "%lu", (unsigned long)getpid ());
387 if ( socketpair (AF_LOCAL, SOCK_STREAM, 0, fds) )
389 _assuan_log_printf ("socketpair failed: %s\n", strerror (errno));
390 return _assuan_error (ASSUAN_General_Error);
393 err = _assuan_new_context (ctx);
394 if (err)
396 close (fds[0]);
397 close (fds[1]);
398 return err;
400 (*ctx)->pipe_mode = 1;
401 (*ctx)->inbound.fd = fds[0];
402 (*ctx)->outbound.fd = fds[0];
403 _assuan_init_uds_io (*ctx);
404 (*ctx)->deinit_handler = _assuan_uds_deinit;
405 (*ctx)->finish_handler = do_finish;
407 (*ctx)->pid = fork ();
408 if ((*ctx)->pid < 0)
410 close (fds[0]);
411 close (fds[1]);
412 _assuan_release_context (*ctx);
413 *ctx = NULL;
414 return _assuan_error (ASSUAN_General_Error);
417 if ((*ctx)->pid == 0)
419 #ifdef _ASSUAN_USE_DOUBLE_FORK
420 pid_t pid;
422 if ((pid = fork ()) == 0)
423 #endif
425 int fd, i, n;
426 char errbuf[512];
427 int *fdp;
429 if (atfork)
430 atfork (atforkvalue, 0);
432 /* Connect stdin and stdout to /dev/null. */
433 fd = open ("/dev/null", O_RDONLY);
434 if (fd == -1 || dup2 (fd, STDIN_FILENO) == -1)
436 _assuan_log_printf ("dup2(dev/null) failed: %s\n",
437 strerror (errno));
438 _exit (4);
440 fd = open ("/dev/null", O_WRONLY);
441 if (fd == -1 || dup2 (fd, STDOUT_FILENO) == -1)
443 _assuan_log_printf ("dup2(dev/null) failed: %s\n",
444 strerror (errno));
445 _exit (4);
448 /* Dup stderr to /dev/null unless it is in the list of FDs to be
449 passed to the child. */
450 fdp = fd_child_list;
451 if (fdp)
453 for (; *fdp != -1 && *fdp != STDERR_FILENO; fdp++)
456 if (!fdp || *fdp == -1)
458 fd = open ("/dev/null", O_WRONLY);
459 if (fd == -1 || dup2 (fd, STDERR_FILENO) == -1)
461 _assuan_log_printf ("dup2(dev/null) failed: %s\n",
462 strerror (errno));
463 _exit (4);
468 /* Close all files which will not be duped, are not in the
469 fd_child_list and are not the connection fd. */
470 n = sysconf (_SC_OPEN_MAX);
471 if (n < 0)
472 n = MAX_OPEN_FDS;
473 for (i=0; i < n; i++)
475 if ( i == STDIN_FILENO || i == STDOUT_FILENO
476 || i == STDERR_FILENO || i == fds[1])
477 continue;
478 fdp = fd_child_list;
479 if (fdp)
481 while (*fdp != -1 && *fdp != i)
482 fdp++;
485 if (!(fdp && *fdp != -1))
486 close(i);
488 errno = 0;
490 /* We store our parents pid in the environment so that the
491 execed assuan server is able to read the actual pid of the
492 client. The server can't use getppid becuase it might have
493 been double forked before the assuan server has been
494 initialized. */
495 setenv ("_assuan_pipe_connect_pid", mypidstr, 1);
497 /* Now set the environment variable used to convey the
498 connection's file descriptor. */
499 sprintf (mypidstr, "%d", fds[1]);
500 if (setenv ("_assuan_connection_fd", mypidstr, 1))
502 _assuan_log_printf ("setenv failed: %s\n", strerror (errno));
503 _exit (4);
506 if (!name && !argv)
508 /* No name and no args given, thus we don't do an exec
509 but continue the forked process. */
510 _assuan_release_context (*ctx);
511 *ctx = NULL;
512 return 0;
515 execv (name, (char *const *) argv);
516 /* oops - use the pipe to tell the parent about it */
517 snprintf (errbuf, sizeof(errbuf)-1,
518 "ERR %d can't exec `%s': %.50s\n",
519 _assuan_error (ASSUAN_Problem_Starting_Server),
520 name, strerror (errno));
521 errbuf[sizeof(errbuf)-1] = 0;
522 writen (fds[1], errbuf, strlen (errbuf));
523 _exit (4);
525 #ifdef _ASSUAN_USE_DOUBLE_FORK
526 if (pid == -1)
527 _exit (1);
528 else
529 _exit (0);
530 #endif
534 #ifdef _ASSUAN_USE_DOUBLE_FORK
535 _assuan_waitpid ((*ctx)->pid, NULL, 0);
536 (*ctx)->pid = -1;
537 #endif
539 close (fds[1]);
541 return initial_handshake (ctx);
543 #endif /*!HAVE_W32_SYSTEM*/
547 #ifdef HAVE_W32_SYSTEM
548 /* Build a command line for use with W32's CreateProcess. On success
549 CMDLINE gets the address of a newly allocated string. */
550 static int
551 build_w32_commandline (const char * const *argv, char **cmdline)
553 int i, n;
554 const char *s;
555 char *buf, *p;
557 *cmdline = NULL;
558 n = 0;
559 for (i=0; (s=argv[i]); i++)
561 n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */
562 for (; *s; s++)
563 if (*s == '\"')
564 n++; /* Need to double inner quotes. */
566 n++;
568 buf = p = xtrymalloc (n);
569 if (!buf)
570 return -1;
572 for (i=0; argv[i]; i++)
574 if (i)
575 p = stpcpy (p, " ");
576 if (!*argv[i]) /* Empty string. */
577 p = stpcpy (p, "\"\"");
578 else if (strpbrk (argv[i], " \t\n\v\f\""))
580 p = stpcpy (p, "\"");
581 for (s=argv[i]; *s; s++)
583 *p++ = *s;
584 if (*s == '\"')
585 *p++ = *s;
587 *p++ = '\"';
588 *p = 0;
590 else
591 p = stpcpy (p, argv[i]);
594 *cmdline= buf;
595 return 0;
597 #endif /*HAVE_W32_SYSTEM*/
600 #ifdef HAVE_W32_SYSTEM
601 /* Create pipe where one end end is inheritable. */
602 static int
603 create_inheritable_pipe (assuan_fd_t filedes[2], int for_write)
605 HANDLE r, w, h;
606 SECURITY_ATTRIBUTES sec_attr;
608 memset (&sec_attr, 0, sizeof sec_attr );
609 sec_attr.nLength = sizeof sec_attr;
610 sec_attr.bInheritHandle = FALSE;
612 if (!CreatePipe (&r, &w, &sec_attr, 0))
614 _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1));
615 return -1;
618 if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w,
619 GetCurrentProcess(), &h, 0,
620 TRUE, DUPLICATE_SAME_ACCESS ))
622 _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1));
623 CloseHandle (r);
624 CloseHandle (w);
625 return -1;
627 if (for_write)
629 CloseHandle (r);
630 r = h;
632 else
634 CloseHandle (w);
635 w = h;
638 filedes[0] = r;
639 filedes[1] = w;
640 return 0;
642 #endif /*HAVE_W32_SYSTEM*/
645 #ifdef HAVE_W32_SYSTEM
646 #define pipe_connect pipe_connect_w32
647 /* W32 version of the pipe connection code. */
648 static assuan_error_t
649 pipe_connect_w32 (assuan_context_t *ctx,
650 const char *name, const char *const argv[],
651 int *fd_child_list,
652 void (*atfork) (void *opaque, int reserved),
653 void *atforkvalue, unsigned int flags)
655 assuan_error_t err;
656 assuan_fd_t rp[2];
657 assuan_fd_t wp[2];
658 char mypidstr[50];
659 char *cmdline;
660 SECURITY_ATTRIBUTES sec_attr;
661 PROCESS_INFORMATION pi =
663 NULL, /* Returns process handle. */
664 0, /* Returns primary thread handle. */
665 0, /* Returns pid. */
666 0 /* Returns tid. */
668 STARTUPINFO si;
669 int fd, *fdp;
670 HANDLE nullfd = INVALID_HANDLE_VALUE;
672 if (!ctx || !name || !argv || !argv[0])
673 return _assuan_error (ASSUAN_Invalid_Value);
675 fix_signals ();
677 sprintf (mypidstr, "%lu", (unsigned long)getpid ());
679 /* Build the command line. */
680 if (build_w32_commandline (argv, &cmdline))
681 return _assuan_error (ASSUAN_Out_Of_Core);
683 /* Create thew two pipes. */
684 if (create_inheritable_pipe (rp, 0))
686 xfree (cmdline);
687 return _assuan_error (ASSUAN_General_Error);
690 if (create_inheritable_pipe (wp, 1))
692 CloseHandle (rp[0]);
693 CloseHandle (rp[1]);
694 xfree (cmdline);
695 return _assuan_error (ASSUAN_General_Error);
699 err = _assuan_new_context (ctx);
700 if (err)
702 CloseHandle (rp[0]);
703 CloseHandle (rp[1]);
704 CloseHandle (wp[0]);
705 CloseHandle (wp[1]);
706 xfree (cmdline);
707 return _assuan_error (ASSUAN_General_Error);
710 (*ctx)->pipe_mode = 1;
711 (*ctx)->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */
712 (*ctx)->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */
713 (*ctx)->deinit_handler = do_deinit;
714 (*ctx)->finish_handler = do_finish;
717 /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env
718 variable. However this requires us to write a full environment
719 handler, because the strings are expected in sorted order. The
720 suggestion given in the MS Reference Library, to save the old
721 value, changeit, create proces and restore it, is not thread
722 safe. */
724 /* Start the process. */
725 memset (&sec_attr, 0, sizeof sec_attr );
726 sec_attr.nLength = sizeof sec_attr;
727 sec_attr.bInheritHandle = FALSE;
729 memset (&si, 0, sizeof si);
730 si.cb = sizeof (si);
731 si.dwFlags = STARTF_USESTDHANDLES;
732 si.hStdInput = wp[0];
733 si.hStdOutput = rp[1];
735 /* Dup stderr to /dev/null unless it is in the list of FDs to be
736 passed to the child. */
737 fd = fileno (stderr);
738 fdp = fd_child_list;
739 if (fdp)
741 for (; *fdp != -1 && *fdp != fd; fdp++)
744 if (!fdp || *fdp == -1)
746 nullfd = CreateFile ("nul", GENERIC_WRITE,
747 FILE_SHARE_READ | FILE_SHARE_WRITE,
748 NULL, OPEN_EXISTING, 0, NULL);
749 if (nullfd == INVALID_HANDLE_VALUE)
751 _assuan_log_printf ("can't open `nul': %s\n", w32_strerror (-1));
752 CloseHandle (rp[0]);
753 CloseHandle (rp[1]);
754 CloseHandle (wp[0]);
755 CloseHandle (wp[1]);
756 xfree (cmdline);
757 _assuan_release_context (*ctx);
758 return -1;
760 si.hStdError = nullfd;
762 else
763 si.hStdError = (void*)_get_osfhandle (fd);
766 /* Note: We inherit all handles flagged as inheritable. This seems
767 to be a security flaw but there seems to be no way of selecting
768 handles to inherit. */
769 /* _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'\n", */
770 /* name, cmdline); */
771 if (!CreateProcess (name, /* Program to start. */
772 cmdline, /* Command line arguments. */
773 &sec_attr, /* Process security attributes. */
774 &sec_attr, /* Thread security attributes. */
775 TRUE, /* Inherit handles. */
776 (CREATE_DEFAULT_ERROR_MODE
777 | ((flags & 128)? DETACHED_PROCESS : 0)
778 | GetPriorityClass (GetCurrentProcess ())
779 | CREATE_SUSPENDED), /* Creation flags. */
780 NULL, /* Environment. */
781 NULL, /* Use current drive/directory. */
782 &si, /* Startup information. */
783 &pi /* Returns process information. */
786 _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1));
787 CloseHandle (rp[0]);
788 CloseHandle (rp[1]);
789 CloseHandle (wp[0]);
790 CloseHandle (wp[1]);
791 if (nullfd != INVALID_HANDLE_VALUE)
792 CloseHandle (nullfd);
793 xfree (cmdline);
794 _assuan_release_context (*ctx);
795 return _assuan_error (ASSUAN_General_Error);
797 xfree (cmdline);
798 cmdline = NULL;
799 if (nullfd != INVALID_HANDLE_VALUE)
801 CloseHandle (nullfd);
802 nullfd = INVALID_HANDLE_VALUE;
805 CloseHandle (rp[1]);
806 CloseHandle (wp[0]);
808 /* _assuan_log_printf ("CreateProcess ready: hProcess=%p hThread=%p" */
809 /* " dwProcessID=%d dwThreadId=%d\n", */
810 /* pi.hProcess, pi.hThread, */
811 /* (int) pi.dwProcessId, (int) pi.dwThreadId); */
813 ResumeThread (pi.hThread);
814 CloseHandle (pi.hThread);
815 (*ctx)->pid = (pid_t) pi.hProcess;
817 return initial_handshake (ctx);
819 #endif /*HAVE_W32_SYSTEM*/
822 /* Connect to a server over a pipe, creating the assuan context and
823 returning it in CTX. The server filename is NAME, the argument
824 vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file
825 descriptors not to close in the child. */
826 assuan_error_t
827 assuan_pipe_connect (assuan_context_t *ctx, const char *name,
828 const char *const argv[], int *fd_child_list)
830 return pipe_connect (ctx, name, argv, fd_child_list, NULL, NULL, 0);
835 assuan_error_t
836 assuan_pipe_connect2 (assuan_context_t *ctx,
837 const char *name, const char *const argv[],
838 int *fd_child_list,
839 void (*atfork) (void *opaque, int reserved),
840 void *atforkvalue)
842 return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue, 0);
846 /* Connect to a server over a full-duplex socket (i.e. created by
847 socketpair), creating the assuan context and returning it in CTX.
848 The server filename is NAME, the argument vector in ARGV.
849 FD_CHILD_LIST is a -1 terminated list of file descriptors not to
850 close in the child. ATFORK is called in the child right after the
851 fork; ATFORKVALUE is passed as the first argument and 0 is passed
852 as the second argument. The ATFORK function should only act if the
853 second value is 0.
855 FLAGS is a bit vector and controls how the function acts:
856 Bit 0: If cleared a simple pipe based server is expected and the
857 function behaves similar to `assuan_pipe_connect'.
859 If set a server based on full-duplex pipes is expected. Such
860 pipes are usually created using the `socketpair' function.
861 It also enables features only available with such servers.
863 Bit 7: If set and there is a need to start ther server it will be
864 started as a background process. This flag is useful under
865 W32 systems, so that no new console is created and pops up a
866 console window when starting the server
869 If NAME as well as ARGV are NULL, no exec is done but the same
870 process is continued. However all file descriptors are closed and
871 some special environment variables are set. To let the caller
872 detect whether the child or the parent continues, the child returns
873 a CTX of NULL. */
874 assuan_error_t
875 assuan_pipe_connect_ext (assuan_context_t *ctx,
876 const char *name, const char *const argv[],
877 int *fd_child_list,
878 void (*atfork) (void *opaque, int reserved),
879 void *atforkvalue, unsigned int flags)
881 if ((flags & 1))
883 #ifdef HAVE_W32_SYSTEM
884 return _assuan_error (ASSUAN_Not_Implemented);
885 #else
886 return socketpair_connect (ctx, name, argv, fd_child_list,
887 atfork, atforkvalue);
888 #endif
890 else
891 return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue,
892 flags);