diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/Makefile.am | 6 | ||||
-rw-r--r-- | tests/ce-createpipe.c | 179 | ||||
-rw-r--r-- | tests/ce-server.c | 1418 | ||||
-rw-r--r-- | tests/common.h | 5 | ||||
-rw-r--r-- | tests/pipeconnect.c | 50 |
5 files changed, 1 insertions, 1657 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index b547d37..f43c712 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,17 +20,13 @@ TESTS_ENVIRONMENT = -EXTRA_DIST = motd ce-createpipe.c +EXTRA_DIST = motd BUILT_SOURCES = CLEANFILES = TESTS = version -if HAVE_W32CE_SYSTEM -w32cetools = ce-createpipe ce-server -endif - if HAVE_W32_SYSTEM testtools = else diff --git a/tests/ce-createpipe.c b/tests/ce-createpipe.c deleted file mode 100644 index b44784c..0000000 --- a/tests/ce-createpipe.c +++ /dev/null @@ -1,179 +0,0 @@ -/* ce-createpipe.c - Test the W32CE CreatePipe implementation. - Copyright (C) 2010 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <errno.h> - -#define WIN32_LEAN_AND_MEAN -#include <windows.h> - -#include "common.h" - -#include "../src/assuan.h" /* We need the CreatePipe prototype. */ - - -static DWORD -reader_thread (void *arg) -{ - HANDLE hd = arg; - DWORD nread; - char buffer[16]; - - for (;;) - { - if (!ReadFile (hd, buffer, sizeof buffer, &nread, FALSE)) - { - log_error ("reader: ReadFile failed: rc=%d\n", (int)GetLastError ()); - break; - } - log_info ("reader: read %d bytes\n", (int)nread); - log_printhex ("got: ", buffer, nread); - } - - log_info ("reader: finished\n"); - CloseHandle (hd); - return 0; -} - - -static DWORD -writer_thread (void *arg) -{ - HANDLE hd = arg; - DWORD nwritten; - int i = 0; - int j; - char buffer[20]; - int count; - - for (count=0; count < 30; count++) - { - for (j=0; j < sizeof buffer; j++) - buffer[j] = i++; - - if (!WriteFile (hd, buffer, sizeof buffer, &nwritten, NULL)) - { - log_error ("writer: WriteFile failed: rc=%d\n", (int)GetLastError ()); - break; - } - if (nwritten != sizeof buffer) - log_info ("writer: wrote only %d bytes\n", (int)nwritten); - } - - log_info ("writer: finished\n"); - CloseHandle (hd); - return 0; -} - - - -static void -run_test (void) -{ - HANDLE hd[2]; - HANDLE threads[2]; - - if (!CreatePipe (&hd[0], &hd[1], NULL, 0)) - { - log_error ("CreatePipe failed: rc=%d\n", (int)GetLastError ()); - return; - } - log_info ("pipe created read=%p write=%p\n", hd[0], hd[1]); - - threads[0] = CreateThread (NULL, 0, reader_thread, hd[0], 0, NULL); - if (!threads[0]) - log_fatal ("error creating reader thread: rc=%d\n", (int)GetLastError ()); - else - log_info ("reader thread created\n"); - threads[1] = CreateThread (NULL, 0, writer_thread, hd[1], 0, NULL); - if (!threads[0]) - log_fatal ("error creating writer thread: rc=%d\n", (int)GetLastError ()); - else - log_info ("writer thread created\n"); - - switch (WaitForMultipleObjects (2, threads, FALSE, INFINITE)) - { - case WAIT_OBJECT_0: - log_info ("reader thread finished first\n"); - break; - case WAIT_OBJECT_0 + 1: - log_info ("writer thread finished first\n"); - break; - default: - log_error ("WFMO failed: rc=%d\n", (int)GetLastError ()); - break; - } - - - - CloseHandle (threads[0]); - CloseHandle (threads[1]); -} - - - -/* - M A I N - */ -int -main (int argc, char **argv) -{ - int last_argc = -1; - - if (argc) - { - log_set_prefix (*argv); - argc--; argv++; - } - while (argc && last_argc != argc ) - { - last_argc = argc; - if (!strcmp (*argv, "--help")) - { - printf ("usage: %s [options]\n" - "\n" - "Options:\n" - " --verbose Show what is going on\n", - log_get_prefix ()); - exit (0); - } - if (!strcmp (*argv, "--verbose")) - { - verbose = 1; - argc--; argv++; - } - else if (!strcmp (*argv, "--debug")) - { - verbose = debug = 1; - argc--; argv++; - } - } - - run_test (); - - return errorcount ? 1 : 0; -} - diff --git a/tests/ce-server.c b/tests/ce-server.c deleted file mode 100644 index 0565aee..0000000 --- a/tests/ce-server.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* ce-server.c - An Assuan testbed for W32CE; server code - Copyright (C) 2010 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 <http://www.gnu.org/licenses/>. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <assert.h> -#include <unistd.h> -#include <sys/stat.h> -#ifdef HAVE_W32_SYSTEM -# define WIN32_LEAN_AND_MEAN -# include <windows.h> -#else -# include <sys/types.h> -# include <sys/socket.h> -# include <netinet/in.h> -# include <arpa/inet.h> -# ifdef HAVE_SYS_SELECT_H -# include <sys/select.h> -# endif -#endif -#include <errno.h> - -#ifdef HAVE_W32CE_SYSTEM -# ifndef FILE_ATTRIBUTE_ROMSTATICREF -# define FILE_ATTRIBUTE_ROMSTATICREF FILE_ATTRIBUTE_OFFLINE -# endif -extern BOOL GetStdioPathW (int, wchar_t *, DWORD *); -extern BOOL SetStdioPathW (int, const wchar_t *); -#endif /*!HAVE_W32CE_SYSTEM*/ - -#include "../src/assuan.h" - -#include "common.h" - -/* The port we are using by default. */ -static short server_port = 15898; - -/* Flag set to indicate a shutdown. */ -static int shutdown_pending; - -/* An object to keep track of file descriptors. */ -struct fdinfo_s -{ - struct fdinfo_s *next; - assuan_fd_t fd; /* The descriptor. */ -}; -typedef struct fdinfo_s *fdinfo_t; - - -/* The local state of a connection. */ -struct state_s -{ - /* The current working directory - access using get_cwd(). */ - char *cwd; - - /* If valid, a socket in listening state created by the dataport - command. */ - assuan_fd_t dataport_listen_fd; - - /* If valid the socket accepted for the dataport. */ - assuan_fd_t dataport_accepted_fd; - - /* The error code from a dataport accept operation. */ - gpg_error_t dataport_accept_err; - - /* A list of all unused descriptors created by dataport commands. */ - fdinfo_t dataport_fds; - - /* The descriptor set by the DATAPORT command. */ - assuan_fd_t dataport_fd; -}; -typedef struct state_s *state_t; - - - -/* Local prototypes. */ -static gpg_error_t cmd_newdataport_cont (void *opaque, gpg_error_t err, - unsigned char *data, size_t datalen); - - - -/* A wrapper around read to make it work under Windows with HANDLES - and socket descriptors. Takes care of EINTR on POSIX. */ -static int -my_read (assuan_fd_t fd, void *buffer, size_t size) -{ - int res; - -#ifdef HAVE_W32_SYSTEM - res = recv (HANDLE2SOCKET (fd), buffer, size, 0); - if (res == -1) - { - switch (WSAGetLastError ()) - { - case WSAENOTSOCK: - { - DWORD nread = 0; - - res = ReadFile (fd, buffer, size, &nread, NULL); - if (!res) - { - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - } - res = -1; - } - else - res = (int) nread; - } - break; - - case WSAEWOULDBLOCK: - gpg_err_set_errno (EAGAIN); - break; - - case ERROR_BROKEN_PIPE: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - } - return res; -#else /*!HAVE_W32_SYSTEM*/ - do - res = read (fd, buffer, size); - while (res == -1 && errno == EINTR); - return res; -#endif /*!HAVE_W32_SYSTEM*/ -} - - -/* Extended version of write(2) to guarantee that all bytes are - written. Returns 0 on success or -1 and ERRNO on failure. NOTE: - This function does not return the number of bytes written, so any - error must be treated as fatal for this connection as the state of - the receiver is unknown. This works best if blocking is allowed - (so EAGAIN cannot occur). Under Windows this function handles - socket descriptors and system handles. */ -static int -my_writen (assuan_fd_t fd, const char *buffer, size_t length) -{ - while (length) - { - int nwritten; -#ifdef HAVE_W32_SYSTEM - nwritten = send (HANDLE2SOCKET (fd), buffer, length, 0); - if (nwritten == -1 && WSAGetLastError () == WSAENOTSOCK) - { - DWORD nwrite; - - nwritten = WriteFile (fd, buffer, length, &nwrite, NULL); - if (!nwritten) - { - switch (GetLastError ()) - { - case ERROR_BROKEN_PIPE: - case ERROR_NO_DATA: - gpg_err_set_errno (EPIPE); - break; - - default: - gpg_err_set_errno (EIO); - break; - } - nwritten= -1; - } - else - nwritten = (int)nwrite; - } -#else /*!HAVE_W32_SYSTEM*/ - nwritten = write (fd, buffer, length); -#endif /*!HAVE_W32_SYSTEM*/ - if (nwritten < 0) - { - if (errno == EINTR) - continue; - return -1; /* write error */ - } - length -= nwritten; - buffer += nwritten; - } - return 0; /* okay */ -} - - - -static state_t -new_state (void) -{ - state_t state = xcalloc (1, sizeof *state); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - state->dataport_fd = ASSUAN_INVALID_FD; - return state; -} - -static void -release_state (state_t state) -{ - fdinfo_t fi, fi2; - - if (!state) - return; - - xfree (state->cwd); - - if (state->dataport_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_fd); - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_listen_fd); - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - assuan_sock_close (state->dataport_accepted_fd); - - for (fi=state->dataport_fds; fi; fi = fi2) - { - fi2 = fi->next; - if (fi->fd != ASSUAN_INVALID_FD) - assuan_sock_close (fi->fd); - } - - xfree (state); -} - - -/* Helper to print a message while leaving a command and to - acknowledge the command. */ -static gpg_error_t -leave_cmd (assuan_context_t ctx, gpg_error_t err) -{ - if (err) - { - const char *name = assuan_get_command_name (ctx); - if (!name) - name = "?"; - if (gpg_err_source (err) == GPG_ERR_SOURCE_DEFAULT) - log_error ("command '%s' failed: %s\n", name, gpg_strerror (err)); - else - log_error ("command '%s' failed: %s <%s>\n", name, - gpg_strerror (err), gpg_strsource (err)); - } - return assuan_process_done (ctx, err); -} - - -#ifdef HAVE_W32CE_SYSTEM -static char * -wchar_to_utf8 (const wchar_t *string) -{ - int n; - size_t length = wcslen (string); - char *result; - - n = WideCharToMultiByte (CP_UTF8, 0, string, length, NULL, 0, NULL, NULL); - if (n < 0 || (n+1) <= 0) - log_fatal ("WideCharToMultiByte failed\n"); - - result = xmalloc (n+1); - n = WideCharToMultiByte (CP_ACP, 0, string, length, result, n, NULL, NULL); - if (n < 0) - log_fatal ("WideCharToMultiByte failed\n"); - - result[n] = 0; - return result; -} - -static wchar_t * -utf8_to_wchar (const char *string) -{ - int n; - size_t length = strlen (string); - wchar_t *result; - size_t nbytes; - - n = MultiByteToWideChar (CP_UTF8, 0, string, length, NULL, 0); - if (n < 0 || (n+1) <= 0) - log_fatal ("MultiByteToWideChar failed\n"); - - nbytes = (size_t)(n+1) * sizeof(*result); - if (nbytes / sizeof(*result) != (n+1)) - log_fatal ("utf8_to_wchar: integer overflow\n"); - result = xmalloc (nbytes); - n = MultiByteToWideChar (CP_UTF8, 0, string, length, result, n); - if (n < 0) - log_fatal ("MultiByteToWideChar failed\n"); - result[n] = 0; - - return result; -} -#endif /*HAVE_W32CE_SYSTEM*/ - -#ifndef HAVE_W32CE_SYSTEM -static char * -gnu_getcwd (void) -{ - size_t size = 100; - - while (1) - { - char *buffer = xmalloc (size); - if (getcwd (buffer, size) == buffer) - return buffer; - xfree (buffer); - if (errno != ERANGE) - return 0; - size *= 2; - } -} -#endif /*!HAVE_W32CE_SYSTEM*/ - - -/* Return the current working directory. The returned string is valid - as long as STATE->cwd is not changed. */ -static const char * -get_cwd (state_t state) -{ - if (!state->cwd) - { - /* No working directory yet. On WindowsCE make it the module - directory of this process. */ -#ifdef HAVE_W32_SYSTEM - char *p; -#endif -#ifdef HAVE_W32CE_SYSTEM - wchar_t buf[MAX_PATH+1]; - size_t n; - - n = GetModuleFileName (NULL, buf, MAX_PATH); - if (!n) - state->cwd = xstrdup ("/"); - else - { - buf[n] = 0; - state->cwd = wchar_to_utf8 (buf); - p = strrchr (state->cwd, '\\'); - if (p) - *p = 0; - } -#else - state->cwd = gnu_getcwd (); -#endif -#ifdef HAVE_W32_SYSTEM - for (p=state->cwd; *p; p++) - if (*p == '\\') - *p = '/'; -#endif /*HAVE_W32_SYSTEM*/ - } - - return state->cwd; -} - - - -static gpg_error_t -reset_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - fdinfo_t fi, fi2; - - /* Close all lingering dataport connections. */ - for (fi=state->dataport_fds; fi; fi = fi2) - { - fi2 = fi->next; - if (fi->fd != ASSUAN_INVALID_FD) - assuan_sock_close (fi->fd); - } - state->dataport_fds = NULL; - - return 0; -} - - -static gpg_error_t -input_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - assuan_fd_t fd = assuan_get_input_fd (ctx); - fdinfo_t fi; - - if (fd != ASSUAN_INVALID_FD) - { - /* The fd is now in use use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return 0; -} - - -static gpg_error_t -output_notify (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - assuan_fd_t fd = assuan_get_output_fd (ctx); - fdinfo_t fi; - - if (fd != ASSUAN_INVALID_FD) - { - /* The fd is now in use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return 0; -} - - - -static const char hlp_echo[] = - "ECHO <line>\n" - "\n" - "Print LINE as data lines.\n"; -static gpg_error_t -cmd_echo (assuan_context_t ctx, char *line) -{ - gpg_error_t err; - - err = assuan_send_data (ctx, line, strlen (line)); - - return leave_cmd (ctx, err); -} - - - -static const char hlp_cat[] = - "CAT [<filename>]\n" - "\n" - "Copy the content of FILENAME to the descriptor set by the OUTPUT\n" - "command. If no OUTPUT command has been given, send the content\n" - "using data lines. Without FILENAME take the content from the\n" - "descriptor set by the INPUT command; if a DATAPORT has been set\n" - "this descriptor is used for I/O and the INOPUT/OUTPUT descriptors\n" - "are not touched."; -static gpg_error_t -cmd_cat (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - assuan_fd_t fd_in = ASSUAN_INVALID_FD; - assuan_fd_t fd_out = ASSUAN_INVALID_FD; - FILE *fp_in = NULL; - char buf[256]; - size_t nread; - int use_dataport = 0; - - if (*line) - { - fp_in = fopen (line, "rb"); - if (!fp_in) - err = gpg_error_from_syserror (); - else - fd_out = assuan_get_output_fd (ctx); - } - else if (state->dataport_fd != ASSUAN_INVALID_FD) - { - use_dataport = 1; - fd_in = state->dataport_fd; - fd_out = state->dataport_fd; - } - else if ((fd_in = assuan_get_input_fd (ctx)) != ASSUAN_INVALID_FD) - { - /* This FD is actually a socket descriptor. We can't fdopen it - because under Windows we ust use recv(2) instead of read(2). - Note that on POSIX systems there is no difference between - libc file descriptors and socket descriptors. */ - - fd_out = assuan_get_output_fd (ctx); - } - else - err = gpg_error (GPG_ERR_ASS_NO_INPUT); - if (err) - goto leave; - - do - { - if (fp_in) - { - nread = fread (buf, 1, sizeof buf, fp_in); - if (nread < sizeof buf) - { - if (ferror (fp_in)) - err = gpg_error_from_syserror (); - else if (feof (fp_in)) - err = gpg_error (GPG_ERR_EOF); - } - } - else - { - int n; - - nread = 0; - n = my_read (fd_in, buf, sizeof buf); - if (n < 0) - err = gpg_error_from_syserror (); - else if (!n) - err = gpg_error (GPG_ERR_EOF); - else - nread = n; - } - - - if (fd_out != ASSUAN_INVALID_FD) - { - if (nread && my_writen (fd_out, buf, nread)) - err = gpg_error_from_syserror (); - } - else if (nread) - err = assuan_send_data (ctx, buf, nread); - } - while (!err); - if (gpg_err_code (err) == GPG_ERR_EOF) - err = 0; - -leave: - if (fp_in) - fclose (fp_in); - if (use_dataport) - { - if (state->dataport_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_fd); - state->dataport_fd = ASSUAN_INVALID_FD; - } - } - else - { - assuan_close_input_fd (ctx); - assuan_close_output_fd (ctx); - } - return leave_cmd (ctx, err); -} - - -static const char hlp_pwd[] = - "PWD\n" - "\n" - "Print the curent working directory of this session.\n"; -static gpg_error_t -cmd_pwd (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - const char *string; - - string = get_cwd (state); - err = assuan_send_data (ctx, string, strlen (string)); - - return leave_cmd (ctx, err); -} - - -static const char hlp_cd[] = - "CD [dir]\n" - "\n" - "Change the curretn directory of the session.\n"; -static gpg_error_t -cmd_cd (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - char *newdir, *p; - - for (p=line; *p; p++) - if (*p == '\\') - *p = '/'; - - if (!*line) - { - xfree (state->cwd); - state->cwd = NULL; - get_cwd (state); - } - else - { - if (*line == '/') - newdir = xstrdup (line); - else - newdir = xstrconcat (get_cwd (state), "/", line, NULL); - - while (strlen(newdir) > 1 && line[strlen(newdir)-1] == '/') - line[strlen(newdir)-1] = 0; - xfree (state->cwd); - state->cwd = newdir; - } - - return leave_cmd (ctx, err); -} - - - - - -#ifdef HAVE_W32CE_SYSTEM -static const char hlp_ls[] = - "LS [<pattern>]\n" - "\n" - "List the files described by PATTERN.\n"; -static gpg_error_t -cmd_ls (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - WIN32_FIND_DATA fi; - char buf[500]; - HANDLE hd; - char *p, *fname; - wchar_t *wfname; - - if (!*line) - fname = xstrconcat (get_cwd (state), "/*", NULL); - else if (*line == '/' || *line == '\\') - fname = xstrdup (line); - else - fname = xstrconcat (get_cwd (state), "/", line, NULL); - for (p=fname; *p; p++) - if (*p == '/') - *p = '\\'; - assuan_write_status (ctx, "PATTERN", fname); - wfname = utf8_to_wchar (fname); - xfree (fname); - hd = FindFirstFile (wfname, &fi); - free (wfname); - if (hd == INVALID_HANDLE_VALUE) - { - log_info ("FindFirstFile returned %d\n", GetLastError ()); - err = gpg_error_from_syserror (); /* Works for W32CE. */ - goto leave; - } - - do - { - DWORD attr = fi.dwFileAttributes; - - fname = wchar_to_utf8 (fi.cFileName); - snprintf (buf, sizeof buf, - "%c%c%c%c%c%c%c%c%c%c%c%c%c %7lu%c %s\n", - (attr & FILE_ATTRIBUTE_DIRECTORY) - ? ((attr & FILE_ATTRIBUTE_DEVICE)? 'c':'d'):'-', - (attr & FILE_ATTRIBUTE_READONLY)? 'r':'-', - (attr & FILE_ATTRIBUTE_HIDDEN)? 'h':'-', - (attr & FILE_ATTRIBUTE_SYSTEM)? 's':'-', - (attr & FILE_ATTRIBUTE_ARCHIVE)? 'a':'-', - (attr & FILE_ATTRIBUTE_COMPRESSED)? 'c':'-', - (attr & FILE_ATTRIBUTE_ENCRYPTED)? 'e':'-', - (attr & FILE_ATTRIBUTE_INROM)? 'R':'-', - (attr & FILE_ATTRIBUTE_REPARSE_POINT)? 'P':'-', - (attr & FILE_ATTRIBUTE_ROMMODULE)? 'M':'-', - (attr & FILE_ATTRIBUTE_ROMSTATICREF)? 'R':'-', - (attr & FILE_ATTRIBUTE_SPARSE_FILE)? 'S':'-', - (attr & FILE_ATTRIBUTE_TEMPORARY)? 't':'-', - (unsigned long)fi.nFileSizeLow, - fi.nFileSizeHigh? 'X':' ', - fname); - free (fname); - err = assuan_send_data (ctx, buf, strlen (buf)); - if (!err) - err = assuan_send_data (ctx, NULL, 0); - } - while (!err && FindNextFile (hd, &fi)); - if (err) - ; - else if (GetLastError () == ERROR_NO_MORE_FILES) - err = 0; - else - { - log_info ("FindNextFile returned %d\n", GetLastError ()); - err = gpg_error_from_syserror (); - } - FindClose (hd); - - leave: - return leave_cmd (ctx, err); -} -#endif /*HAVE_W32CE_SYSTEM*/ - - -#ifdef HAVE_W32CE_SYSTEM -static const char hlp_run[] = - "RUN <filename> [<args>]\n" - "\n" - "Run the program in FILENAME with the arguments ARGS.\n" - "This creates a new process and waits for it to finish.\n" - "FIXME: The process' stdin is connected to the file set by the\n" - "INPUT command; stdout and stderr to the one set by OUTPUT.\n"; -static gpg_error_t -cmd_run (assuan_context_t ctx, char *line) -{ - /* state_t state = assuan_get_pointer (ctx); */ - gpg_error_t err; - BOOL w32ret; - PROCESS_INFORMATION pi = { NULL, 0, 0, 0 }; - char *p; - wchar_t *pgmname = NULL; - wchar_t *cmdline = NULL; - int code; - DWORD exc; - int idx; - struct { - HANDLE hd[2]; - int oldname_valid; - wchar_t oldname[MAX_PATH]; - } pipes[3]; - - for (idx=0; idx < 3; idx++) - { - pipes[idx].hd[0] = pipes[idx].hd[1] = INVALID_HANDLE_VALUE; - pipes[idx].oldname_valid = 0; - } - - p = strchr (line, ' '); - if (p) - { - *p = 0; - pgmname = utf8_to_wchar (line); - for (p++; *p && *p == ' '; p++) - ; - cmdline = utf8_to_wchar (p); - } - else - pgmname = utf8_to_wchar (line); - { - char *tmp1 = wchar_to_utf8 (pgmname); - char *tmp2 = wchar_to_utf8 (cmdline); - log_info ("CreateProcess, path=`%s' cmdline=`%s'\n", tmp1, tmp2); - xfree (tmp2); - xfree (tmp1); - } - - /* Redirect the standard handles. */ - /* Create pipes. */ - for (idx=0; idx < 3; idx++) - { - if (!_assuan_w32ce_create_pipe (&pipes[idx].hd[0], &pipes[idx].hd[1], - NULL, 0)) - { - err = gpg_error_from_syserror (); - log_error ("CreatePipe failed: %d\n", GetLastError ()); - pipes[idx].hd[0] = pipes[idx].hd[1] = INVALID_HANDLE_VALUE; - goto leave; - } - } - - /* Save currently assigned devices. */ - for (idx=0; idx < 3; idx++) - { - DWORD dwlen = MAX_PATH; - if (!GetStdioPathW (idx, pipes[idx].oldname, &dwlen)) - { - err = gpg_error_from_syserror (); - log_error ("GetStdioPath failed: %d\n", GetLastError ()); - goto leave; - } - pipes[idx].oldname_valid = 1; - } - - /* Connect the pipes. */ - { - if (!SetStdioPathW (1, L"\\mystdout.log")) - { - err = gpg_error_from_syserror (); - log_error ("SetStdioPathW(%d) failed: %d\n", idx, GetLastError ()); - goto leave; - } - if (!SetStdioPathW (2, L"\\mystderr.log")) - { - err = gpg_error_from_syserror (); - log_error ("SetStdioPathW(%d) failed: %d\n", idx, GetLastError ()); - goto leave; - } - } - - /* Create the process, restore the devices and check the error. */ - w32ret = CreateProcess (pgmname, /* Program to start. */ - cmdline, /* Command line arguments. */ - NULL, /* Process security. Not used. */ - NULL, /* Thread security. Not used. */ - FALSE, /* Inherit handles. Not used. */ - CREATE_SUSPENDED, /* Creation flags. */ - NULL, /* Environment. Not used. */ - NULL, /* Use current dir. Not used. */ - NULL, /* Startup information. Not used. */ - &pi /* Returns process information. */ - ); - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].oldname_valid) - { - if (!SetStdioPathW (idx, pipes[idx].oldname)) - log_error ("SetStdioPath(%d) failed during restore: %d\n", - idx, GetLastError ()); - else - pipes[idx].oldname_valid = 0; - } - } - if (!w32ret) - { - /* Error checking after restore so that the messages are visible. */ - log_error ("CreateProcess failed: %d\n", GetLastError ()); - err = gpg_error_from_syserror (); - goto leave; - } - - log_info ("CreateProcess ready: hProcess=%p hThread=%p" - " dwProcessID=%d dwThreadId=%d\n", - pi.hProcess, pi.hThread, - (int) pi.dwProcessId, (int) pi.dwThreadId); - - ResumeThread (pi.hThread); - CloseHandle (pi.hThread); - - code = WaitForSingleObject (pi.hProcess, INFINITE); - switch (code) - { - case WAIT_FAILED: - err = gpg_error_from_syserror ();; - log_error ("waiting for process %d to terminate failed: %d\n", - (int)pi.dwProcessId, GetLastError ()); - break; - - case WAIT_OBJECT_0: - if (!GetExitCodeProcess (pi.hProcess, &exc)) - { - err = gpg_error_from_syserror ();; - log_error ("error getting exit code of process %d: %s\n", - (int)pi.dwProcessId, GetLastError () ); - } - else if (exc) - { - log_info ("error running process: exit status %d\n", (int)exc); - err = gpg_error (GPG_ERR_GENERAL); - } - else - { - err = 0; - } - break; - - default: - err = gpg_error_from_syserror ();; - log_error ("WaitForSingleObject returned unexpected " - "code %d for pid %d\n", code, (int)pi.dwProcessId); - break; - } - CloseHandle (pi.hProcess); - - leave: - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].oldname_valid) - { - if (!SetStdioPathW (idx, pipes[idx].oldname)) - log_error ("SetStdioPath(%d) failed during restore: %d\n", - idx, GetLastError ()); - else - pipes[idx].oldname_valid = 0; - } - } - for (idx=0; idx < 3; idx++) - { - if (pipes[idx].hd[0] != INVALID_HANDLE_VALUE) - CloseHandle (pipes[idx].hd[0]); - if (pipes[idx].hd[1] != INVALID_HANDLE_VALUE) - CloseHandle (pipes[idx].hd[1]); - } - xfree (cmdline); - xfree (pgmname); - return leave_cmd (ctx, err); -} -#endif /*HAVE_W32CE_SYSTEM*/ - - - - - -static const char hlp_newdataport[] = - "NEWDATAPORT\n" - "\n" - "Create a new dataport. The server creates a listening socket and\n" - "issues the inquiry:\n" - " INQUIRE CONNECT-TO <port>\n" - "The client is expected to connect to PORT of the server and confirm\n" - "this by sending just an \"END\". In turn the server sends:\n" - " S FDINFO <n>\n" - "With N being the local descriptor for the accepted connection. This\n" - "descriptor may now be used with INPUT or OUTPUT commands."; -struct cmd_dataport_locals -{ - assuan_context_t ctx; - int passthru; - int port; -}; -static gpg_error_t -cmd_newdataport (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - struct sockaddr_in addr; - socklen_t addrlen; - struct cmd_dataport_locals *cont; - char inqline[100]; - - cont = xmalloc (sizeof *cont); - cont->ctx = ctx; - cont->passthru = 0; - cont->port = 0; - - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - log_error ("Oops, still listening on a dataport socket\n"); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - } - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - { - log_error ("Oops, still holding an accepted dataport socket\n"); - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - } - state->dataport_accept_err = 0; - - state->dataport_listen_fd = assuan_sock_new (PF_INET, SOCK_STREAM, 0); - if (state->dataport_listen_fd == ASSUAN_INVALID_FD) - { - err = gpg_error_from_syserror (); - log_error ("socket() failed: %s\n", strerror (errno)); - goto leave; - } - - addr.sin_family = AF_INET; - addr.sin_port = 0; - addr.sin_addr.s_addr = htonl (INADDR_ANY); - if (assuan_sock_bind (state->dataport_listen_fd, - (struct sockaddr *)&addr, sizeof addr)) - { - err = gpg_error_from_syserror (); - log_error ("listen() failed: %s\n", strerror (errno)); - goto leave; - } - - if (listen (HANDLE2SOCKET (state->dataport_listen_fd), 1)) - { - err = gpg_error_from_syserror (); - log_error ("listen() failed: %s\n", strerror (errno)); - goto leave; - } - - addrlen = sizeof addr; - if (getsockname (HANDLE2SOCKET (state->dataport_listen_fd), - (struct sockaddr *)&addr, &addrlen)) - { - err = gpg_error_from_syserror (); - log_error ("getsockname() failed: %s\n", strerror (errno)); - goto leave; - } - cont->port = ntohs (addr.sin_port); - - if (verbose) - log_info ("server now also listening on port %d\n", cont->port); - snprintf (inqline, sizeof inqline, "CONNECT-TO %d", cont->port); - err = assuan_inquire_ext (ctx, inqline, 0, cmd_newdataport_cont, cont); - if (!err) - return 0; /* Transfer to continuation. */ - - leave: - cont->passthru = 1; - return cmd_newdataport_cont (cont, err, NULL, 0); -} - -/* Continuation used by cmd_newdataport. */ -static gpg_error_t -cmd_newdataport_cont (void *opaque, gpg_error_t err, - unsigned char *data, size_t datalen) -{ - struct cmd_dataport_locals *cont = opaque; - assuan_context_t ctx = cont->ctx; - state_t state = assuan_get_pointer (ctx); - char numbuf[35]; - fdinfo_t fi; - - if (cont->passthru || err) - goto leave; - - err = state->dataport_accept_err; - if (err) - goto leave; - if (state->dataport_listen_fd != ASSUAN_INVALID_FD - || state->dataport_accepted_fd == ASSUAN_INVALID_FD) - { - err = gpg_error (GPG_ERR_MISSING_ACTION); - goto leave; - } - - for (fi = state->dataport_fds; fi; fi = fi->next) - if (fi->fd == ASSUAN_INVALID_FD) - break; - if (!fi) - { - fi = xcalloc (1, sizeof *fi); - fi->next = state->dataport_fds; - state->dataport_fds = fi; - } - fi->fd = state->dataport_accepted_fd; - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - - /* Note that under Windows the FD is the socket descriptor. Socket - descriptors are neither handles nor libc file descriptors. */ - snprintf (numbuf, sizeof numbuf, "%d", HANDLE2SOCKET (fi->fd)); - err = assuan_write_status (ctx, "FDINFO", numbuf); - - leave: - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - } - if (state->dataport_accepted_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_accepted_fd); - state->dataport_accepted_fd = ASSUAN_INVALID_FD; - } - xfree (cont); - return leave_cmd (ctx, err); -} - - - -static const char hlp_dataport[] = - "DATAPORT FD[=<n>]\n" - "\n" - "Set the file descriptor to read and write data via port.\n" - "This is similar to the \"INPUT\" and \"OUTPUT\" commands\n" - "but useful for socketpairs."; -static gpg_error_t -cmd_dataport (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err; - assuan_fd_t fd; - - if (state->dataport_fd != ASSUAN_INVALID_FD) - { - assuan_sock_close (state->dataport_fd); - state->dataport_fd = ASSUAN_INVALID_FD; - } - - err = assuan_command_parse_fd (ctx, line, &fd); - if (!err && fd != ASSUAN_INVALID_FD) - { - fdinfo_t fi; - - state->dataport_fd = fd; - - /* The fd is now in use use - remove it from the unused list. */ - for (fi=state->dataport_fds; fi; fi = fi->next) - if (fi->fd == fd) - fi->fd = ASSUAN_INVALID_FD; - } - - return leave_cmd (ctx, err); -} - - - -static const char hlp_getinfo[] = - "GETINFO <what>\n" - "\n" - "Multipurpose function to return a variety of information.\n" - "Supported values for WHAT are:\n" - "\n" - " version - Return the version of the program.\n" - " pid - Return the process id of the server.\n" - " dataports - Return a list of usused dataports."; -static gpg_error_t -cmd_getinfo (assuan_context_t ctx, char *line) -{ - state_t state = assuan_get_pointer (ctx); - gpg_error_t err = 0; - char numbuf[50]; - - if (!strcmp (line, "version")) - { - const char *s = VERSION; - err = assuan_send_data (ctx, s, strlen (s)); - } - else if (!strcmp (line, "pid")) - { - snprintf (numbuf, sizeof numbuf, "%lu", (unsigned long)getpid ()); - err = assuan_send_data (ctx, numbuf, strlen (numbuf)); - } - else if (!strcmp (line, "dataports")) - { - fdinfo_t fi; - int any = 0; - - for (fi=state->dataport_fds; !err && fi; fi = fi->next) - { - if (fi->fd != ASSUAN_INVALID_FD) - { - snprintf (numbuf, sizeof numbuf, "%s%d", - any? " ":"", HANDLE2SOCKET (fi->fd)); - any = 1; - err = assuan_send_data (ctx, numbuf, strlen (numbuf)); - } - } - } - else - err = gpg_error (GPG_ERR_ASS_PARAMETER); - - return leave_cmd (ctx, err); -} - - - -static const char hlp_shutdown[] = - "SHUTDOWN\n" - "\n" - "Shutdown the server process\n"; -static gpg_error_t -cmd_shutdown (assuan_context_t ctx, char *line) -{ - (void)line; - shutdown_pending = 1; - return leave_cmd (ctx, 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); - const char * const help; - } table[] = - { -#ifdef HAVE_W32CE_SYSTEM - { "LS", cmd_ls, hlp_ls }, - { "RUN", cmd_run, hlp_run }, -#endif - { "PWD", cmd_pwd, hlp_pwd }, - { "CD", cmd_cd, hlp_cd }, - { "ECHO", cmd_echo, hlp_echo }, - { "CAT", cmd_cat, hlp_cat }, - { "NEWDATAPORT", cmd_newdataport, hlp_newdataport }, - { "DATAPORT", cmd_dataport, hlp_dataport }, - { "INPUT", NULL }, - { "OUTPUT", NULL }, - { "GETINFO", cmd_getinfo, hlp_getinfo }, - { "SHUTDOWN", cmd_shutdown, hlp_shutdown }, - { 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, table[i].help); - if (rc) - return rc; - } - return 0; -} - - - -static assuan_fd_t -get_connection_fd (assuan_context_t ctx) -{ - assuan_fd_t fds[5]; - - if (assuan_get_active_fds (ctx, 0, fds, DIM (fds)) < 1) - log_fatal ("assuan_get_active_fds failed\n"); - if (fds[0] == ASSUAN_INVALID_FD) - log_fatal ("assuan_get_active_fds returned invalid conenction fd\n"); - return fds[0]; -} - - -/* Startup the server. */ -static void -server (void) -{ - gpg_error_t err; - assuan_fd_t server_fd; - assuan_sock_nonce_t server_nonce; - int one = 1; - struct sockaddr_in name; - assuan_context_t ctx; - state_t state = NULL; - - err = assuan_new (&ctx); - if (err) - log_fatal ("assuan_new failed: %s\n", gpg_strerror (err)); - - server_fd = assuan_sock_new (PF_INET, SOCK_STREAM, 0); - if (server_fd == ASSUAN_INVALID_FD) - log_fatal ("socket() failed: %s\n", strerror (errno)); - - if (setsockopt (HANDLE2SOCKET (server_fd), - SOL_SOCKET, SO_REUSEADDR, (void*)&one, sizeof one)) - log_error ("setsockopt(SO_REUSEADDR) failed: %s\n", strerror (errno)); - - name.sin_family = AF_INET; - name.sin_port = htons (server_port); - name.sin_addr.s_addr = htonl (INADDR_ANY); - if (assuan_sock_bind (server_fd, (struct sockaddr *) &name, sizeof name)) - log_fatal ("bind() failed: %s\n", strerror (errno)); - if (assuan_sock_get_nonce ((struct sockaddr*)&name, sizeof name, - &server_nonce)) - log_fatal ("assuan_sock_get_nonce failed: %s\n", strerror (errno)); - - /* Register the nonce with the context so that assuan_accept knows - about it. We can't do that directly in assuan_sock_bind because - we want these socket wrappers to be context neutral and drop in - replacement for the standard socket functions. */ - assuan_set_sock_nonce (ctx, &server_nonce); - - if (listen (HANDLE2SOCKET (server_fd), 5)) - log_fatal ("listen() failed: %s\n", strerror (errno)); - - log_info ("server listening on port %hd\n", server_port); - - err = assuan_init_socket_server (ctx, server_fd, 0); - if (err) - log_fatal ("assuan_init_socket_server failed: %s\n", gpg_strerror (err)); - - err = register_commands (ctx); - if (err) - log_fatal ("register_commands failed: %s\n", gpg_strerror(err)); - - if (debug) - assuan_set_log_stream (ctx, stderr); - - assuan_register_reset_notify (ctx, reset_notify); - assuan_register_input_notify (ctx, input_notify); - assuan_register_output_notify (ctx, output_notify); - - - state = new_state (); - - assuan_set_pointer (ctx, state); - - while (!shutdown_pending) - { - int done; - - err = assuan_accept (ctx); - if (err) - { - if (gpg_err_code (err) == GPG_ERR_EOF || err == -1) - log_error ("assuan_accept failed: %s\n", gpg_strerror (err)); - break; - } - - log_info ("client connected. Client's pid is %ld\n", - (long)assuan_get_pid (ctx)); - do - { - /* We need to use select here so that we can accept - supplemental connections from the client as requested by - the DATAPORT command. */ - fd_set rfds; - int connfd, datafd, max_fd; - - connfd = HANDLE2SOCKET (get_connection_fd (ctx)); - FD_ZERO (&rfds); - FD_SET (connfd, &rfds); - max_fd = connfd; - - if (state->dataport_listen_fd != ASSUAN_INVALID_FD) - { - datafd = HANDLE2SOCKET (state->dataport_listen_fd); - FD_SET (datafd, &rfds); - if (datafd > max_fd) - max_fd = datafd; - } - else - datafd = -1; - - if (select (max_fd + 1, &rfds, NULL, NULL, NULL) > 0) - { - if (datafd != -1 && FD_ISSET (datafd, &rfds)) - { - struct sockaddr_in clnt_addr; - socklen_t len = sizeof clnt_addr; - int fd; - - fd = accept (datafd, (struct sockaddr*)&clnt_addr, &len); - if (fd == -1) - { - err = gpg_err_code_from_syserror (); - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - log_error ("accepting on dataport failed: %s\n", - gpg_strerror (err)); - state->dataport_accept_err = err; - err = 0; - } - else - { - /* No more need for the listening socket. */ - assuan_sock_close (state->dataport_listen_fd); - state->dataport_listen_fd = ASSUAN_INVALID_FD; - /* Record the accepted fd. */ - state->dataport_accept_err = 0; - state->dataport_accepted_fd = SOCKET2HANDLE (fd); - } - } - - if (FD_ISSET (connfd, &rfds)) - { - err = assuan_process_next (ctx, &done); - } - } - } - while (!err && !done && !shutdown_pending); - if (err) - log_error ("assuan_process failed: %s\n", gpg_strerror (err)); - } - - assuan_sock_close (server_fd); - assuan_release (ctx); - release_state (state); -} - - - - - -/* - - M A I N - -*/ -int -main (int argc, char **argv) -{ - gpg_error_t err; - int last_argc = -1; - - if (argc) - { - log_set_prefix (*argv); - argc--; argv++; - } - while (argc && last_argc != argc ) - { - last_argc = argc; - if (!strcmp (*argv, "--help")) - { - printf ( - "usage: %s [options]\n" - "\n" - "Options:\n" - " --verbose Show what is going on\n", - log_get_prefix ()); - exit (0); - } - if (!strcmp (*argv, "--verbose")) - { - verbose = 1; - argc--; argv++; - } - else if (!strcmp (*argv, "--debug")) - { - verbose = debug = 1; - argc--; argv++; - } - } - - assuan_set_assuan_log_prefix (log_prefix); - if (debug) - assuan_set_assuan_log_stream (stderr); - - err = assuan_sock_init (); - if (err) - log_fatal ("assuan_sock_init failed: %s\n", gpg_strerror (err)); - - log_info ("server starting...\n"); - server (); - log_info ("server finished\n"); - - assuan_sock_deinit (); - - return errorcount ? 1 : 0; -} diff --git a/tests/common.h b/tests/common.h index c5ce811..dc3c073 100644 --- a/tests/common.h +++ b/tests/common.h @@ -26,11 +26,6 @@ #endif -#ifdef HAVE_W32CE_SYSTEM -#define getpid() GetCurrentProcessId () -#define getenv(a) (NULL) -#endif - #if HAVE_W32_SYSTEM #define SOCKET2HANDLE(s) ((void *)(s)) #define HANDLE2SOCKET(h) ((unsigned int)(h)) diff --git a/tests/pipeconnect.c b/tests/pipeconnect.c index ddb4a06..b477af1 100644 --- a/tests/pipeconnect.c +++ b/tests/pipeconnect.c @@ -247,61 +247,11 @@ run_client (const char *servername) static void parse_std_file_handles (int *argcp, char ***argvp) { -#ifdef HAVE_W32CE_SYSTEM - int argc = *argcp; - char **argv = *argvp; - const char *s; - assuan_fd_t fd; - int i; - int fixup = 0; - - if (!argc) - return; - - for (argc--, argv++; argc; argc--, argv++) - { - s = *argv; - if (*s == '-' && s[1] == '&' && s[2] == 'S' - && (s[3] == '0' || s[3] == '1' || s[3] == '2') - && s[4] == '=' - && (strchr ("-01234567890", s[5]) || !strcmp (s+5, "null"))) - { - if (s[5] == 'n') - fd = ASSUAN_INVALID_FD; - else - fd = _assuan_w32ce_finish_pipe (atoi (s+5), s[3] != '0'); - switch (s[3] - '0') - { - case 0: my_stdin = fd; break; - case 1: my_stdout = fd; break; - case 2: my_stderr = fd; break; - } - - fixup++; - } - else - break; - } - - if (fixup) - { - argc = *argcp; - argc -= fixup; - *argcp = argc; - - argv = *argvp; - for (i=1; i < argc; i++) - argv[i] = argv[i + fixup]; - for (; i < argc + fixup; i++) - argv[i] = NULL; - } -#else (void)argcp; (void)argvp; my_stdin = 0; my_stdout = 1; my_stderr = 2; -#endif } |