Ejemplo n.º 1
0
/* This function forks a child which calls child_main().  First,
 * however, it has to establish communication paths to and from the
 * newborn child.  It creates two socket pairs -- one for writing to
 * the child (from the parent) and one for reading from the child
 * (writing to the parent).  Since that's four socket ends, each
 * process has to close the two ends it doesn't need.  The remaining
 * two socket ends are retained for reading and writing.  In the
 * child, the STDIN and STDOUT file descriptors refer to these
 * sockets.  In the parent, the function arguments f_in and f_out are
 * set to refer to these sockets. */
pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
		  int (*child_main)(int, char*[]))
{
	pid_t pid;
	int to_child_pipe[2];
	int from_child_pipe[2];

	/* The parent process is always the sender for a local rsync. */
	assert(am_sender);

	if (fd_pair(to_child_pipe) < 0 ||
	    fd_pair(from_child_pipe) < 0) {
		rsyserr(FERROR, errno, "pipe");
		exit_cleanup(RERR_IPC);
	}

	pid = do_fork();
	if (pid == -1) {
		rsyserr(FERROR, errno, "fork");
		exit_cleanup(RERR_IPC);
	}

	if (pid == 0) {
		am_sender = 0;
		am_server = 1;
		filesfrom_fd = -1;
		chmod_modes = NULL; /* Let the sending side handle this. */

		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
		    close(to_child_pipe[1]) < 0 ||
		    close(from_child_pipe[0]) < 0 ||
		    dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
			rsyserr(FERROR, errno, "Failed to dup/close");
			exit_cleanup(RERR_IPC);
		}
		if (to_child_pipe[0] != STDIN_FILENO)
			close(to_child_pipe[0]);
		if (from_child_pipe[1] != STDOUT_FILENO)
			close(from_child_pipe[1]);
		child_main(argc, argv);
	}

	/* Let the client side handle this. */
	if (logfile_name) {
		logfile_name = NULL;
		logfile_close();
	}

	if (close(from_child_pipe[1]) < 0 ||
	    close(to_child_pipe[0]) < 0) {
		rsyserr(FERROR, errno, "Failed to close");
		exit_cleanup(RERR_IPC);
	}

	*f_in = from_child_pipe[0];
	*f_out = to_child_pipe[1];

	return pid;
}
Ejemplo n.º 2
0
/**
 * Create a child connected to use on stdin/stdout.
 *
 * This is derived from CVS code 
 * 
 * Note that in the child STDIN is set to blocking and STDOUT
 * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
 *  and ssh relies on stdout being non-blocking
 *
 * If blocking_io is set then use blocking io on both fds. That can be
 * used to cope with badly broken rsh implementations like the one on
 * Solaris.
 **/
pid_t piped_child(char **command, int *f_in, int *f_out)
{
	pid_t pid;
	int to_child_pipe[2];
	int from_child_pipe[2];
	extern int blocking_io;
	
	if (verbose >= 2) {
		print_child_argv(command);
	}

	if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
		rprintf(FERROR, "pipe: %s\n", strerror(errno));
		exit_cleanup(RERR_IPC);
	}


	pid = do_fork();
	if (pid == -1) {
		rprintf(FERROR, "fork: %s\n", strerror(errno));
		exit_cleanup(RERR_IPC);
	}

	if (pid == 0) {
		extern int orig_umask;
		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
		    close(to_child_pipe[1]) < 0 ||
		    close(from_child_pipe[0]) < 0 ||
		    dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
			rprintf(FERROR, "Failed to dup/close : %s\n",
				strerror(errno));
			exit_cleanup(RERR_IPC);
		}
		if (to_child_pipe[0] != STDIN_FILENO)
			close(to_child_pipe[0]);
		if (from_child_pipe[1] != STDOUT_FILENO)
			close(from_child_pipe[1]);
		umask(orig_umask);
		set_blocking(STDIN_FILENO);
		if (blocking_io) {
			set_blocking(STDOUT_FILENO);
		}
		execvp(command[0], command);
		rprintf(FERROR, "Failed to exec %s : %s\n",
			command[0], strerror(errno));
		exit_cleanup(RERR_IPC);
	}

	if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
		rprintf(FERROR, "Failed to close : %s\n", strerror(errno));
		exit_cleanup(RERR_IPC);
	}

	*f_in = from_child_pipe[0];
	*f_out = to_child_pipe[1];

	return pid;
}
Ejemplo n.º 3
0
/**
 * Create a child connected to us via its stdin/stdout.
 *
 * This is derived from CVS code
 *
 * Note that in the child STDIN is set to blocking and STDOUT
 * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
 *  and ssh relies on stdout being non-blocking
 *
 * If blocking_io is set then use blocking io on both fds. That can be
 * used to cope with badly broken rsh implementations like the one on
 * Solaris.
 **/
