aboutsummaryrefslogtreecommitdiffstats
path: root/tests/ce-server.c
diff options
context:
space:
mode:
Diffstat (limited to 'tests/ce-server.c')
-rw-r--r--tests/ce-server.c299
1 files changed, 292 insertions, 7 deletions
diff --git a/tests/ce-server.c b/tests/ce-server.c
index 1f4a46d..06f67af 100644
--- a/tests/ce-server.c
+++ b/tests/ce-server.c
@@ -38,6 +38,11 @@
#endif
#include <errno.h>
+#ifdef HAVE_W32CE_SYSTEM
+#ifndef FILE_ATTRIBUTE_ROMSTATICREF
+#define FILE_ATTRIBUTE_ROMSTATICREF FILE_ATTRIBUTE_OFFLINE
+#endif
+#endif
#include "../src/assuan.h"
@@ -49,8 +54,25 @@ static short server_port = 15898;
/* Flag set to indicate a shutdown. */
static int shutdown_pending;
+/* The local state of a connection. */
+struct state_s
+{
+ char *cwd; /* The current working directory - access using get_cwd(). */
+};
+typedef struct state_s *state_t;
+
+static void
+release_state (state_t state)
+{
+ if (!state)
+ return;
+ xfree (state->cwd);
+ xfree (state);
+}
+
+
/* Helper to print a message while leaving a command. */
static gpg_error_t
leave_cmd (assuan_context_t ctx, gpg_error_t err)
@@ -70,6 +92,114 @@ leave_cmd (assuan_context_t ctx, gpg_error_t 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. */
+ char *p;
+#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;
+}
+
+
+
+
+
@@ -88,13 +218,155 @@ cmd_echo (assuan_context_t ctx, char *line)
}
+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));
-static const char hlp_killserver[] =
- "KILLSERVER\n"
+ return leave_cmd (ctx, err);
+}
+
+
+static const char hlp_cd[] =
+ "CD [dir]\n"
"\n"
- "Kill the server process.\n";
+ "Change the curretn directory of the session.\n";
static gpg_error_t
-cmd_killserver (assuan_context_t ctx, char *line)
+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*/
+
+
+static const char hlp_shutdown[] =
+ "SHUTDOWN\n"
+ "\n"
+ "Shutdown the server process after ending this connection\n";
+static gpg_error_t
+cmd_shutdown (assuan_context_t ctx, char *line)
{
(void)ctx;
(void)line;
@@ -113,10 +385,15 @@ register_commands (assuan_context_t ctx)
const char * const help;
} table[] =
{
+#ifdef HAVE_W32CE_SYSTEM
+ { "LS", cmd_ls, hlp_ls },
+#endif
+ { "PWD", cmd_pwd, hlp_pwd },
+ { "CD", cmd_cd, hlp_cd },
{ "ECHO", cmd_echo, hlp_echo },
{ "INPUT", NULL },
{ "OUTPUT", NULL },
- { "KILLSERVER", cmd_killserver, hlp_killserver },
+ { "SHUTDOWN", cmd_shutdown, hlp_shutdown },
{ NULL, NULL }
};
int i;
@@ -143,6 +420,7 @@ server (void)
int one = 1;
struct sockaddr_in name;
assuan_context_t ctx;
+ state_t state = NULL;
err = assuan_new (&ctx);
if (err)
@@ -184,7 +462,12 @@ server (void)
if (err)
log_fatal ("register_commands failed: %s\n", gpg_strerror(err));
- assuan_set_log_stream (ctx, stderr);
+ if (debug)
+ assuan_set_log_stream (ctx, stderr);
+
+
+ state = xcalloc (1, sizeof state);
+ assuan_set_pointer (ctx, state);
while (!shutdown_pending)
{
@@ -206,6 +489,7 @@ server (void)
assuan_sock_close (server_fd);
assuan_release (ctx);
+ release_state (state);
}
@@ -254,7 +538,8 @@ main (int argc, char **argv)
}
assuan_set_assuan_log_prefix (log_prefix);
- assuan_set_assuan_log_stream (stderr);
+ if (debug)
+ assuan_set_assuan_log_stream (stderr);
err = assuan_sock_init ();
if (err)