1175282Sobrien/* 2175282Sobrien * Copyright (C) 1996-2005 The Free Software Foundation, Inc. 3175282Sobrien * 4175282Sobrien * This program is free software; you can redistribute it and/or modify 5175282Sobrien * it under the terms of the GNU General Public License as published by 6175282Sobrien * the Free Software Foundation; either version 2, or (at your option) 7175282Sobrien * any later version. 8175282Sobrien * 9175282Sobrien * This program is distributed in the hope that it will be useful, 10175282Sobrien * but WITHOUT ANY WARRANTY; without even the implied warranty of 11175282Sobrien * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12175282Sobrien * GNU General Public License for more details. 13175282Sobrien */ 14175282Sobrien 1525839Speter/* Code for the buffer data structure. */ 1625839Speter 17102852Speter/* $FreeBSD$ */ 18102852Speter 1925839Speter#include <assert.h> 2025839Speter#include "cvs.h" 2125839Speter#include "buffer.h" 2225839Speter 2325839Speter#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) 2425839Speter 25102840Speter#ifdef HAVE_WINSOCK_H 26102840Speter# include <winsock.h> 27102840Speter#else 28102840Speter# include <sys/socket.h> 29102840Speter#endif 30102840Speter 3125839Speter/* OS/2 doesn't have EIO. FIXME: this whole notion of turning 3225839Speter a different error into EIO strikes me as pretty dubious. */ 3325839Speter#if !defined (EIO) 3425839Speter#define EIO EBADPOS 3525839Speter#endif 3625839Speter 3725839Speter/* Linked list of available buffer_data structures. */ 3825839Speterstatic struct buffer_data *free_buffer_data; 3925839Speter 4025839Speter/* Local functions. */ 4134461Speterstatic void buf_default_memory_error PROTO ((struct buffer *)); 4225839Speterstatic void allocate_buffer_datas PROTO((void)); 4325839Speterstatic struct buffer_data *get_buffer_data PROTO((void)); 4425839Speter 4525839Speter/* Initialize a buffer structure. */ 4625839Speter 4725839Speterstruct buffer * 4825839Speterbuf_initialize (input, output, flush, block, shutdown, memory, closure) 4925839Speter int (*input) PROTO((void *, char *, int, int, int *)); 5025839Speter int (*output) PROTO((void *, const char *, int, int *)); 5125839Speter int (*flush) PROTO((void *)); 5225839Speter int (*block) PROTO((void *, int)); 53102840Speter int (*shutdown) PROTO((struct buffer *)); 5425839Speter void (*memory) PROTO((struct buffer *)); 5525839Speter void *closure; 5625839Speter{ 5725839Speter struct buffer *buf; 5825839Speter 5925839Speter buf = (struct buffer *) xmalloc (sizeof (struct buffer)); 6025839Speter buf->data = NULL; 6125839Speter buf->last = NULL; 6225839Speter buf->nonblocking = 0; 6325839Speter buf->input = input; 6425839Speter buf->output = output; 6525839Speter buf->flush = flush; 6625839Speter buf->block = block; 6725839Speter buf->shutdown = shutdown; 6834461Speter buf->memory_error = memory ? memory : buf_default_memory_error; 6925839Speter buf->closure = closure; 7025839Speter return buf; 7125839Speter} 7225839Speter 7334461Speter/* Free a buffer structure. */ 7434461Speter 7534461Spetervoid 7634461Speterbuf_free (buf) 7734461Speter struct buffer *buf; 7834461Speter{ 79128269Speter if (buf->closure != NULL) 80128269Speter { 81128269Speter free (buf->closure); 82128269Speter buf->closure = NULL; 83128269Speter } 8434461Speter if (buf->data != NULL) 8534461Speter { 8634461Speter buf->last->next = free_buffer_data; 8734461Speter free_buffer_data = buf->data; 8834461Speter } 8934461Speter free (buf); 9034461Speter} 9134461Speter 9225839Speter/* Initialize a buffer structure which is not to be used for I/O. */ 9325839Speter 9425839Speterstruct buffer * 9525839Speterbuf_nonio_initialize (memory) 9625839Speter void (*memory) PROTO((struct buffer *)); 9725839Speter{ 9825839Speter return (buf_initialize 9925839Speter ((int (*) PROTO((void *, char *, int, int, int *))) NULL, 10025839Speter (int (*) PROTO((void *, const char *, int, int *))) NULL, 10125839Speter (int (*) PROTO((void *))) NULL, 10225839Speter (int (*) PROTO((void *, int))) NULL, 103102840Speter (int (*) PROTO((struct buffer *))) NULL, 10425839Speter memory, 10525839Speter (void *) NULL)); 10625839Speter} 10725839Speter 10834461Speter/* Default memory error handler. */ 10934461Speter 11034461Speterstatic void 11134461Speterbuf_default_memory_error (buf) 11234461Speter struct buffer *buf; 11334461Speter{ 11434461Speter error (1, 0, "out of memory"); 11534461Speter} 11634461Speter 11725839Speter/* Allocate more buffer_data structures. */ 11825839Speter 11925839Speterstatic void 12025839Speterallocate_buffer_datas () 12125839Speter{ 12225839Speter struct buffer_data *alc; 12325839Speter char *space; 12425839Speter int i; 12525839Speter 12625839Speter /* Allocate buffer_data structures in blocks of 16. */ 12725839Speter#define ALLOC_COUNT (16) 12825839Speter 129175282Sobrien alc = xmalloc (ALLOC_COUNT * sizeof (struct buffer_data)); 13025839Speter space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE); 131175282Sobrien if (!space) 132175282Sobrien { 133175282Sobrien free (alc); 13425839Speter return; 135175282Sobrien } 13625839Speter for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE) 13725839Speter { 13825839Speter alc->next = free_buffer_data; 13925839Speter free_buffer_data = alc; 14025839Speter alc->text = space; 14125839Speter } 14225839Speter} 14325839Speter 14425839Speter/* Get a new buffer_data structure. */ 14525839Speter 14625839Speterstatic struct buffer_data * 14725839Speterget_buffer_data () 14825839Speter{ 14925839Speter struct buffer_data *ret; 15025839Speter 15125839Speter if (free_buffer_data == NULL) 15225839Speter { 15325839Speter allocate_buffer_datas (); 15425839Speter if (free_buffer_data == NULL) 15525839Speter return NULL; 15625839Speter } 15725839Speter 15825839Speter ret = free_buffer_data; 15925839Speter free_buffer_data = ret->next; 16025839Speter return ret; 16125839Speter} 16225839Speter 16325839Speter 164128269Speter 165128269Speter/* See whether a buffer and its file descriptor is empty. */ 16625839Speterint 167128269Speterbuf_empty (buf) 168128269Speter struct buffer *buf; 169128269Speter{ 170128269Speter /* Try and read any data on the file descriptor first. 171128269Speter * We already know the descriptor is non-blocking. 172128269Speter */ 173128269Speter buf_input_data (buf, NULL); 174128269Speter return buf_empty_p (buf); 175128269Speter} 176128269Speter 177128269Speter 178128269Speter 179128269Speter/* See whether a buffer is empty. */ 180128269Speterint 18125839Speterbuf_empty_p (buf) 18225839Speter struct buffer *buf; 18325839Speter{ 18425839Speter struct buffer_data *data; 18525839Speter 18625839Speter for (data = buf->data; data != NULL; data = data->next) 18725839Speter if (data->size > 0) 18825839Speter return 0; 18925839Speter return 1; 19025839Speter} 19125839Speter 192128269Speter 193128269Speter 19425839Speter#ifdef SERVER_FLOWCONTROL 19525839Speter/* 19625839Speter * Count how much data is stored in the buffer.. 197109660Speter * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE. 19825839Speter */ 19925839Speter 20025839Speterint 20125839Speterbuf_count_mem (buf) 20225839Speter struct buffer *buf; 20325839Speter{ 20425839Speter struct buffer_data *data; 20525839Speter int mem = 0; 20625839Speter 20725839Speter for (data = buf->data; data != NULL; data = data->next) 20825839Speter mem += BUFFER_DATA_SIZE; 20925839Speter 21025839Speter return mem; 21125839Speter} 21225839Speter#endif /* SERVER_FLOWCONTROL */ 21325839Speter 21425839Speter/* Add data DATA of length LEN to BUF. */ 21525839Speter 21625839Spetervoid 21725839Speterbuf_output (buf, data, len) 21825839Speter struct buffer *buf; 21925839Speter const char *data; 22025839Speter int len; 22125839Speter{ 22225839Speter if (buf->data != NULL 22325839Speter && (((buf->last->text + BUFFER_DATA_SIZE) 22425839Speter - (buf->last->bufp + buf->last->size)) 22525839Speter >= len)) 22625839Speter { 22725839Speter memcpy (buf->last->bufp + buf->last->size, data, len); 22825839Speter buf->last->size += len; 22925839Speter return; 23025839Speter } 23125839Speter 23225839Speter while (1) 23325839Speter { 23425839Speter struct buffer_data *newdata; 23525839Speter 23625839Speter newdata = get_buffer_data (); 23725839Speter if (newdata == NULL) 23825839Speter { 23925839Speter (*buf->memory_error) (buf); 24025839Speter return; 24125839Speter } 24225839Speter 24325839Speter if (buf->data == NULL) 24425839Speter buf->data = newdata; 24525839Speter else 24625839Speter buf->last->next = newdata; 24725839Speter newdata->next = NULL; 24825839Speter buf->last = newdata; 24925839Speter 25025839Speter newdata->bufp = newdata->text; 25125839Speter 25225839Speter if (len <= BUFFER_DATA_SIZE) 25325839Speter { 25425839Speter newdata->size = len; 25525839Speter memcpy (newdata->text, data, len); 25625839Speter return; 25725839Speter } 25825839Speter 25925839Speter newdata->size = BUFFER_DATA_SIZE; 26025839Speter memcpy (newdata->text, data, BUFFER_DATA_SIZE); 26125839Speter 26225839Speter data += BUFFER_DATA_SIZE; 26325839Speter len -= BUFFER_DATA_SIZE; 26425839Speter } 26525839Speter 26625839Speter /*NOTREACHED*/ 26725839Speter} 26825839Speter 26925839Speter/* Add a '\0' terminated string to BUF. */ 27025839Speter 27125839Spetervoid 27225839Speterbuf_output0 (buf, string) 27325839Speter struct buffer *buf; 27425839Speter const char *string; 27525839Speter{ 27625839Speter buf_output (buf, string, strlen (string)); 27725839Speter} 27825839Speter 27925839Speter/* Add a single character to BUF. */ 28025839Speter 28125839Spetervoid 28225839Speterbuf_append_char (buf, ch) 28325839Speter struct buffer *buf; 28425839Speter int ch; 28525839Speter{ 28625839Speter if (buf->data != NULL 28725839Speter && (buf->last->text + BUFFER_DATA_SIZE 28825839Speter != buf->last->bufp + buf->last->size)) 28925839Speter { 29025839Speter *(buf->last->bufp + buf->last->size) = ch; 29125839Speter ++buf->last->size; 29225839Speter } 29325839Speter else 29425839Speter { 29525839Speter char b; 29625839Speter 29725839Speter b = ch; 29825839Speter buf_output (buf, &b, 1); 29925839Speter } 30025839Speter} 30125839Speter 30225839Speter/* 30325839Speter * Send all the output we've been saving up. Returns 0 for success or 30425839Speter * errno code. If the buffer has been set to be nonblocking, this 30525839Speter * will just write until the write would block. 30625839Speter */ 30725839Speter 30825839Speterint 30925839Speterbuf_send_output (buf) 31025839Speter struct buffer *buf; 31125839Speter{ 31225839Speter if (buf->output == NULL) 31325839Speter abort (); 31425839Speter 31525839Speter while (buf->data != NULL) 31625839Speter { 31725839Speter struct buffer_data *data; 31825839Speter 31925839Speter data = buf->data; 32025839Speter 32125839Speter if (data->size > 0) 32225839Speter { 32325839Speter int status, nbytes; 32425839Speter 32525839Speter status = (*buf->output) (buf->closure, data->bufp, data->size, 32625839Speter &nbytes); 32725839Speter if (status != 0) 32825839Speter { 32925839Speter /* Some sort of error. Discard the data, and return. */ 33025839Speter 33125839Speter buf->last->next = free_buffer_data; 33225839Speter free_buffer_data = buf->data; 33325839Speter buf->data = NULL; 33425839Speter buf->last = NULL; 33525839Speter 33625839Speter return status; 33725839Speter } 33825839Speter 33925839Speter if (nbytes != data->size) 34025839Speter { 34125839Speter /* Not all the data was written out. This is only 34225839Speter permitted in nonblocking mode. Adjust the buffer, 34325839Speter and return. */ 34425839Speter 34525839Speter assert (buf->nonblocking); 34625839Speter 34725839Speter data->size -= nbytes; 34825839Speter data->bufp += nbytes; 34925839Speter 35025839Speter return 0; 35125839Speter } 35225839Speter } 35325839Speter 35425839Speter buf->data = data->next; 35525839Speter data->next = free_buffer_data; 35625839Speter free_buffer_data = data; 35725839Speter } 35825839Speter 35925839Speter buf->last = NULL; 36025839Speter 36125839Speter return 0; 36225839Speter} 36325839Speter 36425839Speter/* 36525839Speter * Flush any data queued up in the buffer. If BLOCK is nonzero, then 36625839Speter * if the buffer is in nonblocking mode, put it into blocking mode for 36725839Speter * the duration of the flush. This returns 0 on success, or an error 36825839Speter * code. 36925839Speter */ 37025839Speter 37125839Speterint 37225839Speterbuf_flush (buf, block) 37325839Speter struct buffer *buf; 37425839Speter int block; 37525839Speter{ 37625839Speter int nonblocking; 37725839Speter int status; 37825839Speter 37925839Speter if (buf->flush == NULL) 38025839Speter abort (); 38125839Speter 38225839Speter nonblocking = buf->nonblocking; 38325839Speter if (nonblocking && block) 38425839Speter { 38525839Speter status = set_block (buf); 38625839Speter if (status != 0) 38725839Speter return status; 38825839Speter } 38925839Speter 39025839Speter status = buf_send_output (buf); 39125839Speter if (status == 0) 39225839Speter status = (*buf->flush) (buf->closure); 39325839Speter 39425839Speter if (nonblocking && block) 39525839Speter { 39625839Speter int blockstat; 39725839Speter 39825839Speter blockstat = set_nonblock (buf); 39925839Speter if (status == 0) 40025839Speter status = blockstat; 40125839Speter } 40225839Speter 40325839Speter return status; 40425839Speter} 40525839Speter 40625839Speter/* 40725839Speter * Set buffer BUF to nonblocking I/O. Returns 0 for success or errno 40825839Speter * code. 40925839Speter */ 41025839Speter 41125839Speterint 41225839Speterset_nonblock (buf) 41325839Speter struct buffer *buf; 41425839Speter{ 41525839Speter int status; 41625839Speter 41725839Speter if (buf->nonblocking) 41825839Speter return 0; 41925839Speter if (buf->block == NULL) 42025839Speter abort (); 42125839Speter status = (*buf->block) (buf->closure, 0); 42225839Speter if (status != 0) 42325839Speter return status; 42425839Speter buf->nonblocking = 1; 42525839Speter return 0; 42625839Speter} 42725839Speter 42825839Speter/* 42925839Speter * Set buffer BUF to blocking I/O. Returns 0 for success or errno 43025839Speter * code. 43125839Speter */ 43225839Speter 43325839Speterint 43425839Speterset_block (buf) 43525839Speter struct buffer *buf; 43625839Speter{ 43725839Speter int status; 43825839Speter 43925839Speter if (! buf->nonblocking) 44025839Speter return 0; 44125839Speter if (buf->block == NULL) 44225839Speter abort (); 44325839Speter status = (*buf->block) (buf->closure, 1); 44425839Speter if (status != 0) 44525839Speter return status; 44625839Speter buf->nonblocking = 0; 44725839Speter return 0; 44825839Speter} 44925839Speter 45025839Speter/* 45125839Speter * Send a character count and some output. Returns errno code or 0 for 45225839Speter * success. 45325839Speter * 45425839Speter * Sending the count in binary is OK since this is only used on a pipe 45525839Speter * within the same system. 45625839Speter */ 45725839Speter 45825839Speterint 45925839Speterbuf_send_counted (buf) 46025839Speter struct buffer *buf; 46125839Speter{ 46225839Speter int size; 46325839Speter struct buffer_data *data; 46425839Speter 46525839Speter size = 0; 46625839Speter for (data = buf->data; data != NULL; data = data->next) 46725839Speter size += data->size; 46825839Speter 46925839Speter data = get_buffer_data (); 47025839Speter if (data == NULL) 47125839Speter { 47225839Speter (*buf->memory_error) (buf); 47325839Speter return ENOMEM; 47425839Speter } 47525839Speter 47625839Speter data->next = buf->data; 47725839Speter buf->data = data; 47825839Speter if (buf->last == NULL) 47925839Speter buf->last = data; 48025839Speter 48125839Speter data->bufp = data->text; 48225839Speter data->size = sizeof (int); 48325839Speter 48425839Speter *((int *) data->text) = size; 48525839Speter 48625839Speter return buf_send_output (buf); 48725839Speter} 48825839Speter 48925839Speter/* 49025839Speter * Send a special count. COUNT should be negative. It will be 49125839Speter * handled speciallyi by buf_copy_counted. This function returns 0 or 49225839Speter * an errno code. 49325839Speter * 49425839Speter * Sending the count in binary is OK since this is only used on a pipe 49525839Speter * within the same system. 49625839Speter */ 49725839Speter 49825839Speterint 49925839Speterbuf_send_special_count (buf, count) 50025839Speter struct buffer *buf; 50125839Speter int count; 50225839Speter{ 50325839Speter struct buffer_data *data; 50425839Speter 50525839Speter data = get_buffer_data (); 50625839Speter if (data == NULL) 50725839Speter { 50825839Speter (*buf->memory_error) (buf); 50925839Speter return ENOMEM; 51025839Speter } 51125839Speter 51225839Speter data->next = buf->data; 51325839Speter buf->data = data; 51425839Speter if (buf->last == NULL) 51525839Speter buf->last = data; 51625839Speter 51725839Speter data->bufp = data->text; 51825839Speter data->size = sizeof (int); 51925839Speter 52025839Speter *((int *) data->text) = count; 52125839Speter 52225839Speter return buf_send_output (buf); 52325839Speter} 52425839Speter 52525839Speter/* Append a list of buffer_data structures to an buffer. */ 52625839Speter 52725839Spetervoid 52825839Speterbuf_append_data (buf, data, last) 52925839Speter struct buffer *buf; 53025839Speter struct buffer_data *data; 53125839Speter struct buffer_data *last; 53225839Speter{ 53325839Speter if (data != NULL) 53425839Speter { 53525839Speter if (buf->data == NULL) 53625839Speter buf->data = data; 53725839Speter else 53825839Speter buf->last->next = data; 53925839Speter buf->last = last; 54025839Speter } 54125839Speter} 54225839Speter 54334461Speter/* Append the data on one buffer to another. This removes the data 54434461Speter from the source buffer. */ 54534461Speter 54634461Spetervoid 54734461Speterbuf_append_buffer (to, from) 54834461Speter struct buffer *to; 54934461Speter struct buffer *from; 55034461Speter{ 55134461Speter buf_append_data (to, from->data, from->last); 55234461Speter from->data = NULL; 55334461Speter from->last = NULL; 55434461Speter} 55534461Speter 55625839Speter/* 55725839Speter * Copy the contents of file F into buffer_data structures. We can't 55825839Speter * copy directly into an buffer, because we want to handle failure and 55925839Speter * succeess differently. Returns 0 on success, or -2 if out of 56025839Speter * memory, or a status code on error. Since the caller happens to 56125839Speter * know the size of the file, it is passed in as SIZE. On success, 56225839Speter * this function sets *RETP and *LASTP, which may be passed to 56325839Speter * buf_append_data. 56425839Speter */ 56525839Speter 56625839Speterint 56725839Speterbuf_read_file (f, size, retp, lastp) 56825839Speter FILE *f; 56925839Speter long size; 57025839Speter struct buffer_data **retp; 57125839Speter struct buffer_data **lastp; 57225839Speter{ 57325839Speter int status; 57425839Speter 57525839Speter *retp = NULL; 57625839Speter *lastp = NULL; 57725839Speter 57825839Speter while (size > 0) 57925839Speter { 58025839Speter struct buffer_data *data; 58125839Speter int get; 58225839Speter 58325839Speter data = get_buffer_data (); 58425839Speter if (data == NULL) 58525839Speter { 58625839Speter status = -2; 58725839Speter goto error_return; 58825839Speter } 58925839Speter 59025839Speter if (*retp == NULL) 59125839Speter *retp = data; 59225839Speter else 59325839Speter (*lastp)->next = data; 59425839Speter data->next = NULL; 59525839Speter *lastp = data; 59625839Speter 59725839Speter data->bufp = data->text; 59825839Speter data->size = 0; 59925839Speter 60025839Speter if (size > BUFFER_DATA_SIZE) 60125839Speter get = BUFFER_DATA_SIZE; 60225839Speter else 60325839Speter get = size; 60425839Speter 60525839Speter errno = EIO; 60625839Speter if (fread (data->text, get, 1, f) != 1) 60725839Speter { 60825839Speter status = errno; 60925839Speter goto error_return; 61025839Speter } 61125839Speter 61225839Speter data->size += get; 61325839Speter size -= get; 61425839Speter } 61525839Speter 61625839Speter return 0; 61725839Speter 61825839Speter error_return: 61925839Speter if (*retp != NULL) 62025839Speter { 62125839Speter (*lastp)->next = free_buffer_data; 62225839Speter free_buffer_data = *retp; 62325839Speter } 62425839Speter return status; 62525839Speter} 62625839Speter 62725839Speter/* 62825839Speter * Copy the contents of file F into buffer_data structures. We can't 62925839Speter * copy directly into an buffer, because we want to handle failure and 63025839Speter * succeess differently. Returns 0 on success, or -2 if out of 63125839Speter * memory, or a status code on error. On success, this function sets 63225839Speter * *RETP and *LASTP, which may be passed to buf_append_data. 63325839Speter */ 63425839Speter 63525839Speterint 63625839Speterbuf_read_file_to_eof (f, retp, lastp) 63725839Speter FILE *f; 63825839Speter struct buffer_data **retp; 63925839Speter struct buffer_data **lastp; 64025839Speter{ 64125839Speter int status; 64225839Speter 64325839Speter *retp = NULL; 64425839Speter *lastp = NULL; 64525839Speter 64625839Speter while (!feof (f)) 64725839Speter { 64825839Speter struct buffer_data *data; 64925839Speter int get, nread; 65025839Speter 65125839Speter data = get_buffer_data (); 65225839Speter if (data == NULL) 65325839Speter { 65425839Speter status = -2; 65525839Speter goto error_return; 65625839Speter } 65725839Speter 65825839Speter if (*retp == NULL) 65925839Speter *retp = data; 66025839Speter else 66125839Speter (*lastp)->next = data; 66225839Speter data->next = NULL; 66325839Speter *lastp = data; 66425839Speter 66525839Speter data->bufp = data->text; 66625839Speter data->size = 0; 66725839Speter 66825839Speter get = BUFFER_DATA_SIZE; 66925839Speter 67025839Speter errno = EIO; 67125839Speter nread = fread (data->text, 1, get, f); 67225839Speter if (nread == 0 && !feof (f)) 67325839Speter { 67425839Speter status = errno; 67525839Speter goto error_return; 67625839Speter } 67725839Speter 67825839Speter data->size = nread; 67925839Speter } 68025839Speter 68125839Speter return 0; 68225839Speter 68325839Speter error_return: 68425839Speter if (*retp != NULL) 68525839Speter { 68625839Speter (*lastp)->next = free_buffer_data; 68725839Speter free_buffer_data = *retp; 68825839Speter } 68925839Speter return status; 69025839Speter} 69125839Speter 69225839Speter/* Return the number of bytes in a chain of buffer_data structures. */ 69325839Speter 69425839Speterint 69525839Speterbuf_chain_length (buf) 69625839Speter struct buffer_data *buf; 69725839Speter{ 69825839Speter int size = 0; 69925839Speter while (buf) 70025839Speter { 70125839Speter size += buf->size; 70225839Speter buf = buf->next; 70325839Speter } 70425839Speter return size; 70525839Speter} 70625839Speter 70734461Speter/* Return the number of bytes in a buffer. */ 70834461Speter 70934461Speterint 71034461Speterbuf_length (buf) 71134461Speter struct buffer *buf; 71234461Speter{ 71334461Speter return buf_chain_length (buf->data); 71434461Speter} 71534461Speter 71625839Speter/* 71725839Speter * Read an arbitrary amount of data into an input buffer. The buffer 71825839Speter * will be in nonblocking mode, and we just grab what we can. Return 71925839Speter * 0 on success, or -1 on end of file, or -2 if out of memory, or an 72025839Speter * error code. If COUNTP is not NULL, *COUNTP is set to the number of 72125839Speter * bytes read. 72225839Speter */ 72325839Speter 72425839Speterint 72525839Speterbuf_input_data (buf, countp) 72625839Speter struct buffer *buf; 72725839Speter int *countp; 72825839Speter{ 72925839Speter if (buf->input == NULL) 73025839Speter abort (); 73125839Speter 73225839Speter if (countp != NULL) 73325839Speter *countp = 0; 73425839Speter 73525839Speter while (1) 73625839Speter { 73725839Speter int get; 73825839Speter int status, nbytes; 73925839Speter 74025839Speter if (buf->data == NULL 74125839Speter || (buf->last->bufp + buf->last->size 74225839Speter == buf->last->text + BUFFER_DATA_SIZE)) 74325839Speter { 74425839Speter struct buffer_data *data; 74525839Speter 74625839Speter data = get_buffer_data (); 74725839Speter if (data == NULL) 74825839Speter { 74925839Speter (*buf->memory_error) (buf); 75025839Speter return -2; 75125839Speter } 75225839Speter 75325839Speter if (buf->data == NULL) 75425839Speter buf->data = data; 75525839Speter else 75625839Speter buf->last->next = data; 75725839Speter data->next = NULL; 75825839Speter buf->last = data; 75925839Speter 76025839Speter data->bufp = data->text; 76125839Speter data->size = 0; 76225839Speter } 76325839Speter 76425839Speter get = ((buf->last->text + BUFFER_DATA_SIZE) 76525839Speter - (buf->last->bufp + buf->last->size)); 76625839Speter 76725839Speter status = (*buf->input) (buf->closure, 76825839Speter buf->last->bufp + buf->last->size, 76925839Speter 0, get, &nbytes); 77025839Speter if (status != 0) 77125839Speter return status; 77225839Speter 77325839Speter buf->last->size += nbytes; 77425839Speter if (countp != NULL) 77525839Speter *countp += nbytes; 77625839Speter 77725839Speter if (nbytes < get) 77825839Speter { 77925839Speter /* If we did not fill the buffer, then presumably we read 78025839Speter all the available data. */ 78125839Speter return 0; 78225839Speter } 78325839Speter } 78425839Speter 78525839Speter /*NOTREACHED*/ 78625839Speter} 78725839Speter 78825839Speter/* 78925839Speter * Read a line (characters up to a \012) from an input buffer. (We 79025839Speter * use \012 rather than \n for the benefit of non Unix clients for 79125839Speter * which \n means something else). This returns 0 on success, or -1 79225839Speter * on end of file, or -2 if out of memory, or an error code. If it 79325839Speter * succeeds, it sets *LINE to an allocated buffer holding the contents 79425839Speter * of the line. The trailing \012 is not included in the buffer. If 79525839Speter * LENP is not NULL, then *LENP is set to the number of bytes read; 79625839Speter * strlen may not work, because there may be embedded null bytes. 79725839Speter */ 79825839Speter 79925839Speterint 80025839Speterbuf_read_line (buf, line, lenp) 80125839Speter struct buffer *buf; 80225839Speter char **line; 80325839Speter int *lenp; 80425839Speter{ 80525839Speter if (buf->input == NULL) 80625839Speter abort (); 80725839Speter 80825839Speter *line = NULL; 80925839Speter 81025839Speter while (1) 81125839Speter { 81225839Speter int len, finallen = 0; 81325839Speter struct buffer_data *data; 81425839Speter char *nl; 81525839Speter 81625839Speter /* See if there is a newline in BUF. */ 81725839Speter len = 0; 81825839Speter for (data = buf->data; data != NULL; data = data->next) 81925839Speter { 82025839Speter nl = memchr (data->bufp, '\012', data->size); 82125839Speter if (nl != NULL) 82225839Speter { 82325839Speter finallen = nl - data->bufp; 82425839Speter len += finallen; 82525839Speter break; 82625839Speter } 82725839Speter len += data->size; 82825839Speter } 82925839Speter 83025839Speter /* If we found a newline, copy the line into a memory buffer, 83125839Speter and remove it from BUF. */ 83225839Speter if (data != NULL) 83325839Speter { 83425839Speter char *p; 83525839Speter struct buffer_data *nldata; 83625839Speter 837109660Speter p = xmalloc (len + 1); 83825839Speter if (p == NULL) 83925839Speter return -2; 84025839Speter *line = p; 84125839Speter 84225839Speter nldata = data; 84325839Speter data = buf->data; 84425839Speter while (data != nldata) 84525839Speter { 84625839Speter struct buffer_data *next; 84725839Speter 84825839Speter memcpy (p, data->bufp, data->size); 84925839Speter p += data->size; 85025839Speter next = data->next; 85125839Speter data->next = free_buffer_data; 85225839Speter free_buffer_data = data; 85325839Speter data = next; 85425839Speter } 85525839Speter 85625839Speter memcpy (p, data->bufp, finallen); 85725839Speter p[finallen] = '\0'; 85825839Speter 85925839Speter data->size -= finallen + 1; 86025839Speter data->bufp = nl + 1; 86125839Speter buf->data = data; 86225839Speter 86325839Speter if (lenp != NULL) 86425839Speter *lenp = len; 86525839Speter 86625839Speter return 0; 86725839Speter } 86825839Speter 86925839Speter /* Read more data until we get a newline. */ 87025839Speter while (1) 87125839Speter { 87225839Speter int size, status, nbytes; 87325839Speter char *mem; 87425839Speter 87525839Speter if (buf->data == NULL 87625839Speter || (buf->last->bufp + buf->last->size 87725839Speter == buf->last->text + BUFFER_DATA_SIZE)) 87825839Speter { 87925839Speter data = get_buffer_data (); 88025839Speter if (data == NULL) 88125839Speter { 88225839Speter (*buf->memory_error) (buf); 88325839Speter return -2; 88425839Speter } 88525839Speter 88625839Speter if (buf->data == NULL) 88725839Speter buf->data = data; 88825839Speter else 88925839Speter buf->last->next = data; 89025839Speter data->next = NULL; 89125839Speter buf->last = data; 89225839Speter 89325839Speter data->bufp = data->text; 89425839Speter data->size = 0; 89525839Speter } 89625839Speter 89725839Speter mem = buf->last->bufp + buf->last->size; 89825839Speter size = (buf->last->text + BUFFER_DATA_SIZE) - mem; 89925839Speter 90025839Speter /* We need to read at least 1 byte. We can handle up to 90125839Speter SIZE bytes. This will only be efficient if the 90225839Speter underlying communication stream does its own buffering, 90325839Speter or is clever about getting more than 1 byte at a time. */ 90425839Speter status = (*buf->input) (buf->closure, mem, 1, size, &nbytes); 90525839Speter if (status != 0) 90625839Speter return status; 90725839Speter 90825839Speter buf->last->size += nbytes; 90925839Speter 91025839Speter /* Optimize slightly to avoid an unnecessary call to 91125839Speter memchr. */ 91225839Speter if (nbytes == 1) 91325839Speter { 91425839Speter if (*mem == '\012') 91525839Speter break; 91625839Speter } 91725839Speter else 91825839Speter { 91925839Speter if (memchr (mem, '\012', nbytes) != NULL) 92025839Speter break; 92125839Speter } 92225839Speter } 92325839Speter } 92425839Speter} 92525839Speter 92625839Speter/* 92725839Speter * Extract data from the input buffer BUF. This will read up to WANT 92825839Speter * bytes from the buffer. It will set *RETDATA to point at the bytes, 92925839Speter * and set *GOT to the number of bytes to be found there. Any buffer 93025839Speter * call which uses BUF may change the contents of the buffer at *DATA, 93125839Speter * so the data should be fully processed before any further calls are 93225839Speter * made. This returns 0 on success, or -1 on end of file, or -2 if 93325839Speter * out of memory, or an error code. 93425839Speter */ 93525839Speter 93625839Speterint 93725839Speterbuf_read_data (buf, want, retdata, got) 93825839Speter struct buffer *buf; 93925839Speter int want; 94025839Speter char **retdata; 94125839Speter int *got; 94225839Speter{ 94325839Speter if (buf->input == NULL) 94425839Speter abort (); 94525839Speter 94625839Speter while (buf->data != NULL && buf->data->size == 0) 94725839Speter { 94825839Speter struct buffer_data *next; 94925839Speter 95025839Speter next = buf->data->next; 95125839Speter buf->data->next = free_buffer_data; 95225839Speter free_buffer_data = buf->data; 95325839Speter buf->data = next; 95425839Speter if (next == NULL) 95525839Speter buf->last = NULL; 95625839Speter } 95725839Speter 95825839Speter if (buf->data == NULL) 95925839Speter { 96025839Speter struct buffer_data *data; 96125839Speter int get, status, nbytes; 96225839Speter 96325839Speter data = get_buffer_data (); 96425839Speter if (data == NULL) 96525839Speter { 96625839Speter (*buf->memory_error) (buf); 96725839Speter return -2; 96825839Speter } 96925839Speter 97025839Speter buf->data = data; 97125839Speter buf->last = data; 97225839Speter data->next = NULL; 97325839Speter data->bufp = data->text; 97425839Speter data->size = 0; 97525839Speter 97625839Speter if (want < BUFFER_DATA_SIZE) 97725839Speter get = want; 97825839Speter else 97925839Speter get = BUFFER_DATA_SIZE; 98025839Speter status = (*buf->input) (buf->closure, data->bufp, get, 98125839Speter BUFFER_DATA_SIZE, &nbytes); 98225839Speter if (status != 0) 98325839Speter return status; 98425839Speter 98525839Speter data->size = nbytes; 98625839Speter } 98725839Speter 98825839Speter *retdata = buf->data->bufp; 98925839Speter if (want < buf->data->size) 99025839Speter { 99125839Speter *got = want; 99225839Speter buf->data->size -= want; 99325839Speter buf->data->bufp += want; 99425839Speter } 99525839Speter else 99625839Speter { 99725839Speter *got = buf->data->size; 99825839Speter buf->data->size = 0; 99925839Speter } 100025839Speter 100125839Speter return 0; 100225839Speter} 100325839Speter 100425839Speter/* 100525839Speter * Copy lines from an input buffer to an output buffer. This copies 100625839Speter * all complete lines (characters up to a newline) from INBUF to 100725839Speter * OUTBUF. Each line in OUTBUF is preceded by the character COMMAND 100825839Speter * and a space. 100925839Speter */ 101025839Speter 101125839Spetervoid 101225839Speterbuf_copy_lines (outbuf, inbuf, command) 101325839Speter struct buffer *outbuf; 101425839Speter struct buffer *inbuf; 101525839Speter int command; 101625839Speter{ 101725839Speter while (1) 101825839Speter { 101925839Speter struct buffer_data *data; 102025839Speter struct buffer_data *nldata; 102125839Speter char *nl; 102225839Speter int len; 102325839Speter 102425839Speter /* See if there is a newline in INBUF. */ 102525839Speter nldata = NULL; 102625839Speter nl = NULL; 102725839Speter for (data = inbuf->data; data != NULL; data = data->next) 102825839Speter { 102925839Speter nl = memchr (data->bufp, '\n', data->size); 103025839Speter if (nl != NULL) 103125839Speter { 103225839Speter nldata = data; 103325839Speter break; 103425839Speter } 103525839Speter } 103625839Speter 103725839Speter if (nldata == NULL) 103825839Speter { 103925839Speter /* There are no more lines in INBUF. */ 104025839Speter return; 104125839Speter } 104225839Speter 104325839Speter /* Put in the command. */ 104425839Speter buf_append_char (outbuf, command); 104525839Speter buf_append_char (outbuf, ' '); 104625839Speter 104725839Speter if (inbuf->data != nldata) 104825839Speter { 104925839Speter /* 105025839Speter * Simply move over all the buffers up to the one containing 105125839Speter * the newline. 105225839Speter */ 105325839Speter for (data = inbuf->data; data->next != nldata; data = data->next) 105425839Speter ; 105525839Speter data->next = NULL; 105625839Speter buf_append_data (outbuf, inbuf->data, data); 105725839Speter inbuf->data = nldata; 105825839Speter } 105925839Speter 106025839Speter /* 106125839Speter * If the newline is at the very end of the buffer, just move 106225839Speter * the buffer onto OUTBUF. Otherwise we must copy the data. 106325839Speter */ 106425839Speter len = nl + 1 - nldata->bufp; 106525839Speter if (len == nldata->size) 106625839Speter { 106725839Speter inbuf->data = nldata->next; 106825839Speter if (inbuf->data == NULL) 106925839Speter inbuf->last = NULL; 107025839Speter 107125839Speter nldata->next = NULL; 107225839Speter buf_append_data (outbuf, nldata, nldata); 107325839Speter } 107425839Speter else 107525839Speter { 107625839Speter buf_output (outbuf, nldata->bufp, len); 107725839Speter nldata->bufp += len; 107825839Speter nldata->size -= len; 107925839Speter } 108025839Speter } 108125839Speter} 108225839Speter 108325839Speter/* 108425839Speter * Copy counted data from one buffer to another. The count is an 108525839Speter * integer, host size, host byte order (it is only used across a 108625839Speter * pipe). If there is enough data, it should be moved over. If there 108725839Speter * is not enough data, it should remain on the original buffer. A 108825839Speter * negative count is a special case. if one is seen, *SPECIAL is set 108925839Speter * to the (negative) count value and no additional data is gathered 109025839Speter * from the buffer; normally *SPECIAL is set to 0. This function 109125839Speter * returns the number of bytes it needs to see in order to actually 109225839Speter * copy something over. 109325839Speter */ 109425839Speter 109525839Speterint 109625839Speterbuf_copy_counted (outbuf, inbuf, special) 109725839Speter struct buffer *outbuf; 109825839Speter struct buffer *inbuf; 109925839Speter int *special; 110025839Speter{ 110125839Speter *special = 0; 110225839Speter 110325839Speter while (1) 110425839Speter { 110525839Speter struct buffer_data *data; 110625839Speter int need; 110725839Speter union 110825839Speter { 110925839Speter char intbuf[sizeof (int)]; 111025839Speter int i; 111125839Speter } u; 111225839Speter char *intp; 111325839Speter int count; 111425839Speter struct buffer_data *start; 111525839Speter int startoff; 111625839Speter struct buffer_data *stop; 111725839Speter int stopwant; 111825839Speter 111925839Speter /* See if we have enough bytes to figure out the count. */ 112025839Speter need = sizeof (int); 112125839Speter intp = u.intbuf; 112225839Speter for (data = inbuf->data; data != NULL; data = data->next) 112325839Speter { 112425839Speter if (data->size >= need) 112525839Speter { 112625839Speter memcpy (intp, data->bufp, need); 112725839Speter break; 112825839Speter } 112925839Speter memcpy (intp, data->bufp, data->size); 113025839Speter intp += data->size; 113125839Speter need -= data->size; 113225839Speter } 113325839Speter if (data == NULL) 113425839Speter { 113525839Speter /* We don't have enough bytes to form an integer. */ 113625839Speter return need; 113725839Speter } 113825839Speter 113925839Speter count = u.i; 114025839Speter start = data; 114125839Speter startoff = need; 114225839Speter 114325839Speter if (count < 0) 114425839Speter { 114525839Speter /* A negative COUNT is a special case meaning that we 114625839Speter don't need any further information. */ 114725839Speter stop = start; 114825839Speter stopwant = 0; 114925839Speter } 115025839Speter else 115125839Speter { 115225839Speter /* 115325839Speter * We have an integer in COUNT. We have gotten all the 115425839Speter * data from INBUF in all buffers before START, and we 115525839Speter * have gotten STARTOFF bytes from START. See if we have 115625839Speter * enough bytes remaining in INBUF. 115725839Speter */ 115825839Speter need = count - (start->size - startoff); 115925839Speter if (need <= 0) 116025839Speter { 116125839Speter stop = start; 116225839Speter stopwant = count; 116325839Speter } 116425839Speter else 116525839Speter { 116625839Speter for (data = start->next; data != NULL; data = data->next) 116725839Speter { 116825839Speter if (need <= data->size) 116925839Speter break; 117025839Speter need -= data->size; 117125839Speter } 117225839Speter if (data == NULL) 117325839Speter { 117425839Speter /* We don't have enough bytes. */ 117525839Speter return need; 117625839Speter } 117725839Speter stop = data; 117825839Speter stopwant = need; 117925839Speter } 118025839Speter } 118125839Speter 118225839Speter /* 118325839Speter * We have enough bytes. Free any buffers in INBUF before 118425839Speter * START, and remove STARTOFF bytes from START, so that we can 118525839Speter * forget about STARTOFF. 118625839Speter */ 118725839Speter start->bufp += startoff; 118825839Speter start->size -= startoff; 118925839Speter 119025839Speter if (start->size == 0) 119125839Speter start = start->next; 119225839Speter 119325839Speter if (stop->size == stopwant) 119425839Speter { 119525839Speter stop = stop->next; 119625839Speter stopwant = 0; 119725839Speter } 119825839Speter 119925839Speter while (inbuf->data != start) 120025839Speter { 120125839Speter data = inbuf->data; 120225839Speter inbuf->data = data->next; 120325839Speter data->next = free_buffer_data; 120425839Speter free_buffer_data = data; 120525839Speter } 120625839Speter 120725839Speter /* If COUNT is negative, set *SPECIAL and get out now. */ 120825839Speter if (count < 0) 120925839Speter { 121025839Speter *special = count; 121125839Speter return 0; 121225839Speter } 121325839Speter 121425839Speter /* 121525839Speter * We want to copy over the bytes from START through STOP. We 121625839Speter * only want STOPWANT bytes from STOP. 121725839Speter */ 121825839Speter 121925839Speter if (start != stop) 122025839Speter { 122125839Speter /* Attach the buffers from START through STOP to OUTBUF. */ 122225839Speter for (data = start; data->next != stop; data = data->next) 122325839Speter ; 122425839Speter inbuf->data = stop; 122525839Speter data->next = NULL; 122625839Speter buf_append_data (outbuf, start, data); 122725839Speter } 122825839Speter 122925839Speter if (stopwant > 0) 123025839Speter { 123125839Speter buf_output (outbuf, stop->bufp, stopwant); 123225839Speter stop->bufp += stopwant; 123325839Speter stop->size -= stopwant; 123425839Speter } 123525839Speter } 123625839Speter 123725839Speter /*NOTREACHED*/ 123825839Speter} 123925839Speter 124025839Speter/* Shut down a buffer. This returns 0 on success, or an errno code. */ 124125839Speter 124225839Speterint 124325839Speterbuf_shutdown (buf) 124425839Speter struct buffer *buf; 124525839Speter{ 124625839Speter if (buf->shutdown) 1247102840Speter return (*buf->shutdown) (buf); 124825839Speter return 0; 124925839Speter} 125025839Speter 1251128269Speter 1252128269Speter 125325839Speter/* The simplest type of buffer is one built on top of a stdio FILE. 125425839Speter For simplicity, and because it is all that is required, we do not 125525839Speter implement setting this type of buffer into nonblocking mode. The 125625839Speter closure field is just a FILE *. */ 125725839Speter 125825839Speterstatic int stdio_buffer_input PROTO((void *, char *, int, int, int *)); 125925839Speterstatic int stdio_buffer_output PROTO((void *, const char *, int, int *)); 126025839Speterstatic int stdio_buffer_flush PROTO((void *)); 1261102840Speterstatic int stdio_buffer_shutdown PROTO((struct buffer *buf)); 126225839Speter 1263128269Speter 1264128269Speter 126525839Speter/* Initialize a buffer built on a stdio FILE. */ 1266102840Speterstruct stdio_buffer_closure 1267102840Speter{ 1268102840Speter FILE *fp; 1269102840Speter int child_pid; 1270102840Speter}; 1271102840Speter 1272128269Speter 1273128269Speter 127432785Speterstruct buffer * 1275102840Speterstdio_buffer_initialize (fp, child_pid, input, memory) 127625839Speter FILE *fp; 1277102840Speter int child_pid; 127825839Speter int input; 127925839Speter void (*memory) PROTO((struct buffer *)); 128025839Speter{ 1281109660Speter struct stdio_buffer_closure *bc = xmalloc (sizeof (*bc)); 1282102840Speter 1283102840Speter bc->fp = fp; 1284102840Speter bc->child_pid = child_pid; 1285102840Speter 128625839Speter return buf_initialize (input ? stdio_buffer_input : NULL, 128725839Speter input ? NULL : stdio_buffer_output, 128825839Speter input ? NULL : stdio_buffer_flush, 128925839Speter (int (*) PROTO((void *, int))) NULL, 1290102840Speter stdio_buffer_shutdown, 129125839Speter memory, 1292102840Speter (void *) bc); 129325839Speter} 129425839Speter 1295107487Speter/* Return the file associated with a stdio buffer. */ 1296107487SpeterFILE * 1297107487Speterstdio_buffer_get_file (buf) 1298107487Speter struct buffer *buf; 1299107487Speter{ 1300107487Speter struct stdio_buffer_closure *bc; 1301107487Speter 1302107487Speter assert(buf->shutdown == stdio_buffer_shutdown); 1303107487Speter 1304107487Speter bc = (struct stdio_buffer_closure *) buf->closure; 1305107487Speter 1306107487Speter return(bc->fp); 1307107487Speter} 1308107487Speter 130925839Speter/* The buffer input function for a buffer built on a stdio FILE. */ 131025839Speter 131125839Speterstatic int 131225839Speterstdio_buffer_input (closure, data, need, size, got) 131325839Speter void *closure; 131425839Speter char *data; 131525839Speter int need; 131625839Speter int size; 131725839Speter int *got; 131825839Speter{ 1319102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 132025839Speter int nbytes; 132125839Speter 132225839Speter /* Since stdio does its own buffering, we don't worry about 132325839Speter getting more bytes than we need. */ 132425839Speter 132525839Speter if (need == 0 || need == 1) 132625839Speter { 132725839Speter int ch; 132825839Speter 1329102840Speter ch = getc (bc->fp); 133025839Speter 133125839Speter if (ch == EOF) 133225839Speter { 1333102840Speter if (feof (bc->fp)) 133425839Speter return -1; 133525839Speter else if (errno == 0) 133625839Speter return EIO; 133725839Speter else 133825839Speter return errno; 133925839Speter } 134025839Speter 134125839Speter *data = ch; 134225839Speter *got = 1; 134325839Speter return 0; 134425839Speter } 134525839Speter 1346102840Speter nbytes = fread (data, 1, need, bc->fp); 134725839Speter 134825839Speter if (nbytes == 0) 134925839Speter { 135025839Speter *got = 0; 1351102840Speter if (feof (bc->fp)) 135225839Speter return -1; 135325839Speter else if (errno == 0) 135425839Speter return EIO; 135525839Speter else 135625839Speter return errno; 135725839Speter } 135825839Speter 135925839Speter *got = nbytes; 136025839Speter 136125839Speter return 0; 136225839Speter} 136325839Speter 136425839Speter/* The buffer output function for a buffer built on a stdio FILE. */ 136525839Speter 136625839Speterstatic int 136725839Speterstdio_buffer_output (closure, data, have, wrote) 136825839Speter void *closure; 136925839Speter const char *data; 137025839Speter int have; 137125839Speter int *wrote; 137225839Speter{ 1373102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 137425839Speter 137525839Speter *wrote = 0; 137625839Speter 137725839Speter while (have > 0) 137825839Speter { 137925839Speter int nbytes; 138025839Speter 1381102840Speter nbytes = fwrite (data, 1, have, bc->fp); 138225839Speter 138325839Speter if (nbytes != have) 138425839Speter { 138525839Speter if (errno == 0) 138625839Speter return EIO; 138725839Speter else 138825839Speter return errno; 138925839Speter } 139025839Speter 139125839Speter *wrote += nbytes; 139225839Speter have -= nbytes; 139325839Speter data += nbytes; 139425839Speter } 139525839Speter 139625839Speter return 0; 139725839Speter} 139825839Speter 1399128269Speter 1400128269Speter 140125839Speter/* The buffer flush function for a buffer built on a stdio FILE. */ 140225839Speterstatic int 140325839Speterstdio_buffer_flush (closure) 140425839Speter void *closure; 140525839Speter{ 1406102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 140725839Speter 1408102840Speter if (fflush (bc->fp) != 0) 140925839Speter { 141025839Speter if (errno == 0) 141125839Speter return EIO; 141225839Speter else 141325839Speter return errno; 141425839Speter } 141525839Speter 141625839Speter return 0; 141725839Speter} 141825839Speter 1419102840Speter 1420102840Speter 1421102840Speterstatic int 1422102840Speterstdio_buffer_shutdown (buf) 1423102840Speter struct buffer *buf; 1424102840Speter{ 1425128269Speter struct stdio_buffer_closure *bc = buf->closure; 1426102840Speter struct stat s; 1427175282Sobrien int closefp, statted; 1428102840Speter 1429175282Sobrien /* Must be a pipe or a socket. What could go wrong? 1430175282Sobrien * Well, apparently for disconnected clients under AIX, the 1431175282Sobrien * fstat() will return -1 on the server if the client has gone 1432175282Sobrien * away. 1433175282Sobrien */ 1434175282Sobrien if (fstat(fileno(bc->fp), &s) == -1) statted = 0; 1435175282Sobrien else statted = 1; 1436175282Sobrien closefp = statted; 1437102840Speter 1438102840Speter /* Flush the buffer if we can */ 1439102840Speter if (buf->flush) 1440102840Speter { 1441102840Speter buf_flush (buf, 1); 1442102840Speter buf->flush = NULL; 1443102840Speter } 1444102840Speter 1445102840Speter if (buf->input) 1446102840Speter { 1447128269Speter /* There used to be a check here for unread data in the buffer of on 1448128269Speter * the pipe, but it was deemed unnecessary and possibly dangerous. In 1449128269Speter * some sense it could be second-guessing the caller who requested it 1450128269Speter * closed, as well. 1451128269Speter */ 1452102840Speter 1453102840Speter# ifdef SHUTDOWN_SERVER 1454102840Speter if (current_parsed_root->method != server_method) 1455102840Speter# endif 1456102840Speter# ifndef NO_SOCKET_TO_FD 1457102840Speter { 1458102840Speter /* shutdown() sockets */ 1459175282Sobrien if (statted && S_ISSOCK (s.st_mode)) 1460128269Speter shutdown (fileno (bc->fp), 0); 1461102840Speter } 1462102840Speter# endif /* NO_SOCKET_TO_FD */ 1463102840Speter# ifdef START_RSH_WITH_POPEN_RW 1464102840Speter /* Can't be set with SHUTDOWN_SERVER defined */ 1465102840Speter else if (pclose (bc->fp) == EOF) 1466102840Speter { 1467175282Sobrien error (0, errno, "closing connection to %s", 1468102840Speter current_parsed_root->hostname); 1469102840Speter closefp = 0; 1470102840Speter } 1471102840Speter# endif /* START_RSH_WITH_POPEN_RW */ 1472102840Speter 1473102840Speter buf->input = NULL; 1474102840Speter } 1475102840Speter else if (buf->output) 1476102840Speter { 1477102840Speter# ifdef SHUTDOWN_SERVER 1478102840Speter /* FIXME: Should have a SHUTDOWN_SERVER_INPUT & 1479102840Speter * SHUTDOWN_SERVER_OUTPUT 1480102840Speter */ 1481102840Speter if (current_parsed_root->method == server_method) 1482128269Speter SHUTDOWN_SERVER (fileno (bc->fp)); 1483102840Speter else 1484102840Speter# endif 1485102840Speter# ifndef NO_SOCKET_TO_FD 1486102840Speter /* shutdown() sockets */ 1487175282Sobrien if (statted && S_ISSOCK (s.st_mode)) 1488128269Speter shutdown (fileno (bc->fp), 1); 1489102840Speter# else 1490102840Speter { 1491102840Speter /* I'm not sure I like this empty block, but the alternative 1492102840Speter * is a another nested NO_SOCKET_TO_FD switch above. 1493102840Speter */ 1494102840Speter } 1495102840Speter# endif /* NO_SOCKET_TO_FD */ 1496102840Speter 1497102840Speter buf->output = NULL; 1498102840Speter } 1499102840Speter 1500175282Sobrien if (statted && closefp && fclose (bc->fp) == EOF) 1501128269Speter { 1502175282Sobrien if (server_active) 1503128269Speter { 1504128269Speter /* Syslog this? */ 1505128269Speter } 1506128269Speter# ifdef CLIENT_SUPPORT 1507175282Sobrien /* We are already closing the connection. 1508175282Sobrien * On error, print a warning and try to 1509175282Sobrien * continue to avoid infinte loops. 1510175282Sobrien */ 1511128269Speter else 1512175282Sobrien error (0, errno, 1513128269Speter "closing down connection to %s", 1514128269Speter current_parsed_root->hostname); 1515128269Speter# endif /* CLIENT_SUPPORT */ 1516128269Speter } 1517102840Speter 1518102840Speter /* If we were talking to a process, make sure it exited */ 1519128269Speter if (bc->child_pid) 1520128269Speter { 1521128269Speter int w; 1522102840Speter 1523128269Speter do 1524128269Speter w = waitpid (bc->child_pid, (int *) 0, 0); 1525128269Speter while (w == -1 && errno == EINTR); 1526175282Sobrien 1527175282Sobrien /* We are already closing the connection. 1528175282Sobrien * On error, print a warning and try to 1529175282Sobrien * continue to avoid infinte loops. 1530175282Sobrien */ 1531128269Speter if (w == -1) 1532175282Sobrien error (0, errno, "waiting for process %d", bc->child_pid); 1533128269Speter } 1534102840Speter return 0; 1535102840Speter} 1536102840Speter 1537102840Speter 1538102840Speter 153932785Speter/* Certain types of communication input and output data in packets, 154032785Speter where each packet is translated in some fashion. The packetizing 154132785Speter buffer type supports that, given a buffer which handles lower level 154232785Speter I/O and a routine to translate the data in a packet. 154332785Speter 154432785Speter This code uses two bytes for the size of a packet, so packets are 154532785Speter restricted to 65536 bytes in total. 154632785Speter 154732785Speter The translation functions should just translate; they may not 154832785Speter significantly increase or decrease the amount of data. The actual 154932785Speter size of the initial data is part of the translated data. The 155032785Speter output translation routine may add up to PACKET_SLOP additional 155132785Speter bytes, and the input translation routine should shrink the data 155232785Speter correspondingly. */ 155332785Speter 155432785Speter#define PACKET_SLOP (100) 155532785Speter 155632785Speter/* This structure is the closure field of a packetizing buffer. */ 155732785Speter 155832785Speterstruct packetizing_buffer 155932785Speter{ 156032785Speter /* The underlying buffer. */ 156132785Speter struct buffer *buf; 156232785Speter /* The input translation function. Exactly one of inpfn and outfn 156332785Speter will be NULL. The input translation function should 156432785Speter untranslate the data in INPUT, storing the result in OUTPUT. 156532785Speter SIZE is the amount of data in INPUT, and is also the size of 156632785Speter OUTPUT. This should return 0 on success, or an errno code. */ 156732785Speter int (*inpfn) PROTO((void *fnclosure, const char *input, char *output, 156832785Speter int size)); 156932785Speter /* The output translation function. This should translate the 157032785Speter data in INPUT, storing the result in OUTPUT. The first two 157132785Speter bytes in INPUT will be the size of the data, and so will SIZE. 157232785Speter This should set *TRANSLATED to the amount of translated data in 157332785Speter OUTPUT. OUTPUT is large enough to hold SIZE + PACKET_SLOP 157432785Speter bytes. This should return 0 on success, or an errno code. */ 157532785Speter int (*outfn) PROTO((void *fnclosure, const char *input, char *output, 157632785Speter int size, int *translated)); 157732785Speter /* A closure for the translation function. */ 157832785Speter void *fnclosure; 157932785Speter /* For an input buffer, we may have to buffer up data here. */ 158032785Speter /* This is non-zero if the buffered data has been translated. 158132785Speter Otherwise, the buffered data has not been translated, and starts 158232785Speter with the two byte packet size. */ 158332785Speter int translated; 158432785Speter /* The amount of buffered data. */ 158532785Speter int holdsize; 158632785Speter /* The buffer allocated to hold the data. */ 158732785Speter char *holdbuf; 158832785Speter /* The size of holdbuf. */ 158932785Speter int holdbufsize; 159032785Speter /* If translated is set, we need another data pointer to track 159132785Speter where we are in holdbuf. If translated is clear, then this 159232785Speter pointer is not used. */ 159332785Speter char *holddata; 159432785Speter}; 159532785Speter 159632785Speterstatic int packetizing_buffer_input PROTO((void *, char *, int, int, int *)); 159732785Speterstatic int packetizing_buffer_output PROTO((void *, const char *, int, int *)); 159832785Speterstatic int packetizing_buffer_flush PROTO((void *)); 159932785Speterstatic int packetizing_buffer_block PROTO((void *, int)); 1600102840Speterstatic int packetizing_buffer_shutdown PROTO((struct buffer *)); 160132785Speter 160232785Speter/* Create a packetizing buffer. */ 160332785Speter 160432785Speterstruct buffer * 160532785Speterpacketizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory) 160632785Speter struct buffer *buf; 160732785Speter int (*inpfn) PROTO ((void *, const char *, char *, int)); 160832785Speter int (*outfn) PROTO ((void *, const char *, char *, int, int *)); 160932785Speter void *fnclosure; 161032785Speter void (*memory) PROTO((struct buffer *)); 161132785Speter{ 161232785Speter struct packetizing_buffer *pb; 161332785Speter 161432785Speter pb = (struct packetizing_buffer *) xmalloc (sizeof *pb); 161532785Speter memset (pb, 0, sizeof *pb); 161632785Speter 161732785Speter pb->buf = buf; 161832785Speter pb->inpfn = inpfn; 161932785Speter pb->outfn = outfn; 162032785Speter pb->fnclosure = fnclosure; 162132785Speter 162232785Speter if (inpfn != NULL) 162332785Speter { 162432785Speter /* Add PACKET_SLOP to handle larger translated packets, and 162532785Speter add 2 for the count. This buffer is increased if 162632785Speter necessary. */ 162732785Speter pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2; 162832785Speter pb->holdbuf = xmalloc (pb->holdbufsize); 162932785Speter } 163032785Speter 163132785Speter return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL, 163232785Speter inpfn != NULL ? NULL : packetizing_buffer_output, 163332785Speter inpfn != NULL ? NULL : packetizing_buffer_flush, 163432785Speter packetizing_buffer_block, 163532785Speter packetizing_buffer_shutdown, 163632785Speter memory, 163732785Speter pb); 163832785Speter} 163932785Speter 164032785Speter/* Input data from a packetizing buffer. */ 164132785Speter 164232785Speterstatic int 164332785Speterpacketizing_buffer_input (closure, data, need, size, got) 164432785Speter void *closure; 164532785Speter char *data; 164632785Speter int need; 164732785Speter int size; 164832785Speter int *got; 164932785Speter{ 165032785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 165132785Speter 165232785Speter *got = 0; 165332785Speter 165432785Speter if (pb->holdsize > 0 && pb->translated) 165532785Speter { 165632785Speter int copy; 165732785Speter 165832785Speter copy = pb->holdsize; 165932785Speter 166032785Speter if (copy > size) 166132785Speter { 166232785Speter memcpy (data, pb->holddata, size); 166332785Speter pb->holdsize -= size; 166432785Speter pb->holddata += size; 166532785Speter *got = size; 166632785Speter return 0; 166732785Speter } 166832785Speter 166932785Speter memcpy (data, pb->holddata, copy); 167032785Speter pb->holdsize = 0; 167132785Speter pb->translated = 0; 167232785Speter 167332785Speter data += copy; 167432785Speter need -= copy; 167532785Speter size -= copy; 167632785Speter *got = copy; 167732785Speter } 167832785Speter 167932785Speter while (need > 0 || *got == 0) 168032785Speter { 168132785Speter int get, status, nread, count, tcount; 168232785Speter char *bytes; 168332785Speter char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP]; 168432785Speter char *inbuf, *outbuf; 168532785Speter 168632785Speter /* If we don't already have the two byte count, get it. */ 168732785Speter if (pb->holdsize < 2) 168832785Speter { 168932785Speter get = 2 - pb->holdsize; 169032785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 169132785Speter if (status != 0) 169232785Speter { 169332785Speter /* buf_read_data can return -2, but a buffer input 169432785Speter function is only supposed to return -1, 0, or an 169532785Speter error code. */ 169632785Speter if (status == -2) 169732785Speter status = ENOMEM; 169832785Speter return status; 169932785Speter } 170032785Speter 170132785Speter if (nread == 0) 170232785Speter { 170332785Speter /* The buffer is in nonblocking mode, and we didn't 170432785Speter manage to read anything. */ 170532785Speter return 0; 170632785Speter } 170732785Speter 170832785Speter if (get == 1) 170932785Speter pb->holdbuf[1] = bytes[0]; 171032785Speter else 171132785Speter { 171232785Speter pb->holdbuf[0] = bytes[0]; 171332785Speter if (nread < 2) 171432785Speter { 171532785Speter /* We only got one byte, but we needed two. Stash 171632785Speter the byte we got, and try again. */ 171732785Speter pb->holdsize = 1; 171832785Speter continue; 171932785Speter } 172032785Speter pb->holdbuf[1] = bytes[1]; 172132785Speter } 172232785Speter pb->holdsize = 2; 172332785Speter } 172432785Speter 172532785Speter /* Read the packet. */ 172632785Speter 172732785Speter count = (((pb->holdbuf[0] & 0xff) << 8) 172832785Speter + (pb->holdbuf[1] & 0xff)); 172932785Speter 173032785Speter if (count + 2 > pb->holdbufsize) 173132785Speter { 173232785Speter char *n; 173332785Speter 173432785Speter /* We didn't allocate enough space in the initialize 173532785Speter function. */ 173632785Speter 1737109660Speter n = xrealloc (pb->holdbuf, count + 2); 173832785Speter if (n == NULL) 173932785Speter { 174032785Speter (*pb->buf->memory_error) (pb->buf); 174132785Speter return ENOMEM; 174232785Speter } 174332785Speter pb->holdbuf = n; 174432785Speter pb->holdbufsize = count + 2; 174532785Speter } 174632785Speter 174732785Speter get = count - (pb->holdsize - 2); 174832785Speter 174932785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 175032785Speter if (status != 0) 175132785Speter { 175232785Speter /* buf_read_data can return -2, but a buffer input 175332785Speter function is only supposed to return -1, 0, or an error 175432785Speter code. */ 175532785Speter if (status == -2) 175632785Speter status = ENOMEM; 175732785Speter return status; 175832785Speter } 175932785Speter 176032785Speter if (nread == 0) 176132785Speter { 176232785Speter /* We did not get any data. Presumably the buffer is in 176332785Speter nonblocking mode. */ 176432785Speter return 0; 176532785Speter } 176632785Speter 176732785Speter if (nread < get) 176832785Speter { 176932785Speter /* We did not get all the data we need to fill the packet. 177032785Speter buf_read_data does not promise to return all the bytes 177132785Speter requested, so we must try again. */ 177232785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 177332785Speter pb->holdsize += nread; 177432785Speter continue; 177532785Speter } 177632785Speter 177732785Speter /* We have a complete untranslated packet of COUNT bytes. */ 177832785Speter 177932785Speter if (pb->holdsize == 2) 178032785Speter { 178132785Speter /* We just read the entire packet (the 2 bytes in 178232785Speter PB->HOLDBUF are the size). Save a memcpy by 178332785Speter translating directly from BYTES. */ 178432785Speter inbuf = bytes; 178532785Speter } 178632785Speter else 178732785Speter { 178832785Speter /* We already had a partial packet in PB->HOLDBUF. We 178932785Speter need to copy the new data over to make the input 179032785Speter contiguous. */ 179132785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 179232785Speter inbuf = pb->holdbuf + 2; 179332785Speter } 179432785Speter 179532785Speter if (count <= sizeof stackoutbuf) 179632785Speter outbuf = stackoutbuf; 179732785Speter else 179832785Speter { 1799109660Speter outbuf = xmalloc (count); 180032785Speter if (outbuf == NULL) 180132785Speter { 180232785Speter (*pb->buf->memory_error) (pb->buf); 180332785Speter return ENOMEM; 180432785Speter } 180532785Speter } 180632785Speter 180732785Speter status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count); 180832785Speter if (status != 0) 180932785Speter return status; 181032785Speter 181132785Speter /* The first two bytes in the translated buffer are the real 181232785Speter length of the translated data. */ 181332785Speter tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff); 181432785Speter 181532785Speter if (tcount > count) 181632785Speter error (1, 0, "Input translation failure"); 181732785Speter 181832785Speter if (tcount > size) 181932785Speter { 182032785Speter /* We have more data than the caller has provided space 182132785Speter for. We need to save some of it for the next call. */ 182232785Speter 182332785Speter memcpy (data, outbuf + 2, size); 182432785Speter *got += size; 182532785Speter 182632785Speter pb->holdsize = tcount - size; 182732785Speter memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size); 182832785Speter pb->holddata = pb->holdbuf; 182932785Speter pb->translated = 1; 183032785Speter 183132785Speter if (outbuf != stackoutbuf) 183232785Speter free (outbuf); 183332785Speter 183432785Speter return 0; 183532785Speter } 183632785Speter 183732785Speter memcpy (data, outbuf + 2, tcount); 183832785Speter 183932785Speter if (outbuf != stackoutbuf) 184032785Speter free (outbuf); 184132785Speter 184232785Speter pb->holdsize = 0; 184332785Speter 184432785Speter data += tcount; 184532785Speter need -= tcount; 184632785Speter size -= tcount; 184732785Speter *got += tcount; 184832785Speter } 184932785Speter 185032785Speter return 0; 185132785Speter} 185232785Speter 185332785Speter/* Output data to a packetizing buffer. */ 185432785Speter 185532785Speterstatic int 185632785Speterpacketizing_buffer_output (closure, data, have, wrote) 185732785Speter void *closure; 185832785Speter const char *data; 185932785Speter int have; 186032785Speter int *wrote; 186132785Speter{ 186232785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 186332785Speter char inbuf[BUFFER_DATA_SIZE + 2]; 186432785Speter char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4]; 1865175282Sobrien struct buffer_data *outdata = NULL; 186632785Speter char *outbuf; 186732785Speter int size, status, translated; 186832785Speter 186932785Speter if (have > BUFFER_DATA_SIZE) 187032785Speter { 1871109660Speter /* It would be easy to xmalloc a buffer, but I don't think this 187232785Speter case can ever arise. */ 187332785Speter abort (); 187432785Speter } 187532785Speter 187632785Speter inbuf[0] = (have >> 8) & 0xff; 187732785Speter inbuf[1] = have & 0xff; 187832785Speter memcpy (inbuf + 2, data, have); 187932785Speter 188032785Speter size = have + 2; 188132785Speter 188232785Speter /* The output function is permitted to add up to PACKET_SLOP 188332785Speter bytes, and we need 2 bytes for the size of the translated data. 188432785Speter If we can guarantee that the result will fit in a buffer_data, 188532785Speter we translate directly into one to avoid a memcpy in buf_output. */ 188632785Speter if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE) 188732785Speter outbuf = stack_outbuf; 188832785Speter else 188932785Speter { 189032785Speter outdata = get_buffer_data (); 189132785Speter if (outdata == NULL) 189232785Speter { 189332785Speter (*pb->buf->memory_error) (pb->buf); 189432785Speter return ENOMEM; 189532785Speter } 189632785Speter 189732785Speter outdata->next = NULL; 189832785Speter outdata->bufp = outdata->text; 189932785Speter 190032785Speter outbuf = outdata->text; 190132785Speter } 190232785Speter 190332785Speter status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size, 190432785Speter &translated); 190532785Speter if (status != 0) 190632785Speter return status; 190732785Speter 190832785Speter /* The output function is permitted to add up to PACKET_SLOP 190932785Speter bytes. */ 191032785Speter if (translated > size + PACKET_SLOP) 191132785Speter abort (); 191232785Speter 191332785Speter outbuf[0] = (translated >> 8) & 0xff; 191432785Speter outbuf[1] = translated & 0xff; 191532785Speter 191632785Speter if (outbuf == stack_outbuf) 191732785Speter buf_output (pb->buf, outbuf, translated + 2); 191832785Speter else 191932785Speter { 1920175282Sobrien /* if ((have + PACKET_SLOP + 4) > BUFFER_DATA_SIZE), then 1921175282Sobrien outdata may be NULL. */ 1922175282Sobrien if (outdata == NULL) 1923175282Sobrien abort (); 1924175282Sobrien 192532785Speter outdata->size = translated + 2; 192632785Speter buf_append_data (pb->buf, outdata, outdata); 192732785Speter } 192832785Speter 192932785Speter *wrote = have; 193032785Speter 193132785Speter /* We will only be here because buf_send_output was called on the 193232785Speter packetizing buffer. That means that we should now call 193332785Speter buf_send_output on the underlying buffer. */ 193432785Speter return buf_send_output (pb->buf); 193532785Speter} 193632785Speter 1937128269Speter 1938128269Speter 193932785Speter/* Flush data to a packetizing buffer. */ 194032785Speterstatic int 194132785Speterpacketizing_buffer_flush (closure) 194232785Speter void *closure; 194332785Speter{ 194432785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 194532785Speter 194632785Speter /* Flush the underlying buffer. Note that if the original call to 194732785Speter buf_flush passed 1 for the BLOCK argument, then the buffer will 194832785Speter already have been set into blocking mode, so we should always 194932785Speter pass 0 here. */ 195032785Speter return buf_flush (pb->buf, 0); 195132785Speter} 195232785Speter 1953128269Speter 1954128269Speter 195532785Speter/* The block routine for a packetizing buffer. */ 195632785Speterstatic int 195732785Speterpacketizing_buffer_block (closure, block) 195832785Speter void *closure; 195932785Speter int block; 196032785Speter{ 196132785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 196232785Speter 196332785Speter if (block) 196432785Speter return set_block (pb->buf); 196532785Speter else 196632785Speter return set_nonblock (pb->buf); 196732785Speter} 196832785Speter 196932785Speter/* Shut down a packetizing buffer. */ 197032785Speter 197132785Speterstatic int 1972102840Speterpacketizing_buffer_shutdown (buf) 1973102840Speter struct buffer *buf; 197432785Speter{ 1975102840Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure; 197632785Speter 197732785Speter return buf_shutdown (pb->buf); 197832785Speter} 197932785Speter 198025839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */ 1981