io_printf(f_out, "@RSYNCD: OK\n");
- read_args(f_in, name, line, sizeof line, rl_nulls, &argv, &argc, &request);
+ read_args(f_in, name, line, sizeof line, rl_nulls, 1, &argv, &argc, &request);
orig_argv = argv;
save_munge_symlinks = munge_symlinks;
if (protect_args && ret) {
orig_early_argv = orig_argv;
protect_args = 2;
- read_args(f_in, name, line, sizeof line, 1, &argv, &argc, &request);
+ read_args(f_in, name, line, sizeof line, 1, 0, &argv, &argc, &request);
orig_argv = argv;
ret = parse_arguments(&argc, (const char ***) &argv);
} else
return s - buf;
}
+/* Reverse safe_arg()'s backslash escaping of a daemon option arg, the way a
+ * remote shell un-escapes args for the ssh transport. In place; \X -> X. */
+static void unbackslash_arg(char *s)
+{
+ char *f = s, *t = s;
+ while (*f) {
+ if (*f == '\\' && f[1])
+ f++;
+ *t++ = *f++;
+ }
+ *t = '\0';
+}
+
void read_args(int f_in, char *mod_name, char *buf, size_t bufsiz, int rl_nulls,
- char ***argv_p, int *argc_p, char **request_p)
+ int unescape, char ***argv_p, int *argc_p, char **request_p)
{
int maxargs = MAX_ARGS;
int dot_pos = 0, argc = 0, request_len = 0;
glob_expand(buf, &argv, &argc, &maxargs);
} else {
p = strdup(buf);
+ /* An option arg the client escaped with safe_arg() (no
+ * remote shell un-escapes it for a daemon). File args
+ * after the dot are handled by glob_expand() below. */
+ if (unescape)
+ unbackslash_arg(p);
argv[argc++] = p;
if (*p == '.' && p[1] == '\0')
dot_pos = argc;
if (am_server && protect_args) {
char buf[MAXPATHLEN];
protect_args = 2;
- read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, &argv, &argc, NULL);
+ read_args(STDIN_FILENO, NULL, buf, sizeof buf, 1, 0, &argv, &argc, NULL);
if (!parse_arguments(&argc, (const char ***) &argv)) {
option_error();
exit_cleanup(RERR_SYNTAX);