From 48981be8a872c7a0191d2519793205276fdc423a Mon Sep 17 00:00:00 2001 From: William Hubbs Date: Wed, 16 Oct 2013 12:55:37 -0500 Subject: Revert "Make einfo routines private" This reverts commit de88aff0a839844526ae262f8961ec4372fed238. I was advised that splashutils links to libeinfo, so we do have a consumer for this library. --- man/Makefile | 2 +- man/einfo.3 | 210 +++++++++ pkgconfig/Makefile | 4 +- pkgconfig/einfo.pc.in | 9 + src/Makefile | 2 +- src/libeinfo/.gitignore | 1 + src/libeinfo/Makefile | 12 + src/libeinfo/einfo.h | 144 ++++++ src/libeinfo/einfo.map | 35 ++ src/libeinfo/libeinfo.c | 1070 +++++++++++++++++++++++++++++++++++++++++++++ src/rc/Makefile | 27 +- src/rc/einfo.c | 1016 ------------------------------------------ src/rc/einfo.h | 130 ------ src/test/einfo.data.list | 1 + src/test/einfo.funcs.list | 52 +++ src/test/runtests.sh | 18 + 16 files changed, 1563 insertions(+), 1170 deletions(-) create mode 100644 man/einfo.3 create mode 100644 pkgconfig/einfo.pc.in create mode 100644 src/libeinfo/.gitignore create mode 100644 src/libeinfo/Makefile create mode 100644 src/libeinfo/einfo.h create mode 100644 src/libeinfo/einfo.map create mode 100644 src/libeinfo/libeinfo.c delete mode 100644 src/rc/einfo.c delete mode 100644 src/rc/einfo.h create mode 100644 src/test/einfo.data.list create mode 100644 src/test/einfo.funcs.list diff --git a/man/Makefile b/man/Makefile index 6a106e7..4110c8f 100644 --- a/man/Makefile +++ b/man/Makefile @@ -1,4 +1,4 @@ -MAN3= \ +MAN3= einfo.3 \ rc_config.3 rc_deptree.3 rc_find_pids.3 rc_plugin_hook.3 \ rc_runlevel.3 rc_service.3 rc_stringlist.3 MAN8= rc-service.8 rc-status.8 rc-update.8 rc.8 runscript.8 \ diff --git a/man/einfo.3 b/man/einfo.3 new file mode 100644 index 0000000..f7b1fd2 --- /dev/null +++ b/man/einfo.3 @@ -0,0 +1,210 @@ +.\" Copyright (c) 2007-2008 Roy Marples +.\" +.\" 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. +.\" +.Dd Mar 16, 2008 +.Dt EINFO 3 SMM +.Os OpenRC +.Sh NAME +.Nm einfo , ewarn , eerror , ebegin , +.Nm einfon , ewarnn , eerrorn , ebeginn , +.Nm einfov , ewarnv , ebeginv , +.Nm einfovn , ewarnvn , ebeginvn , +.Nm ewarnx , eerrorx , +.Nm eend , ewend , +.Nm eendv , ewendv , +.Nm ebracket , +.Nm eindent , eoutdent , +.Nm eindentv , eoutdentv , +.Nm eprefix +.Nd colorful informational output +.Sh LIBRARY +Enhanced Information output library (libeinfo, -leinfo) +.Sh SYNOPSIS +.In einfo.h +.Ft int Fn einfo "const char * restrict format" ... +.Ft int Fn ewarn "const char * restrict format" ... +.Ft int Fn eerror "const char * restrict format" ... +.Ft int Fn ebegin "const char * restrict format" ... +.Ft int Fn einfon "const char * restrict format" ... +.Ft int Fn ewarnn "const char * restrict format" ... +.Ft int Fn eerrorn "const char * restrict format" ... +.Ft int Fn ebeginn "const char * restrict format" ... +.Ft int Fn einfov "const char * restrict format" ... +.Ft int Fn ewarnv "const char * restrict format" ... +.Ft int Fn ebeginv "const char * restrict format" ... +.Ft int Fn einfovn "const char * restrict format" ... +.Ft int Fn ewarnvn "const char * restrict format" ... +.Ft int Fn ebeginvn "const char * restrict format" ... +.Ft int Fn ewarnx "const char * restrict format" ... +.Ft int Fn eerrorx "const char * restrict format" ... +.Ft int Fn eend "int retval" "const char * restrict format" ... +.Ft int Fn ewend "int retval" "const char * restrict format" ... +.Ft int Fn eendv "int retval" "const char * restrict format" ... +.Ft int Fn ewendv "int retval" "const char * restrict format" ... +.Ft void Fn ebracket "int col" "ECOLOR color" "const char * restrict msg" +.Ft void Fn eindent void +.Ft void Fn eoutdent void +.Ft void Fn eindentv void +.Ft void Fn eoutdentv void +.Ft void Fn eprefix "const char * prefix" +.Sh DESCRIPTION +The +.Fn einfo +family of functions provide a simple informational output that is colorised. +Basically +.Fn einfo , +.Fn ewarn +and +.Fn eerror +behave exactly like +.Fn printf +but prefix the output with a colored *. The function called denotes the color +used with +.Fn einfo +being green, +.Fn ewarn +being yellow and +.Fn eerror +being red. +einfo goes to stdout and the others go to stderr. +The number of real characters printed is returned. +.Fn ebegin +is identical to +.Fn einfo +except that 3 dots are appended to the output. +.Pp +.Fn einfov , +.Fn ewarnv +and +.Fn ebeginv +work the same way to +.Fn einfo , +.Fn ewarn , +and +.Fn ebegin +respectively, but only work when +.Va EINFO_VERBOSE +is true. You can also make the +.Fn einfo , +.Fn ewarn , +and +.Fn ebegin +functions silent by setting +.Va EINFO_QUIET +to true. +.Pp +These functions are designed to output a whole line, so they also +append a newline to the string. To stop this behaviour, you can use the +functions +.Fn einfon , +.Fn ewarnn , +.Fn eerrorn , +.Fn einfovn , +.Fn ewarnvn , +and +.Fn ebeginvn . +.Pp +.Fn eend , +.Fn ewend , +.Fn eendv +and +.Fn ewendv +are the counterparts to the above functions. If +.Fa retval +is zero then ok in green is printed in a bracket at the end of the prior +line. Otherwise we print the formatted string using +.Fn error +(or +.Fn ewarn +if +.Fn ewend +is called) !! in red (or yellow if +.Fn ewend +is called) is printed in a bracket at the end of the line. +The value of +.Fa retval +is returned. +.Pp +.Fn ebracket +does the same as +.Fn eend +but prints +.Fa msg +instead of ok or !! in the color +.Fa color +at the column +.Fa col . +.Pp +.Fn eindent +indents subsequent calls to the above functions by 3 characters. +.Fn eoutdent +removes an +.Fn eindent . +.Fn eindentv +and +.Fn eoutdentv +only work when +.Va EINFO_VERBOSE +is true. +.Pp +.Fn eprefix +prefixes the string +.Fa prefix +to the above functions. +.Sh IMPLEMENTATION NOTES +einfo can optionally be linked against the +.Lb libtermcap +so that we can correctly query the connected console for our color and +cursor escape codes. +If not, then we have a hard coded list of terminals we know about that support +the commonly used codes for color and cursor position. +.Sh ENVIRONMENT +.Va EINFO_QUIET +when set to true makes the +.Fn einfo +and +.Fn einfon +family of functions quiet, so nothing is printed. +.Va EERROR_QUIET +when set to true makes the +.Fn eerror +and +.Fn eerrorn +family of functions quiet, so nothing is printed. +.Pp +.Va EINFO_VERBOSE +when set to true makes the +.Fn einfov +and +.Fn einfovn +family of functions work, so they do print. +.Sh FILES +.Pa /etc/init.d/functions.sh +is provided by OpenRC, which allows shell scripts to use the above functions. +For historical reasons our verbose functions are prefixed with v instead of +suffixed. So einfov becomes veinfo, einfovn becomes veinfon. +Rinse and repeat for the other verbose functions. +.Sh SEE ALSO +.Xr printf 3 , +.Sh AUTHORS +.An Roy Marples diff --git a/pkgconfig/Makefile b/pkgconfig/Makefile index d1dc550..4bf28cf 100644 --- a/pkgconfig/Makefile +++ b/pkgconfig/Makefile @@ -1,6 +1,6 @@ DIR= ${LIBDIR}/pkgconfig -SRCS= openrc.pc.in -INC= openrc.pc +SRCS= einfo.pc.in openrc.pc.in +INC= einfo.pc openrc.pc .DEFAULT: ${SED} -n -e 's/^VERSION=[[:space:]]*\([^[:space:]]*\).*/#define VERSION "\1${GITVER}\"/p' ../../Makefile > version.h diff --git a/pkgconfig/einfo.pc.in b/pkgconfig/einfo.pc.in new file mode 100644 index 0000000..b5242a6 --- /dev/null +++ b/pkgconfig/einfo.pc.in @@ -0,0 +1,9 @@ +prefix=@PREFIX@ +exec_prefix=${prefix} +libdir=${prefix}/@LIB@ +includedir=/usr/include + +Name: einfo +Description: Pretty console informational display +Version: @VERSION@ +Libs: -L${libdir} -leinfo diff --git a/src/Makefile b/src/Makefile index f4cd512..ffbf8d6 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ # Copyright (c) 2007-2008 Roy Marples # Released under the 2-clause BSD license. -SUBDIR= test librc rc +SUBDIR= test libeinfo librc rc ifeq (${MKTOOLS},yes) SUBDIR+= tools diff --git a/src/libeinfo/.gitignore b/src/libeinfo/.gitignore new file mode 100644 index 0000000..373284d --- /dev/null +++ b/src/libeinfo/.gitignore @@ -0,0 +1 @@ +libeinfo.so.1 diff --git a/src/libeinfo/Makefile b/src/libeinfo/Makefile new file mode 100644 index 0000000..ec756b4 --- /dev/null +++ b/src/libeinfo/Makefile @@ -0,0 +1,12 @@ +LIB= einfo +SHLIB_MAJOR= 1 +SRCS= libeinfo.c +INCS= einfo.h +VERSION_MAP= einfo.map + +CPPFLAGS+= -I../includes + +MK= ../../mk +include ${MK}/lib.mk +include ${MK}/cc.mk +include ${MK}/termcap.mk diff --git a/src/libeinfo/einfo.h b/src/libeinfo/einfo.h new file mode 100644 index 0000000..31a891f --- /dev/null +++ b/src/libeinfo/einfo.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2007-2008 Roy Marples + * + * 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. + */ + +#ifndef __EINFO_H__ +#define __EINFO_H__ + +#if defined(__GNUC__) +# define EINFO_PRINTF(a, b) __attribute__((__format__(__printf__, a, b))) +# define EINFO_XPRINTF(a, b) __attribute__((__noreturn__,__format__(__printf__, a, b))) +#else +# define EINFO_PRINTF(a, b) +# define EINFO_XPRINTF(a, b) +#endif + +#include +#include + +/* Although OpenRC requires C99, linking to us should not. */ +#ifdef restrict +# define EINFO_RESTRICT restrict +#else +# ifdef __restrict +# define EINFO_RESTRICT __restrict +# else +# define EINFO_RESTRICT +# endif +#endif + +__BEGIN_DECLS + +/*! @brief Color types to use */ +typedef enum +{ + ECOLOR_NORMAL = 1, + ECOLOR_GOOD = 2, + ECOLOR_WARN = 3, + ECOLOR_BAD = 4, + ECOLOR_HILITE = 5, + ECOLOR_BRACKET = 6 +} ECOLOR; + +/*! @brief Returns the ASCII code for the color */ +const char *ecolor(ECOLOR); + +/*! @brief Writes to syslog. */ +void elog(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); + +/*! + * @brief Display informational messages. + * + * The einfo family of functions display messages in a consistent manner + * across applications. Basically they prefix the message with + * " * ". If the terminal can handle color then we color the * based on + * the command used. Otherwise we are identical to the printf function. + * + * - einfo - green + * - ewarn - yellow + * - eerror - red + * + * The n suffix denotes that no new line should be printed. + * The v suffix means only print if EINFO_VERBOSE is yes. + */ +/*@{*/ +int einfon(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ewarnn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int eerrorn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int einfo(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ewarn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +void ewarnx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); +int eerror(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +void eerrorx(const char * __EINFO_RESTRICT, ...) EINFO_XPRINTF(1, 2); + +int einfovn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ewarnvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ebeginvn(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int eendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +int ewendvn(int, const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +int einfov(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ewarnv(const char * __EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +/*@}*/ + +/*! @ingroup ebegin + * @brief Display informational messages that may take some time. + * + * Similar to einfo, but we add ... to the end of the message */ +/*@{*/ +int ebeginv(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +int ebegin(const char * EINFO_RESTRICT, ...) EINFO_PRINTF(1, 2); +/*@}*/ + +/*! @ingroup eend + * @brief End an ebegin. + * + * If you ebegin, you should eend also. + * eend places [ ok ] or [ !! ] at the end of the terminal line depending on + * retval (0 or ok, anything else for !!) + * + * ebracket allows you to specifiy the position, color and message */ +/*@{*/ +int eend(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +int ewend(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +void ebracket(int, ECOLOR, const char * EINFO_RESTRICT); + +int eendv(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +int ewendv(int, const char * EINFO_RESTRICT, ...) EINFO_PRINTF(2, 3); +/*@}*/ + +/*! @ingroup eindent + * @brief Indents the einfo lines. + * + * For each indent you should outdent when done */ +/*@{*/ +void eindent(void); +void eoutdent(void); +void eindentv(void); +void eoutdentv(void); + +/*! @brief Prefix each einfo line with something */ +void eprefix(const char * EINFO_RESTRICT); + +__END_DECLS +#endif diff --git a/src/libeinfo/einfo.map b/src/libeinfo/einfo.map new file mode 100644 index 0000000..428a895 --- /dev/null +++ b/src/libeinfo/einfo.map @@ -0,0 +1,35 @@ +EINFO_1.0 { +global: + ecolor; + elog; + einfon; + ewarnn; + eerrorn; + einfo; + ewarn; + ewarnx; + eerror; + eerrorx; + einfovn; + ewarnvn; + ebeginvn; + eendvn; + ewendvn; + einfov; + ewarnv; + ebeginv; + ebegin; + eend; + ewend; + ebracket; + eendv; + ewendv; + eindent; + eoutdent; + eindentv; + eoutdentv; + eprefix; + +local: + *; +}; diff --git a/src/libeinfo/libeinfo.c b/src/libeinfo/libeinfo.c new file mode 100644 index 0000000..9791051 --- /dev/null +++ b/src/libeinfo/libeinfo.c @@ -0,0 +1,1070 @@ +/* + einfo.c + Informational functions +*/ + +/* + * Copyright (c) 2007-2008 Roy Marples + * + * 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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef HAVE_TERMCAP +# include +#endif +#include + +#include "einfo.h" +#include "helpers.h" +#include "hidden-visibility.h" + +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) +hidden_proto(elog) +hidden_proto(eoutdent) +hidden_proto(eoutdentv) +hidden_proto(eprefix) +hidden_proto(ewarn) +hidden_proto(ewarnn) +hidden_proto(ewarnv) +hidden_proto(ewarnvn) +hidden_proto(ewarnx) +hidden_proto(ewend) +hidden_proto(ewendv) + +/* Incase we cannot work out how many columns from ioctl, supply a default */ +#define DEFAULT_COLS 80 + +#define OK "ok" +#define NOT_OK "!!" + +/* Number of spaces for an indent */ +#define INDENT_WIDTH 2 + +/* How wide can the indent go? */ +#define INDENT_MAX 40 + +/* Default colours */ +#define GOOD 2 +#define WARN 3 +#define BAD 1 +#define HILITE 6 +#define BRACKET 4 + +/* 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)); +#define _ASSIGN_CAP(_v) do { \ + _v = p; \ + p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \ + } while (0) + +/* 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; + 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 }, +}; +static const char *ecolors_str[ARRAY_SIZE(ecolors)]; + +static char *flush = NULL; +static char *up = NULL; +static char *goto_column = NULL; + +static const char *term = NULL; +static bool term_is_cons25 = false; + +/* Termcap buffers and pointers + * 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 + * Only terminals without "color" in the name need to be explicitly listed */ +static const char *const color_terms[] = { + "Eterm", + "ansi", + "con132x25", + "con132x30", + "con132x43", + "con132x60", + "con80x25", + "con80x28", + "con80x30", + "con80x43", + "con80x50", + "con80x60", + "cons25", + "console", + "cygwin", + "dtterm", + "gnome", + "konsole", + "kterm", + "linux", + "linux-c", + "mlterm", + "putty", + "rxvt", + "rxvt-cygwin", + "rxvt-cygwin-native", + "rxvt-unicode", + "screen", + "screen-bce", + "screen-w", + "screen.linux", + "vt100", + "vt220", + "wsvt25", + "xterm", + "xterm-debian", + NULL +}; +#endif + +/* 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) +{ + 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); + + while (*s != '\0') { + if (src_n != 1) { + *d++ = *s; + src_n--; + } + s++; + } + *d = '\0'; + + return dst_n + (s - src); +} +# 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) +{ + int serrno = errno; + bool retval; + + errno = 0; + retval = yesno(value); + if (errno == 0) { + retval = !retval; + errno = serrno; + } + + return retval; +} + +static bool +is_quiet(void) +{ + return yesno(getenv("EINFO_QUIET")); +} + +static bool +is_really_quiet(void) +{ + return yesno(getenv("EERROR_QUIET")); +} + +static bool +is_verbose(void) +{ + return yesno(getenv ("EINFO_VERBOSE")); +} + +/* Fake tgoto call - very crapy, but works for our needs */ +#ifndef HAVE_TERMCAP +static char * +tgoto(const char *cap, int col, int line) +{ + static char buf[20]; + char *p, *e, c, dbuf[6]; + int oncol = 0, which = line, i; + + p = buf; + e = p + sizeof(buf); + while ((c = *cap++)) { + if (c != '%' || ((c = *cap++) == '%')) { + *p++ = c; + if (p >= e) { + errno = E2BIG; + return NULL; + } + continue; + } + switch (c) { + case '3': + case '2': + case 'd': + i = 0; + do + dbuf[i++] = which % 10 | '0'; + while ((which /= 10)); + if (c != 'd') { + c -= '0'; + if (i > c) { + errno = EINVAL; + return NULL; + } + while (i < c) + dbuf[i++] = '0'; + } + if (p + i >= e) { + errno = E2BIG; + return NULL; + } + do + *p++ = dbuf[--i]; + while (i); + break; + case 'r': + oncol = 0; + break; + case 'i': + col++; + line++; + which++; + continue; + default: + errno = EINVAL; + return NULL; + } + + oncol = 1 - oncol; + which = oncol ? col : line; + } + *p = '\0'; + return buf; +} +#endif + +static bool +colour_terminal(FILE * EINFO_RESTRICT f) +{ + static int in_colour = -1; + char *e, *ee, *end, *d, *p; + int c; + const char *_af = NULL, *_ce = NULL, *_ch = NULL; + const char *_md = NULL, *_me = NULL, *_up = NULL; + const char *bold; + char tmp[100]; + unsigned int i = 0; +#ifdef HAVE_TERMCAP + char *bp; +#endif + + if (f && !isatty(fileno(f))) + return false; + + if (noyes(getenv("EINFO_COLOR"))) + return false; + + if (in_colour == 0) + return false; + if (in_colour == 1) + return true; + + term_is_cons25 = false; + if (!term) { + term = getenv("TERM"); + if (!term) + return false; + } + if (strcmp(term, "cons25") == 0) + term_is_cons25 = true; + +#ifdef HAVE_TERMCAP + /* Check termcap to see if we can do colour or not */ + if (tgetent(termcapbuf, term) == 1) { + bp = tcapbuf; + _af = tgetstr("AF", &bp); + _ce = tgetstr("ce", &bp); + _ch = tgetstr("ch", &bp); + /* 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); + } + + /* 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) { +#else + if (strstr(term, "color")) + in_colour = 1; + + while (color_terms[i] && in_colour != 1) { + if (strcmp(color_terms[i], term) == 0) { + in_colour = 1; + } + i++; + } + + if (in_colour != 1) { + in_colour = 0; + return false; + } +#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 + } + + if (!_af || !_ce || !_me || !_md || !_up) { + in_colour = 0; + return false; + } + + /* Many termcap databases don't have ch or RI even though they + * do work */ + if (!_ch) + _ch = CH; +#endif + + /* Now setup our colours */ + p = ebuffer; + for (i = 0; i < ARRAY_SIZE(ecolors); ++i) { + tmp[0] = '\0'; + if (ecolors[i].name) { + bold = _md; + c = ecolors[i].def; + + /* 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"))) { + ee = strstr(e, ecolors[i].name); + if (ee) + ee += strlen(ecolors[i].name); + + if (ee && *ee == '=') { + d = strdup(ee + 1); + if (d) { + end = strchr(d, ':'); + if (end) + *end = '\0'; + c = atoi(d); + end = strchr(d, ';'); + if (end && *++end == '0') + bold = _me; + free(d); + } + } + } + strlcpy(tmp, tgoto(bold, 0, 0), sizeof(tmp)); + strlcat(tmp, tgoto(_af, 0, c & 0x07), sizeof(tmp)); + } else + _GET_CAP(tmp, _me); + + if (tmp[0]) + _ASSIGN_CAP(ecolors_str[i]); + else + ecolors_str[i] = &nullstr; + } + + _GET_CAP(tmp, _ce); + _ASSIGN_CAP(flush); + _GET_CAP(tmp, _up); + _ASSIGN_CAP(up); + strlcpy(tmp, _ch, sizeof(tmp)); + _ASSIGN_CAP(goto_column); + + in_colour = 1; + return true; +} + +static int +get_term_columns(FILE * EINFO_RESTRICT stream) +{ + struct winsize ws; + char *env = getenv("COLUMNS"); + char *p; + int i; + + if (env) { + i = strtoimax(env, &p, 10); + if (!*p) + return i; + } + + if (ioctl(fileno(stream), TIOCGWINSZ, &ws) == 0) + return ws.ws_col; + + return DEFAULT_COLS; +} + +void +eprefix(const char *EINFO_RESTRICT prefix) +{ + _eprefix = prefix; +} +hidden_def(eprefix) + +static void EINFO_PRINTF(2, 0) +elogv(int level, const char *EINFO_RESTRICT fmt, va_list ap) +{ + char *e = getenv("EINFO_LOG"); + va_list apc; + + if (fmt && e) { + closelog(); + openlog(e, LOG_PID, LOG_DAEMON); + va_copy(apc, ap); + vsyslog(level, fmt, apc); + va_end(apc); + closelog(); + } +} + +void +elog(int level, const char *EINFO_RESTRICT fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + elogv(level, fmt, ap); + va_end(ap); +} +hidden_def(elog) + +static int +_eindent(FILE * EINFO_RESTRICT stream) +{ + char *env = getenv("EINFO_INDENT"); + int amount = 0; + char indent[INDENT_MAX]; + + if (env) { + errno = 0; + amount = strtoimax(env, NULL, 0); + if (errno != 0 || amount < 0) + amount = 0; + else if (amount > INDENT_MAX) + amount = INDENT_MAX; + + if (amount > 0) + memset(indent, ' ', (size_t)amount); + } + + /* Terminate it */ + memset(indent + amount, 0, 1); + return fprintf(stream, "%s", indent); +} + +static const char * +_ecolor(FILE * EINFO_RESTRICT f, ECOLOR color) +{ + unsigned int i; + + if (!colour_terminal(f)) + return ""; + + for (i = 0; i < ARRAY_SIZE(ecolors); ++i) + if (ecolors[i].color == color) + return ecolors_str[i]; + return ""; +} +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); +} + +#define LASTCMD(_cmd) { \ + unsetenv("EINFO_LASTCMD"); \ + setenv("EINFO_LASTCMD", _cmd, 1); \ + } + +static int EINFO_PRINTF(3, 0) + _einfo(FILE *f, ECOLOR color, const char *EINFO_RESTRICT fmt, va_list va) +{ + int retval = 0; + char *last = getenv("EINFO_LASTCMD"); + va_list ap; + + if (last && + !colour_terminal(f) && + strcmp(last, "ewarn") != 0 && + last[strlen(last) - 1] == 'n') + fprintf(f, "\n"); + if (_eprefix) + fprintf(f, "%s%s%s|", _ecolor(f, color), _eprefix, _ecolor(f, ECOLOR_NORMAL)); + fprintf(f, " %s*%s ", _ecolor(f, color), _ecolor(f, ECOLOR_NORMAL)); + retval += _eindent(f); + va_copy(ap, va); + retval += vfprintf(f, fmt, ap) + 3; + va_end(ap); \ + if (colour_terminal(f)) + fprintf(f, "%s", flush); + return retval; +} + +#define _einfovn(fmt, ap) _einfo(stdout, ECOLOR_GOOD, fmt, ap) +#define _ewarnvn(fmt, ap) _einfo(stderr, ECOLOR_WARN, fmt, ap) +#define _eerrorvn(fmt, ap) _einfo(stderr, ECOLOR_BAD, fmt, ap) + +int +einfon(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || is_quiet()) + return 0; + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + va_end(ap); + LASTCMD("einfon"); + return retval; +} +hidden_def(einfon) + +int +ewarnn(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || is_quiet()) + return 0; + va_start(ap, fmt); + retval = _ewarnvn(fmt, ap); + va_end(ap); + LASTCMD("ewarnn"); + return retval; +} +hidden_def(ewarnn) + +int +eerrorn(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || is_really_quiet()) + return 0; + va_start(ap, fmt); + retval = _eerrorvn(fmt, ap); + va_end(ap); + LASTCMD("errorn"); + return retval; +} +hidden_def(eerrorn) + +int +einfo(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(einfo) + +int +ewarn(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(ewarn) + +void +ewarnx(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + } + exit(EXIT_FAILURE); +} +hidden_def(ewarnx) + +int +eerror(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || is_really_quiet()) + return 0; + va_start(ap, fmt); + elogv(LOG_ERR, fmt, ap); + retval = _eerrorvn(fmt, ap); + va_end(ap); + retval += fprintf(stderr, "\n"); + LASTCMD("eerror"); + return retval; +} +hidden_def(eerror) + +void +eerrorx(const char *EINFO_RESTRICT fmt, ...) +{ + va_list ap; + + if (fmt && !is_really_quiet()) { + va_start(ap, fmt); + elogv(LOG_ERR, fmt, ap); + _eerrorvn(fmt, ap); + va_end(ap); + fprintf(stderr, "\n"); + } + exit(EXIT_FAILURE); +} +hidden_def(eerrorx) + +int +ebegin(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(ebegin) + +static void +_eend(FILE * EINFO_RESTRICT fp, int col, ECOLOR color, const char *msg) +{ + int i; + int cols; + + if (!msg) + return; + + cols = get_term_columns(fp) - (strlen(msg) + 5); + + /* 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--; + + 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)); + } else { + if (col > 0) + for (i = 0; i < cols - col; i++) + fprintf(fp, " "); + fprintf(fp, " [ %s ]\n", msg); + } +} + +static int EINFO_PRINTF(3, 0) +_do_eend(const char *cmd, int retval, + const char *EINFO_RESTRICT fmt, va_list ap) +{ + int col = 0; + FILE *fp = stdout; + 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); + } + _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, ...) +{ + va_list ap; + + if (is_quiet()) + return retval; + va_start(ap, fmt); + _do_eend("eend", retval, fmt, ap); + va_end(ap); + LASTCMD("eend"); + return retval; +} +hidden_def(eend) + +int +ewend(int retval, const char *EINFO_RESTRICT fmt, ...) +{ + va_list ap; + + if (is_quiet()) + return retval; + va_start(ap, fmt); + _do_eend("ewend", retval, fmt, ap); + va_end(ap); + LASTCMD("ewend"); + 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"); + int amount = 0; + char num[10]; + + if (env) { + errno = 0; + amount = strtoimax(env, NULL, 0); + if (errno != 0) + amount = 0; + } + 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"); + int amount = 0; + char num[10]; + int serrno = errno; + + if (!env) + return; + errno = 0; + amount = strtoimax(env, NULL, 0); + if (errno != 0) + amount = 0; + else + amount -= INDENT_WIDTH; + if (amount <= 0) + unsetenv("EINFO_INDENT"); + else { + snprintf(num, 10, "%08d", amount); + setenv("EINFO_INDENT", num, 1); + } + errno = serrno; +} +hidden_def(eoutdent) + +int +einfovn(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || !is_verbose()) + return 0; + va_start(ap, fmt); + retval = _einfovn(fmt, ap); + va_end(ap); + LASTCMD("einfovn"); + return retval; +} +hidden_def(einfovn) + +int +ewarnvn(const char *EINFO_RESTRICT fmt, ...) +{ + int retval; + va_list ap; + + if (!fmt || !is_verbose()) + return 0; + va_start(ap, fmt); + retval = _ewarnvn(fmt, ap); + va_end(ap); + LASTCMD("ewarnvn"); + return retval; +} +hidden_def(ewarnvn) + +int +einfov(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(einfov) + +int +ewarnv(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(ewarnv) + +int +ebeginv(const char *EINFO_RESTRICT fmt, ...) +{ + 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"); + return retval; +} +hidden_def(ebeginv) + +int +eendv(int retval, const char *EINFO_RESTRICT fmt, ...) +{ + va_list ap; + + if (!is_verbose()) + return 0; + va_start(ap, fmt); + _do_eend("eendv", retval, fmt, ap); + va_end(ap); + LASTCMD("eendv"); + return retval; +} +hidden_def(eendv) + +int +ewendv(int retval, const char *EINFO_RESTRICT fmt, ...) +{ + va_list ap; + + if (!is_verbose()) + return 0; + va_start(ap, fmt); + _do_eend("ewendv", retval, fmt, ap); + va_end(ap); + LASTCMD("ewendv"); + return retval; +} +hidden_def(ewendv) + +void +eindentv(void) +{ + if (is_verbose()) + eindent(); +} +hidden_def(eindentv) + +void +eoutdentv(void) +{ + if (is_verbose()) + eoutdent(); +} +hidden_def(eoutdentv) diff --git a/src/rc/Makefile b/src/rc/Makefile index 6490826..a2e638e 100644 --- a/src/rc/Makefile +++ b/src/rc/Makefile @@ -1,21 +1,8 @@ PROG= rc -SRCS= \ - checkpath.c \ - einfo.c \ - fstabinfo.c \ - mountinfo.c \ - rc-applets.c \ - rc-depend.c \ - rc-logger.c \ - rc-misc.c \ - rc-plugin.c \ - rc-service.c \ - rc-status.c \ - rc-update.c \ - rc.c \ - runscript.c \ - start-stop-daemon.c \ - swclock.c +SRCS= checkpath.c fstabinfo.c mountinfo.c start-stop-daemon.c \ + rc-applets.c rc-depend.c rc-logger.c \ + rc-misc.c rc-plugin.c rc-service.c rc-status.c rc-update.c \ + runscript.c rc.c swclock.c CLEANFILES= version.h @@ -43,9 +30,9 @@ RC_SBINLINKS= mark_service_starting mark_service_started \ ALL_LINKS= ${BINLINKS} ${SBINLINKS} ${RC_BINLINKS} ${RC_SBINLINKS} CLEANFILES+= ${ALL_LINKS} -CPPFLAGS+= -I../includes -I../librc -LDFLAGS+= -L../librc -LDADD+= -lutil -lrc +CPPFLAGS+= -I../includes -I../librc -I../libeinfo +LDFLAGS+= -L../librc -L../libeinfo +LDADD+= -lutil -lrc -leinfo include ../../Makefile.inc MK= ../../mk diff --git a/src/rc/einfo.c b/src/rc/einfo.c deleted file mode 100644 index 306e788..0000000 --- a/src/rc/einfo.c +++ /dev/null @@ -1,1016 +0,0 @@ -/* - einfo.c - Informational functions -*/ - -/* - * Copyright (c) 2007-2008 Roy Marples - * - * 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 -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef HAVE_TERMCAP -# include -#endif -#include - -#include "einfo.h" -#include "helpers.h" - -/* Incase we cannot work out how many columns from ioctl, supply a default */ -#define DEFAULT_COLS 80 - -#define OK "ok" -#define NOT_OK "!!" - -/* Number of spaces for an indent */ -#define INDENT_WIDTH 2 - -/* How wide can the indent go? */ -#define INDENT_MAX 40 - -/* Default colours */ -#define GOOD 2 -#define WARN 3 -#define BAD 1 -#define HILITE 6 -#define BRACKET 4 - -/* 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)); -#define _ASSIGN_CAP(_v) do { \ - _v = p; \ - p += strlcpy(p, tmp, sizeof(ebuffer) - (p - ebuffer)) + 1; \ - } while (0) - -/* 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; - 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 }, -}; -static const char *ecolors_str[ARRAY_SIZE(ecolors)]; - -static char *flush = NULL; -static char *up = NULL; -static char *goto_column = NULL; - -static const char *term = NULL; -static bool term_is_cons25 = false; - -/* Termcap buffers and pointers - * 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 - * Only terminals without "color" in the name need to be explicitly listed */ -static const char *const color_terms[] = { - "Eterm", - "ansi", - "con132x25", - "con132x30", - "con132x43", - "con132x60", - "con80x25", - "con80x28", - "con80x30", - "con80x43", - "con80x50", - "con80x60", - "cons25", - "console", - "cygwin", - "dtterm", - "gnome", - "konsole", - "kterm", - "linux", - "linux-c", - "mlterm", - "putty", - "rxvt", - "rxvt-cygwin", - "rxvt-cygwin-native", - "rxvt-unicode", - "screen", - "screen-bce", - "screen-w", - "screen.linux", - "vt100", - "vt220", - "wsvt25", - "xterm", - "xterm-debian", - NULL -}; -#endif - -/* 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) -{ - 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); - - while (*s != '\0') { - if (src_n != 1) { - *d++ = *s; - src_n--; - } - s++; - } - *d = '\0'; - - return dst_n + (s - src); -} -# 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) -{ - int serrno = errno; - bool retval; - - errno = 0; - retval = yesno(value); - if (errno == 0) { - retval = !retval; - errno = serrno; - } - - return retval; -} - -static bool -is_quiet(void) -{ - return yesno(getenv("EINFO_QUIET")); -} - -static bool -is_really_quiet(void) -{ - return yesno(getenv("EERROR_QUIET")); -} - -static bool -is_verbose(void) -{ - return yesno(getenv ("EINFO_VERBOSE")); -} - -/* Fake tgoto call - very crapy, but works for our needs */ -#ifndef HAVE_TERMCAP -static char * -tgoto(const char *cap, int col, int line) -{ - static char buf[20]; - char *p, *e, c, dbuf[6]; - int oncol = 0, which = line, i; - - p = buf; - e = p + sizeof(buf); - while ((c = *cap++)) { - if (c != '%' || ((c = *cap++) == '%')) { - *p++ = c; - if (p >= e) { - errno = E2BIG; - return NULL; - } - continue; - } - switch (c) { - case '3': - case '2': - case 'd': - i = 0; - do - dbuf[i++] = which % 10 | '0'; - while ((which /= 10)); - if (c != 'd') { - c -= '0'; - if (i > c) { - errno = EINVAL; - return NULL; - } - while (i < c) - dbuf[i++] = '0'; - } - if (p + i >= e) { - errno = E2BIG; - return NULL; - } - do - *p++ = dbuf[--i]; - while (i); - break; - case 'r': - oncol = 0; - break; - case 'i': - col++; - line++; - which++; - continue; - default: - errno = EINVAL; - return NULL; - } - - oncol = 1 - oncol; - which = oncol ? col : line; - } - *p = '\0'; - return buf; -} -#endif - -static bool -colour_terminal(FILE *f) -{ - static int in_colour = -1; - char *e, *ee, *end, *d, *p; - int c; - const char *_af = NULL, *_ce = NULL, *_ch = NULL; - const char *_md = NULL, *_me = NULL, *_up = NULL; - const char *bold; - char tmp[100]; - unsigned int i = 0; -#ifdef HAVE_TERMCAP - char *bp; -#endif - - if (f && !isatty(fileno(f))) - return false; - - if (noyes(getenv("EINFO_COLOR"))) - return false; - - if (in_colour == 0) - return false; - if (in_colour == 1) - return true; - - term_is_cons25 = false; - if (!term) { - term = getenv("TERM"); - if (!term) - return false; - } - if (strcmp(term, "cons25") == 0) - term_is_cons25 = true; - -#ifdef HAVE_TERMCAP - /* Check termcap to see if we can do colour or not */ - if (tgetent(termcapbuf, term) == 1) { - bp = tcapbuf; - _af = tgetstr("AF", &bp); - _ce = tgetstr("ce", &bp); - _ch = tgetstr("ch", &bp); - /* 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); - } - - /* 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) { -#else - if (strstr(term, "color")) - in_colour = 1; - - while (color_terms[i] && in_colour != 1) { - if (strcmp(color_terms[i], term) == 0) { - in_colour = 1; - } - i++; - } - - if (in_colour != 1) { - in_colour = 0; - return false; - } -#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 - } - - if (!_af || !_ce || !_me || !_md || !_up) { - in_colour = 0; - return false; - } - - /* Many termcap databases don't have ch or RI even though they - * do work */ - if (!_ch) - _ch = CH; -#endif - - /* Now setup our colours */ - p = ebuffer; - for (i = 0; i < ARRAY_SIZE(ecolors); ++i) { - tmp[0] = '\0'; - if (ecolors[i].name) { - bold = _md; - c = ecolors[i].def; - - /* 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"))) { - ee = strstr(e, ecolors[i].name); - if (ee) - ee += strlen(ecolors[i].name); - - if (ee && *ee == '=') { - d = strdup(ee + 1); - if (d) { - end = strchr(d, ':'); - if (end) - *end = '\0'; - c = atoi(d); - end = strchr(d, ';'); - if (end && *++end == '0') - bold = _me; - free(d); - } - } - } - strlcpy(tmp, tgoto(bold, 0, 0), sizeof(tmp)); - strlcat(tmp, tgoto(_af, 0, c & 0x07), sizeof(tmp)); - } else - _GET_CAP(tmp, _me); - - if (tmp[0]) - _ASSIGN_CAP(ecolors_str[i]); - else - ecolors_str[i] = &nullstr; - } - - _GET_CAP(tmp, _ce); - _ASSIGN_CAP(flush); - _GET_CAP(tmp, _up); - _ASSIGN_CAP(up); - strlcpy(tmp, _ch, sizeof(tmp)); - _ASSIGN_CAP(goto_column); - - in_colour = 1; - return true; -} - -static int -get_term_columns(FILE *stream) -{ - struct winsize ws; - char *env = getenv("COLUMNS"); - char *p; - int i; - - if (env) { - i = strtoimax(env, &p, 10); - if (!*p) - return i; - } - - if (ioctl(fileno(stream), TIOCGWINSZ, &ws) == 0) - return ws.ws_col; - - return DEFAULT_COLS; -} - -void -eprefix(const char *prefix) -{ - _eprefix = prefix; -} - -static void EINFO_PRINTF(2, 0) -elogv(int level, const char *fmt, va_list ap) -{ - char *e = getenv("EINFO_LOG"); - va_list apc; - - if (fmt && e) { - closelog(); - openlog(e, LOG_PID, LOG_DAEMON); - va_copy(apc, ap); - vsyslog(level, fmt, apc); - va_end(apc); - closelog(); - } -} - -void -elog(int level, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - elogv(level, fmt, ap); - va_end(ap); -} - -static int -_eindent(FILE *stream) -{ - char *env = getenv("EINFO_INDENT"); - int amount = 0; - char indent[INDENT_MAX]; - - if (env) { - errno = 0; - amount = strtoimax(env, NULL, 0); - if (errno != 0 || amount < 0) - amount = 0; - else if (amount > INDENT_MAX) - amount = INDENT_MAX; - - if (amount > 0) - memset(indent, ' ', (size_t)amount); - } - - /* Terminate it */ - memset(indent + amount, 0, 1); - return fprintf(stream, "%s", indent); -} - -static const char * -_ecolor(FILE *f, ECOLOR color) -{ - unsigned int i; - - if (!colour_terminal(f)) - return ""; - - for (i = 0; i < ARRAY_SIZE(ecolors); ++i) - if (ecolors[i].color == color) - return ecolors_str[i]; - return ""; -} - -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); -} - -#define LASTCMD(_cmd) { \ - unsetenv("EINFO_LASTCMD"); \ - setenv("EINFO_LASTCMD", _cmd, 1); \ - } - -static int EINFO_PRINTF(3, 0) - _einfo(FILE *f, ECOLOR color, const char *fmt, va_list va) -{ - int retval = 0; - char *last = getenv("EINFO_LASTCMD"); - va_list ap; - - if (last && - !colour_terminal(f) && - strcmp(last, "ewarn") != 0 && - last[strlen(last) - 1] == 'n') - fprintf(f, "\n"); - if (_eprefix) - fprintf(f, "%s%s%s|", _ecolor(f, color), _eprefix, _ecolor(f, ECOLOR_NORMAL)); - fprintf(f, " %s*%s ", _ecolor(f, color), _ecolor(f, ECOLOR_NORMAL)); - retval += _eindent(f); - va_copy(ap, va); - retval += vfprintf(f, fmt, ap) + 3; - va_end(ap); \ - if (colour_terminal(f)) - fprintf(f, "%s", flush); - return retval; -} - -#define _einfovn(fmt, ap) _einfo(stdout, ECOLOR_GOOD, fmt, ap) -#define _ewarnvn(fmt, ap) _einfo(stderr, ECOLOR_WARN, fmt, ap) -#define _eerrorvn(fmt, ap) _einfo(stderr, ECOLOR_BAD, fmt, ap) - -int -einfon(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || is_quiet()) - return 0; - va_start(ap, fmt); - retval = _einfovn(fmt, ap); - va_end(ap); - LASTCMD("einfon"); - return retval; -} - -int -ewarnn(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || is_quiet()) - return 0; - va_start(ap, fmt); - retval = _ewarnvn(fmt, ap); - va_end(ap); - LASTCMD("ewarnn"); - return retval; -} - -int -eerrorn(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || is_really_quiet()) - return 0; - va_start(ap, fmt); - retval = _eerrorvn(fmt, ap); - va_end(ap); - LASTCMD("errorn"); - return retval; -} - -int -einfo(const char *fmt, ...) -{ - 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"); - return retval; -} - -int -ewarn(const char *fmt, ...) -{ - 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"); - return retval; -} - -void -ewarnx(const char *fmt, ...) -{ - 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"); - } - exit(EXIT_FAILURE); -} - -int -eerror(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || is_really_quiet()) - return 0; - va_start(ap, fmt); - elogv(LOG_ERR, fmt, ap); - retval = _eerrorvn(fmt, ap); - va_end(ap); - retval += fprintf(stderr, "\n"); - LASTCMD("eerror"); - return retval; -} - -void -eerrorx(const char *fmt, ...) -{ - va_list ap; - - if (fmt && !is_really_quiet()) { - va_start(ap, fmt); - elogv(LOG_ERR, fmt, ap); - _eerrorvn(fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); - } - exit(EXIT_FAILURE); -} - -int -ebegin(const char *fmt, ...) -{ - 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"); - return retval; -} - -static void -_eend(FILE *fp, int col, ECOLOR color, const char *msg) -{ - int i; - int cols; - - if (!msg) - return; - - cols = get_term_columns(fp) - (strlen(msg) + 5); - - /* 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--; - - 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)); - } else { - if (col > 0) - for (i = 0; i < cols - col; i++) - fprintf(fp, " "); - fprintf(fp, " [ %s ]\n", msg); - } -} - -static int EINFO_PRINTF(3, 0) -_do_eend(const char *cmd, int retval, - const char *fmt, va_list ap) -{ - int col = 0; - FILE *fp = stdout; - 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); - } - _eend(fp, col, - retval == 0 ? ECOLOR_GOOD : ECOLOR_BAD, - retval == 0 ? OK : NOT_OK); - return retval; -} - -int -eend(int retval, const char *fmt, ...) -{ - va_list ap; - - if (is_quiet()) - return retval; - va_start(ap, fmt); - _do_eend("eend", retval, fmt, ap); - va_end(ap); - LASTCMD("eend"); - return retval; -} - -int -ewend(int retval, const char *fmt, ...) -{ - va_list ap; - - if (is_quiet()) - return retval; - va_start(ap, fmt); - _do_eend("ewend", retval, fmt, ap); - va_end(ap); - LASTCMD("ewend"); - return retval; -} - -void -ebracket(int col, ECOLOR color, const char *msg) -{ - _eend(stdout, col, color, msg); -} - -void -eindent(void) -{ - char *env = getenv("EINFO_INDENT"); - int amount = 0; - char num[10]; - - if (env) { - errno = 0; - amount = strtoimax(env, NULL, 0); - if (errno != 0) - amount = 0; - } - amount += INDENT_WIDTH; - if (amount > INDENT_MAX) - amount = INDENT_MAX; - snprintf(num, 10, "%08d", amount); - setenv("EINFO_INDENT", num, 1); -} - -void eoutdent(void) -{ - char *env = getenv("EINFO_INDENT"); - int amount = 0; - char num[10]; - int serrno = errno; - - if (!env) - return; - errno = 0; - amount = strtoimax(env, NULL, 0); - if (errno != 0) - amount = 0; - else - amount -= INDENT_WIDTH; - if (amount <= 0) - unsetenv("EINFO_INDENT"); - else { - snprintf(num, 10, "%08d", amount); - setenv("EINFO_INDENT", num, 1); - } - errno = serrno; -} - -int -einfovn(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || !is_verbose()) - return 0; - va_start(ap, fmt); - retval = _einfovn(fmt, ap); - va_end(ap); - LASTCMD("einfovn"); - return retval; -} - -int -ewarnvn(const char *fmt, ...) -{ - int retval; - va_list ap; - - if (!fmt || !is_verbose()) - return 0; - va_start(ap, fmt); - retval = _ewarnvn(fmt, ap); - va_end(ap); - LASTCMD("ewarnvn"); - return retval; -} - -int -einfov(const char *fmt, ...) -{ - 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"); - return retval; -} - -int -ewarnv(const char *fmt, ...) -{ - 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"); - return retval; -} - -int -ebeginv(const char *fmt, ...) -{ - 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"); - return retval; -} - -int -eendv(int retval, const char *fmt, ...) -{ - va_list ap; - - if (!is_verbose()) - return 0; - va_start(ap, fmt); - _do_eend("eendv", retval, fmt, ap); - va_end(ap); - LASTCMD("eendv"); - return retval; -} - -int -ewendv(int retval, const char *fmt, ...) -{ - va_list ap; - - if (!is_verbose()) - return 0; - va_start(ap, fmt); - _do_eend("ewendv", retval, fmt, ap); - va_end(ap); - LASTCMD("ewendv"); - return retval; -} - -void -eindentv(void) -{ - if (is_verbose()) - eindent(); -} - -void -eoutdentv(void) -{ - if (is_verbose()) - eoutdent(); -} diff --git a/src/rc/einfo.h b/src/rc/einfo.h deleted file mode 100644 index 5764569..0000000 --- a/src/rc/einfo.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2007-2008 Roy Marples - * - * 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. - */ - -#ifndef __EINFO_H__ -#define __EINFO_H__ - -#if defined(__GNUC__) -# define EINFO_PRINTF(a, b) __attribute__((__format__(__printf__, a, b))) -# define EINFO_XPRINTF(a, b) __attribute__((__noreturn__,__format__(__printf__, a, b))) -#else -# define EINFO_PRINTF(a, b) -# define EINFO_XPRINTF(a, b) -#endif - -#include -#include - -/*! @brief Color types to use */ -typedef enum -{ - ECOLOR_NORMAL = 1, - ECOLOR_GOOD = 2, - ECOLOR_WARN = 3, - ECOLOR_BAD = 4, - ECOLOR_HILITE = 5, - ECOLOR_BRACKET = 6 -} ECOLOR; - -/*! @brief Returns the ASCII code for the color */ -const char *ecolor(ECOLOR); - -/*! @brief Writes to syslog. */ -void elog(int, const char *, ...) EINFO_PRINTF(2, 3); - -/*! - * @brief Display informational messages. - * - * The einfo family of functions display messages in a consistent manner - * Basically they prefix the message with " * ". - * If the terminal can handle color then we color the * based on - * the command used. Otherwise we are identical to the printf function. - * - * - einfo - green - * - ewarn - yellow - * - eerror - red - * - * The n suffix denotes that no new line should be printed. - * The v suffix means only print if EINFO_VERBOSE is yes. - */ -/*@{*/ -int einfon(const char *, ...) EINFO_PRINTF(1, 2); -int ewarnn(const char *, ...) EINFO_PRINTF(1, 2); -int eerrorn(const char *, ...) EINFO_PRINTF(1, 2); -int einfo(const char *, ...) EINFO_PRINTF(1, 2); -int ewarn(const char *, ...) EINFO_PRINTF(1, 2); -void ewarnx(const char *, ...) EINFO_XPRINTF(1, 2); -int eerror(const char *, ...) EINFO_PRINTF(1, 2); -void eerrorx(const char *, ...) EINFO_XPRINTF(1, 2); - -int einfovn(const char *, ...) EINFO_PRINTF(1, 2); -int ewarnvn(const char * , ...) EINFO_PRINTF(1, 2); -int ebeginvn(const char *, ...) EINFO_PRINTF(1, 2); -int eendvn(int, const char *, ...) EINFO_PRINTF(2, 3); -int ewendvn(int, const char *, ...) EINFO_PRINTF(2, 3); -int einfov(const char *, ...) EINFO_PRINTF(1, 2); -int ewarnv(const char *, ...) EINFO_PRINTF(1, 2); -/*@}*/ - -/*! @ingroup ebegin - * @brief Display informational messages that may take some time. - * - * Similar to einfo, but we add ... to the end of the message */ -/*@{*/ -int ebeginv(const char *, ...) EINFO_PRINTF(1, 2); -int ebegin(const char *, ...) EINFO_PRINTF(1, 2); -/*@}*/ - -/*! @ingroup eend - * @brief End an ebegin. - * - * If you ebegin, you should eend also. - * eend places [ ok ] or [ !! ] at the end of the terminal line depending on - * retval (0 or ok, anything else for !!) - * - * ebracket allows you to specifiy the position, color and message */ -/*@{*/ -int eend(int, const char *, ...) EINFO_PRINTF(2, 3); -int ewend(int, const char *, ...) EINFO_PRINTF(2, 3); -void ebracket(int, ECOLOR, const char *); - -int eendv(int, const char *, ...) EINFO_PRINTF(2, 3); -int ewendv(int, const char *, ...) EINFO_PRINTF(2, 3); -/*@}*/ - -/*! @ingroup eindent - * @brief Indents the einfo lines. - * - * For each indent you should outdent when done */ -/*@{*/ -void eindent(void); -void eoutdent(void); -void eindentv(void); -void eoutdentv(void); - -/*! @brief Prefix each einfo line with something */ -void eprefix(const char *); - -#endif diff --git a/src/test/einfo.data.list b/src/test/einfo.data.list new file mode 100644 index 0000000..c638b2f --- /dev/null +++ b/src/test/einfo.data.list @@ -0,0 +1 @@ +EINFO_1.0 diff --git a/src/test/einfo.funcs.list b/src/test/einfo.funcs.list new file mode 100644 index 0000000..5dbbd96 --- /dev/null +++ b/src/test/einfo.funcs.list @@ -0,0 +1,52 @@ +ebegin +ebegin@@EINFO_1.0 +ebeginv +ebeginv@@EINFO_1.0 +ebracket +ebracket@@EINFO_1.0 +ecolor +ecolor@@EINFO_1.0 +eend +eend@@EINFO_1.0 +eendv +eendv@@EINFO_1.0 +eerror +eerror@@EINFO_1.0 +eerrorn +eerrorn@@EINFO_1.0 +eerrorx +eerrorx@@EINFO_1.0 +eindent +eindent@@EINFO_1.0 +eindentv +eindentv@@EINFO_1.0 +einfo +einfo@@EINFO_1.0 +einfon +einfon@@EINFO_1.0 +einfov +einfov@@EINFO_1.0 +einfovn +einfovn@@EINFO_1.0 +elog +elog@@EINFO_1.0 +eoutdent +eoutdent@@EINFO_1.0 +eoutdentv +eoutdentv@@EINFO_1.0 +eprefix +eprefix@@EINFO_1.0 +ewarn +ewarn@@EINFO_1.0 +ewarnn +ewarnn@@EINFO_1.0 +ewarnv +ewarnv@@EINFO_1.0 +ewarnvn +ewarnvn@@EINFO_1.0 +ewarnx +ewarnx@@EINFO_1.0 +ewend +ewend@@EINFO_1.0 +ewendv +ewendv@@EINFO_1.0 diff --git a/src/test/runtests.sh b/src/test/runtests.sh index b5b053f..5a87c84 100755 --- a/src/test/runtests.sh +++ b/src/test/runtests.sh @@ -3,6 +3,8 @@ top_srcdir=${top_srcdir:-../..} . ${top_srcdir}/test/setup_env.sh +libeinfo_srcdir="${srcdir}/../libeinfo" +libeinfo_builddir="${builddir}/../libeinfo" librc_srcdir="${srcdir}/../librc" librc_builddir="${builddir}/../librc" rc_srcdir="${srcdir}/../rc" @@ -18,6 +20,22 @@ checkit() { ret=0 +ebegin "Checking exported symbols in libeinfo.so (data)" +checkit einfo.data $( +readelf -Ws ${libeinfo_builddir}/libeinfo.so \ + | awk '$4 == "OBJECT" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \ + | LC_ALL=C sort -u +) + +ebegin "Checking exported symbols in libeinfo.so (functions)" +checkit einfo.funcs $( +readelf -Ws ${libeinfo_builddir}/libeinfo.so \ + | awk '$4 == "FUNC" && $5 == "GLOBAL" && $7 != "UND" {print $NF}' \ + | LC_ALL=C sort -u \ + | egrep -v \ + -e '^_(init|fini)$' +) + ebegin "Checking exported symbols in librc.so (data)" checkit rc.data $( readelf -Ws ${librc_builddir}/librc.so \ -- cgit v1.2.3