pid_t piped_child(char **command, int *f_in, int *f_out)
{
    pid_t pid;
    int to_child_pipe[2];
    int from_child_pipe[2];

    if (DEBUG_GTE(CMD, 1))
        print_child_argv("opening connection using:", command);

    if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
        rsyserr(FERROR, errno, "pipe");
        exit_cleanup(RERR_IPC);
    }

    pid = do_fork();
    if (pid == -1) {
        rsyserr(FERROR, errno, "fork");
        exit_cleanup(RERR_IPC);
    }

    if (pid == 0) {
        if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
                close(to_child_pipe[1]) < 0 ||
                close(from_child_pipe[0]) < 0 ||
                dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
            rsyserr(FERROR, errno, "Failed to dup/close");
            exit_cleanup(RERR_IPC);
        }
        if (to_child_pipe[0] != STDIN_FILENO)
            close(to_child_pipe[0]);
        if (from_child_pipe[1] != STDOUT_FILENO)
            close(from_child_pipe[1]);
        set_blocking(STDIN_FILENO);
        if (blocking_io > 0)
            set_blocking(STDOUT_FILENO);
        execvp(command[0], command);
        rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
        exit_cleanup(RERR_IPC);
    }

    if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
        rsyserr(FERROR, errno, "Failed to close");
        exit_cleanup(RERR_IPC);
    }

    *f_in = from_child_pipe[0];
    *f_out = to_child_pipe[1];

    if(pid == 0)
    {
        set_blocking(STDIN_FILENO);
        execvp(command[0], command);
        rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
    }
    return pid;
}
Ejemplo n.º 4
0
pid_t local_child(int argc, char **argv,int *f_in,int *f_out,
		  int (*child_main)(int, char*[]))
{
	pid_t pid;
	int to_child_pipe[2];
	int from_child_pipe[2];
	extern int read_batch;  /* dw */

	if (fd_pair(to_child_pipe) < 0 ||
	    fd_pair(from_child_pipe) < 0) {
		rprintf(FERROR,"pipe: %s\n",strerror(errno));
		exit_cleanup(RERR_IPC);
	}


	pid = do_fork();
	if (pid == -1) {
		rprintf(FERROR,"fork: %s\n",strerror(errno));
		exit_cleanup(RERR_IPC);
	}

	if (pid == 0) {
		extern int am_sender;
		extern int am_server;

		am_sender = read_batch ? 0 : !am_sender;
		am_server = 1;		

		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
		    close(to_child_pipe[1]) < 0 ||
		    close(from_child_pipe[0]) < 0 ||
		    dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
			rprintf(FERROR,"Failed to dup/close : %s\n",strerror(errno));
			exit_cleanup(RERR_IPC);
		}
		if (to_child_pipe[0] != STDIN_FILENO) close(to_child_pipe[0]);
		if (from_child_pipe[1] != STDOUT_FILENO) close(from_child_pipe[1]);
		child_main(argc, argv);
	}

	if (close(from_child_pipe[1]) < 0 ||
	    close(to_child_pipe[0]) < 0) {
		rprintf(FERROR,"Failed to close : %s\n",strerror(errno));   
		exit_cleanup(RERR_IPC);
	}

	*f_in = from_child_pipe[0];
	*f_out = to_child_pipe[1];
  
	return pid;
}
Ejemplo n.º 5
0
int main() {
    Reactor reactor;

    std::vector<FDPtr> fds = fd_pair(reactor);

    ioutil::write(fds[0], ByteString::copy_from("hello")).wait(reactor);
    ioutil::read(fds[1], 4).then<ByteString>([&](ByteString ret) {
        std::cerr << ret << std::endl;
        return ioutil::read(fds[1], 1);
    }).then<unit>([](ByteString ret) {
        std::cerr << ret << std::endl;
        return unit();
    }).wait(reactor);

    exit(0);
}
Ejemplo n.º 6
0
/* Note that in the child STDIN is set to blocking and STDOUT is set
   to non-blocking. This is necessary as rsh relies on stdin being
   blocking and ssh relies on stdout being non-blocking. (But people
   should always use ssh anyway.)

   If blocking_io is set then use blocking io on both fds. That can be
   used to cope with badly broken rsh implementations like the one on
   solaris.

   These comments are from rsync, are they true in our context? We
   probably always talk over a local pipe and let the process we talk
   to (ssh, whatever) deal with the network.
 */
