mirror of
https://github.com/inspircd/inspircd.git
synced 2025-03-08 17:19:01 -05:00
Remove rang and use fmtlib for printing coloured messages.
This supports more platforms (e.g. Haiku) and is actually still maintained unlike the former. All of this code should really be cleaned up for release (maybe by adding something like Anope's LOG_CONSOLE) but for now I've just replaced it with the fmtlib equivalent.
This commit is contained in:
parent
3854c3f8e3
commit
f0d817cf39
@ -31,7 +31,6 @@
|
||||
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#ifndef _WIN32
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
@ -507,9 +506,11 @@ void ServerConfig::Apply(ServerConfig* old, const std::string& useruid)
|
||||
getline(errstr, line, '\n');
|
||||
if (line.empty())
|
||||
continue;
|
||||
|
||||
// On startup, print out to console (still attached at this point)
|
||||
if (!old)
|
||||
std::cout << line << std::endl;
|
||||
fmt::println(line);
|
||||
|
||||
// If a user is rehashing, tell them directly
|
||||
if (user)
|
||||
user->WriteRemoteNotice(INSP_FORMAT("*** {}", line));
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "modules/dns.h"
|
||||
#include "modules/stats.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -36,8 +36,8 @@
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <fmt/color.h>
|
||||
#include <lyra/lyra.hpp>
|
||||
#include <rang/rang.hpp>
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "exitcodes.h"
|
||||
@ -48,6 +48,7 @@
|
||||
# include <grp.h>
|
||||
# include <pwd.h>
|
||||
# include <sys/resource.h>
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# define STDIN_FILENO 0
|
||||
# define STDOUT_FILENO 1
|
||||
@ -77,21 +78,21 @@ namespace
|
||||
if (getegid() != 0 && geteuid() != 0)
|
||||
return;
|
||||
|
||||
std::cout << rang::style::bold << rang::fg::red << "Warning!" << rang::style::reset << " You have started as root. Running as root is generally not required" << std::endl
|
||||
<< "and may allow an attacker to gain access to your system if they find a way to" << std::endl
|
||||
<< "exploit your IRC server." << std::endl
|
||||
<< std::endl;
|
||||
fmt::println("{} You have started as root. Running as root is generally not required", fmt::styled("Warning!", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)));
|
||||
fmt::println("and may allow an attacker to gain access to your system if they find a way to");
|
||||
fmt::println("exploit your IRC server.");
|
||||
fmt::println("");
|
||||
if (isatty(fileno(stdout)))
|
||||
{
|
||||
std::cout << "InspIRCd will start in 30 seconds. If you are sure that you need to run as root" << std::endl
|
||||
<< "then you can pass the " << rang::style::bold << "--runasroot" << rang::style::reset << " option to disable this wait." << std::endl;
|
||||
fmt::println("InspIRCd will start in 30 seconds. If you are sure that you need to run as root");
|
||||
fmt::println("then you can pass the {} option to disable this wait.", fmt::styled("--runasroot", fmt::emphasis::bold));
|
||||
sleep(30);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "If you are sure that you need to run as root then you can pass the " << rang::style::bold << "--runasroot" << rang::style::reset << std::endl
|
||||
<< "option to disable this error." << std::endl;
|
||||
ServerInstance->Exit(EXIT_STATUS_ROOT);
|
||||
fmt::println("If you are sure that you need to run as root then you can pass the {}", fmt::styled("--runasroot", fmt::emphasis::bold));
|
||||
fmt::println("option to disable this error.");
|
||||
ServerInstance->Exit(EXIT_STATUS_ROOT);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@ -235,7 +236,7 @@ namespace
|
||||
if (childpid < 0)
|
||||
{
|
||||
ServerInstance->Logs.Error("STARTUP", "fork() failed: {}", strerror(errno));
|
||||
std::cout << rang::style::bold << rang::fg::red << "Error:" << rang::style::reset << " unable to fork into background: " << strerror(errno);
|
||||
fmt::println("{} unable to fork into background: {}", fmt::styled("Error:", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), strerror(errno));
|
||||
ServerInstance->Exit(EXIT_STATUS_FORK);
|
||||
}
|
||||
else if (childpid > 0)
|
||||
@ -316,7 +317,7 @@ namespace
|
||||
auto result = cli.parse({ServerInstance->Config->CommandLine.argc, ServerInstance->Config->CommandLine.argv});
|
||||
if (!result)
|
||||
{
|
||||
std::cerr << rang::style::bold << rang::fg::red << "Error: " << rang::style::reset << result.message() << '.' << std::endl;
|
||||
fmt::println(stderr, "{} {}", fmt::styled("Error:", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), result.message());
|
||||
ServerInstance->Exit(EXIT_STATUS_ARGV);
|
||||
}
|
||||
|
||||
@ -328,7 +329,7 @@ namespace
|
||||
|
||||
if (do_version)
|
||||
{
|
||||
std::cout << INSPIRCD_VERSION << std::endl;
|
||||
fmt::println(INSPIRCD_VERSION);
|
||||
ServerInstance->Exit(EXIT_STATUS_NOERROR);
|
||||
}
|
||||
|
||||
@ -373,24 +374,24 @@ namespace
|
||||
|
||||
if (!pl.empty())
|
||||
{
|
||||
std::cout << rang::style::bold << rang::fg::red << "Warning!" << rang::style::reset << " Some of your listener" << (pl.size() == 1 ? "s" : "") << " failed to bind:" << std::endl
|
||||
<< std::endl;
|
||||
fmt::println("{} Some of your listeners failed to bind:", fmt::styled("Warning!", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)));
|
||||
fmt::println("");
|
||||
|
||||
for (const auto& fp : pl)
|
||||
{
|
||||
std::cout << " ";
|
||||
fmt::print(" ");
|
||||
if (fp.sa.family() != AF_UNSPEC)
|
||||
std::cout << rang::style::bold << fp.sa.str() << rang::style::reset << ": ";
|
||||
fmt::print("{}: ", fmt::styled(fp.sa.str(), fmt::emphasis::bold));
|
||||
|
||||
std::cout << fp.error << '.' << std::endl
|
||||
<< " " << "Created from <bind> tag at " << fp.tag->source.str() << std::endl
|
||||
<< std::endl;
|
||||
fmt::println("{}.", fp.error);
|
||||
fmt::println("Created from <bind> tag at {}", fp.tag->source.str());
|
||||
fmt::println("");
|
||||
}
|
||||
|
||||
std::cout << rang::style::bold << "Hints:" << rang::style::reset << std::endl
|
||||
<< "- For TCP/IP listeners try using a public IP address in <bind:address> instead" << std::endl
|
||||
<< " of * or leaving it blank." << std::endl
|
||||
<< "- For UNIX socket listeners try enabling <bind:rewrite> to replace old sockets." << std::endl;
|
||||
fmt::print(fmt::text_style(fmt::emphasis::bold), "Hints:");
|
||||
fmt::println("- For TCP/IP listeners try using a public IP address in <bind:address> instead");
|
||||
fmt::println(" of * or leaving it blank.");
|
||||
fmt::println("- For UNIX socket listeners try enabling <bind:rewrite> to replace old sockets.");
|
||||
}
|
||||
}
|
||||
|
||||
@ -454,7 +455,7 @@ void InspIRCd::WritePID()
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Failed to write PID-file '" << pidfile << "', exiting." << std::endl;
|
||||
fmt::println("Failed to write PID-file '{}', exiting.", pidfile);
|
||||
this->Logs.Error("STARTUP", "Failed to write PID-file '{}', exiting.", pidfile);
|
||||
Exit(EXIT_STATUS_PID);
|
||||
}
|
||||
@ -489,9 +490,9 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
Modules.AddServices(provs, sizeof(provs)/sizeof(provs[0]));
|
||||
}
|
||||
|
||||
std::cout << rang::style::bold << rang::fg::green << "InspIRCd - Internet Relay Chat Daemon" << rang::style::reset << std::endl
|
||||
<< "See " << rang::style::bold << rang::fg::green << "/INFO" << rang::style::reset << " for contributors & authors" << std::endl
|
||||
<< std::endl;
|
||||
fmt::println("{}", fmt::styled("InspIRCd - Internet Relay Chat Daemon", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::green)));
|
||||
fmt::println("See {} for contributors & authors", fmt::styled("/INFO", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::green)));
|
||||
fmt::println("");
|
||||
|
||||
Logs.RegisterServices();
|
||||
if (Config->CommandLine.forcedebug)
|
||||
@ -500,7 +501,8 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
if (!FindConfigFile(ConfigFileName))
|
||||
{
|
||||
this->Logs.Error("STARTUP", "Unable to open config file {}", ConfigFileName);
|
||||
std::cout << "ERROR: Cannot open config file: " << ConfigFileName << std::endl << "Exiting..." << std::endl;
|
||||
fmt::println("ERROR: Cannot open config file: {}", ConfigFileName);
|
||||
fmt::println("Exiting...");
|
||||
Exit(EXIT_STATUS_CONFIG);
|
||||
}
|
||||
|
||||
@ -510,7 +512,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
if (!Config->CommandLine.nofork)
|
||||
ForkIntoBackground();
|
||||
|
||||
std::cout << "InspIRCd Process ID: " << rang::style::bold << rang::fg::green << getpid() << rang::style::reset << std::endl;
|
||||
fmt::println("InspIRCd Process ID: {}", fmt::styled(getpid(), fmt::emphasis::bold | fmt::fg(fmt::terminal_color::green)));
|
||||
|
||||
/* During startup we read the configuration now, not in
|
||||
* a separate thread
|
||||
@ -525,7 +527,8 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
}
|
||||
catch (const CoreException& ex)
|
||||
{
|
||||
std::cout << "ERROR: Cannot open log files: " << ex.GetReason() << std::endl << "Exiting..." << std::endl;
|
||||
fmt::println("ERROR: Cannot open log files: {}", ex.GetReason());
|
||||
fmt::println("Exiting...");
|
||||
Exit(EXIT_STATUS_LOG);
|
||||
}
|
||||
|
||||
@ -542,7 +545,7 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
// This is needed as all new XLines are marked pending until ApplyLines() is called
|
||||
this->XLines->ApplyLines();
|
||||
|
||||
std::cout << std::endl;
|
||||
fmt::println("");
|
||||
|
||||
TryBindPorts();
|
||||
|
||||
@ -555,18 +558,20 @@ InspIRCd::InspIRCd(int argc, char** argv)
|
||||
}
|
||||
catch (const CoreException& ex)
|
||||
{
|
||||
std::cout << "ERROR: Cannot open log files: " << ex.GetReason() << std::endl << "Exiting..." << std::endl;
|
||||
fmt::println("ERROR: Cannot open log files: {}", ex.GetReason());
|
||||
fmt::println("Exiting...");
|
||||
Exit(EXIT_STATUS_LOG);
|
||||
}
|
||||
|
||||
std::cout << "InspIRCd is now running as '" << Config->ServerName << "'[" << Config->ServerId << "] with " << SocketEngine::GetMaxFds() << " max open sockets" << std::endl;
|
||||
fmt::println("InspIRCd is now running as '{}'[{}] with {} max open sockets",
|
||||
Config->ServerName, Config->ServerId, SocketEngine::GetMaxFds());
|
||||
|
||||
#ifndef _WIN32
|
||||
if (!Config->CommandLine.nofork)
|
||||
{
|
||||
if (kill(getppid(), SIGTERM) == -1)
|
||||
{
|
||||
std::cout << "Error killing parent process: " << strerror(errno) << std::endl;
|
||||
fmt::println("Error killing parent process: {}", strerror(errno));
|
||||
Logs.Warning("STARTUP", "Error killing parent process: {}", strerror(errno));
|
||||
}
|
||||
}
|
||||
|
@ -23,9 +23,8 @@
|
||||
|
||||
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
|
||||
#include <rang/rang.hpp>
|
||||
#include <fmt/color.h>
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "dynamic.h"
|
||||
@ -128,7 +127,8 @@ bool ModuleManager::Load(const std::string& modname, bool defer)
|
||||
/* We must load the modules AFTER initializing the socket engine, now */
|
||||
void ModuleManager::LoadCoreModules(std::map<std::string, ServiceList>& servicemap)
|
||||
{
|
||||
std::cout << "Loading core modules " << std::flush;
|
||||
fmt::print("Loading core modules ");
|
||||
fflush(stdout);
|
||||
|
||||
try
|
||||
{
|
||||
@ -141,21 +141,24 @@ void ModuleManager::LoadCoreModules(std::map<std::string, ServiceList>& servicem
|
||||
if (!InspIRCd::Match(name, "core_*" DLL_EXTENSION))
|
||||
continue;
|
||||
|
||||
std::cout << "." << std::flush;
|
||||
fmt::print(".");
|
||||
fflush(stdout);
|
||||
this->NewServices = &servicemap[name];
|
||||
|
||||
if (!Load(name, true))
|
||||
{
|
||||
std::cout << std::endl << "[" << rang::style::bold << rang::fg::red << "*" << rang::style::reset << "] " << this->LastError() << std::endl << std::endl;
|
||||
fmt::println("");
|
||||
fmt::println("[{}] {}", fmt::styled("*", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), LastError());
|
||||
fmt::println("");
|
||||
ServerInstance->Exit(EXIT_STATUS_MODULE);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (const std::filesystem::filesystem_error& err)
|
||||
{
|
||||
std::cout << "failed: " << err.what() << std::endl;
|
||||
fmt::println("failed: {}", err.what());
|
||||
ServerInstance->Exit(EXIT_STATUS_MODULE);
|
||||
}
|
||||
|
||||
std::cout << std::endl;
|
||||
fmt::println("");
|
||||
}
|
||||
|
@ -30,9 +30,7 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <rang/rang.hpp>
|
||||
#include <fmt/color.h>
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "exitcodes.h"
|
||||
@ -536,10 +534,12 @@ void ModuleManager::LoadAll()
|
||||
continue;
|
||||
|
||||
this->NewServices = &servicemap[name];
|
||||
std::cout << "[" << rang::style::bold << rang::fg::green << "*" << rang::style::reset << "] Loading module:\t" << rang::style::bold << rang::fg::green << name << rang::style::reset << std::endl;
|
||||
fmt::println("[{}] Loading module:\t{}", fmt::styled("*", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::green)), name);
|
||||
if (!this->Load(name, true))
|
||||
{
|
||||
std::cout << std::endl << "[" << rang::style::bold << rang::fg::red << "*" << rang::style::reset << "] " << this->LastError() << std::endl << std::endl;
|
||||
fmt::println("");
|
||||
fmt::println("[{}] {}", fmt::styled("*", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), LastError());
|
||||
fmt::println("");
|
||||
ServerInstance->Exit(EXIT_STATUS_MODULE);
|
||||
}
|
||||
}
|
||||
@ -558,7 +558,9 @@ void ModuleManager::LoadAll()
|
||||
{
|
||||
LastModuleError = "Unable to initialize " + modname + ": " + modexcept.GetReason();
|
||||
ServerInstance->Logs.Error("MODULE", LastModuleError);
|
||||
std::cout << std::endl << "[" << rang::style::bold << rang::fg::red << "*" << rang::style::reset << "] " << LastModuleError << std::endl << std::endl;
|
||||
fmt::println("");
|
||||
fmt::println("[{}] {}", fmt::styled("*", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), LastModuleError);
|
||||
fmt::println("");
|
||||
ServerInstance->Exit(EXIT_STATUS_MODULE);
|
||||
}
|
||||
}
|
||||
@ -580,7 +582,9 @@ void ModuleManager::LoadAll()
|
||||
{
|
||||
LastModuleError = "Unable to read the configuration for " + modname + ": " + modexcept.GetReason();
|
||||
ServerInstance->Logs.Error("MODULE", LastModuleError);
|
||||
std::cout << std::endl << "[" << rang::style::bold << rang::fg::red << "*" << rang::style::reset << "] " << LastModuleError << std::endl << std::endl;
|
||||
fmt::println("");
|
||||
fmt::println("[{}] {}", fmt::styled("*", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), LastModuleError);
|
||||
fmt::println("");
|
||||
ServerInstance->Exit(EXIT_STATUS_CONFIG);
|
||||
}
|
||||
}
|
||||
|
@ -26,15 +26,14 @@
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <rang/rang.hpp>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <fcntl.h>
|
||||
# include <sys/resource.h>
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <fmt/color.h>
|
||||
|
||||
#include "inspircd.h"
|
||||
#include "exitcodes.h"
|
||||
|
||||
@ -71,7 +70,7 @@ void EventHandler::OnEventHandlerError(int errornum)
|
||||
|
||||
void SocketEngine::InitError()
|
||||
{
|
||||
std::cerr << rang::style::bold << rang::fg::red << "FATAL ERROR!" << rang::style::reset << " Socket engine initialization failed. " << strerror(errno) << '.' << std::endl;
|
||||
fmt::println(stderr, "{} Socket engine initialization failed. {}.", fmt::styled("FATAL ERROR!", fmt::emphasis::bold | fmt::fg(fmt::terminal_color::red)), strerror(errno));
|
||||
InspIRCd::QuickExit(EXIT_STATUS_SOCKETENGINE);
|
||||
}
|
||||
|
||||
|
10
vendor/README.md
vendored
10
vendor/README.md
vendored
@ -52,16 +52,6 @@ This directory contains vendored dependencies that are shipped with InspIRCd to
|
||||
|
||||
**Website** — [https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5](https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5)
|
||||
|
||||
## rang
|
||||
|
||||
**Author** — Abhinav Gauniyal
|
||||
|
||||
**License** — Unlicense
|
||||
|
||||
**Version** — v3.2
|
||||
|
||||
**Website** — [https://github.com/agauniyal/rang/](https://github.com/agauniyal/rang/)
|
||||
|
||||
## sha2
|
||||
|
||||
**Author** — [Olivier Gay](mailto:olivier.gay@a3.epfl.ch)
|
||||
|
24
vendor/rang/LICENSE
vendored
24
vendor/rang/LICENSE
vendored
@ -1,24 +0,0 @@
|
||||
This is free and unencumbered software released into the public domain.
|
||||
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or
|
||||
distribute this software, either in source code form or as a compiled
|
||||
binary, for any purpose, commercial or non-commercial, and by any
|
||||
means.
|
||||
|
||||
In jurisdictions that recognize copyright laws, the author or authors
|
||||
of this software dedicate any and all copyright interest in the
|
||||
software to the public domain. We make this dedication for the benefit
|
||||
of the public at large and to the detriment of our heirs and
|
||||
successors. We intend this dedication to be an overt act of
|
||||
relinquishment in perpetuity of all present and future rights to this
|
||||
software under copyright law.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
For more information, please refer to <http://unlicense.org>
|
502
vendor/rang/rang.hpp
vendored
502
vendor/rang/rang.hpp
vendored
@ -1,502 +0,0 @@
|
||||
#ifndef RANG_DOT_HPP
|
||||
#define RANG_DOT_HPP
|
||||
|
||||
#if defined(__unix__) || defined(__unix) || defined(__linux__)
|
||||
#define OS_LINUX
|
||||
#elif defined(WIN32) || defined(_WIN32) || defined(_WIN64)
|
||||
#define OS_WIN
|
||||
#elif defined(__APPLE__) || defined(__MACH__)
|
||||
#define OS_MAC
|
||||
#else
|
||||
#error Unknown Platform
|
||||
#endif
|
||||
|
||||
#if defined(OS_LINUX) || defined(OS_MAC)
|
||||
#include <unistd.h>
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
|
||||
#if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0600)
|
||||
#error \
|
||||
"Please include rang.hpp before any windows system headers or set _WIN32_WINNT at least to _WIN32_WINNT_VISTA"
|
||||
#elif !defined(_WIN32_WINNT)
|
||||
#define _WIN32_WINNT _WIN32_WINNT_VISTA
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
#include <io.h>
|
||||
#include <memory>
|
||||
|
||||
// Only defined in windows 10 onwards, redefining in lower windows since it
|
||||
// doesn't gets used in lower versions
|
||||
// https://docs.microsoft.com/en-us/windows/console/getconsolemode
|
||||
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
|
||||
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <atomic>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iostream>
|
||||
|
||||
namespace rang {
|
||||
|
||||
/* For better compability with most of terminals do not use any style settings
|
||||
* except of reset, bold and reversed.
|
||||
* Note that on Windows terminals bold style is same as fgB color.
|
||||
*/
|
||||
enum class style {
|
||||
reset = 0,
|
||||
bold = 1,
|
||||
dim = 2,
|
||||
italic = 3,
|
||||
underline = 4,
|
||||
blink = 5,
|
||||
rblink = 6,
|
||||
reversed = 7,
|
||||
conceal = 8,
|
||||
crossed = 9
|
||||
};
|
||||
|
||||
enum class fg {
|
||||
black = 30,
|
||||
red = 31,
|
||||
green = 32,
|
||||
yellow = 33,
|
||||
blue = 34,
|
||||
magenta = 35,
|
||||
cyan = 36,
|
||||
gray = 37,
|
||||
reset = 39
|
||||
};
|
||||
|
||||
enum class bg {
|
||||
black = 40,
|
||||
red = 41,
|
||||
green = 42,
|
||||
yellow = 43,
|
||||
blue = 44,
|
||||
magenta = 45,
|
||||
cyan = 46,
|
||||
gray = 47,
|
||||
reset = 49
|
||||
};
|
||||
|
||||
enum class fgB {
|
||||
black = 90,
|
||||
red = 91,
|
||||
green = 92,
|
||||
yellow = 93,
|
||||
blue = 94,
|
||||
magenta = 95,
|
||||
cyan = 96,
|
||||
gray = 97
|
||||
};
|
||||
|
||||
enum class bgB {
|
||||
black = 100,
|
||||
red = 101,
|
||||
green = 102,
|
||||
yellow = 103,
|
||||
blue = 104,
|
||||
magenta = 105,
|
||||
cyan = 106,
|
||||
gray = 107
|
||||
};
|
||||
|
||||
enum class control { // Behaviour of rang function calls
|
||||
Off = 0, // toggle off rang style/color calls
|
||||
Auto = 1, // (Default) autodect terminal and colorize if needed
|
||||
Force = 2 // force ansi color output to non terminal streams
|
||||
};
|
||||
// Use rang::setControlMode to set rang control mode
|
||||
|
||||
enum class winTerm { // Windows Terminal Mode
|
||||
Auto = 0, // (Default) automatically detects wheter Ansi or Native API
|
||||
Ansi = 1, // Force use Ansi API
|
||||
Native = 2 // Force use Native API
|
||||
};
|
||||
// Use rang::setWinTermMode to explicitly set terminal API for Windows
|
||||
// Calling rang::setWinTermMode have no effect on other OS
|
||||
|
||||
namespace rang_implementation {
|
||||
|
||||
inline std::atomic<control> &controlMode() noexcept
|
||||
{
|
||||
static std::atomic<control> value(control::Auto);
|
||||
return value;
|
||||
}
|
||||
|
||||
inline std::atomic<winTerm> &winTermMode() noexcept
|
||||
{
|
||||
static std::atomic<winTerm> termMode(winTerm::Auto);
|
||||
return termMode;
|
||||
}
|
||||
|
||||
inline bool supportsColor() noexcept
|
||||
{
|
||||
#if defined(OS_LINUX) || defined(OS_MAC)
|
||||
|
||||
static const bool result = [] {
|
||||
const char *Terms[]
|
||||
= { "ansi", "color", "console", "cygwin", "gnome",
|
||||
"konsole", "kterm", "linux", "msys", "putty",
|
||||
"rxvt", "screen", "vt100", "xterm" };
|
||||
|
||||
const char *env_p = std::getenv("TERM");
|
||||
if (env_p == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return std::any_of(std::begin(Terms), std::end(Terms),
|
||||
[&](const char *term) {
|
||||
return std::strstr(env_p, term) != nullptr;
|
||||
});
|
||||
}();
|
||||
|
||||
#elif defined(OS_WIN)
|
||||
// All windows versions support colors through native console methods
|
||||
static constexpr bool result = true;
|
||||
#endif
|
||||
return result;
|
||||
}
|
||||
|
||||
#ifdef OS_WIN
|
||||
|
||||
|
||||
inline bool isMsysPty(int fd) noexcept
|
||||
{
|
||||
// Dynamic load for binary compability with old Windows
|
||||
const auto ptrGetFileInformationByHandleEx
|
||||
= reinterpret_cast<decltype(&GetFileInformationByHandleEx)>(
|
||||
GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")),
|
||||
"GetFileInformationByHandleEx"));
|
||||
if (!ptrGetFileInformationByHandleEx) {
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE h = reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that it's a pipe:
|
||||
if (GetFileType(h) != FILE_TYPE_PIPE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// POD type is binary compatible with FILE_NAME_INFO from WinBase.h
|
||||
// It have the same alignment and used to avoid UB in caller code
|
||||
struct MY_FILE_NAME_INFO {
|
||||
DWORD FileNameLength;
|
||||
WCHAR FileName[MAX_PATH];
|
||||
};
|
||||
|
||||
auto pNameInfo = std::unique_ptr<MY_FILE_NAME_INFO>(
|
||||
new (std::nothrow) MY_FILE_NAME_INFO());
|
||||
if (!pNameInfo) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check pipe name is template of
|
||||
// {"cygwin-","msys-"}XXXXXXXXXXXXXXX-ptyX-XX
|
||||
if (!ptrGetFileInformationByHandleEx(h, FileNameInfo, pNameInfo.get(),
|
||||
sizeof(MY_FILE_NAME_INFO))) {
|
||||
return false;
|
||||
}
|
||||
std::wstring name(pNameInfo->FileName, pNameInfo->FileNameLength / sizeof(WCHAR));
|
||||
if ((name.find(L"msys-") == std::wstring::npos
|
||||
&& name.find(L"cygwin-") == std::wstring::npos)
|
||||
|| name.find(L"-pty") == std::wstring::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline bool isTerminal(const std::streambuf *osbuf) noexcept
|
||||
{
|
||||
using std::cerr;
|
||||
using std::clog;
|
||||
using std::cout;
|
||||
#if defined(OS_LINUX) || defined(OS_MAC)
|
||||
if (osbuf == cout.rdbuf()) {
|
||||
static const bool cout_term = isatty(fileno(stdout)) != 0;
|
||||
return cout_term;
|
||||
} else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
|
||||
static const bool cerr_term = isatty(fileno(stderr)) != 0;
|
||||
return cerr_term;
|
||||
}
|
||||
#elif defined(OS_WIN)
|
||||
if (osbuf == cout.rdbuf()) {
|
||||
static const bool cout_term
|
||||
= (_isatty(_fileno(stdout)) || isMsysPty(_fileno(stdout)));
|
||||
return cout_term;
|
||||
} else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
|
||||
static const bool cerr_term
|
||||
= (_isatty(_fileno(stderr)) || isMsysPty(_fileno(stderr)));
|
||||
return cerr_term;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
using enableStd = typename std::enable_if<
|
||||
std::is_same<T, rang::style>::value || std::is_same<T, rang::fg>::value
|
||||
|| std::is_same<T, rang::bg>::value || std::is_same<T, rang::fgB>::value
|
||||
|| std::is_same<T, rang::bgB>::value,
|
||||
std::ostream &>::type;
|
||||
|
||||
|
||||
#ifdef OS_WIN
|
||||
|
||||
struct SGR { // Select Graphic Rendition parameters for Windows console
|
||||
BYTE fgColor; // foreground color (0-15) lower 3 rgb bits + intense bit
|
||||
BYTE bgColor; // background color (0-15) lower 3 rgb bits + intense bit
|
||||
BYTE bold; // emulated as FOREGROUND_INTENSITY bit
|
||||
BYTE underline; // emulated as BACKGROUND_INTENSITY bit
|
||||
BOOLEAN inverse; // swap foreground/bold & background/underline
|
||||
BOOLEAN conceal; // set foreground/bold to background/underline
|
||||
};
|
||||
|
||||
enum class AttrColor : BYTE { // Color attributes for console screen buffer
|
||||
black = 0,
|
||||
red = 4,
|
||||
green = 2,
|
||||
yellow = 6,
|
||||
blue = 1,
|
||||
magenta = 5,
|
||||
cyan = 3,
|
||||
gray = 7
|
||||
};
|
||||
|
||||
inline HANDLE getConsoleHandle(const std::streambuf *osbuf) noexcept
|
||||
{
|
||||
if (osbuf == std::cout.rdbuf()) {
|
||||
static const HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
return hStdout;
|
||||
} else if (osbuf == std::cerr.rdbuf() || osbuf == std::clog.rdbuf()) {
|
||||
static const HANDLE hStderr = GetStdHandle(STD_ERROR_HANDLE);
|
||||
return hStderr;
|
||||
}
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
inline bool setWinTermAnsiColors(const std::streambuf *osbuf) noexcept
|
||||
{
|
||||
HANDLE h = getConsoleHandle(osbuf);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return false;
|
||||
}
|
||||
DWORD dwMode = 0;
|
||||
if (!GetConsoleMode(h, &dwMode)) {
|
||||
return false;
|
||||
}
|
||||
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
|
||||
if (!SetConsoleMode(h, dwMode)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline bool supportsAnsi(const std::streambuf *osbuf) noexcept
|
||||
{
|
||||
using std::cerr;
|
||||
using std::clog;
|
||||
using std::cout;
|
||||
if (osbuf == cout.rdbuf()) {
|
||||
static const bool cout_ansi
|
||||
= (isMsysPty(_fileno(stdout)) || setWinTermAnsiColors(osbuf));
|
||||
return cout_ansi;
|
||||
} else if (osbuf == cerr.rdbuf() || osbuf == clog.rdbuf()) {
|
||||
static const bool cerr_ansi
|
||||
= (isMsysPty(_fileno(stderr)) || setWinTermAnsiColors(osbuf));
|
||||
return cerr_ansi;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline const SGR &defaultState() noexcept
|
||||
{
|
||||
static const SGR defaultSgr = []() -> SGR {
|
||||
CONSOLE_SCREEN_BUFFER_INFO info;
|
||||
WORD attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
|
||||
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE),
|
||||
&info)
|
||||
|| GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE),
|
||||
&info)) {
|
||||
attrib = info.wAttributes;
|
||||
}
|
||||
SGR sgr = { 0, 0, 0, 0, FALSE, FALSE };
|
||||
sgr.fgColor = attrib & 0x0F;
|
||||
sgr.bgColor = (attrib & 0xF0) >> 4;
|
||||
return sgr;
|
||||
}();
|
||||
return defaultSgr;
|
||||
}
|
||||
|
||||
inline BYTE ansi2attr(BYTE rgb) noexcept
|
||||
{
|
||||
static const AttrColor rev[8]
|
||||
= { AttrColor::black, AttrColor::red, AttrColor::green,
|
||||
AttrColor::yellow, AttrColor::blue, AttrColor::magenta,
|
||||
AttrColor::cyan, AttrColor::gray };
|
||||
return static_cast<BYTE>(rev[rgb]);
|
||||
}
|
||||
|
||||
inline void setWinSGR(rang::bg col, SGR &state) noexcept
|
||||
{
|
||||
if (col != rang::bg::reset) {
|
||||
state.bgColor = ansi2attr(static_cast<BYTE>(col) - 40);
|
||||
} else {
|
||||
state.bgColor = defaultState().bgColor;
|
||||
}
|
||||
}
|
||||
|
||||
inline void setWinSGR(rang::fg col, SGR &state) noexcept
|
||||
{
|
||||
if (col != rang::fg::reset) {
|
||||
state.fgColor = ansi2attr(static_cast<BYTE>(col) - 30);
|
||||
} else {
|
||||
state.fgColor = defaultState().fgColor;
|
||||
}
|
||||
}
|
||||
|
||||
inline void setWinSGR(rang::bgB col, SGR &state) noexcept
|
||||
{
|
||||
state.bgColor = (BACKGROUND_INTENSITY >> 4)
|
||||
| ansi2attr(static_cast<BYTE>(col) - 100);
|
||||
}
|
||||
|
||||
inline void setWinSGR(rang::fgB col, SGR &state) noexcept
|
||||
{
|
||||
state.fgColor
|
||||
= FOREGROUND_INTENSITY | ansi2attr(static_cast<BYTE>(col) - 90);
|
||||
}
|
||||
|
||||
inline void setWinSGR(rang::style style, SGR &state) noexcept
|
||||
{
|
||||
switch (style) {
|
||||
case rang::style::reset: state = defaultState(); break;
|
||||
case rang::style::bold: state.bold = FOREGROUND_INTENSITY; break;
|
||||
case rang::style::underline:
|
||||
case rang::style::blink:
|
||||
state.underline = BACKGROUND_INTENSITY;
|
||||
break;
|
||||
case rang::style::reversed: state.inverse = TRUE; break;
|
||||
case rang::style::conceal: state.conceal = TRUE; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
inline SGR ¤t_state() noexcept
|
||||
{
|
||||
static SGR state = defaultState();
|
||||
return state;
|
||||
}
|
||||
|
||||
inline WORD SGR2Attr(const SGR &state) noexcept
|
||||
{
|
||||
WORD attrib = 0;
|
||||
if (state.conceal) {
|
||||
if (state.inverse) {
|
||||
attrib = (state.fgColor << 4) | state.fgColor;
|
||||
if (state.bold)
|
||||
attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
|
||||
} else {
|
||||
attrib = (state.bgColor << 4) | state.bgColor;
|
||||
if (state.underline)
|
||||
attrib |= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY;
|
||||
}
|
||||
} else if (state.inverse) {
|
||||
attrib = (state.fgColor << 4) | state.bgColor;
|
||||
if (state.bold) attrib |= BACKGROUND_INTENSITY;
|
||||
if (state.underline) attrib |= FOREGROUND_INTENSITY;
|
||||
} else {
|
||||
attrib = state.fgColor | (state.bgColor << 4) | state.bold
|
||||
| state.underline;
|
||||
}
|
||||
return attrib;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void setWinColorAnsi(std::ostream &os, T const value)
|
||||
{
|
||||
os << "\033[" << static_cast<int>(value) << "m";
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void setWinColorNative(std::ostream &os, T const value)
|
||||
{
|
||||
const HANDLE h = getConsoleHandle(os.rdbuf());
|
||||
if (h != INVALID_HANDLE_VALUE) {
|
||||
setWinSGR(value, current_state());
|
||||
// Out all buffered text to console with previous settings:
|
||||
os.flush();
|
||||
SetConsoleTextAttribute(h, SGR2Attr(current_state()));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline enableStd<T> setColor(std::ostream &os, T const value)
|
||||
{
|
||||
if (winTermMode() == winTerm::Auto) {
|
||||
if (supportsAnsi(os.rdbuf())) {
|
||||
setWinColorAnsi(os, value);
|
||||
} else {
|
||||
setWinColorNative(os, value);
|
||||
}
|
||||
} else if (winTermMode() == winTerm::Ansi) {
|
||||
setWinColorAnsi(os, value);
|
||||
} else {
|
||||
setWinColorNative(os, value);
|
||||
}
|
||||
return os;
|
||||
}
|
||||
#else
|
||||
template <typename T>
|
||||
inline enableStd<T> setColor(std::ostream &os, T const value)
|
||||
{
|
||||
return os << "\033[" << static_cast<int>(value) << "m";
|
||||
}
|
||||
#endif
|
||||
} // namespace rang_implementation
|
||||
|
||||
template <typename T>
|
||||
inline rang_implementation::enableStd<T> operator<<(std::ostream &os,
|
||||
const T value)
|
||||
{
|
||||
const control option = rang_implementation::controlMode();
|
||||
switch (option) {
|
||||
case control::Auto:
|
||||
return rang_implementation::supportsColor()
|
||||
&& rang_implementation::isTerminal(os.rdbuf())
|
||||
? rang_implementation::setColor(os, value)
|
||||
: os;
|
||||
case control::Force: return rang_implementation::setColor(os, value);
|
||||
default: return os;
|
||||
}
|
||||
}
|
||||
|
||||
inline void setWinTermMode(const rang::winTerm value) noexcept
|
||||
{
|
||||
rang_implementation::winTermMode() = value;
|
||||
}
|
||||
|
||||
inline void setControlMode(const control value) noexcept
|
||||
{
|
||||
rang_implementation::controlMode() = value;
|
||||
}
|
||||
|
||||
} // namespace rang
|
||||
|
||||
#undef OS_LINUX
|
||||
#undef OS_WIN
|
||||
#undef OS_MAC
|
||||
|
||||
#endif /* ifndef RANG_DOT_HPP */
|
7
vendor/update.toml
vendored
7
vendor/update.toml
vendored
@ -39,13 +39,6 @@ tarball = "https://www.openwall.com/blists/blists-2.0.tar.gz"
|
||||
version = "v2.0"
|
||||
website = "https://openwall.info/wiki/people/solar/software/public-domain-source-code/md5"
|
||||
|
||||
[rang]
|
||||
author = "Abhinav Gauniyal"
|
||||
depth = 1
|
||||
files = "{include/rang.hpp,LICENSE}"
|
||||
git = "https://github.com/agauniyal/rang/"
|
||||
license = "Unlicense"
|
||||
|
||||
[sha2]
|
||||
author = "Olivier Gay"
|
||||
email = "olivier.gay@a3.epfl.ch"
|
||||
|
Loading…
x
Reference in New Issue
Block a user