void exchange_katcl(struct katcl_line *l, int fd) { sane_line_katcl(l); /* WARNING: exchanging fds forces discarding of pending io */ if(l->l_fd >= 0){ close(l->l_fd); } l->l_fd = fd; if(l->l_ready){ destroy_parse_katcl(l->l_ready); l->l_ready = NULL; } if(l->l_next){ l->l_next = reuse_parse_katcl(l->l_next); } if(l->l_stage){ destroy_parse_katcl(l->l_stage); l->l_stage = NULL; } l->l_pending = 0; l->l_arg = 0; l->l_offset = 0; clear_queue_katcl(l->l_queue); l->l_error = 0; l->l_sendable = 1; }
void discard_katcl(struct katcl_line *l) { sane_line_katcl(l); if(l->l_next){ l->l_next = reuse_parse_katcl(l->l_next); } }
int load_katcl(struct katcl_line *l, char *buffer, unsigned int size) { char *ptr; struct katcl_parse *p; sane_line_katcl(l); #if DEBUG > 1 fprintf(stderr, "line: invoking read on line %p\n", l); #endif #ifdef KATCP_CONSISTENCY_CHECKS if(l->l_next == NULL){ fprintf(stderr, "line: logic failure, l_next should always be valid\n"); abort(); } #endif p = l->l_next; if(p->p_size <= (p->p_have + size)){ ptr = (char *)realloc(p->p_buffer, p->p_have + size + 1); if(ptr == NULL){ #ifdef DEBUG fprintf(stderr, "read: realloc to %d failed\n", p->p_size + KATCL_BUFFER_INC); #endif l->l_error = ENOMEM; return -1; } p->p_buffer = ptr; p->p_size = p->p_have + size + 1; } memcpy(p->p_buffer + p->p_have, buffer, size); p->p_have += size; return 0; }
static struct katcl_parse *before_append_katcl(struct katcl_line *l, int flags) { sane_line_katcl(l); #if DEBUG > 1 fprintf(stderr, "line: about to append 0x%x to %p\n", flags, l); #endif if(l->l_stage == NULL){ if(!(flags & KATCP_FLAG_FIRST)){ #ifdef DEBUG fprintf(stderr, "discarding appended data as stage empty\n"); #endif return NULL; } l->l_stage = create_referenced_parse_katcl(); } return l->l_stage; }
int read_katcl(struct katcl_line *l) { int rr; char *ptr; struct katcl_parse *p; sane_line_katcl(l); #if DEBUG > 1 fprintf(stderr, "line: invoking read on line %p\n", l); #endif #ifdef KATCP_CONSISTENCY_CHECKS if(l->l_next == NULL){ fprintf(stderr, "line: logic failure, l_next should always be valid\n"); abort(); } #endif p = l->l_next; if(p->p_size <= p->p_have){ ptr = (char *)realloc(p->p_buffer, p->p_size + KATCL_BUFFER_INC); if(ptr == NULL){ #ifdef DEBUG fprintf(stderr, "read: realloc to %d failed\n", p->p_size + KATCL_BUFFER_INC); #endif l->l_error = ENOMEM; return -1; } p->p_buffer = ptr; p->p_size += KATCL_BUFFER_INC; } rr = read(l->l_fd, p->p_buffer + p->p_have, p->p_size - p->p_have); if(rr < 0){ switch(errno){ case ECONNRESET : #ifdef DEBUG fprintf(stderr, "read: connect reset\n"); #endif return 1; case EAGAIN : case EINTR : return 0; /* more to be read */ default : /* serious error */ l->l_error = errno; #ifdef DEBUG fprintf(stderr, "read: read error: %s\n", strerror(errno)); #endif return -1; } } if(rr == 0){ /* EOF */ #ifdef DEBUG fprintf(stderr, "read: end of file\n"); #endif return 1; } p->p_have += rr; return 0; }