1*86d7f5d3SJohn Marino /*
2*86d7f5d3SJohn Marino * Copyright (C) 1996-2005 The Free Software Foundation, Inc.
3*86d7f5d3SJohn Marino *
4*86d7f5d3SJohn Marino * This program is free software; you can redistribute it and/or modify
5*86d7f5d3SJohn Marino * it under the terms of the GNU General Public License as published by
6*86d7f5d3SJohn Marino * the Free Software Foundation; either version 2, or (at your option)
7*86d7f5d3SJohn Marino * any later version.
8*86d7f5d3SJohn Marino *
9*86d7f5d3SJohn Marino * This program is distributed in the hope that it will be useful,
10*86d7f5d3SJohn Marino * but WITHOUT ANY WARRANTY; without even the implied warranty of
11*86d7f5d3SJohn Marino * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12*86d7f5d3SJohn Marino * GNU General Public License for more details.
13*86d7f5d3SJohn Marino */
14*86d7f5d3SJohn Marino
15*86d7f5d3SJohn Marino /* Code for the buffer data structure. */
16*86d7f5d3SJohn Marino
17*86d7f5d3SJohn Marino #include "cvs.h"
18*86d7f5d3SJohn Marino #include "buffer.h"
19*86d7f5d3SJohn Marino #include "pagealign_alloc.h"
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
22*86d7f5d3SJohn Marino
23*86d7f5d3SJohn Marino # include <sys/socket.h>
24*86d7f5d3SJohn Marino
25*86d7f5d3SJohn Marino /* OS/2 doesn't have EIO. FIXME: this whole notion of turning
26*86d7f5d3SJohn Marino a different error into EIO strikes me as pretty dubious. */
27*86d7f5d3SJohn Marino # if !defined( EIO )
28*86d7f5d3SJohn Marino # define EIO EBADPOS
29*86d7f5d3SJohn Marino # endif
30*86d7f5d3SJohn Marino
31*86d7f5d3SJohn Marino /* Local functions. */
32*86d7f5d3SJohn Marino static void buf_default_memory_error (struct buffer *);
33*86d7f5d3SJohn Marino static struct buffer_data *get_buffer_data (void);
34*86d7f5d3SJohn Marino
35*86d7f5d3SJohn Marino
36*86d7f5d3SJohn Marino
37*86d7f5d3SJohn Marino /* Initialize a buffer structure. */
38*86d7f5d3SJohn Marino struct buffer *
buf_initialize(type_buf_input input,type_buf_output output,type_buf_flush flush,type_buf_block block,type_buf_get_fd get_fd,type_buf_shutdown shutdown,type_buf_memory_error memory_error,void * closure)39*86d7f5d3SJohn Marino buf_initialize (type_buf_input input,
40*86d7f5d3SJohn Marino type_buf_output output,
41*86d7f5d3SJohn Marino type_buf_flush flush,
42*86d7f5d3SJohn Marino type_buf_block block,
43*86d7f5d3SJohn Marino type_buf_get_fd get_fd,
44*86d7f5d3SJohn Marino type_buf_shutdown shutdown,
45*86d7f5d3SJohn Marino type_buf_memory_error memory_error,
46*86d7f5d3SJohn Marino void *closure)
47*86d7f5d3SJohn Marino {
48*86d7f5d3SJohn Marino struct buffer *buf;
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino buf = xmalloc (sizeof (struct buffer));
51*86d7f5d3SJohn Marino buf->data = NULL;
52*86d7f5d3SJohn Marino buf->last = NULL;
53*86d7f5d3SJohn Marino buf->nonblocking = false;
54*86d7f5d3SJohn Marino buf->input = input;
55*86d7f5d3SJohn Marino buf->output = output;
56*86d7f5d3SJohn Marino buf->flush = flush;
57*86d7f5d3SJohn Marino buf->block = block;
58*86d7f5d3SJohn Marino buf->get_fd = get_fd;
59*86d7f5d3SJohn Marino buf->shutdown = shutdown;
60*86d7f5d3SJohn Marino buf->memory_error = memory_error ? memory_error : buf_default_memory_error;
61*86d7f5d3SJohn Marino buf->closure = closure;
62*86d7f5d3SJohn Marino return buf;
63*86d7f5d3SJohn Marino }
64*86d7f5d3SJohn Marino
65*86d7f5d3SJohn Marino
66*86d7f5d3SJohn Marino
67*86d7f5d3SJohn Marino /* Free a buffer structure. */
68*86d7f5d3SJohn Marino void
buf_free(struct buffer * buf)69*86d7f5d3SJohn Marino buf_free (struct buffer *buf)
70*86d7f5d3SJohn Marino {
71*86d7f5d3SJohn Marino if (buf->closure != NULL)
72*86d7f5d3SJohn Marino {
73*86d7f5d3SJohn Marino free (buf->closure);
74*86d7f5d3SJohn Marino buf->closure = NULL;
75*86d7f5d3SJohn Marino }
76*86d7f5d3SJohn Marino buf_free_data (buf);
77*86d7f5d3SJohn Marino free (buf);
78*86d7f5d3SJohn Marino }
79*86d7f5d3SJohn Marino
80*86d7f5d3SJohn Marino
81*86d7f5d3SJohn Marino
82*86d7f5d3SJohn Marino /* Initialize a buffer structure which is not to be used for I/O. */
83*86d7f5d3SJohn Marino struct buffer *
buf_nonio_initialize(void (* memory)(struct buffer *))84*86d7f5d3SJohn Marino buf_nonio_initialize( void (*memory) (struct buffer *) )
85*86d7f5d3SJohn Marino {
86*86d7f5d3SJohn Marino return buf_initialize (NULL, NULL, NULL, NULL, NULL, NULL, memory, NULL);
87*86d7f5d3SJohn Marino }
88*86d7f5d3SJohn Marino
89*86d7f5d3SJohn Marino
90*86d7f5d3SJohn Marino
91*86d7f5d3SJohn Marino /* Default memory error handler. */
92*86d7f5d3SJohn Marino static void
buf_default_memory_error(struct buffer * buf)93*86d7f5d3SJohn Marino buf_default_memory_error (struct buffer *buf)
94*86d7f5d3SJohn Marino {
95*86d7f5d3SJohn Marino error (1, 0, "out of memory");
96*86d7f5d3SJohn Marino }
97*86d7f5d3SJohn Marino
98*86d7f5d3SJohn Marino
99*86d7f5d3SJohn Marino
100*86d7f5d3SJohn Marino /* Allocate more buffer_data structures. */
101*86d7f5d3SJohn Marino /* Get a new buffer_data structure. */
102*86d7f5d3SJohn Marino static struct buffer_data *
get_buffer_data(void)103*86d7f5d3SJohn Marino get_buffer_data (void)
104*86d7f5d3SJohn Marino {
105*86d7f5d3SJohn Marino struct buffer_data *ret;
106*86d7f5d3SJohn Marino
107*86d7f5d3SJohn Marino ret = xmalloc (sizeof (struct buffer_data));
108*86d7f5d3SJohn Marino ret->text = pagealign_xalloc (BUFFER_DATA_SIZE);
109*86d7f5d3SJohn Marino
110*86d7f5d3SJohn Marino return ret;
111*86d7f5d3SJohn Marino }
112*86d7f5d3SJohn Marino
113*86d7f5d3SJohn Marino
114*86d7f5d3SJohn Marino
115*86d7f5d3SJohn Marino /* See whether a buffer and its file descriptor is empty. */
116*86d7f5d3SJohn Marino int
buf_empty(buf)117*86d7f5d3SJohn Marino buf_empty (buf)
118*86d7f5d3SJohn Marino struct buffer *buf;
119*86d7f5d3SJohn Marino {
120*86d7f5d3SJohn Marino /* Try and read any data on the file descriptor first.
121*86d7f5d3SJohn Marino * We already know the descriptor is non-blocking.
122*86d7f5d3SJohn Marino */
123*86d7f5d3SJohn Marino buf_input_data (buf, NULL);
124*86d7f5d3SJohn Marino return buf_empty_p (buf);
125*86d7f5d3SJohn Marino }
126*86d7f5d3SJohn Marino
127*86d7f5d3SJohn Marino
128*86d7f5d3SJohn Marino
129*86d7f5d3SJohn Marino /* See whether a buffer is empty. */
130*86d7f5d3SJohn Marino int
buf_empty_p(struct buffer * buf)131*86d7f5d3SJohn Marino buf_empty_p (struct buffer *buf)
132*86d7f5d3SJohn Marino {
133*86d7f5d3SJohn Marino struct buffer_data *data;
134*86d7f5d3SJohn Marino
135*86d7f5d3SJohn Marino for (data = buf->data; data != NULL; data = data->next)
136*86d7f5d3SJohn Marino if (data->size > 0)
137*86d7f5d3SJohn Marino return 0;
138*86d7f5d3SJohn Marino return 1;
139*86d7f5d3SJohn Marino }
140*86d7f5d3SJohn Marino
141*86d7f5d3SJohn Marino
142*86d7f5d3SJohn Marino
143*86d7f5d3SJohn Marino # if defined (SERVER_FLOWCONTROL) || defined (PROXY_SUPPORT)
144*86d7f5d3SJohn Marino /*
145*86d7f5d3SJohn Marino * Count how much data is stored in the buffer..
146*86d7f5d3SJohn Marino * Note that each buffer is a xmalloc'ed chunk BUFFER_DATA_SIZE.
147*86d7f5d3SJohn Marino */
148*86d7f5d3SJohn Marino int
buf_count_mem(struct buffer * buf)149*86d7f5d3SJohn Marino buf_count_mem (struct buffer *buf)
150*86d7f5d3SJohn Marino {
151*86d7f5d3SJohn Marino struct buffer_data *data;
152*86d7f5d3SJohn Marino int mem = 0;
153*86d7f5d3SJohn Marino
154*86d7f5d3SJohn Marino for (data = buf->data; data != NULL; data = data->next)
155*86d7f5d3SJohn Marino mem += BUFFER_DATA_SIZE;
156*86d7f5d3SJohn Marino
157*86d7f5d3SJohn Marino return mem;
158*86d7f5d3SJohn Marino }
159*86d7f5d3SJohn Marino # endif /* SERVER_FLOWCONTROL || PROXY_SUPPORT */
160*86d7f5d3SJohn Marino
161*86d7f5d3SJohn Marino
162*86d7f5d3SJohn Marino
163*86d7f5d3SJohn Marino /* Add data DATA of length LEN to BUF. */
164*86d7f5d3SJohn Marino void
buf_output(struct buffer * buf,const char * data,size_t len)165*86d7f5d3SJohn Marino buf_output (struct buffer *buf, const char *data, size_t len)
166*86d7f5d3SJohn Marino {
167*86d7f5d3SJohn Marino if (buf->data != NULL
168*86d7f5d3SJohn Marino && (((buf->last->text + BUFFER_DATA_SIZE)
169*86d7f5d3SJohn Marino - (buf->last->bufp + buf->last->size))
170*86d7f5d3SJohn Marino >= len))
171*86d7f5d3SJohn Marino {
172*86d7f5d3SJohn Marino memcpy (buf->last->bufp + buf->last->size, data, len);
173*86d7f5d3SJohn Marino buf->last->size += len;
174*86d7f5d3SJohn Marino return;
175*86d7f5d3SJohn Marino }
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino while (1)
178*86d7f5d3SJohn Marino {
179*86d7f5d3SJohn Marino struct buffer_data *newdata;
180*86d7f5d3SJohn Marino
181*86d7f5d3SJohn Marino newdata = get_buffer_data ();
182*86d7f5d3SJohn Marino if (newdata == NULL)
183*86d7f5d3SJohn Marino {
184*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
185*86d7f5d3SJohn Marino return;
186*86d7f5d3SJohn Marino }
187*86d7f5d3SJohn Marino
188*86d7f5d3SJohn Marino if (buf->data == NULL)
189*86d7f5d3SJohn Marino buf->data = newdata;
190*86d7f5d3SJohn Marino else
191*86d7f5d3SJohn Marino buf->last->next = newdata;
192*86d7f5d3SJohn Marino newdata->next = NULL;
193*86d7f5d3SJohn Marino buf->last = newdata;
194*86d7f5d3SJohn Marino
195*86d7f5d3SJohn Marino newdata->bufp = newdata->text;
196*86d7f5d3SJohn Marino
197*86d7f5d3SJohn Marino if (len <= BUFFER_DATA_SIZE)
198*86d7f5d3SJohn Marino {
199*86d7f5d3SJohn Marino newdata->size = len;
200*86d7f5d3SJohn Marino memcpy (newdata->text, data, len);
201*86d7f5d3SJohn Marino return;
202*86d7f5d3SJohn Marino }
203*86d7f5d3SJohn Marino
204*86d7f5d3SJohn Marino newdata->size = BUFFER_DATA_SIZE;
205*86d7f5d3SJohn Marino memcpy (newdata->text, data, BUFFER_DATA_SIZE);
206*86d7f5d3SJohn Marino
207*86d7f5d3SJohn Marino data += BUFFER_DATA_SIZE;
208*86d7f5d3SJohn Marino len -= BUFFER_DATA_SIZE;
209*86d7f5d3SJohn Marino }
210*86d7f5d3SJohn Marino
211*86d7f5d3SJohn Marino /*NOTREACHED*/
212*86d7f5d3SJohn Marino }
213*86d7f5d3SJohn Marino
214*86d7f5d3SJohn Marino
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino /* Add a '\0' terminated string to BUF. */
217*86d7f5d3SJohn Marino void
buf_output0(struct buffer * buf,const char * string)218*86d7f5d3SJohn Marino buf_output0 (struct buffer *buf, const char *string)
219*86d7f5d3SJohn Marino {
220*86d7f5d3SJohn Marino buf_output (buf, string, strlen (string));
221*86d7f5d3SJohn Marino }
222*86d7f5d3SJohn Marino
223*86d7f5d3SJohn Marino
224*86d7f5d3SJohn Marino
225*86d7f5d3SJohn Marino /* Add a single character to BUF. */
226*86d7f5d3SJohn Marino void
buf_append_char(struct buffer * buf,int ch)227*86d7f5d3SJohn Marino buf_append_char (struct buffer *buf, int ch)
228*86d7f5d3SJohn Marino {
229*86d7f5d3SJohn Marino if (buf->data != NULL
230*86d7f5d3SJohn Marino && (buf->last->text + BUFFER_DATA_SIZE
231*86d7f5d3SJohn Marino != buf->last->bufp + buf->last->size))
232*86d7f5d3SJohn Marino {
233*86d7f5d3SJohn Marino *(buf->last->bufp + buf->last->size) = ch;
234*86d7f5d3SJohn Marino ++buf->last->size;
235*86d7f5d3SJohn Marino }
236*86d7f5d3SJohn Marino else
237*86d7f5d3SJohn Marino {
238*86d7f5d3SJohn Marino char b;
239*86d7f5d3SJohn Marino
240*86d7f5d3SJohn Marino b = ch;
241*86d7f5d3SJohn Marino buf_output (buf, &b, 1);
242*86d7f5d3SJohn Marino }
243*86d7f5d3SJohn Marino }
244*86d7f5d3SJohn Marino
245*86d7f5d3SJohn Marino
246*86d7f5d3SJohn Marino
247*86d7f5d3SJohn Marino /* Free struct buffer_data's from the list starting with FIRST and ending at
248*86d7f5d3SJohn Marino * LAST, inclusive.
249*86d7f5d3SJohn Marino */
250*86d7f5d3SJohn Marino static inline void
buf_free_datas(struct buffer_data * first,struct buffer_data * last)251*86d7f5d3SJohn Marino buf_free_datas (struct buffer_data *first, struct buffer_data *last)
252*86d7f5d3SJohn Marino {
253*86d7f5d3SJohn Marino struct buffer_data *b, *n, *p;
254*86d7f5d3SJohn Marino b = first;
255*86d7f5d3SJohn Marino do
256*86d7f5d3SJohn Marino {
257*86d7f5d3SJohn Marino p = b;
258*86d7f5d3SJohn Marino n = b->next;
259*86d7f5d3SJohn Marino pagealign_free (b->text);
260*86d7f5d3SJohn Marino free (b);
261*86d7f5d3SJohn Marino b = n;
262*86d7f5d3SJohn Marino } while (p != last);
263*86d7f5d3SJohn Marino }
264*86d7f5d3SJohn Marino
265*86d7f5d3SJohn Marino
266*86d7f5d3SJohn Marino
267*86d7f5d3SJohn Marino /*
268*86d7f5d3SJohn Marino * Send all the output we've been saving up. Returns 0 for success or
269*86d7f5d3SJohn Marino * errno code. If the buffer has been set to be nonblocking, this
270*86d7f5d3SJohn Marino * will just write until the write would block.
271*86d7f5d3SJohn Marino */
272*86d7f5d3SJohn Marino int
buf_send_output(struct buffer * buf)273*86d7f5d3SJohn Marino buf_send_output (struct buffer *buf)
274*86d7f5d3SJohn Marino {
275*86d7f5d3SJohn Marino assert (buf->output != NULL);
276*86d7f5d3SJohn Marino
277*86d7f5d3SJohn Marino while (buf->data != NULL)
278*86d7f5d3SJohn Marino {
279*86d7f5d3SJohn Marino struct buffer_data *data;
280*86d7f5d3SJohn Marino
281*86d7f5d3SJohn Marino data = buf->data;
282*86d7f5d3SJohn Marino
283*86d7f5d3SJohn Marino if (data->size > 0)
284*86d7f5d3SJohn Marino {
285*86d7f5d3SJohn Marino int status;
286*86d7f5d3SJohn Marino size_t nbytes;
287*86d7f5d3SJohn Marino
288*86d7f5d3SJohn Marino status = (*buf->output) (buf->closure, data->bufp, data->size,
289*86d7f5d3SJohn Marino &nbytes);
290*86d7f5d3SJohn Marino if (status != 0)
291*86d7f5d3SJohn Marino {
292*86d7f5d3SJohn Marino /* Some sort of error. Discard the data, and return. */
293*86d7f5d3SJohn Marino buf_free_data (buf);
294*86d7f5d3SJohn Marino return status;
295*86d7f5d3SJohn Marino }
296*86d7f5d3SJohn Marino
297*86d7f5d3SJohn Marino if (nbytes != data->size)
298*86d7f5d3SJohn Marino {
299*86d7f5d3SJohn Marino /* Not all the data was written out. This is only
300*86d7f5d3SJohn Marino permitted in nonblocking mode. Adjust the buffer,
301*86d7f5d3SJohn Marino and return. */
302*86d7f5d3SJohn Marino
303*86d7f5d3SJohn Marino assert (buf->nonblocking);
304*86d7f5d3SJohn Marino
305*86d7f5d3SJohn Marino data->size -= nbytes;
306*86d7f5d3SJohn Marino data->bufp += nbytes;
307*86d7f5d3SJohn Marino
308*86d7f5d3SJohn Marino return 0;
309*86d7f5d3SJohn Marino }
310*86d7f5d3SJohn Marino }
311*86d7f5d3SJohn Marino
312*86d7f5d3SJohn Marino buf->data = data->next;
313*86d7f5d3SJohn Marino buf_free_datas (data, data);
314*86d7f5d3SJohn Marino }
315*86d7f5d3SJohn Marino
316*86d7f5d3SJohn Marino buf->last = NULL;
317*86d7f5d3SJohn Marino
318*86d7f5d3SJohn Marino return 0;
319*86d7f5d3SJohn Marino }
320*86d7f5d3SJohn Marino
321*86d7f5d3SJohn Marino
322*86d7f5d3SJohn Marino
323*86d7f5d3SJohn Marino /*
324*86d7f5d3SJohn Marino * Flush any data queued up in the buffer. If BLOCK is nonzero, then
325*86d7f5d3SJohn Marino * if the buffer is in nonblocking mode, put it into blocking mode for
326*86d7f5d3SJohn Marino * the duration of the flush. This returns 0 on success, or an error
327*86d7f5d3SJohn Marino * code.
328*86d7f5d3SJohn Marino */
329*86d7f5d3SJohn Marino int
buf_flush(struct buffer * buf,bool block)330*86d7f5d3SJohn Marino buf_flush (struct buffer *buf, bool block)
331*86d7f5d3SJohn Marino {
332*86d7f5d3SJohn Marino int nonblocking;
333*86d7f5d3SJohn Marino int status;
334*86d7f5d3SJohn Marino
335*86d7f5d3SJohn Marino assert (buf->flush != NULL);
336*86d7f5d3SJohn Marino
337*86d7f5d3SJohn Marino nonblocking = buf->nonblocking;
338*86d7f5d3SJohn Marino if (nonblocking && block)
339*86d7f5d3SJohn Marino {
340*86d7f5d3SJohn Marino status = set_block (buf);
341*86d7f5d3SJohn Marino if (status != 0)
342*86d7f5d3SJohn Marino return status;
343*86d7f5d3SJohn Marino }
344*86d7f5d3SJohn Marino
345*86d7f5d3SJohn Marino status = buf_send_output (buf);
346*86d7f5d3SJohn Marino if (status == 0)
347*86d7f5d3SJohn Marino status = (*buf->flush) (buf->closure);
348*86d7f5d3SJohn Marino
349*86d7f5d3SJohn Marino if (nonblocking && block)
350*86d7f5d3SJohn Marino {
351*86d7f5d3SJohn Marino int blockstat;
352*86d7f5d3SJohn Marino
353*86d7f5d3SJohn Marino blockstat = set_nonblock (buf);
354*86d7f5d3SJohn Marino if (status == 0)
355*86d7f5d3SJohn Marino status = blockstat;
356*86d7f5d3SJohn Marino }
357*86d7f5d3SJohn Marino
358*86d7f5d3SJohn Marino return status;
359*86d7f5d3SJohn Marino }
360*86d7f5d3SJohn Marino
361*86d7f5d3SJohn Marino
362*86d7f5d3SJohn Marino
363*86d7f5d3SJohn Marino /*
364*86d7f5d3SJohn Marino * Set buffer BUF to nonblocking I/O. Returns 0 for success or errno
365*86d7f5d3SJohn Marino * code.
366*86d7f5d3SJohn Marino */
367*86d7f5d3SJohn Marino int
set_nonblock(struct buffer * buf)368*86d7f5d3SJohn Marino set_nonblock (struct buffer *buf)
369*86d7f5d3SJohn Marino {
370*86d7f5d3SJohn Marino int status;
371*86d7f5d3SJohn Marino
372*86d7f5d3SJohn Marino if (buf->nonblocking)
373*86d7f5d3SJohn Marino return 0;
374*86d7f5d3SJohn Marino assert (buf->block != NULL);
375*86d7f5d3SJohn Marino status = (*buf->block) (buf->closure, 0);
376*86d7f5d3SJohn Marino if (status != 0)
377*86d7f5d3SJohn Marino return status;
378*86d7f5d3SJohn Marino buf->nonblocking = true;
379*86d7f5d3SJohn Marino return 0;
380*86d7f5d3SJohn Marino }
381*86d7f5d3SJohn Marino
382*86d7f5d3SJohn Marino
383*86d7f5d3SJohn Marino
384*86d7f5d3SJohn Marino /*
385*86d7f5d3SJohn Marino * Set buffer BUF to blocking I/O. Returns 0 for success or errno
386*86d7f5d3SJohn Marino * code.
387*86d7f5d3SJohn Marino */
388*86d7f5d3SJohn Marino int
set_block(struct buffer * buf)389*86d7f5d3SJohn Marino set_block (struct buffer *buf)
390*86d7f5d3SJohn Marino {
391*86d7f5d3SJohn Marino int status;
392*86d7f5d3SJohn Marino
393*86d7f5d3SJohn Marino if (! buf->nonblocking)
394*86d7f5d3SJohn Marino return 0;
395*86d7f5d3SJohn Marino assert (buf->block != NULL);
396*86d7f5d3SJohn Marino status = (*buf->block) (buf->closure, 1);
397*86d7f5d3SJohn Marino if (status != 0)
398*86d7f5d3SJohn Marino return status;
399*86d7f5d3SJohn Marino buf->nonblocking = false;
400*86d7f5d3SJohn Marino return 0;
401*86d7f5d3SJohn Marino }
402*86d7f5d3SJohn Marino
403*86d7f5d3SJohn Marino
404*86d7f5d3SJohn Marino
405*86d7f5d3SJohn Marino /*
406*86d7f5d3SJohn Marino * Send a character count and some output. Returns errno code or 0 for
407*86d7f5d3SJohn Marino * success.
408*86d7f5d3SJohn Marino *
409*86d7f5d3SJohn Marino * Sending the count in binary is OK since this is only used on a pipe
410*86d7f5d3SJohn Marino * within the same system.
411*86d7f5d3SJohn Marino */
412*86d7f5d3SJohn Marino int
buf_send_counted(struct buffer * buf)413*86d7f5d3SJohn Marino buf_send_counted (struct buffer *buf)
414*86d7f5d3SJohn Marino {
415*86d7f5d3SJohn Marino int size;
416*86d7f5d3SJohn Marino struct buffer_data *data;
417*86d7f5d3SJohn Marino
418*86d7f5d3SJohn Marino size = 0;
419*86d7f5d3SJohn Marino for (data = buf->data; data != NULL; data = data->next)
420*86d7f5d3SJohn Marino size += data->size;
421*86d7f5d3SJohn Marino
422*86d7f5d3SJohn Marino data = get_buffer_data ();
423*86d7f5d3SJohn Marino if (data == NULL)
424*86d7f5d3SJohn Marino {
425*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
426*86d7f5d3SJohn Marino return ENOMEM;
427*86d7f5d3SJohn Marino }
428*86d7f5d3SJohn Marino
429*86d7f5d3SJohn Marino data->next = buf->data;
430*86d7f5d3SJohn Marino buf->data = data;
431*86d7f5d3SJohn Marino if (buf->last == NULL)
432*86d7f5d3SJohn Marino buf->last = data;
433*86d7f5d3SJohn Marino
434*86d7f5d3SJohn Marino data->bufp = data->text;
435*86d7f5d3SJohn Marino data->size = sizeof (int);
436*86d7f5d3SJohn Marino
437*86d7f5d3SJohn Marino *((int *) data->text) = size;
438*86d7f5d3SJohn Marino
439*86d7f5d3SJohn Marino return buf_send_output (buf);
440*86d7f5d3SJohn Marino }
441*86d7f5d3SJohn Marino
442*86d7f5d3SJohn Marino
443*86d7f5d3SJohn Marino
444*86d7f5d3SJohn Marino /*
445*86d7f5d3SJohn Marino * Send a special count. COUNT should be negative. It will be
446*86d7f5d3SJohn Marino * handled specially by buf_copy_counted. This function returns 0 or
447*86d7f5d3SJohn Marino * an errno code.
448*86d7f5d3SJohn Marino *
449*86d7f5d3SJohn Marino * Sending the count in binary is OK since this is only used on a pipe
450*86d7f5d3SJohn Marino * within the same system.
451*86d7f5d3SJohn Marino */
452*86d7f5d3SJohn Marino int
buf_send_special_count(struct buffer * buf,int count)453*86d7f5d3SJohn Marino buf_send_special_count (struct buffer *buf, int count)
454*86d7f5d3SJohn Marino {
455*86d7f5d3SJohn Marino struct buffer_data *data;
456*86d7f5d3SJohn Marino
457*86d7f5d3SJohn Marino data = get_buffer_data ();
458*86d7f5d3SJohn Marino if (data == NULL)
459*86d7f5d3SJohn Marino {
460*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
461*86d7f5d3SJohn Marino return ENOMEM;
462*86d7f5d3SJohn Marino }
463*86d7f5d3SJohn Marino
464*86d7f5d3SJohn Marino data->next = buf->data;
465*86d7f5d3SJohn Marino buf->data = data;
466*86d7f5d3SJohn Marino if (buf->last == NULL)
467*86d7f5d3SJohn Marino buf->last = data;
468*86d7f5d3SJohn Marino
469*86d7f5d3SJohn Marino data->bufp = data->text;
470*86d7f5d3SJohn Marino data->size = sizeof (int);
471*86d7f5d3SJohn Marino
472*86d7f5d3SJohn Marino *((int *) data->text) = count;
473*86d7f5d3SJohn Marino
474*86d7f5d3SJohn Marino return buf_send_output (buf);
475*86d7f5d3SJohn Marino }
476*86d7f5d3SJohn Marino
477*86d7f5d3SJohn Marino
478*86d7f5d3SJohn Marino
479*86d7f5d3SJohn Marino /* Append a list of buffer_data structures to an buffer. */
480*86d7f5d3SJohn Marino void
buf_append_data(struct buffer * buf,struct buffer_data * data,struct buffer_data * last)481*86d7f5d3SJohn Marino buf_append_data (struct buffer *buf, struct buffer_data *data,
482*86d7f5d3SJohn Marino struct buffer_data *last)
483*86d7f5d3SJohn Marino {
484*86d7f5d3SJohn Marino if (data != NULL)
485*86d7f5d3SJohn Marino {
486*86d7f5d3SJohn Marino if (buf->data == NULL)
487*86d7f5d3SJohn Marino buf->data = data;
488*86d7f5d3SJohn Marino else
489*86d7f5d3SJohn Marino buf->last->next = data;
490*86d7f5d3SJohn Marino buf->last = last;
491*86d7f5d3SJohn Marino }
492*86d7f5d3SJohn Marino }
493*86d7f5d3SJohn Marino
494*86d7f5d3SJohn Marino
495*86d7f5d3SJohn Marino
496*86d7f5d3SJohn Marino # ifdef PROXY_SUPPORT
497*86d7f5d3SJohn Marino /* Copy data structures and append them to a buffer.
498*86d7f5d3SJohn Marino *
499*86d7f5d3SJohn Marino * ERRORS
500*86d7f5d3SJohn Marino * Failure to allocate memory here is fatal.
501*86d7f5d3SJohn Marino */
502*86d7f5d3SJohn Marino void
buf_copy_data(struct buffer * buf,struct buffer_data * data,struct buffer_data * last)503*86d7f5d3SJohn Marino buf_copy_data (struct buffer *buf, struct buffer_data *data,
504*86d7f5d3SJohn Marino struct buffer_data *last)
505*86d7f5d3SJohn Marino {
506*86d7f5d3SJohn Marino struct buffer_data *first, *new, *cur, *prev;
507*86d7f5d3SJohn Marino
508*86d7f5d3SJohn Marino assert (buf);
509*86d7f5d3SJohn Marino assert (data);
510*86d7f5d3SJohn Marino
511*86d7f5d3SJohn Marino prev = first = NULL;
512*86d7f5d3SJohn Marino cur = data;
513*86d7f5d3SJohn Marino while (1)
514*86d7f5d3SJohn Marino {
515*86d7f5d3SJohn Marino new = get_buffer_data ();
516*86d7f5d3SJohn Marino if (!new) error (1, errno, "Failed to allocate buffer data.");
517*86d7f5d3SJohn Marino
518*86d7f5d3SJohn Marino if (!first) first = new;
519*86d7f5d3SJohn Marino memcpy (new->text, cur->bufp, cur->size);
520*86d7f5d3SJohn Marino new->bufp = new->text;
521*86d7f5d3SJohn Marino new->size = cur->size;
522*86d7f5d3SJohn Marino new->next = NULL;
523*86d7f5d3SJohn Marino if (prev) prev->next = new;
524*86d7f5d3SJohn Marino if (cur == last) break;
525*86d7f5d3SJohn Marino prev = new;
526*86d7f5d3SJohn Marino cur = cur->next;
527*86d7f5d3SJohn Marino }
528*86d7f5d3SJohn Marino
529*86d7f5d3SJohn Marino buf_append_data (buf, first, new);
530*86d7f5d3SJohn Marino }
531*86d7f5d3SJohn Marino # endif /* PROXY_SUPPORT */
532*86d7f5d3SJohn Marino
533*86d7f5d3SJohn Marino
534*86d7f5d3SJohn Marino
535*86d7f5d3SJohn Marino /* Dispose of any remaining data in the buffer. */
536*86d7f5d3SJohn Marino void
buf_free_data(struct buffer * buffer)537*86d7f5d3SJohn Marino buf_free_data (struct buffer *buffer)
538*86d7f5d3SJohn Marino {
539*86d7f5d3SJohn Marino if (buf_empty_p (buffer)) return;
540*86d7f5d3SJohn Marino buf_free_datas (buffer->data, buffer->last);
541*86d7f5d3SJohn Marino buffer->data = buffer->last = NULL;
542*86d7f5d3SJohn Marino }
543*86d7f5d3SJohn Marino
544*86d7f5d3SJohn Marino
545*86d7f5d3SJohn Marino
546*86d7f5d3SJohn Marino /* Append the data in one buffer to another. This removes the data
547*86d7f5d3SJohn Marino * from the source buffer.
548*86d7f5d3SJohn Marino */
549*86d7f5d3SJohn Marino void
buf_append_buffer(struct buffer * to,struct buffer * from)550*86d7f5d3SJohn Marino buf_append_buffer (struct buffer *to, struct buffer *from)
551*86d7f5d3SJohn Marino {
552*86d7f5d3SJohn Marino struct buffer_data *n;
553*86d7f5d3SJohn Marino
554*86d7f5d3SJohn Marino /* Copy the data pointer to the new buf. */
555*86d7f5d3SJohn Marino buf_append_data (to, from->data, from->last);
556*86d7f5d3SJohn Marino
557*86d7f5d3SJohn Marino n = from->data;
558*86d7f5d3SJohn Marino while (n)
559*86d7f5d3SJohn Marino {
560*86d7f5d3SJohn Marino if (n == from->last) break;
561*86d7f5d3SJohn Marino n = n->next;
562*86d7f5d3SJohn Marino }
563*86d7f5d3SJohn Marino
564*86d7f5d3SJohn Marino /* Remove from the original location. */
565*86d7f5d3SJohn Marino from->data = NULL;
566*86d7f5d3SJohn Marino from->last = NULL;
567*86d7f5d3SJohn Marino }
568*86d7f5d3SJohn Marino
569*86d7f5d3SJohn Marino
570*86d7f5d3SJohn Marino
571*86d7f5d3SJohn Marino /*
572*86d7f5d3SJohn Marino * Copy the contents of file F into buffer_data structures. We can't
573*86d7f5d3SJohn Marino * copy directly into an buffer, because we want to handle failure and
574*86d7f5d3SJohn Marino * success differently. Returns 0 on success, or -2 if out of
575*86d7f5d3SJohn Marino * memory, or a status code on error. Since the caller happens to
576*86d7f5d3SJohn Marino * know the size of the file, it is passed in as SIZE. On success,
577*86d7f5d3SJohn Marino * this function sets *RETP and *LASTP, which may be passed to
578*86d7f5d3SJohn Marino * buf_append_data.
579*86d7f5d3SJohn Marino */
580*86d7f5d3SJohn Marino int
buf_read_file(FILE * f,long int size,struct buffer_data ** retp,struct buffer_data ** lastp)581*86d7f5d3SJohn Marino buf_read_file (FILE *f, long int size, struct buffer_data **retp,
582*86d7f5d3SJohn Marino struct buffer_data **lastp)
583*86d7f5d3SJohn Marino {
584*86d7f5d3SJohn Marino int status;
585*86d7f5d3SJohn Marino
586*86d7f5d3SJohn Marino *retp = NULL;
587*86d7f5d3SJohn Marino *lastp = NULL;
588*86d7f5d3SJohn Marino
589*86d7f5d3SJohn Marino while (size > 0)
590*86d7f5d3SJohn Marino {
591*86d7f5d3SJohn Marino struct buffer_data *data;
592*86d7f5d3SJohn Marino int get;
593*86d7f5d3SJohn Marino
594*86d7f5d3SJohn Marino data = get_buffer_data ();
595*86d7f5d3SJohn Marino if (data == NULL)
596*86d7f5d3SJohn Marino {
597*86d7f5d3SJohn Marino status = -2;
598*86d7f5d3SJohn Marino goto error_return;
599*86d7f5d3SJohn Marino }
600*86d7f5d3SJohn Marino
601*86d7f5d3SJohn Marino if (*retp == NULL)
602*86d7f5d3SJohn Marino *retp = data;
603*86d7f5d3SJohn Marino else
604*86d7f5d3SJohn Marino (*lastp)->next = data;
605*86d7f5d3SJohn Marino data->next = NULL;
606*86d7f5d3SJohn Marino *lastp = data;
607*86d7f5d3SJohn Marino
608*86d7f5d3SJohn Marino data->bufp = data->text;
609*86d7f5d3SJohn Marino data->size = 0;
610*86d7f5d3SJohn Marino
611*86d7f5d3SJohn Marino if (size > BUFFER_DATA_SIZE)
612*86d7f5d3SJohn Marino get = BUFFER_DATA_SIZE;
613*86d7f5d3SJohn Marino else
614*86d7f5d3SJohn Marino get = size;
615*86d7f5d3SJohn Marino
616*86d7f5d3SJohn Marino errno = EIO;
617*86d7f5d3SJohn Marino if (fread (data->text, get, 1, f) != 1)
618*86d7f5d3SJohn Marino {
619*86d7f5d3SJohn Marino status = errno;
620*86d7f5d3SJohn Marino goto error_return;
621*86d7f5d3SJohn Marino }
622*86d7f5d3SJohn Marino
623*86d7f5d3SJohn Marino data->size += get;
624*86d7f5d3SJohn Marino size -= get;
625*86d7f5d3SJohn Marino }
626*86d7f5d3SJohn Marino
627*86d7f5d3SJohn Marino return 0;
628*86d7f5d3SJohn Marino
629*86d7f5d3SJohn Marino error_return:
630*86d7f5d3SJohn Marino if (*retp != NULL)
631*86d7f5d3SJohn Marino buf_free_datas (*retp, (*lastp)->next);
632*86d7f5d3SJohn Marino return status;
633*86d7f5d3SJohn Marino }
634*86d7f5d3SJohn Marino
635*86d7f5d3SJohn Marino
636*86d7f5d3SJohn Marino
637*86d7f5d3SJohn Marino /*
638*86d7f5d3SJohn Marino * Copy the contents of file F into buffer_data structures. We can't
639*86d7f5d3SJohn Marino * copy directly into an buffer, because we want to handle failure and
640*86d7f5d3SJohn Marino * success differently. Returns 0 on success, or -2 if out of
641*86d7f5d3SJohn Marino * memory, or a status code on error. On success, this function sets
642*86d7f5d3SJohn Marino * *RETP and *LASTP, which may be passed to buf_append_data.
643*86d7f5d3SJohn Marino */
644*86d7f5d3SJohn Marino int
buf_read_file_to_eof(FILE * f,struct buffer_data ** retp,struct buffer_data ** lastp)645*86d7f5d3SJohn Marino buf_read_file_to_eof (FILE *f, struct buffer_data **retp,
646*86d7f5d3SJohn Marino struct buffer_data **lastp)
647*86d7f5d3SJohn Marino {
648*86d7f5d3SJohn Marino int status;
649*86d7f5d3SJohn Marino
650*86d7f5d3SJohn Marino *retp = NULL;
651*86d7f5d3SJohn Marino *lastp = NULL;
652*86d7f5d3SJohn Marino
653*86d7f5d3SJohn Marino while (!feof (f))
654*86d7f5d3SJohn Marino {
655*86d7f5d3SJohn Marino struct buffer_data *data;
656*86d7f5d3SJohn Marino int get, nread;
657*86d7f5d3SJohn Marino
658*86d7f5d3SJohn Marino data = get_buffer_data ();
659*86d7f5d3SJohn Marino if (data == NULL)
660*86d7f5d3SJohn Marino {
661*86d7f5d3SJohn Marino status = -2;
662*86d7f5d3SJohn Marino goto error_return;
663*86d7f5d3SJohn Marino }
664*86d7f5d3SJohn Marino
665*86d7f5d3SJohn Marino if (*retp == NULL)
666*86d7f5d3SJohn Marino *retp = data;
667*86d7f5d3SJohn Marino else
668*86d7f5d3SJohn Marino (*lastp)->next = data;
669*86d7f5d3SJohn Marino data->next = NULL;
670*86d7f5d3SJohn Marino *lastp = data;
671*86d7f5d3SJohn Marino
672*86d7f5d3SJohn Marino data->bufp = data->text;
673*86d7f5d3SJohn Marino data->size = 0;
674*86d7f5d3SJohn Marino
675*86d7f5d3SJohn Marino get = BUFFER_DATA_SIZE;
676*86d7f5d3SJohn Marino
677*86d7f5d3SJohn Marino errno = EIO;
678*86d7f5d3SJohn Marino nread = fread (data->text, 1, get, f);
679*86d7f5d3SJohn Marino if (nread == 0 && !feof (f))
680*86d7f5d3SJohn Marino {
681*86d7f5d3SJohn Marino status = errno;
682*86d7f5d3SJohn Marino goto error_return;
683*86d7f5d3SJohn Marino }
684*86d7f5d3SJohn Marino
685*86d7f5d3SJohn Marino data->size = nread;
686*86d7f5d3SJohn Marino }
687*86d7f5d3SJohn Marino
688*86d7f5d3SJohn Marino return 0;
689*86d7f5d3SJohn Marino
690*86d7f5d3SJohn Marino error_return:
691*86d7f5d3SJohn Marino if (*retp != NULL)
692*86d7f5d3SJohn Marino buf_free_datas (*retp, (*lastp)->next);
693*86d7f5d3SJohn Marino return status;
694*86d7f5d3SJohn Marino }
695*86d7f5d3SJohn Marino
696*86d7f5d3SJohn Marino
697*86d7f5d3SJohn Marino
698*86d7f5d3SJohn Marino /* Return the number of bytes in a chain of buffer_data structures. */
699*86d7f5d3SJohn Marino int
buf_chain_length(struct buffer_data * buf)700*86d7f5d3SJohn Marino buf_chain_length (struct buffer_data *buf)
701*86d7f5d3SJohn Marino {
702*86d7f5d3SJohn Marino int size = 0;
703*86d7f5d3SJohn Marino while (buf)
704*86d7f5d3SJohn Marino {
705*86d7f5d3SJohn Marino size += buf->size;
706*86d7f5d3SJohn Marino buf = buf->next;
707*86d7f5d3SJohn Marino }
708*86d7f5d3SJohn Marino return size;
709*86d7f5d3SJohn Marino }
710*86d7f5d3SJohn Marino
711*86d7f5d3SJohn Marino
712*86d7f5d3SJohn Marino
713*86d7f5d3SJohn Marino /* Return the number of bytes in a buffer. */
714*86d7f5d3SJohn Marino int
buf_length(struct buffer * buf)715*86d7f5d3SJohn Marino buf_length (struct buffer *buf)
716*86d7f5d3SJohn Marino {
717*86d7f5d3SJohn Marino return buf_chain_length (buf->data);
718*86d7f5d3SJohn Marino }
719*86d7f5d3SJohn Marino
720*86d7f5d3SJohn Marino
721*86d7f5d3SJohn Marino
722*86d7f5d3SJohn Marino /*
723*86d7f5d3SJohn Marino * Read an arbitrary amount of data into an input buffer. The buffer
724*86d7f5d3SJohn Marino * will be in nonblocking mode, and we just grab what we can. Return
725*86d7f5d3SJohn Marino * 0 on success, or -1 on end of file, or -2 if out of memory, or an
726*86d7f5d3SJohn Marino * error code. If COUNTP is not NULL, *COUNTP is set to the number of
727*86d7f5d3SJohn Marino * bytes read.
728*86d7f5d3SJohn Marino */
729*86d7f5d3SJohn Marino int
buf_input_data(struct buffer * buf,size_t * countp)730*86d7f5d3SJohn Marino buf_input_data (struct buffer *buf, size_t *countp)
731*86d7f5d3SJohn Marino {
732*86d7f5d3SJohn Marino assert (buf->input != NULL);
733*86d7f5d3SJohn Marino
734*86d7f5d3SJohn Marino if (countp != NULL)
735*86d7f5d3SJohn Marino *countp = 0;
736*86d7f5d3SJohn Marino
737*86d7f5d3SJohn Marino while (1)
738*86d7f5d3SJohn Marino {
739*86d7f5d3SJohn Marino int status;
740*86d7f5d3SJohn Marino size_t get, nbytes;
741*86d7f5d3SJohn Marino
742*86d7f5d3SJohn Marino if (buf->data == NULL
743*86d7f5d3SJohn Marino || (buf->last->bufp + buf->last->size
744*86d7f5d3SJohn Marino == buf->last->text + BUFFER_DATA_SIZE))
745*86d7f5d3SJohn Marino {
746*86d7f5d3SJohn Marino struct buffer_data *data;
747*86d7f5d3SJohn Marino
748*86d7f5d3SJohn Marino data = get_buffer_data ();
749*86d7f5d3SJohn Marino if (data == NULL)
750*86d7f5d3SJohn Marino {
751*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
752*86d7f5d3SJohn Marino return -2;
753*86d7f5d3SJohn Marino }
754*86d7f5d3SJohn Marino
755*86d7f5d3SJohn Marino if (buf->data == NULL)
756*86d7f5d3SJohn Marino buf->data = data;
757*86d7f5d3SJohn Marino else
758*86d7f5d3SJohn Marino buf->last->next = data;
759*86d7f5d3SJohn Marino data->next = NULL;
760*86d7f5d3SJohn Marino buf->last = data;
761*86d7f5d3SJohn Marino
762*86d7f5d3SJohn Marino data->bufp = data->text;
763*86d7f5d3SJohn Marino data->size = 0;
764*86d7f5d3SJohn Marino }
765*86d7f5d3SJohn Marino
766*86d7f5d3SJohn Marino get = ((buf->last->text + BUFFER_DATA_SIZE)
767*86d7f5d3SJohn Marino - (buf->last->bufp + buf->last->size));
768*86d7f5d3SJohn Marino
769*86d7f5d3SJohn Marino status = (*buf->input) (buf->closure,
770*86d7f5d3SJohn Marino buf->last->bufp + buf->last->size,
771*86d7f5d3SJohn Marino 0, get, &nbytes);
772*86d7f5d3SJohn Marino if (status != 0)
773*86d7f5d3SJohn Marino return status;
774*86d7f5d3SJohn Marino
775*86d7f5d3SJohn Marino buf->last->size += nbytes;
776*86d7f5d3SJohn Marino if (countp != NULL)
777*86d7f5d3SJohn Marino *countp += nbytes;
778*86d7f5d3SJohn Marino
779*86d7f5d3SJohn Marino if (nbytes < get)
780*86d7f5d3SJohn Marino {
781*86d7f5d3SJohn Marino /* If we did not fill the buffer, then presumably we read
782*86d7f5d3SJohn Marino all the available data. */
783*86d7f5d3SJohn Marino return 0;
784*86d7f5d3SJohn Marino }
785*86d7f5d3SJohn Marino }
786*86d7f5d3SJohn Marino
787*86d7f5d3SJohn Marino /*NOTREACHED*/
788*86d7f5d3SJohn Marino }
789*86d7f5d3SJohn Marino
790*86d7f5d3SJohn Marino
791*86d7f5d3SJohn Marino
792*86d7f5d3SJohn Marino /*
793*86d7f5d3SJohn Marino * Read a line (characters up to a \012) from an input buffer. (We
794*86d7f5d3SJohn Marino * use \012 rather than \n for the benefit of non Unix clients for
795*86d7f5d3SJohn Marino * which \n means something else). This returns 0 on success, or -1
796*86d7f5d3SJohn Marino * on end of file, or -2 if out of memory, or an error code. If it
797*86d7f5d3SJohn Marino * succeeds, it sets *LINE to an allocated buffer holding the contents
798*86d7f5d3SJohn Marino * of the line. The trailing \012 is not included in the buffer. If
799*86d7f5d3SJohn Marino * LENP is not NULL, then *LENP is set to the number of bytes read;
800*86d7f5d3SJohn Marino * strlen may not work, because there may be embedded null bytes.
801*86d7f5d3SJohn Marino */
802*86d7f5d3SJohn Marino int
buf_read_line(struct buffer * buf,char ** line,size_t * lenp)803*86d7f5d3SJohn Marino buf_read_line (struct buffer *buf, char **line, size_t *lenp)
804*86d7f5d3SJohn Marino {
805*86d7f5d3SJohn Marino return buf_read_short_line (buf, line, lenp, SIZE_MAX);
806*86d7f5d3SJohn Marino }
807*86d7f5d3SJohn Marino
808*86d7f5d3SJohn Marino
809*86d7f5d3SJohn Marino
810*86d7f5d3SJohn Marino /* Like buf_read_line, but return -2 if no newline is found in MAX characters.
811*86d7f5d3SJohn Marino */
812*86d7f5d3SJohn Marino int
buf_read_short_line(struct buffer * buf,char ** line,size_t * lenp,size_t max)813*86d7f5d3SJohn Marino buf_read_short_line (struct buffer *buf, char **line, size_t *lenp,
814*86d7f5d3SJohn Marino size_t max)
815*86d7f5d3SJohn Marino {
816*86d7f5d3SJohn Marino assert (buf->input != NULL);
817*86d7f5d3SJohn Marino
818*86d7f5d3SJohn Marino *line = NULL;
819*86d7f5d3SJohn Marino
820*86d7f5d3SJohn Marino while (1)
821*86d7f5d3SJohn Marino {
822*86d7f5d3SJohn Marino size_t len, finallen, predicted_len;
823*86d7f5d3SJohn Marino struct buffer_data *data;
824*86d7f5d3SJohn Marino char *nl;
825*86d7f5d3SJohn Marino
826*86d7f5d3SJohn Marino /* See if there is a newline in BUF. */
827*86d7f5d3SJohn Marino len = 0;
828*86d7f5d3SJohn Marino for (data = buf->data; data != NULL; data = data->next)
829*86d7f5d3SJohn Marino {
830*86d7f5d3SJohn Marino nl = memchr (data->bufp, '\012', data->size);
831*86d7f5d3SJohn Marino if (nl != NULL)
832*86d7f5d3SJohn Marino {
833*86d7f5d3SJohn Marino finallen = nl - data->bufp;
834*86d7f5d3SJohn Marino if (xsum (len, finallen) >= max) return -2;
835*86d7f5d3SJohn Marino len += finallen;
836*86d7f5d3SJohn Marino break;
837*86d7f5d3SJohn Marino }
838*86d7f5d3SJohn Marino else if (xsum (len, data->size) >= max) return -2;
839*86d7f5d3SJohn Marino len += data->size;
840*86d7f5d3SJohn Marino }
841*86d7f5d3SJohn Marino
842*86d7f5d3SJohn Marino /* If we found a newline, copy the line into a memory buffer,
843*86d7f5d3SJohn Marino and remove it from BUF. */
844*86d7f5d3SJohn Marino if (data != NULL)
845*86d7f5d3SJohn Marino {
846*86d7f5d3SJohn Marino char *p;
847*86d7f5d3SJohn Marino struct buffer_data *nldata;
848*86d7f5d3SJohn Marino
849*86d7f5d3SJohn Marino p = xmalloc (len + 1);
850*86d7f5d3SJohn Marino if (p == NULL)
851*86d7f5d3SJohn Marino return -2;
852*86d7f5d3SJohn Marino *line = p;
853*86d7f5d3SJohn Marino
854*86d7f5d3SJohn Marino nldata = data;
855*86d7f5d3SJohn Marino data = buf->data;
856*86d7f5d3SJohn Marino while (data != nldata)
857*86d7f5d3SJohn Marino {
858*86d7f5d3SJohn Marino struct buffer_data *next;
859*86d7f5d3SJohn Marino
860*86d7f5d3SJohn Marino memcpy (p, data->bufp, data->size);
861*86d7f5d3SJohn Marino p += data->size;
862*86d7f5d3SJohn Marino next = data->next;
863*86d7f5d3SJohn Marino buf_free_datas (data, data);
864*86d7f5d3SJohn Marino data = next;
865*86d7f5d3SJohn Marino }
866*86d7f5d3SJohn Marino
867*86d7f5d3SJohn Marino memcpy (p, data->bufp, finallen);
868*86d7f5d3SJohn Marino p[finallen] = '\0';
869*86d7f5d3SJohn Marino
870*86d7f5d3SJohn Marino data->size -= finallen + 1;
871*86d7f5d3SJohn Marino data->bufp = nl + 1;
872*86d7f5d3SJohn Marino buf->data = data;
873*86d7f5d3SJohn Marino
874*86d7f5d3SJohn Marino if (lenp != NULL)
875*86d7f5d3SJohn Marino *lenp = len;
876*86d7f5d3SJohn Marino
877*86d7f5d3SJohn Marino return 0;
878*86d7f5d3SJohn Marino }
879*86d7f5d3SJohn Marino
880*86d7f5d3SJohn Marino /* Read more data until we get a newline or MAX characters. */
881*86d7f5d3SJohn Marino predicted_len = 0;
882*86d7f5d3SJohn Marino while (1)
883*86d7f5d3SJohn Marino {
884*86d7f5d3SJohn Marino int status;
885*86d7f5d3SJohn Marino size_t size, nbytes;
886*86d7f5d3SJohn Marino char *mem;
887*86d7f5d3SJohn Marino
888*86d7f5d3SJohn Marino if (buf->data == NULL
889*86d7f5d3SJohn Marino || (buf->last->bufp + buf->last->size
890*86d7f5d3SJohn Marino == buf->last->text + BUFFER_DATA_SIZE))
891*86d7f5d3SJohn Marino {
892*86d7f5d3SJohn Marino data = get_buffer_data ();
893*86d7f5d3SJohn Marino if (data == NULL)
894*86d7f5d3SJohn Marino {
895*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
896*86d7f5d3SJohn Marino return -2;
897*86d7f5d3SJohn Marino }
898*86d7f5d3SJohn Marino
899*86d7f5d3SJohn Marino if (buf->data == NULL)
900*86d7f5d3SJohn Marino buf->data = data;
901*86d7f5d3SJohn Marino else
902*86d7f5d3SJohn Marino buf->last->next = data;
903*86d7f5d3SJohn Marino data->next = NULL;
904*86d7f5d3SJohn Marino buf->last = data;
905*86d7f5d3SJohn Marino
906*86d7f5d3SJohn Marino data->bufp = data->text;
907*86d7f5d3SJohn Marino data->size = 0;
908*86d7f5d3SJohn Marino }
909*86d7f5d3SJohn Marino
910*86d7f5d3SJohn Marino mem = buf->last->bufp + buf->last->size;
911*86d7f5d3SJohn Marino size = (buf->last->text + BUFFER_DATA_SIZE) - mem;
912*86d7f5d3SJohn Marino
913*86d7f5d3SJohn Marino /* We need to read at least 1 byte. We can handle up to
914*86d7f5d3SJohn Marino SIZE bytes. This will only be efficient if the
915*86d7f5d3SJohn Marino underlying communication stream does its own buffering,
916*86d7f5d3SJohn Marino or is clever about getting more than 1 byte at a time. */
917*86d7f5d3SJohn Marino status = (*buf->input) (buf->closure, mem, 1, size, &nbytes);
918*86d7f5d3SJohn Marino if (status != 0)
919*86d7f5d3SJohn Marino return status;
920*86d7f5d3SJohn Marino
921*86d7f5d3SJohn Marino predicted_len += nbytes;
922*86d7f5d3SJohn Marino buf->last->size += nbytes;
923*86d7f5d3SJohn Marino
924*86d7f5d3SJohn Marino /* Optimize slightly to avoid an unnecessary call to memchr. */
925*86d7f5d3SJohn Marino if (nbytes == 1)
926*86d7f5d3SJohn Marino {
927*86d7f5d3SJohn Marino if (*mem == '\012')
928*86d7f5d3SJohn Marino break;
929*86d7f5d3SJohn Marino }
930*86d7f5d3SJohn Marino else
931*86d7f5d3SJohn Marino {
932*86d7f5d3SJohn Marino if (memchr (mem, '\012', nbytes) != NULL)
933*86d7f5d3SJohn Marino break;
934*86d7f5d3SJohn Marino }
935*86d7f5d3SJohn Marino if (xsum (len, predicted_len) >= max) return -2;
936*86d7f5d3SJohn Marino }
937*86d7f5d3SJohn Marino }
938*86d7f5d3SJohn Marino }
939*86d7f5d3SJohn Marino
940*86d7f5d3SJohn Marino
941*86d7f5d3SJohn Marino
942*86d7f5d3SJohn Marino /*
943*86d7f5d3SJohn Marino * Extract data from the input buffer BUF. This will read up to WANT
944*86d7f5d3SJohn Marino * bytes from the buffer. It will set *RETDATA to point at the bytes,
945*86d7f5d3SJohn Marino * and set *GOT to the number of bytes to be found there. Any buffer
946*86d7f5d3SJohn Marino * call which uses BUF may change the contents of the buffer at *DATA,
947*86d7f5d3SJohn Marino * so the data should be fully processed before any further calls are
948*86d7f5d3SJohn Marino * made. This returns 0 on success, or -1 on end of file, or -2 if
949*86d7f5d3SJohn Marino * out of memory, or an error code.
950*86d7f5d3SJohn Marino */
951*86d7f5d3SJohn Marino int
buf_read_data(struct buffer * buf,size_t want,char ** retdata,size_t * got)952*86d7f5d3SJohn Marino buf_read_data (struct buffer *buf, size_t want, char **retdata, size_t *got)
953*86d7f5d3SJohn Marino {
954*86d7f5d3SJohn Marino assert (buf->input != NULL);
955*86d7f5d3SJohn Marino
956*86d7f5d3SJohn Marino while (buf->data != NULL && buf->data->size == 0)
957*86d7f5d3SJohn Marino {
958*86d7f5d3SJohn Marino struct buffer_data *next;
959*86d7f5d3SJohn Marino
960*86d7f5d3SJohn Marino next = buf->data->next;
961*86d7f5d3SJohn Marino buf_free_datas (buf->data, buf->data);
962*86d7f5d3SJohn Marino buf->data = next;
963*86d7f5d3SJohn Marino if (next == NULL)
964*86d7f5d3SJohn Marino buf->last = NULL;
965*86d7f5d3SJohn Marino }
966*86d7f5d3SJohn Marino
967*86d7f5d3SJohn Marino if (buf->data == NULL)
968*86d7f5d3SJohn Marino {
969*86d7f5d3SJohn Marino struct buffer_data *data;
970*86d7f5d3SJohn Marino int status;
971*86d7f5d3SJohn Marino size_t get, nbytes;
972*86d7f5d3SJohn Marino
973*86d7f5d3SJohn Marino data = get_buffer_data ();
974*86d7f5d3SJohn Marino if (data == NULL)
975*86d7f5d3SJohn Marino {
976*86d7f5d3SJohn Marino (*buf->memory_error) (buf);
977*86d7f5d3SJohn Marino return -2;
978*86d7f5d3SJohn Marino }
979*86d7f5d3SJohn Marino
980*86d7f5d3SJohn Marino buf->data = data;
981*86d7f5d3SJohn Marino buf->last = data;
982*86d7f5d3SJohn Marino data->next = NULL;
983*86d7f5d3SJohn Marino data->bufp = data->text;
984*86d7f5d3SJohn Marino data->size = 0;
985*86d7f5d3SJohn Marino
986*86d7f5d3SJohn Marino if (want < BUFFER_DATA_SIZE)
987*86d7f5d3SJohn Marino get = want;
988*86d7f5d3SJohn Marino else
989*86d7f5d3SJohn Marino get = BUFFER_DATA_SIZE;
990*86d7f5d3SJohn Marino status = (*buf->input) (buf->closure, data->bufp, get,
991*86d7f5d3SJohn Marino BUFFER_DATA_SIZE, &nbytes);
992*86d7f5d3SJohn Marino if (status != 0)
993*86d7f5d3SJohn Marino return status;
994*86d7f5d3SJohn Marino
995*86d7f5d3SJohn Marino data->size = nbytes;
996*86d7f5d3SJohn Marino }
997*86d7f5d3SJohn Marino
998*86d7f5d3SJohn Marino *retdata = buf->data->bufp;
999*86d7f5d3SJohn Marino if (want < buf->data->size)
1000*86d7f5d3SJohn Marino {
1001*86d7f5d3SJohn Marino *got = want;
1002*86d7f5d3SJohn Marino buf->data->size -= want;
1003*86d7f5d3SJohn Marino buf->data->bufp += want;
1004*86d7f5d3SJohn Marino }
1005*86d7f5d3SJohn Marino else
1006*86d7f5d3SJohn Marino {
1007*86d7f5d3SJohn Marino *got = buf->data->size;
1008*86d7f5d3SJohn Marino buf->data->size = 0;
1009*86d7f5d3SJohn Marino }
1010*86d7f5d3SJohn Marino
1011*86d7f5d3SJohn Marino return 0;
1012*86d7f5d3SJohn Marino }
1013*86d7f5d3SJohn Marino
1014*86d7f5d3SJohn Marino
1015*86d7f5d3SJohn Marino
1016*86d7f5d3SJohn Marino /*
1017*86d7f5d3SJohn Marino * Copy lines from an input buffer to an output buffer.
1018*86d7f5d3SJohn Marino * This copies all complete lines (characters up to a
1019*86d7f5d3SJohn Marino * newline) from INBUF to OUTBUF. Each line in OUTBUF is preceded by the
1020*86d7f5d3SJohn Marino * character COMMAND and a space.
1021*86d7f5d3SJohn Marino */
1022*86d7f5d3SJohn Marino void
buf_copy_lines(struct buffer * outbuf,struct buffer * inbuf,int command)1023*86d7f5d3SJohn Marino buf_copy_lines (struct buffer *outbuf, struct buffer *inbuf, int command)
1024*86d7f5d3SJohn Marino {
1025*86d7f5d3SJohn Marino while (1)
1026*86d7f5d3SJohn Marino {
1027*86d7f5d3SJohn Marino struct buffer_data *data;
1028*86d7f5d3SJohn Marino struct buffer_data *nldata;
1029*86d7f5d3SJohn Marino char *nl;
1030*86d7f5d3SJohn Marino int len;
1031*86d7f5d3SJohn Marino
1032*86d7f5d3SJohn Marino /* See if there is a newline in INBUF. */
1033*86d7f5d3SJohn Marino nldata = NULL;
1034*86d7f5d3SJohn Marino nl = NULL;
1035*86d7f5d3SJohn Marino for (data = inbuf->data; data != NULL; data = data->next)
1036*86d7f5d3SJohn Marino {
1037*86d7f5d3SJohn Marino nl = memchr (data->bufp, '\n', data->size);
1038*86d7f5d3SJohn Marino if (nl != NULL)
1039*86d7f5d3SJohn Marino {
1040*86d7f5d3SJohn Marino nldata = data;
1041*86d7f5d3SJohn Marino break;
1042*86d7f5d3SJohn Marino }
1043*86d7f5d3SJohn Marino }
1044*86d7f5d3SJohn Marino
1045*86d7f5d3SJohn Marino if (nldata == NULL)
1046*86d7f5d3SJohn Marino {
1047*86d7f5d3SJohn Marino /* There are no more lines in INBUF. */
1048*86d7f5d3SJohn Marino return;
1049*86d7f5d3SJohn Marino }
1050*86d7f5d3SJohn Marino
1051*86d7f5d3SJohn Marino /* Put in the command. */
1052*86d7f5d3SJohn Marino buf_append_char (outbuf, command);
1053*86d7f5d3SJohn Marino buf_append_char (outbuf, ' ');
1054*86d7f5d3SJohn Marino
1055*86d7f5d3SJohn Marino if (inbuf->data != nldata)
1056*86d7f5d3SJohn Marino {
1057*86d7f5d3SJohn Marino /*
1058*86d7f5d3SJohn Marino * Simply move over all the buffers up to the one containing
1059*86d7f5d3SJohn Marino * the newline.
1060*86d7f5d3SJohn Marino */
1061*86d7f5d3SJohn Marino for (data = inbuf->data; data->next != nldata; data = data->next);
1062*86d7f5d3SJohn Marino data->next = NULL;
1063*86d7f5d3SJohn Marino buf_append_data (outbuf, inbuf->data, data);
1064*86d7f5d3SJohn Marino inbuf->data = nldata;
1065*86d7f5d3SJohn Marino }
1066*86d7f5d3SJohn Marino
1067*86d7f5d3SJohn Marino /*
1068*86d7f5d3SJohn Marino * If the newline is at the very end of the buffer, just move
1069*86d7f5d3SJohn Marino * the buffer onto OUTBUF. Otherwise we must copy the data.
1070*86d7f5d3SJohn Marino */
1071*86d7f5d3SJohn Marino len = nl + 1 - nldata->bufp;
1072*86d7f5d3SJohn Marino if (len == nldata->size)
1073*86d7f5d3SJohn Marino {
1074*86d7f5d3SJohn Marino inbuf->data = nldata->next;
1075*86d7f5d3SJohn Marino if (inbuf->data == NULL)
1076*86d7f5d3SJohn Marino inbuf->last = NULL;
1077*86d7f5d3SJohn Marino
1078*86d7f5d3SJohn Marino nldata->next = NULL;
1079*86d7f5d3SJohn Marino buf_append_data (outbuf, nldata, nldata);
1080*86d7f5d3SJohn Marino }
1081*86d7f5d3SJohn Marino else
1082*86d7f5d3SJohn Marino {
1083*86d7f5d3SJohn Marino buf_output (outbuf, nldata->bufp, len);
1084*86d7f5d3SJohn Marino nldata->bufp += len;
1085*86d7f5d3SJohn Marino nldata->size -= len;
1086*86d7f5d3SJohn Marino }
1087*86d7f5d3SJohn Marino }
1088*86d7f5d3SJohn Marino }
1089*86d7f5d3SJohn Marino
1090*86d7f5d3SJohn Marino
1091*86d7f5d3SJohn Marino
1092*86d7f5d3SJohn Marino /*
1093*86d7f5d3SJohn Marino * Copy counted data from one buffer to another. The count is an
1094*86d7f5d3SJohn Marino * integer, host size, host byte order (it is only used across a
1095*86d7f5d3SJohn Marino * pipe). If there is enough data, it should be moved over. If there
1096*86d7f5d3SJohn Marino * is not enough data, it should remain on the original buffer. A
1097*86d7f5d3SJohn Marino * negative count is a special case. if one is seen, *SPECIAL is set
1098*86d7f5d3SJohn Marino * to the (negative) count value and no additional data is gathered
1099*86d7f5d3SJohn Marino * from the buffer; normally *SPECIAL is set to 0. This function
1100*86d7f5d3SJohn Marino * returns the number of bytes it needs to see in order to actually
1101*86d7f5d3SJohn Marino * copy something over.
1102*86d7f5d3SJohn Marino */
1103*86d7f5d3SJohn Marino int
buf_copy_counted(struct buffer * outbuf,struct buffer * inbuf,int * special)1104*86d7f5d3SJohn Marino buf_copy_counted (struct buffer *outbuf, struct buffer *inbuf, int *special)
1105*86d7f5d3SJohn Marino {
1106*86d7f5d3SJohn Marino *special = 0;
1107*86d7f5d3SJohn Marino
1108*86d7f5d3SJohn Marino while (1)
1109*86d7f5d3SJohn Marino {
1110*86d7f5d3SJohn Marino struct buffer_data *data;
1111*86d7f5d3SJohn Marino int need;
1112*86d7f5d3SJohn Marino union
1113*86d7f5d3SJohn Marino {
1114*86d7f5d3SJohn Marino char intbuf[sizeof (int)];
1115*86d7f5d3SJohn Marino int i;
1116*86d7f5d3SJohn Marino } u;
1117*86d7f5d3SJohn Marino char *intp;
1118*86d7f5d3SJohn Marino int count;
1119*86d7f5d3SJohn Marino struct buffer_data *start;
1120*86d7f5d3SJohn Marino int startoff;
1121*86d7f5d3SJohn Marino struct buffer_data *stop;
1122*86d7f5d3SJohn Marino int stopwant;
1123*86d7f5d3SJohn Marino
1124*86d7f5d3SJohn Marino /* See if we have enough bytes to figure out the count. */
1125*86d7f5d3SJohn Marino need = sizeof (int);
1126*86d7f5d3SJohn Marino intp = u.intbuf;
1127*86d7f5d3SJohn Marino for (data = inbuf->data; data != NULL; data = data->next)
1128*86d7f5d3SJohn Marino {
1129*86d7f5d3SJohn Marino if (data->size >= need)
1130*86d7f5d3SJohn Marino {
1131*86d7f5d3SJohn Marino memcpy (intp, data->bufp, need);
1132*86d7f5d3SJohn Marino break;
1133*86d7f5d3SJohn Marino }
1134*86d7f5d3SJohn Marino memcpy (intp, data->bufp, data->size);
1135*86d7f5d3SJohn Marino intp += data->size;
1136*86d7f5d3SJohn Marino need -= data->size;
1137*86d7f5d3SJohn Marino }
1138*86d7f5d3SJohn Marino if (data == NULL)
1139*86d7f5d3SJohn Marino {
1140*86d7f5d3SJohn Marino /* We don't have enough bytes to form an integer. */
1141*86d7f5d3SJohn Marino return need;
1142*86d7f5d3SJohn Marino }
1143*86d7f5d3SJohn Marino
1144*86d7f5d3SJohn Marino count = u.i;
1145*86d7f5d3SJohn Marino start = data;
1146*86d7f5d3SJohn Marino startoff = need;
1147*86d7f5d3SJohn Marino
1148*86d7f5d3SJohn Marino if (count < 0)
1149*86d7f5d3SJohn Marino {
1150*86d7f5d3SJohn Marino /* A negative COUNT is a special case meaning that we
1151*86d7f5d3SJohn Marino don't need any further information. */
1152*86d7f5d3SJohn Marino stop = start;
1153*86d7f5d3SJohn Marino stopwant = 0;
1154*86d7f5d3SJohn Marino }
1155*86d7f5d3SJohn Marino else
1156*86d7f5d3SJohn Marino {
1157*86d7f5d3SJohn Marino /*
1158*86d7f5d3SJohn Marino * We have an integer in COUNT. We have gotten all the
1159*86d7f5d3SJohn Marino * data from INBUF in all buffers before START, and we
1160*86d7f5d3SJohn Marino * have gotten STARTOFF bytes from START. See if we have
1161*86d7f5d3SJohn Marino * enough bytes remaining in INBUF.
1162*86d7f5d3SJohn Marino */
1163*86d7f5d3SJohn Marino need = count - (start->size - startoff);
1164*86d7f5d3SJohn Marino if (need <= 0)
1165*86d7f5d3SJohn Marino {
1166*86d7f5d3SJohn Marino stop = start;
1167*86d7f5d3SJohn Marino stopwant = count;
1168*86d7f5d3SJohn Marino }
1169*86d7f5d3SJohn Marino else
1170*86d7f5d3SJohn Marino {
1171*86d7f5d3SJohn Marino for (data = start->next; data != NULL; data = data->next)
1172*86d7f5d3SJohn Marino {
1173*86d7f5d3SJohn Marino if (need <= data->size)
1174*86d7f5d3SJohn Marino break;
1175*86d7f5d3SJohn Marino need -= data->size;
1176*86d7f5d3SJohn Marino }
1177*86d7f5d3SJohn Marino if (data == NULL)
1178*86d7f5d3SJohn Marino {
1179*86d7f5d3SJohn Marino /* We don't have enough bytes. */
1180*86d7f5d3SJohn Marino return need;
1181*86d7f5d3SJohn Marino }
1182*86d7f5d3SJohn Marino stop = data;
1183*86d7f5d3SJohn Marino stopwant = need;
1184*86d7f5d3SJohn Marino }
1185*86d7f5d3SJohn Marino }
1186*86d7f5d3SJohn Marino
1187*86d7f5d3SJohn Marino /*
1188*86d7f5d3SJohn Marino * We have enough bytes. Free any buffers in INBUF before
1189*86d7f5d3SJohn Marino * START, and remove STARTOFF bytes from START, so that we can
1190*86d7f5d3SJohn Marino * forget about STARTOFF.
1191*86d7f5d3SJohn Marino */
1192*86d7f5d3SJohn Marino start->bufp += startoff;
1193*86d7f5d3SJohn Marino start->size -= startoff;
1194*86d7f5d3SJohn Marino
1195*86d7f5d3SJohn Marino if (start->size == 0)
1196*86d7f5d3SJohn Marino start = start->next;
1197*86d7f5d3SJohn Marino
1198*86d7f5d3SJohn Marino if (stop->size == stopwant)
1199*86d7f5d3SJohn Marino {
1200*86d7f5d3SJohn Marino stop = stop->next;
1201*86d7f5d3SJohn Marino stopwant = 0;
1202*86d7f5d3SJohn Marino }
1203*86d7f5d3SJohn Marino
1204*86d7f5d3SJohn Marino while (inbuf->data != start)
1205*86d7f5d3SJohn Marino {
1206*86d7f5d3SJohn Marino data = inbuf->data;
1207*86d7f5d3SJohn Marino inbuf->data = data->next;
1208*86d7f5d3SJohn Marino buf_free_datas (data, data);
1209*86d7f5d3SJohn Marino }
1210*86d7f5d3SJohn Marino
1211*86d7f5d3SJohn Marino /* If COUNT is negative, set *SPECIAL and get out now. */
1212*86d7f5d3SJohn Marino if (count < 0)
1213*86d7f5d3SJohn Marino {
1214*86d7f5d3SJohn Marino *special = count;
1215*86d7f5d3SJohn Marino return 0;
1216*86d7f5d3SJohn Marino }
1217*86d7f5d3SJohn Marino
1218*86d7f5d3SJohn Marino /*
1219*86d7f5d3SJohn Marino * We want to copy over the bytes from START through STOP. We
1220*86d7f5d3SJohn Marino * only want STOPWANT bytes from STOP.
1221*86d7f5d3SJohn Marino */
1222*86d7f5d3SJohn Marino
1223*86d7f5d3SJohn Marino if (start != stop)
1224*86d7f5d3SJohn Marino {
1225*86d7f5d3SJohn Marino /* Attach the buffers from START through STOP to OUTBUF. */
1226*86d7f5d3SJohn Marino for (data = start; data->next != stop; data = data->next);
1227*86d7f5d3SJohn Marino inbuf->data = stop;
1228*86d7f5d3SJohn Marino data->next = NULL;
1229*86d7f5d3SJohn Marino buf_append_data (outbuf, start, data);
1230*86d7f5d3SJohn Marino }
1231*86d7f5d3SJohn Marino
1232*86d7f5d3SJohn Marino if (stopwant > 0)
1233*86d7f5d3SJohn Marino {
1234*86d7f5d3SJohn Marino buf_output (outbuf, stop->bufp, stopwant);
1235*86d7f5d3SJohn Marino stop->bufp += stopwant;
1236*86d7f5d3SJohn Marino stop->size -= stopwant;
1237*86d7f5d3SJohn Marino }
1238*86d7f5d3SJohn Marino }
1239*86d7f5d3SJohn Marino
1240*86d7f5d3SJohn Marino /*NOTREACHED*/
1241*86d7f5d3SJohn Marino }
1242*86d7f5d3SJohn Marino
1243*86d7f5d3SJohn Marino
1244*86d7f5d3SJohn Marino
1245*86d7f5d3SJohn Marino int
buf_get_fd(struct buffer * buf)1246*86d7f5d3SJohn Marino buf_get_fd (struct buffer *buf)
1247*86d7f5d3SJohn Marino {
1248*86d7f5d3SJohn Marino if (buf->get_fd)
1249*86d7f5d3SJohn Marino return (*buf->get_fd) (buf->closure);
1250*86d7f5d3SJohn Marino return -1;
1251*86d7f5d3SJohn Marino }
1252*86d7f5d3SJohn Marino
1253*86d7f5d3SJohn Marino
1254*86d7f5d3SJohn Marino
1255*86d7f5d3SJohn Marino /* Shut down a buffer. This returns 0 on success, or an errno code. */
1256*86d7f5d3SJohn Marino int
buf_shutdown(struct buffer * buf)1257*86d7f5d3SJohn Marino buf_shutdown (struct buffer *buf)
1258*86d7f5d3SJohn Marino {
1259*86d7f5d3SJohn Marino if (buf->shutdown) return (*buf->shutdown) (buf);
1260*86d7f5d3SJohn Marino return 0;
1261*86d7f5d3SJohn Marino }
1262*86d7f5d3SJohn Marino
1263*86d7f5d3SJohn Marino
1264*86d7f5d3SJohn Marino
1265*86d7f5d3SJohn Marino /* Certain types of communication input and output data in packets,
1266*86d7f5d3SJohn Marino where each packet is translated in some fashion. The packetizing
1267*86d7f5d3SJohn Marino buffer type supports that, given a buffer which handles lower level
1268*86d7f5d3SJohn Marino I/O and a routine to translate the data in a packet.
1269*86d7f5d3SJohn Marino
1270*86d7f5d3SJohn Marino This code uses two bytes for the size of a packet, so packets are
1271*86d7f5d3SJohn Marino restricted to 65536 bytes in total.
1272*86d7f5d3SJohn Marino
1273*86d7f5d3SJohn Marino The translation functions should just translate; they may not
1274*86d7f5d3SJohn Marino significantly increase or decrease the amount of data. The actual
1275*86d7f5d3SJohn Marino size of the initial data is part of the translated data. The
1276*86d7f5d3SJohn Marino output translation routine may add up to PACKET_SLOP additional
1277*86d7f5d3SJohn Marino bytes, and the input translation routine should shrink the data
1278*86d7f5d3SJohn Marino correspondingly. */
1279*86d7f5d3SJohn Marino
1280*86d7f5d3SJohn Marino # define PACKET_SLOP (100)
1281*86d7f5d3SJohn Marino
1282*86d7f5d3SJohn Marino /* This structure is the closure field of a packetizing buffer. */
1283*86d7f5d3SJohn Marino
1284*86d7f5d3SJohn Marino struct packetizing_buffer
1285*86d7f5d3SJohn Marino {
1286*86d7f5d3SJohn Marino /* The underlying buffer. */
1287*86d7f5d3SJohn Marino struct buffer *buf;
1288*86d7f5d3SJohn Marino /* The input translation function. Exactly one of inpfn and outfn
1289*86d7f5d3SJohn Marino will be NULL. The input translation function should
1290*86d7f5d3SJohn Marino untranslate the data in INPUT, storing the result in OUTPUT.
1291*86d7f5d3SJohn Marino SIZE is the amount of data in INPUT, and is also the size of
1292*86d7f5d3SJohn Marino OUTPUT. This should return 0 on success, or an errno code. */
1293*86d7f5d3SJohn Marino int (*inpfn) (void *fnclosure, const char *input, char *output,
1294*86d7f5d3SJohn Marino size_t size);
1295*86d7f5d3SJohn Marino /* The output translation function. This should translate the
1296*86d7f5d3SJohn Marino data in INPUT, storing the result in OUTPUT. The first two
1297*86d7f5d3SJohn Marino bytes in INPUT will be the size of the data, and so will SIZE.
1298*86d7f5d3SJohn Marino This should set *TRANSLATED to the amount of translated data in
1299*86d7f5d3SJohn Marino OUTPUT. OUTPUT is large enough to hold SIZE + PACKET_SLOP
1300*86d7f5d3SJohn Marino bytes. This should return 0 on success, or an errno code. */
1301*86d7f5d3SJohn Marino int (*outfn) (void *fnclosure, const char *input, char *output,
1302*86d7f5d3SJohn Marino size_t size, size_t *translated);
1303*86d7f5d3SJohn Marino /* A closure for the translation function. */
1304*86d7f5d3SJohn Marino void *fnclosure;
1305*86d7f5d3SJohn Marino /* For an input buffer, we may have to buffer up data here. */
1306*86d7f5d3SJohn Marino /* This is non-zero if the buffered data has been translated.
1307*86d7f5d3SJohn Marino Otherwise, the buffered data has not been translated, and starts
1308*86d7f5d3SJohn Marino with the two byte packet size. */
1309*86d7f5d3SJohn Marino bool translated;
1310*86d7f5d3SJohn Marino /* The amount of buffered data. */
1311*86d7f5d3SJohn Marino size_t holdsize;
1312*86d7f5d3SJohn Marino /* The buffer allocated to hold the data. */
1313*86d7f5d3SJohn Marino char *holdbuf;
1314*86d7f5d3SJohn Marino /* The size of holdbuf. */
1315*86d7f5d3SJohn Marino size_t holdbufsize;
1316*86d7f5d3SJohn Marino /* If translated is set, we need another data pointer to track
1317*86d7f5d3SJohn Marino where we are in holdbuf. If translated is clear, then this
1318*86d7f5d3SJohn Marino pointer is not used. */
1319*86d7f5d3SJohn Marino char *holddata;
1320*86d7f5d3SJohn Marino };
1321*86d7f5d3SJohn Marino
1322*86d7f5d3SJohn Marino
1323*86d7f5d3SJohn Marino
1324*86d7f5d3SJohn Marino static int packetizing_buffer_input (void *, char *, size_t, size_t, size_t *);
1325*86d7f5d3SJohn Marino static int packetizing_buffer_output (void *, const char *, size_t, size_t *);
1326*86d7f5d3SJohn Marino static int packetizing_buffer_flush (void *);
1327*86d7f5d3SJohn Marino static int packetizing_buffer_block (void *, bool);
1328*86d7f5d3SJohn Marino static int packetizing_buffer_get_fd (void *);
1329*86d7f5d3SJohn Marino static int packetizing_buffer_shutdown (struct buffer *);
1330*86d7f5d3SJohn Marino
1331*86d7f5d3SJohn Marino
1332*86d7f5d3SJohn Marino
1333*86d7f5d3SJohn Marino /* Create a packetizing buffer. */
1334*86d7f5d3SJohn Marino struct buffer *
packetizing_buffer_initialize(struct buffer * buf,int (* inpfn)(void *,const char *,char *,size_t),int (* outfn)(void *,const char *,char *,size_t,size_t *),void * fnclosure,void (* memory)(struct buffer *))1335*86d7f5d3SJohn Marino packetizing_buffer_initialize (struct buffer *buf,
1336*86d7f5d3SJohn Marino int (*inpfn) (void *, const char *, char *,
1337*86d7f5d3SJohn Marino size_t),
1338*86d7f5d3SJohn Marino int (*outfn) (void *, const char *, char *,
1339*86d7f5d3SJohn Marino size_t, size_t *),
1340*86d7f5d3SJohn Marino void *fnclosure,
1341*86d7f5d3SJohn Marino void (*memory) (struct buffer *))
1342*86d7f5d3SJohn Marino {
1343*86d7f5d3SJohn Marino struct packetizing_buffer *pb;
1344*86d7f5d3SJohn Marino
1345*86d7f5d3SJohn Marino pb = xmalloc (sizeof *pb);
1346*86d7f5d3SJohn Marino memset (pb, 0, sizeof *pb);
1347*86d7f5d3SJohn Marino
1348*86d7f5d3SJohn Marino pb->buf = buf;
1349*86d7f5d3SJohn Marino pb->inpfn = inpfn;
1350*86d7f5d3SJohn Marino pb->outfn = outfn;
1351*86d7f5d3SJohn Marino pb->fnclosure = fnclosure;
1352*86d7f5d3SJohn Marino
1353*86d7f5d3SJohn Marino if (inpfn != NULL)
1354*86d7f5d3SJohn Marino {
1355*86d7f5d3SJohn Marino /* Add PACKET_SLOP to handle larger translated packets, and
1356*86d7f5d3SJohn Marino add 2 for the count. This buffer is increased if
1357*86d7f5d3SJohn Marino necessary. */
1358*86d7f5d3SJohn Marino pb->holdbufsize = BUFFER_DATA_SIZE + PACKET_SLOP + 2;
1359*86d7f5d3SJohn Marino pb->holdbuf = xmalloc (pb->holdbufsize);
1360*86d7f5d3SJohn Marino }
1361*86d7f5d3SJohn Marino
1362*86d7f5d3SJohn Marino return buf_initialize (inpfn != NULL ? packetizing_buffer_input : NULL,
1363*86d7f5d3SJohn Marino inpfn != NULL ? NULL : packetizing_buffer_output,
1364*86d7f5d3SJohn Marino inpfn != NULL ? NULL : packetizing_buffer_flush,
1365*86d7f5d3SJohn Marino packetizing_buffer_block,
1366*86d7f5d3SJohn Marino packetizing_buffer_get_fd,
1367*86d7f5d3SJohn Marino packetizing_buffer_shutdown,
1368*86d7f5d3SJohn Marino memory,
1369*86d7f5d3SJohn Marino pb);
1370*86d7f5d3SJohn Marino }
1371*86d7f5d3SJohn Marino
1372*86d7f5d3SJohn Marino
1373*86d7f5d3SJohn Marino
1374*86d7f5d3SJohn Marino /* Input data from a packetizing buffer. */
1375*86d7f5d3SJohn Marino static int
packetizing_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)1376*86d7f5d3SJohn Marino packetizing_buffer_input (void *closure, char *data, size_t need, size_t size,
1377*86d7f5d3SJohn Marino size_t *got)
1378*86d7f5d3SJohn Marino {
1379*86d7f5d3SJohn Marino struct packetizing_buffer *pb = closure;
1380*86d7f5d3SJohn Marino
1381*86d7f5d3SJohn Marino *got = 0;
1382*86d7f5d3SJohn Marino
1383*86d7f5d3SJohn Marino if (pb->holdsize > 0 && pb->translated)
1384*86d7f5d3SJohn Marino {
1385*86d7f5d3SJohn Marino size_t copy;
1386*86d7f5d3SJohn Marino
1387*86d7f5d3SJohn Marino copy = pb->holdsize;
1388*86d7f5d3SJohn Marino
1389*86d7f5d3SJohn Marino if (copy > size)
1390*86d7f5d3SJohn Marino {
1391*86d7f5d3SJohn Marino memcpy (data, pb->holddata, size);
1392*86d7f5d3SJohn Marino pb->holdsize -= size;
1393*86d7f5d3SJohn Marino pb->holddata += size;
1394*86d7f5d3SJohn Marino *got = size;
1395*86d7f5d3SJohn Marino return 0;
1396*86d7f5d3SJohn Marino }
1397*86d7f5d3SJohn Marino
1398*86d7f5d3SJohn Marino memcpy (data, pb->holddata, copy);
1399*86d7f5d3SJohn Marino pb->holdsize = 0;
1400*86d7f5d3SJohn Marino pb->translated = false;
1401*86d7f5d3SJohn Marino
1402*86d7f5d3SJohn Marino data += copy;
1403*86d7f5d3SJohn Marino need -= copy;
1404*86d7f5d3SJohn Marino size -= copy;
1405*86d7f5d3SJohn Marino *got = copy;
1406*86d7f5d3SJohn Marino }
1407*86d7f5d3SJohn Marino
1408*86d7f5d3SJohn Marino while (need > 0 || *got == 0)
1409*86d7f5d3SJohn Marino {
1410*86d7f5d3SJohn Marino int status;
1411*86d7f5d3SJohn Marino size_t get, nread, count, tcount;
1412*86d7f5d3SJohn Marino char *bytes;
1413*86d7f5d3SJohn Marino static char *stackoutbuf = NULL;
1414*86d7f5d3SJohn Marino char *inbuf, *outbuf;
1415*86d7f5d3SJohn Marino
1416*86d7f5d3SJohn Marino if (!stackoutbuf)
1417*86d7f5d3SJohn Marino stackoutbuf = xmalloc (BUFFER_DATA_SIZE + PACKET_SLOP);
1418*86d7f5d3SJohn Marino
1419*86d7f5d3SJohn Marino /* If we don't already have the two byte count, get it. */
1420*86d7f5d3SJohn Marino if (pb->holdsize < 2)
1421*86d7f5d3SJohn Marino {
1422*86d7f5d3SJohn Marino get = 2 - pb->holdsize;
1423*86d7f5d3SJohn Marino status = buf_read_data (pb->buf, get, &bytes, &nread);
1424*86d7f5d3SJohn Marino if (status != 0)
1425*86d7f5d3SJohn Marino {
1426*86d7f5d3SJohn Marino /* buf_read_data can return -2, but a buffer input
1427*86d7f5d3SJohn Marino function is only supposed to return -1, 0, or an
1428*86d7f5d3SJohn Marino error code. */
1429*86d7f5d3SJohn Marino if (status == -2)
1430*86d7f5d3SJohn Marino status = ENOMEM;
1431*86d7f5d3SJohn Marino return status;
1432*86d7f5d3SJohn Marino }
1433*86d7f5d3SJohn Marino
1434*86d7f5d3SJohn Marino if (nread == 0)
1435*86d7f5d3SJohn Marino {
1436*86d7f5d3SJohn Marino /* The buffer is in nonblocking mode, and we didn't
1437*86d7f5d3SJohn Marino manage to read anything. */
1438*86d7f5d3SJohn Marino return 0;
1439*86d7f5d3SJohn Marino }
1440*86d7f5d3SJohn Marino
1441*86d7f5d3SJohn Marino if (get == 1)
1442*86d7f5d3SJohn Marino pb->holdbuf[1] = bytes[0];
1443*86d7f5d3SJohn Marino else
1444*86d7f5d3SJohn Marino {
1445*86d7f5d3SJohn Marino pb->holdbuf[0] = bytes[0];
1446*86d7f5d3SJohn Marino if (nread < 2)
1447*86d7f5d3SJohn Marino {
1448*86d7f5d3SJohn Marino /* We only got one byte, but we needed two. Stash
1449*86d7f5d3SJohn Marino the byte we got, and try again. */
1450*86d7f5d3SJohn Marino pb->holdsize = 1;
1451*86d7f5d3SJohn Marino continue;
1452*86d7f5d3SJohn Marino }
1453*86d7f5d3SJohn Marino pb->holdbuf[1] = bytes[1];
1454*86d7f5d3SJohn Marino }
1455*86d7f5d3SJohn Marino pb->holdsize = 2;
1456*86d7f5d3SJohn Marino }
1457*86d7f5d3SJohn Marino
1458*86d7f5d3SJohn Marino /* Read the packet. */
1459*86d7f5d3SJohn Marino
1460*86d7f5d3SJohn Marino count = (((pb->holdbuf[0] & 0xff) << 8)
1461*86d7f5d3SJohn Marino + (pb->holdbuf[1] & 0xff));
1462*86d7f5d3SJohn Marino
1463*86d7f5d3SJohn Marino if (count + 2 > pb->holdbufsize)
1464*86d7f5d3SJohn Marino {
1465*86d7f5d3SJohn Marino char *n;
1466*86d7f5d3SJohn Marino
1467*86d7f5d3SJohn Marino /* We didn't allocate enough space in the initialize
1468*86d7f5d3SJohn Marino function. */
1469*86d7f5d3SJohn Marino
1470*86d7f5d3SJohn Marino n = xrealloc (pb->holdbuf, count + 2);
1471*86d7f5d3SJohn Marino if (n == NULL)
1472*86d7f5d3SJohn Marino {
1473*86d7f5d3SJohn Marino (*pb->buf->memory_error) (pb->buf);
1474*86d7f5d3SJohn Marino return ENOMEM;
1475*86d7f5d3SJohn Marino }
1476*86d7f5d3SJohn Marino pb->holdbuf = n;
1477*86d7f5d3SJohn Marino pb->holdbufsize = count + 2;
1478*86d7f5d3SJohn Marino }
1479*86d7f5d3SJohn Marino
1480*86d7f5d3SJohn Marino get = count - (pb->holdsize - 2);
1481*86d7f5d3SJohn Marino
1482*86d7f5d3SJohn Marino status = buf_read_data (pb->buf, get, &bytes, &nread);
1483*86d7f5d3SJohn Marino if (status != 0)
1484*86d7f5d3SJohn Marino {
1485*86d7f5d3SJohn Marino /* buf_read_data can return -2, but a buffer input
1486*86d7f5d3SJohn Marino function is only supposed to return -1, 0, or an error
1487*86d7f5d3SJohn Marino code. */
1488*86d7f5d3SJohn Marino if (status == -2)
1489*86d7f5d3SJohn Marino status = ENOMEM;
1490*86d7f5d3SJohn Marino return status;
1491*86d7f5d3SJohn Marino }
1492*86d7f5d3SJohn Marino
1493*86d7f5d3SJohn Marino if (nread == 0)
1494*86d7f5d3SJohn Marino {
1495*86d7f5d3SJohn Marino /* We did not get any data. Presumably the buffer is in
1496*86d7f5d3SJohn Marino nonblocking mode. */
1497*86d7f5d3SJohn Marino return 0;
1498*86d7f5d3SJohn Marino }
1499*86d7f5d3SJohn Marino
1500*86d7f5d3SJohn Marino if (nread < get)
1501*86d7f5d3SJohn Marino {
1502*86d7f5d3SJohn Marino /* We did not get all the data we need to fill the packet.
1503*86d7f5d3SJohn Marino buf_read_data does not promise to return all the bytes
1504*86d7f5d3SJohn Marino requested, so we must try again. */
1505*86d7f5d3SJohn Marino memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
1506*86d7f5d3SJohn Marino pb->holdsize += nread;
1507*86d7f5d3SJohn Marino continue;
1508*86d7f5d3SJohn Marino }
1509*86d7f5d3SJohn Marino
1510*86d7f5d3SJohn Marino /* We have a complete untranslated packet of COUNT bytes. */
1511*86d7f5d3SJohn Marino
1512*86d7f5d3SJohn Marino if (pb->holdsize == 2)
1513*86d7f5d3SJohn Marino {
1514*86d7f5d3SJohn Marino /* We just read the entire packet (the 2 bytes in
1515*86d7f5d3SJohn Marino PB->HOLDBUF are the size). Save a memcpy by
1516*86d7f5d3SJohn Marino translating directly from BYTES. */
1517*86d7f5d3SJohn Marino inbuf = bytes;
1518*86d7f5d3SJohn Marino }
1519*86d7f5d3SJohn Marino else
1520*86d7f5d3SJohn Marino {
1521*86d7f5d3SJohn Marino /* We already had a partial packet in PB->HOLDBUF. We
1522*86d7f5d3SJohn Marino need to copy the new data over to make the input
1523*86d7f5d3SJohn Marino contiguous. */
1524*86d7f5d3SJohn Marino memcpy (pb->holdbuf + pb->holdsize, bytes, nread);
1525*86d7f5d3SJohn Marino inbuf = pb->holdbuf + 2;
1526*86d7f5d3SJohn Marino }
1527*86d7f5d3SJohn Marino
1528*86d7f5d3SJohn Marino if (count <= BUFFER_DATA_SIZE + PACKET_SLOP)
1529*86d7f5d3SJohn Marino outbuf = stackoutbuf;
1530*86d7f5d3SJohn Marino else
1531*86d7f5d3SJohn Marino {
1532*86d7f5d3SJohn Marino outbuf = xmalloc (count);
1533*86d7f5d3SJohn Marino if (outbuf == NULL)
1534*86d7f5d3SJohn Marino {
1535*86d7f5d3SJohn Marino (*pb->buf->memory_error) (pb->buf);
1536*86d7f5d3SJohn Marino return ENOMEM;
1537*86d7f5d3SJohn Marino }
1538*86d7f5d3SJohn Marino }
1539*86d7f5d3SJohn Marino
1540*86d7f5d3SJohn Marino status = (*pb->inpfn) (pb->fnclosure, inbuf, outbuf, count);
1541*86d7f5d3SJohn Marino if (status != 0)
1542*86d7f5d3SJohn Marino return status;
1543*86d7f5d3SJohn Marino
1544*86d7f5d3SJohn Marino /* The first two bytes in the translated buffer are the real
1545*86d7f5d3SJohn Marino length of the translated data. */
1546*86d7f5d3SJohn Marino tcount = ((outbuf[0] & 0xff) << 8) + (outbuf[1] & 0xff);
1547*86d7f5d3SJohn Marino
1548*86d7f5d3SJohn Marino if (tcount > count)
1549*86d7f5d3SJohn Marino error (1, 0, "Input translation failure");
1550*86d7f5d3SJohn Marino
1551*86d7f5d3SJohn Marino if (tcount > size)
1552*86d7f5d3SJohn Marino {
1553*86d7f5d3SJohn Marino /* We have more data than the caller has provided space
1554*86d7f5d3SJohn Marino for. We need to save some of it for the next call. */
1555*86d7f5d3SJohn Marino
1556*86d7f5d3SJohn Marino memcpy (data, outbuf + 2, size);
1557*86d7f5d3SJohn Marino *got += size;
1558*86d7f5d3SJohn Marino
1559*86d7f5d3SJohn Marino pb->holdsize = tcount - size;
1560*86d7f5d3SJohn Marino memcpy (pb->holdbuf, outbuf + 2 + size, tcount - size);
1561*86d7f5d3SJohn Marino pb->holddata = pb->holdbuf;
1562*86d7f5d3SJohn Marino pb->translated = true;
1563*86d7f5d3SJohn Marino
1564*86d7f5d3SJohn Marino if (outbuf != stackoutbuf)
1565*86d7f5d3SJohn Marino free (outbuf);
1566*86d7f5d3SJohn Marino
1567*86d7f5d3SJohn Marino return 0;
1568*86d7f5d3SJohn Marino }
1569*86d7f5d3SJohn Marino
1570*86d7f5d3SJohn Marino memcpy (data, outbuf + 2, tcount);
1571*86d7f5d3SJohn Marino
1572*86d7f5d3SJohn Marino if (outbuf != stackoutbuf)
1573*86d7f5d3SJohn Marino free (outbuf);
1574*86d7f5d3SJohn Marino
1575*86d7f5d3SJohn Marino pb->holdsize = 0;
1576*86d7f5d3SJohn Marino
1577*86d7f5d3SJohn Marino data += tcount;
1578*86d7f5d3SJohn Marino need -= tcount;
1579*86d7f5d3SJohn Marino size -= tcount;
1580*86d7f5d3SJohn Marino *got += tcount;
1581*86d7f5d3SJohn Marino }
1582*86d7f5d3SJohn Marino
1583*86d7f5d3SJohn Marino return 0;
1584*86d7f5d3SJohn Marino }
1585*86d7f5d3SJohn Marino
1586*86d7f5d3SJohn Marino
1587*86d7f5d3SJohn Marino
1588*86d7f5d3SJohn Marino /* Output data to a packetizing buffer. */
1589*86d7f5d3SJohn Marino static int
packetizing_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)1590*86d7f5d3SJohn Marino packetizing_buffer_output (void *closure, const char *data, size_t have,
1591*86d7f5d3SJohn Marino size_t *wrote)
1592*86d7f5d3SJohn Marino {
1593*86d7f5d3SJohn Marino struct packetizing_buffer *pb = closure;
1594*86d7f5d3SJohn Marino static char *inbuf = NULL; /* These two buffers are static so that they
1595*86d7f5d3SJohn Marino * depend on the size of BUFFER_DATA_SIZE yet
1596*86d7f5d3SJohn Marino * still only be allocated once per run.
1597*86d7f5d3SJohn Marino */
1598*86d7f5d3SJohn Marino static char *stack_outbuf = NULL;
1599*86d7f5d3SJohn Marino struct buffer_data *outdata = NULL; /* Initialize to silence -Wall. Dumb.
1600*86d7f5d3SJohn Marino */
1601*86d7f5d3SJohn Marino char *outbuf;
1602*86d7f5d3SJohn Marino size_t size, translated;
1603*86d7f5d3SJohn Marino int status;
1604*86d7f5d3SJohn Marino
1605*86d7f5d3SJohn Marino /* It would be easy to xmalloc a buffer, but I don't think this
1606*86d7f5d3SJohn Marino case can ever arise. */
1607*86d7f5d3SJohn Marino assert (have <= BUFFER_DATA_SIZE);
1608*86d7f5d3SJohn Marino
1609*86d7f5d3SJohn Marino if (!inbuf)
1610*86d7f5d3SJohn Marino {
1611*86d7f5d3SJohn Marino inbuf = xmalloc (BUFFER_DATA_SIZE + 2);
1612*86d7f5d3SJohn Marino stack_outbuf = xmalloc (BUFFER_DATA_SIZE + PACKET_SLOP + 4);
1613*86d7f5d3SJohn Marino }
1614*86d7f5d3SJohn Marino
1615*86d7f5d3SJohn Marino inbuf[0] = (have >> 8) & 0xff;
1616*86d7f5d3SJohn Marino inbuf[1] = have & 0xff;
1617*86d7f5d3SJohn Marino memcpy (inbuf + 2, data, have);
1618*86d7f5d3SJohn Marino
1619*86d7f5d3SJohn Marino size = have + 2;
1620*86d7f5d3SJohn Marino
1621*86d7f5d3SJohn Marino /* The output function is permitted to add up to PACKET_SLOP
1622*86d7f5d3SJohn Marino bytes, and we need 2 bytes for the size of the translated data.
1623*86d7f5d3SJohn Marino If we can guarantee that the result will fit in a buffer_data,
1624*86d7f5d3SJohn Marino we translate directly into one to avoid a memcpy in buf_output. */
1625*86d7f5d3SJohn Marino if (size + PACKET_SLOP + 2 > BUFFER_DATA_SIZE)
1626*86d7f5d3SJohn Marino outbuf = stack_outbuf;
1627*86d7f5d3SJohn Marino else
1628*86d7f5d3SJohn Marino {
1629*86d7f5d3SJohn Marino outdata = get_buffer_data ();
1630*86d7f5d3SJohn Marino if (outdata == NULL)
1631*86d7f5d3SJohn Marino {
1632*86d7f5d3SJohn Marino (*pb->buf->memory_error) (pb->buf);
1633*86d7f5d3SJohn Marino return ENOMEM;
1634*86d7f5d3SJohn Marino }
1635*86d7f5d3SJohn Marino
1636*86d7f5d3SJohn Marino outdata->next = NULL;
1637*86d7f5d3SJohn Marino outdata->bufp = outdata->text;
1638*86d7f5d3SJohn Marino
1639*86d7f5d3SJohn Marino outbuf = outdata->text;
1640*86d7f5d3SJohn Marino }
1641*86d7f5d3SJohn Marino
1642*86d7f5d3SJohn Marino status = (*pb->outfn) (pb->fnclosure, inbuf, outbuf + 2, size,
1643*86d7f5d3SJohn Marino &translated);
1644*86d7f5d3SJohn Marino if (status != 0)
1645*86d7f5d3SJohn Marino return status;
1646*86d7f5d3SJohn Marino
1647*86d7f5d3SJohn Marino /* The output function is permitted to add up to PACKET_SLOP
1648*86d7f5d3SJohn Marino bytes. */
1649*86d7f5d3SJohn Marino assert (translated <= size + PACKET_SLOP);
1650*86d7f5d3SJohn Marino
1651*86d7f5d3SJohn Marino outbuf[0] = (translated >> 8) & 0xff;
1652*86d7f5d3SJohn Marino outbuf[1] = translated & 0xff;
1653*86d7f5d3SJohn Marino
1654*86d7f5d3SJohn Marino if (outbuf == stack_outbuf)
1655*86d7f5d3SJohn Marino buf_output (pb->buf, outbuf, translated + 2);
1656*86d7f5d3SJohn Marino else
1657*86d7f5d3SJohn Marino {
1658*86d7f5d3SJohn Marino outdata->size = translated + 2;
1659*86d7f5d3SJohn Marino buf_append_data (pb->buf, outdata, outdata);
1660*86d7f5d3SJohn Marino }
1661*86d7f5d3SJohn Marino
1662*86d7f5d3SJohn Marino *wrote = have;
1663*86d7f5d3SJohn Marino
1664*86d7f5d3SJohn Marino /* We will only be here because buf_send_output was called on the
1665*86d7f5d3SJohn Marino packetizing buffer. That means that we should now call
1666*86d7f5d3SJohn Marino buf_send_output on the underlying buffer. */
1667*86d7f5d3SJohn Marino return buf_send_output (pb->buf);
1668*86d7f5d3SJohn Marino }
1669*86d7f5d3SJohn Marino
1670*86d7f5d3SJohn Marino
1671*86d7f5d3SJohn Marino
1672*86d7f5d3SJohn Marino /* Flush data to a packetizing buffer. */
1673*86d7f5d3SJohn Marino static int
packetizing_buffer_flush(void * closure)1674*86d7f5d3SJohn Marino packetizing_buffer_flush (void *closure)
1675*86d7f5d3SJohn Marino {
1676*86d7f5d3SJohn Marino struct packetizing_buffer *pb = closure;
1677*86d7f5d3SJohn Marino
1678*86d7f5d3SJohn Marino /* Flush the underlying buffer. Note that if the original call to
1679*86d7f5d3SJohn Marino buf_flush passed 1 for the BLOCK argument, then the buffer will
1680*86d7f5d3SJohn Marino already have been set into blocking mode, so we should always
1681*86d7f5d3SJohn Marino pass 0 here. */
1682*86d7f5d3SJohn Marino return buf_flush (pb->buf, 0);
1683*86d7f5d3SJohn Marino }
1684*86d7f5d3SJohn Marino
1685*86d7f5d3SJohn Marino
1686*86d7f5d3SJohn Marino
1687*86d7f5d3SJohn Marino /* The block routine for a packetizing buffer. */
1688*86d7f5d3SJohn Marino static int
packetizing_buffer_block(void * closure,bool block)1689*86d7f5d3SJohn Marino packetizing_buffer_block (void *closure, bool block)
1690*86d7f5d3SJohn Marino {
1691*86d7f5d3SJohn Marino struct packetizing_buffer *pb = closure;
1692*86d7f5d3SJohn Marino
1693*86d7f5d3SJohn Marino if (block)
1694*86d7f5d3SJohn Marino return set_block (pb->buf);
1695*86d7f5d3SJohn Marino else
1696*86d7f5d3SJohn Marino return set_nonblock (pb->buf);
1697*86d7f5d3SJohn Marino }
1698*86d7f5d3SJohn Marino
1699*86d7f5d3SJohn Marino
1700*86d7f5d3SJohn Marino
1701*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers. */
1702*86d7f5d3SJohn Marino static int
packetizing_buffer_get_fd(void * closure)1703*86d7f5d3SJohn Marino packetizing_buffer_get_fd (void *closure)
1704*86d7f5d3SJohn Marino {
1705*86d7f5d3SJohn Marino struct packetizing_buffer *cb = closure;
1706*86d7f5d3SJohn Marino return buf_get_fd (cb->buf);
1707*86d7f5d3SJohn Marino }
1708*86d7f5d3SJohn Marino
1709*86d7f5d3SJohn Marino
1710*86d7f5d3SJohn Marino
1711*86d7f5d3SJohn Marino /* Shut down a packetizing buffer. */
1712*86d7f5d3SJohn Marino static int
packetizing_buffer_shutdown(struct buffer * buf)1713*86d7f5d3SJohn Marino packetizing_buffer_shutdown (struct buffer *buf)
1714*86d7f5d3SJohn Marino {
1715*86d7f5d3SJohn Marino struct packetizing_buffer *pb = buf->closure;
1716*86d7f5d3SJohn Marino
1717*86d7f5d3SJohn Marino return buf_shutdown (pb->buf);
1718*86d7f5d3SJohn Marino }
1719*86d7f5d3SJohn Marino
1720*86d7f5d3SJohn Marino
1721*86d7f5d3SJohn Marino
1722*86d7f5d3SJohn Marino /* All server communication goes through buffer structures. Most of
1723*86d7f5d3SJohn Marino the buffers are built on top of a file descriptor. This structure
1724*86d7f5d3SJohn Marino is used as the closure field in a buffer. */
1725*86d7f5d3SJohn Marino
1726*86d7f5d3SJohn Marino struct fd_buffer
1727*86d7f5d3SJohn Marino {
1728*86d7f5d3SJohn Marino /* The file descriptor. */
1729*86d7f5d3SJohn Marino int fd;
1730*86d7f5d3SJohn Marino /* Nonzero if the file descriptor is in blocking mode. */
1731*86d7f5d3SJohn Marino int blocking;
1732*86d7f5d3SJohn Marino /* The child process id when fd is a pipe. */
1733*86d7f5d3SJohn Marino pid_t child_pid;
1734*86d7f5d3SJohn Marino /* The connection info, when fd is a pipe to a server. */
1735*86d7f5d3SJohn Marino cvsroot_t *root;
1736*86d7f5d3SJohn Marino };
1737*86d7f5d3SJohn Marino
1738*86d7f5d3SJohn Marino static int fd_buffer_input (void *, char *, size_t, size_t, size_t *);
1739*86d7f5d3SJohn Marino static int fd_buffer_output (void *, const char *, size_t, size_t *);
1740*86d7f5d3SJohn Marino static int fd_buffer_flush (void *);
1741*86d7f5d3SJohn Marino static int fd_buffer_block (void *, bool);
1742*86d7f5d3SJohn Marino static int fd_buffer_get_fd (void *);
1743*86d7f5d3SJohn Marino static int fd_buffer_shutdown (struct buffer *);
1744*86d7f5d3SJohn Marino
1745*86d7f5d3SJohn Marino /* Initialize a buffer built on a file descriptor. FD is the file
1746*86d7f5d3SJohn Marino descriptor. INPUT is nonzero if this is for input, zero if this is
1747*86d7f5d3SJohn Marino for output. MEMORY is the function to call when a memory error
1748*86d7f5d3SJohn Marino occurs. */
1749*86d7f5d3SJohn Marino
1750*86d7f5d3SJohn Marino struct buffer *
fd_buffer_initialize(int fd,pid_t child_pid,cvsroot_t * root,bool input,void (* memory)(struct buffer *))1751*86d7f5d3SJohn Marino fd_buffer_initialize (int fd, pid_t child_pid, cvsroot_t *root, bool input,
1752*86d7f5d3SJohn Marino void (*memory) (struct buffer *))
1753*86d7f5d3SJohn Marino {
1754*86d7f5d3SJohn Marino struct fd_buffer *n;
1755*86d7f5d3SJohn Marino
1756*86d7f5d3SJohn Marino n = xmalloc (sizeof *n);
1757*86d7f5d3SJohn Marino n->fd = fd;
1758*86d7f5d3SJohn Marino n->child_pid = child_pid;
1759*86d7f5d3SJohn Marino n->root = root;
1760*86d7f5d3SJohn Marino fd_buffer_block (n, true);
1761*86d7f5d3SJohn Marino return buf_initialize (input ? fd_buffer_input : NULL,
1762*86d7f5d3SJohn Marino input ? NULL : fd_buffer_output,
1763*86d7f5d3SJohn Marino input ? NULL : fd_buffer_flush,
1764*86d7f5d3SJohn Marino fd_buffer_block, fd_buffer_get_fd,
1765*86d7f5d3SJohn Marino fd_buffer_shutdown,
1766*86d7f5d3SJohn Marino memory,
1767*86d7f5d3SJohn Marino n);
1768*86d7f5d3SJohn Marino }
1769*86d7f5d3SJohn Marino
1770*86d7f5d3SJohn Marino
1771*86d7f5d3SJohn Marino
1772*86d7f5d3SJohn Marino /* The buffer input function for a buffer built on a file descriptor.
1773*86d7f5d3SJohn Marino *
1774*86d7f5d3SJohn Marino * In non-blocking mode, this function will read as many bytes as it can in a
1775*86d7f5d3SJohn Marino * single try, up to SIZE bytes, and return.
1776*86d7f5d3SJohn Marino *
1777*86d7f5d3SJohn Marino * In blocking mode with NEED > 0, this function will read as many bytes as it
1778*86d7f5d3SJohn Marino * can but will not return until it has read at least NEED bytes.
1779*86d7f5d3SJohn Marino *
1780*86d7f5d3SJohn Marino * In blocking mode with NEED == 0, this function will block until it can read
1781*86d7f5d3SJohn Marino * either at least one byte or EOF, then read as many bytes as are available
1782*86d7f5d3SJohn Marino * and return. At the very least, compress_buffer_shutdown depends on this
1783*86d7f5d3SJohn Marino * behavior to read EOF and can loop indefinitely without it.
1784*86d7f5d3SJohn Marino *
1785*86d7f5d3SJohn Marino * ASSUMPTIONS
1786*86d7f5d3SJohn Marino * NEED <= SIZE.
1787*86d7f5d3SJohn Marino *
1788*86d7f5d3SJohn Marino * INPUTS
1789*86d7f5d3SJohn Marino * closure Our FD_BUFFER struct.
1790*86d7f5d3SJohn Marino * data The start of our input buffer.
1791*86d7f5d3SJohn Marino * need How many bytes our caller needs.
1792*86d7f5d3SJohn Marino * size How many bytes are available in DATA.
1793*86d7f5d3SJohn Marino * got Where to store the number of bytes read.
1794*86d7f5d3SJohn Marino *
1795*86d7f5d3SJohn Marino * OUTPUTS
1796*86d7f5d3SJohn Marino * data Filled with bytes read.
1797*86d7f5d3SJohn Marino * *got Number of bytes actually read into DATA.
1798*86d7f5d3SJohn Marino *
1799*86d7f5d3SJohn Marino * RETURNS
1800*86d7f5d3SJohn Marino * errno On error.
1801*86d7f5d3SJohn Marino * -1 On EOF.
1802*86d7f5d3SJohn Marino * 0 Otherwise.
1803*86d7f5d3SJohn Marino *
1804*86d7f5d3SJohn Marino * ERRORS
1805*86d7f5d3SJohn Marino * This function can return an error if fd_buffer_block(), or the system
1806*86d7f5d3SJohn Marino * read() or select() calls do.
1807*86d7f5d3SJohn Marino */
1808*86d7f5d3SJohn Marino static int
fd_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)1809*86d7f5d3SJohn Marino fd_buffer_input (void *closure, char *data, size_t need, size_t size,
1810*86d7f5d3SJohn Marino size_t *got)
1811*86d7f5d3SJohn Marino {
1812*86d7f5d3SJohn Marino struct fd_buffer *fb = closure;
1813*86d7f5d3SJohn Marino int nbytes;
1814*86d7f5d3SJohn Marino
1815*86d7f5d3SJohn Marino assert (need <= size);
1816*86d7f5d3SJohn Marino
1817*86d7f5d3SJohn Marino *got = 0;
1818*86d7f5d3SJohn Marino
1819*86d7f5d3SJohn Marino if (fb->blocking)
1820*86d7f5d3SJohn Marino {
1821*86d7f5d3SJohn Marino int status;
1822*86d7f5d3SJohn Marino fd_set readfds;
1823*86d7f5d3SJohn Marino
1824*86d7f5d3SJohn Marino /* Set non-block. */
1825*86d7f5d3SJohn Marino status = fd_buffer_block (fb, false);
1826*86d7f5d3SJohn Marino if (status != 0) return status;
1827*86d7f5d3SJohn Marino
1828*86d7f5d3SJohn Marino FD_ZERO (&readfds);
1829*86d7f5d3SJohn Marino FD_SET (fb->fd, &readfds);
1830*86d7f5d3SJohn Marino do
1831*86d7f5d3SJohn Marino {
1832*86d7f5d3SJohn Marino int numfds;
1833*86d7f5d3SJohn Marino
1834*86d7f5d3SJohn Marino do {
1835*86d7f5d3SJohn Marino /* This used to select on exceptions too, but as far
1836*86d7f5d3SJohn Marino as I know there was never any reason to do that and
1837*86d7f5d3SJohn Marino SCO doesn't let you select on exceptions on pipes. */
1838*86d7f5d3SJohn Marino numfds = fd_select (fb->fd + 1, &readfds, NULL, NULL, NULL);
1839*86d7f5d3SJohn Marino if (numfds < 0 && errno != EINTR)
1840*86d7f5d3SJohn Marino {
1841*86d7f5d3SJohn Marino status = errno;
1842*86d7f5d3SJohn Marino goto block_done;
1843*86d7f5d3SJohn Marino }
1844*86d7f5d3SJohn Marino } while (numfds < 0);
1845*86d7f5d3SJohn Marino
1846*86d7f5d3SJohn Marino nbytes = read (fb->fd, data + *got, size - *got);
1847*86d7f5d3SJohn Marino
1848*86d7f5d3SJohn Marino if (nbytes == 0)
1849*86d7f5d3SJohn Marino {
1850*86d7f5d3SJohn Marino /* End of file. This assumes that we are using POSIX or BSD
1851*86d7f5d3SJohn Marino style nonblocking I/O. On System V we will get a zero
1852*86d7f5d3SJohn Marino return if there is no data, even when not at EOF. */
1853*86d7f5d3SJohn Marino if (*got)
1854*86d7f5d3SJohn Marino {
1855*86d7f5d3SJohn Marino /* We already read some data, so return no error, counting
1856*86d7f5d3SJohn Marino * on the fact that we will read EOF again next time.
1857*86d7f5d3SJohn Marino */
1858*86d7f5d3SJohn Marino status = 0;
1859*86d7f5d3SJohn Marino break;
1860*86d7f5d3SJohn Marino }
1861*86d7f5d3SJohn Marino else
1862*86d7f5d3SJohn Marino {
1863*86d7f5d3SJohn Marino /* Return EOF. */
1864*86d7f5d3SJohn Marino status = -1;
1865*86d7f5d3SJohn Marino break;
1866*86d7f5d3SJohn Marino }
1867*86d7f5d3SJohn Marino }
1868*86d7f5d3SJohn Marino
1869*86d7f5d3SJohn Marino if (nbytes < 0)
1870*86d7f5d3SJohn Marino {
1871*86d7f5d3SJohn Marino /* Some error occurred. */
1872*86d7f5d3SJohn Marino if (!blocking_error (errno))
1873*86d7f5d3SJohn Marino {
1874*86d7f5d3SJohn Marino status = errno;
1875*86d7f5d3SJohn Marino break;
1876*86d7f5d3SJohn Marino }
1877*86d7f5d3SJohn Marino /* else Everything's fine, we just didn't get any data. */
1878*86d7f5d3SJohn Marino }
1879*86d7f5d3SJohn Marino
1880*86d7f5d3SJohn Marino *got += nbytes;
1881*86d7f5d3SJohn Marino } while (*got < need);
1882*86d7f5d3SJohn Marino
1883*86d7f5d3SJohn Marino block_done:
1884*86d7f5d3SJohn Marino if (status == 0 || status == -1)
1885*86d7f5d3SJohn Marino {
1886*86d7f5d3SJohn Marino int newstatus;
1887*86d7f5d3SJohn Marino
1888*86d7f5d3SJohn Marino /* OK or EOF - Reset block. */
1889*86d7f5d3SJohn Marino newstatus = fd_buffer_block (fb, true);
1890*86d7f5d3SJohn Marino if (newstatus) status = newstatus;
1891*86d7f5d3SJohn Marino }
1892*86d7f5d3SJohn Marino return status;
1893*86d7f5d3SJohn Marino }
1894*86d7f5d3SJohn Marino
1895*86d7f5d3SJohn Marino /* The above will always return. Handle non-blocking read. */
1896*86d7f5d3SJohn Marino nbytes = read (fb->fd, data, size);
1897*86d7f5d3SJohn Marino
1898*86d7f5d3SJohn Marino if (nbytes > 0)
1899*86d7f5d3SJohn Marino {
1900*86d7f5d3SJohn Marino *got = nbytes;
1901*86d7f5d3SJohn Marino return 0;
1902*86d7f5d3SJohn Marino }
1903*86d7f5d3SJohn Marino
1904*86d7f5d3SJohn Marino if (nbytes == 0)
1905*86d7f5d3SJohn Marino /* End of file. This assumes that we are using POSIX or BSD
1906*86d7f5d3SJohn Marino style nonblocking I/O. On System V we will get a zero
1907*86d7f5d3SJohn Marino return if there is no data, even when not at EOF. */
1908*86d7f5d3SJohn Marino return -1;
1909*86d7f5d3SJohn Marino
1910*86d7f5d3SJohn Marino /* Some error occurred. */
1911*86d7f5d3SJohn Marino if (blocking_error (errno))
1912*86d7f5d3SJohn Marino /* Everything's fine, we just didn't get any data. */
1913*86d7f5d3SJohn Marino return 0;
1914*86d7f5d3SJohn Marino
1915*86d7f5d3SJohn Marino return errno;
1916*86d7f5d3SJohn Marino }
1917*86d7f5d3SJohn Marino
1918*86d7f5d3SJohn Marino
1919*86d7f5d3SJohn Marino
1920*86d7f5d3SJohn Marino /* The buffer output function for a buffer built on a file descriptor. */
1921*86d7f5d3SJohn Marino
1922*86d7f5d3SJohn Marino static int
fd_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)1923*86d7f5d3SJohn Marino fd_buffer_output (void *closure, const char *data, size_t have, size_t *wrote)
1924*86d7f5d3SJohn Marino {
1925*86d7f5d3SJohn Marino struct fd_buffer *fd = closure;
1926*86d7f5d3SJohn Marino
1927*86d7f5d3SJohn Marino *wrote = 0;
1928*86d7f5d3SJohn Marino
1929*86d7f5d3SJohn Marino while (have > 0)
1930*86d7f5d3SJohn Marino {
1931*86d7f5d3SJohn Marino int nbytes;
1932*86d7f5d3SJohn Marino
1933*86d7f5d3SJohn Marino nbytes = write (fd->fd, data, have);
1934*86d7f5d3SJohn Marino
1935*86d7f5d3SJohn Marino if (nbytes <= 0)
1936*86d7f5d3SJohn Marino {
1937*86d7f5d3SJohn Marino if (! fd->blocking
1938*86d7f5d3SJohn Marino && (nbytes == 0 || blocking_error (errno)))
1939*86d7f5d3SJohn Marino {
1940*86d7f5d3SJohn Marino /* A nonblocking write failed to write any data. Just
1941*86d7f5d3SJohn Marino return. */
1942*86d7f5d3SJohn Marino return 0;
1943*86d7f5d3SJohn Marino }
1944*86d7f5d3SJohn Marino
1945*86d7f5d3SJohn Marino /* Some sort of error occurred. */
1946*86d7f5d3SJohn Marino
1947*86d7f5d3SJohn Marino if (nbytes == 0)
1948*86d7f5d3SJohn Marino return EIO;
1949*86d7f5d3SJohn Marino
1950*86d7f5d3SJohn Marino return errno;
1951*86d7f5d3SJohn Marino }
1952*86d7f5d3SJohn Marino
1953*86d7f5d3SJohn Marino *wrote += nbytes;
1954*86d7f5d3SJohn Marino data += nbytes;
1955*86d7f5d3SJohn Marino have -= nbytes;
1956*86d7f5d3SJohn Marino }
1957*86d7f5d3SJohn Marino
1958*86d7f5d3SJohn Marino return 0;
1959*86d7f5d3SJohn Marino }
1960*86d7f5d3SJohn Marino
1961*86d7f5d3SJohn Marino
1962*86d7f5d3SJohn Marino
1963*86d7f5d3SJohn Marino /* The buffer flush function for a buffer built on a file descriptor. */
1964*86d7f5d3SJohn Marino static int
fd_buffer_flush(void * closure)1965*86d7f5d3SJohn Marino fd_buffer_flush (void *closure)
1966*86d7f5d3SJohn Marino {
1967*86d7f5d3SJohn Marino /* We don't need to do anything here. Our fd doesn't have its own buffer
1968*86d7f5d3SJohn Marino * and syncing won't do anything but slow us down.
1969*86d7f5d3SJohn Marino *
1970*86d7f5d3SJohn Marino * struct fd_buffer *fb = closure;
1971*86d7f5d3SJohn Marino *
1972*86d7f5d3SJohn Marino * if (fsync (fb->fd) < 0 && errno != EROFS && errno != EINVAL)
1973*86d7f5d3SJohn Marino * return errno;
1974*86d7f5d3SJohn Marino */
1975*86d7f5d3SJohn Marino return 0;
1976*86d7f5d3SJohn Marino }
1977*86d7f5d3SJohn Marino
1978*86d7f5d3SJohn Marino
1979*86d7f5d3SJohn Marino
1980*86d7f5d3SJohn Marino static struct stat devnull;
1981*86d7f5d3SJohn Marino static int devnull_set = -1;
1982*86d7f5d3SJohn Marino
1983*86d7f5d3SJohn Marino /* The buffer block function for a buffer built on a file descriptor. */
1984*86d7f5d3SJohn Marino static int
fd_buffer_block(void * closure,bool block)1985*86d7f5d3SJohn Marino fd_buffer_block (void *closure, bool block)
1986*86d7f5d3SJohn Marino {
1987*86d7f5d3SJohn Marino struct fd_buffer *fb = closure;
1988*86d7f5d3SJohn Marino # if defined (F_GETFL) && defined (O_NONBLOCK) && defined (F_SETFL)
1989*86d7f5d3SJohn Marino int flags;
1990*86d7f5d3SJohn Marino
1991*86d7f5d3SJohn Marino flags = fcntl (fb->fd, F_GETFL, 0);
1992*86d7f5d3SJohn Marino if (flags < 0)
1993*86d7f5d3SJohn Marino return errno;
1994*86d7f5d3SJohn Marino
1995*86d7f5d3SJohn Marino if (block)
1996*86d7f5d3SJohn Marino flags &= ~O_NONBLOCK;
1997*86d7f5d3SJohn Marino else
1998*86d7f5d3SJohn Marino flags |= O_NONBLOCK;
1999*86d7f5d3SJohn Marino
2000*86d7f5d3SJohn Marino if (fcntl (fb->fd, F_SETFL, flags) < 0)
2001*86d7f5d3SJohn Marino {
2002*86d7f5d3SJohn Marino /*
2003*86d7f5d3SJohn Marino * BSD returns ENODEV when we try to set block/nonblock on /dev/null.
2004*86d7f5d3SJohn Marino * BSDI returns ENOTTY when we try to set block/nonblock on /dev/null.
2005*86d7f5d3SJohn Marino */
2006*86d7f5d3SJohn Marino struct stat sb;
2007*86d7f5d3SJohn Marino int save_errno = errno;
2008*86d7f5d3SJohn Marino bool isdevnull = false;
2009*86d7f5d3SJohn Marino
2010*86d7f5d3SJohn Marino if (devnull_set == -1)
2011*86d7f5d3SJohn Marino devnull_set = stat ("/dev/null", &devnull);
2012*86d7f5d3SJohn Marino
2013*86d7f5d3SJohn Marino if (devnull_set >= 0)
2014*86d7f5d3SJohn Marino /* Equivalent to /dev/null ? */
2015*86d7f5d3SJohn Marino isdevnull = (fstat (fb->fd, &sb) >= 0
2016*86d7f5d3SJohn Marino && sb.st_dev == devnull.st_dev
2017*86d7f5d3SJohn Marino && sb.st_ino == devnull.st_ino
2018*86d7f5d3SJohn Marino && sb.st_mode == devnull.st_mode
2019*86d7f5d3SJohn Marino && sb.st_uid == devnull.st_uid
2020*86d7f5d3SJohn Marino && sb.st_gid == devnull.st_gid
2021*86d7f5d3SJohn Marino && sb.st_size == devnull.st_size
2022*86d7f5d3SJohn Marino && sb.st_blocks == devnull.st_blocks
2023*86d7f5d3SJohn Marino && sb.st_blksize == devnull.st_blksize);
2024*86d7f5d3SJohn Marino if (isdevnull)
2025*86d7f5d3SJohn Marino errno = 0;
2026*86d7f5d3SJohn Marino else
2027*86d7f5d3SJohn Marino {
2028*86d7f5d3SJohn Marino errno = save_errno;
2029*86d7f5d3SJohn Marino return errno;
2030*86d7f5d3SJohn Marino }
2031*86d7f5d3SJohn Marino }
2032*86d7f5d3SJohn Marino # endif /* F_GETFL && O_NONBLOCK && F_SETFL */
2033*86d7f5d3SJohn Marino
2034*86d7f5d3SJohn Marino fb->blocking = block;
2035*86d7f5d3SJohn Marino
2036*86d7f5d3SJohn Marino return 0;
2037*86d7f5d3SJohn Marino }
2038*86d7f5d3SJohn Marino
2039*86d7f5d3SJohn Marino
2040*86d7f5d3SJohn Marino
2041*86d7f5d3SJohn Marino static int
fd_buffer_get_fd(void * closure)2042*86d7f5d3SJohn Marino fd_buffer_get_fd (void *closure)
2043*86d7f5d3SJohn Marino {
2044*86d7f5d3SJohn Marino struct fd_buffer *fb = closure;
2045*86d7f5d3SJohn Marino return fb->fd;
2046*86d7f5d3SJohn Marino }
2047*86d7f5d3SJohn Marino
2048*86d7f5d3SJohn Marino
2049*86d7f5d3SJohn Marino
2050*86d7f5d3SJohn Marino /* The buffer shutdown function for a buffer built on a file descriptor.
2051*86d7f5d3SJohn Marino *
2052*86d7f5d3SJohn Marino * This function disposes of memory allocated for this buffer.
2053*86d7f5d3SJohn Marino */
2054*86d7f5d3SJohn Marino static int
fd_buffer_shutdown(struct buffer * buf)2055*86d7f5d3SJohn Marino fd_buffer_shutdown (struct buffer *buf)
2056*86d7f5d3SJohn Marino {
2057*86d7f5d3SJohn Marino struct fd_buffer *fb = buf->closure;
2058*86d7f5d3SJohn Marino struct stat s;
2059*86d7f5d3SJohn Marino bool closefd, statted;
2060*86d7f5d3SJohn Marino
2061*86d7f5d3SJohn Marino /* Must be an open pipe, socket, or file. What could go wrong? */
2062*86d7f5d3SJohn Marino if (fstat (fb->fd, &s) == -1) statted = false;
2063*86d7f5d3SJohn Marino else statted = true;
2064*86d7f5d3SJohn Marino /* Don't bother to try closing the FD if we couldn't stat it. This
2065*86d7f5d3SJohn Marino * probably won't work.
2066*86d7f5d3SJohn Marino *
2067*86d7f5d3SJohn Marino * (buf_shutdown() on some of the server/child communication pipes is
2068*86d7f5d3SJohn Marino * getting EBADF on both the fstat and the close. I'm not sure why -
2069*86d7f5d3SJohn Marino * perhaps they were alredy closed somehow?
2070*86d7f5d3SJohn Marino */
2071*86d7f5d3SJohn Marino closefd = statted;
2072*86d7f5d3SJohn Marino
2073*86d7f5d3SJohn Marino /* Flush the buffer if possible. */
2074*86d7f5d3SJohn Marino if (buf->flush)
2075*86d7f5d3SJohn Marino {
2076*86d7f5d3SJohn Marino buf_flush (buf, 1);
2077*86d7f5d3SJohn Marino buf->flush = NULL;
2078*86d7f5d3SJohn Marino }
2079*86d7f5d3SJohn Marino
2080*86d7f5d3SJohn Marino if (buf->input)
2081*86d7f5d3SJohn Marino {
2082*86d7f5d3SJohn Marino /* There used to be a check here for unread data in the buffer of
2083*86d7f5d3SJohn Marino * the pipe, but it was deemed unnecessary and possibly dangerous. In
2084*86d7f5d3SJohn Marino * some sense it could be second-guessing the caller who requested it
2085*86d7f5d3SJohn Marino * closed, as well.
2086*86d7f5d3SJohn Marino */
2087*86d7f5d3SJohn Marino
2088*86d7f5d3SJohn Marino /* FIXME:
2089*86d7f5d3SJohn Marino *
2090*86d7f5d3SJohn Marino * This mess of #ifdefs is hard to read. There must be some relation between
2091*86d7f5d3SJohn Marino * the macros being checked which at least deserves comments - if
2092*86d7f5d3SJohn Marino * SHUTDOWN_SERVER, NO_SOCKET_TO_FD, & START_RSH_WITH_POPEN_RW were completely
2093*86d7f5d3SJohn Marino * independant, then the next few lines could easily refuse to compile.
2094*86d7f5d3SJohn Marino *
2095*86d7f5d3SJohn Marino * The note below about START_RSH_WITH_POPEN_RW never being set when
2096*86d7f5d3SJohn Marino * SHUTDOWN_SERVER is defined means that this code would always break on
2097*86d7f5d3SJohn Marino * systems with SHUTDOWN_SERVER defined and thus the comment must now be
2098*86d7f5d3SJohn Marino * incorrect or the code was broken since the comment was written.
2099*86d7f5d3SJohn Marino */
2100*86d7f5d3SJohn Marino # ifdef SHUTDOWN_SERVER
2101*86d7f5d3SJohn Marino if (fb->root && fb->root->method != server_method)
2102*86d7f5d3SJohn Marino # endif
2103*86d7f5d3SJohn Marino # ifndef NO_SOCKET_TO_FD
2104*86d7f5d3SJohn Marino {
2105*86d7f5d3SJohn Marino /* shutdown() sockets */
2106*86d7f5d3SJohn Marino if (statted && S_ISSOCK (s.st_mode))
2107*86d7f5d3SJohn Marino shutdown (fb->fd, 0);
2108*86d7f5d3SJohn Marino }
2109*86d7f5d3SJohn Marino # endif /* NO_SOCKET_TO_FD */
2110*86d7f5d3SJohn Marino # ifdef START_RSH_WITH_POPEN_RW
2111*86d7f5d3SJohn Marino /* Can't be set with SHUTDOWN_SERVER defined */
2112*86d7f5d3SJohn Marino /* FIXME: This is now certainly broken since pclose is defined by ANSI
2113*86d7f5d3SJohn Marino * C to accept a FILE * argument. The switch will need to happen at a
2114*86d7f5d3SJohn Marino * higher abstraction level to switch between initializing stdio & fd
2115*86d7f5d3SJohn Marino * buffers on systems that need this (or maybe an fd buffer that keeps
2116*86d7f5d3SJohn Marino * track of the FILE * could be used - I think flushing the stream
2117*86d7f5d3SJohn Marino * before beginning exclusive access via the FD is OK.
2118*86d7f5d3SJohn Marino */
2119*86d7f5d3SJohn Marino else if (fb->root && pclose (fb->fd) == EOF)
2120*86d7f5d3SJohn Marino {
2121*86d7f5d3SJohn Marino error (1, errno, "closing connection to %s",
2122*86d7f5d3SJohn Marino fb->root->hostname);
2123*86d7f5d3SJohn Marino closefd = false;
2124*86d7f5d3SJohn Marino }
2125*86d7f5d3SJohn Marino # endif /* START_RSH_WITH_POPEN_RW */
2126*86d7f5d3SJohn Marino
2127*86d7f5d3SJohn Marino buf->input = NULL;
2128*86d7f5d3SJohn Marino }
2129*86d7f5d3SJohn Marino else if (buf->output)
2130*86d7f5d3SJohn Marino {
2131*86d7f5d3SJohn Marino # ifdef SHUTDOWN_SERVER
2132*86d7f5d3SJohn Marino /* FIXME: Should have a SHUTDOWN_SERVER_INPUT &
2133*86d7f5d3SJohn Marino * SHUTDOWN_SERVER_OUTPUT
2134*86d7f5d3SJohn Marino */
2135*86d7f5d3SJohn Marino if (fb->root && fb->root->method == server_method)
2136*86d7f5d3SJohn Marino SHUTDOWN_SERVER (fb->fd);
2137*86d7f5d3SJohn Marino else
2138*86d7f5d3SJohn Marino # endif
2139*86d7f5d3SJohn Marino # ifndef NO_SOCKET_TO_FD
2140*86d7f5d3SJohn Marino /* shutdown() sockets */
2141*86d7f5d3SJohn Marino if (statted && S_ISSOCK (s.st_mode))
2142*86d7f5d3SJohn Marino shutdown (fb->fd, 1);
2143*86d7f5d3SJohn Marino # else
2144*86d7f5d3SJohn Marino {
2145*86d7f5d3SJohn Marino /* I'm not sure I like this empty block, but the alternative
2146*86d7f5d3SJohn Marino * is another nested NO_SOCKET_TO_FD switch as above.
2147*86d7f5d3SJohn Marino */
2148*86d7f5d3SJohn Marino }
2149*86d7f5d3SJohn Marino # endif /* NO_SOCKET_TO_FD */
2150*86d7f5d3SJohn Marino
2151*86d7f5d3SJohn Marino buf->output = NULL;
2152*86d7f5d3SJohn Marino }
2153*86d7f5d3SJohn Marino
2154*86d7f5d3SJohn Marino if (statted && closefd && close (fb->fd) == -1)
2155*86d7f5d3SJohn Marino {
2156*86d7f5d3SJohn Marino if (server_active)
2157*86d7f5d3SJohn Marino {
2158*86d7f5d3SJohn Marino /* Syslog this? */
2159*86d7f5d3SJohn Marino }
2160*86d7f5d3SJohn Marino # ifdef CLIENT_SUPPORT
2161*86d7f5d3SJohn Marino else if (fb->root)
2162*86d7f5d3SJohn Marino error (1, errno, "closing down connection to %s",
2163*86d7f5d3SJohn Marino fb->root->hostname);
2164*86d7f5d3SJohn Marino /* EXITS */
2165*86d7f5d3SJohn Marino # endif /* CLIENT_SUPPORT */
2166*86d7f5d3SJohn Marino
2167*86d7f5d3SJohn Marino error (0, errno, "closing down buffer");
2168*86d7f5d3SJohn Marino }
2169*86d7f5d3SJohn Marino
2170*86d7f5d3SJohn Marino /* If we were talking to a process, make sure it exited */
2171*86d7f5d3SJohn Marino if (fb->child_pid)
2172*86d7f5d3SJohn Marino {
2173*86d7f5d3SJohn Marino int w;
2174*86d7f5d3SJohn Marino
2175*86d7f5d3SJohn Marino do
2176*86d7f5d3SJohn Marino w = waitpid (fb->child_pid, NULL, 0);
2177*86d7f5d3SJohn Marino while (w == -1 && errno == EINTR);
2178*86d7f5d3SJohn Marino if (w == -1)
2179*86d7f5d3SJohn Marino error (1, errno, "waiting for process %d", fb->child_pid);
2180*86d7f5d3SJohn Marino }
2181*86d7f5d3SJohn Marino
2182*86d7f5d3SJohn Marino free (buf->closure);
2183*86d7f5d3SJohn Marino buf->closure = NULL;
2184*86d7f5d3SJohn Marino
2185*86d7f5d3SJohn Marino return 0;
2186*86d7f5d3SJohn Marino }
2187*86d7f5d3SJohn Marino #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
2188