Codebase list mbuffer / upstream/20180625+ds1 log.c
upstream/20180625+ds1

Tree @upstream/20180625+ds1 (Download .tar.gz)

log.c @upstream/20180625+ds1raw · history · blame

/*
 *  Copyright (C) 2000-2017, Thomas Maier-Komor
 *
 *  This is the source code of mbuffer.
 *
 *  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 3 of the License, 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, see <http://www.gnu.org/licenses/>.
 */

#include "log.h"

#if !(defined(__sun) || defined(__linux) || defined(__GLIBC__))
#define NEED_IO_INTERLOCK
#endif

#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__linux)
#include <linux/limits.h>
#elif defined(__bsd)
#include <sys/syslimits.h>
#endif
#include <sys/types.h>
#include <unistd.h>

verbose_t Verbose = warnings;
int Log = STDERR_FILENO, ErrorOccurred = 0, ErrorsFatal = 0;
extern char *Prefix;
extern size_t PrefixLen;

#ifdef NEED_IO_INTERLOCK
#include <pthread.h>
pthread_mutex_t
	LogMut = PTHREAD_MUTEX_INITIALIZER;
#endif


void setVerbose(const char *arg)
{
	long l = strtol(arg,0,0);
	if (0 == strcasecmp(arg,"fatal"))
		Verbose = fatals;
	else if (0 == strcasecmp(arg,"error"))
		Verbose = errors;
	else if (0 == strcasecmp(arg,"warning"))
		Verbose = warnings;
	else if (0 == strcasecmp(arg,"info"))
		Verbose = infos;
	else if (0 == strcasecmp(arg,"debug"))
		Verbose = debugs;
	else if (0 == strcasecmp(arg,"io"))
		Verbose = iomsgs;
	else if (((l > 0) && (l <= 6)) || ((l == 0) && (errno != EINVAL)))
		Verbose = (verbose_t) l;
	else
		errormsg("invalid argument '%s' for setting verbosity level\n",arg);
}


#ifdef DEBUG
void logdebug(const char *msg, ...)
{
	va_list val;
	char buf[256];
	size_t b = PrefixLen;

	va_start(val,msg);
	(void) memcpy(buf,Prefix,b);
	b += vsnprintf(buf + b,sizeof(buf)-b,msg,val);
	assert(b < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
	if (b <= PIPE_BUF) {
		(void) write(Log,buf,b);
	} else {
		int err;
		err = pthread_mutex_lock(&LogMut);
		assert(err == 0);
		(void) write(Log,buf,b);
		err = pthread_mutex_unlock(&LogMut);
		assert(err == 0);
	}
#else
	(void) write(Log,buf,b);
#endif
	va_end(val);
}
#endif


void infomsg(const char *msg, ...)
{
	if (Verbose >= 4) {
		va_list val;
		char buf[256], *b = buf + PrefixLen;
		size_t s;

		va_start(val,msg);
		(void) memcpy(buf,Prefix,PrefixLen);
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		s = b - buf;
		assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
		if (s <= PIPE_BUF) {
			(void) write(Log,buf,s);
		} else {
			int err;
			err = pthread_mutex_lock(&LogMut);
			assert(err == 0);
			(void) write(Log,buf,s);
			err = pthread_mutex_unlock(&LogMut);
			assert(err == 0);
		}
#else
		(void) write(Log,buf,s);
#endif
		va_end(val);
	}
}


void statusmsg(const char *msg, ...)
{
	if (Verbose >= warnings) {
		va_list val;
		char buf[256], *b = buf + PrefixLen;
		size_t s;

		va_start(val,msg);
		(void) memcpy(buf,Prefix,PrefixLen);
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		s = b - buf;
		assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
		if (s <= PIPE_BUF) {
			(void) write(Log,buf,s);
		} else {
			int err;
			err = pthread_mutex_lock(&LogMut);
			assert(err == 0);
			(void) write(Log,buf,s);
			err = pthread_mutex_unlock(&LogMut);
			assert(err == 0);
		}
#else
		(void) write(Log,buf,s);
#endif
		va_end(val);
	}
}


void warningmsg(const char *msg, ...)
{
	if (Verbose >= warnings) {
		va_list val;
		char buf[256], *b = buf + PrefixLen;
		size_t s;

		va_start(val,msg);
		(void) memcpy(buf,Prefix,PrefixLen);
		(void) memcpy(b,"warning: ",9);
		b += 9;
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		s = b - buf;
		assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
		if (s <= PIPE_BUF) {
			(void) write(Log,buf,s);
		} else {
			int err;
			err = pthread_mutex_lock(&LogMut);
			assert(err == 0);
			(void) write(Log,buf,s);
			err = pthread_mutex_unlock(&LogMut);
			assert(err == 0);
		}
#else
		(void) write(Log,buf,s);
#endif
		va_end(val);
	}
}


void errormsg(const char *msg, ...)
{
	ErrorOccurred = 1;
	if (Verbose >= errors) {
		va_list val;
		char buf[256], *b = buf + PrefixLen;
		size_t s;

		va_start(val,msg);
		(void) memcpy(buf,Prefix,PrefixLen);
		(void) memcpy(b,"error: ",7);
		b += 7;
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		s = b - buf;
		assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
		if (s <= PIPE_BUF) {
			(void) write(Log,buf,s);
		} else {
			int err;
			err = pthread_mutex_lock(&LogMut);
			assert(err == 0);
			(void) write(Log,buf,s);
			err = pthread_mutex_unlock(&LogMut);
			assert(err == 0);
		}
#else
		(void) write(Log,buf,s);
#endif
		va_end(val);
	}
	if (ErrorsFatal != 0) {
		(void) close(Log);
		exit(EXIT_FAILURE);
	}
}


void fatal(const char *msg, ...)
{
	if (Verbose >= fatals) {
		va_list val;
		char buf[256], *b = buf + PrefixLen;
		size_t s;

		va_start(val,msg);
		(void) memcpy(buf,Prefix,PrefixLen);
		(void) memcpy(b,"fatal: ",7);
		b += 7;
		b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
		s = b - buf;
		assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
		if (s <= PIPE_BUF) {
			(void) write(Log,buf,s);
		} else {
			int err;
			err = pthread_mutex_lock(&LogMut);
			assert(err == 0);
			(void) write(Log,buf,s);
			err = pthread_mutex_unlock(&LogMut);
			assert(err == 0);
		}
#else
		(void) write(Log,buf,s);
#endif
		va_end(val);
	}
	exit(EXIT_FAILURE);
}


void printmsg(const char *msg, ...)
{
	va_list val;
	char buf[256], *b = buf + PrefixLen;
	size_t s;

	va_start(val,msg);
	(void) memcpy(buf,Prefix,PrefixLen);
	b += vsnprintf(b,sizeof(buf)-(b-buf),msg,val);
	s = b - buf;
	assert(s < sizeof(buf));
#ifdef NEED_IO_INTERLOCK
	if (s <= PIPE_BUF) {
		(void) write(Log,buf,s);
	} else {
		int err;
		err = pthread_mutex_lock(&LogMut);
		assert(err == 0);
		(void) write(Log,buf,s);
		err = pthread_mutex_unlock(&LogMut);
		assert(err == 0);
	}
#else
	(void) write(Log,buf,s);
#endif
	va_end(val);
}