Пример #1
0
int main() {

    arena = Arena_new();

    start_socket_server();
    start_socket_client();
    test_unconnected_put(); //fatal, reconnect

    start_socket_client();
    test_con();
    test_con_2(); //fatal, reconnect

    start_socket_client();
    test_con();
    test_put();
    test_read();
    test_take();
    test_upt(); //fatal, reconnect

    start_socket_client();
    test_con();
    test_upl();

    stop_socket_server();

    return 0;
}
Пример #2
0
void
test_open_socket_fork(void)
{
/* This subtest will start a server and client using TCP. The client will
 * open the socket with SOCK_CLOEXEC turned off, so that after a fork+exec, the
 * socket should stay valid.
 *                o
 *              / | 
 *        server  |
 *      (accept)  |
 *             |  | \
 *             |  |  client
 *             |  |  (connect)
 *             |  |  | \
 *             |  |  |  client_fork
 *             |  |  |  (exec t67a)
 *        (read)  |  |  (write)
 *             |  |  | /
 *             |  |  (waitpid client_fork) 
 *              \ |  |
 * (waitpid server)  |
 *                | /
 * (waitpid client)
 *                |
 *                o
 */
	pid_t pid_server, pid_client;
	int result;

	pid_server = fork();
	if (pid_server < 0) e(1);
	if (pid_server == 0) {
		start_socket_server(FORK_PORT);
		return; /* Never reached */
	}

	pid_client = fork();
	if (pid_client < 0) e(2);
	if (pid_client == 0) {
		pid_t pid_client_fork;
		int sockfd;

		sockfd = start_socket_client(FORK_PORT, 0);
		if (sockfd < 0) e(4);

		pid_client_fork = fork();
		if (pid_client_fork < 0) {
			e(5);
			exit(5);
		}
		if (pid_client_fork == 0) {
			/* We're a fork of the client. After we exec, the
			 * socket should stay valid due to lack of SOCK_CLOEXEC
			 * flag.
			 */
			char sockfd_buf[2];
			int flags;

			/* Verify O_CLOEXEC is off */
			flags = fcntl(sockfd, F_GETFD);
			if (flags < 0) e(5);
			if (flags & FD_CLOEXEC) e(6);

			/* t67a will verify that it can't write to sockfd and
			 * that opening a new file will yield a file descriptor
			 * with a higher number.
			 */
			snprintf(sockfd_buf, sizeof(sockfd_buf), "%d", sockfd);
			execl("./t67a", "t67a", sockfd_buf, NULL);

			/* Should not reach this */
			exit(1);
		} else {
			if (waitpid(pid_client_fork, &result, 0) < 0) e(8);
			exit(WEXITSTATUS(result)); /* Pass on error to main */
		}
		exit(0);	/* Never reached */
	}

	if (waitpid(pid_server, &result, 0) < 0) e(3);
	if (waitpid(pid_client, &result, 0) < 0) e(4);

	/* Let's inspect client result */
	if (WEXITSTATUS(result) != 0) e(5);
}
Пример #3
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;

	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;
}