aboutsummaryrefslogtreecommitdiffstats
path: root/subversion/libsvn_subr/cmdline.c
diff options
context:
space:
mode:
authorPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
committerPeter Wemm <peter@FreeBSD.org>2018-05-08 03:44:38 +0000
commit3faf8d6bffc5d0fb2525ba37bb504c53366caf9d (patch)
tree7e47911263e75034b767fe34b2f8d3d17e91f66d /subversion/libsvn_subr/cmdline.c
parenta55fb3c0d5eca7d887798125d5b95942b1f01d4b (diff)
downloadsrc-3faf8d6bffc5d0fb2525ba37bb504c53366caf9d.tar.gz
src-3faf8d6bffc5d0fb2525ba37bb504c53366caf9d.zip
Import Subversion-1.10.0vendor/subversion/subversion-1.10.0
Notes
Notes: svn path=/vendor/subversion/dist/; revision=333347 svn path=/vendor/subversion/subversion-1.10.0/; revision=333348; tag=vendor/subversion/subversion-1.10.0
Diffstat (limited to 'subversion/libsvn_subr/cmdline.c')
-rw-r--r--subversion/libsvn_subr/cmdline.c229
1 files changed, 173 insertions, 56 deletions
diff --git a/subversion/libsvn_subr/cmdline.c b/subversion/libsvn_subr/cmdline.c
index 9e97bf71f713..2255952189ff 100644
--- a/subversion/libsvn_subr/cmdline.c
+++ b/subversion/libsvn_subr/cmdline.c
@@ -42,6 +42,7 @@
#include <apr_general.h> /* for apr_initialize/apr_terminate */
#include <apr_strings.h> /* for apr_snprintf */
#include <apr_pools.h>
+#include <apr_signal.h>
#include "svn_cmdline.h"
#include "svn_ctype.h"
@@ -342,6 +343,23 @@ svn_cmdline_path_local_style_from_utf8(const char **dest,
}
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;
@@ -821,7 +839,7 @@ most_similar(const char *needle_cstr,
apr_size_t haystack_len,
apr_pool_t *scratch_pool)
{
- const char *max_similar;
+ const char *max_similar = NULL;
apr_size_t max_score = 0;
apr_size_t i;
svn_membuf_t membuf;
@@ -846,10 +864,7 @@ most_similar(const char *needle_cstr,
}
}
- if (max_score)
- return max_similar;
- else
- return NULL;
+ return max_similar;
}
/* Verify that NEEDLE is in HAYSTACK, which contains HAYSTACK_LEN elements. */
@@ -883,7 +898,7 @@ string_in_array(const char *needle,
#include "config_keys.inc"
/* Validate the FILE, SECTION, and OPTION components of CONFIG_OPTION are
- * known. Warn to stderr if not. (An unknown value may be either a typo
+ * 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,
@@ -1171,6 +1186,36 @@ svn_cmdline__print_xml_prop_hash(svn_stringbuf_t **outstr,
}
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)
{
@@ -1179,11 +1224,7 @@ svn_cmdline__be_interactive(svn_boolean_t non_interactive,
* If --force-interactive was passed, always be interactive. */
if (!force_interactive && !non_interactive)
{
-#ifdef WIN32
- return (_isatty(STDIN_FILENO) != 0);
-#else
- return (isatty(STDIN_FILENO) != 0);
-#endif
+ return svn_cmdline__stdin_is_a_terminal();
}
else if (force_interactive)
return TRUE;
@@ -1325,12 +1366,12 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
apr_file_t *tmp_file;
const char *tmpfile_name;
const char *tmpfile_native;
- const char *tmpfile_apr, *base_dir_apr;
+ const char *base_dir_apr;
svn_string_t *translated_contents;
- apr_status_t apr_err, apr_err2;
+ apr_status_t apr_err;
apr_size_t written;
apr_finfo_t finfo_before, finfo_after;
- svn_error_t *err = SVN_NO_ERROR, *err2;
+ svn_error_t *err = SVN_NO_ERROR;
char *old_cwd;
int sys_err;
svn_boolean_t remove_file = TRUE;
@@ -1413,49 +1454,36 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
the file we just created!! ***/
/* Dump initial CONTENTS to TMP_FILE. */
- apr_err = apr_file_write_full(tmp_file, translated_contents->data,
- translated_contents->len, &written);
+ err = svn_io_file_write_full(tmp_file, translated_contents->data,
+ translated_contents->len, &written,
+ pool);
- apr_err2 = apr_file_close(tmp_file);
- if (! apr_err)
- apr_err = apr_err2;
+ 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 (apr_err)
- {
- err = svn_error_wrap_apr(apr_err, _("Can't write to '%s'"),
- tmpfile_name);
- goto cleanup;
- }
-
- err = svn_path_cstring_from_utf8(&tmpfile_apr, tmpfile_name, pool);
if (err)
goto cleanup;
/* Get information about the temporary file before the user has
been allowed to edit its contents. */
- apr_err = apr_stat(&finfo_before, tmpfile_apr,
- APR_FINFO_MTIME, pool);
- if (apr_err)
- {
- err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
- goto cleanup;
- }
+ 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.*/
- apr_file_mtime_set(tmpfile_apr, finfo_before.mtime - 2000, pool);
+ 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. */
- apr_err = apr_stat(&finfo_before, tmpfile_apr,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (apr_err)
- {
- err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
- goto cleanup;
- }
+ 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_utf_cstring_from_utf8(&tmpfile_native, tmpfile_name, pool);
@@ -1483,13 +1511,10 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
}
/* Get information about the temporary file after the assumed editing. */
- apr_err = apr_stat(&finfo_after, tmpfile_apr,
- APR_FINFO_MTIME | APR_FINFO_SIZE, pool);
- if (apr_err)
- {
- err = svn_error_wrap_apr(apr_err, _("Can't stat '%s'"), tmpfile_name);
- goto cleanup;
- }
+ 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) ||
@@ -1527,13 +1552,9 @@ svn_cmdline__edit_string_externally(svn_string_t **edited_contents /* UTF-8! */,
if (remove_file)
{
/* Remove the file from disk. */
- err2 = svn_io_remove_file2(tmpfile_name, FALSE, pool);
-
- /* Only report remove error if there was no previous error. */
- if (! err && err2)
- err = err2;
- else
- svn_error_clear(err2);
+ err = svn_error_compose_create(
+ err,
+ svn_io_remove_file2(tmpfile_name, FALSE, pool));
}
cleanup2:
@@ -1596,3 +1617,99 @@ svn_cmdline__parse_trust_options(
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
+ }
+}