Example #1
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;
}
Example #2
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;
}
Example #3
0
void send_protected_args(int fd, char *args[])
{
	int i;
#ifdef ICONV_OPTION
	int convert = ic_send != (iconv_t)-1;
	xbuf outbuf, inbuf;

	if (convert)
		alloc_xbuf(&outbuf, 1024);
#endif

	for (i = 0; args[i]; i++) {} /* find first NULL */
	args[i] = "rsync"; /* set a new arg0 */
	if (DEBUG_GTE(CMD, 1))
		print_child_argv("protected args:", args + i + 1);
	do {
		if (!args[i][0])
			write_buf(fd, ".", 2);
#ifdef ICONV_OPTION
		else if (convert) {
			INIT_XBUF_STRLEN(inbuf, args[i]);
			iconvbufs(ic_send, &inbuf, &outbuf,
				  ICB_EXPAND_OUT | ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE | ICB_INIT);
			outbuf.buf[outbuf.len] = '\0';
			write_buf(fd, outbuf.buf, outbuf.len + 1);
			outbuf.len = 0;
		}
#endif
		else
			write_buf(fd, args[i], strlen(args[i]) + 1);
	} while (args[++i]);
	write_byte(fd, 0);

#ifdef ICONV_OPTION
	if (convert)
		free(outbuf.buf);
#endif
}
Example #4
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;
}