unrealircd

- supernets unrealircd source & configuration
git clone git://git.acid.vegas/unrealircd.git
Log | Files | Refs | Archive | README | LICENSE

proc_io_client.c (5040B)

      1 /************************************************************************
      2  *   UnrealIRCd - Unreal Internet Relay Chat Daemon - src/proc_io_client.c
      3  *   (c) 2022- Bram Matthys and The UnrealIRCd team
      4  *
      5  *   See file AUTHORS in IRC package for additional names of
      6  *   the programmers. 
      7  *
      8  *   This program is free software; you can redistribute it and/or modify
      9  *   it under the terms of the GNU General Public License as published by
     10  *   the Free Software Foundation; either version 1, or (at your option)
     11  *   any later version.
     12  *
     13  *   This program is distributed in the hope that it will be useful,
     14  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     15  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     16  *   GNU General Public License for more details.
     17  *
     18  *   You should have received a copy of the GNU General Public License
     19  *   along with this program; if not, write to the Free Software
     20  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     21  */
     22 
     23 /** @file
     24  * @brief Inter-process I/O
     25  */
     26 #include "unrealircd.h"
     27 
     28 int procio_client_connect(const char *file)
     29 {
     30 	int fd;
     31 	struct sockaddr_un addr;
     32 
     33 	fd = socket(AF_UNIX, SOCK_STREAM, 0);
     34 	if (fd < 0)
     35 	{
     36 #ifdef _WIN32
     37 		fprintf(stderr, "Your Windows version does not support UNIX sockets, "
     38 		                "so cannot communicate to UnrealIRCd.\n"
     39 		                "Windows 10 version 1803 (April 2018) or later is needed.\n");
     40 #else
     41 		fprintf(stderr, "Cannot communicate to UnrealIRCd: %s\n"
     42 		                "Perhaps your operating system does not support UNIX Sockets?\n",
     43 				strerror(ERRNO));
     44 #endif
     45 		return -1;
     46 	}
     47 
     48 	memset(&addr, 0, sizeof(addr));
     49 	addr.sun_family = AF_UNIX;
     50 	strlcpy(addr.sun_path, file, sizeof(addr.sun_path));
     51 
     52 	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
     53 	{
     54 		fprintf(stderr, "Could not connect to '%s': %s\n",
     55 			CONTROLFILE, strerror(errno));
     56 		fprintf(stderr, "The IRC server does not appear to be running.\n");
     57 		close(fd);
     58 		return -1;
     59 	}
     60 
     61 	return fd;
     62 }
     63 
     64 int procio_send(int fd, const char *command)
     65 {
     66 	char buf[512];
     67 	int n;
     68 	snprintf(buf, sizeof(buf), "%s\r\n", command);
     69 	n = strlen(buf);
     70 	if (send(fd, buf, n, 0) != n)
     71 		return 0;
     72 	return 1;
     73 }
     74 
     75 const char *recolor_logs(const char *str)
     76 {
     77 	static char retbuf[2048];
     78 	char buf[2048], *p;
     79 	const char *color = NULL;
     80 
     81 	strlcpy(buf, str, sizeof(buf));
     82 	p = strchr(buf, ' ');
     83 	if ((*str != '[') || !p)
     84 		return str;
     85 	*p++ = '\0';
     86 
     87 	if (!strcmp(buf, "[debug]"))
     88 		color = log_level_terminal_color(ULOG_DEBUG);
     89 	else if (!strcmp(buf, "[info]"))
     90 		color = log_level_terminal_color(ULOG_INFO);
     91 	else if (!strcmp(buf, "[warning]"))
     92 		color = log_level_terminal_color(ULOG_WARNING);
     93 	else if (!strcmp(buf, "[error]"))
     94 		color = log_level_terminal_color(ULOG_ERROR);
     95 	else if (!strcmp(buf, "[fatal]"))
     96 		color = log_level_terminal_color(ULOG_FATAL);
     97 	else
     98 		color = log_level_terminal_color(ULOG_INVALID);
     99 
    100 	snprintf(retbuf, sizeof(retbuf), "%s%s%s %s",
    101 	         color, buf, TERMINAL_COLOR_RESET, p);
    102 	return retbuf;
    103 }
    104 
    105 const char *recolor_split(const char *str)
    106 {
    107 	static char retbuf[2048];
    108 	char buf[2048], *p;
    109 	const char *color = NULL;
    110 
    111 	strlcpy(buf, str, sizeof(buf));
    112 	p = strchr(buf, ' ');
    113 	if (!p)
    114 		return str;
    115 	*p++ = '\0';
    116 
    117 	snprintf(retbuf, sizeof(retbuf), "%s%s %s%s%s",
    118 	         "\033[92m", buf,
    119 	         "\033[93m", p,
    120 	         TERMINAL_COLOR_RESET);
    121 	return retbuf;
    122 }
    123 
    124 int procio_client(const char *command, int auto_color_logs)
    125 {
    126 	int fd;
    127 	char buf[READBUFSIZE];
    128 	int n;
    129 	dbuf queue;
    130 
    131 	if (auto_color_logs && !terminal_supports_color())
    132 		auto_color_logs = 0;
    133 
    134 	fd = procio_client_connect(CONTROLFILE);
    135 	if (fd < 0)
    136 		return -1;
    137 
    138 	/* Expect the welcome message */
    139 	memset(buf, 0, sizeof(buf));
    140 	n = recv(fd, buf, sizeof(buf), 0);
    141 	if ((n < 0) || strncmp(buf, "READY", 4))
    142 	{
    143 		fprintf(stderr, "Error while communicating to IRCd via '%s': %s\n"
    144 		                "Maybe the IRC server is not running?\n",
    145 		                CONTROLFILE, strerror(errno));
    146 		close(fd);
    147 		return -1;
    148 	}
    149 
    150 	if (!procio_send(fd, command))
    151 	{
    152 		fprintf(stderr, "Error while sending command to IRCd via '%s'. Strange!\n",
    153 		                CONTROLFILE);
    154 		close(fd);
    155 		return -1;
    156 	}
    157 
    158 	*buf = '\0';
    159 	dbuf_queue_init(&queue);
    160 	while(1)
    161 	{
    162 		n = recv(fd, buf, sizeof(buf)-1, 0);
    163 		if (n <= 0)
    164 			break;
    165 		buf[n] = '\0'; /* terminate the string */
    166 		dbuf_put(&queue, buf, n);
    167 
    168 		/* And try to read all complete lines: */
    169 		do
    170 		{
    171 			n = dbuf_getmsg(&queue, buf);
    172 			if (n > 0)
    173 			{
    174 				if (!strncmp(buf, "REPLY ", 6))
    175 				{
    176 					char *reply = buf+6;
    177 					if (auto_color_logs == 0)
    178 						printf("%s\n", reply);
    179 					else if (auto_color_logs == 1)
    180 						printf("%s\n", recolor_logs(reply));
    181 					else
    182 						printf("%s\n", recolor_split(reply));
    183 				} else
    184 				if (!strncmp(buf, "END ", 4))
    185 				{
    186 					int exitcode = atoi(buf+4);
    187 					close(fd);
    188 					return exitcode;
    189 				}
    190 			}
    191 		} while(n > 0);
    192 	}
    193 
    194 	/* IRCd hung up without saying goodbye, possibly problematic,
    195 	 * or at least we cannot determine, so exit with status 66.
    196 	 */
    197 	close(fd);
    198 	return 66;
    199 }