+ if (argc == 0) {
+ list_only = 1;
+ }
+
+ if (!write_batch)
+ send_exclude_list(f_out);
+
+ if (filesfrom_fd >= 0) {
+ io_set_filesfrom_fds(filesfrom_fd, f_out);
+ filesfrom_fd = -1;
+ }
+
+ flist = recv_file_list(f_in);
+ if (!flist || flist->count == 0) {
+ rprintf(FINFO, "client: nothing to do: "
+ "perhaps you need to specify some filenames or "
+ "the --recursive option?\n");
+ exit_cleanup(0);
+ }
+
+ local_name = get_local_name(flist,argv[0]);
+
+ status2 = do_recv(f_in,f_out,flist,local_name);
+
+ if (pid != -1) {
+ if (verbose > 3)
+ rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);
+ io_flush(FULL_FLUSH);
+ wait_process(pid, &status);
+ }
+
+ return MAX(status, status2);
+}
+
+static int copy_argv (char *argv[])
+{
+ int i;
+
+ for (i = 0; argv[i]; i++) {
+ if (!(argv[i] = strdup(argv[i]))) {
+ rprintf (FERROR, "out of memory at %s(%d)\n",
+ __FILE__, __LINE__);
+ return RERR_MALLOC;
+ }
+ }
+
+ return 0;
+}
+
+
+/**
+ * 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;
+
+ /* rsync:// always uses rsync server over direct socket connection */
+ if (strncasecmp(URL_PREFIX, argv[0], strlen(URL_PREFIX)) == 0) {
+ char *host, *path;
+
+ host = argv[0] + strlen(URL_PREFIX);
+ p = strchr(host,'/');
+ if (p) {
+ *p = 0;
+ path = p+1;
+ } else {
+ path = "";
+ }
+ p = strchr(host,':');
+ if (p) {
+ rsync_port = atoi(p+1);
+ *p = 0;
+ }
+ return start_socket_client(host, path, argc-1, argv+1);
+ }
+
+ if (!read_batch) {
+ p = find_colon(argv[0]);
+ if (p) {
+ if (remote_filesfrom_file
+ && remote_filesfrom_file != files_from + 1
+ && strncmp(files_from, argv[0], p-argv[0]+1) != 0) {
+ rprintf(FERROR,
+ "--files-from hostname is not transfer hostname\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (p[1] == ':') { /* double colon */
+ *p = 0;
+ if (!shell_cmd) {
+ return start_socket_client(argv[0], p+2,
+ argc-1, argv+1);
+ }
+ p++;
+ daemon_over_rsh = 1;
+ }
+
+ if (argc < 1) {
+ usage(FERROR);
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ am_sender = 0;
+ *p = 0;
+ shell_machine = argv[0];
+ shell_path = p+1;
+ argc--;
+ argv++;
+ } else {
+ am_sender = 1;
+
+ /* rsync:// destination uses rsync server over direct socket */
+ if (strncasecmp(URL_PREFIX, argv[argc-1], strlen(URL_PREFIX)) == 0) {
+ char *host, *path;
+
+ host = argv[argc-1] + strlen(URL_PREFIX);
+ p = strchr(host,'/');
+ if (p) {
+ *p = 0;
+ path = p+1;
+ } else {
+ path = "";
+ }
+ p = strchr(host,':');
+ if (p) {
+ rsync_port = atoi(p+1);
+ *p = 0;
+ }
+ return start_socket_client(host, path, argc-1, argv);
+ }
+
+ p = find_colon(argv[argc-1]);
+ if (p && remote_filesfrom_file
+ && remote_filesfrom_file != files_from + 1
+ && strncmp(files_from, argv[argc-1], p-argv[argc-1]+1) != 0) {
+ rprintf(FERROR,
+ "--files-from hostname is not transfer hostname\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ if (!p) {
+ local_server = 1;
+ if (remote_filesfrom_file) {
+ rprintf(FERROR,
+ "--files-from is remote but transfer is local\n");
+ exit_cleanup(RERR_SYNTAX);
+ }
+ } else if (p[1] == ':') { /* double colon */
+ *p = 0;
+ if (!shell_cmd) {
+ return start_socket_client(argv[argc-1], p+2,
+ argc-1, argv);
+ }
+ p++;
+ daemon_over_rsh = 1;
+ }
+
+ if (argc < 2) {
+ usage(FERROR);
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ if (local_server) {
+ shell_machine = NULL;
+ shell_path = argv[argc-1];
+ } else {
+ *p = 0;
+ shell_machine = argv[argc-1];
+ shell_path = p+1;
+ }
+ argc--;
+ }
+ } else {
+ am_sender = 1;
+ local_server = 1;
+ shell_path = argv[argc-1];
+ }
+
+ 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?shell_cmd:"",
+ shell_machine?shell_machine:"",
+ shell_user?shell_user:"",
+ shell_path?shell_path:"");
+ }
+
+ if (!am_sender && argc > 1) {
+ usage(FERROR);
+ exit_cleanup(RERR_SYNTAX);
+ }