1 /* CVS client logging buffer.
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)
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. */
20 #if defined CLIENT_SUPPORT || defined SERVER_SUPPORT
22 /* We want to be able to log data sent between us and the server. We
23 do it using log buffers. Each log buffer has another buffer which
24 handles the actual I/O, and a file to log information to.
26 This structure is the closure field of a log buffer. */
30 /* The underlying buffer. */
32 /* The file to log information to. */
36 /* Whether errors writing to the log file should be fatal or not. */
39 /* The name of the file backing this buffer so that it may be deleted on
44 /* Set once logging is permanently disabled for a buffer. */
47 /* The memory buffer (cache) backing this log. */
48 struct buffer
*back_buf
;
50 /* The maximum number of bytes to store in memory before beginning logging
55 /* Once we start logging to a file we do not want to stop unless asked. */
57 #endif /* PROXY_SUPPORT */
63 /* Force the existance of lb->log.
69 * lb->log The new FILE *.
70 * lb->back_fn The name of the new log, for later disposal.
73 * lb->log is NULL or, at least, does not require freeing.
74 * lb->back_fn is NULL or, at least, does not require freeing..
80 * Errors creating the log file will output a message via error(). Whether
81 * the error is fatal or not is dependent on lb->fatal_errors.
84 log_buffer_force_file (struct log_buffer
*lb
)
86 lb
->log
= cvs_temp_file (&lb
->back_fn
);
88 error (lb
->fatal_errors
, errno
, "failed to open log file.");
90 #endif /* PROXY_SUPPORT */
94 /* Create a log buffer.
97 * buf A pointer to the buffer structure to log input from.
98 * fp A file name to log data to. May be NULL.
100 * fatal_errors Whether errors writing to a log file should be
103 * fatal_errors unused
105 * input Whether we will log data for an input or output
108 * max The maximum size of our memory cache.
112 * memory The function to call when memory allocation errors are
116 * A pointer to a new buffer structure.
118 static int log_buffer_input (void *, char *, size_t, size_t, size_t *);
119 static int log_buffer_output (void *, const char *, size_t, size_t *);
120 static int log_buffer_flush (void *);
121 static int log_buffer_block (void *, bool);
122 static int log_buffer_get_fd (void *);
123 static int log_buffer_shutdown (struct buffer
*);
125 log_buffer_initialize (struct buffer
*buf
, FILE *fp
,
126 # ifdef PROXY_SUPPORT
129 # endif /* PROXY_SUPPORT */
131 void (*memory
) (struct buffer
*))
133 struct log_buffer
*lb
= xmalloc (sizeof *lb
);
134 struct buffer
*retbuf
;
140 lb
->fatal_errors
= fatal_errors
;
141 lb
->disabled
= false;
142 assert (size_in_bounds_p (max
));
145 lb
->back_buf
= buf_nonio_initialize (memory
);
146 #endif /* PROXY_SUPPORT */
147 retbuf
= buf_initialize (input
? log_buffer_input
: NULL
,
148 input
? NULL
: log_buffer_output
,
149 input
? NULL
: log_buffer_flush
,
150 log_buffer_block
, log_buffer_get_fd
,
151 log_buffer_shutdown
, memory
, lb
);
153 if (!buf_empty_p (buf
))
155 /* If our buffer already had data, copy it & log it if necessary. This
156 * can happen, for instance, with a pserver, where we deliberately do
157 * not instantiate the log buffer until after authentication so that
158 * auth data does not get logged (the pserver data will not be logged
159 * in this case, but any data which was left unused in the buffer by
160 * the auth code will be logged and put in our new buffer).
162 struct buffer_data
*data
;
165 #endif /* PROXY_SUPPORT */
167 for (data
= buf
->data
; data
!= NULL
; data
= data
->next
)
172 total
= xsum (data
->size
, total
);
179 if (!lb
->log
) log_buffer_force_file (lb
);
182 #endif /* PROXY_SUPPORT */
183 if (fwrite (data
->bufp
, 1, data
->size
, lb
->log
)
184 != (size_t) data
->size
)
188 #else /* !PROXY_SUPPORT */
190 #endif /* PROXY_SUPPORT */
191 errno
, "writing to log file");
197 /* Log to memory buffer. */
198 buf_copy_data (lb
->back_buf
, data
, data
);
199 #endif /* PROXY_SUPPORT */
201 buf_append_buffer (retbuf
, buf
);
208 /* The input function for a log buffer. */
210 log_buffer_input (void *closure
, char *data
, size_t need
, size_t size
,
213 struct log_buffer
*lb
= closure
;
216 assert (lb
->buf
->input
);
218 status
= (*lb
->buf
->input
) (lb
->buf
->closure
, data
, need
, size
, got
);
225 #endif /* PROXY_SUPPORT */
230 && xsum (*got
, buf_count_mem (lb
->back_buf
)) >= lb
->max
)
235 if (!lb
->log
) log_buffer_force_file (lb
);
238 #endif /* PROXY_SUPPORT */
239 if (fwrite (data
, 1, *got
, lb
->log
) != *got
)
243 #else /* !PROXY_SUPPORT */
245 #endif /* PROXY_SUPPORT */
246 errno
, "writing to log file");
252 /* Log to memory buffer. */
253 buf_output (lb
->back_buf
, data
, *got
);
254 #endif /* PROXY_SUPPORT */
262 /* The output function for a log buffer. */
264 log_buffer_output (void *closure
, const char *data
, size_t have
, size_t *wrote
)
266 struct log_buffer
*lb
= closure
;
269 assert (lb
->buf
->output
);
271 status
= (*lb
->buf
->output
) (lb
->buf
->closure
, data
, have
, wrote
);
278 #endif /* PROXY_SUPPORT */
283 && xsum (*wrote
, buf_count_mem (lb
->back_buf
)) >= lb
->max
)
288 if (!lb
->log
) log_buffer_force_file (lb
);
291 #endif /* PROXY_SUPPORT */
292 if (fwrite (data
, 1, *wrote
, lb
->log
) != *wrote
)
296 #else /* !PROXY_SUPPORT */
298 #endif /* PROXY_SUPPORT */
299 errno
, "writing to log file");
305 /* Log to memory buffer. */
306 buf_output (lb
->back_buf
, data
, *wrote
);
307 #endif /* PROXY_SUPPORT */
315 /* The flush function for a log buffer. */
317 log_buffer_flush (void *closure
)
319 struct log_buffer
*lb
= closure
;
321 assert (lb
->buf
->flush
);
323 /* We don't really have to flush the log file here, but doing it
324 * will let tail -f on the log file show what is sent to the
325 * network as it is sent.
327 if (lb
->log
&& (fflush (lb
->log
)))
328 error (0, errno
, "flushing log file");
330 return (*lb
->buf
->flush
) (lb
->buf
->closure
);
335 /* The block function for a log buffer. */
337 log_buffer_block (void *closure
, bool block
)
339 struct log_buffer
*lb
= closure
;
342 return set_block (lb
->buf
);
344 return set_nonblock (lb
->buf
);
350 /* Disable logging without shutting down the next buffer in the chain.
353 log_buffer_rewind (struct buffer
*buf
)
355 struct log_buffer
*lb
= buf
->closure
;
356 struct buffer
*retbuf
;
366 /* flush & rewind the file. */
367 if (fflush (tmp
) < 0)
368 error (0, errno
, "flushing log file");
371 /* Get a descriptor for the log and close the FILE *. */
372 fd
= dup (fileno (tmp
));
373 if (fclose (tmp
) < 0)
374 error (0, errno
, "closing log file");
377 fd
= open (DEVNULL
, O_RDONLY
);
379 /* Catch dup/open errors. */
382 error (lb
->fatal_errors
, errno
, "failed to rewind log buf.");
386 /* Create a new fd buffer around the log. */
387 retbuf
= fd_buffer_initialize (fd
, 0, NULL
, true, buf
->memory_error
);
391 /* Insert the data which wasn't written to a file. */
392 buf_append_buffer (retbuf
, lb
->back_buf
);
400 #endif /* PROXY_SUPPORT */
404 /* Disable logging and close the log without shutting down the next buffer in
407 #ifndef PROXY_SUPPORT
409 #endif /* !PROXY_SUPPORT */
411 log_buffer_closelog (struct buffer
*buf
)
413 struct log_buffer
*lb
= buf
->closure
;
418 #endif /* PROXY_SUPPORT */
425 if (fclose (tmp
) < 0)
426 error (0, errno
, "closing log file");
430 /* Delete the log if we know its name. */
435 if (CVS_UNLINK (tmp
))
436 error (0, errno
, "Failed to delete log file.");
446 #endif /* PROXY_SUPPORT */
451 /* Return the file descriptor underlying any child buffers. */
453 log_buffer_get_fd (void *closure
)
455 struct log_buffer
*lb
= closure
;
456 return buf_get_fd (lb
->buf
);
461 /* The shutdown function for a log buffer. */
463 log_buffer_shutdown (struct buffer
*buf
)
465 struct log_buffer
*lb
= buf
->closure
;
467 log_buffer_closelog (buf
);
468 return buf_shutdown (lb
->buf
);
474 setup_logfiles (char *var
, struct buffer
**to_server_p
,
475 struct buffer
**from_server_p
)
477 char *log
= getenv (var
);
479 /* Set up logfiles, if any.
481 * We do this _after_ authentication on purpose. Wouldn't really like to
482 * worry about logging passwords...
486 int len
= strlen (log
);
487 char *buf
= xmalloc (len
+ 5);
494 /* Open logfiles in binary mode so that they reflect
495 exactly what was transmitted and received (that is
496 more important than that they be maximally
497 convenient to view). */
498 /* Note that if we create several connections in a single CVS client
499 (currently used by update.c), then the last set of logfiles will
500 overwrite the others. There is currently no way around this. */
502 fp
= fopen (buf
, "wb");
504 error (0, errno
, "opening to-server logfile %s", buf
);
506 *to_server_p
= log_buffer_initialize (*to_server_p
, fp
,
507 # ifdef PROXY_SUPPORT
510 # endif /* PROXY_SUPPORT */
514 fp
= fopen (buf
, "wb");
516 error (0, errno
, "opening from-server logfile %s", buf
);
518 *from_server_p
= log_buffer_initialize (*from_server_p
, fp
,
519 # ifdef PROXY_SUPPORT
522 # endif /* PROXY_SUPPORT */
529 #endif /* CLIENT_SUPPORT || SERVER_SUPPORT */