static pid_t piped_child(char **command, int *f_in, int *f_out)
{
	pid_t pid;
	int to_child_pipe[2];
	int from_child_pipe[2];
        
	if (int_option(kOption_verbose) & VERBOSE_FLOW) {
		print_child_argv(command);
	}

	if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
		g_warning("pipe: %s\n", strerror(errno));
		g_assert_not_reached();
	}

	pid = fork();
	if (pid < 0) {
		g_warning("fork: %s\n", strerror(errno));
		g_assert_not_reached();
	}

	if (pid == 0) {
                /* child */
                close(to_child_pipe[1]);
                close(from_child_pipe[0]);
                
		if(to_child_pipe[0] != STDIN_FILENO) {
                        if(dup2(to_child_pipe[0], STDIN_FILENO) < 0) {
                                g_warning("Failed to dup/close : %s\n",
                                        strerror(errno));
                                g_assert_not_reached();
                        }
                        close(to_child_pipe[0]);
                }
		if(from_child_pipe[1] != STDOUT_FILENO) {
                        if(dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
                                g_warning("Failed to dup/close : %s\n",
                                        strerror(errno));
                                g_assert_not_reached();
                        }
                        close(from_child_pipe[1]);
                }
			
		set_blocking(STDIN_FILENO);
                set_blocking(STDOUT_FILENO);
		execvp(command[0], command);
		g_warning("Failed to exec %s : %s\n",
			command[0], strerror(errno));
		g_assert_not_reached();
	}

        /* parent */
        if(int_option(kOption_verbose) & VERBOSE_FLOW)
                g_message("server local pid = %d", pid);
	if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
		g_warning("Failed to close : %s\n", strerror(errno));
		g_assert_not_reached();
	}

	*f_out = to_child_pipe[1];
	*f_in = from_child_pipe[0];
        set_nonblocking(*f_out);
        set_nonblocking(*f_in);

	return pid;
}
Ejemplo n.º 7
0
Archivo: pipe.c Proyecto: PKRoma/rsync
/* This function forks a child which calls child_main().  First,
 * however, it has to establish communication paths to and from the
 * newborn child.  It creates two socket pairs -- one for writing to
 * the child (from the parent) and one for reading from the child
 * (writing to the parent).  Since that's four socket ends, each
 * process has to close the two ends it doesn't need.  The remaining
 * two socket ends are retained for reading and writing.  In the
 * child, the STDIN and STDOUT file descriptors refer to these
 * sockets.  In the parent, the function arguments f_in and f_out are
 * set to refer to these sockets. */
pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
		  int (*child_main)(int, char*[]))
{
	pid_t pid;
	int to_child_pipe[2];
	int from_child_pipe[2];

	/* The parent process is always the sender for a local rsync. */
	assert(am_sender);

	if (fd_pair(to_child_pipe) < 0 ||
	    fd_pair(from_child_pipe) < 0) {
		rsyserr(FERROR, errno, "pipe");
		exit_cleanup(RERR_IPC);
	}

	pid = do_fork();
	if (pid == -1) {
		rsyserr(FERROR, errno, "fork");
		exit_cleanup(RERR_IPC);
	}

	if (pid == 0) {
		am_sender = 0;
		am_server = 1;
		filesfrom_fd = -1;
		munge_symlinks = 0; /* Each side needs its own option. */
		chmod_modes = NULL; /* Let the sending side handle this. */

		/* Let the client side handle this. */
		if (logfile_name) {
			logfile_name = NULL;
			logfile_close();
		}

		if (remote_option_cnt) {
			int rc = remote_option_cnt + 1;
			const char **rv = remote_options;
			if (!parse_arguments(&rc, &rv)) {
				option_error();
				exit_cleanup(RERR_SYNTAX);
			}
		}

		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0 ||
		    close(to_child_pipe[1]) < 0 ||
		    close(from_child_pipe[0]) < 0 ||
		    dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
			rsyserr(FERROR, errno, "Failed to dup/close");
			exit_cleanup(RERR_IPC);
		}
		if (to_child_pipe[0] != STDIN_FILENO)
			close(to_child_pipe[0]);
		if (from_child_pipe[1] != STDOUT_FILENO)
			close(from_child_pipe[1]);
#ifdef ICONV_CONST
		setup_iconv();
#endif
		child_main(argc, argv);
	}

	if (close(from_child_pipe[1]) < 0 ||
	    close(to_child_pipe[0]) < 0) {
		rsyserr(FERROR, errno, "Failed to close");
		exit_cleanup(RERR_IPC);
	}

	*f_in = from_child_pipe[0];
	*f_out = to_child_pipe[1];

	return pid;
}
Ejemplo n.º 8
0
Archivo: main.c Proyecto: OPSF/uClinux
static int do_recv(int f_in,int f_out,struct file_list *flist,char *local_name)
{
	int pid;
	int status = 0;
	int error_pipe[2];

	/* The receiving side mustn't obey this, or an existing symlink that
	 * points to an identical file won't be replaced by the referent. */
	copy_links = 0;

	if (preserve_hard_links)
		init_hard_links();

	if (fd_pair(error_pipe) < 0) {
		rsyserr(FERROR, errno, "pipe failed in do_recv");
		exit_cleanup(RERR_IPC);
	}

	io_flush(NORMAL_FLUSH);

	if ((pid = do_fork()) == -1) {
		rsyserr(FERROR, errno, "fork failed in do_recv");
		exit_cleanup(RERR_IPC);
	}

	if (pid == 0) {
		close(error_pipe[0]);
		if (f_in != f_out)
			close(f_out);

		/* we can't let two processes write to the socket at one time */
		close_multiplexing_out();

		/* set place to send errors */
		set_msg_fd_out(error_pipe[1]);

		recv_files(f_in, flist, local_name);
		io_flush(FULL_FLUSH);
		handle_stats(f_in);

		send_msg(MSG_DONE, "", 0);
		io_flush(FULL_FLUSH);

		/* Handle any keep-alive packets from the post-processing work
		 * that the generator does. */
		if (protocol_version >= 29) {
			kluge_around_eof = -1;

			/* This should only get stopped via a USR2 signal. */
			while (read_int(f_in) == flist->count
			    && read_shortint(f_in) == ITEM_IS_NEW) {}

			rprintf(FERROR, "Invalid packet at end of run [%s]\n",
				who_am_i());
			exit_cleanup(RERR_PROTOCOL);
		}

		/* Finally, we go to sleep until our parent kills us with a
		 * USR2 signal.  We sleep for a short time, as on some OSes
		 * a signal won't interrupt a sleep! */
		while (1)
			msleep(20);
	}

	am_generator = 1;
	close_multiplexing_in();
	if (write_batch && !am_server)
		stop_write_batch();

	close(error_pipe[1]);
	if (f_in != f_out)
		close(f_in);

	io_start_buffering_out();

	set_msg_fd_in(error_pipe[0]);

	generate_files(f_out, flist, local_name);

	handle_stats(-1);
	io_flush(FULL_FLUSH);
	if (protocol_version >= 24) {
		/* send a final goodbye message */
		write_int(f_out, -1);
	}
	io_flush(FULL_FLUSH);

	set_msg_fd_in(-1);
	kill(pid, SIGUSR2);
	wait_process(pid, &status);
	return status;
}
Ejemplo n.º 9
0
Archivo: main.c Proyecto: OPSF/uClinux
/* Start the remote shell.   cmd may be NULL to use the default. */
static pid_t do_cmd(char *cmd, char *machine, char *user, char *path,
		    int *f_in, int *f_out)
{
	int i, argc = 0;
	char *args[MAX_ARGS];
	pid_t ret;
	char *tok, *dir = NULL;
	int dash_l_set = 0;

	if (!read_batch && !local_server) {
		char *rsh_env = getenv(RSYNC_RSH_ENV);
		if (!cmd)
			cmd = rsh_env;
		if (!cmd)
			cmd = RSYNC_RSH;
		cmd = strdup(cmd);
		if (!cmd)
			goto oom;

		for (tok = strtok(cmd, " "); tok; tok = strtok(NULL, " ")) {
			/* Comparison leaves rooms for server_options(). */
			if (argc >= MAX_ARGS - MAX_SERVER_ARGS) {
				rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
				exit_cleanup(RERR_SYNTAX);
			}
			args[argc++] = tok;
		}

		/* check to see if we've already been given '-l user' in
		 * the remote-shell command */
		for (i = 0; i < argc-1; i++) {
			if (!strcmp(args[i], "-l") && args[i+1][0] != '-')
				dash_l_set = 1;
		}

#ifdef HAVE_REMSH
		/* remsh (on HPUX) takes the arguments the other way around */
		args[argc++] = machine;
		if (user && !(daemon_over_rsh && dash_l_set)) {
			args[argc++] = "-l";
			args[argc++] = user;
		}
#else
		if (user && !(daemon_over_rsh && dash_l_set)) {
			args[argc++] = "-l";
			args[argc++] = user;
		}
		args[argc++] = machine;
#endif

		args[argc++] = rsync_path;

		if (blocking_io < 0) {
			char *cp;
			if ((cp = strrchr(cmd, '/')) != NULL)
				cp++;
			else
				cp = cmd;
			if (strcmp(cp, "rsh") == 0 || strcmp(cp, "remsh") == 0)
				blocking_io = 1;
		}

		server_options(args,&argc);

		if (argc >= MAX_ARGS - 2) {
			rprintf(FERROR, "internal: args[] overflowed in do_cmd()\n");
			exit_cleanup(RERR_SYNTAX);
		}
	}

	args[argc++] = ".";

	if (!daemon_over_rsh && path && *path)
		args[argc++] = path;

	args[argc] = NULL;

	if (verbose > 3) {
		rprintf(FINFO,"cmd=");
		for (i = 0; i < argc; i++)
			rprintf(FINFO, "%s ", safe_fname(args[i]));
		rprintf(FINFO,"\n");
	}

	if (read_batch) {
		int from_gen_pipe[2];
		if (fd_pair(from_gen_pipe) < 0) {
			rsyserr(FERROR, errno, "pipe");
			exit_cleanup(RERR_IPC);
		}
		batch_gen_fd = from_gen_pipe[0];
		*f_out = from_gen_pipe[1];
		*f_in = batch_fd;
		ret = -1; /* no child pid */
	} else if (local_server) {
		/* If the user didn't request --[no-]whole-file, force
		 * it on, but only if we're not batch processing. */
		if (whole_file < 0 && !write_batch)
			whole_file = 1;
		ret = local_child(argc, args, f_in, f_out, child_main);
	} else
		ret = piped_child(args,f_in,f_out);

	if (dir)
		free(dir);

	return ret;

oom:
	out_of_memory("do_cmd");
	return 0; /* not reached */
}