bool status_read(struct status_output *so, struct buffer *buf) { bool ret = false; if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_READ)) { ASSERT(buf_defined(&so->read_buf)); ASSERT(buf_defined(buf)); while (true) { const int c = buf_read_u8(&so->read_buf); /* read more of file into buffer */ if (c == -1) { int len; ASSERT(buf_init(&so->read_buf, 0)); len = read(so->fd, BPTR(&so->read_buf), BCAP(&so->read_buf)); if (len <= 0) { break; } ASSERT(buf_inc_len(&so->read_buf, len)); continue; } ret = true; if (c == '\r') { continue; } if (c == '\n') { break; } buf_write_u8(buf, c); } buf_null_terminate(buf); } return ret; }
/* return false if error occurred */ bool status_close(struct status_output *so) { bool ret = true; if (so) { if (so->errors) { ret = false; } if (so->fd >= 0) { if (close(so->fd) < 0) { ret = false; } } if (so->filename) { free(so->filename); } if (buf_defined(&so->read_buf)) { free_buf(&so->read_buf); } free(so); } else { ret = false; } return ret; }
void status_flush(struct status_output *so) { if (so && so->fd >= 0 && (so->flags & STATUS_OUTPUT_WRITE)) { #if defined(HAVE_FTRUNCATE) { const off_t off = lseek(so->fd, (off_t)0, SEEK_CUR); if (ftruncate(so->fd, off) != 0) { msg(M_WARN, "Failed to truncate status file: %s", strerror(errno)); } } #elif defined(HAVE_CHSIZE) { const long off = (long) lseek(so->fd, (off_t)0, SEEK_CUR); chsize(so->fd, off); } #else /* if defined(HAVE_FTRUNCATE) */ #warning both ftruncate and chsize functions appear to be missing from this OS #endif /* clear read buffer */ if (buf_defined(&so->read_buf)) { ASSERT(buf_init(&so->read_buf, 0)); } } }
/* * printf append to a buffer with overflow check */ void buf_printf (struct buffer *buf, const char *format, ...) { if (buf_defined (buf)) { va_list arglist; uint8_t *ptr = BEND (buf); int cap = buf_forward_capacity (buf); if (cap > 0) { va_start (arglist, format); vsnprintf ((char *)ptr, cap, format, arglist); va_end (arglist); *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ buf->len += (int) strlen ((char *)ptr); } } }
bool buf_printf (struct buffer *buf, const char *format, ...) { int ret = false; if (buf_defined (buf)) { va_list arglist; uint8_t *ptr = buf_bend (buf); int cap = buf_forward_capacity (buf); if (cap > 0) { int stat; va_start (arglist, format); stat = vsnprintf ((char *)ptr, cap, format, arglist); va_end (arglist); *(buf->data + buf->capacity - 1) = 0; /* windows vsnprintf needs this */ buf->len += (int) strlen ((char *)ptr); if (stat >= 0 && stat < cap) ret = true; } } return ret; }
static bool recv_line (socket_descriptor_t sd, char *buf, int len, const int timeout_sec, const bool verbose, struct buffer *lookahead, volatile int *signal_received) { struct buffer la; int lastc = 0; CLEAR (la); if (lookahead) la = *lookahead; while (true) { int status; ssize_t size; fd_set reads; struct timeval tv; uint8_t c; if (buf_defined (&la)) { ASSERT (buf_init (&la, 0)); } FD_ZERO (&reads); FD_SET (sd, &reads); tv.tv_sec = timeout_sec; tv.tv_usec = 0; status = select (sd + 1, &reads, NULL, NULL, &tv); get_signal (signal_received); if (*signal_received) goto error; /* timeout? */ if (status == 0) { if (verbose) msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_line: TCP port read timeout expired"); goto error; } /* error */ if (status < 0) { if (verbose) msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_line: TCP port read failed on select()"); goto error; } /* read single char */ size = recv (sd, &c, 1, MSG_NOSIGNAL); /* error? */ if (size != 1) { if (verbose) msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_line: TCP port read failed on recv()"); goto error; } #if 0 if (isprint(c)) msg (M_INFO, "PROXY: read '%c' (%d)", c, (int)c); else msg (M_INFO, "PROXY: read (%d)", (int)c); #endif /* store char in buffer */ if (len > 1) { *buf++ = c; --len; } /* also store char in lookahead buffer */ if (buf_defined (&la)) { buf_write_u8 (&la, c); if (!isprint(c) && !isspace(c)) /* not ascii? */ { if (verbose) msg (D_LINK_ERRORS | M_ERRNO_SOCK, "recv_line: Non-ASCII character (%d) read on recv()", (int)c); *lookahead = la; return false; } } /* end of line? */ if (lastc == '\r' && c == '\n') break; lastc = c; } /* append trailing null */ if (len > 0) *buf++ = '\0'; return true; error: return false; }