buffer.c revision 102852
125839Speter/* Code for the buffer data structure. */ 225839Speter 3102852Speter/* $FreeBSD: head/contrib/cvs/src/buffer.c 102852 2002-09-02 07:58:04Z 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{ 6534461Speter if (buf->data != NULL) 6634461Speter { 6734461Speter buf->last->next = free_buffer_data; 6834461Speter free_buffer_data = buf->data; 6934461Speter } 7034461Speter free (buf); 7134461Speter} 7234461Speter 7325839Speter/* Initialize a buffer structure which is not to be used for I/O. */ 7425839Speter 7525839Speterstruct buffer * 7625839Speterbuf_nonio_initialize (memory) 7725839Speter void (*memory) PROTO((struct buffer *)); 7825839Speter{ 7925839Speter return (buf_initialize 8025839Speter ((int (*) PROTO((void *, char *, int, int, int *))) NULL, 8125839Speter (int (*) PROTO((void *, const char *, int, int *))) NULL, 8225839Speter (int (*) PROTO((void *))) NULL, 8325839Speter (int (*) PROTO((void *, int))) NULL, 84102840Speter (int (*) PROTO((struct buffer *))) NULL, 8525839Speter memory, 8625839Speter (void *) NULL)); 8725839Speter} 8825839Speter 8934461Speter/* Default memory error handler. */ 9034461Speter 9134461Speterstatic void 9234461Speterbuf_default_memory_error (buf) 9334461Speter struct buffer *buf; 9434461Speter{ 9534461Speter error (1, 0, "out of memory"); 9634461Speter} 9734461Speter 9825839Speter/* Allocate more buffer_data structures. */ 9925839Speter 10025839Speterstatic void 10125839Speterallocate_buffer_datas () 10225839Speter{ 10325839Speter struct buffer_data *alc; 10425839Speter char *space; 10525839Speter int i; 10625839Speter 10725839Speter /* Allocate buffer_data structures in blocks of 16. */ 10825839Speter#define ALLOC_COUNT (16) 10925839Speter 11025839Speter alc = ((struct buffer_data *) 11125839Speter malloc (ALLOC_COUNT * sizeof (struct buffer_data))); 11225839Speter space = (char *) valloc (ALLOC_COUNT * BUFFER_DATA_SIZE); 11325839Speter if (alc == NULL || space == NULL) 11425839Speter return; 11525839Speter for (i = 0; i < ALLOC_COUNT; i++, alc++, space += BUFFER_DATA_SIZE) 11625839Speter { 11725839Speter alc->next = free_buffer_data; 11825839Speter free_buffer_data = alc; 11925839Speter alc->text = space; 12025839Speter } 12125839Speter} 12225839Speter 12325839Speter/* Get a new buffer_data structure. */ 12425839Speter 12525839Speterstatic struct buffer_data * 12625839Speterget_buffer_data () 12725839Speter{ 12825839Speter struct buffer_data *ret; 12925839Speter 13025839Speter if (free_buffer_data == NULL) 13125839Speter { 13225839Speter allocate_buffer_datas (); 13325839Speter if (free_buffer_data == NULL) 13425839Speter return NULL; 13525839Speter } 13625839Speter 13725839Speter ret = free_buffer_data; 13825839Speter free_buffer_data = ret->next; 13925839Speter return ret; 14025839Speter} 14125839Speter 14225839Speter/* See whether a buffer is empty. */ 14325839Speter 14425839Speterint 14525839Speterbuf_empty_p (buf) 14625839Speter struct buffer *buf; 14725839Speter{ 14825839Speter struct buffer_data *data; 14925839Speter 15025839Speter for (data = buf->data; data != NULL; data = data->next) 15125839Speter if (data->size > 0) 15225839Speter return 0; 15325839Speter return 1; 15425839Speter} 15525839Speter 15625839Speter#ifdef SERVER_FLOWCONTROL 15725839Speter/* 15825839Speter * Count how much data is stored in the buffer.. 15925839Speter * Note that each buffer is a malloc'ed chunk BUFFER_DATA_SIZE. 16025839Speter */ 16125839Speter 16225839Speterint 16325839Speterbuf_count_mem (buf) 16425839Speter struct buffer *buf; 16525839Speter{ 16625839Speter struct buffer_data *data; 16725839Speter int mem = 0; 16825839Speter 16925839Speter for (data = buf->data; data != NULL; data = data->next) 17025839Speter mem += BUFFER_DATA_SIZE; 17125839Speter 17225839Speter return mem; 17325839Speter} 17425839Speter#endif /* SERVER_FLOWCONTROL */ 17525839Speter 17625839Speter/* Add data DATA of length LEN to BUF. */ 17725839Speter 17825839Spetervoid 17925839Speterbuf_output (buf, data, len) 18025839Speter struct buffer *buf; 18125839Speter const char *data; 18225839Speter int len; 18325839Speter{ 18425839Speter if (buf->data != NULL 18525839Speter && (((buf->last->text + BUFFER_DATA_SIZE) 18625839Speter - (buf->last->bufp + buf->last->size)) 18725839Speter >= len)) 18825839Speter { 18925839Speter memcpy (buf->last->bufp + buf->last->size, data, len); 19025839Speter buf->last->size += len; 19125839Speter return; 19225839Speter } 19325839Speter 19425839Speter while (1) 19525839Speter { 19625839Speter struct buffer_data *newdata; 19725839Speter 19825839Speter newdata = get_buffer_data (); 19925839Speter if (newdata == NULL) 20025839Speter { 20125839Speter (*buf->memory_error) (buf); 20225839Speter return; 20325839Speter } 20425839Speter 20525839Speter if (buf->data == NULL) 20625839Speter buf->data = newdata; 20725839Speter else 20825839Speter buf->last->next = newdata; 20925839Speter newdata->next = NULL; 21025839Speter buf->last = newdata; 21125839Speter 21225839Speter newdata->bufp = newdata->text; 21325839Speter 21425839Speter if (len <= BUFFER_DATA_SIZE) 21525839Speter { 21625839Speter newdata->size = len; 21725839Speter memcpy (newdata->text, data, len); 21825839Speter return; 21925839Speter } 22025839Speter 22125839Speter newdata->size = BUFFER_DATA_SIZE; 22225839Speter memcpy (newdata->text, data, BUFFER_DATA_SIZE); 22325839Speter 22425839Speter data += BUFFER_DATA_SIZE; 22525839Speter len -= BUFFER_DATA_SIZE; 22625839Speter } 22725839Speter 22825839Speter /*NOTREACHED*/ 22925839Speter} 23025839Speter 23125839Speter/* Add a '\0' terminated string to BUF. */ 23225839Speter 23325839Spetervoid 23425839Speterbuf_output0 (buf, string) 23525839Speter struct buffer *buf; 23625839Speter const char *string; 23725839Speter{ 23825839Speter buf_output (buf, string, strlen (string)); 23925839Speter} 24025839Speter 24125839Speter/* Add a single character to BUF. */ 24225839Speter 24325839Spetervoid 24425839Speterbuf_append_char (buf, ch) 24525839Speter struct buffer *buf; 24625839Speter int ch; 24725839Speter{ 24825839Speter if (buf->data != NULL 24925839Speter && (buf->last->text + BUFFER_DATA_SIZE 25025839Speter != buf->last->bufp + buf->last->size)) 25125839Speter { 25225839Speter *(buf->last->bufp + buf->last->size) = ch; 25325839Speter ++buf->last->size; 25425839Speter } 25525839Speter else 25625839Speter { 25725839Speter char b; 25825839Speter 25925839Speter b = ch; 26025839Speter buf_output (buf, &b, 1); 26125839Speter } 26225839Speter} 26325839Speter 26425839Speter/* 26525839Speter * Send all the output we've been saving up. Returns 0 for success or 26625839Speter * errno code. If the buffer has been set to be nonblocking, this 26725839Speter * will just write until the write would block. 26825839Speter */ 26925839Speter 27025839Speterint 27125839Speterbuf_send_output (buf) 27225839Speter struct buffer *buf; 27325839Speter{ 27425839Speter if (buf->output == NULL) 27525839Speter abort (); 27625839Speter 27725839Speter while (buf->data != NULL) 27825839Speter { 27925839Speter struct buffer_data *data; 28025839Speter 28125839Speter data = buf->data; 28225839Speter 28325839Speter if (data->size > 0) 28425839Speter { 28525839Speter int status, nbytes; 28625839Speter 28725839Speter status = (*buf->output) (buf->closure, data->bufp, data->size, 28825839Speter &nbytes); 28925839Speter if (status != 0) 29025839Speter { 29125839Speter /* Some sort of error. Discard the data, and return. */ 29225839Speter 29325839Speter buf->last->next = free_buffer_data; 29425839Speter free_buffer_data = buf->data; 29525839Speter buf->data = NULL; 29625839Speter buf->last = NULL; 29725839Speter 29825839Speter return status; 29925839Speter } 30025839Speter 30125839Speter if (nbytes != data->size) 30225839Speter { 30325839Speter /* Not all the data was written out. This is only 30425839Speter permitted in nonblocking mode. Adjust the buffer, 30525839Speter and return. */ 30625839Speter 30725839Speter assert (buf->nonblocking); 30825839Speter 30925839Speter data->size -= nbytes; 31025839Speter data->bufp += nbytes; 31125839Speter 31225839Speter return 0; 31325839Speter } 31425839Speter } 31525839Speter 31625839Speter buf->data = data->next; 31725839Speter data->next = free_buffer_data; 31825839Speter free_buffer_data = data; 31925839Speter } 32025839Speter 32125839Speter buf->last = NULL; 32225839Speter 32325839Speter return 0; 32425839Speter} 32525839Speter 32625839Speter/* 32725839Speter * Flush any data queued up in the buffer. If BLOCK is nonzero, then 32825839Speter * if the buffer is in nonblocking mode, put it into blocking mode for 32925839Speter * the duration of the flush. This returns 0 on success, or an error 33025839Speter * code. 33125839Speter */ 33225839Speter 33325839Speterint 33425839Speterbuf_flush (buf, block) 33525839Speter struct buffer *buf; 33625839Speter int block; 33725839Speter{ 33825839Speter int nonblocking; 33925839Speter int status; 34025839Speter 34125839Speter if (buf->flush == NULL) 34225839Speter abort (); 34325839Speter 34425839Speter nonblocking = buf->nonblocking; 34525839Speter if (nonblocking && block) 34625839Speter { 34725839Speter status = set_block (buf); 34825839Speter if (status != 0) 34925839Speter return status; 35025839Speter } 35125839Speter 35225839Speter status = buf_send_output (buf); 35325839Speter if (status == 0) 35425839Speter status = (*buf->flush) (buf->closure); 35525839Speter 35625839Speter if (nonblocking && block) 35725839Speter { 35825839Speter int blockstat; 35925839Speter 36025839Speter blockstat = set_nonblock (buf); 36125839Speter if (status == 0) 36225839Speter status = blockstat; 36325839Speter } 36425839Speter 36525839Speter return status; 36625839Speter} 36725839Speter 36825839Speter/* 36925839Speter * Set buffer BUF to nonblocking I/O. Returns 0 for success or errno 37025839Speter * code. 37125839Speter */ 37225839Speter 37325839Speterint 37425839Speterset_nonblock (buf) 37525839Speter struct buffer *buf; 37625839Speter{ 37725839Speter int status; 37825839Speter 37925839Speter if (buf->nonblocking) 38025839Speter return 0; 38125839Speter if (buf->block == NULL) 38225839Speter abort (); 38325839Speter status = (*buf->block) (buf->closure, 0); 38425839Speter if (status != 0) 38525839Speter return status; 38625839Speter buf->nonblocking = 1; 38725839Speter return 0; 38825839Speter} 38925839Speter 39025839Speter/* 39125839Speter * Set buffer BUF to blocking I/O. Returns 0 for success or errno 39225839Speter * code. 39325839Speter */ 39425839Speter 39525839Speterint 39625839Speterset_block (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, 1); 40625839Speter if (status != 0) 40725839Speter return status; 40825839Speter buf->nonblocking = 0; 40925839Speter return 0; 41025839Speter} 41125839Speter 41225839Speter/* 41325839Speter * Send a character count and some output. Returns errno code or 0 for 41425839Speter * success. 41525839Speter * 41625839Speter * Sending the count in binary is OK since this is only used on a pipe 41725839Speter * within the same system. 41825839Speter */ 41925839Speter 42025839Speterint 42125839Speterbuf_send_counted (buf) 42225839Speter struct buffer *buf; 42325839Speter{ 42425839Speter int size; 42525839Speter struct buffer_data *data; 42625839Speter 42725839Speter size = 0; 42825839Speter for (data = buf->data; data != NULL; data = data->next) 42925839Speter size += data->size; 43025839Speter 43125839Speter data = get_buffer_data (); 43225839Speter if (data == NULL) 43325839Speter { 43425839Speter (*buf->memory_error) (buf); 43525839Speter return ENOMEM; 43625839Speter } 43725839Speter 43825839Speter data->next = buf->data; 43925839Speter buf->data = data; 44025839Speter if (buf->last == NULL) 44125839Speter buf->last = data; 44225839Speter 44325839Speter data->bufp = data->text; 44425839Speter data->size = sizeof (int); 44525839Speter 44625839Speter *((int *) data->text) = size; 44725839Speter 44825839Speter return buf_send_output (buf); 44925839Speter} 45025839Speter 45125839Speter/* 45225839Speter * Send a special count. COUNT should be negative. It will be 45325839Speter * handled speciallyi by buf_copy_counted. This function returns 0 or 45425839Speter * an errno code. 45525839Speter * 45625839Speter * Sending the count in binary is OK since this is only used on a pipe 45725839Speter * within the same system. 45825839Speter */ 45925839Speter 46025839Speterint 46125839Speterbuf_send_special_count (buf, count) 46225839Speter struct buffer *buf; 46325839Speter int count; 46425839Speter{ 46525839Speter struct buffer_data *data; 46625839Speter 46725839Speter data = get_buffer_data (); 46825839Speter if (data == NULL) 46925839Speter { 47025839Speter (*buf->memory_error) (buf); 47125839Speter return ENOMEM; 47225839Speter } 47325839Speter 47425839Speter data->next = buf->data; 47525839Speter buf->data = data; 47625839Speter if (buf->last == NULL) 47725839Speter buf->last = data; 47825839Speter 47925839Speter data->bufp = data->text; 48025839Speter data->size = sizeof (int); 48125839Speter 48225839Speter *((int *) data->text) = count; 48325839Speter 48425839Speter return buf_send_output (buf); 48525839Speter} 48625839Speter 48725839Speter/* Append a list of buffer_data structures to an buffer. */ 48825839Speter 48925839Spetervoid 49025839Speterbuf_append_data (buf, data, last) 49125839Speter struct buffer *buf; 49225839Speter struct buffer_data *data; 49325839Speter struct buffer_data *last; 49425839Speter{ 49525839Speter if (data != NULL) 49625839Speter { 49725839Speter if (buf->data == NULL) 49825839Speter buf->data = data; 49925839Speter else 50025839Speter buf->last->next = data; 50125839Speter buf->last = last; 50225839Speter } 50325839Speter} 50425839Speter 50534461Speter/* Append the data on one buffer to another. This removes the data 50634461Speter from the source buffer. */ 50734461Speter 50834461Spetervoid 50934461Speterbuf_append_buffer (to, from) 51034461Speter struct buffer *to; 51134461Speter struct buffer *from; 51234461Speter{ 51334461Speter buf_append_data (to, from->data, from->last); 51434461Speter from->data = NULL; 51534461Speter from->last = NULL; 51634461Speter} 51734461Speter 51825839Speter/* 51925839Speter * Copy the contents of file F into buffer_data structures. We can't 52025839Speter * copy directly into an buffer, because we want to handle failure and 52125839Speter * succeess differently. Returns 0 on success, or -2 if out of 52225839Speter * memory, or a status code on error. Since the caller happens to 52325839Speter * know the size of the file, it is passed in as SIZE. On success, 52425839Speter * this function sets *RETP and *LASTP, which may be passed to 52525839Speter * buf_append_data. 52625839Speter */ 52725839Speter 52825839Speterint 52925839Speterbuf_read_file (f, size, retp, lastp) 53025839Speter FILE *f; 53125839Speter long size; 53225839Speter struct buffer_data **retp; 53325839Speter struct buffer_data **lastp; 53425839Speter{ 53525839Speter int status; 53625839Speter 53725839Speter *retp = NULL; 53825839Speter *lastp = NULL; 53925839Speter 54025839Speter while (size > 0) 54125839Speter { 54225839Speter struct buffer_data *data; 54325839Speter int get; 54425839Speter 54525839Speter data = get_buffer_data (); 54625839Speter if (data == NULL) 54725839Speter { 54825839Speter status = -2; 54925839Speter goto error_return; 55025839Speter } 55125839Speter 55225839Speter if (*retp == NULL) 55325839Speter *retp = data; 55425839Speter else 55525839Speter (*lastp)->next = data; 55625839Speter data->next = NULL; 55725839Speter *lastp = data; 55825839Speter 55925839Speter data->bufp = data->text; 56025839Speter data->size = 0; 56125839Speter 56225839Speter if (size > BUFFER_DATA_SIZE) 56325839Speter get = BUFFER_DATA_SIZE; 56425839Speter else 56525839Speter get = size; 56625839Speter 56725839Speter errno = EIO; 56825839Speter if (fread (data->text, get, 1, f) != 1) 56925839Speter { 57025839Speter status = errno; 57125839Speter goto error_return; 57225839Speter } 57325839Speter 57425839Speter data->size += get; 57525839Speter size -= get; 57625839Speter } 57725839Speter 57825839Speter return 0; 57925839Speter 58025839Speter error_return: 58125839Speter if (*retp != NULL) 58225839Speter { 58325839Speter (*lastp)->next = free_buffer_data; 58425839Speter free_buffer_data = *retp; 58525839Speter } 58625839Speter return status; 58725839Speter} 58825839Speter 58925839Speter/* 59025839Speter * Copy the contents of file F into buffer_data structures. We can't 59125839Speter * copy directly into an buffer, because we want to handle failure and 59225839Speter * succeess differently. Returns 0 on success, or -2 if out of 59325839Speter * memory, or a status code on error. On success, this function sets 59425839Speter * *RETP and *LASTP, which may be passed to buf_append_data. 59525839Speter */ 59625839Speter 59725839Speterint 59825839Speterbuf_read_file_to_eof (f, retp, lastp) 59925839Speter FILE *f; 60025839Speter struct buffer_data **retp; 60125839Speter struct buffer_data **lastp; 60225839Speter{ 60325839Speter int status; 60425839Speter 60525839Speter *retp = NULL; 60625839Speter *lastp = NULL; 60725839Speter 60825839Speter while (!feof (f)) 60925839Speter { 61025839Speter struct buffer_data *data; 61125839Speter int get, nread; 61225839Speter 61325839Speter data = get_buffer_data (); 61425839Speter if (data == NULL) 61525839Speter { 61625839Speter status = -2; 61725839Speter goto error_return; 61825839Speter } 61925839Speter 62025839Speter if (*retp == NULL) 62125839Speter *retp = data; 62225839Speter else 62325839Speter (*lastp)->next = data; 62425839Speter data->next = NULL; 62525839Speter *lastp = data; 62625839Speter 62725839Speter data->bufp = data->text; 62825839Speter data->size = 0; 62925839Speter 63025839Speter get = BUFFER_DATA_SIZE; 63125839Speter 63225839Speter errno = EIO; 63325839Speter nread = fread (data->text, 1, get, f); 63425839Speter if (nread == 0 && !feof (f)) 63525839Speter { 63625839Speter status = errno; 63725839Speter goto error_return; 63825839Speter } 63925839Speter 64025839Speter data->size = nread; 64125839Speter } 64225839Speter 64325839Speter return 0; 64425839Speter 64525839Speter error_return: 64625839Speter if (*retp != NULL) 64725839Speter { 64825839Speter (*lastp)->next = free_buffer_data; 64925839Speter free_buffer_data = *retp; 65025839Speter } 65125839Speter return status; 65225839Speter} 65325839Speter 65425839Speter/* Return the number of bytes in a chain of buffer_data structures. */ 65525839Speter 65625839Speterint 65725839Speterbuf_chain_length (buf) 65825839Speter struct buffer_data *buf; 65925839Speter{ 66025839Speter int size = 0; 66125839Speter while (buf) 66225839Speter { 66325839Speter size += buf->size; 66425839Speter buf = buf->next; 66525839Speter } 66625839Speter return size; 66725839Speter} 66825839Speter 66934461Speter/* Return the number of bytes in a buffer. */ 67034461Speter 67134461Speterint 67234461Speterbuf_length (buf) 67334461Speter struct buffer *buf; 67434461Speter{ 67534461Speter return buf_chain_length (buf->data); 67634461Speter} 67734461Speter 67825839Speter/* 67925839Speter * Read an arbitrary amount of data into an input buffer. The buffer 68025839Speter * will be in nonblocking mode, and we just grab what we can. Return 68125839Speter * 0 on success, or -1 on end of file, or -2 if out of memory, or an 68225839Speter * error code. If COUNTP is not NULL, *COUNTP is set to the number of 68325839Speter * bytes read. 68425839Speter */ 68525839Speter 68625839Speterint 68725839Speterbuf_input_data (buf, countp) 68825839Speter struct buffer *buf; 68925839Speter int *countp; 69025839Speter{ 69125839Speter if (buf->input == NULL) 69225839Speter abort (); 69325839Speter 69425839Speter if (countp != NULL) 69525839Speter *countp = 0; 69625839Speter 69725839Speter while (1) 69825839Speter { 69925839Speter int get; 70025839Speter int status, nbytes; 70125839Speter 70225839Speter if (buf->data == NULL 70325839Speter || (buf->last->bufp + buf->last->size 70425839Speter == buf->last->text + BUFFER_DATA_SIZE)) 70525839Speter { 70625839Speter struct buffer_data *data; 70725839Speter 70825839Speter data = get_buffer_data (); 70925839Speter if (data == NULL) 71025839Speter { 71125839Speter (*buf->memory_error) (buf); 71225839Speter return -2; 71325839Speter } 71425839Speter 71525839Speter if (buf->data == NULL) 71625839Speter buf->data = data; 71725839Speter else 71825839Speter buf->last->next = data; 71925839Speter data->next = NULL; 72025839Speter buf->last = data; 72125839Speter 72225839Speter data->bufp = data->text; 72325839Speter data->size = 0; 72425839Speter } 72525839Speter 72625839Speter get = ((buf->last->text + BUFFER_DATA_SIZE) 72725839Speter - (buf->last->bufp + buf->last->size)); 72825839Speter 72925839Speter status = (*buf->input) (buf->closure, 73025839Speter buf->last->bufp + buf->last->size, 73125839Speter 0, get, &nbytes); 73225839Speter if (status != 0) 73325839Speter return status; 73425839Speter 73525839Speter buf->last->size += nbytes; 73625839Speter if (countp != NULL) 73725839Speter *countp += nbytes; 73825839Speter 73925839Speter if (nbytes < get) 74025839Speter { 74125839Speter /* If we did not fill the buffer, then presumably we read 74225839Speter all the available data. */ 74325839Speter return 0; 74425839Speter } 74525839Speter } 74625839Speter 74725839Speter /*NOTREACHED*/ 74825839Speter} 74925839Speter 75025839Speter/* 75125839Speter * Read a line (characters up to a \012) from an input buffer. (We 75225839Speter * use \012 rather than \n for the benefit of non Unix clients for 75325839Speter * which \n means something else). This returns 0 on success, or -1 75425839Speter * on end of file, or -2 if out of memory, or an error code. If it 75525839Speter * succeeds, it sets *LINE to an allocated buffer holding the contents 75625839Speter * of the line. The trailing \012 is not included in the buffer. If 75725839Speter * LENP is not NULL, then *LENP is set to the number of bytes read; 75825839Speter * strlen may not work, because there may be embedded null bytes. 75925839Speter */ 76025839Speter 76125839Speterint 76225839Speterbuf_read_line (buf, line, lenp) 76325839Speter struct buffer *buf; 76425839Speter char **line; 76525839Speter int *lenp; 76625839Speter{ 76725839Speter if (buf->input == NULL) 76825839Speter abort (); 76925839Speter 77025839Speter *line = NULL; 77125839Speter 77225839Speter while (1) 77325839Speter { 77425839Speter int len, finallen = 0; 77525839Speter struct buffer_data *data; 77625839Speter char *nl; 77725839Speter 77825839Speter /* See if there is a newline in BUF. */ 77925839Speter len = 0; 78025839Speter for (data = buf->data; data != NULL; data = data->next) 78125839Speter { 78225839Speter nl = memchr (data->bufp, '\012', data->size); 78325839Speter if (nl != NULL) 78425839Speter { 78525839Speter finallen = nl - data->bufp; 78625839Speter len += finallen; 78725839Speter break; 78825839Speter } 78925839Speter len += data->size; 79025839Speter } 79125839Speter 79225839Speter /* If we found a newline, copy the line into a memory buffer, 79325839Speter and remove it from BUF. */ 79425839Speter if (data != NULL) 79525839Speter { 79625839Speter char *p; 79725839Speter struct buffer_data *nldata; 79825839Speter 79925839Speter p = malloc (len + 1); 80025839Speter if (p == NULL) 80125839Speter return -2; 80225839Speter *line = p; 80325839Speter 80425839Speter nldata = data; 80525839Speter data = buf->data; 80625839Speter while (data != nldata) 80725839Speter { 80825839Speter struct buffer_data *next; 80925839Speter 81025839Speter memcpy (p, data->bufp, data->size); 81125839Speter p += data->size; 81225839Speter next = data->next; 81325839Speter data->next = free_buffer_data; 81425839Speter free_buffer_data = data; 81525839Speter data = next; 81625839Speter } 81725839Speter 81825839Speter memcpy (p, data->bufp, finallen); 81925839Speter p[finallen] = '\0'; 82025839Speter 82125839Speter data->size -= finallen + 1; 82225839Speter data->bufp = nl + 1; 82325839Speter buf->data = data; 82425839Speter 82525839Speter if (lenp != NULL) 82625839Speter *lenp = len; 82725839Speter 82825839Speter return 0; 82925839Speter } 83025839Speter 83125839Speter /* Read more data until we get a newline. */ 83225839Speter while (1) 83325839Speter { 83425839Speter int size, status, nbytes; 83525839Speter char *mem; 83625839Speter 83725839Speter if (buf->data == NULL 83825839Speter || (buf->last->bufp + buf->last->size 83925839Speter == buf->last->text + BUFFER_DATA_SIZE)) 84025839Speter { 84125839Speter data = get_buffer_data (); 84225839Speter if (data == NULL) 84325839Speter { 84425839Speter (*buf->memory_error) (buf); 84525839Speter return -2; 84625839Speter } 84725839Speter 84825839Speter if (buf->data == NULL) 84925839Speter buf->data = data; 85025839Speter else 85125839Speter buf->last->next = data; 85225839Speter data->next = NULL; 85325839Speter buf->last = data; 85425839Speter 85525839Speter data->bufp = data->text; 85625839Speter data->size = 0; 85725839Speter } 85825839Speter 85925839Speter mem = buf->last->bufp + buf->last->size; 86025839Speter size = (buf->last->text + BUFFER_DATA_SIZE) - mem; 86125839Speter 86225839Speter /* We need to read at least 1 byte. We can handle up to 86325839Speter SIZE bytes. This will only be efficient if the 86425839Speter underlying communication stream does its own buffering, 86525839Speter or is clever about getting more than 1 byte at a time. */ 86625839Speter status = (*buf->input) (buf->closure, mem, 1, size, &nbytes); 86725839Speter if (status != 0) 86825839Speter return status; 86925839Speter 87025839Speter buf->last->size += nbytes; 87125839Speter 87225839Speter /* Optimize slightly to avoid an unnecessary call to 87325839Speter memchr. */ 87425839Speter if (nbytes == 1) 87525839Speter { 87625839Speter if (*mem == '\012') 87725839Speter break; 87825839Speter } 87925839Speter else 88025839Speter { 88125839Speter if (memchr (mem, '\012', nbytes) != NULL) 88225839Speter break; 88325839Speter } 88425839Speter } 88525839Speter } 88625839Speter} 88725839Speter 88825839Speter/* 88925839Speter * Extract data from the input buffer BUF. This will read up to WANT 89025839Speter * bytes from the buffer. It will set *RETDATA to point at the bytes, 89125839Speter * and set *GOT to the number of bytes to be found there. Any buffer 89225839Speter * call which uses BUF may change the contents of the buffer at *DATA, 89325839Speter * so the data should be fully processed before any further calls are 89425839Speter * made. This returns 0 on success, or -1 on end of file, or -2 if 89525839Speter * out of memory, or an error code. 89625839Speter */ 89725839Speter 89825839Speterint 89925839Speterbuf_read_data (buf, want, retdata, got) 90025839Speter struct buffer *buf; 90125839Speter int want; 90225839Speter char **retdata; 90325839Speter int *got; 90425839Speter{ 90525839Speter if (buf->input == NULL) 90625839Speter abort (); 90725839Speter 90825839Speter while (buf->data != NULL && buf->data->size == 0) 90925839Speter { 91025839Speter struct buffer_data *next; 91125839Speter 91225839Speter next = buf->data->next; 91325839Speter buf->data->next = free_buffer_data; 91425839Speter free_buffer_data = buf->data; 91525839Speter buf->data = next; 91625839Speter if (next == NULL) 91725839Speter buf->last = NULL; 91825839Speter } 91925839Speter 92025839Speter if (buf->data == NULL) 92125839Speter { 92225839Speter struct buffer_data *data; 92325839Speter int get, status, nbytes; 92425839Speter 92525839Speter data = get_buffer_data (); 92625839Speter if (data == NULL) 92725839Speter { 92825839Speter (*buf->memory_error) (buf); 92925839Speter return -2; 93025839Speter } 93125839Speter 93225839Speter buf->data = data; 93325839Speter buf->last = data; 93425839Speter data->next = NULL; 93525839Speter data->bufp = data->text; 93625839Speter data->size = 0; 93725839Speter 93825839Speter if (want < BUFFER_DATA_SIZE) 93925839Speter get = want; 94025839Speter else 94125839Speter get = BUFFER_DATA_SIZE; 94225839Speter status = (*buf->input) (buf->closure, data->bufp, get, 94325839Speter BUFFER_DATA_SIZE, &nbytes); 94425839Speter if (status != 0) 94525839Speter return status; 94625839Speter 94725839Speter data->size = nbytes; 94825839Speter } 94925839Speter 95025839Speter *retdata = buf->data->bufp; 95125839Speter if (want < buf->data->size) 95225839Speter { 95325839Speter *got = want; 95425839Speter buf->data->size -= want; 95525839Speter buf->data->bufp += want; 95625839Speter } 95725839Speter else 95825839Speter { 95925839Speter *got = buf->data->size; 96025839Speter buf->data->size = 0; 96125839Speter } 96225839Speter 96325839Speter return 0; 96425839Speter} 96525839Speter 96625839Speter/* 96725839Speter * Copy lines from an input buffer to an output buffer. This copies 96825839Speter * all complete lines (characters up to a newline) from INBUF to 96925839Speter * OUTBUF. Each line in OUTBUF is preceded by the character COMMAND 97025839Speter * and a space. 97125839Speter */ 97225839Speter 97325839Spetervoid 97425839Speterbuf_copy_lines (outbuf, inbuf, command) 97525839Speter struct buffer *outbuf; 97625839Speter struct buffer *inbuf; 97725839Speter int command; 97825839Speter{ 97925839Speter while (1) 98025839Speter { 98125839Speter struct buffer_data *data; 98225839Speter struct buffer_data *nldata; 98325839Speter char *nl; 98425839Speter int len; 98525839Speter 98625839Speter /* See if there is a newline in INBUF. */ 98725839Speter nldata = NULL; 98825839Speter nl = NULL; 98925839Speter for (data = inbuf->data; data != NULL; data = data->next) 99025839Speter { 99125839Speter nl = memchr (data->bufp, '\n', data->size); 99225839Speter if (nl != NULL) 99325839Speter { 99425839Speter nldata = data; 99525839Speter break; 99625839Speter } 99725839Speter } 99825839Speter 99925839Speter if (nldata == NULL) 100025839Speter { 100125839Speter /* There are no more lines in INBUF. */ 100225839Speter return; 100325839Speter } 100425839Speter 100525839Speter /* Put in the command. */ 100625839Speter buf_append_char (outbuf, command); 100725839Speter buf_append_char (outbuf, ' '); 100825839Speter 100925839Speter if (inbuf->data != nldata) 101025839Speter { 101125839Speter /* 101225839Speter * Simply move over all the buffers up to the one containing 101325839Speter * the newline. 101425839Speter */ 101525839Speter for (data = inbuf->data; data->next != nldata; data = data->next) 101625839Speter ; 101725839Speter data->next = NULL; 101825839Speter buf_append_data (outbuf, inbuf->data, data); 101925839Speter inbuf->data = nldata; 102025839Speter } 102125839Speter 102225839Speter /* 102325839Speter * If the newline is at the very end of the buffer, just move 102425839Speter * the buffer onto OUTBUF. Otherwise we must copy the data. 102525839Speter */ 102625839Speter len = nl + 1 - nldata->bufp; 102725839Speter if (len == nldata->size) 102825839Speter { 102925839Speter inbuf->data = nldata->next; 103025839Speter if (inbuf->data == NULL) 103125839Speter inbuf->last = NULL; 103225839Speter 103325839Speter nldata->next = NULL; 103425839Speter buf_append_data (outbuf, nldata, nldata); 103525839Speter } 103625839Speter else 103725839Speter { 103825839Speter buf_output (outbuf, nldata->bufp, len); 103925839Speter nldata->bufp += len; 104025839Speter nldata->size -= len; 104125839Speter } 104225839Speter } 104325839Speter} 104425839Speter 104525839Speter/* 104625839Speter * Copy counted data from one buffer to another. The count is an 104725839Speter * integer, host size, host byte order (it is only used across a 104825839Speter * pipe). If there is enough data, it should be moved over. If there 104925839Speter * is not enough data, it should remain on the original buffer. A 105025839Speter * negative count is a special case. if one is seen, *SPECIAL is set 105125839Speter * to the (negative) count value and no additional data is gathered 105225839Speter * from the buffer; normally *SPECIAL is set to 0. This function 105325839Speter * returns the number of bytes it needs to see in order to actually 105425839Speter * copy something over. 105525839Speter */ 105625839Speter 105725839Speterint 105825839Speterbuf_copy_counted (outbuf, inbuf, special) 105925839Speter struct buffer *outbuf; 106025839Speter struct buffer *inbuf; 106125839Speter int *special; 106225839Speter{ 106325839Speter *special = 0; 106425839Speter 106525839Speter while (1) 106625839Speter { 106725839Speter struct buffer_data *data; 106825839Speter int need; 106925839Speter union 107025839Speter { 107125839Speter char intbuf[sizeof (int)]; 107225839Speter int i; 107325839Speter } u; 107425839Speter char *intp; 107525839Speter int count; 107625839Speter struct buffer_data *start; 107725839Speter int startoff; 107825839Speter struct buffer_data *stop; 107925839Speter int stopwant; 108025839Speter 108125839Speter /* See if we have enough bytes to figure out the count. */ 108225839Speter need = sizeof (int); 108325839Speter intp = u.intbuf; 108425839Speter for (data = inbuf->data; data != NULL; data = data->next) 108525839Speter { 108625839Speter if (data->size >= need) 108725839Speter { 108825839Speter memcpy (intp, data->bufp, need); 108925839Speter break; 109025839Speter } 109125839Speter memcpy (intp, data->bufp, data->size); 109225839Speter intp += data->size; 109325839Speter need -= data->size; 109425839Speter } 109525839Speter if (data == NULL) 109625839Speter { 109725839Speter /* We don't have enough bytes to form an integer. */ 109825839Speter return need; 109925839Speter } 110025839Speter 110125839Speter count = u.i; 110225839Speter start = data; 110325839Speter startoff = need; 110425839Speter 110525839Speter if (count < 0) 110625839Speter { 110725839Speter /* A negative COUNT is a special case meaning that we 110825839Speter don't need any further information. */ 110925839Speter stop = start; 111025839Speter stopwant = 0; 111125839Speter } 111225839Speter else 111325839Speter { 111425839Speter /* 111525839Speter * We have an integer in COUNT. We have gotten all the 111625839Speter * data from INBUF in all buffers before START, and we 111725839Speter * have gotten STARTOFF bytes from START. See if we have 111825839Speter * enough bytes remaining in INBUF. 111925839Speter */ 112025839Speter need = count - (start->size - startoff); 112125839Speter if (need <= 0) 112225839Speter { 112325839Speter stop = start; 112425839Speter stopwant = count; 112525839Speter } 112625839Speter else 112725839Speter { 112825839Speter for (data = start->next; data != NULL; data = data->next) 112925839Speter { 113025839Speter if (need <= data->size) 113125839Speter break; 113225839Speter need -= data->size; 113325839Speter } 113425839Speter if (data == NULL) 113525839Speter { 113625839Speter /* We don't have enough bytes. */ 113725839Speter return need; 113825839Speter } 113925839Speter stop = data; 114025839Speter stopwant = need; 114125839Speter } 114225839Speter } 114325839Speter 114425839Speter /* 114525839Speter * We have enough bytes. Free any buffers in INBUF before 114625839Speter * START, and remove STARTOFF bytes from START, so that we can 114725839Speter * forget about STARTOFF. 114825839Speter */ 114925839Speter start->bufp += startoff; 115025839Speter start->size -= startoff; 115125839Speter 115225839Speter if (start->size == 0) 115325839Speter start = start->next; 115425839Speter 115525839Speter if (stop->size == stopwant) 115625839Speter { 115725839Speter stop = stop->next; 115825839Speter stopwant = 0; 115925839Speter } 116025839Speter 116125839Speter while (inbuf->data != start) 116225839Speter { 116325839Speter data = inbuf->data; 116425839Speter inbuf->data = data->next; 116525839Speter data->next = free_buffer_data; 116625839Speter free_buffer_data = data; 116725839Speter } 116825839Speter 116925839Speter /* If COUNT is negative, set *SPECIAL and get out now. */ 117025839Speter if (count < 0) 117125839Speter { 117225839Speter *special = count; 117325839Speter return 0; 117425839Speter } 117525839Speter 117625839Speter /* 117725839Speter * We want to copy over the bytes from START through STOP. We 117825839Speter * only want STOPWANT bytes from STOP. 117925839Speter */ 118025839Speter 118125839Speter if (start != stop) 118225839Speter { 118325839Speter /* Attach the buffers from START through STOP to OUTBUF. */ 118425839Speter for (data = start; data->next != stop; data = data->next) 118525839Speter ; 118625839Speter inbuf->data = stop; 118725839Speter data->next = NULL; 118825839Speter buf_append_data (outbuf, start, data); 118925839Speter } 119025839Speter 119125839Speter if (stopwant > 0) 119225839Speter { 119325839Speter buf_output (outbuf, stop->bufp, stopwant); 119425839Speter stop->bufp += stopwant; 119525839Speter stop->size -= stopwant; 119625839Speter } 119725839Speter } 119825839Speter 119925839Speter /*NOTREACHED*/ 120025839Speter} 120125839Speter 120225839Speter/* Shut down a buffer. This returns 0 on success, or an errno code. */ 120325839Speter 120425839Speterint 120525839Speterbuf_shutdown (buf) 120625839Speter struct buffer *buf; 120725839Speter{ 120825839Speter if (buf->shutdown) 1209102840Speter return (*buf->shutdown) (buf); 121025839Speter return 0; 121125839Speter} 121225839Speter 121325839Speter/* The simplest type of buffer is one built on top of a stdio FILE. 121425839Speter For simplicity, and because it is all that is required, we do not 121525839Speter implement setting this type of buffer into nonblocking mode. The 121625839Speter closure field is just a FILE *. */ 121725839Speter 121825839Speterstatic int stdio_buffer_input PROTO((void *, char *, int, int, int *)); 121925839Speterstatic int stdio_buffer_output PROTO((void *, const char *, int, int *)); 122025839Speterstatic int stdio_buffer_flush PROTO((void *)); 1221102840Speterstatic int stdio_buffer_shutdown PROTO((struct buffer *buf)); 122225839Speter 122325839Speter/* Initialize a buffer built on a stdio FILE. */ 122425839Speter 1225102840Speterstruct stdio_buffer_closure 1226102840Speter{ 1227102840Speter FILE *fp; 1228102840Speter int child_pid; 1229102840Speter}; 1230102840Speter 123132785Speterstruct buffer * 1232102840Speterstdio_buffer_initialize (fp, child_pid, input, memory) 123325839Speter FILE *fp; 1234102840Speter int child_pid; 123525839Speter int input; 123625839Speter void (*memory) PROTO((struct buffer *)); 123725839Speter{ 1238102840Speter struct stdio_buffer_closure *bc = malloc (sizeof (*bc)); 1239102840Speter 1240102840Speter bc->fp = fp; 1241102840Speter bc->child_pid = child_pid; 1242102840Speter 124325839Speter return buf_initialize (input ? stdio_buffer_input : NULL, 124425839Speter input ? NULL : stdio_buffer_output, 124525839Speter input ? NULL : stdio_buffer_flush, 124625839Speter (int (*) PROTO((void *, int))) NULL, 1247102840Speter stdio_buffer_shutdown, 124825839Speter memory, 1249102840Speter (void *) bc); 125025839Speter} 125125839Speter 125225839Speter/* The buffer input function for a buffer built on a stdio FILE. */ 125325839Speter 125425839Speterstatic int 125525839Speterstdio_buffer_input (closure, data, need, size, got) 125625839Speter void *closure; 125725839Speter char *data; 125825839Speter int need; 125925839Speter int size; 126025839Speter int *got; 126125839Speter{ 1262102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 126325839Speter int nbytes; 126425839Speter 126525839Speter /* Since stdio does its own buffering, we don't worry about 126625839Speter getting more bytes than we need. */ 126725839Speter 126825839Speter if (need == 0 || need == 1) 126925839Speter { 127025839Speter int ch; 127125839Speter 1272102840Speter ch = getc (bc->fp); 127325839Speter 127425839Speter if (ch == EOF) 127525839Speter { 1276102840Speter if (feof (bc->fp)) 127725839Speter return -1; 127825839Speter else if (errno == 0) 127925839Speter return EIO; 128025839Speter else 128125839Speter return errno; 128225839Speter } 128325839Speter 128425839Speter *data = ch; 128525839Speter *got = 1; 128625839Speter return 0; 128725839Speter } 128825839Speter 1289102840Speter nbytes = fread (data, 1, need, bc->fp); 129025839Speter 129125839Speter if (nbytes == 0) 129225839Speter { 129325839Speter *got = 0; 1294102840Speter if (feof (bc->fp)) 129525839Speter return -1; 129625839Speter else if (errno == 0) 129725839Speter return EIO; 129825839Speter else 129925839Speter return errno; 130025839Speter } 130125839Speter 130225839Speter *got = nbytes; 130325839Speter 130425839Speter return 0; 130525839Speter} 130625839Speter 130725839Speter/* The buffer output function for a buffer built on a stdio FILE. */ 130825839Speter 130925839Speterstatic int 131025839Speterstdio_buffer_output (closure, data, have, wrote) 131125839Speter void *closure; 131225839Speter const char *data; 131325839Speter int have; 131425839Speter int *wrote; 131525839Speter{ 1316102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 131725839Speter 131825839Speter *wrote = 0; 131925839Speter 132025839Speter while (have > 0) 132125839Speter { 132225839Speter int nbytes; 132325839Speter 1324102840Speter nbytes = fwrite (data, 1, have, bc->fp); 132525839Speter 132625839Speter if (nbytes != have) 132725839Speter { 132825839Speter if (errno == 0) 132925839Speter return EIO; 133025839Speter else 133125839Speter return errno; 133225839Speter } 133325839Speter 133425839Speter *wrote += nbytes; 133525839Speter have -= nbytes; 133625839Speter data += nbytes; 133725839Speter } 133825839Speter 133925839Speter return 0; 134025839Speter} 134125839Speter 134225839Speter/* The buffer flush function for a buffer built on a stdio FILE. */ 134325839Speter 134425839Speterstatic int 134525839Speterstdio_buffer_flush (closure) 134625839Speter void *closure; 134725839Speter{ 1348102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) closure; 134925839Speter 1350102840Speter if (fflush (bc->fp) != 0) 135125839Speter { 135225839Speter if (errno == 0) 135325839Speter return EIO; 135425839Speter else 135525839Speter return errno; 135625839Speter } 135725839Speter 135825839Speter return 0; 135925839Speter} 136025839Speter 1361102840Speter 1362102840Speter 1363102840Speterstatic int 1364102840Speterstdio_buffer_shutdown (buf) 1365102840Speter struct buffer *buf; 1366102840Speter{ 1367102840Speter struct stdio_buffer_closure *bc = (struct stdio_buffer_closure *) buf->closure; 1368102840Speter struct stat s; 1369102840Speter int closefp = 1; 1370102840Speter 1371102840Speter /* Must be a pipe or a socket. What could go wrong? */ 1372102840Speter assert (fstat ( fileno (bc->fp), &s ) != -1); 1373102840Speter 1374102840Speter /* Flush the buffer if we can */ 1375102840Speter if (buf->flush) 1376102840Speter { 1377102840Speter buf_flush (buf, 1); 1378102840Speter buf->flush = NULL; 1379102840Speter } 1380102840Speter 1381102840Speter if (buf->input) 1382102840Speter { 1383102852Speter if (! buf_empty_p (buf)) 1384102840Speter { 1385102840Speter# ifdef SERVER_SUPPORT 1386102840Speter if (server_active) 1387102840Speter /* FIXME: This should probably be sysloged since it doesn't 1388102840Speter * have anywhere else to go at this point. 1389102840Speter */ 1390102840Speter error (0, 0, "dying gasps from client unexpected"); 1391102840Speter else 1392102840Speter#endif 1393102840Speter error (0, 0, "dying gasps from %s unexpected", current_parsed_root->hostname); 1394102840Speter } 1395102840Speter else if (ferror (bc->fp)) 1396102840Speter { 1397102840Speter# ifdef SERVER_SUPPORT 1398102840Speter if (server_active) 1399102840Speter /* FIXME: This should probably be sysloged since it doesn't 1400102840Speter * have anywhere else to go at this point. 1401102840Speter */ 1402102840Speter error (0, errno, "reading from client"); 1403102840Speter else 1404102840Speter#endif 1405102840Speter error (0, errno, "reading from %s", current_parsed_root->hostname); 1406102840Speter } 1407102840Speter 1408102840Speter# ifdef SHUTDOWN_SERVER 1409102840Speter if (current_parsed_root->method != server_method) 1410102840Speter# endif 1411102840Speter# ifndef NO_SOCKET_TO_FD 1412102840Speter { 1413102840Speter /* shutdown() sockets */ 1414102840Speter if (S_ISSOCK(s.st_mode)) 1415102840Speter shutdown ( fileno (bc->fp), 0); 1416102840Speter } 1417102840Speter# endif /* NO_SOCKET_TO_FD */ 1418102840Speter# ifdef START_RSH_WITH_POPEN_RW 1419102840Speter /* Can't be set with SHUTDOWN_SERVER defined */ 1420102840Speter else if (pclose (bc->fp) == EOF) 1421102840Speter { 1422102840Speter error (1, errno, "closing connection to %s", 1423102840Speter current_parsed_root->hostname); 1424102840Speter closefp = 0; 1425102840Speter } 1426102840Speter# endif /* START_RSH_WITH_POPEN_RW */ 1427102840Speter 1428102840Speter buf->input = NULL; 1429102840Speter } 1430102840Speter else if (buf->output) 1431102840Speter { 1432102840Speter# ifdef SHUTDOWN_SERVER 1433102840Speter /* FIXME: Should have a SHUTDOWN_SERVER_INPUT & 1434102840Speter * SHUTDOWN_SERVER_OUTPUT 1435102840Speter */ 1436102840Speter if (current_parsed_root->method == server_method) 1437102840Speter SHUTDOWN_SERVER ( fileno (bc->fp) ); 1438102840Speter else 1439102840Speter# endif 1440102840Speter# ifndef NO_SOCKET_TO_FD 1441102840Speter /* shutdown() sockets */ 1442102840Speter if (S_ISSOCK(s.st_mode)) 1443102840Speter shutdown ( fileno (bc->fp), 1); 1444102840Speter# else 1445102840Speter { 1446102840Speter /* I'm not sure I like this empty block, but the alternative 1447102840Speter * is a another nested NO_SOCKET_TO_FD switch above. 1448102840Speter */ 1449102840Speter } 1450102840Speter# endif /* NO_SOCKET_TO_FD */ 1451102840Speter 1452102840Speter buf->output = NULL; 1453102840Speter } 1454102840Speter 1455102840Speter if (closefp && fclose (bc->fp) == EOF) 1456102840Speter error (1, errno, 1457102840Speter "closing down connection to %s", 1458102840Speter current_parsed_root->hostname); 1459102840Speter 1460102840Speter /* If we were talking to a process, make sure it exited */ 1461102840Speter if (bc->child_pid 1462102840Speter && waitpid (bc->child_pid, (int *) 0, 0) == -1) 1463102840Speter error (1, errno, "waiting for process %d", bc->child_pid); 1464102840Speter 1465102840Speter return 0; 1466102840Speter} 1467102840Speter 1468102840Speter 1469102840Speter 147032785Speter/* Certain types of communication input and output data in packets, 147132785Speter where each packet is translated in some fashion. The packetizing 147232785Speter buffer type supports that, given a buffer which handles lower level 147332785Speter I/O and a routine to translate the data in a packet. 147432785Speter 147532785Speter This code uses two bytes for the size of a packet, so packets are 147632785Speter restricted to 65536 bytes in total. 147732785Speter 147832785Speter The translation functions should just translate; they may not 147932785Speter significantly increase or decrease the amount of data. The actual 148032785Speter size of the initial data is part of the translated data. The 148132785Speter output translation routine may add up to PACKET_SLOP additional 148232785Speter bytes, and the input translation routine should shrink the data 148332785Speter correspondingly. */ 148432785Speter 148532785Speter#define PACKET_SLOP (100) 148632785Speter 148732785Speter/* This structure is the closure field of a packetizing buffer. */ 148832785Speter 148932785Speterstruct packetizing_buffer 149032785Speter{ 149132785Speter /* The underlying buffer. */ 149232785Speter struct buffer *buf; 149332785Speter /* The input translation function. Exactly one of inpfn and outfn 149432785Speter will be NULL. The input translation function should 149532785Speter untranslate the data in INPUT, storing the result in OUTPUT. 149632785Speter SIZE is the amount of data in INPUT, and is also the size of 149732785Speter OUTPUT. This should return 0 on success, or an errno code. */ 149832785Speter int (*inpfn) PROTO((void *fnclosure, const char *input, char *output, 149932785Speter int size)); 150032785Speter /* The output translation function. This should translate the 150132785Speter data in INPUT, storing the result in OUTPUT. The first two 150232785Speter bytes in INPUT will be the size of the data, and so will SIZE. 150332785Speter This should set *TRANSLATED to the amount of translated data in 150432785Speter OUTPUT. OUTPUT is large enough to hold SIZE + PACKET_SLOP 150532785Speter bytes. This should return 0 on success, or an errno code. */ 150632785Speter int (*outfn) PROTO((void *fnclosure, const char *input, char *output, 150732785Speter int size, int *translated)); 150832785Speter /* A closure for the translation function. */ 150932785Speter void *fnclosure; 151032785Speter /* For an input buffer, we may have to buffer up data here. */ 151132785Speter /* This is non-zero if the buffered data has been translated. 151232785Speter Otherwise, the buffered data has not been translated, and starts 151332785Speter with the two byte packet size. */ 151432785Speter int translated; 151532785Speter /* The amount of buffered data. */ 151632785Speter int holdsize; 151732785Speter /* The buffer allocated to hold the data. */ 151832785Speter char *holdbuf; 151932785Speter /* The size of holdbuf. */ 152032785Speter int holdbufsize; 152132785Speter /* If translated is set, we need another data pointer to track 152232785Speter where we are in holdbuf. If translated is clear, then this 152332785Speter pointer is not used. */ 152432785Speter char *holddata; 152532785Speter}; 152632785Speter 152732785Speterstatic int packetizing_buffer_input PROTO((void *, char *, int, int, int *)); 152832785Speterstatic int packetizing_buffer_output PROTO((void *, const char *, int, int *)); 152932785Speterstatic int packetizing_buffer_flush PROTO((void *)); 153032785Speterstatic int packetizing_buffer_block PROTO((void *, int)); 1531102840Speterstatic int packetizing_buffer_shutdown PROTO((struct buffer *)); 153232785Speter 153332785Speter/* Create a packetizing buffer. */ 153432785Speter 153532785Speterstruct buffer * 153632785Speterpacketizing_buffer_initialize (buf, inpfn, outfn, fnclosure, memory) 153732785Speter struct buffer *buf; 153832785Speter int (*inpfn) PROTO ((void *, const char *, char *, int)); 153932785Speter int (*outfn) PROTO ((void *, const char *, char *, int, int *)); 154032785Speter void *fnclosure; 154132785Speter void (*memory) PROTO((struct buffer *)); 154232785Speter{ 154332785Speter struct packetizing_buffer *pb; 154432785Speter 154532785Speter pb = (struct packetizing_buffer *) xmalloc (sizeof *pb); 154632785Speter memset (pb, 0, sizeof *pb); 154732785Speter 154832785Speter pb->buf = buf; 154932785Speter pb->inpfn = inpfn; 155032785Speter pb->outfn = outfn; 155132785Speter pb->fnclosure = fnclosure; 155232785Speter 155332785Speter if (inpfn != NULL) 155432785Speter { 155532785Speter /* Add PACKET_SLOP to handle larger translated packets, and 155632785Speter add 2 for the count. This buffer is increased if 155732785Speter necessary. */ 155832785Speter pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2; 155932785Speter pb->holdbuf = xmalloc (pb->holdbufsize); 156032785Speter } 156132785Speter 156232785Speter return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL, 156332785Speter inpfn != NULL ? NULL : packetizing_buffer_output, 156432785Speter inpfn != NULL ? NULL : packetizing_buffer_flush, 156532785Speter packetizing_buffer_block, 156632785Speter packetizing_buffer_shutdown, 156732785Speter memory, 156832785Speter pb); 156932785Speter} 157032785Speter 157132785Speter/* Input data from a packetizing buffer. */ 157232785Speter 157332785Speterstatic int 157432785Speterpacketizing_buffer_input (closure, data, need, size, got) 157532785Speter void *closure; 157632785Speter char *data; 157732785Speter int need; 157832785Speter int size; 157932785Speter int *got; 158032785Speter{ 158132785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 158232785Speter 158332785Speter *got = 0; 158432785Speter 158532785Speter if (pb->holdsize > 0 && pb->translated) 158632785Speter { 158732785Speter int copy; 158832785Speter 158932785Speter copy = pb->holdsize; 159032785Speter 159132785Speter if (copy > size) 159232785Speter { 159332785Speter memcpy (data, pb->holddata, size); 159432785Speter pb->holdsize -= size; 159532785Speter pb->holddata += size; 159632785Speter *got = size; 159732785Speter return 0; 159832785Speter } 159932785Speter 160032785Speter memcpy (data, pb->holddata, copy); 160132785Speter pb->holdsize = 0; 160232785Speter pb->translated = 0; 160332785Speter 160432785Speter data += copy; 160532785Speter need -= copy; 160632785Speter size -= copy; 160732785Speter *got = copy; 160832785Speter } 160932785Speter 161032785Speter while (need > 0 || *got == 0) 161132785Speter { 161232785Speter int get, status, nread, count, tcount; 161332785Speter char *bytes; 161432785Speter char stackoutbuf[BUFFER_DATA_SIZE + PACKET_SLOP]; 161532785Speter char *inbuf, *outbuf; 161632785Speter 161732785Speter /* If we don't already have the two byte count, get it. */ 161832785Speter if (pb->holdsize < 2) 161932785Speter { 162032785Speter get = 2 - pb->holdsize; 162132785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 162232785Speter if (status != 0) 162332785Speter { 162432785Speter /* buf_read_data can return -2, but a buffer input 162532785Speter function is only supposed to return -1, 0, or an 162632785Speter error code. */ 162732785Speter if (status == -2) 162832785Speter status = ENOMEM; 162932785Speter return status; 163032785Speter } 163132785Speter 163232785Speter if (nread == 0) 163332785Speter { 163432785Speter /* The buffer is in nonblocking mode, and we didn't 163532785Speter manage to read anything. */ 163632785Speter return 0; 163732785Speter } 163832785Speter 163932785Speter if (get == 1) 164032785Speter pb->holdbuf[1] = bytes[0]; 164132785Speter else 164232785Speter { 164332785Speter pb->holdbuf[0] = bytes[0]; 164432785Speter if (nread < 2) 164532785Speter { 164632785Speter /* We only got one byte, but we needed two. Stash 164732785Speter the byte we got, and try again. */ 164832785Speter pb->holdsize = 1; 164932785Speter continue; 165032785Speter } 165132785Speter pb->holdbuf[1] = bytes[1]; 165232785Speter } 165332785Speter pb->holdsize = 2; 165432785Speter } 165532785Speter 165632785Speter /* Read the packet. */ 165732785Speter 165832785Speter count = (((pb->holdbuf[0] & 0xff) << 8) 165932785Speter + (pb->holdbuf[1] & 0xff)); 166032785Speter 166132785Speter if (count + 2 > pb->holdbufsize) 166232785Speter { 166332785Speter char *n; 166432785Speter 166532785Speter /* We didn't allocate enough space in the initialize 166632785Speter function. */ 166732785Speter 166832785Speter n = realloc (pb->holdbuf, count + 2); 166932785Speter if (n == NULL) 167032785Speter { 167132785Speter (*pb->buf->memory_error) (pb->buf); 167232785Speter return ENOMEM; 167332785Speter } 167432785Speter pb->holdbuf = n; 167532785Speter pb->holdbufsize = count + 2; 167632785Speter } 167732785Speter 167832785Speter get = count - (pb->holdsize - 2); 167932785Speter 168032785Speter status = buf_read_data (pb->buf, get, &bytes, &nread); 168132785Speter if (status != 0) 168232785Speter { 168332785Speter /* buf_read_data can return -2, but a buffer input 168432785Speter function is only supposed to return -1, 0, or an error 168532785Speter code. */ 168632785Speter if (status == -2) 168732785Speter status = ENOMEM; 168832785Speter return status; 168932785Speter } 169032785Speter 169132785Speter if (nread == 0) 169232785Speter { 169332785Speter /* We did not get any data. Presumably the buffer is in 169432785Speter nonblocking mode. */ 169532785Speter return 0; 169632785Speter } 169732785Speter 169832785Speter if (nread < get) 169932785Speter { 170032785Speter /* We did not get all the data we need to fill the packet. 170132785Speter buf_read_data does not promise to return all the bytes 170232785Speter requested, so we must try again. */ 170332785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 170432785Speter pb->holdsize += nread; 170532785Speter continue; 170632785Speter } 170732785Speter 170832785Speter /* We have a complete untranslated packet of COUNT bytes. */ 170932785Speter 171032785Speter if (pb->holdsize == 2) 171132785Speter { 171232785Speter /* We just read the entire packet (the 2 bytes in 171332785Speter PB->HOLDBUF are the size). Save a memcpy by 171432785Speter translating directly from BYTES. */ 171532785Speter inbuf = bytes; 171632785Speter } 171732785Speter else 171832785Speter { 171932785Speter /* We already had a partial packet in PB->HOLDBUF. We 172032785Speter need to copy the new data over to make the input 172132785Speter contiguous. */ 172232785Speter memcpy (pb->holdbuf + pb->holdsize, bytes, nread); 172332785Speter inbuf = pb->holdbuf + 2; 172432785Speter } 172532785Speter 172632785Speter if (count <= sizeof stackoutbuf) 172732785Speter outbuf = stackoutbuf; 172832785Speter else 172932785Speter { 173032785Speter outbuf = malloc (count); 173132785Speter if (outbuf == NULL) 173232785Speter { 173332785Speter (*pb->buf->memory_error) (pb->buf); 173432785Speter return ENOMEM; 173532785Speter } 173632785Speter } 173732785Speter 173832785Speter status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count); 173932785Speter if (status != 0) 174032785Speter return status; 174132785Speter 174232785Speter /* The first two bytes in the translated buffer are the real 174332785Speter length of the translated data. */ 174432785Speter tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff); 174532785Speter 174632785Speter if (tcount > count) 174732785Speter error (1, 0, "Input translation failure"); 174832785Speter 174932785Speter if (tcount > size) 175032785Speter { 175132785Speter /* We have more data than the caller has provided space 175232785Speter for. We need to save some of it for the next call. */ 175332785Speter 175432785Speter memcpy (data, outbuf + 2, size); 175532785Speter *got += size; 175632785Speter 175732785Speter pb->holdsize = tcount - size; 175832785Speter memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size); 175932785Speter pb->holddata = pb->holdbuf; 176032785Speter pb->translated = 1; 176132785Speter 176232785Speter if (outbuf != stackoutbuf) 176332785Speter free (outbuf); 176432785Speter 176532785Speter return 0; 176632785Speter } 176732785Speter 176832785Speter memcpy (data, outbuf + 2, tcount); 176932785Speter 177032785Speter if (outbuf != stackoutbuf) 177132785Speter free (outbuf); 177232785Speter 177332785Speter pb->holdsize = 0; 177432785Speter 177532785Speter data += tcount; 177632785Speter need -= tcount; 177732785Speter size -= tcount; 177832785Speter *got += tcount; 177932785Speter } 178032785Speter 178132785Speter return 0; 178232785Speter} 178332785Speter 178432785Speter/* Output data to a packetizing buffer. */ 178532785Speter 178632785Speterstatic int 178732785Speterpacketizing_buffer_output (closure, data, have, wrote) 178832785Speter void *closure; 178932785Speter const char *data; 179032785Speter int have; 179132785Speter int *wrote; 179232785Speter{ 179332785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 179432785Speter char inbuf[BUFFER_DATA_SIZE + 2]; 179532785Speter char stack_outbuf[BUFFER_DATA_SIZE + PACKET_SLOP + 4]; 179632785Speter struct buffer_data *outdata; 179732785Speter char *outbuf; 179832785Speter int size, status, translated; 179932785Speter 180032785Speter if (have > BUFFER_DATA_SIZE) 180132785Speter { 180232785Speter /* It would be easy to malloc a buffer, but I don't think this 180332785Speter case can ever arise. */ 180432785Speter abort (); 180532785Speter } 180632785Speter 180732785Speter inbuf[0] = (have >> 8) & 0xff; 180832785Speter inbuf[1] = have & 0xff; 180932785Speter memcpy (inbuf + 2, data, have); 181032785Speter 181132785Speter size = have + 2; 181232785Speter 181332785Speter /* The output function is permitted to add up to PACKET_SLOP 181432785Speter bytes, and we need 2 bytes for the size of the translated data. 181532785Speter If we can guarantee that the result will fit in a buffer_data, 181632785Speter we translate directly into one to avoid a memcpy in buf_output. */ 181732785Speter if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE) 181832785Speter outbuf = stack_outbuf; 181932785Speter else 182032785Speter { 182132785Speter outdata = get_buffer_data (); 182232785Speter if (outdata == NULL) 182332785Speter { 182432785Speter (*pb->buf->memory_error) (pb->buf); 182532785Speter return ENOMEM; 182632785Speter } 182732785Speter 182832785Speter outdata->next = NULL; 182932785Speter outdata->bufp = outdata->text; 183032785Speter 183132785Speter outbuf = outdata->text; 183232785Speter } 183332785Speter 183432785Speter status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size, 183532785Speter &translated); 183632785Speter if (status != 0) 183732785Speter return status; 183832785Speter 183932785Speter /* The output function is permitted to add up to PACKET_SLOP 184032785Speter bytes. */ 184132785Speter if (translated > size + PACKET_SLOP) 184232785Speter abort (); 184332785Speter 184432785Speter outbuf[0] = (translated >> 8) & 0xff; 184532785Speter outbuf[1] = translated & 0xff; 184632785Speter 184732785Speter if (outbuf == stack_outbuf) 184832785Speter buf_output (pb->buf, outbuf, translated + 2); 184932785Speter else 185032785Speter { 185132785Speter outdata->size = translated + 2; 185232785Speter buf_append_data (pb->buf, outdata, outdata); 185332785Speter } 185432785Speter 185532785Speter *wrote = have; 185632785Speter 185732785Speter /* We will only be here because buf_send_output was called on the 185832785Speter packetizing buffer. That means that we should now call 185932785Speter buf_send_output on the underlying buffer. */ 186032785Speter return buf_send_output (pb->buf); 186132785Speter} 186232785Speter 186332785Speter/* Flush data to a packetizing buffer. */ 186432785Speter 186532785Speterstatic int 186632785Speterpacketizing_buffer_flush (closure) 186732785Speter void *closure; 186832785Speter{ 186932785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 187032785Speter 187132785Speter /* Flush the underlying buffer. Note that if the original call to 187232785Speter buf_flush passed 1 for the BLOCK argument, then the buffer will 187332785Speter already have been set into blocking mode, so we should always 187432785Speter pass 0 here. */ 187532785Speter return buf_flush (pb->buf, 0); 187632785Speter} 187732785Speter 187832785Speter/* The block routine for a packetizing buffer. */ 187932785Speter 188032785Speterstatic int 188132785Speterpacketizing_buffer_block (closure, block) 188232785Speter void *closure; 188332785Speter int block; 188432785Speter{ 188532785Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) closure; 188632785Speter 188732785Speter if (block) 188832785Speter return set_block (pb->buf); 188932785Speter else 189032785Speter return set_nonblock (pb->buf); 189132785Speter} 189232785Speter 189332785Speter/* Shut down a packetizing buffer. */ 189432785Speter 189532785Speterstatic int 1896102840Speterpacketizing_buffer_shutdown (buf) 1897102840Speter struct buffer *buf; 189832785Speter{ 1899102840Speter struct packetizing_buffer *pb = (struct packetizing_buffer *) buf->closure; 190032785Speter 190132785Speter return buf_shutdown (pb->buf); 190232785Speter} 190332785Speter 190425839Speter#endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */ 1905