buffer.c revision 128269
125839Speter/* Code for the buffer data structure. */ 225839Speter 3102852Speter/* $FreeBSD: head/contrib/cvs/src/buffer.c 128269 2004-04-15 01:17:28Z peter $ */ 4102852Speter 525839Speter#include <assert.h> 625839Speter#include "cvs.h" 725839Speter#include "buffer.h" 825839Speter 925839Speter#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) 1025839Speter 11102840Speter#ifdef HAVE_WINSOCK_H 12102840Speter# include <winsock.h> 13102840Speter#else 14102840Speter# include <sys/socket.h> 15102840Speter#endif 16102840Speter 1725839Speter/* OS/2 doesn't have EIO. FIXME: this whole notion of turning 1825839Speter a different error into EIO strikes me as pretty dubious. */ 1925839Speter#if !defined (EIO) 2025839Speter#define EIO EBADPOS 2125839Speter#endif 2225839Speter 2325839Speter/* Linked list of available buffer_data structures. */ 2425839Speterstatic struct buffer_data *free_buffer_data; 2525839Speter 2625839Speter/* Local functions. */ 2734461Speterstatic void buf_default_memory_error PROTO ((struct buffer *)); 2825839Speterstatic void allocate_buffer_datas PROTO((void)); 2925839Speterstatic struct buffer_data *get_buffer_data PROTO((void)); 3025839Speter 3125839Speter/* Initialize a buffer structure. */ 3225839Speter 3325839Speterstruct buffer * 3425839Speterbuf_initialize (input, output, flush, block, shutdown, memory, closure) 3525839Speter int (*input) PROTO((void *, char *, int, int, int *)); 3625839Speter int (*output) PROTO((void *, const char *, int, int *)); 3725839Speter int (*flush) PROTO((void *)); 3825839Speter int (*block) PROTO((void *, int)); 39102840Speter int (*shutdown) PROTO((struct buffer *)); 4025839Speter void (*memory) PROTO((struct buffer *)); 4125839Speter void *closure; 4225839Speter{ 4325839Speter struct buffer *buf; 4425839Speter 4525839Speter buf = (struct buffer *) xmalloc (sizeof (struct buffer)); 4625839Speter buf->data = NULL; 4725839Speter buf->last = NULL; 4825839Speter buf->nonblocking = 0; 4925839Speter buf->input = input; 5025839Speter buf->output = output; 5125839Speter buf->flush = flush; 5225839Speter buf->block = block; 5325839Speter buf->shutdown = shutdown; 5434461Speter buf->memory_error = memory ? memory : buf_default_memory_error; 5525839Speter buf->closure = closure; 5625839Speter return buf; 5725839Speter} 5825839Speter 5934461Speter/* Free a buffer structure. */ 6034461Speter 6134461Spetervoid 6234461Speterbuf_free (buf) 6334461Speter struct buffer *buf; 6434461Speter{ 65128269Speter if (buf->closure != NULL) 66128269Speter { 67128269Speter free (buf->closure); 68128269Speter buf->closure = NULL; 69128269Speter } 7034461Speter if (buf->data != NULL) 7134461Speter { 7234461Speter buf->last->next = free_buffer_data; 7334461Speter free_buffer_data = buf->data; 7434461Speter } 7534461Speter free (buf); 7634461Speter} 7734461Speter 7825839Speter/* Initialize a buffer structure which is not to be used for I/O. */ 7925839Speter 8025839Speterstruct buffer * 8125839Speterbuf_nonio_initialize (memory) 8225839Speter void (*memory) PROTO((struct buffer *)); 8325839Speter{ 8425839Speter return (buf_initialize 8525839Speter ((int (*) PROTO((void *, char *, int, int, int *))) NULL, 8625839Speter (int (*) PROTO((void *, const char *, int, int *))) NULL, 8725839Speter (int (*) PROTO((void *))) NULL, 8825839Speter (int (*) PROTO((void *, int))) NULL, 89102840Speter (int (*) PROTO((struct buffer *))) NULL, 9025839Speter memory, 9125839Speter (void *) NULL)); 9225839Speter} 9325839Speter 9434461Speter/* Default memory error handler. */ 9534461Speter 9634461Speterstatic void 9734461Speterbuf_default_memory_error (buf) 9834461Speter struct buffer *buf; 9934461Speter{ 10034461Speter error (1, 0, "out of memory"); 10134461Speter} 10234461Speter 10325839Speter/* Allocate more buffer_data structures. */ 10425839Speter 10525839Speterstatic void 10625839Speterallocate_buffer_datas () 10725839Speter{ 10825839Speter struct buffer_data *alc; 10925839Speter char *space; 11025839Speter int i; 11125839Speter 11225839Speter /* Allocate buffer_data structures in blocks of 16. */ 11325839Speter#define ALLOC_COUNT (16) 11425839Speter 11525839Speter alc = ((struct buffer_data *) 116109660Speter xmalloc (ALLOC_COUNT * sizeof (struct buffer_data))); 11725839Speter space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE); 11825839Speter if (alc == NULL || space == NULL) 11925839Speter return; 12025839Speter for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE) 12125839Speter { 12225839Speter alc->next = free_buffer_data; 12325839Speter free_buffer_data = alc; 12425839Speter alc->text = space; 12525839Speter } 12625839Speter} 12725839Speter 12825839Speter/* Get a new buffer_data structure. */ 12925839Speter 13025839Speterstatic struct buffer_data * 13125839Speterget_buffer_data () 13225839Speter{ 13325839Speter struct buffer_data *ret; 13425839Speter 13525839Speter if (free_buffer_data == NULL) 13625839Speter { 13725839Speter allocate_buffer_datas (); 13825839Speter if (free_buffer_data == NULL) 13925839Speter return NULL; 14025839Speter } 14125839Speter 14225839Speter ret = free_buffer_data; 14325839Speter free_buffer_data = ret->next; 14425839Speter return ret; 14525839Speter} 14625839Speter 14725839Speter 148128269Speter 149128269Speter/* See whether a buffer and its file descriptor is empty. */ 15025839Speterint 151128269Speterbuf_empty (buf) 152128269Speter struct buffer *buf; 153128269Speter{ 154128269Speter /* Try and read any data on the file descriptor first. 155128269Speter * We already know the descriptor is non-blocking. 156128269Speter */ 157128269Speter buf_input_data (buf, NULL); 158128269Speter return buf_empty_p (buf); 159128269Speter} 160128269Speter 161128269Speter 162128269Speter 163128269Speter/* See whether a buffer is empty. */ 164128269Speterint 16525839Speterbuf_empty_p (buf) 16625839Speter struct buffer *buf; 16725839Speter{ 16825839Speter struct buffer_data *data; 16925839Speter 17025839Speter for (data = buf->data; data != NULL; data = data->next) 17125839Speter if (data->size > 0) 17225839Speter return 0; 17325839Speter return 1; 17425839Speter} 17525839Speter 176128269Speter 177128269Speter 17825839Speter#ifdef SERVER_FLOWCONTROL 17925839Speter/* 18025839Speter * Count how much data is stored in the buffer.. 181109660Speter * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE. 18225839Speter */ 18325839Speter 18425839Speterint 18525839Speterbuf_count_mem (buf) 18625839Speter struct buffer *buf; 18725839Speter{ 18825839Speter struct buffer_data *data; 18925839Speter int mem = 0; 19025839Speter 19125839Speter for (data = buf->data; data != NULL; data = data->next) 19225839Speter mem += BUFFER_DATA_SIZE; 19325839Speter 19425839Speter return mem; 19525839Speter} 19625839Speter#endif /* SERVER_FLOWCONTROL */ 19725839Speter 19825839Speter/* Add data DATA of length LEN to BUF. */ 19925839Speter 20025839Spetervoid 20125839Speterbuf_output (buf, data, len) 20225839Speter struct buffer *buf; 20325839Speter const char *data; 20425839Speter int len; 20525839Speter{ 20625839Speter if (buf->data != NULL 20725839Speter && (((buf->last->text + BUFFER_DATA_SIZE) 20825839Speter - (buf->last->bufp + buf->last->size)) 20925839Speter >= len)) 21025839Speter { 21125839Speter memcpy (buf->last->bufp + buf->last->size, data, len); 21225839Speter buf->last->size += len; 21325839Speter return; 21425839Speter } 21525839Speter 21625839Speter while (1) 21725839Speter { 21825839Speter struct buffer_data *newdata; 21925839Speter 22025839Speter newdata = get_buffer_data (); 22125839Speter if (newdata == NULL) 22225839Speter { 22325839Speter (*buf->memory_error) (buf); 22425839Speter return; 22525839Speter } 22625839Speter 22725839Speter if (buf->data == NULL) 22825839Speter buf->data = newdata; 22925839Speter else 23025839Speter buf->last->next = newdata; 23125839Speter newdata->next = NULL; 23225839Speter buf->last = newdata; 23325839Speter 23425839Speter newdata->bufp = newdata->text; 23525839Speter 23625839Speter if (len <= BUFFER_DATA_SIZE) 23725839Speter { 23825839Speter newdata->size = len; 23925839Speter memcpy (newdata->text, data, len); 24025839Speter return; 24125839Speter } 24225839Speter 24325839Speter newdata->size = BUFFER_DATA_SIZE; 24425839Speter memcpy (newdata->text, data, BUFFER_DATA_SIZE); 24525839Speter 24625839Speter data += BUFFER_DATA_SIZE; 24725839Speter len -= BUFFER_DATA_SIZE; 24825839Speter } 24925839Speter 25025839Speter /*NOTREACHED*/ 25125839Speter} 25225839Speter 25325839Speter/* Add a '\0' terminated string to BUF. */ 25425839Speter 25525839Spetervoid 25625839Speterbuf_output0 (buf, string) 25725839Speter struct buffer *buf; 25825839Speter const char *string; 25925839Speter{ 26025839Speter buf_output (buf, string, strlen (string)); 26125839Speter} 26225839Speter 26325839Speter/* Add a single character to BUF. */ 26425839Speter 26525839Spetervoid 26625839Speterbuf_append_char (buf, ch) 26725839Speter struct buffer *buf; 26825839Speter int ch; 26925839Speter{ 27025839Speter if (buf->data != NULL 27125839Speter && (buf->last->text + BUFFER_DATA_SIZE 27225839Speter != buf->last->bufp + buf->last->size)) 27325839Speter { 27425839Speter *(buf->last->bufp + buf->last->size) = ch; 27525839Speter ++buf->last->size; 27625839Speter } 27725839Speter else 27825839Speter { 27925839Speter char b; 28025839Speter 28125839Speter b = ch; 28225839Speter buf_output (buf, &b, 1); 28325839Speter } 28425839Speter} 28525839Speter 28625839Speter/* 28725839Speter * Send all the output we've been saving up. Returns 0 for success or 28825839Speter * errno code. If the buffer has been set to be nonblocking, this 28925839Speter * will just write until the write would block. 29025839Speter */ 29125839Speter 29225839Speterint 29325839Speterbuf_send_output (buf) 29425839Speter struct buffer *buf; 29525839Speter{ 29625839Speter if (buf->output == NULL) 29725839Speter abort (); 29825839Speter 29925839Speter while (buf->data != NULL) 30025839Speter { 30125839Speter struct buffer_data *data; 30225839Speter 30325839Speter data = buf->data; 30425839Speter 30525839Speter if (data->size > 0) 30625839Speter { 30725839Speter int status, nbytes; 30825839Speter 30925839Speter status = (*buf->output) (buf->closure, data->bufp, data->size, 31025839Speter &nbytes); 31125839Speter if (status != 0) 31225839Speter { 31325839Speter /* Some sort of error. Discard the data, and return. */ 31425839Speter 31525839Speter buf->last->next = free_buffer_data; 31625839Speter free_buffer_data = buf->data; 31725839Speter buf->data = NULL; 31825839Speter buf->last = NULL; 31925839Speter 32025839Speter return status; 32125839Speter } 32225839Speter 32325839Speter if (nbytes != data->size) 32425839Speter { 32525839Speter /* Not all the data was written out. This is only 32625839Speter permitted in nonblocking mode. Adjust the buffer, 32725839Speter and return. */ 32825839Speter 32925839Speter assert (buf->nonblocking); 33025839Speter 33125839Speter data->size -= nbytes; 33225839Speter data->bufp += nbytes; 33325839Speter 33425839Speter return 0; 33525839Speter } 33625839Speter } 33725839Speter 33825839Speter buf->data = data->next; 33925839Speter data->next = free_buffer_data; 34025839Speter free_buffer_data = data; 34125839Speter } 34225839Speter 34325839Speter buf->last = NULL; 34425839Speter 34525839Speter return 0; 34625839Speter} 34725839Speter 34825839Speter/* 34925839Speter * Flush any data queued up in the buffer. If BLOCK is nonzero, then 35025839Speter * if the buffer is in nonblocking mode, put it into blocking mode for 35125839Speter * the duration of the flush. This returns 0 on success, or an error 35225839Speter * code. 35325839Speter */ 35425839Speter 35525839Speterint 35625839Speterbuf_flush (buf, block) 35725839Speter struct buffer *buf; 35825839Speter int block; 35925839Speter{ 36025839Speter int nonblocking; 36125839Speter int status; 36225839Speter 36325839Speter if (buf->flush == NULL) 36425839Speter abort (); 36525839Speter 36625839Speter nonblocking = buf->nonblocking; 36725839Speter if (nonblocking && block) 36825839Speter { 36925839Speter status = set_block (buf); 37025839Speter if (status != 0) 37125839Speter return status; 37225839Speter } 37325839Speter 37425839Speter status = buf_send_output (buf); 37525839Speter if (status == 0) 37625839Speter status = (*buf->flush) (buf->closure); 37725839Speter 37825839Speter if (nonblocking && block) 37925839Speter { 38025839Speter int blockstat; 38125839Speter 38225839Speter blockstat = set_nonblock (buf); 38325839Speter if (status == 0) 38425839Speter status = blockstat; 38525839Speter } 38625839Speter 38725839Speter return status; 38825839Speter} 38925839Speter 39025839Speter/* 39125839Speter * Set buffer BUF to nonblocking I/O. Returns 0 for success or errno 39225839Speter * code. 39325839Speter */ 39425839Speter 39525839Speterint 39625839Speterset_nonblock (buf) 39725839Speter struct buffer *buf; 39825839Speter{ 39925839Speter int status; 40025839Speter 40125839Speter if (buf->nonblocking) 40225839Speter return 0; 40325839Speter if (buf->block == NULL) 40425839Speter abort (); 40525839Speter status = (*buf->block) (buf->closure, 0); 40625839Speter if (status != 0) 40725839Speter return status; 40825839Speter buf->nonblocking = 1; 40925839Speter return 0; 41025839Speter} 41125839Speter 41225839Speter/* 41325839Speter * Set buffer BUF to blocking I/O. Returns 0 for success or errno 41425839Speter * code. 41525839Speter */ 41625839Speter 41725839Speterint 41825839Speterset_block (buf) 41925839Speter struct buffer *buf; 42025839Speter{ 42125839Speter int status; 42225839Speter 42325839Speter if (! buf->nonblocking) 42425839Speter return 0; 42525839Speter if (buf->block == NULL) 42625839Speter abort (); 42725839Speter status = (*buf->block) (buf->closure, 1); 42825839Speter if (status != 0) 42925839Speter return status; 43025839Speter buf->nonblocking = 0; 43125839Speter return 0; 43225839Speter} 43325839Speter 43425839Speter/* 43525839Speter * Send a character count and some output. Returns errno code or 0 for 43625839Speter * success. 43725839Speter * 43825839Speter * Sending the count in binary is OK since this is only used on a pipe 43925839Speter * within the same system. 44025839Speter */ 44125839Speter 44225839Speterint 44325839Speterbuf_send_counted (buf) 44425839Speter struct buffer *buf; 44525839Speter{ 44625839Speter int size; 44725839Speter struct buffer_data *data; 44825839Speter 44925839Speter size = 0; 45025839Speter for (data = buf->data; data != NULL; data = data->next) 45125839Speter size += data->size; 45225839Speter 45325839Speter data = get_buffer_data (); 45425839Speter if (data == NULL) 45525839Speter { 45625839Speter (*buf->memory_error) (buf); 45725839Speter return ENOMEM; 45825839Speter } 45925839Speter 46025839Speter data->next = buf->data; 46125839Speter buf->data = data; 46225839Speter if (buf->last == NULL) 46325839Speter buf->last = data; 46425839Speter 46525839Speter data->bufp = data->text; 46625839Speter data->size = sizeof (int); 46725839Speter 46825839Speter *((int *) data->text) = size; 46925839Speter 47025839Speter return buf_send_output (buf); 47125839Speter} 47225839Speter 47325839Speter/* 47425839Speter * Send a special count. COUNT should be negative. It will be 47525839Speter * handled speciallyi by buf_copy_counted. This function returns 0 or 47625839Speter * an errno code. 47725839Speter * 47825839Speter * Sending the count in binary is OK since this is only used on a pipe 47925839Speter * within the same system. 48025839Speter */ 48125839Speter 48225839Speterint 48325839Speterbuf_send_special_count (buf, count) 48425839Speter struct buffer *buf; 48525839Speter int count; 48625839Speter{ 48725839Speter struct buffer_data *data; 48825839Speter 48925839Speter data = get_buffer_data (); 49025839Speter if (data == NULL) 49125839Speter { 49225839Speter (*buf->memory_error) (buf); 49325839Speter return ENOMEM; 49425839Speter } 49525839Speter 49625839Speter data->next = buf->data; 49725839Speter buf->data = data; 49825839Speter if (buf->last == NULL) 49925839Speter buf->last = data; 50025839Speter 50125839Speter data->bufp = data->text; 50225839Speter data->size = sizeof (int); 50325839Speter 50425839Speter *((int *) data->text) = count; 50525839Speter 50625839Speter return buf_send_output (buf); 50725839Speter} 50825839Speter 50925839Speter/* Append a list of buffer_data structures to an buffer. */ 51025839Speter 51125839Spetervoid 51225839Speterbuf_append_data (buf, data, last) 51325839Speter struct buffer *buf; 51425839Speter struct buffer_data *data; 51525839Speter struct buffer_data *last; 51625839Speter{ 51725839Speter if (data != NULL) 51825839Speter { 51925839Speter if (buf->data == NULL) 52025839Speter buf->data = data; 52125839Speter else 52225839Speter buf->last->next = data; 52325839Speter buf->last = last; 52425839Speter } 52525839Speter} 52625839Speter 52734461Speter/* Append the data on one buffer to another. This removes the data 52834461Speter from the source buffer. */ 52934461Speter 53034461Spetervoid 53134461Speterbuf_append_buffer (to, from) 53234461Speter struct buffer *to; 53334461Speter struct buffer *from; 53434461Speter{ 53534461Speter buf_append_data (to, from->data, from->last); 53634461Speter from->data = NULL; 53734461Speter from->last = NULL; 53834461Speter} 53934461Speter 54025839Speter/* 54125839Speter * Copy the contents of file F into buffer_data structures. We can't 54225839Speter * copy directly into an buffer, because we want to handle failure and 54325839Speter * succeess differently. Returns 0 on success, or -2 if out of 54425839Speter * memory, or a status code on error. Since the caller happens to 54525839Speter * know the size of the file, it is passed in as SIZE. On success, 54625839Speter * this function sets *RETP and *LASTP, which may be passed to 54725839Speter * buf_append_data. 54825839Speter */ 54925839Speter 55025839Speterint 55125839Speterbuf_read_file (f, size, retp, lastp) 55225839Speter FILE *f; 55325839Speter long size; 55425839Speter struct buffer_data **retp; 55525839Speter struct buffer_data **lastp; 55625839Speter{ 55725839Speter int status; 55825839Speter 55925839Speter *retp = NULL; 56025839Speter *lastp = NULL; 56125839Speter 56225839Speter while (size > 0) 56325839Speter { 56425839Speter struct buffer_data *data; 56525839Speter int get; 56625839Speter 56725839Speter data = get_buffer_data (); 56825839Speter if (data == NULL) 56925839Speter { 57025839Speter status = -2; 57125839Speter goto error_return; 57225839Speter } 57325839Speter 57425839Speter if (*retp == NULL) 57525839Speter *retp = data; 57625839Speter else 57725839Speter (*lastp)->next = data; 57825839Speter data->next = NULL; 57925839Speter *lastp = data; 58025839Speter 58125839Speter data->bufp = data->text; 58225839Speter data->size = 0; 58325839Speter 58425839Speter if (size > BUFFER_DATA_SIZE) 58525839Speter get = BUFFER_DATA_SIZE; 58625839Speter else 58725839Speter get = size; 58825839Speter 58925839Speter errno = EIO; 59025839Speter if (fread (data->text, get, 1, f) != 1) 59125839Speter { 59225839Speter status = errno; 59325839Speter goto error_return; 59425839Speter } 59525839Speter 59625839Speter data->size += get; 59725839Speter size -= get; 59825839Speter } 59925839Speter 60025839Speter return 0; 60125839Speter 60225839Speter error_return: 60325839Speter if (*retp != NULL) 60425839Speter { 60525839Speter (*lastp)->next = free_buffer_data; 60625839Speter free_buffer_data = *retp; 60725839Speter } 60825839Speter return status; 60925839Speter} 61025839Speter 61125839Speter/* 61225839Speter * Copy the contents of file F into buffer_data structures. We can't 61325839Speter * copy directly into an buffer, because we want to handle failure and 61425839Speter * succeess differently. Returns 0 on success, or -2 if out of 61525839Speter * memory, or a status code on error. On success, this function sets 61625839Speter * *RETP and *LASTP, which may be passed to buf_append_data. 61725839Speter */ 61825839Speter 61925839Speterint 62025839Speterbuf_read_file_to_eof (f, retp, lastp) 62125839Speter FILE *f; 62225839Speter struct buffer_data **retp; 62325839Speter struct buffer_data **lastp; 62425839Speter{ 62525839Speter int status; 62625839Speter 62725839Speter *retp = NULL; 62825839Speter *lastp = NULL; 62925839Speter 63025839Speter while (!feof (f)) 63125839Speter { 63225839Speter struct buffer_data *data; 63325839Speter int get, nread; 63425839Speter 63525839Speter data = get_buffer_data (); 63625839Speter if (data == NULL) 63725839Speter { 63825839Speter status = -2; 63925839Speter goto error_return; 64025839Speter } 64125839Speter 64225839Speter if (*retp == NULL) 64325839Speter *retp = data; 64425839Speter else 64525839Speter (*lastp)->next = data; 64625839Speter data->next = NULL; 64725839Speter *lastp = data; 64825839Speter 64925839Speter data->bufp = data->text; 65025839Speter data->size = 0; 65125839Speter 65225839Speter get = BUFFER_DATA_SIZE; 65325839Speter 65425839Speter errno = EIO; 65525839Speter nread = fread (data->text, 1, get, f); 65625839Speter if (nread == 0 && !feof (f)) 65725839Speter { 65825839Speter status = errno; 65925839Speter goto error_return; 66025839Speter } 66125839Speter 66225839Speter data->size = nread; 66325839Speter } 66425839Speter 66525839Speter return 0; 66625839Speter 66725839Speter error_return: 66825839Speter if (*retp != NULL) 66925839Speter { 67025839Speter (*lastp)->next = free_buffer_data; 67125839Speter free_buffer_data = *retp; 67225839Speter } 67325839Speter return status; 67425839Speter} 67525839Speter 67625839Speter/* Return the number of bytes in a chain of buffer_data structures. */ 67725839Speter 67825839Speterint 67925839Speterbuf_chain_length (buf) 68025839Speter struct buffer_data *buf; 68125839Speter{ 68225839Speter int size = 0; 68325839Speter while (buf) 68425839Speter { 68525839Speter size += buf->size; 68625839Speter buf = buf->next; 68725839Speter } 68825839Speter return size; 68925839Speter} 69025839Speter 69134461Speter/* Return the number of bytes in a buffer. */ 69234461Speter 69334461Speterint 69434461Speterbuf_length (buf) 69534461Speter struct buffer *buf; 69634461Speter{ 69734461Speter return buf_chain_length (buf->data); 69834461Speter} 69934461Speter 70025839Speter/* 70125839Speter * Read an arbitrary amount of data into an input buffer. The buffer 70225839Speter * will be in nonblocking mode, and we just grab what we can. Return 70325839Speter * 0 on success, or -1 on end of file, or -2 if out of memory, or an 70425839Speter * error code. If COUNTP is not NULL, *COUNTP is set to the number of 70525839Speter * bytes read. 70625839Speter */ 70725839Speter 70825839Speterint 70925839Speterbuf_input_data (buf, countp) 71025839Speter struct buffer *buf; 71125839Speter int *countp; 71225839Speter{ 71325839Speter if (buf->input == NULL) 71425839Speter abort (); 71525839Speter 71625839Speter if (countp != NULL) 71725839Speter *countp = 0; 71825839Speter 71925839Speter while (1) 72025839Speter { 72125839Speter int get; 72225839Speter int status, nbytes; 72325839Speter 72425839Speter if (buf->data == NULL 72525839Speter || (buf->last->bufp + buf->last->size 72625839Speter == buf->last->text + BUFFER_DATA_SIZE)) 72725839Speter { 72825839Speter struct buffer_data *data; 72925839Speter 73025839Speter data = get_buffer_data (); 73125839Speter if (data == NULL) 73225839Speter { 73325839Speter (*buf->memory_error) (buf); 73425839Speter return -2; 73525839Speter } 73625839Speter 73725839Speter if (buf->data == NULL) 73825839Speter buf->data = data; 73925839Speter else 74025839Speter buf->last->next = data; 74125839Speter data->next = NULL; 74225839Speter buf->last = data; 74325839Speter 74425839Speter data->bufp = data->text; 74525839Speter data->size = 0; 74625839Speter } 74725839Speter 74825839Speter get = ((buf->last->text + BUFFER_DATA_SIZE) 74925839Speter - (buf->last->bufp + buf->last->size)); 75025839Speter 75125839Speter status = (*buf->input) (buf->closure, 75225839Speter buf->last->bufp + buf->last->size, 75325839Speter 0, get, &nbytes); 75425839Speter if (status != 0) 75525839Speter return status; 75625839Speter 75725839Speter buf->last->size += nbytes; 75825839Speter if (countp != NULL) 75925839Speter *countp += nbytes; 76025839Speter 76125839Speter if (nbytes < get) 76225839Speter { 76325839Speter /* If we did not fill the buffer, then presumably we read 76425839Speter all the available data. */ 76525839Speter return 0; 76625839Speter } 76725839Speter } 76825839Speter 76925839Speter /*NOTREACHED*/ 77025839Speter} 77125839Speter 77225839Speter/* 77325839Speter * Read a line (characters up to a \012) from an input buffer. (We 77425839Speter * use \012 rather than \n for the benefit of non Unix clients for 77525839Speter * which \n means something else). This returns 0 on success, or -1 77625839Speter * on end of file, or -2 if out of memory, or an error code. If it 77725839Speter * succeeds, it sets *LINE to an allocated buffer holding the contents 77825839Speter * of the line. The trailing \012 is not included in the buffer. If 77925839Speter * LENP is not NULL, then *LENP is set to the number of bytes read; 78025839Speter * strlen may not work, because there may be embedded null bytes. 78125839Speter */ 78225839Speter 78325839Speterint 78425839Speterbuf_read_line (buf, line, lenp) 78525839Speter struct buffer *buf; 78625839Speter char **line; 78725839Speter int *lenp; 78825839Speter{ 78925839Speter if (buf->input == NULL) 79025839Speter abort (); 79125839Speter 79225839Speter *line = NULL; 79325839Speter 79425839Speter while (1) 79525839Speter { 79625839Speter int len, finallen = 0; 79725839Speter struct buffer_data *data; 79825839Speter char *nl; 79925839Speter 80025839Speter /* See if there is a newline in BUF. */ 80125839Speter len = 0; 80225839Speter for (data = buf->data; data != NULL; data = data->next) 80325839Speter { 80425839Speter nl = memchr (data->bufp, '\012', data->size); 80525839Speter if (nl != NULL) 80625839Speter { 80725839Speter finallen = nl - data->bufp; 80825839Speter len += finallen; 80925839Speter break; 81025839Speter } 81125839Speter len += data->size; 81225839Speter } 81325839Speter 81425839Speter /* If we found a newline, copy the line into a memory buffer, 81525839Speter and remove it from BUF. */ 81625839Speter if (data != NULL) 81725839Speter { 81825839Speter char *p; 81925839Speter struct buffer_data *nldata; 82025839Speter 821109660Speter p = xmalloc (len + 1); 82225839Speter if (p == NULL) 82325839Speter return -2; 82425839Speter *line = p; 82525839Speter 82625839Speter nldata = data; 82725839Speter data = buf->data; 82825839Speter while (data != nldata) 82925839Speter { 83025839Speter struct buffer_data *next; 83125839Speter 83225839Speter memcpy (p, data->bufp, data->size); 83325839Speter p += data->size; 83425839Speter next = data->next; 83525839Speter data->next = free_buffer_data; 83625839Speter free_buffer_data = data; 83725839Speter data = next; 83825839Speter } 83925839Speter 84025839Speter memcpy (p, data->bufp, finallen); 84125839Speter p[finallen] = '\0'; 84225839Speter 84325839Speter data->size -= finallen + 1; 84425839Speter data->bufp = nl + 1; 84525839Speter buf->data = data; 84625839Speter 84725839Speter if (lenp != NULL) 84825839Speter *lenp = len; 84925839Speter 85025839Speter return 0; 85125839Speter } 85225839Speter 85325839Speter /* Read more data until we get a newline. */ 85425839Speter while (1) 85525839Speter { 85625839Speter int size, status, nbytes; 85725839Speter char *mem; 85825839Speter 85925839Speter if (buf->data == NULL 86025839Speter || (buf->last->bufp + buf->last->size 86125839Speter == buf->last->text + BUFFER_DATA_SIZE)) 86225839Speter { 86325839Speter data = get_buffer_data (); 86425839Speter if (data == NULL) 86525839Speter { 86625839Speter (*buf->memory_error) (buf); 86725839Speter return -2; 86825839Speter } 86925839Speter 87025839Speter if (buf->data == NULL) 87125839Speter buf->data = data; 87225839Speter else 87325839Speter buf->last->next = data; 87425839Speter data->next = NULL; 87525839Speter buf->last = data; 87625839Speter 87725839Speter data->bufp = data->text; 87825839Speter data->size = 0; 87925839Speter } 88025839Speter 88125839Speter mem = buf->last->bufp + buf->last->size; 88225839Speter size = (buf->last->text + BUFFER_DATA_SIZE) - mem; 88325839Speter 88425839Speter /* We need to read at least 1 byte. We can handle up to 88525839Speter SIZE bytes. This will only be efficient if the 88625839Speter underlying communication stream does its own buffering, 88725839Speter or is clever about getting more than 1 byte at a time. */ 88825839Speter status = (*buf->input) (buf->closure, mem, 1, size, &nbytes); 88925839Speter if (status != 0) 89025839Speter return status; 89125839Speter 89225839Speter buf->last->size += nbytes; 89325839Speter 89425839Speter /* Optimize slightly to avoid an unnecessary call to 89525839Speter memchr. */ 89625839Speter if (nbytes == 1) 89725839Speter { 89825839Speter if (*mem == '\012') 89925839Speter break; 90025839Speter } 90125839Speter else 90225839Speter { 90325839Speter if (memchr (mem, '\012', nbytes) != NULL) 90425839Speter break; 90525839Speter } 90625839Speter } 90725839Speter } 90825839Speter} 90925839Speter 91025839Speter/* 91125839Speter * Extract data from the input buffer BUF. This will read up to WANT 91225839Speter * bytes from the buffer. It will set *RETDATA to point at the bytes, 91325839Speter * and set *GOT to the number of bytes to be found there. Any buffer 91425839Speter * call which uses BUF may change the contents of the buffer at *DATA, 91525839Speter * so the data should be fully processed before any further calls are 91625839Speter * made. This returns 0 on success, or -1 on end of file, or -2 if 91725839Speter * out of memory, or an error code. 91825839Speter */ 91925839Speter 92025839Speterint 92125839Speterbuf_read_data (buf, want, retdata, got) 92225839Speter struct buffer *buf; 92325839Speter int want; 92425839Speter char **retdata; 92525839Speter int *got; 92625839Speter{ 92725839Speter if (buf->input == NULL) 92825839Speter abort (); 92925839Speter 93025839Speter while (buf->data != NULL && buf->data->size == 0) 93125839Speter { 93225839Speter struct buffer_data *next; 93325839Speter 93425839Speter next = buf->data->next; 93525839Speter buf->data->next = free_buffer_data; 93625839Speter free_buffer_data = buf->data; 93725839Speter buf->data = next; 93825839Speter if (next == NULL) 93925839Speter buf->last = NULL; 94025839Speter } 94125839Speter 94225839Speter if (buf->data == NULL) 94325839Speter { 94425839Speter struct buffer_data *data; 94525839Speter int get, status, nbytes; 94625839Speter 94725839Speter data = get_buffer_data (); 94825839Speter if (data == NULL) 94925839Speter { 95025839Speter (*buf->memory_error) (buf); 95125839Speter return -2; 95225839Speter } 95325839Speter 95425839Speter buf->data = data; 95525839Speter buf->last = data; 95625839Speter data->next = NULL; 95725839Speter data->bufp = data->text; 95825839Speter data->size = 0; 95925839Speter 96025839Speter if (want < BUFFER_DATA_SIZE) 96125839Speter get = want; 96225839Speter else 96325839Speter get = BUFFER_DATA_SIZE; 96425839Speter status = (*buf->input) (buf->closure, data->bufp, get, 96525839Speter BUFFER_DATA_SIZE, &nbytes); 96625839Speter if (status != 0) 96725839Speter return status; 96825839Speter 96925839Speter data->size = nbytes; 97025839Speter } 97125839Speter 97225839Speter *retdata = buf->data->bufp; 97325839Speter if (want < buf->data->size) 97425839Speter { 97525839Speter *got = want; 97625839Speter buf->data->size -= want; 97725839Speter buf->data->bufp += want; 97825839Speter } 97925839Speter else 98025839Speter { 98125839Speter *got = buf->data->size; 98225839Speter buf->data->size = 0; 98325839Speter } 98425839Speter 98525839Speter return 0; 98625839Speter} 98725839Speter 98825839Speter/* 98925839Speter * Copy lines from an input buffer to an output buffer. This copies 99025839Speter * all complete lines (characters up to a newline) from INBUF to 99125839Speter * OUTBUF. Each line in OUTBUF is preceded by the character COMMAND 99225839Speter * and a space. 99325839Speter */ 99425839Speter 99525839Spetervoid 99625839Speterbuf_copy_lines (outbuf, inbuf, command) 99725839Speter struct buffer *outbuf; 99825839Speter struct buffer *inbuf; 99925839Speter int command; 100025839Speter{ 100125839Speter while (1) 100225839Speter { 100325839Speter struct buffer_data *data; 100425839Speter struct buffer_data *nldata; 100525839Speter char *nl; 100625839Speter int len; 100725839Speter 100825839Speter /* See if there is a newline in INBUF. */ 100925839Speter nldata = NULL; 101025839Speter nl = NULL; 101125839Speter for (data = inbuf->data; data != NULL; data = data->next) 101225839Speter { 101325839Speter nl = memchr (data->bufp, '\n', data->size); 101425839Speter if (nl != NULL) 101525839Speter { 101625839Speter nldata = data; 101725839Speter break; 101825839Speter } 101925839Speter } 102025839Speter 102125839Speter if (nldata == NULL) 102225839Speter { 102325839Speter /* There are no more lines in INBUF. */ 102425839Speter return; 102525839Speter } 102625839Speter 102725839Speter /* Put in the command. */ 102825839Speter buf_append_char (outbuf, command); 102925839Speter buf_append_char (outbuf, ' '); 103025839Speter 103125839Speter if (inbuf->data != nldata) 103225839Speter { 103325839Speter /* 103425839Speter * Simply move over all the buffers up to the one containing 103525839Speter * the newline. 103625839Speter */ 103725839Speter for (data = inbuf->data; data->next != nldata; data = data->next) 103825839Speter ; 103925839Speter data->next = NULL; 104025839Speter buf_append_data (outbuf, inbuf->data, data); 104125839Speter inbuf->data = nldata; 104225839Speter } 104325839Speter 104425839Speter /* 104525839Speter * If the newline is at the very end of the buffer, just move 104625839Speter * the buffer onto OUTBUF. Otherwise we must copy the data. 104725839Speter */ 104825839Speter len = nl + 1 - nldata->bufp; 104925839Speter if (len == nldata->size) 105025839Speter { 105125839Speter inbuf->data = nldata->next; 105225839Speter if (inbuf->data == NULL) 105325839Speter inbuf->last = NULL; 105425839Speter 105525839Speter nldata->next = NULL; 105625839Speter buf_append_data (outbuf, nldata, nldata); 105725839Speter } 105825839Speter else 105925839Speter { 106025839Speter buf_output (outbuf, nldata->bufp, len); 106125839Speter nldata->bufp += len; 106225839Speter nldata->size -= len; 106325839Speter } 106425839Speter } 106525839Speter} 106625839Speter 106725839Speter/* 106825839Speter * Copy counted data from one buffer to another. The count is an 106925839Speter * integer, host size, host byte order (it is only used across a 107025839Speter * pipe). If there is enough data, it should be moved over. If there 107125839Speter * is not enough data, it should remain on the original buffer. A 107225839Speter * negative count is a special case. if one is seen, *SPECIAL is set 107325839Speter * to the (negative) count value and no additional data is gathered 107425839Speter * from the buffer; normally *SPECIAL is set to 0. This function 107525839Speter * returns the number of bytes it needs to see in order to actually 107625839Speter * copy something over. 107725839Speter */ 107825839Speter 107925839Speterint 108025839Speterbuf_copy_counted (outbuf, inbuf, special) 108125839Speter struct buffer *outbuf; 108225839Speter struct buffer *inbuf; 108325839Speter int *special; 108425839Speter{ 108525839Speter *special = 0; 108625839Speter 108725839Speter while (1) 108825839Speter { 108925839Speter struct buffer_data *data; 109025839Speter int need; 109125839Speter union 109225839Speter { 109325839Speter char intbuf[sizeof (int)]; 109425839Speter int i; 109525839Speter } u; 109625839Speter char *intp; 109725839Speter int count; 109825839Speter struct buffer_data *start; 109925839Speter int startoff; 110025839Speter struct buffer_data *stop; 110125839Speter int stopwant; 110225839Speter 110325839Speter /* See if we have enough bytes to figure out the count. */ 110425839Speter need = sizeof (int); 110525839Speter intp = u.intbuf; 110625839Speter for (data = inbuf->data; data != NULL; data = data->next) 110725839Speter { 110825839Speter if (data->size >= need) 110925839Speter { 111025839Speter memcpy (intp, data->bufp, need); 111125839Speter break; 111225839Speter } 111325839Speter memcpy (intp, data->bufp, data->size); 111425839Speter intp += data->size; 111525839Speter need -= data->size; 111625839Speter } 111725839Speter if (data == NULL) 111825839Speter { 111925839Speter /* We don't have enough bytes to form an integer. */ 112025839Speter return need; 112125839Speter } 112225839Speter 112325839Speter count = u.i; 112425839Speter start = data; 112525839Speter startoff = need; 112625839Speter 112725839Speter if (count < 0) 112825839Speter { 112925839Speter /* A negative COUNT is a special case meaning that we 113025839Speter don't need any further information. */ 113125839Speter stop = start; 113225839Speter stopwant = 0; 113325839Speter } 113425839Speter else 113525839Speter { 113625839Speter /* 113725839Speter * We have an integer in COUNT. We have gotten all the 113825839Speter * data from INBUF in all buffers before START, and we 113925839Speter * have gotten STARTOFF bytes from START. See if we have 114025839Speter * enough bytes remaining in INBUF. 114125839Speter */ 114225839Speter need = count - (start->size - startoff); 114325839Speter if (need <= 0) 114425839Speter { 114525839Speter stop = start; 114625839Speter stopwant = count; 114725839Speter } 114825839Speter else 114925839Speter { 115025839Speter for (data = start->next; data != NULL; data = data->next) 115125839Speter { 115225839Speter if (need <= data->size) 115325839Speter break; 115425839Speter need -= data->size; 115525839Speter } 115625839Speter if (data == NULL) 115725839Speter { 115825839Speter /* We don't have enough bytes. */ 115925839Speter return need; 116025839Speter } 116125839Speter stop = data; 116225839Speter stopwant = need; 116325839Speter } 116425839Speter } 116525839Speter 116625839Speter /* 116725839Speter * We have enough bytes. Free any buffers in INBUF before 116825839Speter * START, and remove STARTOFF bytes from START, so that we can 116925839Speter * forget about STARTOFF. 117025839Speter */ 117125839Speter start->bufp += startoff; 117225839Speter start->size -= startoff; 117325839Speter 117425839Speter if (start->size == 0) 117525839Speter start = start->next; 117625839Speter 117725839Speter if (stop->size == stopwant) 117825839Speter { 117925839Speter stop = stop->next; 118025839Speter stopwant = 0; 118125839Speter } 118225839Speter 118325839Speter while (inbuf->data != start) 118425839Speter { 118525839Speter data = inbuf->data; 118625839Speter inbuf->data = data->next; 118725839Speter data->next = free_buffer_data; 118825839Speter free_buffer_data = data; 118925839Speter } 119025839Speter 119125839Speter /* If COUNT is negative, set *SPECIAL and get out now. */ 119225839Speter if (count < 0) 119325839Speter { 119425839Speter *special = count; 119525839Speter return 0; 119625839Speter } 119725839Speter 119825839Speter /* 119925839Speter * We want to copy over the bytes from START through STOP. We 120025839Speter * only want STOPWANT bytes from STOP. 120125839Speter */ 120225839Speter 120325839Speter if (start != stop) 120425839Speter { 120525839Speter /* Attach the buffers from START through STOP to OUTBUF. */ 120625839Speter for (data = start; data->next != stop; data = data->next) 120725839Speter ; 120825839Speter inbuf->data = stop; 120925839Speter data->next = NULL; 121025839Speter buf_append_data (outbuf, start, data); 121125839Speter } 121225839Speter 121325839Speter if (stopwant > 0) 121425839Speter { 121525839Speter buf_output (outbuf, stop->bufp, stopwant); 121625839Speter stop->bufp += stopwant; 121725839Speter stop->size -= stopwant; 121825839Speter } 121925839Speter } 122025839Speter 122125839Speter /*NOTREACHED*/ 122225839Speter} 122325839Speter 122425839Speter/* Shut down a buffer. This returns 0 on success, or an errno code. */ 122525839Speter 122625839Speterint 122725839Speterbuf_shutdown (buf) 122825839Speter struct buffer *buf; 122925839Speter{ 123025839Speter if (buf->shutdown) 1231102840Speter return (*buf->shutdown) (buf); 123225839Speter return 0; 123325839Speter} 123425839Speter 1235128269Speter 1236128269Speter 123725839Speter/* The simplest type of buffer is one built on top of a stdio FILE. 123825839Speter For simplicity, and because it is all that is required, we do not 123925839Speter implement setting this type of buffer into nonblocking mode. The 124025839Speter closure field is just a FILE *. */ 124125839Speter 124225839Speterstatic int stdio_buffer_input PROTO((void *, char *, int, int, int *)); 124325839Speterstatic int stdio_buffer_output PROTO((void *, const char *, int, int *)); 124425839Speterstatic int stdio_buffer_flush PROTO((void *)); 1245102840Speterstatic int stdio_buffer_shutdown PROTO((struct buffer *buf)); 124625839Speter 1247128269Speter 1248128269Speter 124925839Speter/* Initialize a buffer built on a stdio FILE. */ 1250102840Speterstruct stdio_buffer_closure 1251102840Speter{ 1252102840Speter FILE *fp; 1253102840Speter int child_pid; 1254102840Speter}; 1255102840Speter 1256128269Speter 1257128269Speter 125832785Speterstruct buffer * 1259102840Speterstdio_buffer_initialize (fp, child_pid, input, memory) 126025839Speter FILE *fp; 1261102840Speter int child_pid; 126225839Speter int input; 126325839Speter void (*memory) PROTO((struct buffer *)); 126425839Speter{ 1265109660Speter struct stdio_buffer_closure *bc = xmalloc (sizeof (*bc)); 1266102840Speter 1267102840Speter bc->fp = fp; 1268102840Speter bc->child_pid = child_pid; 1269102840Speter 127025839Speter return buf_initialize (input ? stdio_buffer_input : NULL, 127125839Speter input ? NULL : stdio_buffer_output, 127225839Speter input ? NULL : stdio_buffer_flush, 127325839Speter (int (*) PROTO((void *, int))) NULL, 1274102840Speter stdio_buffer_shutdown, 127525839Speter memory, 1276102840Speter (void *) bc); 127725839Speter} 127825839Speter 1279107487Speter/* Return the file associated with a stdio buffer. */ 1280107487SpeterFILE * 1281107487Speterstdio_buffer_get_file (buf) 1282107487Speter struct buffer *buf; 1283107487Speter{ 1284107487Speter struct stdio_buffer_closure *bc; 1285107487Speter 1286107487Speter assert(buf->shutdown == stdio_buffer_shutdown); 1287107487Speter 1288107487Speter bc = (struct stdio_buffer_closure *) buf->closure; 1289107487Speter 1290107487Speter return(bc->fp); 1291107487Speter} 1292107487Speter 129325839Speter/* The buffer input function for a buffer built on a stdio FILE. */ 129425839Speter 129525839Speterstatic int 129625839Speterstdio_buffer_input (closure, data, need, size, got) 129725839Speter void *closure; 129825839Speter char *data; 129925839Speter int need; 130025839Speter int size; 130125839Speter int *got; 130225839Speter{ 1303102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 130425839Speter int nbytes; 130525839Speter 130625839Speter /* Since stdio does its own buffering, we don't worry about 130725839Speter getting more bytes than we need. */ 130825839Speter 130925839Speter if (need == 0 || need == 1) 131025839Speter { 131125839Speter int ch; 131225839Speter 1313102840Speter ch = getc (bc->fp); 131425839Speter 131525839Speter if (ch == EOF) 131625839Speter { 1317102840Speter if (feof (bc->fp)) 131825839Speter return -1; 131925839Speter else if (errno == 0) 132025839Speter return EIO; 132125839Speter else 132225839Speter return errno; 132325839Speter } 132425839Speter 132525839Speter *data = ch; 132625839Speter *got = 1; 132725839Speter return 0; 132825839Speter } 132925839Speter 1330102840Speter nbytes = fread (data, 1, need, bc->fp); 133125839Speter 133225839Speter if (nbytes == 0) 133325839Speter { 133425839Speter *got = 0; 1335102840Speter if (feof (bc->fp)) 133625839Speter return -1; 133725839Speter else if (errno == 0) 133825839Speter return EIO; 133925839Speter else 134025839Speter return errno; 134125839Speter } 134225839Speter 134325839Speter *got = nbytes; 134425839Speter 134525839Speter return 0; 134625839Speter} 134725839Speter 134825839Speter/* The buffer output function for a buffer built on a stdio FILE. */ 134925839Speter 135025839Speterstatic int 135125839Speterstdio_buffer_output (closure, data, have, wrote) 135225839Speter void *closure; 135325839Speter const char *data; 135425839Speter int have; 135525839Speter int *wrote; 135625839Speter{ 1357102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 135825839Speter 135925839Speter *wrote = 0; 136025839Speter 136125839Speter while (have > 0) 136225839Speter { 136325839Speter int nbytes; 136425839Speter 1365102840Speter nbytes = fwrite (data, 1, have, bc->fp); 136625839Speter 136725839Speter if (nbytes != have) 136825839Speter { 136925839Speter if (errno == 0) 137025839Speter return EIO; 137125839Speter else 137225839Speter return errno; 137325839Speter } 137425839Speter 137525839Speter *wrote += nbytes; 137625839Speter have -= nbytes; 137725839Speter data += nbytes; 137825839Speter } 137925839Speter 138025839Speter return 0; 138125839Speter} 138225839Speter 1383128269Speter 1384128269Speter 138525839Speter/* The buffer flush function for a buffer built on a stdio FILE. */ 138625839Speterstatic int 138725839Speterstdio_buffer_flush (closure) 138825839Speter void *closure; 138925839Speter{ 1390102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 139125839Speter 1392102840Speter if (fflush (bc->fp) != 0) 139325839Speter { 139425839Speter if (errno == 0) 139525839Speter return EIO; 139625839Speter else 139725839Speter return errno; 139825839Speter } 139925839Speter 140025839Speter return 0; 140125839Speter} 140225839Speter 1403102840Speter 1404102840Speter 1405102840Speterstatic int 1406102840Speterstdio_buffer_shutdown (buf) 1407102840Speter struct buffer *buf; 1408102840Speter{ 1409128269Speter struct stdio_buffer_closure *bc = buf->closure; 1410102840Speter struct stat s; 1411102840Speter int closefp = 1; 1412102840Speter 1413102840Speter /* Must be a pipe or a socket. What could go wrong? */ 1414128269Speter assert (fstat (fileno (bc->fp), &s) != -1); 1415102840Speter 1416102840Speter /* Flush the buffer if we can */ 1417102840Speter if (buf->flush) 1418102840Speter { 1419102840Speter buf_flush (buf, 1); 1420102840Speter buf->flush = NULL; 1421102840Speter } 1422102840Speter 1423102840Speter if (buf->input) 1424102840Speter { 1425128269Speter /* There used to be a check here for unread data in the buffer of on 1426128269Speter * the pipe, but it was deemed unnecessary and possibly dangerous. In 1427128269Speter * some sense it could be second-guessing the caller who requested it 1428128269Speter * closed, as well. 1429128269Speter */ 1430102840Speter 1431102840Speter# ifdef SHUTDOWN_SERVER 1432102840Speter if (current_parsed_root->method != server_method) 1433102840Speter# endif 1434102840Speter# ifndef NO_SOCKET_TO_FD 1435102840Speter { 1436102840Speter /* shutdown() sockets */ 1437128269Speter if (S_ISSOCK (s.st_mode)) 1438128269Speter shutdown (fileno (bc->fp), 0); 1439102840Speter } 1440102840Speter# endif /* NO_SOCKET_TO_FD */ 1441102840Speter# ifdef START_RSH_WITH_POPEN_RW 1442102840Speter /* Can't be set with SHUTDOWN_SERVER defined */ 1443102840Speter else if (pclose (bc->fp) == EOF) 1444102840Speter { 1445102840Speter error (1, errno, "closing connection to %s", 1446102840Speter current_parsed_root->hostname); 1447102840Speter closefp = 0; 1448102840Speter } 1449102840Speter# endif /* START_RSH_WITH_POPEN_RW */ 1450102840Speter 1451102840Speter buf->input = NULL; 1452102840Speter } 1453102840Speter else if (buf->output) 1454102840Speter { 1455102840Speter# ifdef SHUTDOWN_SERVER 1456102840Speter /* FIXME: Should have a SHUTDOWN_SERVER_INPUT & 1457102840Speter * SHUTDOWN_SERVER_OUTPUT 1458102840Speter */ 1459102840Speter if (current_parsed_root->method == server_method) 1460128269Speter SHUTDOWN_SERVER (fileno (bc->fp)); 1461102840Speter else 1462102840Speter# endif 1463102840Speter# ifndef NO_SOCKET_TO_FD 1464102840Speter /* shutdown() sockets */ 1465128269Speter if (S_ISSOCK (s.st_mode)) 1466128269Speter shutdown (fileno (bc->fp), 1); 1467102840Speter# else 1468102840Speter { 1469102840Speter /* I'm not sure I like this empty block, but the alternative 1470102840Speter * is a another nested NO_SOCKET_TO_FD switch above. 1471102840Speter */ 1472102840Speter } 1473102840Speter# endif /* NO_SOCKET_TO_FD */ 1474102840Speter 1475102840Speter buf->output = NULL; 1476102840Speter } 1477102840Speter 1478102840Speter if (closefp && fclose (bc->fp) == EOF) 1479128269Speter { 1480128269Speter if (0 1481128269Speter# ifdef SERVER_SUPPORT 1482128269Speter || server_active 1483128269Speter# endif /* SERVER_SUPPORT */ 1484128269Speter ) 1485128269Speter { 1486128269Speter /* Syslog this? */ 1487128269Speter } 1488128269Speter# ifdef CLIENT_SUPPORT 1489128269Speter else 1490128269Speter error (1, errno, 1491128269Speter "closing down connection to %s", 1492128269Speter current_parsed_root->hostname); 1493128269Speter# endif /* CLIENT_SUPPORT */ 1494128269Speter } 1495102840Speter 1496102840Speter /* If we were talking to a process, make sure it exited */ 1497128269Speter if (bc->child_pid) 1498128269Speter { 1499128269Speter int w; 1500102840Speter 1501128269Speter do 1502128269Speter w = waitpid (bc->child_pid, (int *) 0, 0); 1503128269Speter while (w == -1 && errno == EINTR); 1504128269Speter if (w == -1) 1505128269Speter error (1, errno, "waiting for process %d", bc->child_pid); 1506128269Speter } 1507102840Speter return 0; 1508102840Speter} 1509102840Speter 1510102840Speter 1511102840Speter 151232785Speter/* Certain types of communication input and output data in packets, 151332785Speter where each packet is translated in some fashion. The packetizing 151432785Speter buffer type supports that, given a buffer which handles lower level 151532785Speter I/O and a routine to translate the data in a packet. 151632785Speter 151732785Speter This code uses two bytes for the size of a packet, so packets are 151832785Speter restricted to 65536 bytes in total. 151932785Speter 152032785Speter The translation functions should just translate; they may not 152132785Speter significantly increase or decrease the amount of data. The actual 152232785Speter size of the initial data is part of the translated data. The 152332785Speter output translation routine may add up to PACKET_SLOP additional 152432785Speter bytes, and the input translation routine should shrink the data 152532785Speter correspondingly. */ 152632785Speter 152732785Speter#define PACKET_SLOP (100) 152832785Speter 152932785Speter/* This structure is the closure field of a packetizing buffer. */ 153032785Speter 153132785Speterstruct packetizing_buffer 153232785Speter{ 153332785Speter /* The underlying buffer. */ 153432785Speter struct buffer *buf; 153532785Speter /* The input translation function. Exactly one of inpfn and outfn 153632785Speter will be NULL. The input translation function should 153732785Speter untranslate the data in INPUT, storing the result in OUTPUT. 153832785Speter SIZE is the amount of data in INPUT, and is also the size of 153932785Speter OUTPUT. This should return 0 on success, or an errno code. */ 154032785Speter int (*inpfn) PROTO((void *fnclosure, const char *input, char *output, 154132785Speter int size)); 154232785Speter /* The output translation function. This should translate the 154332785Speter data in INPUT, storing the result in OUTPUT. The first two 154432785Speter bytes in INPUT will be the size of the data, and so will SIZE. 154532785Speter This should set *TRANSLATED to the amount of translated data in 154632785Speter OUTPUT. OUTPUT is large enough to hold SIZE + PACKET_SLOP 154732785Speter bytes. This should return 0 on success, or an errno code. */ 154832785Speter int (*outfn) PROTO((void *fnclosure, const char *input, char *output, 154932785Speter int size, int *translated)); 155032785Speter /* A closure for the translation function. */ 155132785Speter void *fnclosure; 155232785Speter /* For an input buffer, we may have to buffer up data here. */ 155332785Speter /* This is non-zero if the buffered data has been translated. 155432785Speter Otherwise, the buffered data has not been translated, and starts 155532785Speter with the two byte packet size. */ 155632785Speter int translated; 155732785Speter /* The amount of buffered data. */ 155832785Speter int holdsize; 155932785Speter /* The buffer allocated to hold the data. */ 156032785Speter char *holdbuf; 156132785Speter /* The size of holdbuf. */ 156232785Speter int holdbufsize; 156332785Speter /* If translated is set, we need another data pointer to track 156432785Speter where we are in holdbuf. If translated is clear, then this 156532785Speter pointer is not used. */ 156632785Speter char *holddata; 156732785Speter}; 156832785Speter 156932785Speterstatic int packetizing_buffer_input PROTO((void *, char *, int, int, int *)); 157032785Speterstatic int packetizing_buffer_output PROTO((void *, const char *, int, int *)); 157132785Speterstatic int packetizing_buffer_flush PROTO((void *)); 157232785Speterstatic int packetizing_buffer_block PROTO((void *, int)); 1573102840Speterstatic int packetizing_buffer_shutdown PROTO((struct buffer *)); 157432785Speter 157532785Speter/* Create a packetizing buffer. */ 157632785Speter 157732785Speterstruct buffer * 157832785Speterpacketizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory) 157932785Speter struct buffer *buf; 158032785Speter int (*inpfn) PROTO ((void *, const char *, char *, int)); 158132785Speter int (*outfn) PROTO ((void *, const char *, char *, int, int *)); 158232785Speter void *fnclosure; 158332785Speter void (*memory) PROTO((struct buffer *)); 158432785Speter{ 158532785Speter struct packetizing_buffer *pb; 158632785Speter 158732785Speter pb = (struct packetizing_buffer *) xmalloc (sizeof *pb); 158832785Speter memset (pb, 0, sizeof *pb); 158932785Speter 159032785Speter pb->buf = buf; 159132785Speter pb->inpfn = inpfn; 159232785Speter pb->outfn = outfn; 159332785Speter pb->fnclosure = fnclosure; 159432785Speter 159532785Speter if (inpfn != NULL) 159632785Speter { 159732785Speter /* Add PACKET_SLOP to handle larger translated packets, and 159832785Speter add 2 for the count. This buffer is increased if 159932785Speter necessary. */ 160032785Speter pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2; 160132785Speter pb->holdbuf = xmalloc (pb->holdbufsize); 160232785Speter } 160332785Speter 160432785Speter return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL, 160532785Speter inpfn != NULL ? NULL : packetizing_buffer_output, 160632785Speter inpfn != NULL ? NULL : packetizing_buffer_flush, 160732785Speter packetizing_buffer_block, 160832785Speter packetizing_buffer_shutdown, 160932785Speter memory, 161032785Speter pb); 161132785Speter} 161232785Speter 161332785Speter/* Input data from a packetizing buffer. */ 161432785Speter 161532785Speterstatic int 161632785Speterpacketizing_buffer_input (closure, data, need, size, got) 161732785Speter void *closure; 161832785Speter char *data; 161932785Speter int need; 162032785Speter int size; 162132785Speter int *got; 162232785Speter{ 162332785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 162432785Speter 162532785Speter *got = 0; 162632785Speter 162732785Speter if (pb->holdsize > 0 && pb->translated) 162832785Speter { 162932785Speter int copy; 163032785Speter 163132785Speter copy = pb->holdsize; 163232785Speter 163332785Speter if (copy > size) 163432785Speter { 163532785Speter memcpy (data, pb->holddata, size); 163632785Speter pb->holdsize -= size; 163732785Speter pb->holddata += size; 163832785Speter *got = size; 163932785Speter return 0; 164032785Speter } 164132785Speter 164232785Speter memcpy (data, pb->holddata, copy); 164332785Speter pb->holdsize = 0; 164432785Speter pb->translated = 0; 164532785Speter 164632785Speter data += copy; 164732785Speter need -= copy; 164832785Speter size -= copy; 164932785Speter *got = copy; 165032785Speter } 165132785Speter 165232785Speter while (need > 0 || *got == 0) 165332785Speter { 165432785Speter int get, status, nread, count, tcount; 165532785Speter char *bytes; 165632785Speter char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP]; 165732785Speter char *inbuf, *outbuf; 165832785Speter 165932785Speter /* If we don't already have the two byte count, get it. */ 166032785Speter if (pb->holdsize < 2) 166132785Speter { 166232785Speter get = 2 - pb->holdsize; 166332785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 166432785Speter if (status != 0) 166532785Speter { 166632785Speter /* buf_read_data can return -2, but a buffer input 166732785Speter function is only supposed to return -1, 0, or an 166832785Speter error code. */ 166932785Speter if (status == -2) 167032785Speter status = ENOMEM; 167132785Speter return status; 167232785Speter } 167332785Speter 167432785Speter if (nread == 0) 167532785Speter { 167632785Speter /* The buffer is in nonblocking mode, and we didn't 167732785Speter manage to read anything. */ 167832785Speter return 0; 167932785Speter } 168032785Speter 168132785Speter if (get == 1) 168232785Speter pb->holdbuf[1] = bytes[0]; 168332785Speter else 168432785Speter { 168532785Speter pb->holdbuf[0] = bytes[0]; 168632785Speter if (nread < 2) 168732785Speter { 168832785Speter /* We only got one byte, but we needed two. Stash 168932785Speter the byte we got, and try again. */ 169032785Speter pb->holdsize = 1; 169132785Speter continue; 169232785Speter } 169332785Speter pb->holdbuf[1] = bytes[1]; 169432785Speter } 169532785Speter pb->holdsize = 2; 169632785Speter } 169732785Speter 169832785Speter /* Read the packet. */ 169932785Speter 170032785Speter count = (((pb->holdbuf[0] & 0xff) << 8) 170132785Speter + (pb->holdbuf[1] & 0xff)); 170232785Speter 170332785Speter if (count + 2 > pb->holdbufsize) 170432785Speter { 170532785Speter char *n; 170632785Speter 170732785Speter /* We didn't allocate enough space in the initialize 170832785Speter function. */ 170932785Speter 1710109660Speter n = xrealloc (pb->holdbuf, count + 2); 171132785Speter if (n == NULL) 171232785Speter { 171332785Speter (*pb->buf->memory_error) (pb->buf); 171432785Speter return ENOMEM; 171532785Speter } 171632785Speter pb->holdbuf = n; 171732785Speter pb->holdbufsize = count + 2; 171832785Speter } 171932785Speter 172032785Speter get = count - (pb->holdsize - 2); 172132785Speter 172232785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 172332785Speter if (status != 0) 172432785Speter { 172532785Speter /* buf_read_data can return -2, but a buffer input 172632785Speter function is only supposed to return -1, 0, or an error 172732785Speter code. */ 172832785Speter if (status == -2) 172932785Speter status = ENOMEM; 173032785Speter return status; 173132785Speter } 173232785Speter 173332785Speter if (nread == 0) 173432785Speter { 173532785Speter /* We did not get any data. Presumably the buffer is in 173632785Speter nonblocking mode. */ 173732785Speter return 0; 173832785Speter } 173932785Speter 174032785Speter if (nread < get) 174132785Speter { 174232785Speter /* We did not get all the data we need to fill the packet. 174332785Speter buf_read_data does not promise to return all the bytes 174432785Speter requested, so we must try again. */ 174532785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 174632785Speter pb->holdsize += nread; 174732785Speter continue; 174832785Speter } 174932785Speter 175032785Speter /* We have a complete untranslated packet of COUNT bytes. */ 175132785Speter 175232785Speter if (pb->holdsize == 2) 175332785Speter { 175432785Speter /* We just read the entire packet (the 2 bytes in 175532785Speter PB->HOLDBUF are the size). Save a memcpy by 175632785Speter translating directly from BYTES. */ 175732785Speter inbuf = bytes; 175832785Speter } 175932785Speter else 176032785Speter { 176132785Speter /* We already had a partial packet in PB->HOLDBUF. We 176232785Speter need to copy the new data over to make the input 176332785Speter contiguous. */ 176432785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 176532785Speter inbuf = pb->holdbuf + 2; 176632785Speter } 176732785Speter 176832785Speter if (count <= sizeof stackoutbuf) 176932785Speter outbuf = stackoutbuf; 177032785Speter else 177132785Speter { 1772109660Speter outbuf = xmalloc (count); 177332785Speter if (outbuf == NULL) 177432785Speter { 177532785Speter (*pb->buf->memory_error) (pb->buf); 177632785Speter return ENOMEM; 177732785Speter } 177832785Speter } 177932785Speter 178032785Speter status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count); 178132785Speter if (status != 0) 178232785Speter return status; 178332785Speter 178432785Speter /* The first two bytes in the translated buffer are the real 178532785Speter length of the translated data. */ 178632785Speter tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff); 178732785Speter 178832785Speter if (tcount > count) 178932785Speter error (1, 0, "Input translation failure"); 179032785Speter 179132785Speter if (tcount > size) 179232785Speter { 179332785Speter /* We have more data than the caller has provided space 179432785Speter for. We need to save some of it for the next call. */ 179532785Speter 179632785Speter memcpy (data, outbuf + 2, size); 179732785Speter *got += size; 179832785Speter 179932785Speter pb->holdsize = tcount - size; 180032785Speter memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size); 180132785Speter pb->holddata = pb->holdbuf; 180232785Speter pb->translated = 1; 180332785Speter 180432785Speter if (outbuf != stackoutbuf) 180532785Speter free (outbuf); 180632785Speter 180732785Speter return 0; 180832785Speter } 180932785Speter 181032785Speter memcpy (data, outbuf + 2, tcount); 181132785Speter 181232785Speter if (outbuf != stackoutbuf) 181332785Speter free (outbuf); 181432785Speter 181532785Speter pb->holdsize = 0; 181632785Speter 181732785Speter data += tcount; 181832785Speter need -= tcount; 181932785Speter size -= tcount; 182032785Speter *got += tcount; 182132785Speter } 182232785Speter 182332785Speter return 0; 182432785Speter} 182532785Speter 182632785Speter/* Output data to a packetizing buffer. */ 182732785Speter 182832785Speterstatic int 182932785Speterpacketizing_buffer_output (closure, data, have, wrote) 183032785Speter void *closure; 183132785Speter const char *data; 183232785Speter int have; 183332785Speter int *wrote; 183432785Speter{ 183532785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 183632785Speter char inbuf[BUFFER_DATA_SIZE + 2]; 183732785Speter char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4]; 183832785Speter struct buffer_data *outdata; 183932785Speter char *outbuf; 184032785Speter int size, status, translated; 184132785Speter 184232785Speter if (have > BUFFER_DATA_SIZE) 184332785Speter { 1844109660Speter /* It would be easy to xmalloc a buffer, but I don't think this 184532785Speter case can ever arise. */ 184632785Speter abort (); 184732785Speter } 184832785Speter 184932785Speter inbuf[0] = (have >> 8) & 0xff; 185032785Speter inbuf[1] = have & 0xff; 185132785Speter memcpy (inbuf + 2, data, have); 185232785Speter 185332785Speter size = have + 2; 185432785Speter 185532785Speter /* The output function is permitted to add up to PACKET_SLOP 185632785Speter bytes, and we need 2 bytes for the size of the translated data. 185732785Speter If we can guarantee that the result will fit in a buffer_data, 185832785Speter we translate directly into one to avoid a memcpy in buf_output. */ 185932785Speter if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE) 186032785Speter outbuf = stack_outbuf; 186132785Speter else 186232785Speter { 186332785Speter outdata = get_buffer_data (); 186432785Speter if (outdata == NULL) 186532785Speter { 186632785Speter (*pb->buf->memory_error) (pb->buf); 186732785Speter return ENOMEM; 186832785Speter } 186932785Speter 187032785Speter outdata->next = NULL; 187132785Speter outdata->bufp = outdata->text; 187232785Speter 187332785Speter outbuf = outdata->text; 187432785Speter } 187532785Speter 187632785Speter status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size, 187732785Speter &translated); 187832785Speter if (status != 0) 187932785Speter return status; 188032785Speter 188132785Speter /* The output function is permitted to add up to PACKET_SLOP 188232785Speter bytes. */ 188332785Speter if (translated > size + PACKET_SLOP) 188432785Speter abort (); 188532785Speter 188632785Speter outbuf[0] = (translated >> 8) & 0xff; 188732785Speter outbuf[1] = translated & 0xff; 188832785Speter 188932785Speter if (outbuf == stack_outbuf) 189032785Speter buf_output (pb->buf, outbuf, translated + 2); 189132785Speter else 189232785Speter { 189332785Speter outdata->size = translated + 2; 189432785Speter buf_append_data (pb->buf, outdata, outdata); 189532785Speter } 189632785Speter 189732785Speter *wrote = have; 189832785Speter 189932785Speter /* We will only be here because buf_send_output was called on the 190032785Speter packetizing buffer. That means that we should now call 190132785Speter buf_send_output on the underlying buffer. */ 190232785Speter return buf_send_output (pb->buf); 190332785Speter} 190432785Speter 1905128269Speter 1906128269Speter 190732785Speter/* Flush data to a packetizing buffer. */ 190832785Speterstatic int 190932785Speterpacketizing_buffer_flush (closure) 191032785Speter void *closure; 191132785Speter{ 191232785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 191332785Speter 191432785Speter /* Flush the underlying buffer. Note that if the original call to 191532785Speter buf_flush passed 1 for the BLOCK argument, then the buffer will 191632785Speter already have been set into blocking mode, so we should always 191732785Speter pass 0 here. */ 191832785Speter return buf_flush (pb->buf, 0); 191932785Speter} 192032785Speter 1921128269Speter 1922128269Speter 192332785Speter/* The block routine for a packetizing buffer. */ 192432785Speterstatic int 192532785Speterpacketizing_buffer_block (closure, block) 192632785Speter void *closure; 192732785Speter int block; 192832785Speter{ 192932785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 193032785Speter 193132785Speter if (block) 193232785Speter return set_block (pb->buf); 193332785Speter else 193432785Speter return set_nonblock (pb->buf); 193532785Speter} 193632785Speter 193732785Speter/* Shut down a packetizing buffer. */ 193832785Speter 193932785Speterstatic int 1940102840Speterpacketizing_buffer_shutdown (buf) 1941102840Speter struct buffer *buf; 194232785Speter{ 1943102840Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure; 194432785Speter 194532785Speter return buf_shutdown (pb->buf); 194632785Speter} 194732785Speter 194825839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */ 1949