1*86d7f5d3SJohn Marino /* CVS client logging buffer.
2*86d7f5d3SJohn Marino
3*86d7f5d3SJohn Marino This program is free software; you can redistribute it and/or modify
4*86d7f5d3SJohn Marino it under the terms of the GNU General Public License as published by
5*86d7f5d3SJohn Marino the Free Software Foundation; either version 2, or (at your option)
6*86d7f5d3SJohn Marino any later version.
7*86d7f5d3SJohn Marino
8*86d7f5d3SJohn Marino This program is distributed in the hope that it will be useful,
9*86d7f5d3SJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
10*86d7f5d3SJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11*86d7f5d3SJohn Marino GNU General Public License for more details. */
12*86d7f5d3SJohn Marino
13*86d7f5d3SJohn Marino #include <config.h>
14*86d7f5d3SJohn Marino
15*86d7f5d3SJohn Marino #include <stdio.h>
16*86d7f5d3SJohn Marino
17*86d7f5d3SJohn Marino #include "cvs.h"
18*86d7f5d3SJohn Marino #include "buffer.h"
19*86d7f5d3SJohn Marino #include "ms-buffer.h"
20*86d7f5d3SJohn Marino
21*86d7f5d3SJohn Marino #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
22*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
23*86d7f5d3SJohn Marino
24*86d7f5d3SJohn Marino /* This structure is the closure field of a multi-source buffer. */
25*86d7f5d3SJohn Marino struct ms_buffer
26*86d7f5d3SJohn Marino {
27*86d7f5d3SJohn Marino /* Our buffer struct. */
28*86d7f5d3SJohn Marino struct buffer *buf;
29*86d7f5d3SJohn Marino
30*86d7f5d3SJohn Marino /* The underlying buffers. */
31*86d7f5d3SJohn Marino struct buffer *cur;
32*86d7f5d3SJohn Marino List *bufs;
33*86d7f5d3SJohn Marino
34*86d7f5d3SJohn Marino /* Whether we are in blocking mode or not. */
35*86d7f5d3SJohn Marino bool block;
36*86d7f5d3SJohn Marino };
37*86d7f5d3SJohn Marino
38*86d7f5d3SJohn Marino
39*86d7f5d3SJohn Marino
40*86d7f5d3SJohn Marino /* The block function for a multi-source buffer. */
41*86d7f5d3SJohn Marino static int
ms_buffer_block(void * closure,bool block)42*86d7f5d3SJohn Marino ms_buffer_block (void *closure, bool block)
43*86d7f5d3SJohn Marino {
44*86d7f5d3SJohn Marino struct ms_buffer *mb = closure;
45*86d7f5d3SJohn Marino
46*86d7f5d3SJohn Marino mb->block = block;
47*86d7f5d3SJohn Marino if (block)
48*86d7f5d3SJohn Marino return set_block (mb->cur);
49*86d7f5d3SJohn Marino else
50*86d7f5d3SJohn Marino return set_nonblock (mb->cur);
51*86d7f5d3SJohn Marino }
52*86d7f5d3SJohn Marino
53*86d7f5d3SJohn Marino
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino /* The input function for a log buffer. */
56*86d7f5d3SJohn Marino static int
ms_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)57*86d7f5d3SJohn Marino ms_buffer_input (void *closure, char *data, size_t need, size_t size,
58*86d7f5d3SJohn Marino size_t *got)
59*86d7f5d3SJohn Marino {
60*86d7f5d3SJohn Marino struct ms_buffer *mb = closure;
61*86d7f5d3SJohn Marino int status;
62*86d7f5d3SJohn Marino
63*86d7f5d3SJohn Marino assert (mb->cur->input);
64*86d7f5d3SJohn Marino status = (*mb->cur->input) (mb->cur->closure, data, need, size, got);
65*86d7f5d3SJohn Marino if (status == -1)
66*86d7f5d3SJohn Marino {
67*86d7f5d3SJohn Marino Node *p;
68*86d7f5d3SJohn Marino /* EOF. Set up the next buffer in line but return success and no
69*86d7f5d3SJohn Marino * data since our caller may have selected on the target to find
70*86d7f5d3SJohn Marino * ready data before calling us.
71*86d7f5d3SJohn Marino *
72*86d7f5d3SJohn Marino * If there are no more buffers, return EOF.
73*86d7f5d3SJohn Marino */
74*86d7f5d3SJohn Marino if (list_isempty (mb->bufs)) return -1;
75*86d7f5d3SJohn Marino buf_shutdown (mb->cur);
76*86d7f5d3SJohn Marino buf_free (mb->cur);
77*86d7f5d3SJohn Marino p = mb->bufs->list->next;
78*86d7f5d3SJohn Marino mb->cur = p->data;
79*86d7f5d3SJohn Marino p->delproc = NULL;
80*86d7f5d3SJohn Marino p->data = NULL;
81*86d7f5d3SJohn Marino delnode (p);
82*86d7f5d3SJohn Marino if (!buf_empty_p (mb->cur)) buf_append_buffer (mb->buf, mb->cur);
83*86d7f5d3SJohn Marino ms_buffer_block (closure, mb->block);
84*86d7f5d3SJohn Marino *got = 0;
85*86d7f5d3SJohn Marino status = 0;
86*86d7f5d3SJohn Marino }
87*86d7f5d3SJohn Marino
88*86d7f5d3SJohn Marino return status;
89*86d7f5d3SJohn Marino }
90*86d7f5d3SJohn Marino
91*86d7f5d3SJohn Marino
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers. */
94*86d7f5d3SJohn Marino static int
ms_buffer_get_fd(void * closure)95*86d7f5d3SJohn Marino ms_buffer_get_fd (void *closure)
96*86d7f5d3SJohn Marino {
97*86d7f5d3SJohn Marino struct ms_buffer *mb = closure;
98*86d7f5d3SJohn Marino return buf_get_fd (mb->cur);
99*86d7f5d3SJohn Marino }
100*86d7f5d3SJohn Marino
101*86d7f5d3SJohn Marino
102*86d7f5d3SJohn Marino
103*86d7f5d3SJohn Marino /* The shutdown function for a multi-source buffer. */
104*86d7f5d3SJohn Marino static int
ms_buffer_shutdown(struct buffer * buf)105*86d7f5d3SJohn Marino ms_buffer_shutdown (struct buffer *buf)
106*86d7f5d3SJohn Marino {
107*86d7f5d3SJohn Marino struct ms_buffer *mb = buf->closure;
108*86d7f5d3SJohn Marino Node *p;
109*86d7f5d3SJohn Marino int err = 0;
110*86d7f5d3SJohn Marino
111*86d7f5d3SJohn Marino assert (mb->cur);
112*86d7f5d3SJohn Marino err += buf_shutdown (mb->cur);
113*86d7f5d3SJohn Marino buf_free (mb->cur);
114*86d7f5d3SJohn Marino for (p = mb->bufs->list->next; p != mb->bufs->list; p = p->next)
115*86d7f5d3SJohn Marino {
116*86d7f5d3SJohn Marino assert (p);
117*86d7f5d3SJohn Marino err += buf_shutdown (p->data);
118*86d7f5d3SJohn Marino }
119*86d7f5d3SJohn Marino
120*86d7f5d3SJohn Marino dellist (&mb->bufs);
121*86d7f5d3SJohn Marino return err;
122*86d7f5d3SJohn Marino }
123*86d7f5d3SJohn Marino
124*86d7f5d3SJohn Marino
125*86d7f5d3SJohn Marino
126*86d7f5d3SJohn Marino static void
delbuflist(Node * p)127*86d7f5d3SJohn Marino delbuflist (Node *p)
128*86d7f5d3SJohn Marino {
129*86d7f5d3SJohn Marino if (p->data)
130*86d7f5d3SJohn Marino buf_free (p->data);
131*86d7f5d3SJohn Marino }
132*86d7f5d3SJohn Marino
133*86d7f5d3SJohn Marino
134*86d7f5d3SJohn Marino
135*86d7f5d3SJohn Marino /* Create a multi-source buffer. This could easily be generalized to support
136*86d7f5d3SJohn Marino * any number of source buffers, but for now only two are necessary.
137*86d7f5d3SJohn Marino */
138*86d7f5d3SJohn Marino struct buffer *
ms_buffer_initialize(void (* memory)(struct buffer *),struct buffer * buf,struct buffer * buf2)139*86d7f5d3SJohn Marino ms_buffer_initialize (void (*memory) (struct buffer *),
140*86d7f5d3SJohn Marino struct buffer *buf, struct buffer *buf2/*, ...*/)
141*86d7f5d3SJohn Marino {
142*86d7f5d3SJohn Marino struct ms_buffer *mb = xmalloc (sizeof *mb);
143*86d7f5d3SJohn Marino struct buffer *retbuf;
144*86d7f5d3SJohn Marino Node *p;
145*86d7f5d3SJohn Marino
146*86d7f5d3SJohn Marino mb->block = false;
147*86d7f5d3SJohn Marino mb->cur = buf;
148*86d7f5d3SJohn Marino set_nonblock (buf);
149*86d7f5d3SJohn Marino mb->bufs = getlist ();
150*86d7f5d3SJohn Marino p = getnode ();
151*86d7f5d3SJohn Marino p->data = buf2;
152*86d7f5d3SJohn Marino p->delproc = delbuflist;
153*86d7f5d3SJohn Marino addnode (mb->bufs, p);
154*86d7f5d3SJohn Marino retbuf = buf_initialize (ms_buffer_input, NULL, NULL,
155*86d7f5d3SJohn Marino ms_buffer_block, ms_buffer_get_fd,
156*86d7f5d3SJohn Marino ms_buffer_shutdown, memory, mb);
157*86d7f5d3SJohn Marino if (!buf_empty_p (buf)) buf_append_buffer (retbuf, buf);
158*86d7f5d3SJohn Marino mb->buf = retbuf;
159*86d7f5d3SJohn Marino
160*86d7f5d3SJohn Marino return retbuf;
161*86d7f5d3SJohn Marino }
162*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
163*86d7f5d3SJohn Marino #endif /* defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT) */
164