You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by mt...@apache.org on 2010/01/12 20:38:08 UTC
svn commit: r898481 - in /commons/sandbox/runtime/trunk/src/main/native:
include/acr_args.h include/arch/windows/acr_arch_registry.h
os/win32/registry.c shared/args.c shared/ini.c shared/string.c
test/testsuite.c
Author: mturk
Date: Tue Jan 12 19:38:08 2010
New Revision: 898481
URL: http://svn.apache.org/viewvc?rev=898481&view=rev
Log:
Implement Registry interpreter search
Modified:
commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h
commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_registry.h
commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c
commons/sandbox/runtime/trunk/src/main/native/shared/args.c
commons/sandbox/runtime/trunk/src/main/native/shared/ini.c
commons/sandbox/runtime/trunk/src/main/native/shared/string.c
commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c
Modified: commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/acr_args.h Tue Jan 12 19:38:08 2010
@@ -32,24 +32,53 @@
*/
/**
+ * This function expands $(FOO) or ${FOO} to ACR_GetEnv("FOO")
+ * unless the $(FOO) is enclosed inside single quotes.
+ * Input string is freed if expansion took place.
+ *
+ * @param str Input string to expand.
+ * @return expanded string.
+ */
+ACR_DECLARE(char *) ACR_ArgumentExpandA(char *str);
+
+/**
+ * This function expands $(FOO) or ${FOO} to ACR_GetEnv("FOO")
+ * unless the $(FOO) is enclosed inside single quotes.
+ * Input string is freed if expansion took place.
+ *
+ * @param str Input string to expand.
+ * @return expanded string.
+ */
+ACR_DECLARE(wchar_t *) ACR_ArgumentExpandW(wchar_t *str);
+
+/**
* This function provides a way to parse a generic argument string
* into a standard argv[] form of argument list. It respects the
- * usual "whitespace" and quoteing rules. In the future this could
- * be expanded to include support for the apr_call_exec command line
- * string processing (including converting '+' to ' ' and doing the
- * url processing. It does not currently support this function.
+ * usual "whitespace" and quoteing rules.
+ * Params are used for single arguments $1...9 or %1...9 if provided
+ * the argument is replaced with empty string.
+ * Special $* or %* argument is replaced with space separated
+ * params.
+ * After the parameters are processed each argument is expanded
+ * using ACR_ArgumentExpand function.
*
* @param cmdline Input argument string for conversion to argv[].
- * @param argv Output location. This is a pointer to an array
- * of pointers to strings (ie. &(char *argv[]).
- * This value will be allocated from the contexts
- * pool and filled in with copies of the tokens
- * found during parsing of the cmdline.
- * @return number of argumennts in argv array or -1 in case of error.
+ * @param nparams Number of optional parameters.
+ * @param params Optional parameters array.
+ * @param argv Output location. Use ACR_Afree when no longer needed.
+ *
+ * @return number of arguments in argv array or -1 in case of error.
*/
ACR_DECLARE(int) ACR_StringToArgvA(const char *cmdline,
+ int nparams,
+ char *const *params,
char ***argv);
+ACR_DECLARE(int) ACR_StringToArgvW(const wchar_t *cmdline,
+ int nparams,
+ const wchar_t *const *params,
+ wchar_t ***argv);
+
/**
* Merge two argument arrays into one.
* @param argv1 Source argument array.
Modified: commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_registry.h
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_registry.h?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_registry.h (original)
+++ commons/sandbox/runtime/trunk/src/main/native/include/arch/windows/acr_arch_registry.h Tue Jan 12 19:38:08 2010
@@ -69,6 +69,8 @@
wchar_t *name;
} x_registry_t;
+ACR_DECLARE(int) ACR_GetInterpreterFromRegistry(const wchar_t *fname,
+ wchar_t ***args);
#ifdef __cplusplus
}
Modified: commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/os/win32/registry.c Tue Jan 12 19:38:08 2010
@@ -23,12 +23,16 @@
#include "acr_memory.h"
#include "acr_string.h"
#include "acr_tlsd.h"
+#include "acr_args.h"
+#include "acr_port.h"
#include "acr_vm.h"
#include <shlwapi.h>
/* Windows Registry utility functions
*/
+extern wchar_t *SHELL_PATH;
+
static HKEY reg_rootnamed(const char *name)
{
if (!strnicmp(name, "HKLM", 4))
@@ -439,7 +443,7 @@
ACR_SET_OS_ERROR(ACR_EINVAL);
return NULL;
}
- if ((rc = (LONG)RegQueryValueExW(k->key, name, NULL,
+ if ((rc = (int)RegQueryValueExW(k->key, name, NULL,
&rt, NULL, &rl)) != ERROR_SUCCESS) {
goto cleanup;
}
@@ -748,6 +752,139 @@
return i;
}
+ACR_DECLARE(int) ACR_GetInterpreterFromRegistry(const wchar_t *fname,
+ wchar_t ***args)
+{
+ int rc, argc;
+ wchar_t *cmd;
+ wchar_t *exn;
+ wchar_t **argv;
+ wchar_t basename[MAX_PATH] = L"";
+ const wchar_t *ext;
+ const wchar_t *const opt[] = { fname, NULL };
+ x_registry_t k;
+
+ *args = NULL;
+
+ if (*fname == L'.' && *(fname + 1) && iswalnum(*(fname + 1))) {
+ ext = fname;
+ }
+ else {
+ if (!basename_w(fname, basename, MAX_PATH))
+ return ACR_EINVAL;
+
+ ext = wcsrchr(basename, L'.');
+ }
+ if (!ext || !iswalnum(*(ext + 1))) {
+ /* Files without extension should be handled
+ * before calling this function
+ */
+ return ACR_EINVAL;
+ }
+ k.key = NULL;
+ k.name = NULL;
+ k.sam = KEY_READ;
+
+ /* Check if the fname is fname.exe in which case
+ * try the App Path first.
+ */
+ if (wcscmp(basename, fname) == 0 && wcscasecmp(ext, L".EXE") == 0) {
+ /* XXX: What is first checked? SearchPath or App Paths?
+ */
+ exn = ACR_StrvcatW(INVALID_HANDLE_VALUE, THROW_NMARK,
+ NULL,
+ L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths\\",
+ basename,
+ NULL);
+ if (exn == NULL)
+ return ACR_ENOMEM;
+
+ rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, exn, 0, k.sam, &k.key);
+ x_free(exn);
+ if (rc == 0) {
+ /* Key was found
+ */
+ exn = RegistryGetW(&k, NULL, 0);
+ SAFE_CLOSE_KEY(k.key);
+ if (exn) {
+ *args = s_malloc(wchar_t *, 2);
+ (*args)[0] = ACR_ArgumentExpandW(exn);
+ (*args)[1] = NULL;
+
+ return 0;
+ }
+ }
+ SAFE_CLOSE_KEY(k.key);
+ }
+
+ /* Step 1:
+ * Get the Shell handler from the HKCR
+ */
+
+ rc = RegOpenKeyExW(HKEY_CLASSES_ROOT, ext, 0, k.sam, &k.key);
+ if (rc) {
+ /* Extension was't found
+ */
+ return ACR_EBADF;
+ }
+ exn = RegistryGetW(&k, NULL, 0);
+ SAFE_CLOSE_KEY(k.key);
+
+ if (exn == NULL)
+ return ACR_ENOENT;
+
+ /* Step 2:
+ * Get the Shell open command
+ */
+ exn = ACR_StrvcatW(INVALID_HANDLE_VALUE, THROW_NMARK,
+ exn, L"\\SHELL\\OPEN\\COMMAND", NULL);
+ if (exn == NULL)
+ return ACR_ENOMEM;
+
+ rc = RegOpenKeyExW(HKEY_CLASSES_ROOT, exn, 0, k.sam, &k.key);
+ x_free(exn);
+ if (rc) {
+ /* Shell handler was't found
+ * Corrupted registry?
+ */
+ return ACR_ENOENT;
+ }
+
+ cmd = RegistryGetW(&k, NULL, 0);
+ SAFE_CLOSE_KEY(k.key);
+
+ if (cmd == NULL)
+ return ACR_ENOENT;
+
+ if (wcscasecmp(ext, L".BAT") == 0 ||
+ wcscasecmp(ext, L".CMD") == 0) {
+ /* Special case for batch files */
+ wchar_t *sh = ACR_StrvcatW(INVALID_HANDLE_VALUE, THROW_NMARK,
+ NULL,
+ SHELL_PATH,
+ L" /D /C ",
+ cmd,
+ NULL);;
+ x_free(cmd);
+ cmd = sh;
+ }
+ /* Interpreter contains the raw Shell cmdline
+ * AFAICT the format is as follows:
+ * [["]Interpreter.exe["]] [additional cmd line options] [["]%1["]] [["]%*["]]
+ *
+ *
+ */
+ argc = ACR_StringToArgvW(cmd, 1, opt, &argv);
+ x_free(cmd);
+
+ if (argc > 0) {
+ *args = argv;
+ return 0;
+ }
+ else
+ return ACR_EOF;
+}
+
static REGSAM _regsam_translate(int nsam)
{
REGSAM rsam = 0;
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/args.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/args.c?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/args.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/args.c Tue Jan 12 19:38:08 2010
@@ -28,33 +28,64 @@
/**
* Just like strpbrk but it doesn't break if the char
- * is escaped by single quote
+ * is escaped inside single quotes
*/
static char *strpbrk_s(const char *s1, const char *s2)
{
const char *scanp;
+ int inquote = 0;
int c, sc, pc = *s1;
/* Some early sanity check */
if (!s1 || !*s1)
return NULL;
while ((c = *s1++) != 0) {
- for (scanp = s2; (sc = *scanp++) != 0;) {
- if (sc == c && pc != '\'')
+ for (scanp = s2; (sc = *scanp++) != '\0';) {
+ if (sc == c && inquote == 0)
return (char *)(s1 - 1);
}
/* Don't update the previous marker if it was \' already
* In that case we have escaped single quote.
*/
- if (pc == '\\' && c == '\'')
- pc = 0;
- else
- pc = c;
+ if (c == '\'' && pc != '\\')
+ inquote = !inquote;
+ pc = c;
}
return NULL;
}
-static char *_strexpand(char *str)
+#if defined(WIN32)
+static wchar_t *wcspbrk_s(const wchar_t *s1, const wchar_t *s2)
+{
+ const wchar_t *scanp;
+ int inquote = 0;
+ int c, sc, pc = *s1;
+
+ /* Some early sanity check */
+ if (!s1 || !*s1)
+ return NULL;
+ while ((c = *s1++) != 0) {
+ for (scanp = s2; (sc = *scanp++) != L'\0';) {
+ if (sc == c && inquote == 0)
+ return (wchar_t *)(s1 - 1);
+ }
+ /* Don't update the previous marker if it was \' already
+ * In that case we have escaped single quote.
+ */
+ if (c == L'\'' && pc != L'\\')
+ inquote = !inquote;
+ pc = c;
+ }
+ return NULL;
+}
+#endif
+
+/* Expand $(FOO) or ${FOO} to ACR_GetEnv("FOO")
+ * Do not expand if the $(FOO) is enclosed inside
+ * single quotes.
+ * Input string is freed if expansion took place
+ */
+ACR_DECLARE(char *) ACR_ArgumentExpandA(char *str)
{
char *var_pos;
char *var_end;
@@ -68,24 +99,6 @@
return str; /* Guard against zero input */
var_pos = strpbrk_s(var_ptr, "$");
if (!var_pos) {
-#if defined(WIN32)
- char *buf;
- DWORD siz;
-
- siz = ExpandEnvironmentStringsA(str, NULL, 0);
- if (siz) {
- buf = s_malloc(char, siz);
- if (buf == NULL)
- return str;
- siz = ExpandEnvironmentStringsA(str, buf, siz);
- if (!siz) {
- x_free(buf);
- return str;
- }
- x_free(str);
- return buf;
- }
-#endif
/* Nothing to replace.
*/
return str;
@@ -94,34 +107,39 @@
/* Loop for each unescaped $ */
while (var_pos) {
int wch = 0;
+ int sch = *(var_pos);
+ int bch = *(var_pos + 1);
var_end = NULL;
var_rep = NULL;
- if (*(var_pos + 1) == '(') {
+
+ *var_pos++ = '\0';
+ if (bch == '(') {
var_end = strpbrk(var_pos + 1, " })");
wch = ')';
}
- else if (*(var_pos + 1) == '{') {
+ else if (bch == '{') {
var_end = strpbrk(var_pos + 1, " })");
wch = '}';
}
+ /* Add the string before $ */
+ acr_sbuf_cat(&sbuf, var_ptr);
+
if (var_end && *var_end == wch) {
*var_pos++ = '\0';
- *var_pos++ = '\0';
*var_end++ = '\0';
- /* Add the string before $ */
- acr_sbuf_cat(&sbuf, var_ptr);
- /* var_pos holds the variable name */
+ /* var_pos holds the variable name
+ */
var_rep = ACR_EnvGet(var_pos);
if (var_rep) {
+ /* Replace ${FOO} with getenv("FOO")
+ */
acr_sbuf_cat(&sbuf, var_rep);
x_free(var_rep);
}
else {
+ /* Put back the ${FOO} */
acr_sbuf_putc(&sbuf, '$');
- if (wch == '}')
- acr_sbuf_putc(&sbuf, '{');
- else
- acr_sbuf_putc(&sbuf, '(');
+ acr_sbuf_putc(&sbuf, bch);
acr_sbuf_cat(&sbuf, var_pos);
acr_sbuf_putc(&sbuf, wch);
}
@@ -129,8 +147,6 @@
var_pos = strpbrk_s(var_ptr, "$");
}
else {
- *var_pos++ = '\0';
- acr_sbuf_cat(&sbuf, var_ptr);
acr_sbuf_putc(&sbuf, '$');
var_ptr = var_pos;
var_pos = strpbrk_s(var_ptr, "$");
@@ -138,40 +154,142 @@
}
/* Add what's left from the original string */
acr_sbuf_cat(&sbuf, var_ptr);
+ acr_sbuf_rtrim(&sbuf);
acr_sbuf_finish(&sbuf);
x_free(str);
str = acr_sbuf_data(&sbuf);
+#if defined(WIN32)
+ /* Check for the possible %FOO% */
+ if (strchr(str, '%')) {
+ char *buf;
+ DWORD siz;
+
+ siz = ExpandEnvironmentStringsA(str, NULL, 0);
+ if (siz) {
+ buf = s_malloc(char, siz);
+ if (buf == NULL)
+ return str;
+ siz = ExpandEnvironmentStringsA(str, buf, siz);
+ if (!siz) {
+ x_free(buf);
+ return str;
+ }
+ x_free(str);
+ return buf;
+ }
+ }
+#endif
+
return str;
}
-/*
- * This function provides a way to parse a generic argument string
- * into a standard argv[] form of argument list. It respects the
- * usual "whitespace" and quoteing rules. In the future this could
- * be expanded to include support for the apr_call_exec command line
- * string processing (including converting '+' to ' ' and doing the
- * url processing. It does not currently support this function.
- *
- * cmdline: Input argument string for conversion to argv[].
- * argv: Output location. This is a pointer to an array
- * of pointers to strings (ie. &(char *argv[]).
- * This value will be allocated from the contexts
- * pool and filled in with copies of the tokens
- * found during parsing of the cmdline.
+/* Expand $(FOO) or ${FOO} to ACR_GetEnv("FOO")
+ * Do not expand if the $(FOO) is enclosed inside
+ * single quotes.
+ * Input string is freed if expansion took place
*/
-ACR_DECLARE(int) ACR_StringToArgvA(const char *cmdline,
- char ***argv)
+ACR_DECLARE(wchar_t *) ACR_ArgumentExpandW(wchar_t *str)
{
- const char *cp;
- const char *ct;
- char *cleaned, *dirty;
- char *args;
- char *argp;
- char *exps;
- int escaped;
- int isquoted, numargs = 0, argnum;
- size_t offset;
+#if defined(WIN32)
+ /* This function is noop for non windows platforms
+ */
+ wchar_t *var_pos;
+ wchar_t *var_end;
+ wchar_t *var_ptr;
+ wchar_t *var_rep;
+ acr_wbuf_t sbuf;
+
+ var_ptr = str;
+
+ if (!var_ptr || !*var_ptr)
+ return str; /* Guard against zero input */
+ var_pos = wcspbrk_s(var_ptr, L"$");
+ if (!var_pos) {
+ /* Nothing to replace.
+ */
+ return str;
+ }
+ acr_wbuf_new(&sbuf, NULL, wcslen(str), ACR_SBUF_AUTOEXTEND);
+ /* Loop for each unescaped $ */
+ while (var_pos) {
+ wchar_t wch = 0;
+ wchar_t sch = *(var_pos);
+ wchar_t bch = *(var_pos + 1);
+ var_end = NULL;
+ var_rep = NULL;
+
+ *var_pos++ = L'\0';
+ if (bch == L'(') {
+ var_end = wcspbrk(var_pos + 1, L" })");
+ wch = L')';
+ }
+ else if (bch == L'{') {
+ var_end = wcspbrk(var_pos + 1, L" })");
+ wch = L'}';
+ }
+ /* Add the string before $ */
+ acr_wbuf_cat(&sbuf, var_ptr);
+
+ if (var_end && *var_end == wch) {
+ *var_pos++ = L'\0';
+ *var_end++ = L'\0';
+ /* var_pos holds the variable name
+ */
+ var_rep = acr_EnvGetW(var_pos);
+ if (var_rep) {
+ /* Replace ${FOO} with getenv("FOO")
+ */
+ acr_wbuf_cat(&sbuf, var_rep);
+ x_free(var_rep);
+ }
+ else {
+ /* Put back the ${FOO} */
+ acr_wbuf_putc(&sbuf, L'$');
+ acr_wbuf_putc(&sbuf, bch);
+ acr_wbuf_cat(&sbuf, var_pos);
+ acr_wbuf_putc(&sbuf, wch);
+ }
+ var_ptr = var_end;
+ var_pos = wcspbrk_s(var_ptr, L"$");
+ }
+ else {
+ acr_wbuf_putc(&sbuf, L'$');
+ var_ptr = var_pos;
+ var_pos = wcspbrk_s(var_ptr, L"$");
+ }
+ }
+ /* Add what's left from the original string */
+ acr_wbuf_cat(&sbuf, var_ptr);
+ acr_wbuf_rtrim(&sbuf);
+ acr_wbuf_finish(&sbuf);
+ x_free(str);
+
+ str = acr_wbuf_data(&sbuf);
+ /* Check for the possible %FOO% */
+ if (wcschr(str, L'%')) {
+ wchar_t *buf;
+ DWORD siz;
+
+ siz = ExpandEnvironmentStringsW(str, NULL, 0);
+ if (siz) {
+ buf = s_malloc(wchar_t, siz);
+ if (buf == NULL)
+ return str;
+ siz = ExpandEnvironmentStringsW(str, buf, siz);
+ if (!siz) {
+ x_free(buf);
+ return str;
+ }
+ x_free(str);
+ return buf;
+ }
+ }
+#endif
+
+ return str;
+}
+
#define SKIP_WHITESPACEA(C) \
for ( ; *C == ' ' || *C == '\t'; ) { \
C++; \
@@ -210,27 +328,252 @@
* Compresses the arg string to remove all of the '\' escape chars.
* The final argv strings should not have any extra escape chars in it.
*/
-#define REMOVE_ESCAPE_CHARSA(C, D, E) \
- E = 0; \
- while(*D) { \
- if (!E && *D == '\\') { \
- E = 1; \
- } \
- else { \
- E = 0; \
- *C++ = *D; \
- } \
- ++D; \
- } \
+#define REMOVE_ESCAPE_CHARSA(C, D, E) \
+ E = 0; \
+ while(*D) { \
+ if (!E && \
+ (*D == '\\' && (*(D+1) == ' ' || *(D+1) == '\t' || \
+ *(D+1) == '"' || *(D+1) == '\''))) { \
+ E = 1; \
+ } \
+ else { \
+ E = 0; \
+ *C++ = *D; \
+ } \
+ ++D; \
+ } \
+ *C = 0
+
+#define SKIP_WHITESPACEW(C) \
+ for ( ; *C == L' ' || *C == L'\t'; ) { \
+ C++; \
+ };
+
+#define CHECK_QUOTATIONW(C, Q) \
+ Q = 0; \
+ if (*C == L'"') { \
+ Q = 1; \
+ C++; \
+ } \
+ else if (*C == L'\'') { \
+ Q = 2; \
+ C++; \
+ }
+
+/* DETERMINE_NEXTSTRING:
+ * At exit, cp will point to one of the following: NULL, SPACE, TAB or QUOTE.
+ * NULL implies the argument string has been fully traversed.
+ */
+#define DETERMINE_NEXTSTRINGW(C, Q) \
+ for ( ; *C != L'\0'; C++) { \
+ if ((*C == L'\\' && (*(C+1) == L' ' || *(C+1) == L'\t' || \
+ *(C+1) == L'"' || *(C+1) == L'\''))) { \
+ C++; \
+ continue; \
+ } \
+ if ((!Q && (*C == L' ' || *C == L'\t')) \
+ || (Q == 1 && *C == L'"') \
+ || (Q == 2 && *C == L'\'')) { \
+ break; \
+ } \
+ }
+
+/* REMOVE_ESCAPE_CHARS:
+ * Compresses the arg string to remove all of the '\' escape chars.
+ * The final argv strings should not have any extra escape chars in it.
+ */
+#define REMOVE_ESCAPE_CHARSW(C, D, E) \
+ E = 0; \
+ while(*D) { \
+ if (!E && \
+ (*D == L'\\' && (*(D+1) == L' ' || *(D+1) == L'\t' || \
+ *(D+1) == L'"' || *(D+1) == L'\''))) { \
+ E = 1; \
+ } \
+ else { \
+ E = 0; \
+ *C++ = *D; \
+ } \
+ ++D; \
+ } \
*C = 0
+ACR_DECLARE(char *) ACR_StringGetWordA(char **line)
+{
+ char *cleaned;
+ char *dirty;
+ char *argp;
+ char *args = *line;
+ char *word;
+ int escaped;
+ int isquoted;
+
+ if (!*args)
+ return NULL;
+ SKIP_WHITESPACEA(args);
+ CHECK_QUOTATIONA(args, isquoted);
+ argp = args;
+ DETERMINE_NEXTSTRINGA(args, isquoted);
+ word = argp;
+ if (*args)
+ *(args++) = '\0';
+
+ cleaned = dirty = word;
+ REMOVE_ESCAPE_CHARSA(cleaned, dirty, escaped);
+
+ *line = args;
+ return word;
+}
+
+ACR_DECLARE(wchar_t *) ACR_StringGetWordW(wchar_t **line)
+{
+ wchar_t *cleaned;
+ wchar_t *dirty;
+ wchar_t *argp;
+ wchar_t *args = *line;
+ wchar_t *word;
+ int escaped;
+ int isquoted;
+
+ if (!*args)
+ return NULL;
+ SKIP_WHITESPACEW(args);
+ CHECK_QUOTATIONW(args, isquoted);
+ argp = args;
+ DETERMINE_NEXTSTRINGW(args, isquoted);
+ word = argp;
+ if (*args)
+ *(args++) = L'\0';
+
+ cleaned = dirty = word;
+ REMOVE_ESCAPE_CHARSW(cleaned, dirty, escaped);
+
+ *line = args;
+ return word;
+}
+
+/*
+ * This function provides a way to parse a generic argument string
+ * into a standard argv[] form of argument list. It respects the
+ * usual "whitespace" and quoteing rules. In the future this could
+ * be expanded to include support for the apr_call_exec command line
+ * string processing (including converting '+' to ' ' and doing the
+ * url processing. It does not currently support this function.
+ *
+ * cmdline: Input argument string for conversion to argv[].
+ * argv: Output location. This is a pointer to an array
+ * of pointers to strings (ie. &(char *argv[]).
+ * This value will be allocated from the contexts
+ * pool and filled in with copies of the tokens
+ * found during parsing of the cmdline.
+ */
+ACR_DECLARE(int) ACR_StringToArgvA(const char *cmdline,
+ int nparams,
+ char *const *params,
+ char ***argv)
+{
+ const char *cp;
+ char *args;
+ char *cmds;
+ int isquoted, numargs, argnum, argidx = 0;
+
+ SKIP_WHITESPACEA(cmdline);
cp = cmdline;
- SKIP_WHITESPACEA(cp);
- exps = x_strdup(cp);
- if (!exps)
+
+ /* This is ugly and expensive, but if anyone wants to figure a
+ * way to support any number of args without counting and
+ * allocating, please go ahead and change the code.
+ *
+ * Must account for the trailing NULL arg.
+ */
+ numargs = 1;
+ while (*cp != '\0') {
+ CHECK_QUOTATIONA(cp, isquoted);
+ DETERMINE_NEXTSTRINGA(cp, isquoted);
+ if (*cp != '\0') {
+ cp++;
+ }
+ numargs++;
+ SKIP_WHITESPACEA(cp);
+ }
+ if (!argv) {
+ /* We are only interested in the number of arguments
+ */
+ return numargs;
+ }
+ cmds = x_strdup(cmdline);
+ if (!cmds)
+ return -1;
+ *argv = s_calloc(char *, numargs);
+ if (!*argv) {
+ x_free(cmds);
return -1;
- exps = _strexpand(exps);
- ct = exps;
+ }
+ args = cmds;
+ /* determine first argument */
+ for (argnum = 0; argnum < (numargs - 1); argnum++) {
+ char *argument = ACR_StringGetWordA(&args);
+
+ if (!argument)
+ break;
+ if (*argument == '%' || *argument == '$') {
+ cp = argument + 1;
+ if (*cp == '*' && *(cp + 1) == '\0') {
+ if (argidx <= nparams)
+ break;
+ argument = x_strdup(params[argidx++]);
+ for (; argidx < nparams; argidx++) {
+ argument = ACR_StrvcatA(INVALID_HANDLE_VALUE,
+ THROW_NMARK,
+ argument, " ",
+ params[argidx],
+ NULL);
+ }
+ (*argv)[argnum] = ACR_ArgumentExpandA(argument);
+ continue;
+ }
+ else if (acr_isdigit(*cp) && *(cp + 1) == '\0') {
+ argidx = *cp - '0';
+ if (argidx == 0) {
+ if (argnum == 0) {
+ /* Guard against '$0 ...' strings
+ */
+ break;
+ }
+ (*argv)[argnum] = x_strdup((*argv)[0]);
+ continue;
+ }
+ else if (argidx <= nparams) {
+ /* $n <- params[n-1] */
+ argument = (char *)params[argidx-1];
+ }
+ else {
+ /* We have $n without params[n-1]
+ * Stop processing
+ */
+ break;
+ }
+ }
+ }
+ (*argv)[argnum] = ACR_ArgumentExpandA(x_strdup(argument));
+ }
+
+ x_free(cmds);
+ return argnum;
+}
+
+ACR_DECLARE(int) ACR_StringToArgvW(const wchar_t *cmdline,
+ int nparams,
+ const wchar_t *const *params,
+ wchar_t ***argv)
+{
+ const wchar_t *cp;
+ wchar_t *args;
+ wchar_t *cmds;
+ int isquoted, numargs, argnum, argidx = 0;
+
+ SKIP_WHITESPACEW(cmdline);
+ cp = cmdline;
/* This is ugly and expensive, but if anyone wants to figure a
* way to support any number of args without counting and
@@ -239,45 +582,78 @@
* Must account for the trailing NULL arg.
*/
numargs = 1;
- while (*ct != '\0') {
- CHECK_QUOTATIONA(ct, isquoted);
- DETERMINE_NEXTSTRINGA(ct, isquoted);
- if (*ct != '\0') {
- ct++;
+ while (*cp != L'\0') {
+ CHECK_QUOTATIONW(cp, isquoted);
+ DETERMINE_NEXTSTRINGW(cp, isquoted);
+ if (*cp != L'\0') {
+ cp++;
}
numargs++;
- SKIP_WHITESPACEA(ct);
+ SKIP_WHITESPACEW(cp);
}
if (!argv) {
- x_free(exps);
+ /* We are only interested in the number of arguments
+ */
return numargs;
}
- offset = ACR_ALIGN_DEFAULT(numargs * sizeof(char*));
- args = x_malloc(offset + strlen(exps) + 1);
- if (!args) {
- x_free(exps);
+ cmds = x_wcsdup(cmdline);
+ if (!cmds)
+ return -1;
+ *argv = s_calloc(wchar_t *, numargs);
+ if (!*argv) {
+ x_free(cmds);
return -1;
}
- *argv = (char **)args;
- args += offset;
- strcpy(args, exps);
- x_free(exps);
+ args = cmds;
/* determine first argument */
for (argnum = 0; argnum < (numargs-1); argnum++) {
- SKIP_WHITESPACEA(args);
- CHECK_QUOTATIONA(args, isquoted);
- argp = args;
- DETERMINE_NEXTSTRINGA(args, isquoted);
- args++;
- (*argv)[argnum] = argp;
- (*argv)[argnum][args - argp - 1] = '\0';
+ wchar_t *argument = ACR_StringGetWordW(&args);
- cleaned = dirty = (*argv)[argnum];
- REMOVE_ESCAPE_CHARSA(cleaned, dirty, escaped);
+ if (!argument)
+ break;
+ if (*argument == L'%' || *argument == L'$') {
+ cp = argument + 1;
+ if (*cp == L'*' && *(cp + 1) == L'\0') {
+ if (argidx >= nparams)
+ break;
+ argument = x_wcsdup(params[argidx++]);
+ for (; argidx < nparams; argidx++) {
+ argument = ACR_StrvcatW(INVALID_HANDLE_VALUE,
+ THROW_NMARK,
+ argument, L" ",
+ params[argidx],
+ NULL);
+ }
+ (*argv)[argnum] = ACR_ArgumentExpandW(argument);
+ continue;
+ }
+ else if (iswdigit(*cp) && *(cp + 1) == L'\0') {
+ argidx = *cp - L'0';
+ if (argidx == 0) {
+ if (argnum == 0) {
+ /* Guard against '$0 ...' strings
+ */
+ break;
+ }
+ (*argv)[argnum] = x_wcsdup((*argv)[0]);
+ continue;
+ }
+ else if (argidx <= nparams) {
+ /* $n <- params[n-1] */
+ argument = (wchar_t *)params[argidx-1];
+ }
+ else {
+ /* We have $n without params[n-1]
+ * Stop processing
+ */
+ break;
+ }
+ }
+ }
+ (*argv)[argnum] = ACR_ArgumentExpandW(x_wcsdup(argument));
}
- /* Always NULL terminate the array */
- (*argv)[argnum] = NULL;
+ x_free(cmds);
return argnum;
}
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/ini.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/ini.c?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/ini.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/ini.c Tue Jan 12 19:38:08 2010
@@ -435,28 +435,28 @@
/**
* Just like strpbrk but it doesn't break if the char
- * is escaped by single quote
+ * is escaped inside single quotes.
*/
static char *strpbrk_s(const char *s1, const char *s2)
{
const char *scanp;
+ int inquote = 0;
int c, sc, pc = *s1;
/* Some early sanity check */
if (!s1 || !*s1)
return NULL;
while ((c = *s1++) != 0) {
- for (scanp = s2; (sc = *scanp++) != 0;) {
- if (sc == c && pc != '\'')
+ for (scanp = s2; (sc = *scanp++) != '\0';) {
+ if (sc == c && inquote == 0)
return (char *)(s1 - 1);
}
/* Don't update the previous marker if it was \' already
* In that case we have escaped single quote.
*/
- if (pc == '\\' && c == '\'')
- pc = 0;
- else
- pc = c;
+ if (c == '\'' && pc != '\\')
+ inquote = !inquote;
+ pc = c;
}
return NULL;
}
Modified: commons/sandbox/runtime/trunk/src/main/native/shared/string.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/shared/string.c?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/shared/string.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/shared/string.c Tue Jan 12 19:38:08 2010
@@ -1026,9 +1026,10 @@
else {
len = strlen(argp);
}
-
- memcpy(cp, argp, len);
- cp += len;
+ if (len) {
+ memcpy(cp, argp, len);
+ cp += len;
+ }
}
va_end(adummy);
@@ -1063,7 +1064,11 @@
/* Allocate the required string */
- res = (wchar_t *)ACR_Malloc(_E, file, line, (len + 1) * sizeof(wchar_t));
+ res = ACR_MALLOC(wchar_t, len + 1);
+ if (!res) {
+ x_free(p);
+ return NULL;
+ }
cp = res;
if (p) {
memcpy(cp, p, wcslen(p) * sizeof(wchar_t));
Modified: commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c
URL: http://svn.apache.org/viewvc/commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c?rev=898481&r1=898480&r2=898481&view=diff
==============================================================================
--- commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c (original)
+++ commons/sandbox/runtime/trunk/src/main/native/test/testsuite.c Tue Jan 12 19:38:08 2010
@@ -56,6 +56,7 @@
#define _TXT(X) L ## X
static LPWSTR wide_args[64];
static LPWSTR *wargv = NULL;
+#include "acr_arch_registry.h"
#else
extern mode_t acr_default_umask;
extern mode_t acr_default_perms;
@@ -656,6 +657,32 @@
return 0;
}
+#if defined(WIN32)
+static int test_registry(int argc, const char *const argv[])
+{
+ wchar_t **args;
+ wchar_t **ap;
+ int rc;
+
+ if (argc < 1) {
+ return ACR_EINVAL;
+ }
+ rc = ACR_GetInterpreterFromRegistry(wargv[0], &args);
+ if (rc) {
+ fprintf(stderr, "Failed with %d\n", rc);
+ return rc;
+ }
+ ap = args;
+ while(*ap) {
+ fprintf(stdout, "ARG : %S.\n", *ap);
+ ap++;
+ }
+ ACR_Afree(INVALID_HANDLE_VALUE, THROW_FMARK, args);
+ return 0;
+}
+
+#endif
+
int main(int argc, const char *const argv[])
{
int rv = 0;
@@ -767,6 +794,12 @@
else if (!strcasecmp(run_test, "daemon")) {
rv = test_exec4(argc, argv);
}
+#if defined(WIN32)
+ else if (!strcasecmp(run_test, "registry")) {
+ rv = test_registry(argc, argv);
+ }
+
+#endif
}
cleanup: