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 }