- int pid, status = 0, status2 = 0;
- int opt;
- int option_index;
- char *shell_cmd = NULL;
- char *shell_machine = NULL;
- char *shell_path = NULL;
- char *shell_user = NULL;
- char *p;
- int f_in,f_out;
- struct file_list *flist;
- char *local_name = NULL;
-
- signal(SIGUSR1, sigusr1_handler);
-
- starttime = time(NULL);
- am_root = (getuid() == 0);
-
- /* we set a 0 umask so that correct file permissions can be
- carried across */
- orig_umask = umask(0);
-
- while ((opt = getopt_long(argc, argv,
- short_options, long_options, &option_index))
- != -1) {
- switch (opt)
- {
- case OPT_VERSION:
- printf("rsync version %s protocol version %d\n",
- VERSION,PROTOCOL_VERSION);
- exit_cleanup(0);
-
- case OPT_SUFFIX:
- backup_suffix = optarg;
- break;
-
- case OPT_RSYNC_PATH:
- rsync_path = optarg;
- break;
-
- case 'I':
- ignore_times = 1;
- break;
-
- case 'x':
- one_file_system=1;
- break;
-
- case OPT_DELETE:
- delete_mode = 1;
- break;
-
- case OPT_NUMERIC_IDS:
- numeric_ids = 1;
- break;
-
- case OPT_EXCLUDE:
- add_exclude(optarg);
- break;
-
- case OPT_EXCLUDE_FROM:
- add_exclude_file(optarg,1);
- break;
-
- case 'h':
- usage(FINFO);
- exit_cleanup(0);
-
- case 'b':
- make_backups=1;
- break;
-
- case 'n':
- dry_run=1;
- break;
-
- case 'S':
- sparse_files=1;
- break;
-
- case 'C':
- cvs_exclude=1;
- break;
-
- case 'u':
- update_only=1;
- break;
-
- case 'l':
- preserve_links=1;
- break;
-
- case 'L':
- copy_links=1;
- break;
-
- case 'W':
- whole_file=1;
- break;
-
- case 'H':
-#if SUPPORT_HARD_LINKS
- preserve_hard_links=1;
-#else
- fprintf(FERROR,"ERROR: hard links not supported on this platform\n");
- exit_cleanup(1);
-#endif
- break;
+ 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
+ && !read_batch) {
+ 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) { /* for read_batch, NO source is specified */
+ p = find_colon(argv[0]);
+ if (p) { /* source is remote */
+ 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) { /* destination required */
+ usage(FERROR);
+ exit_cleanup(RERR_SYNTAX);
+ }
+
+ am_sender = 0;
+ *p = 0;
+ shell_machine = argv[0];
+ shell_path = p+1;
+ argv++;
+ } else { /* source is local */
+ 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]); /* look in dest arg */
+ 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) { /* no colon found, so src & dest are local */
+ 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 { /* read_batch */
+ local_server = 1;
+ shell_path = argv[argc-1];
+ if (find_colon(shell_path)) {
+ 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?shell_cmd:"",
+ shell_machine?shell_machine:"",
+ shell_user?shell_user:"",
+ shell_path?shell_path:"");
+ }