+#ifdef ICONV_OPTION
+ if (flags & RL_CONVERT) {
+ xbuf outbuf;
+ INIT_XBUF(outbuf, buf, 0, bufsiz);
+ iconv_buf.pos = 0;
+ iconv_buf.len = s - iconv_buf.buf;
+ iconvbufs(ic_recv, &iconv_buf, &outbuf,
+ ICB_INCLUDE_BAD | ICB_INCLUDE_INCOMPLETE);
+ outbuf.buf[outbuf.len] = '\0';
+ return outbuf.len;
+ }
+#endif
+
+ return s - buf;
+}
+
+int 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 maxargs = MAX_ARGS;
+ int dot_pos = 0;
+ int argc = 0;
+ char **argv, *p;
+ int rl_flags = (rl_nulls ? RL_EOL_NULLS : 0);
+
+#ifdef ICONV_OPTION
+ rl_flags |= (protect_args && ic_recv != (iconv_t)-1 ? RL_CONVERT : 0);
+#endif
+
+ if (!(argv = new_array(char *, maxargs)))
+ out_of_memory("read_args");
+ if (mod_name)
+ argv[argc++] = "rsyncd";
+
+ while (1) {
+ if (read_line(f_in, buf, bufsiz, rl_flags) == 0)
+ break;
+
+ if (argc == maxargs) {
+ maxargs += MAX_ARGS;
+ if (!(argv = realloc_array(argv, char *, maxargs)))
+ out_of_memory("read_args");
+ }
+
+ if (dot_pos) {
+ if (request_p) {
+ *request_p = strdup(buf);
+ request_p = NULL;
+ }
+ if (mod_name)
+ glob_expand_module(mod_name, buf, &argv, &argc, &maxargs);
+ else
+ glob_expand(buf, &argv, &argc, &maxargs);
+ } else {
+ if (!(p = strdup(buf)))
+ out_of_memory("read_args");
+ argv[argc++] = p;
+ if (*p == '.' && p[1] == '\0')
+ dot_pos = argc;
+ }
+ }
+
+ *argc_p = argc;
+ *argv_p = argv;
+
+ return dot_pos ? dot_pos : argc;
+}
+
+int io_start_buffering_out(int f_out)
+{
+ if (iobuf_out) {
+ assert(f_out == iobuf_f_out);
+ return 0;
+ }
+ if (!(iobuf_out = new_array(char, IO_BUFFER_SIZE)))
+ out_of_memory("io_start_buffering_out");
+ iobuf_out_cnt = 0;
+ iobuf_f_out = f_out;
+ return 1;
+}
+
+int io_start_buffering_in(int f_in)
+{
+ if (iobuf_in) {
+ assert(f_in == iobuf_f_in);
+ return 0;
+ }
+ iobuf_in_siz = 2 * IO_BUFFER_SIZE;
+ if (!(iobuf_in = new_array(char, iobuf_in_siz)))
+ out_of_memory("io_start_buffering_in");
+ iobuf_f_in = f_in;
+ return 1;
+}
+
+void io_end_buffering_in(void)
+{
+ if (!iobuf_in)
+ return;
+ free(iobuf_in);
+ iobuf_in = NULL;
+ iobuf_in_ndx = 0;
+ iobuf_in_remaining = 0;
+ iobuf_f_in = -1;
+}
+
+void io_end_buffering_out(void)
+{
+ if (!iobuf_out)
+ return;
+ io_flush(FULL_FLUSH);
+ free(iobuf_out);
+ iobuf_out = NULL;
+ iobuf_f_out = -1;