Author: rinrab
Date: Wed May 28 19:56:36 2025
New Revision: 1925917
URL: http://svn.apache.org/viewvc?rev=1925917&view=rev
Log:
Move svn-editor stuff into a separate file, cmdline_editor.c.
* subversion/libsvn_subr/cmdline.c
(find_editor_binary,
escape_path,
svn_cmdline__edit_file_externally,
svn_cmdline__edit_string_externally): Removed.
* subversion/libsvn_subr/cmdline_editor.c: svn-copied from cmdline.c, keeping
only required things.
(includes): cleanup.
(find_editor_binary,
escape_path,
svn_cmdline__edit_file_externally,
svn_cmdline__edit_string_externally): Copied from cmdline.c.
No functional changes. Let GHA workflows verify it.
Added:
subversion/trunk/subversion/libsvn_subr/cmdline_editor.c
- copied, changed from r1925915,
subversion/trunk/subversion/libsvn_subr/cmdline.c
Modified:
subversion/trunk/subversion/libsvn_subr/cmdline.c
Modified: subversion/trunk/subversion/libsvn_subr/cmdline.c
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cmdline.c?rev=1925917&r1=1925916&r2=1925917&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cmdline.c Wed May 28 19:56:36 2025
@@ -1240,522 +1240,6 @@ svn_cmdline__be_interactive(svn_boolean_
}
-/* Helper for the edit_externally functions. Set *EDITOR to some path to an
- editor binary, in native C string on Unix/Linux platforms and in UTF-8
- string on Windows platform. Sources to search include: the EDITOR_CMD
- argument (if not NULL), $SVN_EDITOR, the runtime CONFIG variable (if CONFIG
- is not NULL), $VISUAL, $EDITOR. Return
- SVN_ERR_CL_NO_EXTERNAL_EDITOR if no binary can be found. */
-static svn_error_t *
-find_editor_binary(const char **editor,
- const char *editor_cmd,
- apr_hash_t *config,
- apr_pool_t *pool)
-{
- const char *e;
- const char *e_cfg;
- struct svn_config_t *cfg;
- apr_status_t status;
-
- /* Use the editor specified on the command line via --editor-cmd, if any. */
-#ifdef WIN32
- /* On Windows, editor_cmd is transcoded to the system active code page
- because we use main() as a entry point without APR's (or our own) wrapper
- in command line tools. */
- if (editor_cmd)
- {
- SVN_ERR(svn_utf_cstring_to_utf8(&e, editor_cmd, pool));
- }
- else
- {
- e = NULL;
- }
-#else
- e = editor_cmd;
-#endif
-
- /* Otherwise look for the Subversion-specific environment variable. */
- if (! e)
- {
- status = apr_env_get((char **)&e, "SVN_EDITOR", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
-
- /* If not found then fall back on the config file. */
- if (! e)
- {
- cfg = config ? svn_hash_gets(config, SVN_CONFIG_CATEGORY_CONFIG) : NULL;
- svn_config_get(cfg, &e_cfg, SVN_CONFIG_SECTION_HELPERS,
- SVN_CONFIG_OPTION_EDITOR_CMD, NULL);
-#ifdef WIN32
- if (e_cfg)
- {
- /* On Windows, we assume that config values are set in system active
- code page, so we need transcode it here. */
- SVN_ERR(svn_utf_cstring_to_utf8(&e, e_cfg, pool));
- }
-#else
- e = e_cfg;
-#endif
- }
-
- /* If not found yet then try general purpose environment variables. */
- if (! e)
- {
- status = apr_env_get((char**)&e, "VISUAL", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
- if (! e)
- {
- status = apr_env_get((char**)&e, "EDITOR", pool);
- if (status || ! *e)
- {
- e = NULL;
- }
- }
-
-#ifdef SVN_CLIENT_EDITOR
- /* If still not found then fall back on the hard-coded default. */
- if (! e)
- e = SVN_CLIENT_EDITOR;
-#endif
-
- /* Error if there is no editor specified */
- if (e)
- {
- const char *c;
-
- for (c = e; *c; c++)
- if (!svn_ctype_isspace(*c))
- break;
-
- if (! *c)
- return svn_error_create
- (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
- _("The EDITOR, SVN_EDITOR or VISUAL environment variable or "
- "'editor-cmd' run-time configuration option is empty or "
- "consists solely of whitespace. Expected a shell command."));
- }
- else
- return svn_error_create
- (SVN_ERR_CL_NO_EXTERNAL_EDITOR, NULL,
- _("None of the environment variables SVN_EDITOR, VISUAL or EDITOR are "
- "set, and no 'editor-cmd' run-time configuration option was found"));
-
- *editor = e;
- return SVN_NO_ERROR;
-}
-
-/* Wrapper around apr_pescape_shell() which also escapes whitespace. */
-static const char *
-escape_path(apr_pool_t *pool, const char *orig_path)
-{
- apr_size_t len, esc_len;
- apr_status_t status;
-
- len = strlen(orig_path);
- esc_len = 0;
-
- status = apr_escape_shell(NULL, orig_path, len, &esc_len);
-
- if (status == APR_NOTFOUND)
- {
- /* No special characters found by APR, so just surround it in double
- quotes in case there is whitespace, which APR (as of 1.6.5) doesn't
- consider special. */
- return apr_psprintf(pool, "\"%s\"", orig_path);
- }
- else
- {
-#ifdef WIN32
- const char *p;
- /* Following the advice from
-
https://docs.microsoft.com/en-us/archive/blogs/twistylittlepassagesallalike/everyone-quotes-command-line-arguments-the-wrong-way
- 1. Surround argument with double-quotes
- 2. Escape backslashes, if they're followed by a double-quote, and
double-quotes
- 3. Escape any metacharacter, including double-quotes, with ^ */
-
- /* Use APR's buffer size as an approximation for how large the escaped
- string should be, plus 4 bytes for the leading/trailing ^" */
- svn_stringbuf_t *buf = svn_stringbuf_create_ensure(esc_len + 4, pool);
- svn_stringbuf_appendcstr(buf, "^\"");
- for (p = orig_path; *p; p++)
- {
- int nr_backslash = 0;
- while (*p && *p == '\\')
- {
- nr_backslash++;
- p++;
- }
-
- if (!*p)
- /* We've reached the end of the argument, so we need 2n backslash
- characters. That will be interpreted as n backslashes and the
- final double-quote character will be interpreted as the final
- string delimiter. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2);
- else if (*p == '"')
- {
- /* Double-quote as part of the argument means we need to double
- any preceding backslashes and then add one to escape the
- double-quote. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash * 2 + 1);
- svn_stringbuf_appendbyte(buf, '^');
- svn_stringbuf_appendbyte(buf, *p);
- }
- else
- {
- /* Since there's no double-quote, we just insert any backslashes
- literally. No escaping needed. */
- svn_stringbuf_appendfill(buf, '\\', nr_backslash);
- if (strchr("()%!^<>&|", *p))
- svn_stringbuf_appendbyte(buf, '^');
- svn_stringbuf_appendbyte(buf, *p);
- }
- }
- svn_stringbuf_appendcstr(buf, "^\"");
- return buf->data;
-#else
- char *path, *p, *esc_path;
-
- /* Account for whitespace, since APR doesn't */
- for (p = (char *)orig_path; *p; p++)
- if (strchr(" \t\n\r", *p))
- esc_len++;
-
- path = apr_pcalloc(pool, esc_len);
- apr_escape_shell(path, orig_path, len, NULL);
-
- p = esc_path = apr_pcalloc(pool, len + esc_len + 1);
- while (*path)
- {
- if (strchr(" \t\n\r", *path))
- *p++ = '\\';
- *p++ = *path++;
- }
-
- return esc_path;
-#endif
- }
-}
-
-svn_error_t *
-svn_cmdline__edit_file_externally(const char *path,
- const char *editor_cmd,
- apr_hash_t *config,
- apr_pool_t *pool)
-{
- const char *editor, *cmd, *base_dir, *file_name, *base_dir_apr;
- const char *file_name_local;
-#ifdef WIN32
- const WCHAR *wcmd;
-#endif
- char *old_cwd;
- int sys_err;
- apr_status_t apr_err;
-
- svn_dirent_split(&base_dir, &file_name, path, pool);
-
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
-
- apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
- if (apr_err)
- return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
-
- /* APR doesn't like "" directories */
- if (base_dir[0] == '\0')
- base_dir_apr = ".";
- else
- SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
-
- apr_err = apr_filepath_set(base_dir_apr, pool);
- if (apr_err)
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
-
- SVN_ERR(svn_path_cstring_from_utf8(&file_name_local,
- escape_path(pool, file_name), pool));
- /* editor is explicitly documented as being interpreted by the user's shell,
- and as such should already be quoted/escaped as needed. */
-#ifndef WIN32
- cmd = apr_psprintf(pool, "%s %s", editor, file_name_local);
- sys_err = system(cmd);
-#else
- cmd = apr_psprintf(pool, "\"%s %s\"", editor, file_name_local);
- SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
- sys_err = _wsystem(wcmd);
-#endif
-
- apr_err = apr_filepath_set(old_cwd, pool);
- if (apr_err)
- svn_handle_error2(svn_error_wrap_apr
- (apr_err, _("Can't restore working directory")),
- stderr, TRUE /* fatal */, "svn: ");
-
- if (sys_err)
- {
- const char *cmd_utf8;
-
- /* Extracting any meaning from sys_err is platform specific, so just
- use the raw value. */
- SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
- return svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"),
- cmd_utf8, sys_err);
- }
-
- return SVN_NO_ERROR;
-}
-
-
-svn_error_t *
-svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8!
*/,
- const char **tmpfile_left /* UTF-8! */,
- const char *editor_cmd,
- const char *base_dir /* UTF-8! */,
- const svn_string_t *contents /* UTF-8! */,
- const char *filename,
- apr_hash_t *config,
- svn_boolean_t as_text,
- const char *encoding,
- apr_pool_t *pool)
-{
- const char *editor;
- const char *cmd;
-#ifdef WIN32
- const WCHAR *wcmd;
-#endif
- apr_file_t *tmp_file;
- const char *tmpfile_name;
- const char *tmpfile_native;
- const char *base_dir_apr;
- svn_string_t *translated_contents;
- apr_status_t apr_err;
- apr_size_t written;
- apr_finfo_t finfo_before, finfo_after;
- svn_error_t *err = SVN_NO_ERROR;
- char *old_cwd;
- int sys_err;
- svn_boolean_t remove_file = TRUE;
-
- SVN_ERR(find_editor_binary(&editor, editor_cmd, config, pool));
-
- /* Convert file contents from UTF-8/LF if desired. */
- if (as_text)
- {
- const char *translated;
- SVN_ERR(svn_subst_translate_cstring2(contents->data, &translated,
- APR_EOL_STR, FALSE,
- NULL, FALSE, pool));
- translated_contents = svn_string_create_empty(pool);
- if (encoding)
- SVN_ERR(svn_utf_cstring_from_utf8_ex2(&translated_contents->data,
- translated, encoding, pool));
- else
- SVN_ERR(svn_utf_cstring_from_utf8(&translated_contents->data,
- translated, pool));
- translated_contents->len = strlen(translated_contents->data);
- }
- else
- translated_contents = svn_string_dup(contents, pool);
-
- /* Move to BASE_DIR to avoid getting characters that need quoting
- into tmpfile_name */
- apr_err = apr_filepath_get(&old_cwd, APR_FILEPATH_NATIVE, pool);
- if (apr_err)
- return svn_error_wrap_apr(apr_err, _("Can't get working directory"));
-
- /* APR doesn't like "" directories */
- if (base_dir[0] == '\0')
- base_dir_apr = ".";
- else
- SVN_ERR(svn_path_cstring_from_utf8(&base_dir_apr, base_dir, pool));
- apr_err = apr_filepath_set(base_dir_apr, pool);
- if (apr_err)
- {
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
- }
-
- /*** From here on, any problems that occur require us to cd back!! ***/
-
- /* Ask the working copy for a temporary file named FILENAME-something. */
- err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
- "" /* dirpath */,
- filename,
- ".tmp",
- svn_io_file_del_none, pool, pool);
-
- if (err && (APR_STATUS_IS_EACCES(err->apr_err) || err->apr_err == EROFS))
- {
- const char *temp_dir_apr;
-
- svn_error_clear(err);
-
- SVN_ERR(svn_io_temp_dir(&base_dir, pool));
-
- SVN_ERR(svn_path_cstring_from_utf8(&temp_dir_apr, base_dir, pool));
- apr_err = apr_filepath_set(temp_dir_apr, pool);
- if (apr_err)
- {
- return svn_error_wrap_apr
- (apr_err, _("Can't change working directory to '%s'"), base_dir);
- }
-
- err = svn_io_open_uniquely_named(&tmp_file, &tmpfile_name,
- "" /* dirpath */,
- filename,
- ".tmp",
- svn_io_file_del_none, pool, pool);
- }
-
- if (err)
- goto cleanup2;
-
- /*** From here on, any problems that occur require us to cleanup
- the file we just created!! ***/
-
- /* Dump initial CONTENTS to TMP_FILE. */
- err = svn_io_file_write_full(tmp_file, translated_contents->data,
- translated_contents->len, &written,
- pool);
-
- err = svn_error_compose_create(err, svn_io_file_close(tmp_file, pool));
-
- /* Make sure the whole CONTENTS were written, else return an error. */
- if (err)
- goto cleanup;
-
- /* Get information about the temporary file before the user has
- been allowed to edit its contents. */
- err = svn_io_stat(&finfo_before, tmpfile_name, APR_FINFO_MTIME, pool);
- if (err)
- goto cleanup;
-
- /* Backdate the file a little bit in case the editor is very fast
- and doesn't change the size. (Use two seconds, since some
- filesystems have coarse granularity.) It's OK if this call
- fails, so we don't check its return value.*/
- err = svn_io_set_file_affected_time(finfo_before.mtime
- - apr_time_from_sec(2),
- tmpfile_name, pool);
- svn_error_clear(err);
-
- /* Stat it again to get the mtime we actually set. */
- err = svn_io_stat(&finfo_before, tmpfile_name,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (err)
- goto cleanup;
-
- /* Prepare the editor command line. */
- err = svn_path_cstring_from_utf8(&tmpfile_native,
- escape_path(pool, tmpfile_name), pool);
- if (err)
- goto cleanup;
-
- /* editor is explicitly documented as being interpreted by the user's shell,
- and as such should already be quoted/escaped as needed. */
-#ifndef WIN32
- cmd = apr_psprintf(pool, "%s %s", editor, tmpfile_native);
-#else
- cmd = apr_psprintf(pool, "\"%s %s\"", editor, tmpfile_native);
-#endif
-
- /* If the caller wants us to leave the file around, return the path
- of the file we'll use, and make a note not to destroy it. */
- if (tmpfile_left)
- {
- *tmpfile_left = svn_dirent_join(base_dir, tmpfile_name, pool);
- remove_file = FALSE;
- }
-
- /* Now, run the editor command line. */
-#ifndef WIN32
- sys_err = system(cmd);
-#else
- SVN_ERR(svn_utf__win32_utf8_to_utf16(&wcmd, cmd, NULL, pool));
- sys_err = _wsystem(wcmd);
-#endif
- if (sys_err != 0)
- {
- const char *cmd_utf8;
-
- /* Extracting any meaning from sys_err is platform specific, so just
- use the raw value. */
- SVN_ERR(svn_path_cstring_to_utf8(&cmd_utf8, cmd, pool));
- err = svn_error_createf(SVN_ERR_EXTERNAL_PROGRAM, NULL,
- _("system('%s') returned %d"),
- cmd_utf8, sys_err);
- goto cleanup;
- }
-
- /* Get information about the temporary file after the assumed editing. */
- err = svn_io_stat(&finfo_after, tmpfile_name,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (err)
- goto cleanup;
-
- /* If the file looks changed... */
- if ((finfo_before.mtime != finfo_after.mtime) ||
- (finfo_before.size != finfo_after.size))
- {
- svn_stringbuf_t *edited_contents_s;
- err = svn_stringbuf_from_file2(&edited_contents_s, tmpfile_name, pool);
- if (err)
- goto cleanup;
-
- *edited_contents = svn_stringbuf__morph_into_string(edited_contents_s);
-
- /* Translate back to UTF8/LF if desired. */
- if (as_text)
- {
- err = svn_subst_translate_string2(edited_contents, NULL, NULL,
- *edited_contents, encoding, FALSE,
- pool, pool);
- if (err)
- {
- err = svn_error_quick_wrap
- (err,
- _("Error normalizing edited contents to internal format"));
- goto cleanup;
- }
- }
- }
- else
- {
- /* No edits seem to have been made */
- *edited_contents = NULL;
- }
-
- cleanup:
- if (remove_file)
- {
- /* Remove the file from disk. */
- err = svn_error_compose_create(
- err,
- svn_io_remove_file2(tmpfile_name, FALSE, pool));
- }
-
- cleanup2:
- /* If we against all probability can't cd back, all further relative
- file references would be screwed up, so we have to abort. */
- apr_err = apr_filepath_set(old_cwd, pool);
- if (apr_err)
- {
- svn_handle_error2(svn_error_wrap_apr
- (apr_err, _("Can't restore working directory")),
- stderr, TRUE /* fatal */, "svn: ");
- }
-
- return svn_error_trace(err);
-}
-
svn_error_t *
svn_cmdline__parse_trust_options(
svn_boolean_t *trust_server_cert_unknown_ca,
Copied: subversion/trunk/subversion/libsvn_subr/cmdline_editor.c (from
r1925915, subversion/trunk/subversion/libsvn_subr/cmdline.c)
URL:
http://svn.apache.org/viewvc/subversion/trunk/subversion/libsvn_subr/cmdline_editor.c?p2=subversion/trunk/subversion/libsvn_subr/cmdline_editor.c&p1=subversion/trunk/subversion/libsvn_subr/cmdline.c&r1=1925915&r2=1925917&rev=1925917&view=diff
==============================================================================
--- subversion/trunk/subversion/libsvn_subr/cmdline.c (original)
+++ subversion/trunk/subversion/libsvn_subr/cmdline_editor.c Wed May 28
19:56:36 2025
@@ -1,5 +1,5 @@
/*
- * cmdline.c : Helpers for command-line programs.
+ * cmdline_editor.c : svn editor implementation.
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@@ -21,1225 +21,31 @@
* ====================================================================
*/
-
-#include <stdlib.h> /* for atexit() */
-#include <stdio.h> /* for setvbuf() */
-#include <locale.h> /* for setlocale() */
-
-#ifndef WIN32
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#else
-#include <crtdbg.h>
-#include <io.h>
-#include <conio.h>
-#endif
-
-#include <apr.h> /* for STDIN_FILENO */
-#include <apr_errno.h> /* for apr_strerror */
#include <apr_version.h>
#if APR_VERSION_AT_LEAST(1,5,0)
#include <apr_escape.h>
#else
#include "private/svn_dep_compat.h"
#endif
-#include <apr_general.h> /* for apr_initialize/apr_terminate */
-#include <apr_strings.h> /* for apr_snprintf */
#include <apr_env.h> /* for apr_env_get */
#include <apr_pools.h>
-#include <apr_signal.h>
#include "svn_cmdline.h"
#include "svn_ctype.h"
-#include "svn_dso.h"
#include "svn_dirent_uri.h"
#include "svn_hash.h"
#include "svn_path.h"
#include "svn_pools.h"
#include "svn_error.h"
-#include "svn_nls.h"
#include "svn_utf.h"
-#include "svn_auth.h"
-#include "svn_xml.h"
-#include "svn_base64.h"
#include "svn_config.h"
-#include "svn_sorts.h"
-#include "svn_props.h"
#include "svn_subst.h"
#include "private/svn_cmdline_private.h"
#include "private/svn_utf_private.h"
-#include "private/svn_sorts_private.h"
-#include "private/svn_string_private.h"
#include "svn_private_config.h"
-#include "win32_crashrpt.h"
-
-#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER < 1400)
-/* Before Visual Studio 2005, the C runtime didn't handle encodings for the
- stdio output handling. */
-#define CMDLINE_USE_CUSTOM_ENCODING
-
-/* The stdin encoding. If null, it's the same as the native encoding. */
-static const char *input_encoding = NULL;
-
-/* The stdout encoding. If null, it's the same as the native encoding. */
-static const char *output_encoding = NULL;
-#elif defined(WIN32) && defined(_MSC_VER)
-/* For now limit this code to Visual C++, as the result is highly dependent
- on the CRT implementation */
-#define USE_WIN32_CONSOLE_SHORTCUT
-
-/* When TRUE, stdout/stderr is directly connected to a console */
-static svn_boolean_t shortcut_stdout_to_console = FALSE;
-static svn_boolean_t shortcut_stderr_to_console = FALSE;
-#endif
-
-
-int
-svn_cmdline_init(const char *progname, FILE *error_stream)
-{
- apr_status_t status;
- apr_pool_t *pool;
- svn_error_t *err;
- char prefix_buf[64]; /* 64 is probably bigger than most program names */
-
-#ifndef WIN32
- {
- struct stat st;
-
- /* The following makes sure that file descriptors 0 (stdin), 1
- (stdout) and 2 (stderr) will not be "reused", because if
- e.g. file descriptor 2 would be reused when opening a file, a
- write to stderr would write to that file and most likely
- corrupt it. */
- if ((fstat(0, &st) == -1 && open("/dev/null", O_RDONLY) == -1) ||
- (fstat(1, &st) == -1 && open("/dev/null", O_WRONLY) == -1) ||
- (fstat(2, &st) == -1 && open("/dev/null", O_WRONLY) == -1))
- {
- if (error_stream)
- fprintf(error_stream, "%s: error: cannot open '/dev/null'\n",
- progname);
- return EXIT_FAILURE;
- }
- }
-#endif
-
- /* Ignore any errors encountered while attempting to change stream
- buffering, as the streams should retain their default buffering
- modes. */
- if (error_stream)
- setvbuf(error_stream, NULL, _IONBF, 0);
-#ifndef WIN32
- setvbuf(stdout, NULL, _IOLBF, 0);
-#endif
-
-#ifdef WIN32
-#ifdef CMDLINE_USE_CUSTOM_ENCODING
- /* Initialize the input and output encodings. */
- {
- static char input_encoding_buffer[16];
- static char output_encoding_buffer[16];
-
- apr_snprintf(input_encoding_buffer, sizeof input_encoding_buffer,
- "CP%u", (unsigned) GetConsoleCP());
- input_encoding = input_encoding_buffer;
-
- apr_snprintf(output_encoding_buffer, sizeof output_encoding_buffer,
- "CP%u", (unsigned) GetConsoleOutputCP());
- output_encoding = output_encoding_buffer;
- }
-#endif /* CMDLINE_USE_CUSTOM_ENCODING */
-
-#ifdef SVN_USE_WIN32_CRASHHANDLER
- if (!getenv("SVN_CMDLINE_DISABLE_CRASH_HANDLER"))
- {
- /* Attach (but don't load) the crash handler */
- SetUnhandledExceptionFilter(svn__unhandled_exception_filter);
-
-#if _MSC_VER >= 1400
- /* ### This should work for VC++ 2002 (=1300) and later */
- /* Show the abort message on STDERR instead of a dialog to allow
- scripts (e.g. our testsuite) to continue after an abort without
- user intervention. Allow overriding for easier debugging. */
- if (!getenv("SVN_CMDLINE_USE_DIALOG_FOR_ABORT"))
- {
- /* In release mode: Redirect abort() errors to stderr */
- _set_error_mode(_OUT_TO_STDERR);
-
- /* In _DEBUG mode: Redirect all debug output (E.g. assert() to
stderr.
- (Ignored in release builds) */
- _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDERR);
- _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDERR);
- _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDERR);
- _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE |
_CRTDBG_MODE_DEBUG);
- _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE |
_CRTDBG_MODE_DEBUG);
- }
-#endif /* _MSC_VER >= 1400 */
- }
-#endif /* SVN_USE_WIN32_CRASHHANDLER */
-
-#endif /* WIN32 */
-
- /* C programs default to the "C" locale. But because svn is supposed
- to be i18n-aware, it should inherit the default locale of its
- environment. */
- if (!setlocale(LC_ALL, "")
- && !setlocale(LC_CTYPE, ""))
- {
- if (error_stream)
- {
- const char *env_vars[] = { "LC_ALL", "LC_CTYPE", "LANG", NULL };
- const char **env_var = &env_vars[0], *env_val = NULL;
- while (*env_var)
- {
- env_val = getenv(*env_var);
- if (env_val && env_val[0])
- break;
- ++env_var;
- }
-
- if (!*env_var)
- {
- /* Unlikely. Can setlocale fail if no env vars are set? */
- --env_var;
- env_val = "not set";
- }
-
- fprintf(error_stream,
- "%s: warning: cannot set LC_CTYPE locale\n"
- "%s: warning: environment variable %s is %s\n"
- "%s: warning: please check that your locale name is
correct\n",
- progname, progname, *env_var, env_val, progname);
- }
- }
-
- /* Initialize the APR subsystem, and register an atexit() function
- to Uninitialize that subsystem at program exit. */
- status = apr_initialize();
- if (status)
- {
- if (error_stream)
- {
- char buf[1024];
- apr_strerror(status, buf, sizeof(buf) - 1);
- fprintf(error_stream,
- "%s: error: cannot initialize APR: %s\n",
- progname, buf);
- }
- return EXIT_FAILURE;
- }
-
- strncpy(prefix_buf, progname, sizeof(prefix_buf) - 3);
- prefix_buf[sizeof(prefix_buf) - 3] = '\0';
- strcat(prefix_buf, ": ");
-
- /* DSO pool must be created before any other pools used by the
- application so that pool cleanup doesn't unload DSOs too
- early. See docstring of svn_dso_initialize2(). */
- if ((err = svn_dso_initialize2()))
- {
- if (error_stream)
- svn_handle_error2(err, error_stream, TRUE, prefix_buf);
-
- svn_error_clear(err);
- return EXIT_FAILURE;
- }
-
- if (0 > atexit(apr_terminate))
- {
- if (error_stream)
- fprintf(error_stream,
- "%s: error: atexit registration failed\n",
- progname);
- return EXIT_FAILURE;
- }
-
- /* Create a pool for use by the UTF-8 routines. It will be cleaned
- up by APR at exit time. */
- pool = svn_pool_create(NULL);
- svn_utf_initialize2(FALSE, pool);
-
- if ((err = svn_nls_init()))
- {
- if (error_stream)
- svn_handle_error2(err, error_stream, TRUE, prefix_buf);
-
- svn_error_clear(err);
- return EXIT_FAILURE;
- }
-
-#ifdef USE_WIN32_CONSOLE_SHORTCUT
- if (_isatty(STDOUT_FILENO))
- {
- DWORD ignored;
- HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
-
- /* stdout is a char device handle, but is it the console? */
- if (GetConsoleMode(stdout_handle, &ignored))
- shortcut_stdout_to_console = TRUE;
-
- /* Don't close stdout_handle */
- }
- if (_isatty(STDERR_FILENO))
- {
- DWORD ignored;
- HANDLE stderr_handle = GetStdHandle(STD_ERROR_HANDLE);
-
- /* stderr is a char device handle, but is it the console? */
- if (GetConsoleMode(stderr_handle, &ignored))
- shortcut_stderr_to_console = TRUE;
-
- /* Don't close stderr_handle */
- }
-#endif
-
- return EXIT_SUCCESS;
-}
-
-
-svn_error_t *
-svn_cmdline_cstring_from_utf8(const char **dest,
- const char *src,
- apr_pool_t *pool)
-{
-#ifdef CMDLINE_USE_CUSTOM_ENCODING
- if (output_encoding != NULL)
- return svn_utf_cstring_from_utf8_ex2(dest, src, output_encoding, pool);
-#endif
-
- return svn_utf_cstring_from_utf8(dest, src, pool);
-}
-
-
-const char *
-svn_cmdline_cstring_from_utf8_fuzzy(const char *src,
- apr_pool_t *pool)
-{
- return svn_utf__cstring_from_utf8_fuzzy(src, pool,
- svn_cmdline_cstring_from_utf8);
-}
-
-
-svn_error_t *
-svn_cmdline_cstring_to_utf8(const char **dest,
- const char *src,
- apr_pool_t *pool)
-{
-#ifdef CMDLINE_USE_CUSTOM_ENCODING
- if (input_encoding != NULL)
- return svn_utf_cstring_to_utf8_ex2(dest, src, input_encoding, pool);
-#endif
-
- return svn_utf_cstring_to_utf8(dest, src, pool);
-}
-
-
-svn_error_t *
-svn_cmdline_path_local_style_from_utf8(const char **dest,
- const char *src,
- apr_pool_t *pool)
-{
- return svn_cmdline_cstring_from_utf8(dest,
- svn_dirent_local_style(src, pool),
- pool);
-}
-
-svn_error_t *
-svn_cmdline__stdin_readline(const char **result,
- apr_pool_t *result_pool,
- apr_pool_t *scratch_pool)
-{
- svn_stringbuf_t *buf = NULL;
- svn_stream_t *stdin_stream = NULL;
- svn_boolean_t oob = FALSE;
-
- SVN_ERR(svn_stream_for_stdin2(&stdin_stream, TRUE, scratch_pool));
- SVN_ERR(svn_stream_readline(stdin_stream, &buf, APR_EOL_STR, &oob,
result_pool));
-
- *result = buf->data;
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline_printf(apr_pool_t *pool, const char *fmt, ...)
-{
- const char *message;
- va_list ap;
-
- /* A note about encoding issues:
- * APR uses the execution character set, but here we give it UTF-8 strings,
- * both the fmt argument and any other string arguments. Since apr_pvsprintf
- * only cares about and produces ASCII characters, this works under the
- * assumption that all supported platforms use an execution character set
- * with ASCII as a subset.
- */
-
- va_start(ap, fmt);
- message = apr_pvsprintf(pool, fmt, ap);
- va_end(ap);
-
- return svn_cmdline_fputs(message, stdout, pool);
-}
-
-svn_error_t *
-svn_cmdline_fprintf(FILE *stream, apr_pool_t *pool, const char *fmt, ...)
-{
- const char *message;
- va_list ap;
-
- /* See svn_cmdline_printf () for a note about character encoding issues. */
-
- va_start(ap, fmt);
- message = apr_pvsprintf(pool, fmt, ap);
- va_end(ap);
-
- return svn_cmdline_fputs(message, stream, pool);
-}
-
-svn_error_t *
-svn_cmdline_fputs(const char *string, FILE* stream, apr_pool_t *pool)
-{
- svn_error_t *err;
- const char *out;
-
-#ifdef USE_WIN32_CONSOLE_SHORTCUT
- /* For legacy reasons the Visual C++ runtime converts output to the console
- from the native 'ansi' encoding, to unicode, then back to 'ansi' and then
- onwards to the console which is implemented as unicode.
-
- For operations like 'svn status -v' this may cause about 70% of the total
- processing time, with absolutely no gain.
-
- For this specific scenario this shortcut exists. It has the nice side
- effect of allowing full unicode output to the console.
-
- Note that this shortcut is not used when the output is redirected, as in
- that case the data is put on the pipe/file after the first conversion to
- ansi. In this case the most expensive conversion is already avoided.
- */
- if ((stream == stdout && shortcut_stdout_to_console)
- || (stream == stderr && shortcut_stderr_to_console))
- {
- WCHAR *result;
-
- if (string[0] == '\0')
- return SVN_NO_ERROR;
-
- SVN_ERR(svn_cmdline_fflush(stream)); /* Flush existing output */
-
- SVN_ERR(svn_utf__win32_utf8_to_utf16(&result, string, NULL, pool));
-
- if (_cputws(result))
- {
- if (apr_get_os_error())
- {
- return svn_error_wrap_apr(apr_get_os_error(), _("Write error"));
- }
- }
-
- return SVN_NO_ERROR;
- }
-#endif
-
- err = svn_cmdline_cstring_from_utf8(&out, string, pool);
-
- if (err)
- {
- svn_error_clear(err);
- out = svn_cmdline_cstring_from_utf8_fuzzy(string, pool);
- }
-
- /* On POSIX systems, errno will be set on an error in fputs, but this might
- not be the case on other platforms. We reset errno and only
- use it if it was set by the below fputs call. Else, we just return
- a generic error. */
- errno = 0;
-
- if (fputs(out, stream) == EOF)
- {
- if (apr_get_os_error()) /* is errno on POSIX */
- {
- /* ### Issue #3014: Return a specific error for broken pipes,
- * ### with a single element in the error chain. */
- if (SVN__APR_STATUS_IS_EPIPE(apr_get_os_error()))
- return svn_error_create(SVN_ERR_IO_PIPE_WRITE_ERROR, NULL, NULL);
- else
- return svn_error_wrap_apr(apr_get_os_error(), _("Write error"));
- }
- else
- return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL, NULL);
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline_fflush(FILE *stream)
-{
- /* See comment in svn_cmdline_fputs about use of errno and stdio. */
- errno = 0;
- if (fflush(stream) == EOF)
- {
- if (apr_get_os_error()) /* is errno on POSIX */
- {
- /* ### Issue #3014: Return a specific error for broken pipes,
- * ### with a single element in the error chain. */
- if (SVN__APR_STATUS_IS_EPIPE(apr_get_os_error()))
- return svn_error_create(SVN_ERR_IO_PIPE_WRITE_ERROR, NULL, NULL);
- else
- return svn_error_wrap_apr(apr_get_os_error(), _("Write error"));
- }
- else
- return svn_error_create(SVN_ERR_IO_WRITE_ERROR, NULL, NULL);
- }
-
- return SVN_NO_ERROR;
-}
-
-const char *svn_cmdline_output_encoding(apr_pool_t *pool)
-{
-#ifdef CMDLINE_USE_CUSTOM_ENCODING
- if (output_encoding)
- return apr_pstrdup(pool, output_encoding);
-#endif
-
- return SVN_APR_LOCALE_CHARSET;
-}
-
-int
-svn_cmdline_handle_exit_error(svn_error_t *err,
- apr_pool_t *pool,
- const char *prefix)
-{
- /* Issue #3014:
- * Don't print anything on broken pipes. The pipe was likely
- * closed by the process at the other end. We expect that
- * process to perform error reporting as necessary.
- *
- * ### This assumes that there is only one error in a chain for
- * ### SVN_ERR_IO_PIPE_WRITE_ERROR. See svn_cmdline_fputs(). */
- if (err->apr_err != SVN_ERR_IO_PIPE_WRITE_ERROR)
- svn_handle_error2(err, stderr, FALSE, prefix);
- svn_error_clear(err);
- if (pool)
- svn_pool_destroy(pool);
- return EXIT_FAILURE;
-}
-
-struct trust_server_cert_non_interactive_baton {
- svn_boolean_t trust_server_cert_unknown_ca;
- svn_boolean_t trust_server_cert_cn_mismatch;
- svn_boolean_t trust_server_cert_expired;
- svn_boolean_t trust_server_cert_not_yet_valid;
- svn_boolean_t trust_server_cert_other_failure;
-};
-
-/* This implements 'svn_auth_ssl_server_trust_prompt_func_t'.
-
- Don't actually prompt. Instead, set *CRED_P to valid credentials
- iff FAILURES is empty or may be accepted according to the flags
- in BATON. If there are any other failure bits, then set *CRED_P
- to null (that is, reject the cert).
-
- Ignore MAY_SAVE; we don't save certs we never prompted for.
-
- Ignore REALM and CERT_INFO,
-
- Ignore any further films by George Lucas. */
-static svn_error_t *
-trust_server_cert_non_interactive(svn_auth_cred_ssl_server_trust_t **cred_p,
- void *baton,
- const char *realm,
- apr_uint32_t failures,
- const svn_auth_ssl_server_cert_info_t
- *cert_info,
- svn_boolean_t may_save,
- apr_pool_t *pool)
-{
- struct trust_server_cert_non_interactive_baton *b = baton;
- apr_uint32_t non_ignored_failures;
- *cred_p = NULL;
-
- /* Mask away bits we are instructed to ignore. */
- non_ignored_failures = failures & ~(
- (b->trust_server_cert_unknown_ca ? SVN_AUTH_SSL_UNKNOWNCA : 0)
- | (b->trust_server_cert_cn_mismatch ? SVN_AUTH_SSL_CNMISMATCH : 0)
- | (b->trust_server_cert_expired ? SVN_AUTH_SSL_EXPIRED : 0)
- | (b->trust_server_cert_not_yet_valid ? SVN_AUTH_SSL_NOTYETVALID : 0)
- | (b->trust_server_cert_other_failure ? SVN_AUTH_SSL_OTHER : 0)
- );
-
- /* If no failures remain, accept the certificate. */
- if (non_ignored_failures == 0)
- {
- *cred_p = apr_pcalloc(pool, sizeof(**cred_p));
- (*cred_p)->may_save = FALSE;
- (*cred_p)->accepted_failures = failures;
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline_create_auth_baton2(svn_auth_baton_t **ab,
- svn_boolean_t non_interactive,
- const char *auth_username,
- const char *auth_password,
- const char *config_dir,
- svn_boolean_t no_auth_cache,
- svn_boolean_t trust_server_cert_unknown_ca,
- svn_boolean_t trust_server_cert_cn_mismatch,
- svn_boolean_t trust_server_cert_expired,
- svn_boolean_t trust_server_cert_not_yet_valid,
- svn_boolean_t trust_server_cert_other_failure,
- svn_config_t *cfg,
- svn_cancel_func_t cancel_func,
- void *cancel_baton,
- apr_pool_t *pool)
-
-{
- svn_boolean_t store_password_val = TRUE;
- svn_boolean_t store_auth_creds_val = TRUE;
- svn_auth_provider_object_t *provider;
- svn_cmdline_prompt_baton2_t *pb = NULL;
-
- /* The whole list of registered providers */
- apr_array_header_t *providers;
-
- /* Populate the registered providers with the platform-specific providers */
- SVN_ERR(svn_auth_get_platform_specific_client_providers(&providers,
- cfg, pool));
-
- /* If we have a cancellation function, cram it and the stuff it
- needs into the prompt baton. */
- if (cancel_func)
- {
- pb = apr_palloc(pool, sizeof(*pb));
- pb->cancel_func = cancel_func;
- pb->cancel_baton = cancel_baton;
- pb->config_dir = config_dir;
- }
-
- if (!non_interactive)
- {
- /* This provider doesn't prompt the user in order to get creds;
- it prompts the user regarding the caching of creds. */
- svn_auth_get_simple_provider2(&provider,
- svn_cmdline_auth_plaintext_prompt,
- pb, pool);
- }
- else
- {
- svn_auth_get_simple_provider2(&provider, NULL, NULL, pool);
- }
-
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- svn_auth_get_username_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- svn_auth_get_ssl_server_trust_file_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- svn_auth_get_ssl_client_cert_file_provider(&provider, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- if (!non_interactive)
- {
- /* This provider doesn't prompt the user in order to get creds;
- it prompts the user regarding the caching of creds. */
- svn_auth_get_ssl_client_cert_pw_file_provider2
- (&provider, svn_cmdline_auth_plaintext_passphrase_prompt,
- pb, pool);
- }
- else
- {
- svn_auth_get_ssl_client_cert_pw_file_provider2(&provider, NULL, NULL,
- pool);
- }
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- if (!non_interactive)
- {
- svn_boolean_t ssl_client_cert_file_prompt;
-
- SVN_ERR(svn_config_get_bool(cfg, &ssl_client_cert_file_prompt,
- SVN_CONFIG_SECTION_AUTH,
-
SVN_CONFIG_OPTION_SSL_CLIENT_CERT_FILE_PROMPT,
- FALSE));
-
- /* Two basic prompt providers: username/password, and just username. */
- svn_auth_get_simple_prompt_provider(&provider,
- svn_cmdline_auth_simple_prompt,
- pb,
- 2, /* retry limit */
- pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- svn_auth_get_username_prompt_provider
- (&provider, svn_cmdline_auth_username_prompt, pb,
- 2, /* retry limit */ pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- /* SSL prompt providers: server-certs and client-cert-passphrases. */
- svn_auth_get_ssl_server_trust_prompt_provider
- (&provider, svn_cmdline_auth_ssl_server_trust_prompt, pb, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- svn_auth_get_ssl_client_cert_pw_prompt_provider
- (&provider, svn_cmdline_auth_ssl_client_cert_pw_prompt, pb, 2, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
-
- /* If configuration allows, add a provider for client-cert path
- prompting, too. */
- if (ssl_client_cert_file_prompt)
- {
- svn_auth_get_ssl_client_cert_prompt_provider
- (&provider, svn_cmdline_auth_ssl_client_cert_prompt, pb, 2, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- }
- }
- else if (trust_server_cert_unknown_ca || trust_server_cert_cn_mismatch ||
- trust_server_cert_expired || trust_server_cert_not_yet_valid ||
- trust_server_cert_other_failure)
- {
- struct trust_server_cert_non_interactive_baton *b;
-
- b = apr_palloc(pool, sizeof(*b));
- b->trust_server_cert_unknown_ca = trust_server_cert_unknown_ca;
- b->trust_server_cert_cn_mismatch = trust_server_cert_cn_mismatch;
- b->trust_server_cert_expired = trust_server_cert_expired;
- b->trust_server_cert_not_yet_valid = trust_server_cert_not_yet_valid;
- b->trust_server_cert_other_failure = trust_server_cert_other_failure;
-
- /* Remember, only register this provider if non_interactive. */
- svn_auth_get_ssl_server_trust_prompt_provider
- (&provider, trust_server_cert_non_interactive, b, pool);
- APR_ARRAY_PUSH(providers, svn_auth_provider_object_t *) = provider;
- }
-
- /* Build an authentication baton to give to libsvn_client. */
- svn_auth_open(ab, providers, pool);
-
- /* Place any default --username or --password credentials into the
- auth_baton's run-time parameter hash. */
- if (auth_username)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DEFAULT_USERNAME,
- auth_username);
- if (auth_password)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DEFAULT_PASSWORD,
- auth_password);
-
- /* Same with the --non-interactive option. */
- if (non_interactive)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_NON_INTERACTIVE, "");
-
- if (config_dir)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_CONFIG_DIR,
- config_dir);
-
- /* Determine whether storing passwords in any form is allowed.
- * This is the deprecated location for this option, the new
- * location is SVN_CONFIG_CATEGORY_SERVERS. The RA layer may
- * override the value we set here. */
- SVN_ERR(svn_config_get_bool(cfg, &store_password_val,
- SVN_CONFIG_SECTION_AUTH,
- SVN_CONFIG_OPTION_STORE_PASSWORDS,
- SVN_CONFIG_DEFAULT_OPTION_STORE_PASSWORDS));
-
- if (! store_password_val)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_DONT_STORE_PASSWORDS, "");
-
- /* Determine whether we are allowed to write to the auth/ area.
- * This is the deprecated location for this option, the new
- * location is SVN_CONFIG_CATEGORY_SERVERS. The RA layer may
- * override the value we set here. */
- SVN_ERR(svn_config_get_bool(cfg, &store_auth_creds_val,
- SVN_CONFIG_SECTION_AUTH,
- SVN_CONFIG_OPTION_STORE_AUTH_CREDS,
- SVN_CONFIG_DEFAULT_OPTION_STORE_AUTH_CREDS));
-
- if (no_auth_cache || ! store_auth_creds_val)
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_NO_AUTH_CACHE, "");
-
-#ifdef SVN_HAVE_GNOME_KEYRING
- svn_auth_set_parameter(*ab, SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC,
- &svn_cmdline__auth_gnome_keyring_unlock_prompt);
-#endif /* SVN_HAVE_GNOME_KEYRING */
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline__getopt_init(apr_getopt_t **os,
- int argc,
- const char *argv[],
- apr_pool_t *pool)
-{
- apr_status_t apr_err = apr_getopt_init(os, pool, argc, argv);
- if (apr_err)
- return svn_error_wrap_apr(apr_err,
- _("Error initializing command line arguments"));
- return SVN_NO_ERROR;
-}
-
-
-void
-svn_cmdline__print_xml_prop(svn_stringbuf_t **outstr,
- const char* propname,
- svn_string_t *propval,
- svn_boolean_t inherited_prop,
- apr_pool_t *pool)
-{
- const char *xml_safe;
- const char *encoding = NULL;
-
- if (*outstr == NULL)
- *outstr = svn_stringbuf_create_empty(pool);
-
- if (svn_xml_is_xml_safe(propval->data, propval->len))
- {
- svn_stringbuf_t *xml_esc = NULL;
- svn_xml_escape_cdata_string(&xml_esc, propval, pool);
- xml_safe = xml_esc->data;
- }
- else
- {
- const svn_string_t *base64ed = svn_base64_encode_string2(propval, TRUE,
- pool);
- encoding = "base64";
- xml_safe = base64ed->data;
- }
-
- if (encoding)
- svn_xml_make_open_tag(
- outstr, pool, svn_xml_protect_pcdata,
- inherited_prop ? "inherited_property" : "property",
- "name", propname,
- "encoding", encoding, SVN_VA_NULL);
- else
- svn_xml_make_open_tag(
- outstr, pool, svn_xml_protect_pcdata,
- inherited_prop ? "inherited_property" : "property",
- "name", propname, SVN_VA_NULL);
-
- svn_stringbuf_appendcstr(*outstr, xml_safe);
-
- svn_xml_make_close_tag(
- outstr, pool,
- inherited_prop ? "inherited_property" : "property");
-
- return;
-}
-
-/* Return the most similar string to NEEDLE in HAYSTACK, which contains
- * HAYSTACK_LEN elements. Return NULL if no string is sufficiently similar.
- */
-/* See svn_cl__similarity_check() for a more general solution. */
-static const char *
-most_similar(const char *needle_cstr,
- const char **haystack,
- apr_size_t haystack_len,
- apr_pool_t *scratch_pool)
-{
- const char *max_similar = NULL;
- apr_size_t max_score = 0;
- apr_size_t i;
- svn_membuf_t membuf;
- svn_string_t *needle_str = svn_string_create(needle_cstr, scratch_pool);
-
- svn_membuf__create(&membuf, 64, scratch_pool);
-
- for (i = 0; i < haystack_len; i++)
- {
- apr_size_t score;
- svn_string_t *hay = svn_string_create(haystack[i], scratch_pool);
-
- score = svn_string__similarity(needle_str, hay, &membuf, NULL);
-
- /* If you update this factor, consider updating
- * svn_cl__similarity_check(). */
- if (score >= (2 * SVN_STRING__SIM_RANGE_MAX + 1) / 3
- && score > max_score)
- {
- max_score = score;
- max_similar = haystack[i];
- }
- }
-
- return max_similar;
-}
-
-/* Verify that NEEDLE is in HAYSTACK, which contains HAYSTACK_LEN elements. */
-static svn_error_t *
-string_in_array(const char *needle,
- const char **haystack,
- apr_size_t haystack_len,
- apr_pool_t *scratch_pool)
-{
- const char *next_of_kin;
- apr_size_t i;
- for (i = 0; i < haystack_len; i++)
- {
- if (!strcmp(needle, haystack[i]))
- return SVN_NO_ERROR;
- }
-
- /* Error. */
- next_of_kin = most_similar(needle, haystack, haystack_len, scratch_pool);
- if (next_of_kin)
- return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Ignoring unknown value '%s'; "
- "did you mean '%s'?"),
- needle, next_of_kin);
- else
- return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Ignoring unknown value '%s'"),
- needle);
-}
-
-#include "config_keys.inc"
-
-/* Validate the FILE, SECTION, and OPTION components of CONFIG_OPTION are
- * known. Return an error if not. (An unknown value may be either a typo
- * or added in a newer minor version of Subversion.) */
-static svn_error_t *
-validate_config_option(svn_cmdline__config_argument_t *config_option,
- apr_pool_t *scratch_pool)
-{
- svn_boolean_t arbitrary_keys = FALSE;
-
- /* TODO: some day, we could also verify that OPTION is valid for SECTION;
- i.e., forbid invalid combinations such as config:auth:diff-extensions. */
-
-#define ARRAYLEN(x) ( sizeof((x)) / sizeof((x)[0]) )
-
- SVN_ERR(string_in_array(config_option->file, svn__valid_config_files,
- ARRAYLEN(svn__valid_config_files),
- scratch_pool));
- SVN_ERR(string_in_array(config_option->section, svn__valid_config_sections,
- ARRAYLEN(svn__valid_config_sections),
- scratch_pool));
-
- /* Don't validate option names for sections such as servers[group],
- * config[tunnels], and config[auto-props] that permit arbitrary options. */
- {
- int i;
-
- for (i = 0; i < ARRAYLEN(svn__empty_config_sections); i++)
- {
- if (!strcmp(config_option->section, svn__empty_config_sections[i]))
- arbitrary_keys = TRUE;
- }
- }
-
- if (! arbitrary_keys)
- SVN_ERR(string_in_array(config_option->option, svn__valid_config_options,
- ARRAYLEN(svn__valid_config_options),
- scratch_pool));
-
-#undef ARRAYLEN
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline__parse_config_option(apr_array_header_t *config_options,
- const char *opt_arg,
- const char *prefix,
- apr_pool_t *pool)
-{
- svn_cmdline__config_argument_t *config_option;
- const char *first_colon, *second_colon, *equals_sign;
- apr_size_t len = strlen(opt_arg);
- if ((first_colon = strchr(opt_arg, ':')) && (first_colon != opt_arg))
- {
- if ((second_colon = strchr(first_colon + 1, ':')) &&
- (second_colon != first_colon + 1))
- {
- if ((equals_sign = strchr(second_colon + 1, '=')) &&
- (equals_sign != second_colon + 1))
- {
- svn_error_t *warning;
-
- config_option = apr_pcalloc(pool, sizeof(*config_option));
- config_option->file = apr_pstrndup(pool, opt_arg,
- first_colon - opt_arg);
- config_option->section = apr_pstrndup(pool, first_colon + 1,
- second_colon - first_colon
- 1);
- config_option->option = apr_pstrndup(pool, second_colon + 1,
- equals_sign - second_colon
- 1);
-
- warning = validate_config_option(config_option, pool);
- if (warning)
- {
- svn_handle_warning2(stderr, warning, prefix);
- svn_error_clear(warning);
- }
-
- if (! (strchr(config_option->option, ':')))
- {
- config_option->value = apr_pstrndup(pool, equals_sign + 1,
- opt_arg + len -
equals_sign - 1);
- APR_ARRAY_PUSH(config_options,
svn_cmdline__config_argument_t *)
- = config_option;
- return SVN_NO_ERROR;
- }
- }
- }
- }
- return svn_error_create(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Invalid syntax of argument of --config-option"));
-}
-
-svn_error_t *
-svn_cmdline__apply_config_options(apr_hash_t *config,
- const apr_array_header_t *config_options,
- const char *prefix,
- const char *argument_name)
-{
- int i;
-
- for (i = 0; i < config_options->nelts; i++)
- {
- svn_config_t *cfg;
- svn_cmdline__config_argument_t *arg =
- APR_ARRAY_IDX(config_options, i,
- svn_cmdline__config_argument_t *);
-
- cfg = svn_hash_gets(config, arg->file);
-
- if (cfg)
- {
- svn_config_set(cfg, arg->section, arg->option, arg->value);
- }
- else
- {
- svn_error_t *err = svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR,
NULL,
- _("Unrecognized file in argument of %s"), argument_name);
-
- svn_handle_warning2(stderr, err, prefix);
- svn_error_clear(err);
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Return a copy, allocated in POOL, of the next line of text from *STR
- * up to and including a CR and/or an LF. Change *STR to point to the
- * remainder of the string after the returned part. If there are no
- * characters to be returned, return NULL; never return an empty string.
- */
-static const char *
-next_line(const char **str, apr_pool_t *pool)
-{
- const char *start = *str;
- const char *p = *str;
-
- /* n.b. Throughout this fn, we never read any character after a '\0'. */
- /* Skip over all non-EOL characters, if any. */
- while (*p != '\r' && *p != '\n' && *p != '\0')
- p++;
- /* Skip over \r\n or \n\r or \r or \n, if any. */
- if (*p == '\r' || *p == '\n')
- {
- char c = *p++;
-
- if ((c == '\r' && *p == '\n') || (c == '\n' && *p == '\r'))
- p++;
- }
-
- /* Now p points after at most one '\n' and/or '\r'. */
- *str = p;
-
- if (p == start)
- return NULL;
-
- return svn_string_ncreate(start, p - start, pool)->data;
-}
-
-const char *
-svn_cmdline__indent_string(const char *str,
- const char *indent,
- apr_pool_t *pool)
-{
- svn_stringbuf_t *out = svn_stringbuf_create_empty(pool);
- const char *line;
-
- while ((line = next_line(&str, pool)))
- {
- svn_stringbuf_appendcstr(out, indent);
- svn_stringbuf_appendcstr(out, line);
- }
- return out->data;
-}
-
-svn_error_t *
-svn_cmdline__print_prop_hash(svn_stream_t *out,
- apr_hash_t *prop_hash,
- svn_boolean_t names_only,
- apr_pool_t *pool)
-{
- apr_array_header_t *sorted_props;
- int i;
-
- sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
- pool);
- for (i = 0; i < sorted_props->nelts; i++)
- {
- svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
- const char *pname = item.key;
- svn_string_t *propval = item.value;
- const char *pname_stdout;
-
- if (svn_prop_needs_translation(pname))
- SVN_ERR(svn_subst_detranslate_string(&propval, propval,
- TRUE, pool));
-
- SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_stdout, pname, pool));
-
- if (out)
- {
- pname_stdout = apr_psprintf(pool, " %s\n", pname_stdout);
- SVN_ERR(svn_subst_translate_cstring2(pname_stdout, &pname_stdout,
- APR_EOL_STR, /* 'native' eol */
- FALSE, /* no repair */
- NULL, /* no keywords */
- FALSE, /* no expansion */
- pool));
-
- SVN_ERR(svn_stream_puts(out, pname_stdout));
- }
- else
- {
- /* ### We leave these printfs for now, since if propval wasn't
- translated above, we don't know anything about its encoding.
- In fact, it might be binary data... */
- printf(" %s\n", pname_stdout);
- }
-
- if (!names_only)
- {
- /* Add an extra newline to the value before indenting, so that
- * every line of output has the indentation whether the value
- * already ended in a newline or not. */
- const char *newval = apr_psprintf(pool, "%s\n", propval->data);
- const char *indented_newval = svn_cmdline__indent_string(newval,
- " ",
- pool);
- if (out)
- {
- SVN_ERR(svn_stream_puts(out, indented_newval));
- }
- else
- {
- printf("%s", indented_newval);
- }
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_error_t *
-svn_cmdline__print_xml_prop_hash(svn_stringbuf_t **outstr,
- apr_hash_t *prop_hash,
- svn_boolean_t names_only,
- svn_boolean_t inherited_props,
- apr_pool_t *pool)
-{
- apr_array_header_t *sorted_props;
- int i;
-
- if (*outstr == NULL)
- *outstr = svn_stringbuf_create_empty(pool);
-
- sorted_props = svn_sort__hash(prop_hash, svn_sort_compare_items_lexically,
- pool);
- for (i = 0; i < sorted_props->nelts; i++)
- {
- svn_sort__item_t item = APR_ARRAY_IDX(sorted_props, i, svn_sort__item_t);
- const char *pname = item.key;
- svn_string_t *propval = item.value;
-
- if (names_only)
- {
- svn_xml_make_open_tag(
- outstr, pool, svn_xml_self_closing,
- inherited_props ? "inherited_property" : "property",
- "name", pname, SVN_VA_NULL);
- }
- else
- {
- const char *pname_out;
-
- if (svn_prop_needs_translation(pname))
- SVN_ERR(svn_subst_detranslate_string(&propval, propval,
- TRUE, pool));
-
- SVN_ERR(svn_cmdline_cstring_from_utf8(&pname_out, pname, pool));
-
- svn_cmdline__print_xml_prop(outstr, pname_out, propval,
- inherited_props, pool);
- }
- }
-
- return SVN_NO_ERROR;
-}
-
-svn_boolean_t
-svn_cmdline__stdin_is_a_terminal(void)
-{
-#ifdef WIN32
- return (_isatty(STDIN_FILENO) != 0);
-#else
- return (isatty(STDIN_FILENO) != 0);
-#endif
-}
-
-svn_boolean_t
-svn_cmdline__stdout_is_a_terminal(void)
-{
-#ifdef WIN32
- return (_isatty(STDOUT_FILENO) != 0);
-#else
- return (isatty(STDOUT_FILENO) != 0);
-#endif
-}
-
-svn_boolean_t
-svn_cmdline__stderr_is_a_terminal(void)
-{
-#ifdef WIN32
- return (_isatty(STDERR_FILENO) != 0);
-#else
- return (isatty(STDERR_FILENO) != 0);
-#endif
-}
-
-svn_boolean_t
-svn_cmdline__be_interactive(svn_boolean_t non_interactive,
- svn_boolean_t force_interactive)
-{
- /* If neither --non-interactive nor --force-interactive was passed,
- * be interactive if stdin is a terminal.
- * If --force-interactive was passed, always be interactive. */
- if (!force_interactive && !non_interactive)
- {
- return svn_cmdline__stdin_is_a_terminal();
- }
- else if (force_interactive)
- return TRUE;
-
- return !non_interactive;
-}
-
-
/* Helper for the edit_externally functions. Set *EDITOR to some path to an
editor binary, in native C string on Unix/Linux platforms and in UTF-8
string on Windows platform. Sources to search include: the EDITOR_CMD
@@ -1755,203 +561,3 @@ svn_cmdline__edit_string_externally(svn_
return svn_error_trace(err);
}
-
-svn_error_t *
-svn_cmdline__parse_trust_options(
- svn_boolean_t *trust_server_cert_unknown_ca,
- svn_boolean_t *trust_server_cert_cn_mismatch,
- svn_boolean_t *trust_server_cert_expired,
- svn_boolean_t *trust_server_cert_not_yet_valid,
- svn_boolean_t *trust_server_cert_other_failure,
- const char *opt_arg,
- apr_pool_t *scratch_pool)
-{
- apr_array_header_t *failures;
- int i;
-
- *trust_server_cert_unknown_ca = FALSE;
- *trust_server_cert_cn_mismatch = FALSE;
- *trust_server_cert_expired = FALSE;
- *trust_server_cert_not_yet_valid = FALSE;
- *trust_server_cert_other_failure = FALSE;
-
- failures = svn_cstring_split(opt_arg, ", \n\r\t\v", TRUE, scratch_pool);
-
- for (i = 0; i < failures->nelts; i++)
- {
- const char *value = APR_ARRAY_IDX(failures, i, const char *);
- if (!strcmp(value, "unknown-ca"))
- *trust_server_cert_unknown_ca = TRUE;
- else if (!strcmp(value, "cn-mismatch"))
- *trust_server_cert_cn_mismatch = TRUE;
- else if (!strcmp(value, "expired"))
- *trust_server_cert_expired = TRUE;
- else if (!strcmp(value, "not-yet-valid"))
- *trust_server_cert_not_yet_valid = TRUE;
- else if (!strcmp(value, "other"))
- *trust_server_cert_other_failure = TRUE;
- else
- return svn_error_createf(SVN_ERR_CL_ARG_PARSING_ERROR, NULL,
- _("Unknown value '%s' for %s.\n"
- "Supported values: %s"),
- value,
- "--trust-server-cert-failures",
- "unknown-ca, cn-mismatch, expired, "
- "not-yet-valid, other");
- }
-
- return SVN_NO_ERROR;
-}
-
-/* Flags to see if we've been cancelled by the client or not. */
-static volatile sig_atomic_t cancelled = FALSE;
-static volatile sig_atomic_t signum_cancelled = 0;
-
-/* The signals we handle. */
-static int signal_map [] = {
- SIGINT
-#ifdef SIGBREAK
- /* SIGBREAK is a Win32 specific signal generated by ctrl-break. */
- , SIGBREAK
-#endif
-#ifdef SIGHUP
- , SIGHUP
-#endif
-#ifdef SIGTERM
- , SIGTERM
-#endif
-};
-
-/* A signal handler to support cancellation. */
-static void
-signal_handler(int signum)
-{
- int i;
-
- apr_signal(signum, SIG_IGN);
- cancelled = TRUE;
- for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i)
- if (signal_map[i] == signum)
- {
- signum_cancelled = i + 1;
- break;
- }
-}
-
-/* An svn_cancel_func_t callback. */
-static svn_error_t *
-check_cancel(void *baton)
-{
- /* Cancel baton should be always NULL in command line client. */
- SVN_ERR_ASSERT(baton == NULL);
- if (cancelled)
- return svn_error_create(SVN_ERR_CANCELLED, NULL, _("Caught signal"));
- else
- return SVN_NO_ERROR;
-}
-
-svn_cancel_func_t
-svn_cmdline__setup_cancellation_handler(void)
-{
- int i;
-
- for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i)
- apr_signal(signal_map[i], signal_handler);
-
-#ifdef SIGPIPE
- /* Disable SIGPIPE generation for the platforms that have it. */
- apr_signal(SIGPIPE, SIG_IGN);
-#endif
-
-#ifdef SIGXFSZ
- /* Disable SIGXFSZ generation for the platforms that have it, otherwise
- * working with large files when compiled against an APR that doesn't have
- * large file support will crash the program, which is uncool. */
- apr_signal(SIGXFSZ, SIG_IGN);
-#endif
-
- return check_cancel;
-}
-
-void
-svn_cmdline__disable_cancellation_handler(void)
-{
- int i;
-
- for (i = 0; i < sizeof(signal_map)/sizeof(signal_map[0]); ++i)
- apr_signal(signal_map[i], SIG_DFL);
-}
-
-void
-svn_cmdline__cancellation_exit(void)
-{
- int signum = 0;
-
- if (cancelled && signum_cancelled)
- signum = signal_map[signum_cancelled - 1];
- if (signum)
- {
-#ifndef WIN32
- apr_signal(signum, SIG_DFL);
- /* No APR support for getpid() so cannot use apr_proc_kill(). */
- kill(getpid(), signum);
-#endif
- }
-}
-
-#if defined(WIN32)
-
-svn_error_t *
-svn_cmdline__win32_get_cstring_argv(const char **cstring_argv_p[],
- int argc,
- const wchar_t *argv[],
- apr_pool_t *result_pool)
-{
- apr_array_header_t *cstring_argv;
- int i;
-
- cstring_argv = apr_array_make(result_pool, argc + 1, sizeof(const char *));
-
- for (i = 0; i < argc; i++)
- {
- const wchar_t *arg = argv[i];
- char *cstring_arg;
- int rv;
-
- /* Passing -1 for the string length guarantees that the returned length
- will account for a terminating null character. */
- rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, NULL, 0, NULL, NULL);
- if (rv <= 0)
- {
- return svn_error_wrap_apr(apr_get_os_error(),
- _("Conversion from UTF-16 failed"));
- }
-
- cstring_arg = apr_palloc(result_pool, rv);
- rv = WideCharToMultiByte(CP_ACP, 0, arg, -1, cstring_arg, rv, NULL,
NULL);
- if (rv <= 0)
- {
- return svn_error_wrap_apr(apr_get_os_error(),
- _("Conversion from UTF-16 failed"));
- }
-
- APR_ARRAY_PUSH(cstring_argv, const char *) = cstring_arg;
- }
-
- APR_ARRAY_PUSH(cstring_argv, const char *) = NULL;
-
- *cstring_argv_p = (const char **)cstring_argv->elts;
- return SVN_NO_ERROR;
-}
-
-#endif
-
-svn_error_t *
-svn_cmdline__default_get_cstring_argv(const char **cstring_argv_p[],
- int argc,
- const char *argv[],
- apr_pool_t *result_pool)
-{
- *cstring_argv_p = argv;
- return SVN_NO_ERROR;
-}