source: code/cmd.c@ 21477e9

Last change on this file since 21477e9 was b28dd0e, checked in by Stuart Henderson <stu@…>, 11 years ago

Ignore flags for /w, ircII uses -s by default with "SHOW_CHANNEL_NAMES"

  • Property mode set to 100644
File size: 9.5 KB
Line 
1/*
2 * Copyright (c) 2009, 2010, 2013 Mike Belopuhov
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <sys/param.h>
18#include <sys/queue.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <string.h>
22#include <syslog.h>
23#include <unistd.h>
24#include <vis.h>
25#include <event.h>
26
27#include "icb.h"
28
29extern int creategroups;
30
31void icb_cmd_help(struct icb_session *, char *);
32void icb_cmd_beep(struct icb_session *, char *);
33void icb_cmd_boot(struct icb_session *, char *);
34void icb_cmd_change(struct icb_session *, char *);
35void icb_cmd_name(struct icb_session *, char *);
36void icb_cmd_nobeep(struct icb_session *, char *);
37void icb_cmd_personal(struct icb_session *, char *);
38void icb_cmd_pass(struct icb_session *, char *);
39void icb_cmd_topic(struct icb_session *, char *);
40void icb_cmd_who(struct icb_session *, char *);
41
42void *
43icb_cmd_lookup(char *cmd)
44{
45 struct {
46 const char *cmd;
47 void (*handler)(struct icb_session *, char *);
48 } cmdtab[] = {
49 { "?", icb_cmd_help },
50 { "beep", icb_cmd_beep },
51 { "boot", icb_cmd_boot },
52 { "g", icb_cmd_change },
53 { "m", icb_cmd_personal },
54 { "msg", icb_cmd_personal },
55 { "name", icb_cmd_name },
56 { "nobeep", icb_cmd_nobeep },
57 { "pass", icb_cmd_pass },
58 { "topic", icb_cmd_topic },
59 { "w", icb_cmd_who },
60 { NULL, NULL }
61 };
62 int i;
63
64 for (i = 0; cmdtab[i].cmd != NULL; i++)
65 if (strcasecmp(cmdtab[i].cmd, cmd) == 0)
66 return (cmdtab[i].handler);
67 return (NULL);
68}
69
70void
71icb_cmd_help(struct icb_session *is, char *arg __attribute__((unused)))
72{
73 icb_status(is, STATUS_HELP, "Server supports following commands:");
74 icb_status(is, STATUS_HELP, "beep boot g m name nobeep pass topic");
75}
76
77void
78icb_cmd_beep(struct icb_session *is, char *arg)
79{
80 struct icb_group *ig = is->group;
81 struct icb_session *s;
82 char whom[ICB_MAXNICKLEN];
83
84 if (strlen(arg) == 0) {
85 icb_error(is, "Invalid user");
86 return;
87 }
88
89 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
90
91 LIST_FOREACH(s, &ig->sess, entry) {
92 if (strcmp(s->nick, whom) == 0)
93 break;
94 }
95 if (s == NULL) {
96 icb_status(is, STATUS_NOTIFY, "%s is not signed on", whom);
97 return;
98 }
99
100 if (ISSETF(s->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2)) {
101 icb_error(is, "User has nobeep enabled");
102 if (ISSETF(s->flags, ICB_SF_NOBEEP2))
103 icb_status(s, STATUS_NOBEEP,
104 "%s attempted to beep you", is->nick);
105 return;
106 }
107
108 icb_sendfmt(s, "%c%s", ICB_M_BEEP, is->nick);
109}
110
111void
112icb_cmd_boot(struct icb_session *is, char *arg)
113{
114 struct icb_group *ig;
115 struct icb_session *s;
116 char whom[ICB_MAXNICKLEN];
117
118 /* to boot or not to boot, that is the question */
119 ig = is->group;
120 if (!icb_ismod(ig, is)) {
121 icb_status(is, STATUS_NOTIFY, "Sorry, booting is a privilege "
122 "you don't possess");
123 return;
124 }
125
126 if (strlen(arg) == 0) {
127 icb_error(is, "Invalid user");
128 return;
129 }
130
131 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
132
133 /* who would be a target then? */
134 LIST_FOREACH(s, &ig->sess, entry) {
135 if (strcmp(s->nick, whom) == 0)
136 break;
137 }
138 if (s == NULL) {
139 icb_status(is, STATUS_NOTIFY, "No such user");
140 return;
141 }
142
143 /* okay, here we go, but first, be polite and notify a user */
144 icb_status(s, STATUS_BOOT, "%s booted you", is->nick);
145 icb_status_group(s->group, s, STATUS_BOOT, "%s was booted", s->nick);
146 icb_drop(s, "booted");
147}
148
149void
150icb_cmd_change(struct icb_session *is, char *arg)
151{
152 struct icb_group *ig;
153 struct icb_session *s;
154 char group[ICB_MAXGRPLEN];
155 int changing = 0;
156
157 if (strlen(arg) == 0) {
158 icb_error(is, "Invalid group");
159 return;
160 }
161
162 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
163
164 LIST_FOREACH(ig, &groups, entry) {
165 if (strcmp(ig->name, group) == 0)
166 break;
167 }
168 if (ig == NULL) {
169 if (!creategroups) {
170 icb_error(is, "Invalid group");
171 return;
172 } else {
173 if ((ig = icb_addgroup(is, group, NULL)) == NULL) {
174 icb_error(is, "Can't create group");
175 return;
176 }
177 icb_log(NULL, LOG_DEBUG, "%s created group %s",
178 is->nick, group);
179 }
180 }
181
182 /* see if we're changing to the same group */
183 if (is->group && is->group == ig) {
184 icb_error(is, "You are already in that group");
185 return;
186 }
187
188 LIST_FOREACH(s, &ig->sess, entry) {
189 if (strcmp(s->nick, is->nick) == 0) {
190 icb_error(is, "Nick is already in use");
191 return;
192 }
193 }
194
195 if (is->group) {
196 changing = 1;
197 if (icb_ismod(is->group, is))
198 (void)icb_pass(is->group, is, NULL);
199 LIST_REMOVE(is, entry);
200 icb_status_group(is->group, NULL, STATUS_DEPART,
201 "%s (%s@%s) just left", is->nick, is->client, is->host);
202 }
203
204 is->group = ig;
205 LIST_INSERT_HEAD(&ig->sess, is, entry);
206
207 /* notify group */
208 icb_status_group(ig, is, changing ? STATUS_ARRIVE : STATUS_SIGNON,
209 "%s (%s@%s) entered group", is->nick, is->client, is->host);
210
211 /* acknowledge successful join */
212 icb_status(is, STATUS_STATUS, "You are now in group %s%s", ig->name,
213 icb_ismod(ig, is) ? " as moderator" : "");
214
215 /* send user a topic name */
216 if (strlen(ig->topic) > 0)
217 icb_status(is, STATUS_TOPIC, "The topic is: %s", ig->topic);
218}
219
220void
221icb_cmd_name(struct icb_session *is, char *arg)
222{
223 struct icb_group *ig = is->group;
224 struct icb_session *s;
225 char nick[ICB_MAXNICKLEN];
226
227 if (strlen(arg) == 0) {
228 icb_status(is, STATUS_NAME, "Your nickname is %s",
229 is->nick);
230 return;
231 }
232 if (strcasecmp(arg, "admin") == 0) {
233 icb_error(is, "Wuff wuff!");
234 return;
235 }
236 /* sanitize user input */
237 if (strlen(arg) > ICB_MAXNICKLEN)
238 arg[ICB_MAXNICKLEN - 1] = '\0';
239 icb_vis(nick, arg, ICB_MAXNICKLEN, VIS_SP);
240 LIST_FOREACH(s, &ig->sess, entry) {
241 if (strcmp(s->nick, nick) == 0) {
242 icb_error(is, "Nick is already in use");
243 return;
244 }
245 }
246 icb_status_group(ig, NULL, STATUS_NAME,
247 "%s changed nickname to %s", is->nick, nick);
248 strlcpy(is->nick, nick, sizeof is->nick);
249}
250
251void
252icb_cmd_nobeep(struct icb_session *is, char *arg)
253{
254 if (strlen(arg) == 0) {
255 /* fail if we have verbose turned on */
256 if (ISSETF(is->flags, ICB_SF_NOBEEP2)) {
257 icb_error(is, "Can't toggle your nobeep status");
258 return;
259 }
260 /* otherwise toggle the status */
261 if (ISSETF(is->flags, ICB_SF_NOBEEP))
262 CLRF(is->flags, ICB_SF_NOBEEP);
263 else
264 SETF(is->flags, ICB_SF_NOBEEP);
265 icb_status(is, STATUS_NOBEEP, "No-Beep %s",
266 ISSETF(is->flags, ICB_SF_NOBEEP) ? "on" : "off");
267 return;
268 }
269
270 if (strcmp(arg, "on") == 0) {
271 SETF(is->flags, ICB_SF_NOBEEP);
272 CLRF(is->flags, ICB_SF_NOBEEP2); /* can't be on and verbose */
273 icb_status(is, STATUS_NOBEEP, "No-Beep on");
274 } else if (strcmp(arg, "verbose") == 0) {
275 SETF(is->flags, ICB_SF_NOBEEP2);
276 CLRF(is->flags, ICB_SF_NOBEEP); /* can't be on and verbose */
277 icb_status(is, STATUS_NOBEEP, "No-Beep on (verbose)");
278 } else if (strcmp(arg, "off") == 0) {
279 CLRF(is->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2);
280 icb_status(is, STATUS_NOBEEP, "No-Beep off");
281 } else
282 icb_error(is, "Invalid nobeep mode");
283}
284
285void
286icb_cmd_personal(struct icb_session *is, char *arg)
287{
288 char *p;
289
290 if ((p = strchr(arg, ' ')) == 0) {
291 icb_error(is, "Empty message");
292 return;
293 }
294 *p = '\0';
295 icb_privmsg(is, arg, ++p);
296}
297
298void
299icb_cmd_pass(struct icb_session *is, char *arg)
300{
301 struct icb_group *ig = is->group;
302 struct icb_session *s;
303 char whom[ICB_MAXNICKLEN];
304
305 if (!ig->mod) { /* if there is no mod, let anyone grab it */
306 if (icb_pass(ig, ig->mod, is) < 0)
307 icb_error(is, "Acquiring group moderation failed.");
308 } else if (icb_ismod(ig, is)) {
309 if (strlen(arg) == 0) {
310 /* no argument: relinquish moderator */
311 (void)icb_pass(ig, ig->mod, NULL);
312 return;
313 }
314 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
315 LIST_FOREACH(s, &ig->sess, entry) {
316 if (strcmp(s->nick, whom) == 0)
317 break;
318 }
319 if (s == NULL) {
320 icb_status(is, STATUS_NOTIFY, "No such user");
321 return;
322 }
323 if (icb_pass(ig, ig->mod, s) < 0)
324 icb_error(s, "Acquiring group moderation failed.");
325 }
326}
327
328void
329icb_cmd_topic(struct icb_session *is, char *arg)
330{
331 struct icb_group *ig = is->group;
332 char topic[ICB_MAXTOPICLEN];
333
334 if (strlen(arg) == 0) { /* querying the topic */
335 if (strlen(ig->topic) > 0)
336 icb_status(is, STATUS_TOPIC, "The topic is: %s",
337 ig->topic);
338 else
339 icb_status(is, STATUS_TOPIC, "The topic is not set.");
340 } else { /* setting the topic */
341 if (!icb_ismod(ig, is)) {
342 icb_status(is, STATUS_NOTIFY, "Setting the topic is "
343 "only for moderators.");
344 return;
345 }
346 icb_vis(topic, arg, ICB_MAXTOPICLEN, 0);
347 strlcpy(ig->topic, topic, sizeof ig->topic);
348 icb_status_group(ig, NULL, STATUS_TOPIC,
349 "%s changed the topic to \"%s\"", is->nick, ig->topic);
350 }
351}
352
353void
354icb_cmd_who(struct icb_session *is, char *arg)
355{
356 struct icb_group *ig;
357 char group[ICB_MAXGRPLEN];
358
359 while (strlen(arg) && arg[0] == '-') { /* ignore options, for now */
360 /* ircII "set SHOW_CHANNEL_NAMES ON" uses /w -s */
361 while(arg[0] != ' ' && arg[0] != 0)
362 arg++;
363 if(arg[0] == ' ')
364 arg++;
365 }
366
367 if (strlen(arg) == 0)
368 return icb_who(is, NULL);
369
370 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
371 LIST_FOREACH(ig, &groups, entry) {
372 if (strcmp(ig->name, group) == 0)
373 break;
374 }
375 if (ig == NULL) {
376 icb_error(is, "The group %s doesn't exist.", group);
377 return;
378 }
379 icb_who(is, ig);
380}
Note: See TracBrowser for help on using the repository browser.