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