+#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 | ICB_INIT);
+ outbuf.buf[outbuf.len] = '\0';
+ return outbuf.len;
+ }
+#endif
+
+ return s - buf;
+}
+
+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 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 && !protect_args)
+ argv[argc++] = "rsyncd";
+
+ while (1) {
+ if (read_line(f_in, buf, bufsiz, rl_flags) == 0)
+ break;
+
+ if (argc == maxargs-1) {
+ 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;
+ }
+ }
+ argv[argc] = NULL;
+
+ glob_expand(NULL, NULL, NULL, NULL);
+
+ *argc_p = argc;
+ *argv_p = argv;
+}
+
+int io_start_buffering_out(int f_out)
+{
+ if (msgs2stderr && DEBUG_GTE(IO, 2))
+ rprintf(FINFO, "[%s] io_start_buffering_out(%d)\n", who_am_i(), f_out);
+
+ if (OUT_MULTIPLEXED && !iobuf.msg.buf) {
+ iobuf.msg.size = IO_BUFFER_SIZE - 4;
+ if (!(iobuf.msg.buf = new_array(char, iobuf.msg.size + 4)))
+ out_of_memory("io_start_buffering_out");
+ iobuf.msg.pos = iobuf.msg.len = 0;
+ }
+
+ if (iobuf.out.buf) {
+ if (iobuf.out_fd == -1)
+ iobuf.out_fd = f_out;
+ assert(f_out == iobuf.out_fd);
+ return 0;
+ }
+
+ iobuf.out.size = IO_BUFFER_SIZE * 2 - 4;
+ /* The 4 overflow bytes makes some circular-buffer wrapping operations easier. */
+ if (!(iobuf.out.buf = new_array(char, iobuf.out.size + 4)))
+ out_of_memory("io_start_buffering_out");
+ iobuf.out.pos = iobuf.out.len = 0;
+ iobuf.out_fd = f_out;
+
+ return 1;
+}
+
+int io_start_buffering_in(int f_in)
+{
+ if (msgs2stderr && DEBUG_GTE(IO, 2))
+ rprintf(FINFO, "[%s] io_start_buffering_in(%d)\n", who_am_i(), f_in);
+
+ if (iobuf.in.buf) {
+ if (iobuf.in_fd == -1)
+ iobuf.in_fd = f_in;
+ assert(f_in == iobuf.in_fd);
+ return 0;
+ }
+
+ iobuf.in.size = IO_BUFFER_SIZE;
+ if (!(iobuf.in.buf = new_array(char, iobuf.in.size)))
+ out_of_memory("io_start_buffering_in");
+
+ iobuf.in.pos = iobuf.in.len = 0;
+
+ iobuf.in_fd = f_in;
+
+ return 1;
+}
+
+static void free_xbuf(xbuf *x)
+{
+ if (x->buf)
+ free(x->buf);
+ memset(x, 0, sizeof (xbuf));
+}
+
+void io_end_buffering_in(BOOL free_buffers)
+{
+ if (DEBUG_GTE(IO, 2)) {
+ rprintf(FINFO, "[%s] io_end_buffering_in(%s)\n",
+ who_am_i(), free_buffers ? "True" : "False");
+ }
+
+ if (free_buffers)
+ free_xbuf(&iobuf.in);
+ else
+ iobuf.in.pos = iobuf.in.len = 0;
+
+ iobuf.in_fd = -1;
+}
+
+void io_end_buffering_out(BOOL free_buffers)
+{
+ if (DEBUG_GTE(IO, 2)) {
+ rprintf(FINFO, "[%s] io_end_buffering_out(%s)\n",
+ who_am_i(), free_buffers ? "True" : "False");
+ }
+
+ io_flush(FULL_FLUSH);
+
+ if (free_buffers) {
+ free_xbuf(&iobuf.out);
+ free_xbuf(&iobuf.msg);
+ } else {
+ iobuf.out.pos = iobuf.out.len = 0;
+ iobuf.msg.pos = iobuf.msg.len = 0;
+ }
+
+ iobuf.out_fd = -1;