openrc/src/libeinfo/libeinfo.c

1073 lines
19 KiB
C
Raw Normal View History

/*
einfo.c
Informational functions
*/
2008-01-14 10:35:22 +05:30
/*
* Copyright 2007-2008 Roy Marples
* All rights reserved
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
const char libeinfo_copyright[] = "Copyright (c) 2007-2008 Roy Marples";
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
2008-01-22 15:40:09 +05:30
#include <inttypes.h>
#include <limits.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <syslog.h>
2007-12-08 08:20:35 +05:30
#ifdef HAVE_TERMCAP
2008-01-11 21:21:40 +05:30
# include <termcap.h>
2007-12-08 08:20:35 +05:30
#endif
#include <unistd.h>
#include "einfo.h"
#include "hidden-visibility.h"
2007-04-17 15:02:18 +05:30
hidden_proto(ecolor)
hidden_proto(ebegin)
hidden_proto(ebeginv)
hidden_proto(ebracket)
hidden_proto(eend)
hidden_proto(eendv)
hidden_proto(eerror)
hidden_proto(eerrorn)
hidden_proto(eerrorx)
hidden_proto(eindent)
hidden_proto(eindentv)
hidden_proto(einfo)
hidden_proto(einfon)
hidden_proto(einfov)
hidden_proto(einfovn)
2007-08-16 22:23:20 +05:30
hidden_proto(elog)
hidden_proto(eoutdent)
hidden_proto(eoutdentv)
2007-10-03 18:25:27 +05:30
hidden_proto(eprefix)
hidden_proto(ewarn)
hidden_proto(ewarnn)
hidden_proto(ewarnv)
hidden_proto(ewarnvn)
hidden_proto(ewarnx)
hidden_proto(ewend)
hidden_proto(ewendv)
2008-01-11 21:21:40 +05:30
/* Incase we cannot work out how many columns from ioctl, supply a default */
#define DEFAULT_COLS 80
2008-01-11 21:21:40 +05:30
#define OK "ok"
#define NOT_OK "!!"
/* Number of spaces for an indent */
#define INDENT_WIDTH 2
/* How wide can the indent go? */
2008-01-11 21:21:40 +05:30
#define INDENT_MAX 40
2007-04-17 15:02:18 +05:30
/* Default colours */
2008-01-14 10:35:22 +05:30
#define GOOD 2
2008-01-11 21:21:40 +05:30
#define WARN 3
#define BAD 1
#define HILITE 6
#define BRACKET 4
2007-12-08 08:20:35 +05:30
/* We fallback to these escape codes if termcap isn't available
* like say /usr isn't mounted */
#define AF "\033[3%dm"
#define CE "\033[K"
#define CH "\033[%dC"
#define MD "\033[1m"
#define ME "\033[m"
#define UP "\033[A"
#define _GET_CAP(_d, _c) strlcpy(_d, tgoto(_c, 0, 0), sizeof(_d));
2008-01-11 21:21:40 +05:30
#define _ASSIGN_CAP(_v) { \
_v = p; \
p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \
2008-01-11 21:21:40 +05:30
}
2007-12-08 08:20:35 +05:30
/* A pointer to a string to prefix to einfo/ewarn/eerror messages */
static const char *_eprefix = NULL;
/* Buffers and structures to hold the final colours */
static char ebuffer[100];
struct ecolor {
ECOLOR color;
2007-12-08 08:20:35 +05:30
int def;
const char *name;
};
static char nullstr = '\0';
static const struct ecolor ecolors[] = {
{ ECOLOR_GOOD, GOOD, "good" },
{ ECOLOR_WARN, WARN, "warn" },
{ ECOLOR_BAD, BAD, "bad" },
{ ECOLOR_HILITE, HILITE, "hilite" },
{ ECOLOR_BRACKET, BRACKET, "bracket" },
{ ECOLOR_NORMAL, 0, NULL },
2007-12-08 08:20:35 +05:30
};
static const char *ecolors_str[sizeof(ecolors)/sizeof(ecolors[0])];
2007-12-08 08:20:35 +05:30
static char *flush = NULL;
static char *up = NULL;
static char *goto_column = NULL;
static const char *term = NULL;
static bool term_is_cons25 = false;
2008-01-14 10:35:22 +05:30
/* Termcap buffers and pointers
2007-12-08 08:20:35 +05:30
* Static buffers suck hard, but some termcap implementations require them */
#ifdef HAVE_TERMCAP
static char termcapbuf[2048];
static char tcapbuf[512];
#else
/* No curses support, so we hardcode a list of colour capable terms */
2007-12-20 20:45:53 +05:30
static const char *const color_terms[] = {
2007-04-11 18:14:47 +05:30
"Eterm",
"ansi",
"color-xterm",
"con132x25",
"con132x30",
"con132x43",
"con132x60",
"con80x25",
"con80x28",
"con80x30",
"con80x43",
"con80x50",
"con80x60",
"cons25",
"console",
"cygwin",
"dtterm",
"gnome",
"konsole",
"kterm",
"linux",
"linux-c",
"mach-color",
"mlterm",
"putty",
"rxvt",
"rxvt-cygwin",
"rxvt-cygwin-native",
"rxvt-unicode",
"screen",
"screen-bce",
"screen-w",
"screen.linux",
"vt100",
2008-01-11 04:52:46 +05:30
"vt220",
"wsvt25",
2007-04-11 18:14:47 +05:30
"xterm",
"xterm-256color",
"xterm-color",
"xterm-debian",
NULL
};
2007-12-08 08:20:35 +05:30
#endif
2007-12-08 08:20:35 +05:30
/* strlcat and strlcpy are nice, shame glibc does not define them */
#ifdef __GLIBC__
# if ! defined (__UCLIBC__) && ! defined (__dietlibc__)
static size_t strlcat(char *dst, const char *src, size_t size)
2007-12-08 08:20:35 +05:30
{
char *d = dst;
const char *s = src;
size_t src_n = size;
size_t dst_n;
while (src_n-- != 0 && *d != '\0')
d++;
dst_n = d - dst;
src_n = size - dst_n;
if (src_n == 0)
return dst_n + strlen(src);
2007-12-08 08:20:35 +05:30
while (*s != '\0') {
if (src_n != 1) {
*d++ = *s;
src_n--;
}
s++;
}
*d = '\0';
return dst_n + (s - src);
2007-12-08 08:20:35 +05:30
}
static size_t strlcpy(char *dst, const char *src, size_t size)
2007-12-08 08:20:35 +05:30
{
const char *s = src;
size_t n = size;
if (n && --n)
do {
if (! (*dst++ = *src++))
break;
} while (--n);
if (! n) {
if (size)
*dst = '\0';
while (*src++);
}
return src - s - 1;
2007-12-08 08:20:35 +05:30
}
# endif
#endif
static bool yesno(const char *value)
{
if (! value) {
errno = ENOENT;
return false;
}
if (strcasecmp(value, "yes") == 0 ||
strcasecmp(value, "y") == 0 ||
strcasecmp(value, "true") == 0 ||
strcasecmp(value, "on") == 0 ||
strcasecmp(value, "1") == 0)
return true;
if (strcasecmp(value, "no") != 0 &&
strcasecmp(value, "n") != 0 &&
strcasecmp(value, "false") != 0 &&
strcasecmp(value, "off") != 0 &&
strcasecmp(value, "0") != 0)
errno = EINVAL;
return false;
}
static bool noyes(const char *value)
2007-12-08 08:20:35 +05:30
{
int serrno = errno;
bool retval;
errno = 0;
retval = yesno(value);
if (errno == 0) {
retval = ! retval;
errno = serrno;
}
return retval;
}
static bool is_quiet(void)
2007-12-08 08:20:35 +05:30
{
return yesno(getenv("EINFO_QUIET"));
}
static bool is_verbose(void)
2007-12-08 08:20:35 +05:30
{
return yesno(getenv ("EINFO_VERBOSE"));
}
2007-12-08 08:20:35 +05:30
/* Fake tgoto call - very crapy, but works for our needs */
#ifndef HAVE_TERMCAP
static char *tgoto(const char *cap, int a, int b)
2007-12-08 08:20:35 +05:30
{
static char buf[20];
snprintf(buf, sizeof(buf), cap, b, a);
return buf;
2007-12-08 08:20:35 +05:30
}
#endif
static bool colour_terminal(FILE * __EINFO_RESTRICT f)
{
2007-04-11 18:14:47 +05:30
static int in_colour = -1;
2007-12-08 08:20:35 +05:30
char *e;
int c;
const char *_af = NULL;
const char *_ce = NULL;
const char *_ch = NULL;
const char *_md = NULL;
const char *_me = NULL;
const char *_up = NULL;
char tmp[100];
char *p;
unsigned int i = 0;
if (f && ! isatty(fileno(f)))
return false;
if (noyes(getenv("EINFO_COLOR")))
return false;
2007-06-28 21:14:14 +05:30
2007-04-11 18:14:47 +05:30
if (in_colour == 0)
return false;
2007-04-11 18:14:47 +05:30
if (in_colour == 1)
return true;
2007-12-08 08:20:35 +05:30
term_is_cons25 = false;
if (! term) {
term = getenv("TERM");
if (! term)
return false;
}
if (strcmp(term, "cons25") == 0)
term_is_cons25 = true;
2007-12-08 08:20:35 +05:30
#ifdef HAVE_TERMCAP
/* Check termcap to see if we can do colour or not */
if (tgetent(termcapbuf, term) == 1) {
2007-12-08 08:20:35 +05:30
char *bp = tcapbuf;
_af = tgetstr("AF", &bp);
_ce = tgetstr("ce", &bp);
_ch = tgetstr("ch", &bp);
2007-12-08 08:20:35 +05:30
/* Our ch use also works with RI .... for now */
if (! _ch)
_ch = tgetstr("RI", &bp);
_md = tgetstr("md", &bp);
_me = tgetstr("me", &bp);
_up = tgetstr("up", &bp);
2007-12-08 08:20:35 +05:30
}
/* Cheat here as vanilla BSD has the whole termcap info in /usr
* which is not available to us when we boot */
if (term_is_cons25 || strcmp(term, "wsvt25") == 0) {
2007-12-08 08:20:35 +05:30
#else
while (color_terms[i]) {
if (strcmp(color_terms[i], term) == 0) {
2007-12-08 08:20:35 +05:30
in_colour = 1;
}
i++;
}
if (in_colour != 1) {
in_colour = 0;
return false;
2007-04-11 18:14:47 +05:30
}
2007-12-08 08:20:35 +05:30
#endif
if (! _af)
_af = AF;
if (! _ce)
_ce = CE;
if (! _ch)
_ch = CH;
if (! _md)
_md = MD;
if (! _me)
_me = ME;
if (! _up)
_up = UP;
#ifdef HAVE_TERMCAP
2007-04-11 18:14:47 +05:30
}
if (! _af || ! _ce || ! _me || !_md || ! _up) {
2007-12-08 08:20:35 +05:30
in_colour = 0;
return false;
2007-12-08 08:20:35 +05:30
}
/* Many termcap databases don't have ch or RI even though they
* do work */
if (! _ch)
_ch = CH;
2007-12-08 08:20:35 +05:30
#endif
/* Now setup our colours */
p = ebuffer;
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
2007-12-08 08:20:35 +05:30
tmp[0] = '\0';
if (ecolors[i].name) {
const char *bold = _md;
c = ecolors[i].def;
2008-01-11 21:21:40 +05:30
2007-12-08 08:20:35 +05:30
/* See if the user wants to override the colour
* We use a :col;bold: format like 2;1: for bold green
* and 1;0: for a normal red */
if ((e = getenv("EINFO_COLOR"))) {
char *ee = strstr(e, ecolors[i].name);
2007-12-08 08:20:35 +05:30
if (ee)
ee += strlen(ecolors[i].name);
2007-12-08 08:20:35 +05:30
if (ee && *ee == '=') {
char *d = strdup(ee + 1);
if (d) {
char *end = strchr(d, ':');
if (end)
*end = '\0';
2007-12-08 08:20:35 +05:30
c = atoi(d);
2007-12-08 08:20:35 +05:30
end = strchr(d, ';');
if (end && *++end == '0')
bold = _me;
2007-12-08 08:20:35 +05:30
free(d);
}
2007-12-08 08:20:35 +05:30
}
}
strlcpy(tmp, tgoto(bold, 0, 0), sizeof(tmp));
strlcat(tmp, tgoto(_af, 0, c & 0x07), sizeof(tmp));
2007-12-08 08:20:35 +05:30
} else
_GET_CAP(tmp, _me);
2007-12-08 08:20:35 +05:30
if (tmp[0])
_ASSIGN_CAP(ecolors_str[i])
2007-12-08 08:20:35 +05:30
else
ecolors_str[i] = &nullstr;
2007-12-08 08:20:35 +05:30
}
_GET_CAP(tmp, _ce);
_ASSIGN_CAP(flush);
_GET_CAP(tmp, _up);
_ASSIGN_CAP(up);
strlcpy(tmp, _ch, sizeof(tmp));
_ASSIGN_CAP(goto_column);
2007-12-08 08:20:35 +05:30
in_colour = 1;
return true;
}
static int get_term_columns(FILE * __EINFO_RESTRICT stream)
{
2007-04-17 17:51:15 +05:30
struct winsize ws;
char *env = getenv("COLUMNS");
2007-10-03 17:19:08 +05:30
char *p;
int i;
if (env) {
i = strtoimax(env, &p, 10);
2007-10-03 17:19:08 +05:30
if (! *p)
return i;
2007-10-03 17:19:08 +05:30
}
if (ioctl(fileno(stream), TIOCGWINSZ, &ws) == 0)
return ws.ws_col;
return DEFAULT_COLS;
}
void eprefix(const char *__EINFO_RESTRICT prefix)
{
_eprefix = prefix;
}
2007-10-03 18:25:27 +05:30
hidden_def(eprefix)
static void elogv(int level, const char *__EINFO_RESTRICT fmt, va_list ap)
{
char *e = getenv("EINFO_LOG");
2007-04-11 18:14:47 +05:30
va_list apc;
2007-04-11 18:14:47 +05:30
if (fmt && e) {
closelog();
openlog(e, LOG_PID, LOG_DAEMON);
va_copy(apc, ap);
vsyslog(level, fmt, apc);
va_end(apc);
closelog();
2007-04-11 18:14:47 +05:30
}
}
2007-04-11 18:14:47 +05:30
void elog(int level, const char *__EINFO_RESTRICT fmt, ...)
2007-08-16 22:23:20 +05:30
{
va_list ap;
va_start(ap, fmt);
elogv(level, fmt, ap);
va_end(ap);
2007-08-16 22:23:20 +05:30
}
hidden_def(elog)
static int _eindent(FILE * __EINFO_RESTRICT stream)
{
char *env = getenv("EINFO_INDENT");
2007-04-11 18:14:47 +05:30
int amount = 0;
char indent[INDENT_MAX];
2007-04-11 18:14:47 +05:30
if (env) {
errno = 0;
amount = strtoimax(env, NULL, 0);
2007-04-11 18:14:47 +05:30
if (errno != 0 || amount < 0)
amount = 0;
else if (amount > INDENT_MAX)
amount = INDENT_MAX;
2007-04-11 18:14:47 +05:30
if (amount > 0)
memset(indent, ' ', (size_t) amount);
2007-04-11 18:14:47 +05:30
}
2007-04-11 18:14:47 +05:30
/* Terminate it */
memset(indent + amount, 0, 1);
return fprintf(stream, "%s", indent);
}
static const char *_ecolor(FILE * __EINFO_RESTRICT f, ECOLOR color)
{
2007-12-08 08:20:35 +05:30
unsigned int i;
2007-04-17 15:02:18 +05:30
if (! colour_terminal(f))
return "";
for (i = 0; i < sizeof(ecolors) / sizeof(ecolors[0]); i++) {
2007-12-08 08:20:35 +05:30
if (ecolors[i].color == color)
return ecolors_str[i];
}
return "";
}
2007-04-17 15:02:18 +05:30
hidden_def(ecolor)
const char *ecolor(ECOLOR color)
{
FILE *f = stdout;
/* Try and guess a valid tty */
if (! isatty(fileno(f))) {
f = stderr;
if (! isatty(fileno(f))) {
f = stdin;
if (! isatty(fileno(f)))
f = NULL;
}
}
return _ecolor(f, color);
}
2008-01-11 21:21:40 +05:30
#define LASTCMD(_cmd) { \
unsetenv("EINFO_LASTCMD"); \
setenv("EINFO_LASTCMD", _cmd, 1); \
2008-01-11 21:21:40 +05:30
}
2007-12-08 08:20:35 +05:30
#define EINFOVN(_file, _color) \
2007-12-08 08:20:35 +05:30
{ \
char *_e = getenv("EINFO_LASTCMD"); \
if (_e && ! colour_terminal(_file) && strcmp(_e, "ewarn") != 0 && \
2008-01-11 21:21:40 +05:30
_e[strlen (_e) - 1] == 'n') \
fprintf(_file, "\n"); \
2007-12-08 08:20:35 +05:30
if (_eprefix) \
fprintf(_file, "%s%s%s|", _ecolor(_file, _color), _eprefix, _ecolor(_file, ECOLOR_NORMAL)); \
fprintf(_file, " %s*%s ", _ecolor(_file, _color), _ecolor(_file, ECOLOR_NORMAL)); \
retval += _eindent(_file); \
2008-01-11 21:21:40 +05:30
{ \
va_list _ap; \
va_copy(_ap, ap); \
retval += vfprintf(_file, fmt, _ap) + 3; \
va_end(_ap); \
2008-01-11 21:21:40 +05:30
} \
if (colour_terminal(_file)) \
fprintf(_file, "%s", flush); \
2007-12-08 08:20:35 +05:30
}
static int _einfovn(const char *__EINFO_RESTRICT fmt, va_list ap)
{
2007-04-11 18:14:47 +05:30
int retval = 0;
EINFOVN(stdout, ECOLOR_GOOD);
return retval;
}
static int _ewarnvn(const char *__EINFO_RESTRICT fmt, va_list ap)
{
2007-04-11 18:14:47 +05:30
int retval = 0;
EINFOVN(stderr, ECOLOR_WARN);
return retval;
}
static int _eerrorvn(const char *__EINFO_RESTRICT fmt, va_list ap)
{
2007-04-11 18:14:47 +05:30
int retval = 0;
EINFOVN(stderr, ECOLOR_BAD);
return retval;
}
int einfon(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || is_quiet())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
va_end(ap);
LASTCMD("einfon");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(einfon)
int ewarnn(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || is_quiet())
return 0;
2007-04-10 16:54:58 +05:30
va_start(ap, fmt);
retval = _ewarnvn(fmt, ap);
va_end(ap);
LASTCMD("ewarnn");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewarnn)
int eerrorn(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
va_start(ap, fmt);
retval = _eerrorvn(fmt, ap);
va_end(ap);
LASTCMD("errorn");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(eerrorn)
int einfo(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || is_quiet())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
retval += printf("\n");
va_end(ap);
LASTCMD("einfo");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(einfo)
int ewarn(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || is_quiet())
return 0;
va_start(ap, fmt);
elogv(LOG_WARNING, fmt, ap);
retval = _ewarnvn(fmt, ap);
retval += fprintf(stderr, "\n");
va_end(ap);
LASTCMD("ewarn");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewarn)
void ewarnx(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (fmt && ! is_quiet()) {
va_start(ap, fmt);
elogv(LOG_WARNING, fmt, ap);
retval = _ewarnvn(fmt, ap);
va_end(ap);
retval += fprintf(stderr, "\n");
2007-04-11 18:14:47 +05:30
}
exit(EXIT_FAILURE);
}
hidden_def(ewarnx)
int eerror(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
2007-04-11 18:14:47 +05:30
if (! fmt)
return 0;
va_start(ap, fmt);
elogv(LOG_ERR, fmt, ap);
retval = _eerrorvn(fmt, ap);
va_end(ap);
retval += fprintf(stderr, "\n");
LASTCMD("eerror");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(eerror)
void eerrorx(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
va_list ap;
2007-04-11 18:14:47 +05:30
if (fmt) {
va_start(ap, fmt);
elogv(LOG_ERR, fmt, ap);
_eerrorvn(fmt, ap);
va_end(ap);
fprintf(stderr, "\n");
2007-04-11 18:14:47 +05:30
}
exit(EXIT_FAILURE);
}
hidden_def(eerrorx)
int ebegin(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || is_quiet())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
va_end(ap);
retval += printf(" ...");
if (colour_terminal(stdout))
retval += printf("\n");
LASTCMD("ebegin");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ebegin)
static void _eend(FILE * __EINFO_RESTRICT fp, int col, ECOLOR color,
const char *msg)
{
2007-04-11 18:14:47 +05:30
int i;
int cols;
if (! msg)
return;
cols = get_term_columns(fp) - (strlen(msg) + 3);
2007-04-11 18:14:47 +05:30
/* cons25 is special - we need to remove one char, otherwise things
* do not align properly at all. */
if (! term) {
term = getenv("TERM");
if (term && strcmp(term, "cons25") == 0)
term_is_cons25 = true;
else
term_is_cons25 = false;
}
if (term_is_cons25)
cols--;
2007-04-11 18:14:47 +05:30
/* If extra spacing is required around msg, then please change
* via a runtime knob and leave this default as is as it saves 2
* valuable columns when running on 80 column screens. */
if (cols > 0 && colour_terminal(fp)) {
fprintf(fp, "%s%s %s[%s%s%s]%s\n", up, tgoto(goto_column, 0, cols),
ecolor(ECOLOR_BRACKET), ecolor(color), msg,
ecolor(ECOLOR_BRACKET), ecolor(ECOLOR_NORMAL));
2007-04-11 18:14:47 +05:30
} else {
if (col > 0)
for (i = 0; i < cols - col; i++)
fprintf(fp, " ");
fprintf(fp, " [%s]\n", msg);
2007-04-11 18:14:47 +05:30
}
}
static int _do_eend(const char *cmd, int retval, const char *__EINFO_RESTRICT fmt, va_list ap)
{
2007-04-11 18:14:47 +05:30
int col = 0;
FILE *fp = stdout;
2007-04-11 18:14:47 +05:30
va_list apc;
if (fmt && *fmt != '\0' && retval != 0) {
fp = stderr;
va_copy(apc, ap);
if (strcmp(cmd, "ewend") == 0)
col = _ewarnvn(fmt, apc);
else
col = _eerrorvn(fmt, apc);
col += fprintf(fp, "\n");
va_end(apc);
2007-04-11 18:14:47 +05:30
}
_eend(fp, col,
retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD,
retval == 0 ? OK : NOT_OK);
return retval;
}
int eend(int retval, const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
va_list ap;
if (is_quiet())
return retval;
va_start(ap, fmt);
_do_eend("eend", retval, fmt, ap);
va_end(ap);
LASTCMD("eend");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(eend)
2007-04-10 16:54:58 +05:30
int ewend(int retval, const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
va_list ap;
if (is_quiet())
return retval;
va_start(ap, fmt);
_do_eend("ewend", retval, fmt, ap);
va_end(ap);
LASTCMD("ewend");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewend)
void ebracket(int col, ECOLOR color, const char *msg)
{
_eend(stdout, col, color, msg);
}
hidden_def(ebracket)
void eindent(void)
{
char *env = getenv("EINFO_INDENT");
2007-04-11 18:14:47 +05:30
int amount = 0;
char num[10];
2007-04-11 18:14:47 +05:30
if (env) {
errno = 0;
amount = strtoimax(env, NULL, 0);
2007-04-11 18:14:47 +05:30
if (errno != 0)
amount = 0;
}
2007-04-11 18:14:47 +05:30
amount += INDENT_WIDTH;
if (amount > INDENT_MAX)
amount = INDENT_MAX;
snprintf(num, 10, "%08d", amount);
setenv("EINFO_INDENT", num, 1);
}
hidden_def(eindent)
void eoutdent(void)
{
char *env = getenv("EINFO_INDENT");
2007-04-11 18:14:47 +05:30
int amount = 0;
char num[10];
int serrno = errno;
2007-04-11 18:14:47 +05:30
if (! env)
return;
2007-04-10 16:54:58 +05:30
2007-04-11 18:14:47 +05:30
errno = 0;
amount = strtoimax(env, NULL, 0);
2007-04-11 18:14:47 +05:30
if (errno != 0)
amount = 0;
else
amount -= INDENT_WIDTH;
2007-04-11 18:14:47 +05:30
if (amount <= 0)
unsetenv("EINFO_INDENT");
2007-04-11 18:14:47 +05:30
else {
snprintf(num, 10, "%08d", amount);
setenv("EINFO_INDENT", num, 1);
2007-04-11 18:14:47 +05:30
}
errno = serrno;
}
hidden_def(eoutdent)
int einfovn(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || ! is_verbose())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
va_end(ap);
LASTCMD("einfovn");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(einfovn)
int ewarnvn(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || ! is_verbose())
return 0;
2007-04-10 16:54:58 +05:30
va_start(ap, fmt);
retval = _ewarnvn(fmt, ap);
va_end(ap);
LASTCMD("ewarnvn");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewarnvn)
int einfov(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || ! is_verbose())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
retval += printf("\n");
va_end(ap);
LASTCMD("einfov");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(einfov)
int ewarnv(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || ! is_verbose())
return 0;
va_start(ap, fmt);
retval = _ewarnvn(fmt, ap);
retval += printf("\n");
va_end(ap);
LASTCMD("ewarnv");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewarnv)
int ebeginv(const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
int retval;
va_list ap;
if (! fmt || ! is_verbose())
return 0;
va_start(ap, fmt);
retval = _einfovn(fmt, ap);
retval += printf(" ...");
if (colour_terminal(stdout))
retval += printf("\n");
va_end(ap);
LASTCMD("ebeginv");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ebeginv)
int eendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
va_list ap;
2008-01-11 21:21:40 +05:30
if (! is_verbose())
return 0;
va_start(ap, fmt);
_do_eend("eendv", retval, fmt, ap);
va_end(ap);
LASTCMD("eendv");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(eendv)
int ewendv(int retval, const char *__EINFO_RESTRICT fmt, ...)
{
2007-04-11 18:14:47 +05:30
va_list ap;
if (! is_verbose())
return 0;
va_start(ap, fmt);
_do_eend("ewendv", retval, fmt, ap);
va_end(ap);
LASTCMD("ewendv");
2007-12-08 08:20:35 +05:30
return retval;
}
hidden_def(ewendv)
void eindentv(void)
{
if (is_verbose())
2007-04-11 18:14:47 +05:30
eindent ();
}
hidden_def(eindentv)
void eoutdentv(void)
{
if (is_verbose())
eoutdent();
}
hidden_def(eoutdentv)