source: code/cmd.c@ ad8b08d

Last change on this file since ad8b08d was 7882a6f, checked in by Mike Belopuhov <mike@…>, 11 years ago

Get rid of the icbd callbacks interface

I believe the idea was initially to have both icb and irc in one
daemon but that's not going to happen.

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