diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c index 13ea3de..fc56334 100644 --- a/src/assuan-pipe-connect.c +++ b/src/assuan-pipe-connect.c @@ -1,429 +1,453 @@ /* assuan-pipe-connect.c - Establish a pipe connection (client) * Copyright (C) 2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010, * 2011 Free Software Foundation, Inc. * * This file is part of Assuan. * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include /* On Windows systems signal.h is not needed and even not supported on WindowsCE. */ #ifndef HAVE_DOSISH_SYSTEM # include #endif #ifdef HAVE_UNISTD_H # include #endif #include #ifdef HAVE_FCNTL_H #include #endif #ifdef HAVE_SYS_TYPES_H # include #endif #ifndef HAVE_W32_SYSTEM # include #else # ifdef HAVE_WINSOCK2_H # include # endif # include #endif #include "assuan-defs.h" #include "debug.h" /* Hacks for Slowaris. */ #ifndef PF_LOCAL # ifdef PF_UNIX # define PF_LOCAL PF_UNIX # else # define PF_LOCAL AF_UNIX # endif #endif #ifndef AF_LOCAL # define AF_LOCAL AF_UNIX #endif /* This should be called to make sure that SIGPIPE gets ignored. */ static void fix_signals (void) { #ifndef HAVE_DOSISH_SYSTEM /* No SIGPIPE for these systems. */ static int fixed_signals; if (!fixed_signals) { struct sigaction act; sigaction (SIGPIPE, NULL, &act); if (act.sa_handler == SIG_DFL) { act.sa_handler = SIG_IGN; sigemptyset (&act.sa_mask); act.sa_flags = 0; sigaction (SIGPIPE, &act, NULL); } fixed_signals = 1; /* FIXME: This is not MT safe */ } #endif /*HAVE_DOSISH_SYSTEM*/ } /* Helper for pipe_connect. */ static gpg_error_t initial_handshake (assuan_context_t ctx) { assuan_response_t response; int off; gpg_error_t err; err = _assuan_read_from_server (ctx, &response, &off, 0); if (err) TRACE1 (ctx, ASSUAN_LOG_SYSIO, "initial_handshake", ctx, "can't connect server: %s", gpg_strerror (err)); - else if (response != ASSUAN_RESPONSE_OK) + else if (response == ASSUAN_RESPONSE_OK) + { +#ifdef HAVE_W32_SYSTEM + const char *line = ctx->inbound.line + off; + int pid = ASSUAN_INVALID_PID; + + /* Parse the message: OK ..., process %i */ + line = strchr (line, ','); + if (line) + { + line = strchr (line + 1, ' '); + if (line) + { + line = strchr (line + 1, ' '); + if (line) + pid = atoi (line + 1); + } + } + if (pid != ASSUAN_INVALID_PID) + ctx->pid = pid; +#else + ; +#endif + } + else { TRACE1 (ctx, ASSUAN_LOG_SYSIO, "initial_handshake", ctx, "can't connect server: `%s'", ctx->inbound.line); err = _assuan_error (ctx, GPG_ERR_ASS_CONNECT_FAILED); } return err; } struct at_pipe_fork { void (*user_atfork) (void *opaque, int reserved); void *user_atforkvalue; pid_t parent_pid; }; static void at_pipe_fork_cb (void *opaque, int reserved) { struct at_pipe_fork *atp = opaque; if (atp->user_atfork) atp->user_atfork (atp->user_atforkvalue, reserved); #ifndef HAVE_W32_SYSTEM { char mypidstr[50]; /* We store our parents pid in the environment so that the execed assuan server is able to read the actual pid of the client. The server can't use getppid because it might have been double forked before the assuan server has been initialized. */ sprintf (mypidstr, "%lu", (unsigned long) atp->parent_pid); setenv ("_assuan_pipe_connect_pid", mypidstr, 1); /* Make sure that we never pass a connection fd variable when using a simple pipe. */ unsetenv ("_assuan_connection_fd"); } #endif } static gpg_error_t pipe_connect (assuan_context_t ctx, const char *name, const char **argv, assuan_fd_t *fd_child_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue, unsigned int flags) { gpg_error_t rc; assuan_fd_t rp[2]; assuan_fd_t wp[2]; pid_t pid; int res; struct at_pipe_fork atp; unsigned int spawn_flags; atp.user_atfork = atfork; atp.user_atforkvalue = atforkvalue; atp.parent_pid = getpid (); if (!ctx || !name || !argv || !argv[0]) return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE); if (! ctx->flags.no_fixsignals) fix_signals (); if (_assuan_pipe (ctx, rp, 1) < 0) return _assuan_error (ctx, gpg_err_code_from_syserror ()); if (_assuan_pipe (ctx, wp, 0) < 0) { _assuan_close (ctx, rp[0]); _assuan_close_inheritable (ctx, rp[1]); return _assuan_error (ctx, gpg_err_code_from_syserror ()); } spawn_flags = 0; if (flags & ASSUAN_PIPE_CONNECT_DETACHED) spawn_flags |= ASSUAN_SPAWN_DETACHED; /* FIXME: Use atfork handler that closes child fds on Unix. */ res = _assuan_spawn (ctx, &pid, name, argv, wp[0], rp[1], fd_child_list, at_pipe_fork_cb, &atp, spawn_flags); if (res < 0) { rc = gpg_err_code_from_syserror (); _assuan_close (ctx, rp[0]); _assuan_close_inheritable (ctx, rp[1]); _assuan_close_inheritable (ctx, wp[0]); _assuan_close (ctx, wp[1]); return _assuan_error (ctx, rc); } /* Close the stdin/stdout child fds in the parent. */ _assuan_close_inheritable (ctx, rp[1]); _assuan_close_inheritable (ctx, wp[0]); ctx->engine.release = _assuan_client_release; ctx->engine.readfnc = _assuan_simple_read; ctx->engine.writefnc = _assuan_simple_write; #ifdef HAVE_W32_SYSTEM ctx->engine.sendfd = w32_fdpass_send; #else ctx->engine.sendfd = NULL; #endif ctx->engine.receivefd = NULL; ctx->finish_handler = _assuan_client_finish; ctx->max_accepts = 1; ctx->accept_handler = NULL; ctx->inbound.fd = rp[0]; /* Our inbound is read end of read pipe. */ ctx->outbound.fd = wp[1]; /* Our outbound is write end of write pipe. */ ctx->pid = pid; rc = initial_handshake (ctx); if (rc) _assuan_reset (ctx); return rc; } /* FIXME: For socketpair_connect, use spawn function and add atfork handler to do the right thing. Instead of stdin and stdout, we extend the fd_child_list by fds[1]. */ #ifndef HAVE_W32_SYSTEM struct at_socketpair_fork { assuan_fd_t peer_fd; void (*user_atfork) (void *opaque, int reserved); void *user_atforkvalue; pid_t parent_pid; }; static void at_socketpair_fork_cb (void *opaque, int reserved) { struct at_socketpair_fork *atp = opaque; if (atp->user_atfork) atp->user_atfork (atp->user_atforkvalue, reserved); #ifndef HAVE_W32_SYSTEM { char mypidstr[50]; /* We store our parents pid in the environment so that the execed assuan server is able to read the actual pid of the client. The server can't use getppid because it might have been double forked before the assuan server has been initialized. */ sprintf (mypidstr, "%lu", (unsigned long) atp->parent_pid); setenv ("_assuan_pipe_connect_pid", mypidstr, 1); /* Now set the environment variable used to convey the connection's file descriptor. */ sprintf (mypidstr, "%d", atp->peer_fd); if (setenv ("_assuan_connection_fd", mypidstr, 1)) _exit (4); } #endif } /* This function is similar to pipe_connect but uses a socketpair and sets the I/O up to use sendmsg/recvmsg. */ static gpg_error_t socketpair_connect (assuan_context_t ctx, const char *name, const char **argv, assuan_fd_t *fd_child_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue) { gpg_error_t err; int idx; int fds[2]; char mypidstr[50]; pid_t pid; int *child_fds = NULL; int child_fds_cnt = 0; struct at_socketpair_fork atp; int rc; TRACE_BEG3 (ctx, ASSUAN_LOG_CTX, "socketpair_connect", ctx, "name=%s,atfork=%p,atforkvalue=%p", name ? name : "(null)", atfork, atforkvalue); atp.user_atfork = atfork; atp.user_atforkvalue = atforkvalue; atp.parent_pid = getpid (); if (!ctx || (name && (!argv || !argv[0])) || (!name && !argv)) return _assuan_error (ctx, GPG_ERR_ASS_INV_VALUE); if (! ctx->flags.no_fixsignals) fix_signals (); sprintf (mypidstr, "%lu", (unsigned long)getpid ()); if (fd_child_list) while (fd_child_list[child_fds_cnt] != ASSUAN_INVALID_FD) child_fds_cnt++; child_fds = _assuan_malloc (ctx, (child_fds_cnt + 2) * sizeof (int)); if (! child_fds) return TRACE_ERR (gpg_err_code_from_syserror ()); child_fds[1] = ASSUAN_INVALID_FD; if (fd_child_list) memcpy (&child_fds[1], fd_child_list, (child_fds_cnt + 1) * sizeof (int)); if (_assuan_socketpair (ctx, AF_LOCAL, SOCK_STREAM, 0, fds)) { TRACE_LOG1 ("socketpair failed: %s", strerror (errno)); _assuan_free (ctx, child_fds); return TRACE_ERR (GPG_ERR_ASS_GENERAL); } atp.peer_fd = fds[1]; child_fds[0] = fds[1]; rc = _assuan_spawn (ctx, &pid, name, argv, ASSUAN_INVALID_FD, ASSUAN_INVALID_FD, child_fds, at_socketpair_fork_cb, &atp, 0); if (rc < 0) { err = gpg_err_code_from_syserror (); _assuan_close (ctx, fds[0]); _assuan_close (ctx, fds[1]); _assuan_free (ctx, child_fds); return TRACE_ERR (err); } /* For W32, the user needs to know the server-local names of the inherited handles. Return them here. Note that the translation of the peer socketpair fd (fd_child_list[0]) must be done by the wrapper program based on the environment variable _assuan_connection_fd. */ if (fd_child_list) { for (idx = 0; fd_child_list[idx] != -1; idx++) /* We add 1 to skip over the socketpair end. */ fd_child_list[idx] = child_fds[idx + 1]; } _assuan_free (ctx, child_fds); /* If this is the server child process, exit early. */ if (! name && (*argv)[0] == 's') { _assuan_close (ctx, fds[0]); return 0; } _assuan_close (ctx, fds[1]); ctx->engine.release = _assuan_client_release; ctx->finish_handler = _assuan_client_finish; ctx->max_accepts = 1; ctx->inbound.fd = fds[0]; ctx->outbound.fd = fds[0]; _assuan_init_uds_io (ctx); err = initial_handshake (ctx); if (err) _assuan_reset (ctx); return err; } #endif /*!HAVE_W32_SYSTEM*/ /* Connect to a server over a full-duplex socket (i.e. created by socketpair), creating the assuan context and returning it in CTX. The server filename is NAME, the argument vector in ARGV. FD_CHILD_LIST is a -1 terminated list of file descriptors not to close in the child. ATFORK is called in the child right after the fork; ATFORKVALUE is passed as the first argument and 0 is passed as the second argument. The ATFORK function should only act if the second value is 0. FLAGS is a bit vector and controls how the function acts: Bit 0: If cleared a simple pipe based server is expected and the function behaves similar to `assuan_pipe_connect'. If set a server based on full-duplex pipes is expected. Such pipes are usually created using the `socketpair' function. It also enables features only available with such servers. Bit 7: If set and there is a need to start the server it will be started as a background process. This flag is useful under W32 systems, so that no new console is created and pops up a console window when starting the server If NAME is NULL, no exec is done but the same process is continued. However all file descriptors are closed and some special environment variables are set. To let the caller detect whether the child or the parent continues, the child returns "client" or "server" in *ARGV (but it is sufficient to check only the first character). This feature is only available on POSIX platforms. */ gpg_error_t assuan_pipe_connect (assuan_context_t ctx, const char *name, const char *argv[], assuan_fd_t *fd_child_list, void (*atfork) (void *opaque, int reserved), void *atforkvalue, unsigned int flags) { TRACE2 (ctx, ASSUAN_LOG_CTX, "assuan_pipe_connect", ctx, "name=%s, flags=0x%x", name ? name : "(null)", flags); #ifndef HAVE_W32_SYSTEM if (flags & ASSUAN_PIPE_CONNECT_FDPASSING) return socketpair_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue); else #endif return pipe_connect (ctx, name, argv, fd_child_list, atfork, atforkvalue, flags); } diff --git a/src/assuan-pipe-server.c b/src/assuan-pipe-server.c index 8da54ad..5c960a6 100644 --- a/src/assuan-pipe-server.c +++ b/src/assuan-pipe-server.c @@ -1,139 +1,147 @@ /* assuan-pipe-server.c - Assuan server working over a pipe * Copyright (C) 2001, 2002, 2009 Free Software Foundation, Inc. * * This file is part of Assuan. * * Assuan is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Assuan is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * SPDX-License-Identifier: LGPL-2.1+ */ #ifdef HAVE_CONFIG_H #include #endif #include #include #ifdef HAVE_SYS_TYPES_H # include #endif #ifdef HAVE_SYS_STAT_H # include #endif #ifdef HAVE_UNISTD_H # include #endif #ifdef HAVE_W32_SYSTEM # ifdef HAVE_WINSOCK2_H # include # endif # include #ifdef HAVE_FCNTL_H # include #endif #endif #include "assuan-defs.h" #include "debug.h" /* Returns true if atoi(S) denotes a valid socket. */ #ifndef HAVE_W32_SYSTEM static int is_valid_socket (const char *s) { struct stat buf; if ( fstat (atoi (s), &buf ) ) return 0; return S_ISSOCK (buf.st_mode); } #endif /*!HAVE_W32_SYSTEM*/ /* This actually is a int file descriptor (and not assuan_fd_t) as _get_osfhandle is called on W32 systems. */ gpg_error_t assuan_init_pipe_server (assuan_context_t ctx, assuan_fd_t filedes[2]) { const char *s; unsigned long ul; gpg_error_t rc; assuan_fd_t infd = ASSUAN_INVALID_FD; assuan_fd_t outfd = ASSUAN_INVALID_FD; int is_usd = 0; TRACE_BEG (ctx, ASSUAN_LOG_CTX, "assuan_init_pipe_server", ctx); if (filedes) { TRACE_LOG2 ("fd[0]=0x%x, fd[1]=0x%x", filedes[0], filedes[1]); } rc = _assuan_register_std_commands (ctx); if (rc) return TRACE_ERR (rc); #ifdef HAVE_W32_SYSTEM - infd = filedes[0]; - outfd = filedes[1]; + if (filedes) + { + infd = filedes[0]; + outfd = filedes[1]; + } + else + { + infd = assuan_fd_from_posix_fd (0); + outfd = assuan_fd_from_posix_fd (1); + } #else s = getenv ("_assuan_connection_fd"); if (s && *s && is_valid_socket (s)) { /* Well, we are called with an bi-directional file descriptor. Prepare for using sendmsg/recvmsg. In this case we ignore the passed file descriptors. */ infd = atoi (s); outfd = atoi (s); is_usd = 1; } else if (filedes && filedes[0] != ASSUAN_INVALID_FD && filedes[1] != ASSUAN_INVALID_FD ) { /* Standard pipe server. */ infd = filedes[0]; outfd = filedes[1]; } else { rc = _assuan_error (ctx, GPG_ERR_ASS_SERVER_START); return TRACE_ERR (rc); } #endif ctx->flags.is_server = 1; ctx->engine.release = _assuan_server_release; ctx->engine.readfnc = _assuan_simple_read; ctx->engine.writefnc = _assuan_simple_write; ctx->engine.sendfd = NULL; #ifdef HAVE_W32_SYSTEM ctx->engine.receivefd = w32_fdpass_recv; #else ctx->engine.receivefd = NULL; #endif ctx->max_accepts = 1; s = getenv ("_assuan_pipe_connect_pid"); if (s && (ul=strtoul (s, NULL, 10)) && ul) ctx->pid = (pid_t)ul; else ctx->pid = (pid_t)-1; ctx->accept_handler = NULL; ctx->finish_handler = _assuan_server_finish; ctx->inbound.fd = infd; ctx->outbound.fd = outfd; if (is_usd) _assuan_init_uds_io (ctx); return TRACE_SUC(); } diff --git a/tests/Makefile.am b/tests/Makefile.am index f43c712..317c66d 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -1,47 +1,47 @@ # Makefile for Assuan regression tests # Copyright (C) 2006 Free Software Foundation, Inc. # # This file is part of Assuan. # # Assuan is free software; you can redistribute it and/or modify it # under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation; either version 3 of # the License, or (at your option) any later version. # # Assuan is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with this program; if not, see . ## Process this file with automake to produce Makefile.in TESTS_ENVIRONMENT = EXTRA_DIST = motd BUILT_SOURCES = CLEANFILES = TESTS = version if HAVE_W32_SYSTEM +TESTS += fdpassing testtools = else TESTS += pipeconnect testtools = socks5 endif if USE_DESCRIPTOR_PASSING TESTS += fdpassing endif AM_CFLAGS = $(GPG_ERROR_CFLAGS) AM_LDFLAGS = -no-install noinst_HEADERS = common.h noinst_PROGRAMS = $(TESTS) $(w32cetools) $(testtools) -LDADD = ../src/libassuan.la $(GPG_ERROR_LIBS) \ - @LDADD_FOR_TESTS_KLUDGE@ +LDADD = ../src/libassuan.la $(GPG_ERROR_LIBS) @LDADD_FOR_TESTS_KLUDGE@ diff --git a/tests/fdpassing.c b/tests/fdpassing.c index 0e23ffc..9e1b6e9 100644 --- a/tests/fdpassing.c +++ b/tests/fdpassing.c @@ -1,324 +1,332 @@ /* fdpassing - Check the file descriptor passing. Copyright (C) 2006, 2009 Free Software Foundation, Inc. This file is part of Assuan. Assuan is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Assuan is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program; if not, see . */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include -#include #include #include -#include /* Used by main driver. */ #include "../src/assuan.h" #include "common.h" /* S E R V E R */ static gpg_error_t cmd_echo (assuan_context_t ctx, char *line) { int fd; int c; FILE *fp; int nbytes; log_info ("got ECHO command (%s)\n", line); - fd = assuan_get_input_fd (ctx); + fd = (int)assuan_get_input_fd (ctx); if (fd == -1) return gpg_error (GPG_ERR_ASS_NO_INPUT); fp = fdopen (fd, "r"); if (!fp) { log_error ("fdopen failed on input fd: %s\n", strerror (errno)); return gpg_error (GPG_ERR_ASS_GENERAL); } nbytes = 0; while ( (c=getc (fp)) != -1) { - putc (c, stdout); + putc (c, stderr); nbytes++; } - fflush (stdout); - log_info ("done printing %d bytes to stdout\n", nbytes); + fflush (stderr); + log_info ("done printing %d bytes to stderr\n", nbytes); fclose (fp); return 0; } static gpg_error_t register_commands (assuan_context_t ctx) { static struct { const char *name; gpg_error_t (*handler) (assuan_context_t, char *line); } table[] = { { "ECHO", cmd_echo }, { "INPUT", NULL }, { "OUTPUT", NULL }, { NULL, NULL } }; int i; gpg_error_t rc; for (i=0; table[i].name; i++) { rc = assuan_register_command (ctx, table[i].name, table[i].handler, NULL); if (rc) return rc; } return 0; } static void server (void) { int rc; assuan_context_t ctx; log_info ("server started\n"); rc = assuan_new (&ctx); if (rc) log_fatal ("assuan_new failed: %s\n", gpg_strerror (rc)); rc = assuan_init_pipe_server (ctx, NULL); if (rc) log_fatal ("assuan_init_pipe_server failed: %s\n", gpg_strerror (rc)); rc = register_commands (ctx); if (rc) log_fatal ("register_commands failed: %s\n", gpg_strerror(rc)); assuan_set_log_stream (ctx, stderr); for (;;) { rc = assuan_accept (ctx); if (rc) { if (rc != -1) log_error ("assuan_accept failed: %s\n", gpg_strerror (rc)); break; } log_info ("client connected. Client's pid is %ld\n", (long)assuan_get_pid (ctx)); rc = assuan_process (ctx); if (rc) log_error ("assuan_process failed: %s\n", gpg_strerror (rc)); } assuan_release (ctx); } /* C L I E N T */ /* Client main. If true is returned, a disconnect has not been done. */ static int client (assuan_context_t ctx, const char *fname) { int rc; FILE *fp; int i; log_info ("client started. Servers's pid is %ld\n", (long)assuan_get_pid (ctx)); for (i=0; i < 6; i++) { fp = fopen (fname, "r"); if (!fp) { log_error ("failed to open `%s': %s\n", fname, strerror (errno)); return -1; } - rc = assuan_sendfd (ctx, fileno (fp)); + rc = assuan_sendfd (ctx, (assuan_fd_t)fileno (fp)); if (rc) { fclose (fp); log_error ("assuan_sendfd failed: %s\n", gpg_strerror (rc)); return -1; } fclose (fp); rc = assuan_transact (ctx, "INPUT FD", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) { log_error ("sending INPUT FD failed: %s\n", gpg_strerror (rc)); return -1; } rc = assuan_transact (ctx, "ECHO", NULL, NULL, NULL, NULL, NULL, NULL); if (rc) { log_error ("sending ECHO failed: %s\n", gpg_strerror (rc)); return -1; } } /* Give us some time to check with lsof that all descriptors are closed. */ /* sleep (10); */ assuan_release (ctx); return 0; } /* M A I N */ int main (int argc, char **argv) { int last_argc = -1; assuan_context_t ctx; gpg_error_t err; - int no_close_fds[2]; + assuan_fd_t no_close_fds[2]; const char *arglist[10]; int is_server = 0; int with_exec = 0; char *fname = prepend_srcdir ("motd"); if (argc) { log_set_prefix (*argv); argc--; argv++; } while (argc && last_argc != argc ) { last_argc = argc; if (!strcmp (*argv, "--help")) { puts ( "usage: ./fdpassing [options]\n" "\n" "Options:\n" " --verbose Show what is going on\n" -" --with-exec Exec the child. Default is just a fork\n" +" --with-exec Exec the child. Default is just a fork on POSIX machine\n" ); exit (0); } if (!strcmp (*argv, "--verbose")) { verbose = 1; argc--; argv++; } else if (!strcmp (*argv, "--debug")) { verbose = debug = 1; argc--; argv++; } else if (!strcmp (*argv, "--server")) { is_server = 1; argc--; argv++; } else if (!strcmp (*argv, "--with-exec")) { with_exec = 1; argc--; argv++; } } +#ifdef HAVE_W32_SYSTEM + with_exec = 1; +#endif assuan_set_assuan_log_prefix (log_prefix); if (is_server) { server (); log_info ("server finished\n"); } else { const char *loc; + const char *program_name; + +#ifdef HAVE_W32_SYSTEM + program_name = "fdpassing.exe"; +#else + program_name = "fdpassing"; +#endif - no_close_fds[0] = 2; - no_close_fds[1] = -1; + no_close_fds[0] = verbose? assuan_fd_from_posix_fd (2): (assuan_fd_t)-1; + no_close_fds[1] = (assuan_fd_t)-1; if (with_exec) { - arglist[0] = "fdpassing"; + arglist[0] = program_name; arglist[1] = "--server"; arglist[2] = verbose? "--verbose":NULL; arglist[3] = NULL; } err = assuan_new (&ctx); if (err) log_fatal ("assuan_new failed: %s\n", gpg_strerror (err)); - err = assuan_pipe_connect (ctx, with_exec? "./fdpassing":NULL, + err = assuan_pipe_connect (ctx, with_exec? program_name : NULL, with_exec ? arglist : &loc, no_close_fds, NULL, NULL, 1); if (err) { log_error ("assuan_pipe_connect failed: %s\n", gpg_strerror (err)); assuan_release (ctx); errorcount++; } else if (!with_exec && loc[0] == 's') { server (); assuan_release (ctx); log_info ("server finished\n"); } else { if (client (ctx, fname)) { log_info ("waiting for server to terminate...\n"); assuan_release (ctx); } log_info ("client finished\n"); } } xfree (fname); return errorcount ? 1 : 0; }