source: code/cmd.c@ 61fdba7

Last change on this file since 61fdba7 was 61fdba7, checked in by Mike Belopuhov <mike@…>, 10 years ago

Allow to beep chaps lurking in different groups

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