#include "dots/output.h" #include #include #include #include #include "dots/err.h" #include "dots/request.h" #include "dots/internal/control_msg.h" #define INITIAL_OUTPUTF_BUF_SIZE 4096 int dots_output(const dots_request_t *req, const unsigned char *data, size_t data_len) { int ret; /* Send a OUTPUT control message. */ struct control_msg msg = { 0 }; ret = dots_send_control_msg(req, &msg, CONTROL_MSG_TYPE_OUTPUT, data, data_len); if (ret) { goto exit; } exit: return ret; } int dots_outputf(const dots_request_t *req, const char *fmt, ...) { int ret; va_list args; va_start(args, fmt); char *buf = NULL; size_t buf_size = INITIAL_OUTPUTF_BUF_SIZE; while (1) { /* Grow (or allocate) buffer. */ char *new_buf = realloc(buf, buf_size); if (!new_buf) { ret = DOTS_ERR_LIBC; goto exit_free_buf; } buf = new_buf; /* Attempt to write format string to buffer. */ ret = vsnprintf(buf, buf_size, fmt, args); if (ret < 0) { ret = DOTS_ERR_LIBC; goto exit_free_buf; } if ((size_t) ret == buf_size) { continue; } size_t data_len = ret; /* Write output and break. */ ret = dots_output(req, (unsigned char *) buf, data_len); if (ret) { goto exit_free_buf; } break; } ret = 0; exit_free_buf: free(buf); return ret; }