diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rwxr-xr-x | autogen.sh | 59 | ||||
-rw-r--r-- | build-w32.sh | 10 | ||||
-rw-r--r-- | src/ChangeLog | 15 | ||||
-rw-r--r-- | src/assuan-defs.h | 7 | ||||
-rw-r--r-- | src/assuan-logging.c | 24 | ||||
-rw-r--r-- | src/assuan-pipe-connect.c | 324 | ||||
-rw-r--r-- | src/assuan-socket-connect.c | 18 | ||||
-rw-r--r-- | src/assuan-util.c | 3 |
9 files changed, 424 insertions, 40 deletions
@@ -1,3 +1,7 @@ +2004-12-18 Werner Koch <[email protected]> + + * autogen.sh: Add Option --build-w32. + 2004-12-07 Werner Koch <[email protected]> * configure.ac: Define HAVE_W32_SYSTEM and HAVE_DOSISH_SYSTEM. @@ -29,6 +29,63 @@ check_version () { } +DIE=no + + +# ***** W32 build script ******* +# Used to cross-compile for Windows. +if test "$1" = "--build-w32"; then + tmp=`dirname $0` + tsdir=`cd "$tmp"; pwd` + shift + if [ ! -f $tsdir/config.guess ]; then + echo "$tsdir/config.guess not found" >&2 + exit 1 + fi + build=`$tsdir/config.guess` + + [ -z "$w32root" ] && w32root="$HOME/w32root" + echo "Using $w32root as standard install directory" >&2 + + # See whether we have the Debian cross compiler package or the + # old mingw32/cpd system + if i586-mingw32msvc-gcc --version >/dev/null 2>&1 ; then + host=i586-mingw32msvc + crossbindir=/usr/$host/bin + else + host=i386--mingw32 + if ! mingw32 --version >/dev/null; then + echo "We need at least version 0.3 of MingW32/CPD" >&2 + exit 1 + fi + crossbindir=`mingw32 --install-dir`/bin + # Old autoconf version required us to setup the environment + # with the proper tool names. + CC=`mingw32 --get-path gcc` + CPP=`mingw32 --get-path cpp` + AR=`mingw32 --get-path ar` + RANLIB=`mingw32 --get-path ranlib` + export CC CPP AR RANLIB + fi + + if [ -f "$tsdir/config.log" ]; then + if ! head $tsdir/config.log | grep "$host" >/dev/null; then + echo "Pease run a 'make distclean' first" >&2 + exit 1 + fi + fi + + ./configure --enable-maintainer-mode --prefix=${w32root} \ + --host=i586-mingw32msvc --build=${build} \ + --disable-shared + + exit $? +fi +# ***** end W32 build script ******* + + + + # Grep the required versions from configure.ac autoconf_vers=`sed -n '/^AC_PREREQ(/ { s/^.*(\(.*\))/\1/p @@ -65,8 +122,6 @@ ACLOCAL=${AUTOMAKE_PREFIX}${ACLOCAL:-aclocal}${AUTOMAKE_SUFFIX} #GETTEXT=${GETTEXT_PREFIX}${GETTEXT:-gettext}${GETTEXT_SUFFIX} #MSGMERGE=${GETTEXT_PREFIX}${MSGMERGE:-msgmerge}${GETTEXT_SUFFIX} -DIE=no - if check_version $AUTOCONF $autoconf_vers_num $autoconf_vers ; then check_version $AUTOHEADER $autoconf_vers_num $autoconf_vers autoconf diff --git a/build-w32.sh b/build-w32.sh deleted file mode 100644 index 264d157..0000000 --- a/build-w32.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -[ -z "$w32root" ] && w32root="$HOME/w32root" - - ./configure --enable-maintainer-mode --prefix=${w32root} \ - --host=i586-mingw32msvc --build=`./config.guess` - - - - diff --git a/src/ChangeLog b/src/ChangeLog index f46d346..8ebb394 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,18 @@ +2004-12-18 Werner Koch <[email protected]> + + * assuan-logging.c (_assuan_w32_strerror): New. + * assuan-defs.h (w32_strerror): new. + * assuan-pipe-connect.c (assuan_pipe_connect2, fix_signals): + Factored signal code out to new function. + (build_w32_commandline, create_inheritable_pipe): New. Taken + from gnupg 1.9. + (assuan_pipe_connect2) [W32]: Implemented for W32. + +2004-12-14 Werner Koch <[email protected]> + + * assuan-socket-connect.c (assuan_socket_connect): Always allow + NAME to start with a froward slash. + 2004-12-07 Werner Koch <[email protected]> * assuan-logging.c, assuan-io.c: Include config.h diff --git a/src/assuan-defs.h b/src/assuan-defs.h index 6e23771..0cb5400 100644 --- a/src/assuan-defs.h +++ b/src/assuan-defs.h @@ -207,6 +207,12 @@ void _assuan_free (void *p); void _assuan_log_print_buffer (FILE *fp, const void *buffer, size_t length); void _assuan_log_sanitized_string (const char *string); +#ifdef HAVE_W32_SYSTEM +const char *_assuan_w32_strerror (int ec); +#define w32_strerror(e) _assuan_w32_strerror ((e)) +#endif /*HAVE_W32_SYSTEM*/ + + /*-- assuan-logging.c --*/ void _assuan_set_default_log_stream (FILE *fp); @@ -216,7 +222,6 @@ void _assuan_log_printf (const char *format, ...) #endif ; - /*-- assuan-io.c --*/ ssize_t _assuan_simple_read (ASSUAN_CONTEXT ctx, void *buffer, size_t size); ssize_t _assuan_simple_write (ASSUAN_CONTEXT ctx, const void *buffer, diff --git a/src/assuan-logging.c b/src/assuan-logging.c index d677664..7c65d57 100644 --- a/src/assuan-logging.c +++ b/src/assuan-logging.c @@ -21,11 +21,14 @@ #ifdef HAVE_CONFIG_H #include <config.h> #endif - -#include "assuan-defs.h" #include <stdio.h> #include <string.h> #include <stdarg.h> +#ifdef HAVE_W32_SYSTEM +#include <windows.h> +#endif /*HAVE_W32_SYSTEM*/ + +#include "assuan-defs.h" static char prefix_buffer[80]; static FILE *_assuan_log; @@ -90,3 +93,20 @@ _assuan_log_printf (const char *format, ...) vfprintf (fp, format, arg_ptr ); va_end (arg_ptr); } + + + +#ifdef HAVE_W32_SYSTEM +const char * +_assuan_w32_strerror (int ec) +{ + static char strerr[256]; + + if (ec == -1) + ec = (int)GetLastError (); + FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM, NULL, ec, + MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), + strerr, sizeof (strerr)-1, NULL); + return strerr; +} +#endif /*HAVE_W32_SYSTEM*/ diff --git a/src/assuan-pipe-connect.c b/src/assuan-pipe-connect.c index db23648..4deb83d 100644 --- a/src/assuan-pipe-connect.c +++ b/src/assuan-pipe-connect.c @@ -44,6 +44,44 @@ #define MAX_OPEN_FDS 20 #endif +#ifdef HAVE_W32_SYSTEM +/* We assume that a HANDLE can be represented by an int which should + be true for all i386 systems (HANDLE is defined as void *) and + these are the only systems for which Windows is available. Further + we assume that -1 denotes an invalid handle. */ +#define fd_to_handle(a) ((HANDLE)(a)) +#define handle_to_fd(a) ((int)(a)) +#define pid_to_handle(a) ((HANDLE)(a)) +#define handle_to_pid(a) ((int)(a)) +#endif /*HAVE_W32_SYSTEM*/ + + +/* 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*/ +} + + #ifndef HAVE_W32_SYSTEM static int writen (int fd, const char *buffer, size_t length) @@ -65,7 +103,6 @@ writen (int fd, const char *buffer, size_t length) } #endif -#ifndef HAVE_W32_SYSTEM static int do_finish (assuan_context_t ctx) { @@ -81,20 +118,122 @@ do_finish (assuan_context_t ctx) } if (ctx->pid != -1 && ctx->pid) { +#ifdef HAVE_W32_SYSTEM + /* fixme: We need to check whether -1 is an invalid HANDLE and + what the heck a pid of Zero means. */ +#else /*!HAVE_W32_SYSTEM*/ + /* FIXME: Does it really make sense to use the waitpid? What + about using a double fork and forget abnout it. */ waitpid (ctx->pid, NULL, 0); /* FIXME Check return value. */ ctx->pid = -1; +#endif /*!HAVE_W32_SYSTEM*/ } return 0; } -#endif -#ifndef HAVE_W32_SYSTEM static void do_deinit (assuan_context_t ctx) { do_finish (ctx); } -#endif + + +#ifdef HAVE_W32_SYSTEM +/* Build a command line for use with W32's CreateProcess. On success + CMDLINE gets the address of a newly allocated string. */ +static int +build_w32_commandline (const char *pgmname, char * const *argv, char **cmdline) +{ + int i, n; + const char *s; + char *buf, *p; + + *cmdline = NULL; + n = strlen (pgmname); + for (i=0; (s=argv[i]); i++) + { + n += strlen (s) + 1 + 2; /* (1 space, 2 quoting */ + for (; *s; s++) + if (*s == '\"') + n++; /* Need to double inner quotes. */ + } + n++; + + buf = p = xtrymalloc (n); + if (!buf) + return -1; + + /* fixme: PGMNAME may not contain spaces etc. */ + p = stpcpy (p, pgmname); + for (i=0; argv[i]; i++) + { + if (!*argv[i]) /* Empty string. */ + p = stpcpy (p, " \"\""); + else if (strpbrk (argv[i], " \t\n\v\f\"")) + { + p = stpcpy (p, " \""); + for (s=argv[i]; *s; s++) + { + *p++ = *s; + if (*s == '\"') + *p++ = *s; + } + *p++ = '\"'; + *p = 0; + } + else + p = stpcpy (stpcpy (p, " "), argv[i]); + } + + *cmdline= buf; + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ + + +#ifdef HAVE_W32_SYSTEM +/* Create pipe where one end end is inheritable. */ +static int +create_inheritable_pipe (int filedes[2], int for_write) +{ + HANDLE r, w, h; + SECURITY_ATTRIBUTES sec_attr; + + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + if (!CreatePipe (&r, &w, &sec_attr, 0)) + { + _assuan_log_printf ("CreatePipe failed: %s\n", w32_strerror (-1)); + return -1; + } + + if (!DuplicateHandle (GetCurrentProcess(), for_write? r : w, + GetCurrentProcess(), &h, 0, + TRUE, DUPLICATE_SAME_ACCESS )) + { + _assuan_log_printf ("DuplicateHandle failed: %s\n", w32_strerror (-1)); + CloseHandle (r); + CloseHandle (w); + return -1; + } + if (for_write) + { + CloseHandle (r); + r = h; + } + else + { + CloseHandle (w); + w = h; + } + + filedes[0] = handle_to_fd (r); + filedes[1] = handle_to_fd (w); + return 0; +} +#endif /*HAVE_W32_SYSTEM*/ /* Connect to a server over a pipe, creating the assuan context and @@ -112,32 +251,172 @@ assuan_pipe_connect2 (assuan_context_t *ctx, void *atforkvalue) { #ifdef HAVE_W32_SYSTEM - return ASSUAN_Not_Implemented; -#else - static int fixed_signals = 0; assuan_error_t err; int rp[2]; int wp[2]; char mypidstr[50]; + char *cmdline; + SECURITY_ATTRIBUTES sec_attr; + PROCESS_INFORMATION pi = + { + NULL, /* Returns process handle. */ + 0, /* Returns primary thread handle. */ + 0, /* Returns pid. */ + 0 /* Returns tid. */ + }; + STARTUPINFO si; + int fd, *fdp; + HANDLE nullfd = INVALID_HANDLE_VALUE; if (!ctx || !name || !argv || !argv[0]) return ASSUAN_Invalid_Value; - 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); + fix_signals (); + + sprintf (mypidstr, "%lu", (unsigned long)getpid ()); + + /* Build the command line. */ + if (build_w32_commandline (name, argv, &cmdline)) + return ASSUAN_Out_Of_Core; + + /* Create thew two pipes. */ + if (create_inheritable_pipe (rp, 0)) + { + xfree (cmdline); + return ASSUAN_General_Error; + } + + if (create_inheritable_pipe (wp, 1)) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + xfree (cmdline); + return ASSUAN_General_Error; + } + + + err = _assuan_new_context (ctx); + if (err) + { + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + return ASSUAN_General_Error; + } + + (*ctx)->pipe_mode = 1; + (*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)->deinit_handler = do_deinit; + (*ctx)->finish_handler = do_finish; + + + /* fixme: Actually we should set the "_assuan_pipe_connect_pid" env + variable. However this requires us to write a full environment + handler, because the strings are expected in sorted order. The + suggestion given in the MS Reference Library, to save the old + value, changeit, create proces and restore it, is not thread + safe. */ + + /* Start the process. */ + memset (&sec_attr, 0, sizeof sec_attr ); + sec_attr.nLength = sizeof sec_attr; + sec_attr.bInheritHandle = FALSE; + + memset (&si, 0, sizeof si); + si.cb = sizeof (si); + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdInput = fd_to_handle (wp[0]); + si.hStdOutput = fd_to_handle (rp[1]); + + /* Dup stderr to /dev/null unless it is in the list of FDs to be + passed to the child. */ + fd = fileno (stderr); + fdp = fd_child_list; + if (fdp) + { + for (; *fdp != -1 && *fdp != fd; fdp++) + ; + } + if (!fdp || *fdp == -1) + { + nullfd = CreateFile ("nul", GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, 0, NULL); + if (nullfd == INVALID_HANDLE_VALUE) + { + _assuan_log_printf ("can't open `/dev/nul': %s\n", + w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + xfree (cmdline); + _assuan_release_context (*ctx); + return -1; } - fixed_signals = 1; - /* FIXME: This is not MT safe */ + si.hStdError = nullfd; } + else + si.hStdError = fd_to_handle (_get_osfhandle (fd)); + + + /* Note: We inherit all handles flagged as inheritable. This seems + to be a security flaw but there seems to be no way of selecting + handles to inherit. */ + _assuan_log_printf ("CreateProcess, path=`%s' cmdline=`%s'", + name, cmdline); + if (!CreateProcess (name, /* Program to start. */ + cmdline, /* Command line arguments. */ + &sec_attr, /* Process security attributes. */ + &sec_attr, /* Thread security attributes. */ + TRUE, /* Inherit handles. */ + (CREATE_DEFAULT_ERROR_MODE + | GetPriorityClass (GetCurrentProcess ())) + , /* Creation flags. */ + NULL, /* Environment. */ + NULL, /* Use current drive/directory. */ + &si, /* Startup information. */ + &pi /* Returns process information. */ + )) + { + _assuan_log_printf ("CreateProcess failed: %s\n", w32_strerror (-1)); + CloseHandle (fd_to_handle (rp[0])); + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + CloseHandle (fd_to_handle (wp[1])); + if (nullfd != INVALID_HANDLE_VALUE) + CloseHandle (nullfd); + xfree (cmdline); + _assuan_release_context (*ctx); + return ASSUAN_General_Error; + } + xfree (cmdline); + cmdline = NULL; + if (nullfd != INVALID_HANDLE_VALUE) + { + CloseHandle (nullfd); + nullfd = INVALID_HANDLE_VALUE; + } + + CloseHandle (fd_to_handle (rp[1])); + CloseHandle (fd_to_handle (wp[0])); + + CloseHandle (pi.hThread); + (*ctx)->pid = handle_to_pid (pi.hProcess); + +#else /*!HAVE_W32_SYSTEM*/ + assuan_error_t err; + int rp[2]; + int wp[2]; + char mypidstr[50]; + + if (!ctx || !name || !argv || !argv[0]) + return ASSUAN_Invalid_Value; + + fix_signals (); sprintf (mypidstr, "%lu", (unsigned long)getpid ()); @@ -246,7 +525,7 @@ assuan_pipe_connect2 (assuan_context_t *ctx, { while (*fdp != -1 && *fdp != i) fdp++; - } +` } if (!(fdp && *fdp != -1)) close(i); @@ -272,6 +551,8 @@ assuan_pipe_connect2 (assuan_context_t *ctx, close (rp[1]); close (wp[0]); +#endif /*!HAVE_W32_SYSTEM*/ + /* initial handshake */ { int okay, off; @@ -295,7 +576,6 @@ assuan_pipe_connect2 (assuan_context_t *ctx, } return err; -#endif } diff --git a/src/assuan-socket-connect.c b/src/assuan-socket-connect.c index 1902f13..0a60133 100644 --- a/src/assuan-socket-connect.c +++ b/src/assuan-socket-connect.c @@ -86,13 +86,17 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, struct sockaddr_un srvr_addr; size_t len; +#ifdef HAVE_W32_SYSTEM + _assuan_log_printf ("%s: name =`%s'\n", __FUNCTION__, name); +#endif + if (!r_ctx || !name) return ASSUAN_Invalid_Value; *r_ctx = NULL; - /* we require that the name starts with a slash, so that we can + /* We require that the name starts with a slash, so that we can alter reuse this function for other socket types */ - if (*name != DIRSEP_C) + if (*name != DIRSEP_C && *name != '/') return ASSUAN_Invalid_Value; if (strlen (name)+1 >= sizeof srvr_addr.sun_path) return ASSUAN_Invalid_Value; @@ -102,6 +106,9 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, return err; ctx->deinit_handler = do_deinit; ctx->finish_handler = do_finish; +#ifdef HAVE_W32_SYSTEM + _assuan_log_printf ("%s: got context\n", __FUNCTION__ ); +#endif fd = _assuan_sock_new (PF_LOCAL, SOCK_STREAM, 0); if (fd == -1) @@ -117,6 +124,10 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, srvr_addr.sun_path[sizeof (srvr_addr.sun_path) - 1] = 0; len = SUN_LEN (&srvr_addr); +#ifdef HAVE_W32_SYSTEM + _assuan_log_printf ("%s: about to connect\n", __FUNCTION__ ); +#endif + if (_assuan_sock_connect (fd, (struct sockaddr *) &srvr_addr, len) == -1) { _assuan_log_printf ("can't connect to `%s': %s\n", @@ -125,6 +136,9 @@ assuan_socket_connect (ASSUAN_CONTEXT *r_ctx, _assuan_close (fd); return ASSUAN_Connect_Failed; } +#ifdef HAVE_W32_SYSTEM + _assuan_log_printf ("%s: connected\n", __FUNCTION__ ); +#endif ctx->inbound.fd = fd; ctx->outbound.fd = fd; diff --git a/src/assuan-util.c b/src/assuan-util.c index b300b43..43fa91e 100644 --- a/src/assuan-util.c +++ b/src/assuan-util.c @@ -1,5 +1,5 @@ /* assuan-util.c - Utility functions for Assuan - * Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc. + * Copyright (C) 2001, 2002, 2003, 2004 Free Software Foundation, Inc. * * This file is part of Assuan. * @@ -218,3 +218,4 @@ _assuan_log_sanitized_string (const char *string) funlockfile (fp); #endif } + |