/* This routine tries to write out an equivalent --read-batch command * given the user's --write-batch args. However, it doesn't really * understand most of the options, so it uses some overly simple * heuristics to munge the command line into something that will * (hopefully) work. */ void write_batch_shell_file(int argc, char *argv[], int file_arg_cnt) { int fd, i, len, err = 0; char *p, filename[MAXPATHLEN]; stringjoin(filename, sizeof filename, batch_name, ".sh", NULL); fd = do_open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IXUSR); if (fd < 0) { rsyserr(FERROR, errno, "Batch file %s open error", filename); exit_cleanup(RERR_FILESELECT); } /* Write argvs info to BATCH.sh file */ if (write_arg(fd, argv[0]) < 0) err = 1; if (filter_list.head) { if (protocol_version >= 29) write_sbuf(fd, " --filter=._-"); else write_sbuf(fd, " --exclude-from=-"); } for (i = 1; i < argc - file_arg_cnt; i++) { p = argv[i]; if (strncmp(p, "--files-from", 12) == 0 || strncmp(p, "--filter", 8) == 0 || strncmp(p, "--include", 9) == 0 || strncmp(p, "--exclude", 9) == 0) { if (strchr(p, '=') == NULL) i++; continue; } if (strcmp(p, "-f") == 0) { i++; continue; } if (write(fd, " ", 1) != 1) err = 1; if (strncmp(p, "--write-batch", len = 13) == 0 || strncmp(p, "--only-write-batch", len = 18) == 0) { if (write(fd, "--read-batch", 12) != 12) err = 1; if (p[len] == '=') { if (write(fd, "=", 1) != 1 || write_arg(fd, p + len + 1) < 0) err = 1; } } else { if (write_arg(fd, p) < 0) err = 1; } } if (!(p = check_for_hostspec(argv[argc - 1], &p, &i))) p = argv[argc - 1]; if (write(fd, " ${1:-", 6) != 6 || write_arg(fd, p) < 0) err = 1; write_byte(fd, '}'); if (filter_list.head) write_filter_rules(fd); if (write(fd, "\n", 1) != 1 || close(fd) < 0 || err) { rsyserr(FERROR, errno, "Batch file %s write error", filename); exit_cleanup(RERR_FILEIO); } }
/** * Start a client for either type of remote connection. Work out * whether the arguments request a remote shell or rsyncd connection, * and call the appropriate connection function, then run_client. * * Calls either start_socket_client (for sockets) or do_cmd and * client_run (for ssh). **/ static int start_client(int argc, char *argv[]) { char *p; char *shell_machine = NULL; char *shell_path = NULL; char *shell_user = NULL; int ret; pid_t pid; int f_in,f_out; int rc; /* Don't clobber argv[] so that ps(1) can still show the right * command line. */ if ((rc = copy_argv(argv))) return rc; if (!read_batch) { /* for read_batch, NO source is specified */ argc--; shell_path = check_for_hostspec(argv[0], &shell_machine, &rsync_port); if (shell_path) { /* source is remote */ argv++; if (filesfrom_host && *filesfrom_host && strcmp(filesfrom_host, shell_machine) != 0) { rprintf(FERROR, "--files-from hostname is not the same as the transfer hostname\n"); exit_cleanup(RERR_SYNTAX); } if (rsync_port) { if (!shell_cmd) { return start_socket_client(shell_machine, shell_path, argc, argv); } daemon_over_rsh = 1; } am_sender = 0; } else { /* source is local, check dest arg */ am_sender = 1; if (argc < 1) { /* destination required */ usage(FERROR); exit_cleanup(RERR_SYNTAX); } shell_path = check_for_hostspec(argv[argc], &shell_machine, &rsync_port); if (shell_path && filesfrom_host && *filesfrom_host && strcmp(filesfrom_host, shell_machine) != 0) { rprintf(FERROR, "--files-from hostname is not the same as the transfer hostname\n"); exit_cleanup(RERR_SYNTAX); } if (!shell_path) { /* no hostspec found, so src & dest are local */ local_server = 1; if (filesfrom_host) { rprintf(FERROR, "--files-from cannot be remote when the transfer is local\n"); exit_cleanup(RERR_SYNTAX); } shell_machine = NULL; shell_path = argv[argc]; } else if (rsync_port) { if (!shell_cmd) { return start_socket_client(shell_machine, shell_path, argc, argv); } daemon_over_rsh = 1; } } } else { /* read_batch */ local_server = 1; shell_path = argv[argc-1]; if (check_for_hostspec(shell_path, &shell_machine, &rsync_port)) { rprintf(FERROR, "remote destination is not allowed with --read-batch\n"); exit_cleanup(RERR_SYNTAX); } } if (shell_machine) { p = strrchr(shell_machine,'@'); if (p) { *p = 0; shell_user = shell_machine; shell_machine = p+1; } } if (verbose > 3) { rprintf(FINFO,"cmd=%s machine=%s user=%s path=%s\n", shell_cmd ? safe_fname(shell_cmd) : "", shell_machine ? safe_fname(shell_machine) : "", shell_user ? safe_fname(shell_user) : "", shell_path ? safe_fname(shell_path) : ""); } /* for remote source, only single dest arg can remain ... */ if (!am_sender && argc > 1) { usage(FERROR); exit_cleanup(RERR_SYNTAX); } /* ... or no dest at all */ if (!am_sender && argc == 0) list_only |= 1; pid = do_cmd(shell_cmd,shell_machine,shell_user,shell_path, &f_in,&f_out); /* if we're running an rsync server on the remote host over a * remote shell command, we need to do the RSYNCD protocol first */ if (daemon_over_rsh) { int tmpret; tmpret = start_inband_exchange(shell_user, shell_path, f_in, f_out, argc); if (tmpret < 0) return tmpret; } ret = client_run(f_in, f_out, pid, argc, argv); fflush(stdout); fflush(stderr); return ret; }