unable to rsync between a PC with cygwin and a unix machine using rsh The problems occurs only when using rsync with rsh from cygwin, because the rsh syntax on cygwin requires that the command shall be quoted. But when rsync fork/exec the rsh the command apears without quote (as set set of argv) and rsh wants the full command as a unique argv entry. Doing that leads to the follwing message: $ rsync -av --no-whole-file --rsync-path=/usr/local/bin/rsync -e rsh Partitions / wtcrep@pdmread1:/local/home/wtcrep/pfc_tst_rsync rsh: unknown option -- server Try `rsh --help' for more information. rsync: read error: Connection reset by peer rsync error: error in rsync protocol data stream (code 12) at /home/lapo/packagi ng/tmp/rsync-2.6.2/io.c(354) In fact fork exec uses done is the following: rsh -l wtcrep pdmread1 /usr/local/bin/rsync --server \ -vvlogDtpr . /local/home/wtcrep/pfc_tst_rsync and in fact what rsh is waiting for is rsh -l wtcrep pdmread1 \ "/usr/local/bin/rsync --server -vvlogDtpr . /local/home/wtcrep/pfc_tst_rsync" I did tests also between 2 Unix workstations (1 HP & 1 Sun) the rsync works fine. There is not the problem described above. I think that rsh implementations on Sun & HP are less strict therefore the problem does not appear. But it should appear on Linux machine that uses the same implementation as Cygwin. I did a change in the main.c to get rid of the problem. My change resides completely in the do_cmd function Hoping this can help. Don't hesitate to contact me if you want additionnal information kind regards Patrick PS: Here is the my code change. -------------------------------------------------------------------------- /* Start the remote shell. cmd may be NULL to use the default. */ static pid_t do_cmd(char *cmd, char *machine, char *user, char *path, int *f_in, int *f_out) { int i, argc = 0; char *args[100]; pid_t ret; char *tok, *dir = NULL; int dash_l_set = 0; /* Start ofc PFC patched section to handle the of the whole command under cygwin rsh ---------------------------------------------------- */ char *other_args[100] ; int other_argc = 0 ; char the_cmd[1024] ; /* End of PFC patched section */ if (!read_batch && !local_server) { char *rsh_env = getenv(RSYNC_RSH_ENV); if (!cmd) cmd = rsh_env; if (!cmd) cmd = RSYNC_RSH; cmd = strdup(cmd); if (!cmd) goto oom; for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) args[argc++] = tok; /* check to see if we've already been given '-l user' in * the remote-shell command */ for (i = 0; i < argc-1; i++) { if (!strcmp(args[i], "-l") && args[i+1][0] != '-') dash_l_set = 1; } #if HAVE_REMSH /* remsh (on HPUX) takes the arguments the other way around */ args[argc++] = machine; if (user && !(daemon_over_rsh && dash_l_set)) { args[argc++] = "-l"; args[argc++] = user; } #else if (user && !(daemon_over_rsh && dash_l_set)) { args[argc++] = "-l"; args[argc++] = user; } args[argc++] = machine; #endif /* ---------------------------------------------------- Start ofc PFC patched section to handle the of the whole command under cygwin rsh ---------------------------------------------------- */ other_args[other_argc++] = rsync_path; if (blocking_io < 0) { char *cp; if ((cp = strrchr(cmd, '/')) != NULL) cp++; else cp = cmd; if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0) blocking_io = 1; } server_options(other_args,&other_argc); } other_args[other_argc++] = "."; if (!daemon_over_rsh && path && *path) other_args[other_argc++] = path; if (!read_batch && !local_server) { strcpy(the_cmd, ""); for (i=0;i<other_argc;i++){ strcat(the_cmd, other_args[i] ) ; strcat(the_cmd, " " ) ; } args[argc++] = the_cmd ; } else { for (i=0;i<other_argc;i++) args[argc++] =other_args[i] ; } ; /* --------------------------- End of PFC patched section --------------------------- */ if (argc >= (int)(sizeof args / sizeof args[0])) { rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n"); exit_cleanup(RERR_MALLOC); /* XXX Need better RERR? */ } args[argc] = NULL; if (verbose > 3) { rprintf(FINFO,"cmd="); for (i=0;i<argc;i++) rprintf(FINFO,"%s ",args[i]); rprintf(FINFO,"\n"); } if (local_server) { if (read_batch) create_flist_from_batch(); /* sets batch_flist */ ret = local_child(argc, args, f_in, f_out, child_main); } else { ret = piped_child(args,f_in,f_out); } if (dir) free(dir); return ret; oom: out_of_memory("do_cmd"); return 0; /* not reached */ } --------------------------------------------------------------------------
This is a bug in cygwin's rsh program that they should fix. When they changed their getopt library to one that does command-line reordering, the same problem showed up for ssh, and I managed to talk them into fixing it. You should request that the same change be made to cygwin's rsh. Work arounds are: - Specify --rsh="rsh --" option to rsync (this should work if they fixed the bug in how the -- option is parsed that was present back when ssh was similarly broken). - Export POSIXLY_CORRECT in your environment. This will prevent all commands from reordering their command-line arguments and affects other program aspects, so this is probably not a good way to go. - Create a shell script that exports POSIXLY_CORRECT and then execs the real rsh with the supplied command-line args. Rename the rsh program and name the new shell script "rsh". This fixes rsh for everyone on your system. Also, please do not put large amounts of patch data in the comments -- that's what attachments are for.
I just tried running rsh on the latest cygwin, and it is not reordering the command-line arguments, so it appears that the cygwin folks have already fixed this problem. Note also that rsh doesn't accept the "--" argument, so that suggestion from my previous comment doesn't work.