/* $Id: aerr.C,v 1.5 2005/07/18 21:23:17 dm Exp $ */
/*
*
* Copyright (C) 1998 David Mazieres (dm@uun.org)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
* USA
*
*/
#include "async.h"
#include <dirent.h>
static suio *erruio = New suio;
static void _err_output_async (suio *, int);
static void
_err_reset_async ()
{
erruio->clear ();
fdcb (errfd, selwrite, NULL);
}
void
err_init ()
{
int flags;
erruio->clear ();
if ((flags = fcntl (errfd, F_GETFL, 0)) != -1)
fcntl (errfd, F_SETFL, flags|O_APPEND);
_err_output = _err_output_async;
_err_reset_hook = _err_reset_async;
}
void
err_flush ()
{
if (_err_output != _err_output_async)
return;
make_sync (errfd);
erruio->output (errfd);
}
static void
err_wcb ()
{
int n;
int cnt;
if (!erruio->resid () || _err_output != _err_output_async) {
fdcb (errfd, selwrite, NULL);
return;
}
/* Try to write whole lines at a time. */
for (cnt = min (erruio->iovcnt (), (size_t) UIO_MAXIOV);
cnt > 0 && (erruio->iov ()[cnt-1].iov_len == 0
|| *((char *) erruio->iov ()[cnt-1].iov_base
+ erruio->iov ()[cnt-1].iov_len - 1) != '\n');
cnt--)
;
if (!cnt) {
if (erruio->iovcnt () < UIO_MAXIOV) {
/* Wait for a carriage return */
fdcb (errfd, selwrite, NULL);
return;
}
else
cnt = -1;
}
/* Write asynchronously, but keep stderr synchronous in case of
* emergency (e.g. maybe assert wants to fprintf to stderr). */
if (globaldestruction)
n = erruio->output (errfd, cnt);
else {
_make_async (errfd);
n = erruio->output (errfd, cnt);
make_sync (errfd);
}
if (n < 0)
err_reset ();
if (erruio->resid () && !globaldestruction)
fdcb (errfd, selwrite, wrap (err_wcb));
else
fdcb (errfd, selwrite, NULL);
}
void
_err_output_async (suio *uio, int flags)
{
int saved_errno = errno;
if (flags & warnobj::panicflag) {
erruio->copyu (uio);
make_sync (errfd);
erruio->output (errfd);
myabort ();
}
/* Start new iovecs after newlines so as to output entire lines when
* possible. */
if (erruio->resid ()) {
const iovec *iovp = erruio->iov () + erruio->iovcnt () - 1;
if (((char *) iovp->iov_base)[iovp->iov_len - 1] == '\n')
erruio->breakiov ();
}
erruio->copyu (uio);
if (flags & warnobj::fatalflag) {
err_flush ();
exit (1);
}
err_wcb ();
errno = saved_errno;
}
EXITFN (exitflush);
static void
exitflush ()
{
if (_err_output != _err_output_async) {
err_flush ();
err_reset ();
}
}
syntax highlighted by Code2HTML, v. 0.9.1