extern int default_af_hint;
extern int logfile_format_has_i;
extern int logfile_format_has_o_or_i;
-extern mode_t orig_umask;
extern char *bind_address;
extern char *config_file;
extern char *logfile_format;
}
/* This strips the \n. */
- if (!read_line_old(f_in, buf, bufsiz)) {
+ if (!read_line_old(f_in, buf, bufsiz, 0)) {
if (am_client)
rprintf(FERROR, "rsync: did not see server greeting\n");
return -1;
if (strncmp(*argv, modname, modlen) == 0
&& argv[0][modlen] == '\0')
sargs[sargc++] = modname; /* we send "modname/" */
- else
+ else if (**argv == '-') {
+ if (asprintf(sargs + sargc++, "./%s", *argv) < 0)
+ out_of_memory("start_inband_exchange");
+ } else
sargs[sargc++] = *argv;
argv++;
argc--;
kluge_around_eof = list_only && protocol_version < 25 ? 1 : 0;
while (1) {
- if (!read_line_old(f_in, line, sizeof line)) {
+ if (!read_line_old(f_in, line, sizeof line, 0)) {
rprintf(FERROR, "rsync: didn't get server startup line\n");
return -1;
}
return 0;
}
-static char *finish_pre_exec(pid_t pid, int fd, char *request,
+static char *finish_pre_exec(pid_t pid, int write_fd, int read_fd, char *request,
char **early_argv, char **argv)
{
- int j = 0, status = -1;
+ char buf[BIGPATHBUFLEN], *bp;
+ int j = 0, status = -1, msglen = sizeof buf - 1;
if (!request)
request = "(NONE)";
- write_buf(fd, request, strlen(request)+1);
+ write_buf(write_fd, request, strlen(request)+1);
if (early_argv) {
for ( ; *early_argv; early_argv++)
- write_buf(fd, *early_argv, strlen(*early_argv)+1);
+ write_buf(write_fd, *early_argv, strlen(*early_argv)+1);
j = 1; /* Skip arg0 name in argv. */
}
for ( ; argv[j]; j++) {
- write_buf(fd, argv[j], strlen(argv[j])+1);
+ write_buf(write_fd, argv[j], strlen(argv[j])+1);
if (argv[j][0] == '.' && argv[j][1] == '\0')
break;
}
- write_byte(fd, 0);
+ write_byte(write_fd, 0);
- close(fd);
+ close(write_fd);
+
+ /* Read the stdout from the pre-xfer exec program. This it is only
+ * displayed to the user if the script also returns an error status. */
+ for (bp = buf; msglen > 0; msglen -= j) {
+ if ((j = read(read_fd, bp, msglen)) <= 0) {
+ if (j == 0)
+ break;
+ if (errno == EINTR)
+ continue;
+ break; /* Just ignore the read error for now... */
+ }
+ bp += j;
+ if (j > 1 && bp[-1] == '\n' && bp[-2] == '\r') {
+ bp--;
+ j--;
+ bp[-1] = '\n';
+ }
+ }
+ *bp = '\0';
+
+ close(read_fd);
if (wait_process(pid, &status, 0) < 0
|| !WIFEXITED(status) || WEXITSTATUS(status) != 0) {
char *e;
- if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s\n",
+ if (asprintf(&e, "pre-xfer exec returned failure (%d)%s%s%s\n%s",
status, status < 0 ? ": " : "",
- status < 0 ? strerror(errno) : "") < 0)
- out_of_memory("finish_pre_exec");
+ status < 0 ? strerror(errno) : "",
+ *buf ? ":" : "", buf) < 0)
+ return "out_of_memory in finish_pre_exec\n";
return e;
}
return NULL;
char *p, *err_msg = NULL;
char *name = lp_name(i);
int use_chroot = lp_use_chroot(i);
- int ret, pre_exec_fd = -1;
+ int ret, pre_exec_arg_fd = -1, pre_exec_error_fd = -1;
int save_munge_symlinks;
pid_t pre_exec_pid = 0;
char *request = NULL;
set_env_str("RSYNC_HOST_NAME", host);
set_env_str("RSYNC_HOST_ADDR", addr);
- if (!allow_access(addr, host, lp_hosts_allow(i), lp_hosts_deny(i))) {
+ if (!allow_access(addr, &host, i)) {
rprintf(FLOG, "rsync denied on module %s from %s (%s)\n",
name, host, addr);
if (!lp_list(i))
return -1;
}
+ read_only = lp_read_only(i); /* may also be overridden by auth_server() */
auth_user = auth_server(f_in, f_out, i, host, addr, "@RSYNCD: AUTHREQD ");
if (!auth_user) {
module_id = i;
- if (lp_read_only(i))
- read_only = 1;
-
if (lp_transfer_logging(i) && !logfile_format)
logfile_format = lp_log_format(i);
if (log_format_has(logfile_format, 'i'))
if (*lp_prexfer_exec(i) || *lp_postxfer_exec(i)) {
int status;
- umask(orig_umask);
/* For post-xfer exec, fork a new process to run the rsync
* daemon while this process waits for the exit status and
* runs the indicated command at that point. */
return -1;
}
if (pid) {
+ close(f_in);
+ if (f_out != f_in)
+ close(f_out);
set_env_num("RSYNC_PID", (long)pid);
if (wait_process(pid, &status, 0) < 0)
status = -1;
* command, though it first waits for the parent process to
* send us the user's request via a pipe. */
if (*lp_prexfer_exec(i)) {
- int fds[2];
+ int arg_fds[2], error_fds[2];
set_env_num("RSYNC_PID", (long)getpid());
- if (pipe(fds) < 0 || (pre_exec_pid = fork()) < 0) {
+ if (pipe(arg_fds) < 0 || pipe(error_fds) < 0 || (pre_exec_pid = fork()) < 0) {
rsyserr(FLOG, errno, "pre-xfer exec preparation failed");
io_printf(f_out, "@ERROR: pre-xfer exec preparation failed\n");
return -1;
if (pre_exec_pid == 0) {
char buf[BIGPATHBUFLEN];
int j, len;
- close(fds[1]);
- set_blocking(fds[0]);
- len = read_arg_from_pipe(fds[0], buf, BIGPATHBUFLEN);
+ close(arg_fds[1]);
+ close(error_fds[0]);
+ pre_exec_arg_fd = arg_fds[0];
+ pre_exec_error_fd = error_fds[1];
+ set_blocking(pre_exec_arg_fd);
+ set_blocking(pre_exec_error_fd);
+ len = read_arg_from_pipe(pre_exec_arg_fd, buf, BIGPATHBUFLEN);
if (len <= 0)
_exit(1);
set_env_str("RSYNC_REQUEST", buf);
for (j = 0; ; j++) {
- len = read_arg_from_pipe(fds[0], buf,
+ len = read_arg_from_pipe(pre_exec_arg_fd, buf,
BIGPATHBUFLEN);
if (len <= 0) {
if (!len)
if (asprintf(&p, "RSYNC_ARG%d=%s", j, buf) > 0)
putenv(p);
}
- close(fds[0]);
+ close(pre_exec_arg_fd);
close(STDIN_FILENO);
- close(STDOUT_FILENO);
+ dup2(pre_exec_error_fd, STDOUT_FILENO);
+ close(pre_exec_error_fd);
status = system(lp_prexfer_exec(i));
if (!WIFEXITED(status))
_exit(1);
_exit(WEXITSTATUS(status));
}
- close(fds[0]);
- set_blocking(fds[1]);
- pre_exec_fd = fds[1];
+ close(arg_fds[0]);
+ close(error_fds[1]);
+ pre_exec_arg_fd = arg_fds[1];
+ pre_exec_error_fd = error_fds[0];
+ set_blocking(pre_exec_arg_fd);
+ set_blocking(pre_exec_error_fd);
}
- umask(0);
}
#endif
munge_symlinks = save_munge_symlinks; /* The client mustn't control this. */
if (pre_exec_pid) {
- err_msg = finish_pre_exec(pre_exec_pid, pre_exec_fd, request,
- orig_early_argv, orig_argv);
+ err_msg = finish_pre_exec(pre_exec_pid, pre_exec_arg_fd, pre_exec_error_fd,
+ request, orig_early_argv, orig_argv);
}
if (orig_early_argv)
}
if (!ret || err_msg) {
- if (err_msg)
- rwrite(FERROR, err_msg, strlen(err_msg), 0);
- else
+ if (err_msg) {
+ while ((p = strchr(err_msg, '\n')) != NULL) {
+ int len = p - err_msg + 1;
+ rwrite(FERROR, err_msg, len, 0);
+ err_msg += len;
+ }
+ if (*err_msg)
+ rprintf(FERROR, "%s\n", err_msg);
+ } else
option_error();
msleep(400);
exit_cleanup(RERR_UNSUPPORTED);
return -1;
line[0] = 0;
- if (!read_line_old(f_in, line, sizeof line))
+ if (!read_line_old(f_in, line, sizeof line, 0))
return -1;
if (!*line || strcmp(line, "#list") == 0) {
return;
cleanup_set_pid(pid);
- if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666 & ~orig_umask)) == -1) {
+ if ((fd = do_open(pid_file, O_WRONLY|O_CREAT|O_EXCL, 0666)) == -1) {
failure:
cleanup_set_pid(0);
fprintf(stderr, "failed to create pid file %s: %s\n", pid_file, strerror(errno));