File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / pipe.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    1: /*
    2:  * Routines used to setup various kinds of inter-process pipes.
    3:  *
    4:  * Copyright (C) 1996-2000 Andrew Tridgell
    5:  * Copyright (C) 1996 Paul Mackerras
    6:  * Copyright (C) 2001, 2002 Martin Pool <mbp@samba.org>
    7:  * Copyright (C) 2004-2020 Wayne Davison
    8:  *
    9:  * This program is free software; you can redistribute it and/or modify
   10:  * it under the terms of the GNU General Public License as published by
   11:  * the Free Software Foundation; either version 3 of the License, or
   12:  * (at your option) any later version.
   13:  *
   14:  * This program is distributed in the hope that it will be useful,
   15:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   16:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17:  * GNU General Public License for more details.
   18:  *
   19:  * You should have received a copy of the GNU General Public License along
   20:  * with this program; if not, visit the http://fsf.org website.
   21:  */
   22: 
   23: #include "rsync.h"
   24: 
   25: extern int am_sender;
   26: extern int am_server;
   27: extern int blocking_io;
   28: extern int filesfrom_fd;
   29: extern int munge_symlinks;
   30: extern int always_checksum;
   31: extern int use_db;
   32: extern char *db_config;
   33: extern char *logfile_name;
   34: extern int remote_option_cnt;
   35: extern const char **remote_options;
   36: extern struct chmod_mode_struct *chmod_modes;
   37: 
   38: int same_db = 0;
   39: 
   40: /**
   41:  * Create a child connected to us via its stdin/stdout.
   42:  *
   43:  * This is derived from CVS code
   44:  *
   45:  * Note that in the child STDIN is set to blocking and STDOUT
   46:  * is set to non-blocking. This is necessary as rsh relies on stdin being blocking
   47:  *  and ssh relies on stdout being non-blocking
   48:  *
   49:  * If blocking_io is set then use blocking io on both fds. That can be
   50:  * used to cope with badly broken rsh implementations like the one on
   51:  * Solaris.
   52:  **/
   53: pid_t piped_child(char **command, int *f_in, int *f_out)
   54: {
   55: 	pid_t pid;
   56: 	int to_child_pipe[2];
   57: 	int from_child_pipe[2];
   58: 
   59: 	if (DEBUG_GTE(CMD, 1))
   60: 		print_child_argv("opening connection using:", command);
   61: 
   62: 	if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
   63: 		rsyserr(FERROR, errno, "pipe");
   64: 		exit_cleanup(RERR_IPC);
   65: 	}
   66: 
   67: 	pid = do_fork();
   68: 	if (pid == -1) {
   69: 		rsyserr(FERROR, errno, "fork");
   70: 		exit_cleanup(RERR_IPC);
   71: 	}
   72: 
   73: 	if (pid == 0) {
   74: 		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0
   75: 		 || close(to_child_pipe[1]) < 0
   76: 		 || close(from_child_pipe[0]) < 0
   77: 		 || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
   78: 			rsyserr(FERROR, errno, "Failed to dup/close");
   79: 			exit_cleanup(RERR_IPC);
   80: 		}
   81: 		if (to_child_pipe[0] != STDIN_FILENO)
   82: 			close(to_child_pipe[0]);
   83: 		if (from_child_pipe[1] != STDOUT_FILENO)
   84: 			close(from_child_pipe[1]);
   85: 		set_blocking(STDIN_FILENO);
   86: 		if (blocking_io > 0)
   87: 			set_blocking(STDOUT_FILENO);
   88: 		execvp(command[0], command);
   89: 		rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
   90: 		exit_cleanup(RERR_IPC);
   91: 	}
   92: 
   93: 	if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
   94: 		rsyserr(FERROR, errno, "Failed to close");
   95: 		exit_cleanup(RERR_IPC);
   96: 	}
   97: 
   98: 	*f_in = from_child_pipe[0];
   99: 	*f_out = to_child_pipe[1];
  100: 
  101: 	return pid;
  102: }
  103: 
  104: /* This function forks a child which calls child_main().  First,
  105:  * however, it has to establish communication paths to and from the
  106:  * newborn child.  It creates two socket pairs -- one for writing to
  107:  * the child (from the parent) and one for reading from the child
  108:  * (writing to the parent).  Since that's four socket ends, each
  109:  * process has to close the two ends it doesn't need.  The remaining
  110:  * two socket ends are retained for reading and writing.  In the
  111:  * child, the STDIN and STDOUT file descriptors refer to these
  112:  * sockets.  In the parent, the function arguments f_in and f_out are
  113:  * set to refer to these sockets. */
  114: pid_t local_child(int argc, char **argv, int *f_in, int *f_out,
  115: 		  int (*child_main)(int, char*[]))
  116: {
  117: 	pid_t pid;
  118: 	int to_child_pipe[2];
  119: 	int from_child_pipe[2];
  120: 
  121: 	/* The parent process is always the sender for a local rsync. */
  122: 	assert(am_sender);
  123: 
  124: 	if (fd_pair(to_child_pipe) < 0 || fd_pair(from_child_pipe) < 0) {
  125: 		rsyserr(FERROR, errno, "pipe");
  126: 		exit_cleanup(RERR_IPC);
  127: 	}
  128: 
  129: 	pid = do_fork();
  130: 	if (pid == -1) {
  131: 		rsyserr(FERROR, errno, "fork");
  132: 		exit_cleanup(RERR_IPC);
  133: 	}
  134: 
  135: 	if (pid == 0) {
  136: 		am_sender = 0;
  137: 		am_server = 1;
  138: 		filesfrom_fd = -1;
  139: 		munge_symlinks = 0; /* Each side needs its own option. */
  140: 		chmod_modes = NULL; /* Let the sending side handle this. */
  141: 
  142: 		/* Let the client side handle this. */
  143: 		if (logfile_name) {
  144: 			logfile_name = NULL;
  145: 			logfile_close();
  146: 		}
  147: 
  148: 		if (remote_option_cnt) {
  149: 			const char *db_config_save = db_config;
  150: 			int rc = remote_option_cnt + 1;
  151: 			const char **rv = remote_options;
  152: 			if (!parse_arguments(&rc, &rv)) {
  153: 				option_error();
  154: 				exit_cleanup(RERR_SYNTAX);
  155: 			}
  156: 			if (db_config == db_config_save)
  157: 				same_db = db_config != NULL;
  158: 			else if (!db_config || !db_config_save || strcmp(db_config, db_config_save) != 0) {
  159: 				use_db = 0;
  160: 				if (db_config)
  161: 					db_read_config(FERROR, db_config);
  162: 			}
  163: 		} else if (use_db)
  164: 			same_db = 1;
  165: 
  166: 		if (dup2(to_child_pipe[0], STDIN_FILENO) < 0
  167: 		 || close(to_child_pipe[1]) < 0
  168: 		 || close(from_child_pipe[0]) < 0
  169: 		 || dup2(from_child_pipe[1], STDOUT_FILENO) < 0) {
  170: 			rsyserr(FERROR, errno, "Failed to dup/close");
  171: 			exit_cleanup(RERR_IPC);
  172: 		}
  173: 		if (to_child_pipe[0] != STDIN_FILENO)
  174: 			close(to_child_pipe[0]);
  175: 		if (from_child_pipe[1] != STDOUT_FILENO)
  176: 			close(from_child_pipe[1]);
  177: #ifdef ICONV_CONST
  178: 		setup_iconv();
  179: #endif
  180: 		child_main(argc, argv);
  181: 	}
  182: 
  183: 	if (close(from_child_pipe[1]) < 0 || close(to_child_pipe[0]) < 0) {
  184: 		rsyserr(FERROR, errno, "Failed to close");
  185: 		exit_cleanup(RERR_IPC);
  186: 	}
  187: 
  188: 	*f_in = from_child_pipe[0];
  189: 	*f_out = to_child_pipe[1];
  190: 
  191: 	return pid;
  192: }
  193: 
  194: pid_t run_filter(char *command[], int out, int *pipe_to_filter)
  195: {
  196: 	pid_t pid;
  197: 	int pipefds[2];
  198: 
  199: 	if (DEBUG_GTE(CMD, 1))
  200: 		print_child_argv("opening connection using:", command);
  201: 
  202: 	if (pipe(pipefds) < 0) {
  203: 		rsyserr(FERROR, errno, "pipe");
  204: 		exit_cleanup(RERR_IPC);
  205: 	}
  206: 
  207: 	pid = do_fork();
  208: 	if (pid == -1) {
  209: 		rsyserr(FERROR, errno, "fork");
  210: 		exit_cleanup(RERR_IPC);
  211: 	}
  212: 
  213: 	if (pid == 0) {
  214: 		if (dup2(pipefds[0], STDIN_FILENO) < 0
  215: 		 || close(pipefds[1]) < 0
  216: 		 || dup2(out, STDOUT_FILENO) < 0) {
  217: 			rsyserr(FERROR, errno, "Failed dup/close");
  218: 			exit_cleanup(RERR_IPC);
  219: 		}
  220: 		umask(orig_umask);
  221: 		set_blocking(STDIN_FILENO);
  222: 		if (blocking_io)
  223: 			set_blocking(STDOUT_FILENO);
  224: 		execvp(command[0], command);
  225: 		rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
  226: 		exit_cleanup(RERR_IPC);
  227: 	}
  228: 
  229: 	if (close(pipefds[0]) < 0) {
  230: 		rsyserr(FERROR, errno, "Failed to close");
  231: 		exit_cleanup(RERR_IPC);
  232: 	}
  233: 
  234: 	*pipe_to_filter = pipefds[1];
  235: 
  236: 	return pid;
  237: }
  238: 
  239: pid_t run_filter_on_file(char *command[], int out, int in)
  240: {
  241: 	pid_t pid;
  242: 
  243: 	if (DEBUG_GTE(CMD, 1))
  244: 		print_child_argv("opening connection using:", command);
  245: 
  246: 	pid = do_fork();
  247: 	if (pid == -1) {
  248: 		rsyserr(FERROR, errno, "fork");
  249: 		exit_cleanup(RERR_IPC);
  250: 	}
  251: 
  252: 	if (pid == 0) {
  253: 		if (dup2(in, STDIN_FILENO) < 0
  254: 		 || dup2(out, STDOUT_FILENO) < 0) {
  255: 			rsyserr(FERROR, errno, "Failed to dup2");
  256: 			exit_cleanup(RERR_IPC);
  257: 		}
  258: 		if (blocking_io)
  259: 			set_blocking(STDOUT_FILENO);
  260: 		execvp(command[0], command);
  261: 		rsyserr(FERROR, errno, "Failed to exec %s", command[0]);
  262: 		exit_cleanup(RERR_IPC);
  263: 	}
  264: 
  265: 	return pid;
  266: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>