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