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
20*86d7f5d3SJohn Marino #if defined CLIENT_SUPPORT || defined SERVER_SUPPORT
21*86d7f5d3SJohn Marino
22*86d7f5d3SJohn Marino /* We want to be able to log data sent between us and the server. We
23*86d7f5d3SJohn Marino do it using log buffers. Each log buffer has another buffer which
24*86d7f5d3SJohn Marino handles the actual I/O, and a file to log information to.
25*86d7f5d3SJohn Marino
26*86d7f5d3SJohn Marino This structure is the closure field of a log buffer. */
27*86d7f5d3SJohn Marino
28*86d7f5d3SJohn Marino struct log_buffer
29*86d7f5d3SJohn Marino {
30*86d7f5d3SJohn Marino /* The underlying buffer. */
31*86d7f5d3SJohn Marino struct buffer *buf;
32*86d7f5d3SJohn Marino /* The file to log information to. */
33*86d7f5d3SJohn Marino FILE *log;
34*86d7f5d3SJohn Marino
35*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
36*86d7f5d3SJohn Marino /* Whether errors writing to the log file should be fatal or not. */
37*86d7f5d3SJohn Marino bool fatal_errors;
38*86d7f5d3SJohn Marino
39*86d7f5d3SJohn Marino /* The name of the file backing this buffer so that it may be deleted on
40*86d7f5d3SJohn Marino * buffer shutdown.
41*86d7f5d3SJohn Marino */
42*86d7f5d3SJohn Marino char *back_fn;
43*86d7f5d3SJohn Marino
44*86d7f5d3SJohn Marino /* Set once logging is permanently disabled for a buffer. */
45*86d7f5d3SJohn Marino bool disabled;
46*86d7f5d3SJohn Marino
47*86d7f5d3SJohn Marino /* The memory buffer (cache) backing this log. */
48*86d7f5d3SJohn Marino struct buffer *back_buf;
49*86d7f5d3SJohn Marino
50*86d7f5d3SJohn Marino /* The maximum number of bytes to store in memory before beginning logging
51*86d7f5d3SJohn Marino * to a file.
52*86d7f5d3SJohn Marino */
53*86d7f5d3SJohn Marino size_t max;
54*86d7f5d3SJohn Marino
55*86d7f5d3SJohn Marino /* Once we start logging to a file we do not want to stop unless asked. */
56*86d7f5d3SJohn Marino bool tofile;
57*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
58*86d7f5d3SJohn Marino };
59*86d7f5d3SJohn Marino
60*86d7f5d3SJohn Marino
61*86d7f5d3SJohn Marino
62*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
63*86d7f5d3SJohn Marino /* Force the existance of lb->log.
64*86d7f5d3SJohn Marino *
65*86d7f5d3SJohn Marino * INPUTS
66*86d7f5d3SJohn Marino * lb The log buffer.
67*86d7f5d3SJohn Marino *
68*86d7f5d3SJohn Marino * OUTPUTS
69*86d7f5d3SJohn Marino * lb->log The new FILE *.
70*86d7f5d3SJohn Marino * lb->back_fn The name of the new log, for later disposal.
71*86d7f5d3SJohn Marino *
72*86d7f5d3SJohn Marino * ASSUMPTIONS
73*86d7f5d3SJohn Marino * lb->log is NULL or, at least, does not require freeing.
74*86d7f5d3SJohn Marino * lb->back_fn is NULL or, at least, does not require freeing..
75*86d7f5d3SJohn Marino *
76*86d7f5d3SJohn Marino * RETURNS
77*86d7f5d3SJohn Marino * Nothing.
78*86d7f5d3SJohn Marino *
79*86d7f5d3SJohn Marino * ERRORS
80*86d7f5d3SJohn Marino * Errors creating the log file will output a message via error(). Whether
81*86d7f5d3SJohn Marino * the error is fatal or not is dependent on lb->fatal_errors.
82*86d7f5d3SJohn Marino */
83*86d7f5d3SJohn Marino static inline void
log_buffer_force_file(struct log_buffer * lb)84*86d7f5d3SJohn Marino log_buffer_force_file (struct log_buffer *lb)
85*86d7f5d3SJohn Marino {
86*86d7f5d3SJohn Marino lb->log = cvs_temp_file (&lb->back_fn);
87*86d7f5d3SJohn Marino if (!lb->log)
88*86d7f5d3SJohn Marino error (lb->fatal_errors, errno, "failed to open log file.");
89*86d7f5d3SJohn Marino }
90*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
91*86d7f5d3SJohn Marino
92*86d7f5d3SJohn Marino
93*86d7f5d3SJohn Marino
94*86d7f5d3SJohn Marino /* Create a log buffer.
95*86d7f5d3SJohn Marino *
96*86d7f5d3SJohn Marino * INPUTS
97*86d7f5d3SJohn Marino * buf A pointer to the buffer structure to log input from.
98*86d7f5d3SJohn Marino * fp A file name to log data to. May be NULL.
99*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
100*86d7f5d3SJohn Marino * fatal_errors Whether errors writing to a log file should be
101*86d7f5d3SJohn Marino * considered fatal.
102*86d7f5d3SJohn Marino #else
103*86d7f5d3SJohn Marino * fatal_errors unused
104*86d7f5d3SJohn Marino #endif
105*86d7f5d3SJohn Marino * input Whether we will log data for an input or output
106*86d7f5d3SJohn Marino * buffer.
107*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
108*86d7f5d3SJohn Marino * max The maximum size of our memory cache.
109*86d7f5d3SJohn Marino #else
110*86d7f5d3SJohn Marino * max unused
111*86d7f5d3SJohn Marino #endif
112*86d7f5d3SJohn Marino * memory The function to call when memory allocation errors are
113*86d7f5d3SJohn Marino * encountered.
114*86d7f5d3SJohn Marino *
115*86d7f5d3SJohn Marino * RETURNS
116*86d7f5d3SJohn Marino * A pointer to a new buffer structure.
117*86d7f5d3SJohn Marino */
118*86d7f5d3SJohn Marino static int log_buffer_input (void *, char *, size_t, size_t, size_t *);
119*86d7f5d3SJohn Marino static int log_buffer_output (void *, const char *, size_t, size_t *);
120*86d7f5d3SJohn Marino static int log_buffer_flush (void *);
121*86d7f5d3SJohn Marino static int log_buffer_block (void *, bool);
122*86d7f5d3SJohn Marino static int log_buffer_get_fd (void *);
123*86d7f5d3SJohn Marino static int log_buffer_shutdown (struct buffer *);
124*86d7f5d3SJohn Marino struct buffer *
log_buffer_initialize(struct buffer * buf,FILE * fp,bool fatal_errors,size_t max,bool input,void (* memory)(struct buffer *))125*86d7f5d3SJohn Marino log_buffer_initialize (struct buffer *buf, FILE *fp,
126*86d7f5d3SJohn Marino # ifdef PROXY_SUPPORT
127*86d7f5d3SJohn Marino bool fatal_errors,
128*86d7f5d3SJohn Marino size_t max,
129*86d7f5d3SJohn Marino # endif /* PROXY_SUPPORT */
130*86d7f5d3SJohn Marino bool input,
131*86d7f5d3SJohn Marino void (*memory) (struct buffer *))
132*86d7f5d3SJohn Marino {
133*86d7f5d3SJohn Marino struct log_buffer *lb = xmalloc (sizeof *lb);
134*86d7f5d3SJohn Marino struct buffer *retbuf;
135*86d7f5d3SJohn Marino
136*86d7f5d3SJohn Marino lb->buf = buf;
137*86d7f5d3SJohn Marino lb->log = fp;
138*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
139*86d7f5d3SJohn Marino lb->back_fn = NULL;
140*86d7f5d3SJohn Marino lb->fatal_errors = fatal_errors;
141*86d7f5d3SJohn Marino lb->disabled = false;
142*86d7f5d3SJohn Marino assert (size_in_bounds_p (max));
143*86d7f5d3SJohn Marino lb->max = max;
144*86d7f5d3SJohn Marino lb->tofile = false;
145*86d7f5d3SJohn Marino lb->back_buf = buf_nonio_initialize (memory);
146*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
147*86d7f5d3SJohn Marino retbuf = buf_initialize (input ? log_buffer_input : NULL,
148*86d7f5d3SJohn Marino input ? NULL : log_buffer_output,
149*86d7f5d3SJohn Marino input ? NULL : log_buffer_flush,
150*86d7f5d3SJohn Marino log_buffer_block, log_buffer_get_fd,
151*86d7f5d3SJohn Marino log_buffer_shutdown, memory, lb);
152*86d7f5d3SJohn Marino
153*86d7f5d3SJohn Marino if (!buf_empty_p (buf))
154*86d7f5d3SJohn Marino {
155*86d7f5d3SJohn Marino /* If our buffer already had data, copy it & log it if necessary. This
156*86d7f5d3SJohn Marino * can happen, for instance, with a pserver, where we deliberately do
157*86d7f5d3SJohn Marino * not instantiate the log buffer until after authentication so that
158*86d7f5d3SJohn Marino * auth data does not get logged (the pserver data will not be logged
159*86d7f5d3SJohn Marino * in this case, but any data which was left unused in the buffer by
160*86d7f5d3SJohn Marino * the auth code will be logged and put in our new buffer).
161*86d7f5d3SJohn Marino */
162*86d7f5d3SJohn Marino struct buffer_data *data;
163*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
164*86d7f5d3SJohn Marino size_t total = 0;
165*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
166*86d7f5d3SJohn Marino
167*86d7f5d3SJohn Marino for (data = buf->data; data != NULL; data = data->next)
168*86d7f5d3SJohn Marino {
169*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
170*86d7f5d3SJohn Marino if (!lb->tofile)
171*86d7f5d3SJohn Marino {
172*86d7f5d3SJohn Marino total = xsum (data->size, total);
173*86d7f5d3SJohn Marino if (total >= max)
174*86d7f5d3SJohn Marino lb->tofile = true;
175*86d7f5d3SJohn Marino }
176*86d7f5d3SJohn Marino
177*86d7f5d3SJohn Marino if (lb->tofile)
178*86d7f5d3SJohn Marino {
179*86d7f5d3SJohn Marino if (!lb->log) log_buffer_force_file (lb);
180*86d7f5d3SJohn Marino if (lb->log)
181*86d7f5d3SJohn Marino {
182*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
183*86d7f5d3SJohn Marino if (fwrite (data->bufp, 1, data->size, lb->log)
184*86d7f5d3SJohn Marino != (size_t) data->size)
185*86d7f5d3SJohn Marino error (
186*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
187*86d7f5d3SJohn Marino fatal_errors,
188*86d7f5d3SJohn Marino #else /* !PROXY_SUPPORT */
189*86d7f5d3SJohn Marino false,
190*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
191*86d7f5d3SJohn Marino errno, "writing to log file");
192*86d7f5d3SJohn Marino fflush (lb->log);
193*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
194*86d7f5d3SJohn Marino }
195*86d7f5d3SJohn Marino }
196*86d7f5d3SJohn Marino else
197*86d7f5d3SJohn Marino /* Log to memory buffer. */
198*86d7f5d3SJohn Marino buf_copy_data (lb->back_buf, data, data);
199*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
200*86d7f5d3SJohn Marino }
201*86d7f5d3SJohn Marino buf_append_buffer (retbuf, buf);
202*86d7f5d3SJohn Marino }
203*86d7f5d3SJohn Marino return retbuf;
204*86d7f5d3SJohn Marino }
205*86d7f5d3SJohn Marino
206*86d7f5d3SJohn Marino
207*86d7f5d3SJohn Marino
208*86d7f5d3SJohn Marino /* The input function for a log buffer. */
209*86d7f5d3SJohn Marino static int
log_buffer_input(void * closure,char * data,size_t need,size_t size,size_t * got)210*86d7f5d3SJohn Marino log_buffer_input (void *closure, char *data, size_t need, size_t size,
211*86d7f5d3SJohn Marino size_t *got)
212*86d7f5d3SJohn Marino {
213*86d7f5d3SJohn Marino struct log_buffer *lb = closure;
214*86d7f5d3SJohn Marino int status;
215*86d7f5d3SJohn Marino
216*86d7f5d3SJohn Marino assert (lb->buf->input);
217*86d7f5d3SJohn Marino
218*86d7f5d3SJohn Marino status = (*lb->buf->input) (lb->buf->closure, data, need, size, got);
219*86d7f5d3SJohn Marino if (status != 0)
220*86d7f5d3SJohn Marino return status;
221*86d7f5d3SJohn Marino
222*86d7f5d3SJohn Marino if (
223*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
224*86d7f5d3SJohn Marino !lb->disabled &&
225*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
226*86d7f5d3SJohn Marino *got > 0)
227*86d7f5d3SJohn Marino {
228*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
229*86d7f5d3SJohn Marino if (!lb->tofile
230*86d7f5d3SJohn Marino && xsum (*got, buf_count_mem (lb->back_buf)) >= lb->max)
231*86d7f5d3SJohn Marino lb->tofile = true;
232*86d7f5d3SJohn Marino
233*86d7f5d3SJohn Marino if (lb->tofile)
234*86d7f5d3SJohn Marino {
235*86d7f5d3SJohn Marino if (!lb->log) log_buffer_force_file (lb);
236*86d7f5d3SJohn Marino if (lb->log)
237*86d7f5d3SJohn Marino {
238*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
239*86d7f5d3SJohn Marino if (fwrite (data, 1, *got, lb->log) != *got)
240*86d7f5d3SJohn Marino error (
241*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
242*86d7f5d3SJohn Marino lb->fatal_errors,
243*86d7f5d3SJohn Marino #else /* !PROXY_SUPPORT */
244*86d7f5d3SJohn Marino false,
245*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
246*86d7f5d3SJohn Marino errno, "writing to log file");
247*86d7f5d3SJohn Marino fflush (lb->log);
248*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
249*86d7f5d3SJohn Marino }
250*86d7f5d3SJohn Marino }
251*86d7f5d3SJohn Marino else
252*86d7f5d3SJohn Marino /* Log to memory buffer. */
253*86d7f5d3SJohn Marino buf_output (lb->back_buf, data, *got);
254*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
255*86d7f5d3SJohn Marino }
256*86d7f5d3SJohn Marino
257*86d7f5d3SJohn Marino return 0;
258*86d7f5d3SJohn Marino }
259*86d7f5d3SJohn Marino
260*86d7f5d3SJohn Marino
261*86d7f5d3SJohn Marino
262*86d7f5d3SJohn Marino /* The output function for a log buffer. */
263*86d7f5d3SJohn Marino static int
log_buffer_output(void * closure,const char * data,size_t have,size_t * wrote)264*86d7f5d3SJohn Marino log_buffer_output (void *closure, const char *data, size_t have, size_t *wrote)
265*86d7f5d3SJohn Marino {
266*86d7f5d3SJohn Marino struct log_buffer *lb = closure;
267*86d7f5d3SJohn Marino int status;
268*86d7f5d3SJohn Marino
269*86d7f5d3SJohn Marino assert (lb->buf->output);
270*86d7f5d3SJohn Marino
271*86d7f5d3SJohn Marino status = (*lb->buf->output) (lb->buf->closure, data, have, wrote);
272*86d7f5d3SJohn Marino if (status != 0)
273*86d7f5d3SJohn Marino return status;
274*86d7f5d3SJohn Marino
275*86d7f5d3SJohn Marino if (
276*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
277*86d7f5d3SJohn Marino !lb->disabled &&
278*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
279*86d7f5d3SJohn Marino *wrote > 0)
280*86d7f5d3SJohn Marino {
281*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
282*86d7f5d3SJohn Marino if (!lb->tofile
283*86d7f5d3SJohn Marino && xsum (*wrote, buf_count_mem (lb->back_buf)) >= lb->max)
284*86d7f5d3SJohn Marino lb->tofile = true;
285*86d7f5d3SJohn Marino
286*86d7f5d3SJohn Marino if (lb->tofile)
287*86d7f5d3SJohn Marino {
288*86d7f5d3SJohn Marino if (!lb->log) log_buffer_force_file (lb);
289*86d7f5d3SJohn Marino if (lb->log)
290*86d7f5d3SJohn Marino {
291*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
292*86d7f5d3SJohn Marino if (fwrite (data, 1, *wrote, lb->log) != *wrote)
293*86d7f5d3SJohn Marino error (
294*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
295*86d7f5d3SJohn Marino lb->fatal_errors,
296*86d7f5d3SJohn Marino #else /* !PROXY_SUPPORT */
297*86d7f5d3SJohn Marino false,
298*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
299*86d7f5d3SJohn Marino errno, "writing to log file");
300*86d7f5d3SJohn Marino fflush (lb->log);
301*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
302*86d7f5d3SJohn Marino }
303*86d7f5d3SJohn Marino }
304*86d7f5d3SJohn Marino else
305*86d7f5d3SJohn Marino /* Log to memory buffer. */
306*86d7f5d3SJohn Marino buf_output (lb->back_buf, data, *wrote);
307*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
308*86d7f5d3SJohn Marino }
309*86d7f5d3SJohn Marino
310*86d7f5d3SJohn Marino return 0;
311*86d7f5d3SJohn Marino }
312*86d7f5d3SJohn Marino
313*86d7f5d3SJohn Marino
314*86d7f5d3SJohn Marino
315*86d7f5d3SJohn Marino /* The flush function for a log buffer. */
316*86d7f5d3SJohn Marino static int
log_buffer_flush(void * closure)317*86d7f5d3SJohn Marino log_buffer_flush (void *closure)
318*86d7f5d3SJohn Marino {
319*86d7f5d3SJohn Marino struct log_buffer *lb = closure;
320*86d7f5d3SJohn Marino
321*86d7f5d3SJohn Marino assert (lb->buf->flush);
322*86d7f5d3SJohn Marino
323*86d7f5d3SJohn Marino /* We don't really have to flush the log file here, but doing it
324*86d7f5d3SJohn Marino * will let tail -f on the log file show what is sent to the
325*86d7f5d3SJohn Marino * network as it is sent.
326*86d7f5d3SJohn Marino */
327*86d7f5d3SJohn Marino if (lb->log && (fflush (lb->log)))
328*86d7f5d3SJohn Marino error (0, errno, "flushing log file");
329*86d7f5d3SJohn Marino
330*86d7f5d3SJohn Marino return (*lb->buf->flush) (lb->buf->closure);
331*86d7f5d3SJohn Marino }
332*86d7f5d3SJohn Marino
333*86d7f5d3SJohn Marino
334*86d7f5d3SJohn Marino
335*86d7f5d3SJohn Marino /* The block function for a log buffer. */
336*86d7f5d3SJohn Marino static int
log_buffer_block(void * closure,bool block)337*86d7f5d3SJohn Marino log_buffer_block (void *closure, bool block)
338*86d7f5d3SJohn Marino {
339*86d7f5d3SJohn Marino struct log_buffer *lb = closure;
340*86d7f5d3SJohn Marino
341*86d7f5d3SJohn Marino if (block)
342*86d7f5d3SJohn Marino return set_block (lb->buf);
343*86d7f5d3SJohn Marino else
344*86d7f5d3SJohn Marino return set_nonblock (lb->buf);
345*86d7f5d3SJohn Marino }
346*86d7f5d3SJohn Marino
347*86d7f5d3SJohn Marino
348*86d7f5d3SJohn Marino
349*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
350*86d7f5d3SJohn Marino /* Disable logging without shutting down the next buffer in the chain.
351*86d7f5d3SJohn Marino */
352*86d7f5d3SJohn Marino struct buffer *
log_buffer_rewind(struct buffer * buf)353*86d7f5d3SJohn Marino log_buffer_rewind (struct buffer *buf)
354*86d7f5d3SJohn Marino {
355*86d7f5d3SJohn Marino struct log_buffer *lb = buf->closure;
356*86d7f5d3SJohn Marino struct buffer *retbuf;
357*86d7f5d3SJohn Marino int fd;
358*86d7f5d3SJohn Marino
359*86d7f5d3SJohn Marino lb->disabled = true;
360*86d7f5d3SJohn Marino
361*86d7f5d3SJohn Marino if (lb->log)
362*86d7f5d3SJohn Marino {
363*86d7f5d3SJohn Marino FILE *tmp = lb->log;
364*86d7f5d3SJohn Marino lb->log = NULL;
365*86d7f5d3SJohn Marino
366*86d7f5d3SJohn Marino /* flush & rewind the file. */
367*86d7f5d3SJohn Marino if (fflush (tmp) < 0)
368*86d7f5d3SJohn Marino error (0, errno, "flushing log file");
369*86d7f5d3SJohn Marino rewind (tmp);
370*86d7f5d3SJohn Marino
371*86d7f5d3SJohn Marino /* Get a descriptor for the log and close the FILE *. */
372*86d7f5d3SJohn Marino fd = dup (fileno (tmp));
373*86d7f5d3SJohn Marino if (fclose (tmp) < 0)
374*86d7f5d3SJohn Marino error (0, errno, "closing log file");
375*86d7f5d3SJohn Marino }
376*86d7f5d3SJohn Marino else
377*86d7f5d3SJohn Marino fd = open (DEVNULL, O_RDONLY);
378*86d7f5d3SJohn Marino
379*86d7f5d3SJohn Marino /* Catch dup/open errors. */
380*86d7f5d3SJohn Marino if (fd < 0)
381*86d7f5d3SJohn Marino {
382*86d7f5d3SJohn Marino error (lb->fatal_errors, errno, "failed to rewind log buf.");
383*86d7f5d3SJohn Marino return NULL;
384*86d7f5d3SJohn Marino }
385*86d7f5d3SJohn Marino
386*86d7f5d3SJohn Marino /* Create a new fd buffer around the log. */
387*86d7f5d3SJohn Marino retbuf = fd_buffer_initialize (fd, 0, NULL, true, buf->memory_error);
388*86d7f5d3SJohn Marino
389*86d7f5d3SJohn Marino {
390*86d7f5d3SJohn Marino struct buffer *tmp;
391*86d7f5d3SJohn Marino /* Insert the data which wasn't written to a file. */
392*86d7f5d3SJohn Marino buf_append_buffer (retbuf, lb->back_buf);
393*86d7f5d3SJohn Marino tmp = lb->back_buf;
394*86d7f5d3SJohn Marino lb->back_buf = NULL;
395*86d7f5d3SJohn Marino buf_free (tmp);
396*86d7f5d3SJohn Marino }
397*86d7f5d3SJohn Marino
398*86d7f5d3SJohn Marino return retbuf;
399*86d7f5d3SJohn Marino }
400*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
401*86d7f5d3SJohn Marino
402*86d7f5d3SJohn Marino
403*86d7f5d3SJohn Marino
404*86d7f5d3SJohn Marino /* Disable logging and close the log without shutting down the next buffer in
405*86d7f5d3SJohn Marino * the chain.
406*86d7f5d3SJohn Marino */
407*86d7f5d3SJohn Marino #ifndef PROXY_SUPPORT
408*86d7f5d3SJohn Marino static
409*86d7f5d3SJohn Marino #endif /* !PROXY_SUPPORT */
410*86d7f5d3SJohn Marino void
log_buffer_closelog(struct buffer * buf)411*86d7f5d3SJohn Marino log_buffer_closelog (struct buffer *buf)
412*86d7f5d3SJohn Marino {
413*86d7f5d3SJohn Marino struct log_buffer *lb = buf->closure;
414*86d7f5d3SJohn Marino void *tmp;
415*86d7f5d3SJohn Marino
416*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
417*86d7f5d3SJohn Marino lb->disabled = true;
418*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
419*86d7f5d3SJohn Marino
420*86d7f5d3SJohn Marino /* Close the log. */
421*86d7f5d3SJohn Marino if (lb->log)
422*86d7f5d3SJohn Marino {
423*86d7f5d3SJohn Marino tmp = lb->log;
424*86d7f5d3SJohn Marino lb->log = NULL;
425*86d7f5d3SJohn Marino if (fclose (tmp) < 0)
426*86d7f5d3SJohn Marino error (0, errno, "closing log file");
427*86d7f5d3SJohn Marino }
428*86d7f5d3SJohn Marino
429*86d7f5d3SJohn Marino #ifdef PROXY_SUPPORT
430*86d7f5d3SJohn Marino /* Delete the log if we know its name. */
431*86d7f5d3SJohn Marino if (lb->back_fn)
432*86d7f5d3SJohn Marino {
433*86d7f5d3SJohn Marino tmp = lb->back_fn;
434*86d7f5d3SJohn Marino lb->back_fn = NULL;
435*86d7f5d3SJohn Marino if (CVS_UNLINK (tmp))
436*86d7f5d3SJohn Marino error (0, errno, "Failed to delete log file.");
437*86d7f5d3SJohn Marino free (tmp);
438*86d7f5d3SJohn Marino }
439*86d7f5d3SJohn Marino
440*86d7f5d3SJohn Marino if (lb->back_buf)
441*86d7f5d3SJohn Marino {
442*86d7f5d3SJohn Marino tmp = lb->back_buf;
443*86d7f5d3SJohn Marino lb->back_buf = NULL;
444*86d7f5d3SJohn Marino buf_free (tmp);
445*86d7f5d3SJohn Marino }
446*86d7f5d3SJohn Marino #endif /* PROXY_SUPPORT */
447*86d7f5d3SJohn Marino }
448*86d7f5d3SJohn Marino
449*86d7f5d3SJohn Marino
450*86d7f5d3SJohn Marino
451*86d7f5d3SJohn Marino /* Return the file descriptor underlying any child buffers. */
452*86d7f5d3SJohn Marino static int
log_buffer_get_fd(void * closure)453*86d7f5d3SJohn Marino log_buffer_get_fd (void *closure)
454*86d7f5d3SJohn Marino {
455*86d7f5d3SJohn Marino struct log_buffer *lb = closure;
456*86d7f5d3SJohn Marino return buf_get_fd (lb->buf);
457*86d7f5d3SJohn Marino }
458*86d7f5d3SJohn Marino
459*86d7f5d3SJohn Marino
460*86d7f5d3SJohn Marino
461*86d7f5d3SJohn Marino /* The shutdown function for a log buffer. */
462*86d7f5d3SJohn Marino static int
log_buffer_shutdown(struct buffer * buf)463*86d7f5d3SJohn Marino log_buffer_shutdown (struct buffer *buf)
464*86d7f5d3SJohn Marino {
465*86d7f5d3SJohn Marino struct log_buffer *lb = buf->closure;
466*86d7f5d3SJohn Marino
467*86d7f5d3SJohn Marino log_buffer_closelog (buf);
468*86d7f5d3SJohn Marino return buf_shutdown (lb->buf);
469*86d7f5d3SJohn Marino }
470*86d7f5d3SJohn Marino
471*86d7f5d3SJohn Marino
472*86d7f5d3SJohn Marino
473*86d7f5d3SJohn Marino void
setup_logfiles(char * var,struct buffer ** to_server_p,struct buffer ** from_server_p)474*86d7f5d3SJohn Marino setup_logfiles (char *var, struct buffer **to_server_p,
475*86d7f5d3SJohn Marino struct buffer **from_server_p)
476*86d7f5d3SJohn Marino {
477*86d7f5d3SJohn Marino char *log = getenv (var);
478*86d7f5d3SJohn Marino
479*86d7f5d3SJohn Marino /* Set up logfiles, if any.
480*86d7f5d3SJohn Marino *
481*86d7f5d3SJohn Marino * We do this _after_ authentication on purpose. Wouldn't really like to
482*86d7f5d3SJohn Marino * worry about logging passwords...
483*86d7f5d3SJohn Marino */
484*86d7f5d3SJohn Marino if (log)
485*86d7f5d3SJohn Marino {
486*86d7f5d3SJohn Marino int len = strlen (log);
487*86d7f5d3SJohn Marino char *buf = xmalloc (len + 5);
488*86d7f5d3SJohn Marino char *p;
489*86d7f5d3SJohn Marino FILE *fp;
490*86d7f5d3SJohn Marino
491*86d7f5d3SJohn Marino strcpy (buf, log);
492*86d7f5d3SJohn Marino p = buf + len;
493*86d7f5d3SJohn Marino
494*86d7f5d3SJohn Marino /* Open logfiles in binary mode so that they reflect
495*86d7f5d3SJohn Marino exactly what was transmitted and received (that is
496*86d7f5d3SJohn Marino more important than that they be maximally
497*86d7f5d3SJohn Marino convenient to view). */
498*86d7f5d3SJohn Marino /* Note that if we create several connections in a single CVS client
499*86d7f5d3SJohn Marino (currently used by update.c), then the last set of logfiles will
500*86d7f5d3SJohn Marino overwrite the others. There is currently no way around this. */
501*86d7f5d3SJohn Marino strcpy (p, ".in");
502*86d7f5d3SJohn Marino fp = fopen (buf, "wb");
503*86d7f5d3SJohn Marino if (!fp)
504*86d7f5d3SJohn Marino error (0, errno, "opening to-server logfile %s", buf);
505*86d7f5d3SJohn Marino else
506*86d7f5d3SJohn Marino *to_server_p = log_buffer_initialize (*to_server_p, fp,
507*86d7f5d3SJohn Marino # ifdef PROXY_SUPPORT
508*86d7f5d3SJohn Marino false,
509*86d7f5d3SJohn Marino 0,
510*86d7f5d3SJohn Marino # endif /* PROXY_SUPPORT */
511*86d7f5d3SJohn Marino false, NULL);
512*86d7f5d3SJohn Marino
513*86d7f5d3SJohn Marino strcpy (p, ".out");
514*86d7f5d3SJohn Marino fp = fopen (buf, "wb");
515*86d7f5d3SJohn Marino if (!fp)
516*86d7f5d3SJohn Marino error (0, errno, "opening from-server logfile %s", buf);
517*86d7f5d3SJohn Marino else
518*86d7f5d3SJohn Marino *from_server_p = log_buffer_initialize (*from_server_p, fp,
519*86d7f5d3SJohn Marino # ifdef PROXY_SUPPORT
520*86d7f5d3SJohn Marino false,
521*86d7f5d3SJohn Marino 0,
522*86d7f5d3SJohn Marino # endif /* PROXY_SUPPORT */
523*86d7f5d3SJohn Marino true, NULL);
524*86d7f5d3SJohn Marino
525*86d7f5d3SJohn Marino free (buf);
526*86d7f5d3SJohn Marino }
527*86d7f5d3SJohn Marino }
528*86d7f5d3SJohn Marino
529*86d7f5d3SJohn Marino #endif /* CLIENT_SUPPORT || SERVER_SUPPORT */
530