#include <stdio.h>
#include <fm/fmd_api.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <time.h>
#include "out.h"
#include "stats.h"
#include "io.h"
static struct stats *Outcount;
static struct stats *Errcount;
static struct stats *Warncount;
static int Exitcode;
static const char *Myname;
static FILE *Altfp;
#define MAXOUT 8192
static char Outbuf[MAXOUT];
static int Outidx;
void
out_init(const char *myname)
{
Outcount = stats_new_counter("output.calls", "total calls", 1);
Errcount = stats_new_counter("output.errors", "total errors", 0);
Warncount = stats_new_counter("output.warnings", "total warnings", 0);
if (myname == NULL)
return;
if ((Myname = strrchr(myname, '/')) == NULL &&
(Myname = strrchr(myname, '\\')) == NULL)
Myname = myname;
else
Myname++;
}
void
out_fini(void)
{
stats_delete(Outcount);
Outcount = NULL;
stats_delete(Errcount);
Errcount = NULL;
stats_delete(Warncount);
Warncount = NULL;
}
void
out_altfp(FILE *fp)
{
Altfp = fp;
}
static void
voutbufprintf(const char *fmt, va_list ap)
{
int len = vsnprintf(&Outbuf[Outidx], MAXOUT - Outidx, fmt, ap);
Outidx += len;
if (Outidx >= MAXOUT)
Outidx = MAXOUT - 1;
}
static void
outbufprintf(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
voutbufprintf(fmt, ap);
va_end(ap);
}
static void
vout(int flags, const char *fmt, va_list ap)
{
int safe_errno = errno;
stats_counter_bump(Outcount);
if ((flags & O_DEBUG) && Debug == 0)
return;
if ((flags & O_VERB) && Verbose == 0)
return;
if ((flags & O_VERB2) && Verbose < 2)
return;
if ((flags & O_VERB3) && Verbose < 3)
return;
if ((flags & O_WARN) && Warn == 0)
return;
if ((flags & O_ALTFP) && Altfp == NULL)
return;
if (Outidx == 0) {
if (flags & O_USAGE) {
Exitcode++;
outbufprintf("usage: %s ", Myname);
} else {
if (Myname && flags & (O_DIE|O_ERR|O_WARN|O_PROG))
outbufprintf("%s: ", Myname);
if (flags & O_DIE) {
Exitcode++;
outbufprintf("fatal error: ");
} else if (flags & O_ERR) {
Exitcode++;
stats_counter_bump(Errcount);
outbufprintf("error: ");
} else if (flags & O_WARN) {
stats_counter_bump(Warncount);
outbufprintf("warning: ");
}
}
}
if (fmt != NULL)
voutbufprintf(fmt, ap);
if (flags & O_SYS) {
const char *msg = strerror(safe_errno);
if (Outidx != 0)
outbufprintf(": ");
if (msg)
outbufprintf("%s", msg);
else
outbufprintf("(error %d)", safe_errno);
}
if (flags & O_STAMP) {
time_t clock;
char *tmsg;
(void) time(&clock);
tmsg = ctime(&clock);
if (tmsg && *tmsg) {
tmsg[strlen(tmsg) - 1] = '\0';
if (Outidx != 0)
outbufprintf(" ");
outbufprintf("%s", tmsg);
}
}
if (flags & O_NONL)
return;
if (flags & O_ALTFP)
(void) fprintf(Altfp, "%s\n", Outbuf);
else if (flags & O_ABORT)
io_abort(Outbuf);
else if (flags & O_DIE)
io_die(Outbuf);
else if (flags & O_ERR)
io_err(Outbuf);
else
io_out(Outbuf);
Outidx = 0;
Outbuf[0] = '\0';
}
void
out(int flags, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vout(flags, fmt, ap);
va_end(ap);
}
void
outfl(int flags, const char *fname, int line, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
if (fname)
out(flags|O_NONL, "%s:%d: ", fname, line);
vout(flags, fmt, ap);
va_end(ap);
}
void
out_exit(int code)
{
io_exit(Exitcode + code);
}
int
out_errcount(void)
{
return (stats_counter_value(Errcount));
}
int
out_warncount(void)
{
return (stats_counter_value(Warncount));
}