mirror of https://github.com/pissnet/pissircd
"./unrealircd reloadtls" and there is now also a "./unrealircd status" The output is colorized if the terminal supports it (just like on the boot screen) and also the exit status is 0 for success and non-0 for failure. The purpose of all this is that you can easily detect rehash errors on the command line. These three commands communicate to UnrealIRCd via the new control UNIX socket, which is in ~/data/unrealircd.ctl. This also does a lot of other stuff because we now have an internal tool called bin/unrealircdctl which is called by ./unrealircd for some of the commands to communicate to the unrealircd.ctl socket. Later on more of the existing functionality may be moved to that tool and we may also provide it on Windows in CLI mode so people have more of the same functionality as on *NIX.pull/41/head
parent
834736070e
commit
39688517b0
@ -0,0 +1,31 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/ircd_vars.c
|
||||
* (c) 2021- Bram Matthys and The UnrealIRCd team
|
||||
* License: GPLv2
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
/** @file
|
||||
* @brief UnrealIRCd global variables of the IRCd
|
||||
*/
|
||||
|
||||
int SVSNOOP = 0;
|
||||
time_t timeofday = 0;
|
||||
struct timeval timeofday_tv;
|
||||
int tainted = 0;
|
||||
LoopStruct loop;
|
||||
MODVAR IRCCounts irccounts;
|
||||
MODVAR Client me; /* That's me */
|
||||
MODVAR char *me_hash;
|
||||
char *configfile = NULL; /* Server configuration file */
|
||||
int debuglevel = 0; /* Server debug level */
|
||||
int bootopt = 0; /* Server boot option flags */
|
||||
char *debugmode = ""; /* -"- -"- -"- */
|
||||
int dorehash = 0; /**< Rehash server on next socket loop */
|
||||
int dorestart = 0; /**< Restart server on next socket loop */
|
||||
int doreloadcert = 0; /**< Reload TLS certificate on next socket loop */
|
||||
#ifndef _WIN32
|
||||
char **myargv;
|
||||
#else
|
||||
LPCSTR cmdLine;
|
||||
#endif
|
@ -0,0 +1,181 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/proc_io_client.c
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Inter-process I/O
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
|
||||
int procio_client_connect(const char *file)
|
||||
{
|
||||
int fd;
|
||||
struct sockaddr_un addr;
|
||||
|
||||
fd = socket(AF_UNIX, SOCK_STREAM, 0);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sun_family = AF_UNIX;
|
||||
strlcpy(addr.sun_path, file, sizeof(addr.sun_path));
|
||||
|
||||
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||
return -1;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int procio_send(int fd, const char *command)
|
||||
{
|
||||
char buf[512];
|
||||
int n;
|
||||
snprintf(buf, sizeof(buf), "%s\r\n", command);
|
||||
n = strlen(buf);
|
||||
if (send(fd, buf, n, 0) != n)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const char *recolor_logs(const char *str)
|
||||
{
|
||||
static char retbuf[2048];
|
||||
char buf[2048], *p;
|
||||
const char *color = NULL;
|
||||
|
||||
strlcpy(buf, str, sizeof(buf));
|
||||
p = strchr(buf, ' ');
|
||||
if ((*str != '[') || !p)
|
||||
return str;
|
||||
*p++ = '\0';
|
||||
|
||||
if (!strcmp(buf, "[debug]"))
|
||||
color = log_level_terminal_color(ULOG_DEBUG);
|
||||
else if (!strcmp(buf, "[info]"))
|
||||
color = log_level_terminal_color(ULOG_INFO);
|
||||
else if (!strcmp(buf, "[warning]"))
|
||||
color = log_level_terminal_color(ULOG_WARNING);
|
||||
else if (!strcmp(buf, "[error]"))
|
||||
color = log_level_terminal_color(ULOG_ERROR);
|
||||
else if (!strcmp(buf, "[fatal]"))
|
||||
color = log_level_terminal_color(ULOG_FATAL);
|
||||
else
|
||||
color = log_level_terminal_color(ULOG_INVALID);
|
||||
|
||||
snprintf(retbuf, sizeof(retbuf), "%s%s%s %s",
|
||||
color, buf, TERMINAL_COLOR_RESET, p);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
const char *recolor_split(const char *str)
|
||||
{
|
||||
static char retbuf[2048];
|
||||
char buf[2048], *p;
|
||||
const char *color = NULL;
|
||||
|
||||
strlcpy(buf, str, sizeof(buf));
|
||||
p = strchr(buf, ' ');
|
||||
if (!p)
|
||||
return str;
|
||||
*p++ = '\0';
|
||||
|
||||
snprintf(retbuf, sizeof(retbuf), "%s%s %s%s%s",
|
||||
"\033[92m", buf,
|
||||
"\033[93m", p,
|
||||
TERMINAL_COLOR_RESET);
|
||||
return retbuf;
|
||||
}
|
||||
|
||||
int procio_client(const char *command, int auto_color_logs)
|
||||
{
|
||||
int fd;
|
||||
char buf[READBUFSIZE];
|
||||
int n;
|
||||
dbuf queue;
|
||||
|
||||
if (auto_color_logs && !terminal_supports_color())
|
||||
auto_color_logs = 0;
|
||||
|
||||
fd = procio_client_connect(CONTROLFILE);
|
||||
if (fd < 0)
|
||||
{
|
||||
fprintf(stderr, "Could not connect to '%s': %s\n",
|
||||
CONTROLFILE, strerror(errno));
|
||||
fprintf(stderr, "Maybe the IRC server is not running?\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Expect the welcome message */
|
||||
memset(buf, 0, sizeof(buf));
|
||||
n = recv(fd, buf, sizeof(buf), 0);
|
||||
if ((n < 0) || strncmp(buf, "READY", 4))
|
||||
{
|
||||
fprintf(stderr, "Error while communicating to IRCd via '%s': %s\n"
|
||||
"Maybe the IRC server is not running?\n",
|
||||
CONTROLFILE, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!procio_send(fd, command))
|
||||
{
|
||||
fprintf(stderr, "Error while sending command to IRCd via '%s'. Strange!\n",
|
||||
CONTROLFILE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
*buf = '\0';
|
||||
dbuf_queue_init(&queue);
|
||||
while(1)
|
||||
{
|
||||
n = recv(fd, buf, sizeof(buf)-1, 0);
|
||||
if (n <= 0)
|
||||
break;
|
||||
buf[n] = '\0'; /* terminate the string */
|
||||
dbuf_put(&queue, buf, n);
|
||||
|
||||
/* And try to read all complete lines: */
|
||||
do
|
||||
{
|
||||
n = dbuf_getmsg(&queue, buf);
|
||||
if (n > 0)
|
||||
{
|
||||
if (!strncmp(buf, "REPLY ", 6))
|
||||
{
|
||||
char *reply = buf+6;
|
||||
if (auto_color_logs == 0)
|
||||
printf("%s\n", reply);
|
||||
else if (auto_color_logs == 1)
|
||||
printf("%s\n", recolor_logs(reply));
|
||||
else
|
||||
printf("%s\n", recolor_split(reply));
|
||||
} else
|
||||
if (!strncmp(buf, "END ", 4))
|
||||
{
|
||||
int exitcode = atoi(buf+4);
|
||||
close(fd);
|
||||
return exitcode;
|
||||
}
|
||||
}
|
||||
} while(n > 0);
|
||||
}
|
||||
|
||||
return 0; /* zero is good */
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/************************************************************************
|
||||
* UnrealIRCd - Unreal Internet Relay Chat Daemon - src/proc_io_server.c
|
||||
* (c) 2022- Bram Matthys and The UnrealIRCd team
|
||||
*
|
||||
* See file AUTHORS in IRC package for additional names of
|
||||
* the programmers.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 1, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* @brief Inter-process I/O
|
||||
*/
|
||||
#include "unrealircd.h"
|
||||
#include <ares.h>
|
||||
|
||||
CMD_FUNC(procio_status);
|
||||
CMD_FUNC(procio_rehash);
|
||||
CMD_FUNC(procio_exit);
|
||||
CMD_FUNC(procio_help);
|
||||
|
||||
/** Create the unrealircd.ctl socket (server-side) */
|
||||
void add_proc_io_server(void)
|
||||
{
|
||||
ConfigItem_listen *listener = safe_alloc(sizeof(ConfigItem_listen));
|
||||
safe_strdup(listener->file, CONTROLFILE);
|
||||
listener->socket_type = SOCKET_TYPE_UNIX;
|
||||
listener->options = LISTENER_CONTROL;
|
||||
listener->fd = -1;
|
||||
AddListItem(listener, conf_listen);
|
||||
if (add_listener(listener) == -1)
|
||||
exit(-1);
|
||||
CommandAdd(NULL, "STATUS", procio_status, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "REHASH", procio_rehash, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "EXIT", procio_exit, MAXPARA, CMD_CONTROL);
|
||||
CommandAdd(NULL, "HELP", procio_help, MAXPARA, CMD_CONTROL);
|
||||
}
|
||||
|
||||
/** Start of "control channel" client handshake - this is minimal
|
||||
* @param client The client
|
||||
*/
|
||||
void start_of_control_client_handshake(Client *client)
|
||||
{
|
||||
sendto_one(client, NULL, "READY %s %s", me.name, version);
|
||||
fd_setselect(client->local->fd, FD_SELECT_READ, read_packet, client);
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_status)
|
||||
{
|
||||
sendto_one(client, NULL, "REPLY servername %s", me.name);
|
||||
sendto_one(client, NULL, "REPLY unrealircd_version %s", version);
|
||||
sendto_one(client, NULL, "REPLY libssl_version %s", SSLeay_version(SSLEAY_VERSION));
|
||||
sendto_one(client, NULL, "REPLY libsodium_version %s", sodium_version_string());
|
||||
#ifdef USE_LIBCURL
|
||||
sendto_one(client, NULL, "REPLY libcurl_version %s", curl_version());
|
||||
#endif
|
||||
sendto_one(client, NULL, "REPLY libcares_version %s", ares_version(NULL));
|
||||
sendto_one(client, NULL, "REPLY libpcre2_version %s", pcre2_version());
|
||||
sendto_one(client, NULL, "REPLY global_clients %ld", (long)irccounts.clients);
|
||||
sendto_one(client, NULL, "REPLY local_clients %ld", (long)irccounts.me_clients);
|
||||
sendto_one(client, NULL, "REPLY operators %ld", (long)irccounts.operators);
|
||||
sendto_one(client, NULL, "REPLY servers %ld", (long)irccounts.servers);
|
||||
sendto_one(client, NULL, "REPLY channels %ld", (long)irccounts.channels);
|
||||
sendto_one(client, NULL, "END 0");
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_rehash)
|
||||
{
|
||||
if (loop.rehashing)
|
||||
{
|
||||
sendto_one(client, NULL, "REPLY ERROR: A rehash is already in progress");
|
||||
sendto_one(client, NULL, "END 1");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (parv[1] && !strcmp(parv[1], "-tls"))
|
||||
{
|
||||
int ret;
|
||||
SetMonitorRehash(client);
|
||||
unreal_log(ULOG_INFO, "config", "CONFIG_RELOAD_TLS", NULL, "Reloading all TLS related data (./unrealircd reloadtls)");
|
||||
ret = reinit_tls();
|
||||
sendto_one(client, NULL, "END %d", ret == 0 ? -1 : 0);
|
||||
ClearMonitorRehash(client);
|
||||
} else {
|
||||
SetMonitorRehash(client);
|
||||
request_rehash(client);
|
||||
/* completion will go via procio_post_rehash() */
|
||||
}
|
||||
}
|
||||
|
||||
CMD_FUNC(procio_exit)
|
||||