Blame


1 d23d2886 2023-07-30 op /* $Id: icb.c,v 1.3 2015/08/21 19:01:12 dhartmei Exp $ */
2 d23d2886 2023-07-30 op
3 d23d2886 2023-07-30 op /*
4 a29564dd 2023-08-20 op * Copyright (c) 2023 Omar Polo <op@openbsd.org>
5 d23d2886 2023-07-30 op * Copyright (c) 2003-2004 Daniel Hartmeier
6 d23d2886 2023-07-30 op * All rights reserved.
7 d23d2886 2023-07-30 op *
8 d23d2886 2023-07-30 op * Redistribution and use in source and binary forms, with or without
9 d23d2886 2023-07-30 op * modification, are permitted provided that the following conditions
10 d23d2886 2023-07-30 op * are met:
11 d23d2886 2023-07-30 op *
12 d23d2886 2023-07-30 op * - Redistributions of source code must retain the above copyright
13 d23d2886 2023-07-30 op * notice, this list of conditions and the following disclaimer.
14 d23d2886 2023-07-30 op * - Redistributions in binary form must reproduce the above
15 d23d2886 2023-07-30 op * copyright notice, this list of conditions and the following
16 d23d2886 2023-07-30 op * disclaimer in the documentation and/or other materials provided
17 d23d2886 2023-07-30 op * with the distribution.
18 d23d2886 2023-07-30 op *
19 d23d2886 2023-07-30 op * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 d23d2886 2023-07-30 op * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 d23d2886 2023-07-30 op * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22 d23d2886 2023-07-30 op * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23 d23d2886 2023-07-30 op * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 d23d2886 2023-07-30 op * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25 d23d2886 2023-07-30 op * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 d23d2886 2023-07-30 op * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 d23d2886 2023-07-30 op * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 d23d2886 2023-07-30 op * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 d23d2886 2023-07-30 op * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 d23d2886 2023-07-30 op * POSSIBILITY OF SUCH DAMAGE.
31 d23d2886 2023-07-30 op *
32 d23d2886 2023-07-30 op */
33 d23d2886 2023-07-30 op
34 a3ace556 2023-08-01 op #include <err.h>
35 d23d2886 2023-07-30 op #include <stdio.h>
36 d23d2886 2023-07-30 op #include <stdlib.h>
37 d23d2886 2023-07-30 op #include <string.h>
38 fe009782 2023-08-01 op
39 d23d2886 2023-07-30 op #include "icb.h"
40 d23d2886 2023-07-30 op #include "irc.h"
41 d23d2886 2023-07-30 op
42 c8394ca1 2023-08-01 op extern void icbirc_quit(void);
43 d23d2886 2023-07-30 op extern int sync_write(int, const char *, int);
44 d23d2886 2023-07-30 op
45 d23d2886 2023-07-30 op static unsigned char icb_args(const char *, unsigned char, char [255][255]);
46 d23d2886 2023-07-30 op static void icb_cmd(const char *, unsigned char, int, int);
47 d23d2886 2023-07-30 op static void icb_ico(int, const char *);
48 d23d2886 2023-07-30 op static void icb_iwl(int, const char *, const char *, long,
49 d23d2886 2023-07-30 op long, const char *, const char *);
50 d23d2886 2023-07-30 op static void icb_send_hw(int, const char *);
51 d23d2886 2023-07-30 op
52 fbe4e593 2023-08-01 op int icb_logged_in;
53 d23d2886 2023-07-30 op
54 d23d2886 2023-07-30 op static char icb_protolevel[256];
55 d23d2886 2023-07-30 op static char icb_hostid[256];
56 d23d2886 2023-07-30 op static char icb_serverid[256];
57 d23d2886 2023-07-30 op static char icb_moderator[256];
58 d23d2886 2023-07-30 op enum { imode_none, imode_list, imode_names, imode_whois, imode_who };
59 d23d2886 2023-07-30 op static int imode = imode_none;
60 d23d2886 2023-07-30 op static char icurgroup[256];
61 d23d2886 2023-07-30 op static char igroup[256];
62 d23d2886 2023-07-30 op static char inick[256];
63 d23d2886 2023-07-30 op static char ihostmask[256];
64 d23d2886 2023-07-30 op static unsigned off;
65 d23d2886 2023-07-30 op
66 d23d2886 2023-07-30 op /*
67 d23d2886 2023-07-30 op * A single ICB packet consists of a length byte, a command byte and
68 d23d2886 2023-07-30 op * variable arguments. The length includes command and arguments, but
69 d23d2886 2023-07-30 op * not the length byte itself. Since length is at most 255, the entire
70 d23d2886 2023-07-30 op * packet is at most 256 bytes long.
71 d23d2886 2023-07-30 op *
72 d23d2886 2023-07-30 op * icb_recv() gets passed read(2) chunks and assembles a complete packet
73 d23d2886 2023-07-30 op * (including the length byte) in cmd. Once complete, the packet is
74 d23d2886 2023-07-30 op * passed to icb_cmd() without the length byte. Hence, arguments to
75 d23d2886 2023-07-30 op * icb_cmd() are at most 255 bytes long.
76 d23d2886 2023-07-30 op *
77 d23d2886 2023-07-30 op * icb_cmd() skips the command byte and passes only the variable
78 d23d2886 2023-07-30 op * arguments to icb_args(). Hence, arguments to icb_args() are at most
79 d23d2886 2023-07-30 op * 254 octects long.
80 d23d2886 2023-07-30 op *
81 d23d2886 2023-07-30 op * Variable arguments consist of zero or more strings separated by
82 d23d2886 2023-07-30 op * \001 characters. The strings need not be null-terminated and may
83 d23d2886 2023-07-30 op * be empty. Hence, there can be at most 255 strings and a string can
84 d23d2886 2023-07-30 op * be at most 254 bytes long. icb_args() fills the array argument,
85 d23d2886 2023-07-30 op * null-terminating each argument.
86 d23d2886 2023-07-30 op *
87 d23d2886 2023-07-30 op * This (together with the comments below) should be convincing proof
88 d23d2886 2023-07-30 op * that the char [255][255] as well as the unsigned char variables
89 d23d2886 2023-07-30 op * cannot overflow.
90 d23d2886 2023-07-30 op *
91 d23d2886 2023-07-30 op * Further argument parsing in icb_cmd() and icb_ico() relies on the
92 d23d2886 2023-07-30 op * fact that any argument can be at most 255 bytes long (including
93 d23d2886 2023-07-30 op * null-termination).
94 d23d2886 2023-07-30 op *
95 d23d2886 2023-07-30 op * The icb_send_*() functions may get arbitrarily long arguments from
96 d23d2886 2023-07-30 op * IRC, they may generate packets of at most 256 bytes size. Overlong
97 d23d2886 2023-07-30 op * arguments are truncated, except for open and personal messages,
98 d23d2886 2023-07-30 op * which are split across multiple packets, if needed (generating
99 d23d2886 2023-07-30 op * separate messages on ICB).
100 d23d2886 2023-07-30 op *
101 d23d2886 2023-07-30 op * The ICB protocol definition is not very clear about null-termination
102 d23d2886 2023-07-30 op * of arguments for packets generated by the client. Without any
103 d23d2886 2023-07-30 op * termination, at least one common server implementation shows a
104 d23d2886 2023-07-30 op * buffer re-use bug. Terminating all arguments, however, causes
105 d23d2886 2023-07-30 op * another server implementation to refuse certain commands. The
106 d23d2886 2023-07-30 op * best approach seems to be to null-terminate only the last
107 d23d2886 2023-07-30 op * argument. Where the code below violates that rule, that was done
108 d23d2886 2023-07-30 op * intentionally after testing.
109 d23d2886 2023-07-30 op *
110 d23d2886 2023-07-30 op */
111 d23d2886 2023-07-30 op
112 d23d2886 2023-07-30 op void
113 d23d2886 2023-07-30 op scan(const char **s, char *d, size_t siz, const char *skip, const char *term)
114 d23d2886 2023-07-30 op {
115 d23d2886 2023-07-30 op while (**s && strchr(skip, **s) != NULL)
116 d23d2886 2023-07-30 op (*s)++;
117 d23d2886 2023-07-30 op while (**s && strchr(term, **s) == NULL) {
118 d23d2886 2023-07-30 op if (siz > 1) {
119 d23d2886 2023-07-30 op *d++ = **s;
120 d23d2886 2023-07-30 op siz--;
121 d23d2886 2023-07-30 op }
122 d23d2886 2023-07-30 op (*s)++;
123 d23d2886 2023-07-30 op }
124 d23d2886 2023-07-30 op if (siz > 0)
125 d23d2886 2023-07-30 op *d = 0;
126 d23d2886 2023-07-30 op }
127 d23d2886 2023-07-30 op
128 d23d2886 2023-07-30 op void
129 d23d2886 2023-07-30 op icb_init(void)
130 d23d2886 2023-07-30 op {
131 d23d2886 2023-07-30 op memset(icb_protolevel, 0, sizeof(icb_protolevel));
132 d23d2886 2023-07-30 op memset(icb_hostid, 0, sizeof(icb_hostid));
133 d23d2886 2023-07-30 op memset(icb_serverid, 0, sizeof(icb_serverid));
134 d23d2886 2023-07-30 op memset(icb_moderator, 0, sizeof(icb_moderator));
135 d23d2886 2023-07-30 op imode = imode_none;
136 d23d2886 2023-07-30 op memset(icurgroup, 0, sizeof(icurgroup));
137 d23d2886 2023-07-30 op memset(igroup, 0, sizeof(igroup));
138 d23d2886 2023-07-30 op memset(inick, 0, sizeof(inick));
139 d23d2886 2023-07-30 op memset(ihostmask, 0, sizeof(ihostmask));
140 d23d2886 2023-07-30 op off = 0;
141 d23d2886 2023-07-30 op }
142 d23d2886 2023-07-30 op
143 d23d2886 2023-07-30 op void
144 d23d2886 2023-07-30 op icb_recv(const char *buf, unsigned len, int fd, int server_fd)
145 d23d2886 2023-07-30 op {
146 d23d2886 2023-07-30 op static unsigned char cmd[256];
147 d23d2886 2023-07-30 op
148 d23d2886 2023-07-30 op while (len > 0) {
149 d23d2886 2023-07-30 op if (off == 0) {
150 d23d2886 2023-07-30 op cmd[off++] = *buf++;
151 d23d2886 2023-07-30 op /* 0 < cmd[0] <= 255 */
152 d23d2886 2023-07-30 op len--;
153 d23d2886 2023-07-30 op }
154 d23d2886 2023-07-30 op /* off > 0, 0 < cmd[0] <= 255 */
155 d23d2886 2023-07-30 op while (len > 0 && (off - 1) < cmd[0]) {
156 d23d2886 2023-07-30 op cmd[off++] = *buf++;
157 d23d2886 2023-07-30 op len--;
158 d23d2886 2023-07-30 op }
159 d23d2886 2023-07-30 op /* len == 0 || (off - 1) == cmd[0] */
160 d23d2886 2023-07-30 op if ((off - 1) == cmd[0]) {
161 d23d2886 2023-07-30 op icb_cmd(cmd + 1, off - 1 /* <= 255 */, fd, server_fd);
162 d23d2886 2023-07-30 op off = 0;
163 d23d2886 2023-07-30 op }
164 d23d2886 2023-07-30 op }
165 d23d2886 2023-07-30 op }
166 d23d2886 2023-07-30 op
167 d23d2886 2023-07-30 op static unsigned char
168 d23d2886 2023-07-30 op icb_args(const char *data, unsigned char len, char args[255][255])
169 d23d2886 2023-07-30 op {
170 d23d2886 2023-07-30 op unsigned char i = 0, j = 0, k = 0;
171 d23d2886 2023-07-30 op
172 d23d2886 2023-07-30 op /* 0 < len < 255 */
173 d23d2886 2023-07-30 op while (i < len) {
174 d23d2886 2023-07-30 op /* 0 <= i, j, k < 255 */
175 d23d2886 2023-07-30 op if (data[i] == '\001') {
176 d23d2886 2023-07-30 op args[j++][k] = 0;
177 d23d2886 2023-07-30 op k = 0;
178 d23d2886 2023-07-30 op } else if (data[i] == '\r' || data[i] == '\n')
179 d23d2886 2023-07-30 op args[j][k++] = '?';
180 d23d2886 2023-07-30 op else
181 d23d2886 2023-07-30 op args[j][k++] = data[i];
182 d23d2886 2023-07-30 op i++;
183 d23d2886 2023-07-30 op }
184 d23d2886 2023-07-30 op /* i, j, k < 255 */
185 d23d2886 2023-07-30 op if (k > 0)
186 d23d2886 2023-07-30 op args[j++][k] = 0;
187 d23d2886 2023-07-30 op /* j <= 255 */
188 d23d2886 2023-07-30 op for (i = j; i < 255; ++i)
189 d23d2886 2023-07-30 op args[i][0] = 0;
190 d23d2886 2023-07-30 op return (j);
191 d23d2886 2023-07-30 op }
192 d23d2886 2023-07-30 op
193 d23d2886 2023-07-30 op static void
194 d23d2886 2023-07-30 op icb_cmd(const char *cmd, unsigned char len, int fd, int server_fd)
195 d23d2886 2023-07-30 op {
196 d23d2886 2023-07-30 op char args[255][255];
197 d23d2886 2023-07-30 op const char *a = args[1];
198 d23d2886 2023-07-30 op unsigned char i, j;
199 d23d2886 2023-07-30 op char s[8192];
200 d23d2886 2023-07-30 op
201 d23d2886 2023-07-30 op if (len == 0)
202 d23d2886 2023-07-30 op return;
203 d23d2886 2023-07-30 op
204 d23d2886 2023-07-30 op /* 0 < len <= 255 */
205 d23d2886 2023-07-30 op i = icb_args(cmd + 1, len - 1 /* < 255 */, args);
206 d23d2886 2023-07-30 op /* 0 <= i <= 255 */
207 d23d2886 2023-07-30 op switch (cmd[0]) {
208 d23d2886 2023-07-30 op case 'a': /* Login OK */
209 d23d2886 2023-07-30 op irc_send_code(fd, icb_hostid, irc_nick, "001",
210 d23d2886 2023-07-30 op "Welcome to icbirc %s", irc_nick);
211 d23d2886 2023-07-30 op irc_send_code(fd, icb_hostid, irc_nick, "002",
212 d23d2886 2023-07-30 op "Your host is %s running %s protocol %s",
213 d23d2886 2023-07-30 op icb_hostid, icb_serverid, icb_protolevel);
214 d23d2886 2023-07-30 op /* some clients really want to see a MOTD */
215 d23d2886 2023-07-30 op irc_send_code(fd, icb_hostid, irc_nick, "375",
216 d23d2886 2023-07-30 op "ICB server: %s", icb_serverid);
217 d23d2886 2023-07-30 op irc_send_code(fd, icb_hostid, irc_nick, "376",
218 d23d2886 2023-07-30 op "End of MOTD");
219 d23d2886 2023-07-30 op icb_logged_in = 1;
220 d23d2886 2023-07-30 op break;
221 d23d2886 2023-07-30 op case 'b': /* Open Message */
222 d23d2886 2023-07-30 op if (!in_irc_channel) {
223 d23d2886 2023-07-30 op irc_send_join(fd, irc_nick, irc_channel);
224 d23d2886 2023-07-30 op icb_send_names(server_fd, irc_channel);
225 d23d2886 2023-07-30 op }
226 d23d2886 2023-07-30 op irc_send_msg(fd, args[0], irc_channel, args[1]);
227 d23d2886 2023-07-30 op break;
228 d23d2886 2023-07-30 op case 'c': /* Personal Message */
229 d23d2886 2023-07-30 op irc_send_msg(fd, args[0], irc_nick, args[1]);
230 d23d2886 2023-07-30 op break;
231 d23d2886 2023-07-30 op case 'd': /* Status Message */
232 d23d2886 2023-07-30 op if (!strcmp(args[0], "Status") && !strncmp(args[1],
233 d23d2886 2023-07-30 op "You are now in group ", 21)) {
234 d23d2886 2023-07-30 op if (irc_channel[0])
235 d23d2886 2023-07-30 op irc_send_part(fd, irc_nick, irc_channel);
236 d23d2886 2023-07-30 op irc_channel[0] = '#';
237 d23d2886 2023-07-30 op a += 21;
238 d23d2886 2023-07-30 op scan(&a, irc_channel + 1, sizeof(irc_channel) - 1,
239 d23d2886 2023-07-30 op " ", " ");
240 d23d2886 2023-07-30 op irc_send_join(fd, irc_nick, irc_channel);
241 d23d2886 2023-07-30 op icb_send_names(server_fd, irc_channel);
242 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Arrive") ||
243 d23d2886 2023-07-30 op !strcmp(args[0], "Sign-on")) {
244 d23d2886 2023-07-30 op char nick[256], host[256];
245 d23d2886 2023-07-30 op
246 d23d2886 2023-07-30 op scan(&a, nick, sizeof(nick), " ", " ");
247 d23d2886 2023-07-30 op scan(&a, host, sizeof(host), " (", ")");
248 d23d2886 2023-07-30 op snprintf(s, sizeof(s), "%s!%s", nick, host);
249 d23d2886 2023-07-30 op irc_send_join(fd, s, irc_channel);
250 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Depart")) {
251 d23d2886 2023-07-30 op char nick[256], host[256];
252 d23d2886 2023-07-30 op
253 d23d2886 2023-07-30 op scan(&a, nick, sizeof(nick), " ", " ");
254 d23d2886 2023-07-30 op scan(&a, host, sizeof(host), " (", ")");
255 d23d2886 2023-07-30 op snprintf(s, sizeof(s), "%s!%s", nick, host);
256 d23d2886 2023-07-30 op irc_send_part(fd, s, irc_channel);
257 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Sign-off")) {
258 d23d2886 2023-07-30 op char nick[256], host[256], reason[256];
259 d23d2886 2023-07-30 op
260 d23d2886 2023-07-30 op scan(&a, nick, sizeof(nick), " ", " ");
261 d23d2886 2023-07-30 op scan(&a, host, sizeof(host), " (", ")");
262 d23d2886 2023-07-30 op scan(&a, reason, sizeof(reason), " )", "");
263 d23d2886 2023-07-30 op if (strlen(reason) > 0 &&
264 d23d2886 2023-07-30 op reason[strlen(reason) - 1] == '.')
265 d23d2886 2023-07-30 op reason[strlen(reason) - 1] = 0;
266 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s!%s QUIT :%s\r\n",
267 d23d2886 2023-07-30 op nick, host, reason);
268 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
269 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Name")) {
270 d23d2886 2023-07-30 op char old_nick[256], new_nick[256];
271 d23d2886 2023-07-30 op
272 d23d2886 2023-07-30 op scan(&a, old_nick, sizeof(old_nick), " ", " ");
273 d23d2886 2023-07-30 op if (strncmp(a, " changed nickname to ", 21))
274 d23d2886 2023-07-30 op return;
275 d23d2886 2023-07-30 op a += 21;
276 d23d2886 2023-07-30 op scan(&a, new_nick, sizeof(new_nick), " ", " ");
277 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s NICK :%s\r\n",
278 d23d2886 2023-07-30 op old_nick, new_nick);
279 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
280 d23d2886 2023-07-30 op if (!strcmp(old_nick, irc_nick))
281 d23d2886 2023-07-30 op strlcpy(irc_nick, new_nick,
282 d23d2886 2023-07-30 op sizeof(irc_nick));
283 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Topic")) {
284 d23d2886 2023-07-30 op char nick[256], topic[256];
285 d23d2886 2023-07-30 op
286 d23d2886 2023-07-30 op scan(&a, nick, sizeof(nick), " ", " ");
287 d23d2886 2023-07-30 op if (strncmp(a, " changed the topic to \"", 23))
288 d23d2886 2023-07-30 op return;
289 d23d2886 2023-07-30 op a += 23;
290 d23d2886 2023-07-30 op scan(&a, topic, sizeof(topic), "", "\"");
291 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s TOPIC %s :%s\r\n",
292 d23d2886 2023-07-30 op nick, irc_channel, topic);
293 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
294 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Pass")) {
295 d23d2886 2023-07-30 op char old_mod[256], new_mod[256];
296 d23d2886 2023-07-30 op
297 d23d2886 2023-07-30 op scan(&a, old_mod, sizeof(old_mod), " ", " ");
298 d23d2886 2023-07-30 op if (!strncmp(a, " has passed moderation to ", 26)) {
299 d23d2886 2023-07-30 op a += 26;
300 d23d2886 2023-07-30 op scan(&a, new_mod, sizeof(new_mod), " ", " ");
301 d23d2886 2023-07-30 op snprintf(s, sizeof(s),
302 d23d2886 2023-07-30 op ":%s MODE %s -o+o %s %s\r\n",
303 d23d2886 2023-07-30 op old_mod, irc_channel, old_mod, new_mod);
304 d23d2886 2023-07-30 op } else if (!strcmp(a, " is now mod.")) {
305 d23d2886 2023-07-30 op snprintf(s, sizeof(s),
306 d23d2886 2023-07-30 op ":%s MODE %s +o %s\r\n",
307 d23d2886 2023-07-30 op icb_hostid, irc_channel, old_mod);
308 d23d2886 2023-07-30 op } else
309 d23d2886 2023-07-30 op return;
310 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
311 d23d2886 2023-07-30 op strlcpy(icb_moderator, new_mod, sizeof(icb_moderator));
312 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "Boot")) {
313 d23d2886 2023-07-30 op char nick[256];
314 d23d2886 2023-07-30 op
315 d23d2886 2023-07-30 op scan(&a, nick, sizeof(nick), " ", " ");
316 d23d2886 2023-07-30 op if (strcmp(a, " was booted."))
317 d23d2886 2023-07-30 op return;
318 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s KICK %s %s :booted\r\n",
319 d23d2886 2023-07-30 op icb_moderator, irc_channel, nick);
320 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
321 d23d2886 2023-07-30 op } else
322 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Status Message: %s: %s",
323 d23d2886 2023-07-30 op args[0], args[1]);
324 d23d2886 2023-07-30 op break;
325 d23d2886 2023-07-30 op case 'e': /* Error Message */
326 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Error Message: %s", args[0]);
327 d23d2886 2023-07-30 op break;
328 d23d2886 2023-07-30 op case 'f': /* Important Message */
329 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Important Message: %s: %s",
330 d23d2886 2023-07-30 op args[0], args[1]);
331 d23d2886 2023-07-30 op break;
332 d23d2886 2023-07-30 op case 'g': /* Exit */
333 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Exit");
334 ed972677 2023-08-01 op warnx("server Exit");
335 c8394ca1 2023-08-01 op icbirc_quit();
336 d23d2886 2023-07-30 op break;
337 d23d2886 2023-07-30 op case 'i': /* Command Output */
338 d23d2886 2023-07-30 op if (!strcmp(args[0], "co")) {
339 d23d2886 2023-07-30 op for (j = 1; j < i; ++j)
340 d23d2886 2023-07-30 op icb_ico(fd, args[j]);
341 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "wl")) {
342 d23d2886 2023-07-30 op icb_iwl(fd, args[1], args[2], atol(args[3]),
343 d23d2886 2023-07-30 op atol(args[5]), args[6], args[7]);
344 d23d2886 2023-07-30 op } else if (!strcmp(args[0], "wh")) {
345 d23d2886 2023-07-30 op /* display whois header, deprecated */
346 d23d2886 2023-07-30 op } else
347 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Command Output: %s: %u args",
348 d23d2886 2023-07-30 op args[0], i - 1);
349 d23d2886 2023-07-30 op break;
350 d23d2886 2023-07-30 op case 'j': /* Protocol */
351 d23d2886 2023-07-30 op strlcpy(icb_protolevel, args[0], sizeof(icb_protolevel));
352 d23d2886 2023-07-30 op strlcpy(icb_hostid, args[1], sizeof(icb_hostid));
353 d23d2886 2023-07-30 op strlcpy(icb_serverid, args[2], sizeof(icb_serverid));
354 d23d2886 2023-07-30 op break;
355 d23d2886 2023-07-30 op case 'k': /* Beep */
356 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Beep from %s", args[0]);
357 d23d2886 2023-07-30 op break;
358 d23d2886 2023-07-30 op case 'l': /* Ping */
359 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Ping '%s'", args[0]);
360 d23d2886 2023-07-30 op break;
361 d23d2886 2023-07-30 op case 'm': /* Pong */
362 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB Pong '%s'", args[0]);
363 d23d2886 2023-07-30 op break;
364 d23d2886 2023-07-30 op case 'n': /* No-op */
365 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB No-op");
366 d23d2886 2023-07-30 op break;
367 d23d2886 2023-07-30 op default:
368 d23d2886 2023-07-30 op irc_send_notice(fd, "ICB unknown command %d: %u args",
369 d23d2886 2023-07-30 op (int)cmd[0], i);
370 d23d2886 2023-07-30 op }
371 d23d2886 2023-07-30 op }
372 d23d2886 2023-07-30 op
373 d23d2886 2023-07-30 op static void
374 d23d2886 2023-07-30 op icb_iwl(int fd, const char *flags, const char *nick, long idle,
375 d23d2886 2023-07-30 op long signon, const char *ident, const char *host)
376 d23d2886 2023-07-30 op {
377 d23d2886 2023-07-30 op char s[8192];
378 d23d2886 2023-07-30 op int chanop = strchr(flags, 'm') != NULL;
379 d23d2886 2023-07-30 op
380 d23d2886 2023-07-30 op if (imode == imode_whois && !strcmp(nick, inick)) {
381 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 311 %s %s %s %s * :\r\n",
382 d23d2886 2023-07-30 op icb_hostid, irc_nick, nick, ident, host);
383 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
384 d23d2886 2023-07-30 op if (icurgroup[0]) {
385 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 319 %s %s :%s%s\r\n",
386 d23d2886 2023-07-30 op icb_hostid, irc_nick, nick, chanop ? "@" : "",
387 d23d2886 2023-07-30 op icurgroup);
388 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
389 d23d2886 2023-07-30 op }
390 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 312 %s %s %s :\r\n",
391 d23d2886 2023-07-30 op icb_hostid, irc_nick, nick, icb_hostid);
392 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
393 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 317 %s %s %ld %ld :seconds idle, "
394 d23d2886 2023-07-30 op "signon time\r\n",
395 d23d2886 2023-07-30 op icb_hostid, irc_nick, nick, idle, signon);
396 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
397 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 318 %s %s :End of /WHOIS list.\r\n",
398 d23d2886 2023-07-30 op icb_hostid, irc_nick, nick);
399 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
400 d23d2886 2023-07-30 op } else if (imode == imode_names && !strcmp(icurgroup, igroup)) {
401 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 353 %s @ %s :%s%s \r\n",
402 d23d2886 2023-07-30 op icb_hostid, irc_nick, icurgroup, chanop ? "@" : "", nick);
403 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
404 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 352 %s %s %s %s %s %s H :5 %s\r\n",
405 d23d2886 2023-07-30 op icb_hostid, irc_nick, icurgroup, nick, host, icb_hostid,
406 d23d2886 2023-07-30 op nick, ident);
407 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
408 d23d2886 2023-07-30 op } else if (imode == imode_who) {
409 d23d2886 2023-07-30 op int match;
410 d23d2886 2023-07-30 op
411 d23d2886 2023-07-30 op if (ihostmask[0] == '#')
412 d23d2886 2023-07-30 op match = !strcmp(icurgroup, ihostmask);
413 d23d2886 2023-07-30 op else {
414 d23d2886 2023-07-30 op char hostmask[1024];
415 d23d2886 2023-07-30 op
416 d23d2886 2023-07-30 op snprintf(hostmask, sizeof(hostmask), "%s!%s@%s",
417 d23d2886 2023-07-30 op nick, ident, host);
418 d23d2886 2023-07-30 op match = strstr(hostmask, ihostmask) != NULL;
419 d23d2886 2023-07-30 op }
420 d23d2886 2023-07-30 op if (match) {
421 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 352 %s %s %s %s %s %s "
422 d23d2886 2023-07-30 op "H :5 %s\r\n",
423 d23d2886 2023-07-30 op icb_hostid, irc_nick, icurgroup, nick, host,
424 d23d2886 2023-07-30 op icb_hostid, nick, ident);
425 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
426 d23d2886 2023-07-30 op }
427 d23d2886 2023-07-30 op }
428 d23d2886 2023-07-30 op
429 d23d2886 2023-07-30 op if (chanop && !strcmp(icurgroup, irc_channel))
430 d23d2886 2023-07-30 op strlcpy(icb_moderator, nick, sizeof(icb_moderator));
431 d23d2886 2023-07-30 op }
432 d23d2886 2023-07-30 op
433 d23d2886 2023-07-30 op static void
434 d23d2886 2023-07-30 op icb_ico(int fd, const char *arg)
435 d23d2886 2023-07-30 op {
436 d23d2886 2023-07-30 op char s[8192];
437 d23d2886 2023-07-30 op
438 d23d2886 2023-07-30 op if (!strncmp(arg, "Group: ", 7)) {
439 d23d2886 2023-07-30 op char group[256];
440 d23d2886 2023-07-30 op int i = 0;
441 d23d2886 2023-07-30 op char *topic;
442 d23d2886 2023-07-30 op
443 d23d2886 2023-07-30 op arg += 7;
444 d23d2886 2023-07-30 op group[i++] = '#';
445 d23d2886 2023-07-30 op while (*arg && *arg != ' ')
446 d23d2886 2023-07-30 op group[i++] = *arg++;
447 d23d2886 2023-07-30 op group[i] = 0;
448 d23d2886 2023-07-30 op strlcpy(icurgroup, group, sizeof(icurgroup));
449 d23d2886 2023-07-30 op topic = strstr(arg, "Topic: ");
450 d23d2886 2023-07-30 op if (topic == NULL)
451 d23d2886 2023-07-30 op topic = "(None)";
452 d23d2886 2023-07-30 op else
453 d23d2886 2023-07-30 op topic += 7;
454 d23d2886 2023-07-30 op if (imode == imode_list) {
455 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 322 %s %s 1 :%s\r\n",
456 d23d2886 2023-07-30 op icb_hostid, irc_nick, group, topic);
457 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
458 d23d2886 2023-07-30 op } else if (imode == imode_names &&
459 d23d2886 2023-07-30 op !strcmp(icurgroup, igroup)) {
460 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 332 %s %s :%s\r\n",
461 d23d2886 2023-07-30 op icb_hostid, irc_nick, icurgroup, topic);
462 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
463 d23d2886 2023-07-30 op }
464 d23d2886 2023-07-30 op } else if (!strncmp(arg, "Total: ", 7)) {
465 d23d2886 2023-07-30 op if (imode == imode_list) {
466 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 323 %s :End of /LIST\r\n",
467 d23d2886 2023-07-30 op icb_hostid, irc_nick);
468 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
469 d23d2886 2023-07-30 op } else if (imode == imode_names) {
470 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 366 %s %s :End of "
471 d23d2886 2023-07-30 op "/NAMES list.\r\n",
472 d23d2886 2023-07-30 op icb_hostid, irc_nick, igroup);
473 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
474 d23d2886 2023-07-30 op } else if (imode == imode_who) {
475 d23d2886 2023-07-30 op snprintf(s, sizeof(s), ":%s 315 %s %s :End of "
476 d23d2886 2023-07-30 op "/WHO list.\r\n",
477 d23d2886 2023-07-30 op icb_hostid, irc_nick, ihostmask);
478 d23d2886 2023-07-30 op sync_write(fd, s, strlen(s));
479 d23d2886 2023-07-30 op }
480 d23d2886 2023-07-30 op imode = imode_none;
481 d23d2886 2023-07-30 op } else if (strcmp(arg, " "))
482 d23d2886 2023-07-30 op irc_send_notice(fd, "*** Unknown ico: %s", arg);
483 d23d2886 2023-07-30 op }
484 d23d2886 2023-07-30 op
485 d23d2886 2023-07-30 op #define MAX_MSG_SIZE 246
486 d23d2886 2023-07-30 op
487 d23d2886 2023-07-30 op void
488 d23d2886 2023-07-30 op icb_send_login(int fd, const char *nick, const char *ident, const char *group)
489 d23d2886 2023-07-30 op {
490 d23d2886 2023-07-30 op char cmd[256];
491 d23d2886 2023-07-30 op unsigned off = 1;
492 d23d2886 2023-07-30 op const char *login_cmd = "login";
493 d23d2886 2023-07-30 op
494 d23d2886 2023-07-30 op cmd[off++] = 'a';
495 d23d2886 2023-07-30 op while (*ident && off < MAX_MSG_SIZE)
496 d23d2886 2023-07-30 op cmd[off++] = *ident++;
497 d23d2886 2023-07-30 op cmd[off++] = '\001';
498 d23d2886 2023-07-30 op while (*nick && off < MAX_MSG_SIZE)
499 d23d2886 2023-07-30 op cmd[off++] = *nick++;
500 d23d2886 2023-07-30 op cmd[off++] = '\001';
501 d23d2886 2023-07-30 op while (*group && off < MAX_MSG_SIZE)
502 d23d2886 2023-07-30 op cmd[off++] = *group++;
503 d23d2886 2023-07-30 op cmd[off++] = '\001';
504 d23d2886 2023-07-30 op while (*login_cmd)
505 d23d2886 2023-07-30 op cmd[off++] = *login_cmd++;
506 d23d2886 2023-07-30 op cmd[off++] = '\001';
507 d23d2886 2023-07-30 op cmd[off++] = '\001';
508 d23d2886 2023-07-30 op cmd[off++] = '\001';
509 d23d2886 2023-07-30 op cmd[0] = off - 1;
510 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
511 d23d2886 2023-07-30 op }
512 d23d2886 2023-07-30 op
513 d23d2886 2023-07-30 op void
514 d23d2886 2023-07-30 op icb_send_openmsg(int fd, const char *msg)
515 d23d2886 2023-07-30 op {
516 d23d2886 2023-07-30 op unsigned char cmd[256];
517 d23d2886 2023-07-30 op unsigned off;
518 d23d2886 2023-07-30 op
519 d23d2886 2023-07-30 op while (*msg) {
520 d23d2886 2023-07-30 op off = 1;
521 d23d2886 2023-07-30 op cmd[off++] = 'b';
522 d23d2886 2023-07-30 op while (*msg && off < MAX_MSG_SIZE)
523 d23d2886 2023-07-30 op cmd[off++] = *msg++;
524 d23d2886 2023-07-30 op cmd[off++] = 0;
525 d23d2886 2023-07-30 op cmd[0] = off - 1;
526 d23d2886 2023-07-30 op /* cmd[0] <= MAX_MSG_SIZE */
527 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
528 d23d2886 2023-07-30 op }
529 d23d2886 2023-07-30 op }
530 d23d2886 2023-07-30 op
531 d23d2886 2023-07-30 op void
532 d23d2886 2023-07-30 op icb_send_privmsg(int fd, const char *nick, const char *msg)
533 d23d2886 2023-07-30 op {
534 d23d2886 2023-07-30 op unsigned char cmd[256];
535 d23d2886 2023-07-30 op unsigned off;
536 d23d2886 2023-07-30 op
537 d23d2886 2023-07-30 op while (*msg) {
538 d23d2886 2023-07-30 op const char *n = nick;
539 d23d2886 2023-07-30 op
540 d23d2886 2023-07-30 op off = 1;
541 d23d2886 2023-07-30 op cmd[off++] = 'h';
542 d23d2886 2023-07-30 op cmd[off++] = 'm';
543 d23d2886 2023-07-30 op cmd[off++] = '\001';
544 d23d2886 2023-07-30 op while (*n && off < MAX_MSG_SIZE)
545 d23d2886 2023-07-30 op cmd[off++] = *n++;
546 d23d2886 2023-07-30 op cmd[off++] = ' ';
547 d23d2886 2023-07-30 op while (*msg && off < MAX_MSG_SIZE)
548 d23d2886 2023-07-30 op cmd[off++] = *msg++;
549 d23d2886 2023-07-30 op cmd[off++] = 0;
550 d23d2886 2023-07-30 op cmd[0] = off - 1;
551 d23d2886 2023-07-30 op /* cmd[0] <= MAX_MSG_SIZE */
552 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
553 d23d2886 2023-07-30 op }
554 d23d2886 2023-07-30 op }
555 d23d2886 2023-07-30 op
556 d23d2886 2023-07-30 op void
557 d23d2886 2023-07-30 op icb_send_group(int fd, const char *group)
558 d23d2886 2023-07-30 op {
559 d23d2886 2023-07-30 op char cmd[256];
560 d23d2886 2023-07-30 op unsigned off = 1;
561 d23d2886 2023-07-30 op
562 d23d2886 2023-07-30 op cmd[off++] = 'h';
563 d23d2886 2023-07-30 op cmd[off++] = 'g';
564 d23d2886 2023-07-30 op cmd[off++] = '\001';
565 d23d2886 2023-07-30 op while (*group && off < MAX_MSG_SIZE)
566 d23d2886 2023-07-30 op cmd[off++] = *group++;
567 d23d2886 2023-07-30 op cmd[off++] = 0;
568 d23d2886 2023-07-30 op cmd[0] = off - 1;
569 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
570 d23d2886 2023-07-30 op }
571 d23d2886 2023-07-30 op
572 d23d2886 2023-07-30 op static void
573 d23d2886 2023-07-30 op icb_send_hw(int fd, const char *arg)
574 d23d2886 2023-07-30 op {
575 d23d2886 2023-07-30 op char cmd[256];
576 d23d2886 2023-07-30 op unsigned off = 1;
577 d23d2886 2023-07-30 op
578 d23d2886 2023-07-30 op icurgroup[0] = 0;
579 d23d2886 2023-07-30 op cmd[off++] = 'h';
580 d23d2886 2023-07-30 op cmd[off++] = 'w';
581 d23d2886 2023-07-30 op cmd[off++] = '\001';
582 d23d2886 2023-07-30 op while (*arg && off < MAX_MSG_SIZE)
583 d23d2886 2023-07-30 op cmd[off++] = *arg++;
584 d23d2886 2023-07-30 op cmd[off++] = 0;
585 d23d2886 2023-07-30 op cmd[0] = off - 1;
586 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
587 d23d2886 2023-07-30 op }
588 d23d2886 2023-07-30 op
589 d23d2886 2023-07-30 op void
590 d23d2886 2023-07-30 op icb_send_list(int fd)
591 d23d2886 2023-07-30 op {
592 d23d2886 2023-07-30 op if (imode != imode_none)
593 d23d2886 2023-07-30 op return;
594 d23d2886 2023-07-30 op imode = imode_list;
595 d23d2886 2023-07-30 op icb_send_hw(fd, "-g");
596 d23d2886 2023-07-30 op }
597 d23d2886 2023-07-30 op
598 d23d2886 2023-07-30 op void
599 d23d2886 2023-07-30 op icb_send_names(int fd, const char *group)
600 d23d2886 2023-07-30 op {
601 d23d2886 2023-07-30 op if (imode != imode_none)
602 d23d2886 2023-07-30 op return;
603 d23d2886 2023-07-30 op imode = imode_names;
604 d23d2886 2023-07-30 op strlcpy(igroup, group, sizeof(igroup));
605 d23d2886 2023-07-30 op icb_send_hw(fd, "");
606 d23d2886 2023-07-30 op }
607 d23d2886 2023-07-30 op
608 d23d2886 2023-07-30 op void
609 d23d2886 2023-07-30 op icb_send_whois(int fd, const char *nick)
610 d23d2886 2023-07-30 op {
611 d23d2886 2023-07-30 op if (imode != imode_none)
612 d23d2886 2023-07-30 op return;
613 d23d2886 2023-07-30 op imode = imode_whois;
614 d23d2886 2023-07-30 op strlcpy(inick, nick, sizeof(inick));
615 d23d2886 2023-07-30 op icb_send_hw(fd, "");
616 d23d2886 2023-07-30 op }
617 d23d2886 2023-07-30 op
618 d23d2886 2023-07-30 op void
619 d23d2886 2023-07-30 op icb_send_who(int fd, const char *hostmask)
620 d23d2886 2023-07-30 op {
621 d23d2886 2023-07-30 op if (imode != imode_none)
622 d23d2886 2023-07-30 op return;
623 d23d2886 2023-07-30 op imode = imode_who;
624 d23d2886 2023-07-30 op strlcpy(ihostmask, hostmask, sizeof(ihostmask));
625 d23d2886 2023-07-30 op icb_send_hw(fd, "");
626 d23d2886 2023-07-30 op }
627 d23d2886 2023-07-30 op
628 d23d2886 2023-07-30 op void
629 d23d2886 2023-07-30 op icb_send_pass(int fd, const char *nick)
630 d23d2886 2023-07-30 op {
631 d23d2886 2023-07-30 op char cmd[256];
632 d23d2886 2023-07-30 op unsigned off = 1;
633 d23d2886 2023-07-30 op const char *pass_cmd = "pass";
634 d23d2886 2023-07-30 op
635 d23d2886 2023-07-30 op cmd[off++] = 'h';
636 d23d2886 2023-07-30 op while (*pass_cmd)
637 d23d2886 2023-07-30 op cmd[off++] = *pass_cmd++;
638 d23d2886 2023-07-30 op cmd[off++] = '\001';
639 d23d2886 2023-07-30 op while (*nick && off < MAX_MSG_SIZE)
640 d23d2886 2023-07-30 op cmd[off++] = *nick++;
641 d23d2886 2023-07-30 op cmd[off++] = 0;
642 d23d2886 2023-07-30 op cmd[0] = off - 1;
643 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
644 d23d2886 2023-07-30 op }
645 d23d2886 2023-07-30 op
646 d23d2886 2023-07-30 op void
647 d23d2886 2023-07-30 op icb_send_topic(int fd, const char *topic)
648 d23d2886 2023-07-30 op {
649 d23d2886 2023-07-30 op char cmd[256];
650 d23d2886 2023-07-30 op unsigned off = 1;
651 d23d2886 2023-07-30 op const char *topic_cmd = "topic";
652 d23d2886 2023-07-30 op
653 d23d2886 2023-07-30 op cmd[off++] = 'h';
654 d23d2886 2023-07-30 op while (*topic_cmd)
655 d23d2886 2023-07-30 op cmd[off++] = *topic_cmd++;
656 d23d2886 2023-07-30 op cmd[off++] = '\001';
657 d23d2886 2023-07-30 op while (*topic && off < MAX_MSG_SIZE)
658 d23d2886 2023-07-30 op cmd[off++] = *topic++;
659 d23d2886 2023-07-30 op cmd[off++] = 0;
660 d23d2886 2023-07-30 op cmd[0] = off - 1;
661 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
662 d23d2886 2023-07-30 op }
663 d23d2886 2023-07-30 op
664 d23d2886 2023-07-30 op void
665 d23d2886 2023-07-30 op icb_send_boot(int fd, const char *nick)
666 d23d2886 2023-07-30 op {
667 d23d2886 2023-07-30 op char cmd[256];
668 d23d2886 2023-07-30 op unsigned off = 1;
669 d23d2886 2023-07-30 op const char *boot_cmd = "boot";
670 d23d2886 2023-07-30 op
671 d23d2886 2023-07-30 op cmd[off++] = 'h';
672 d23d2886 2023-07-30 op while (*boot_cmd)
673 d23d2886 2023-07-30 op cmd[off++] = *boot_cmd++;
674 d23d2886 2023-07-30 op cmd[off++] = '\001';
675 d23d2886 2023-07-30 op while (*nick && off < MAX_MSG_SIZE)
676 d23d2886 2023-07-30 op cmd[off++] = *nick++;
677 d23d2886 2023-07-30 op cmd[off++] = 0;
678 d23d2886 2023-07-30 op cmd[0] = off - 1;
679 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
680 d23d2886 2023-07-30 op }
681 d23d2886 2023-07-30 op
682 d23d2886 2023-07-30 op void
683 d23d2886 2023-07-30 op icb_send_name(int fd, const char *nick)
684 d23d2886 2023-07-30 op {
685 d23d2886 2023-07-30 op char cmd[256];
686 d23d2886 2023-07-30 op unsigned off = 1;
687 d23d2886 2023-07-30 op const char *name_cmd = "name";
688 d23d2886 2023-07-30 op
689 d23d2886 2023-07-30 op cmd[off++] = 'h';
690 d23d2886 2023-07-30 op while (*name_cmd)
691 d23d2886 2023-07-30 op cmd[off++] = *name_cmd++;
692 d23d2886 2023-07-30 op cmd[off++] = '\001';
693 d23d2886 2023-07-30 op while (*nick && off < MAX_MSG_SIZE)
694 d23d2886 2023-07-30 op cmd[off++] = *nick++;
695 d23d2886 2023-07-30 op cmd[off++] = 0;
696 d23d2886 2023-07-30 op cmd[0] = off - 1;
697 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
698 d23d2886 2023-07-30 op }
699 d23d2886 2023-07-30 op
700 d23d2886 2023-07-30 op void
701 d23d2886 2023-07-30 op icb_send_raw(int fd, const char *data)
702 d23d2886 2023-07-30 op {
703 d23d2886 2023-07-30 op char cmd[256];
704 d23d2886 2023-07-30 op unsigned off = 1;
705 d23d2886 2023-07-30 op
706 d23d2886 2023-07-30 op while (*data && off < MAX_MSG_SIZE) {
707 d23d2886 2023-07-30 op if (*data == ',')
708 d23d2886 2023-07-30 op cmd[off++] = '\001';
709 d23d2886 2023-07-30 op else if (*data == '\\')
710 d23d2886 2023-07-30 op cmd[off++] = 0;
711 d23d2886 2023-07-30 op else
712 d23d2886 2023-07-30 op cmd[off++] = *data;
713 d23d2886 2023-07-30 op data++;
714 d23d2886 2023-07-30 op }
715 d23d2886 2023-07-30 op cmd[off++] = 0;
716 d23d2886 2023-07-30 op cmd[0] = off - 1;
717 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
718 d23d2886 2023-07-30 op }
719 d23d2886 2023-07-30 op
720 d23d2886 2023-07-30 op void
721 d23d2886 2023-07-30 op icb_send_noop(int fd)
722 d23d2886 2023-07-30 op {
723 d23d2886 2023-07-30 op char cmd[256];
724 d23d2886 2023-07-30 op unsigned off = 1;
725 d23d2886 2023-07-30 op
726 d23d2886 2023-07-30 op cmd[off++] = 'n';
727 d23d2886 2023-07-30 op cmd[off++] = 0;
728 d23d2886 2023-07-30 op cmd[0] = off - 1;
729 d23d2886 2023-07-30 op sync_write(fd, cmd, off);
730 d23d2886 2023-07-30 op }