summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWayne Davison <wayne@opencoder.net>2020-06-27 10:39:16 -0700
committerWayne Davison <wayne@opencoder.net>2020-06-27 10:51:29 -0700
commit3a6f06003cdd29e9385dba3a9673122e0e356c76 (patch)
treef2a868ffcd2220a4e2cf118217ea416f7e85a9a0
parentf805d1a7f7e6a2d14febc532bb357a10c46c8972 (diff)
downloadrsync-3a6f06003cdd29e9385dba3a9673122e0e356c76.tar.gz
Improve the output when a negotiation fails.
-rw-r--r--cleanup.c7
-rw-r--r--compat.c50
2 files changed, 43 insertions, 14 deletions
diff --git a/cleanup.c b/cleanup.c
index cf8330ac..ab981ec7 100644
--- a/cleanup.c
+++ b/cleanup.c
@@ -221,8 +221,13 @@ NORETURN void _exit_cleanup(int code, const char *file, int line)
/* If line < 0, this exit is after a MSG_ERROR_EXIT event, so
* we don't want to output a duplicate error. */
if ((exit_code && line > 0)
- || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1))))
+ || am_daemon || (logfile_name && (am_server || !INFO_GTE(STATS, 1)))) {
+#ifdef HAVE_USLEEP /* Try for a teeny delay if both sender & receiver are sending a msg at the same time. */
+ if (am_server && exit_code)
+ usleep(50);
+#endif
log_exit(exit_code, exit_file, exit_line);
+ }
#include "case_N.h"
switch_step++;
diff --git a/compat.c b/compat.c
index bf0b4e6d..6d260f0d 100644
--- a/compat.c
+++ b/compat.c
@@ -313,6 +313,9 @@ static int parse_nni_str(struct name_num_obj *nno, const char *from, char *tobuf
return to - tobuf;
}
+/* This routine is always called with a tmpbuf of MAX_NSTR_STRLEN length, but the
+ * buffer may be pre-populated with a "len" length string to use OR a len of -1
+ * to tell us to read a string from the fd. */
static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf, int len)
{
struct name_num_item *ret = NULL;
@@ -328,23 +331,26 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
}
if (len > 0) {
+ struct name_num_item *nni;
int best = nno->saw_len; /* We want best == 1 from the client list, so start with a big number. */
- char *tok;
- if (am_server) {
- int j;
- /* Since we're parsing client names, anything in our list that we parse first is #1. */
- for (j = 0; j < nno->saw_len; j++) {
- if (nno->saw[j])
- nno->saw[j] = 1;
- }
- }
- for (tok = strtok(tmpbuf, " \t"); tok; tok = strtok(NULL, " \t")) {
- struct name_num_item *nni = get_nni_by_name(nno, tok, -1);
+ char *space, *tok = tmpbuf;
+ while (tok) {
+ while (*tok == ' ') tok++; /* Should be unneeded... */
+ if (!*tok)
+ break;
+ if ((space = strchr(tok, ' ')) != NULL)
+ *space = '\0';
+ nni = get_nni_by_name(nno, tok, -1);
+ if (space) {
+ *space = ' ';
+ tok = space + 1;
+ } else
+ tok = NULL;
if (!nni || !nno->saw[nni->num] || best <= nno->saw[nni->num])
continue;
ret = nni;
best = nno->saw[nni->num];
- if (best == 1)
+ if (best == 1 || am_server) /* The server side stops at the first acceptable client choice */
break;
}
if (ret) {
@@ -356,8 +362,26 @@ static void recv_negotiate_str(int f_in, struct name_num_obj *nno, char *tmpbuf,
}
}
- if (!am_server || !do_negotiated_strings)
+ if (!am_server || !do_negotiated_strings) {
+ char *cp = tmpbuf;
+ int j;
rprintf(FERROR, "Failed to negotiate a %s choice.\n", nno->type);
+ rprintf(FERROR, "%s list: %s\n", am_server ? "Client" : "Server", tmpbuf);
+ /* Recreate our original list from the saw values. This can't overflow our huge
+ * buffer because we don't have enough valid entries to get anywhere close. */
+ for (j = 1; j <= nno->saw_len; j++) {
+ struct name_num_item *nni;
+ for (nni = nno->list; nni->name; nni++) {
+ if (nno->saw[nni->num] == j) {
+ *cp++ = ' ';
+ cp += strlcpy(cp, nni->name, MAX_NSTR_STRLEN - (cp - tmpbuf));
+ break;
+ }
+ }
+ }
+ rprintf(FERROR, "%s list:%s\n", am_server ? "Server" : "Client", tmpbuf);
+ }
+
exit_cleanup(RERR_UNSUPPORTED);
}