⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 Rsync 3.0.5 source code
💻 C
📖 第 1 页 / 共 3 页
字号:
			io_start_buffering_out(f_out);		if (!filesfrom_host)			set_msg_fd_in(f_in);		send_filter_list(f_out);		if (filesfrom_host)			filesfrom_fd = f_in;		if (write_batch && !am_server)			start_write_batch(f_out);		flist = send_file_list(f_out, argc, argv);		set_msg_fd_in(-1);		if (verbose > 3)			rprintf(FINFO,"file list sent\n");		if (protocol_version >= 23)			io_start_multiplex_in();		io_flush(NORMAL_FLUSH);		send_files(f_in, f_out);		io_flush(FULL_FLUSH);		handle_stats(-1);		if (protocol_version >= 24)			read_final_goodbye(f_in);		if (pid != -1) {			if (verbose > 3)				rprintf(FINFO,"client_run waiting on %d\n", (int) pid);			io_flush(FULL_FLUSH);			wait_process_with_flush(pid, &exit_code);		}		output_summary();		io_flush(FULL_FLUSH);		exit_cleanup(exit_code);	}	if (!read_batch) {		if (protocol_version >= 23)			io_start_multiplex_in();		if (need_messages_from_generator)			io_start_multiplex_out();	}	send_filter_list(read_batch ? -1 : f_out);	if (filesfrom_fd >= 0) {		io_set_filesfrom_fds(filesfrom_fd, f_out);		filesfrom_fd = -1;	}	if (write_batch && !am_server)		start_write_batch(f_in);	flist = recv_file_list(f_in);	if (inc_recurse && file_total == 1)		recv_additional_file_list(f_in);	if (flist && flist->used > 0) {		local_name = get_local_name(flist, argv[0]);		check_alt_basis_dirs();		exit_code2 = do_recv(f_in, f_out, local_name);	} else {		handle_stats(-1);		output_summary();	}	if (pid != -1) {		if (verbose > 3)			rprintf(FINFO,"client_run2 waiting on %d\n", (int) pid);		io_flush(FULL_FLUSH);		wait_process_with_flush(pid, &exit_code);	}	return MAX(exit_code, exit_code2);}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, *shell_machine = NULL, *shell_user = NULL;	char **remote_argv;	int remote_argc;	int f_in, f_out;	int ret;	pid_t pid;	/* Don't clobber argv[] so that ps(1) can still show the right	 * command line. */	if ((ret = copy_argv(argv)) != 0)		return ret;	if (!read_batch) { /* for read_batch, NO source is specified */		char *path = check_for_hostspec(argv[0], &shell_machine, &rsync_port);		if (path) { /* source is remote */			char *dummy_host;			int dummy_port = 0;			*argv = path;			remote_argv = argv;			remote_argc = argc;			argv += argc - 1;			if (argc == 1 || **argv == ':')				argc = 0; /* no dest arg */			else if (check_for_hostspec(*argv, &dummy_host, &dummy_port)) {				rprintf(FERROR,					"The source and destination cannot both be remote.\n");				exit_cleanup(RERR_SYNTAX);			} else {				remote_argc--; /* don't count dest */				argc = 1;			}			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);			}			am_sender = 0;			if (rsync_port)				daemon_over_rsh = shell_cmd ? 1 : -1;		} else { /* source is local, check dest arg */			am_sender = 1;			if (argc > 1) {				p = argv[--argc];				remote_argv = argv + argc;			} else {				static char *dotarg[1] = { "." };				p = dotarg[0];				remote_argv = dotarg;			}			remote_argc = 1;			path = check_for_hostspec(p, &shell_machine, &rsync_port);			if (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 (!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;			} else { /* hostspec was found, so dest is remote */				argv[argc] = path;				if (rsync_port)					daemon_over_rsh = shell_cmd ? 1 : -1;			}		}	} else {  /* read_batch */		local_server = 1;		if (check_for_hostspec(argv[argc-1], &shell_machine, &rsync_port)) {			rprintf(FERROR, "remote destination is not allowed with --read-batch\n");			exit_cleanup(RERR_SYNTAX);		}		remote_argv = argv += argc - 1;		remote_argc = argc = 1;	}	if (am_sender) {		char *dummy_host;		int dummy_port = rsync_port;		int i;		/* For local source, extra source args must not have hostspec. */		for (i = 1; i < argc; i++) {			if (check_for_hostspec(argv[i], &dummy_host, &dummy_port)) {				rprintf(FERROR, "Unexpected remote arg: %s\n", argv[i]);				exit_cleanup(RERR_SYNTAX);			}		}	} else {		char *dummy_host;		int dummy_port = rsync_port;		int i;		/* For remote source, any extra source args must have either		 * the same hostname or an empty hostname. */		for (i = 1; i < remote_argc; i++) {			char *arg = check_for_hostspec(remote_argv[i], &dummy_host, &dummy_port);			if (!arg) {				rprintf(FERROR, "Unexpected local arg: %s\n", remote_argv[i]);				rprintf(FERROR, "If arg is a remote file/dir, prefix it with a colon (:).\n");				exit_cleanup(RERR_SYNTAX);			}			if (*dummy_host && strcmp(dummy_host, shell_machine) != 0) {				rprintf(FERROR, "All source args must come from the same machine.\n");				exit_cleanup(RERR_SYNTAX);			}			if (rsync_port != dummy_port) {				if (!rsync_port || !dummy_port)					rprintf(FERROR, "All source args must use the same hostspec format.\n");				else					rprintf(FERROR, "All source args must use the same port number.\n");				exit_cleanup(RERR_SYNTAX);			}			remote_argv[i] = arg;		}	}	if (daemon_over_rsh < 0)		return start_socket_client(shell_machine, remote_argc, remote_argv, argc, argv);	if (password_file && !daemon_over_rsh) {		rprintf(FERROR, "The --password-file option may only be "				"used when accessing an rsync daemon.\n");		exit_cleanup(RERR_SYNTAX);	}	if (connect_timeout) {		rprintf(FERROR, "The --contimeout option may only be "				"used when connecting to an rsync daemon.\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",			NS(shell_cmd), NS(shell_machine), NS(shell_user),			remote_argv ? NS(remote_argv[0]) : "");	}	pid = do_cmd(shell_cmd, shell_machine, shell_user, remote_argv, remote_argc,		     &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(f_in, f_out, shell_user, remote_argc, remote_argv);		if (tmpret < 0)			return tmpret;	}	ret = client_run(f_in, f_out, pid, argc, argv);	fflush(stdout);	fflush(stderr);	return ret;}static RETSIGTYPE sigusr1_handler(UNUSED(int val)){	exit_cleanup(RERR_SIGNAL1);}static RETSIGTYPE sigusr2_handler(UNUSED(int val)){	if (!am_server)		output_summary();	close_all();	if (got_xfer_error)		_exit(RERR_PARTIAL);	_exit(0);}RETSIGTYPE remember_children(UNUSED(int val)){#ifdef WNOHANG	int cnt, status;	pid_t pid;	/* An empty waitpid() loop was put here by Tridge and we could never	 * get him to explain why he put it in, so rather than taking it	 * out we're instead saving the child exit statuses for later use.	 * The waitpid() loop presumably eliminates all possibility of leaving	 * zombie children, maybe that's why he did it. */	while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {		/* save the child's exit status */		for (cnt = 0; cnt < MAXCHILDPROCS; cnt++) {			if (pid_stat_table[cnt].pid == 0) {				pid_stat_table[cnt].pid = pid;				pid_stat_table[cnt].status = status;				break;			}		}	}#endif#ifndef HAVE_SIGACTION	signal(SIGCHLD, remember_children);#endif}/** * This routine catches signals and tries to send them to gdb. * * Because it's called from inside a signal handler it ought not to * use too many library routines. * * @todo Perhaps use "screen -X" instead/as well, to help people * debugging without easy access to X.  Perhaps use an environment * variable, or just call a script? * * @todo The /proc/ magic probably only works on Linux (and * Solaris?)  Can we be more portable? **/#ifdef MAINTAINER_MODEconst char *get_panic_action(void){	const char *cmd_fmt = getenv("RSYNC_PANIC_ACTION");	if (cmd_fmt)		return cmd_fmt;	else		return "xterm -display :0 -T Panic -n Panic "			"-e gdb /proc/%d/exe %d";}/** * Handle a fatal signal by launching a debugger, controlled by $RSYNC_PANIC_ACTION. * * This signal handler is only installed if we were configured with * --enable-maintainer-mode.  Perhaps it should always be on and we * should just look at the environment variable, but I'm a bit leery * of a signal sending us into a busy loop. **/static RETSIGTYPE rsync_panic_handler(UNUSED(int whatsig)){	char cmd_buf[300];	int ret;	snprintf(cmd_buf, sizeof cmd_buf, get_panic_action(),		 getpid(), getpid());	/* Unless we failed to execute gdb, we allow the process to	 * continue.  I'm not sure if that's right. */	ret = system(cmd_buf);	if (ret)		_exit(ret);}#endifint main(int argc,char *argv[]){	int ret;	int orig_argc = argc;	char **orig_argv = argv;#ifdef HAVE_SIGACTION# ifdef HAVE_SIGPROCMASK	sigset_t sigmask;	sigemptyset(&sigmask);# endif	sigact.sa_flags = SA_NOCLDSTOP;#endif	SIGACTMASK(SIGUSR1, sigusr1_handler);	SIGACTMASK(SIGUSR2, sigusr2_handler);	SIGACTMASK(SIGCHLD, remember_children);#ifdef MAINTAINER_MODE	SIGACTMASK(SIGSEGV, rsync_panic_handler);	SIGACTMASK(SIGFPE, rsync_panic_handler);	SIGACTMASK(SIGABRT, rsync_panic_handler);	SIGACTMASK(SIGBUS, rsync_panic_handler);#endif	starttime = time(NULL);	our_uid = MY_UID();	am_root = our_uid == 0;	memset(&stats, 0, sizeof(stats));	if (argc < 2) {		usage(FERROR);		exit_cleanup(RERR_SYNTAX);	}	/* we set a 0 umask so that correct file permissions can be	 * carried across */	orig_umask = umask(0);#if defined CONFIG_LOCALE && defined HAVE_SETLOCALE	setlocale(LC_CTYPE, "");#endif	if (!parse_arguments(&argc, (const char ***) &argv)) {		/* FIXME: We ought to call the same error-handling		 * code here, rather than relying on getopt. */		option_error();		exit_cleanup(RERR_SYNTAX);	}	SIGACTMASK(SIGINT, sig_int);	SIGACTMASK(SIGHUP, sig_int);	SIGACTMASK(SIGTERM, sig_int);#if defined HAVE_SIGACTION && HAVE_SIGPROCMASK	sigprocmask(SIG_UNBLOCK, &sigmask, NULL);#endif	/* Ignore SIGPIPE; we consistently check error codes and will	 * see the EPIPE. */	SIGACTION(SIGPIPE, SIG_IGN);#ifdef SIGXFSZ	SIGACTION(SIGXFSZ, SIG_IGN);#endif	/* Initialize change_dir() here because on some old systems getcwd	 * (implemented by forking "pwd" and reading its output) doesn't	 * work when there are other child processes.  Also, on all systems	 * that implement getcwd that way "pwd" can't be found after chroot. */	change_dir(NULL, CD_NORMAL);	init_flist();	if ((write_batch || read_batch) && !am_server) {		if (write_batch)			write_batch_shell_file(orig_argc, orig_argv, argc);		if (read_batch && strcmp(batch_name, "-") == 0)			batch_fd = STDIN_FILENO;		else {			batch_fd = do_open(batch_name,				   write_batch ? O_WRONLY | O_CREAT | O_TRUNC				   : O_RDONLY, S_IRUSR | S_IWUSR);		}		if (batch_fd < 0) {			rsyserr(FERROR, errno, "Batch file %s open error",				full_fname(batch_name));			exit_cleanup(RERR_FILEIO);		}		if (read_batch)			read_stream_flags(batch_fd);		else			write_stream_flags(batch_fd);	}	if (write_batch < 0)		dry_run = 1;	if (am_server) {#ifdef ICONV_CONST		setup_iconv();#endif	} else if (am_daemon)		return daemon_main();	if (am_server && protect_args) {		char buf[MAXPATHLEN];		protect_args = 2;		read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);		if (!parse_arguments(&argc, (const char ***) &argv)) {			option_error();			exit_cleanup(RERR_SYNTAX);		}	}	if (argc < 1) {		usage(FERROR);		exit_cleanup(RERR_SYNTAX);	}	if (am_server) {		set_nonblocking(STDIN_FILENO);		set_nonblocking(STDOUT_FILENO);		if (am_daemon)			return start_daemon(STDIN_FILENO, STDOUT_FILENO);		start_server(STDIN_FILENO, STDOUT_FILENO, argc, argv);	}	ret = start_client(argc, argv);	if (ret == -1)		exit_cleanup(RERR_STARTCLIENT);	else		exit_cleanup(ret);	return ret;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -