diff options
author | Wayne Davison <wayne@opencoder.net> | 2020-06-27 10:39:16 -0700 |
---|---|---|
committer | Wayne Davison <wayne@opencoder.net> | 2020-06-27 10:51:29 -0700 |
commit | 3a6f06003cdd29e9385dba3a9673122e0e356c76 (patch) | |
tree | f2a868ffcd2220a4e2cf118217ea416f7e85a9a0 | |
parent | f805d1a7f7e6a2d14febc532bb357a10c46c8972 (diff) | |
download | rsync-3a6f06003cdd29e9385dba3a9673122e0e356c76.tar.gz |
Improve the output when a negotiation fails.
-rw-r--r-- | cleanup.c | 7 | ||||
-rw-r--r-- | compat.c | 50 |
2 files changed, 43 insertions, 14 deletions
@@ -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++; @@ -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); } |