+int read_line(int f, char *buf, int maxlen)
+{
+ while (maxlen) {
+ read_buf(f, buf, 1);
+ if (buf[0] == '\n') {
+ buf[0] = 0;
+ break;
+ }
+ if (buf[0] != '\r') {
+ buf++;
+ maxlen--;
+ }
+ }
+ if (maxlen == 0) {
+ *buf = 0;
+ return 0;
+ }
+ return 1;
+}
+
+
+void io_printf(int fd, const char *format, ...)
+{
+ va_list ap;
+ char buf[1024];
+ int len;
+
+ va_start(ap, format);
+ len = vslprintf(buf, sizeof(buf)-1, format, ap);
+ va_end(ap);
+
+ if (len < 0) exit_cleanup(1);
+
+ write_sbuf(fd, buf);
+}
+
+
+/* setup for multiplexing an error stream with the data stream */
+void io_start_multiplex_out(int fd)
+{
+ multiplex_out_fd = fd;
+ io_flush();
+ io_start_buffering(fd);
+ io_multiplexing_out = 1;
+}
+
+/* setup for multiplexing an error stream with the data stream */
+void io_start_multiplex_in(int fd)
+{
+ multiplex_in_fd = fd;
+ io_flush();
+ if (read_buffer_len) {
+ fprintf(stderr,"ERROR: data in read buffer at mplx start\n");
+ exit_cleanup(1);
+ }
+
+ io_multiplexing_in = 1;
+}
+
+/* write an message to the error stream */
+int io_multiplex_write(int f, char *buf, int len)
+{
+ if (!io_multiplexing_out) return 0;
+
+ io_flush();
+
+ SIVAL(io_buffer-4, 0, ((MPLEX_BASE + f)<<24) + len);
+ memcpy(io_buffer, buf, len);
+
+ writefd_unbuffered(multiplex_out_fd, io_buffer-4, len+4);
+ return 1;
+}
+
+void io_close_input(int fd)
+{
+ buffer_f_in = -1;
+}