source: code/cmd.c@ e26e899

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

Bitch if trying to beep yourself

  • 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:");
[8bcfd50]76 icb_status(is, STATUS_HELP, "beep boot g m name nobeep pass topic w");
[9195a6a]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 }
[ec3eb38]115 if (s == is) {
116 icb_error(is, "Very funny... Not!");
117 return;
118 }
[bf02a60]119
120 if (ISSETF(s->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2)) {
121 icb_error(is, "User has nobeep enabled");
122 if (ISSETF(s->flags, ICB_SF_NOBEEP2))
123 icb_status(s, STATUS_NOBEEP,
124 "%s attempted to beep you", is->nick);
125 return;
126 }
127
128 icb_sendfmt(s, "%c%s", ICB_M_BEEP, is->nick);
129}
130
[cd7b81d]131void
132icb_cmd_boot(struct icb_session *is, char *arg)
133{
134 struct icb_group *ig;
135 struct icb_session *s;
[626f420]136 char whom[ICB_MAXNICKLEN];
[cd7b81d]137
138 /* to boot or not to boot, that is the question */
139 ig = is->group;
[4284008]140 if (!icb_ismod(ig, is)) {
[cd7b81d]141 icb_status(is, STATUS_NOTIFY, "Sorry, booting is a privilege "
142 "you don't possess");
143 return;
144 }
145
[fdbbc45]146 if (strlen(arg) == 0) {
[626f420]147 icb_error(is, "Invalid user");
148 return;
149 }
150
[b7bc432]151 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
[626f420]152
[cd7b81d]153 /* who would be a target then? */
154 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]155 if (strcmp(s->nick, whom) == 0)
[cd7b81d]156 break;
157 }
158 if (s == NULL) {
159 icb_status(is, STATUS_NOTIFY, "No such user");
160 return;
161 }
[383d37b]162 if (s == is) {
163 icb_error(is, "Just quit, would you?");
164 return;
165 }
[cd7b81d]166
167 /* okay, here we go, but first, be polite and notify a user */
168 icb_status(s, STATUS_BOOT, "%s booted you", is->nick);
169 icb_status_group(s->group, s, STATUS_BOOT, "%s was booted", s->nick);
[7882a6f]170 icbd_drop(s, "booted");
[cd7b81d]171}
172
173void
174icb_cmd_change(struct icb_session *is, char *arg)
175{
176 struct icb_group *ig;
177 struct icb_session *s;
[626f420]178 char group[ICB_MAXGRPLEN];
[cd7b81d]179 int changing = 0;
180
181 if (strlen(arg) == 0) {
[7ff6405]182 icb_error(is, "Invalid group name");
[cd7b81d]183 return;
184 }
185
[b7bc432]186 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
[626f420]187
[cd7b81d]188 LIST_FOREACH(ig, &groups, entry) {
[626f420]189 if (strcmp(ig->name, group) == 0)
[cd7b81d]190 break;
191 }
192 if (ig == NULL) {
193 if (!creategroups) {
[7ff6405]194 icb_error(is, "Can't create new groups");
[cd7b81d]195 return;
196 } else {
[677a45b]197 if ((ig = icb_addgroup(is, group)) == NULL) {
[7ff6405]198 icb_error(is, "Can't create group %s", group);
[cd7b81d]199 return;
200 }
[7882a6f]201 icbd_log(NULL, LOG_DEBUG, "%s created group %s",
[626f420]202 is->nick, group);
[cd7b81d]203 }
204 }
205
[4d92f03]206 /* see if we're changing to the same group */
[cd7b81d]207 if (is->group && is->group == ig) {
[4d92f03]208 icb_error(is, "You are already in that group");
[cd7b81d]209 return;
210 }
211
212 LIST_FOREACH(s, &ig->sess, entry) {
213 if (strcmp(s->nick, is->nick) == 0) {
214 icb_error(is, "Nick is already in use");
215 return;
216 }
217 }
218
219 if (is->group) {
220 changing = 1;
[4284008]221 if (icb_ismod(is->group, is))
[cd7b81d]222 (void)icb_pass(is->group, is, NULL);
223 LIST_REMOVE(is, entry);
224 icb_status_group(is->group, NULL, STATUS_DEPART,
225 "%s (%s@%s) just left", is->nick, is->client, is->host);
226 }
227
228 is->group = ig;
229 LIST_INSERT_HEAD(&ig->sess, is, entry);
230
231 /* notify group */
232 icb_status_group(ig, is, changing ? STATUS_ARRIVE : STATUS_SIGNON,
233 "%s (%s@%s) entered group", is->nick, is->client, is->host);
234
235 /* acknowledge successful join */
236 icb_status(is, STATUS_STATUS, "You are now in group %s%s", ig->name,
[4284008]237 icb_ismod(ig, is) ? " as moderator" : "");
[cd7b81d]238
239 /* send user a topic name */
240 if (strlen(ig->topic) > 0)
241 icb_status(is, STATUS_TOPIC, "The topic is: %s", ig->topic);
242}
243
244void
245icb_cmd_name(struct icb_session *is, char *arg)
246{
247 struct icb_group *ig = is->group;
248 struct icb_session *s;
[626f420]249 char nick[ICB_MAXNICKLEN];
[cd7b81d]250
251 if (strlen(arg) == 0) {
252 icb_status(is, STATUS_NAME, "Your nickname is %s",
253 is->nick);
254 return;
255 }
256 if (strcasecmp(arg, "admin") == 0) {
257 icb_error(is, "Wuff wuff!");
258 return;
259 }
260 /* sanitize user input */
261 if (strlen(arg) > ICB_MAXNICKLEN)
262 arg[ICB_MAXNICKLEN - 1] = '\0';
[b7bc432]263 icb_vis(nick, arg, ICB_MAXNICKLEN, VIS_SP);
[cd7b81d]264 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]265 if (strcmp(s->nick, nick) == 0) {
[cd7b81d]266 icb_error(is, "Nick is already in use");
267 return;
268 }
269 }
270 icb_status_group(ig, NULL, STATUS_NAME,
[626f420]271 "%s changed nickname to %s", is->nick, nick);
272 strlcpy(is->nick, nick, sizeof is->nick);
[cd7b81d]273}
274
[bf02a60]275void
276icb_cmd_nobeep(struct icb_session *is, char *arg)
277{
278 if (strlen(arg) == 0) {
279 /* fail if we have verbose turned on */
280 if (ISSETF(is->flags, ICB_SF_NOBEEP2)) {
281 icb_error(is, "Can't toggle your nobeep status");
282 return;
283 }
284 /* otherwise toggle the status */
285 if (ISSETF(is->flags, ICB_SF_NOBEEP))
286 CLRF(is->flags, ICB_SF_NOBEEP);
287 else
288 SETF(is->flags, ICB_SF_NOBEEP);
289 icb_status(is, STATUS_NOBEEP, "No-Beep %s",
290 ISSETF(is->flags, ICB_SF_NOBEEP) ? "on" : "off");
291 return;
292 }
293
294 if (strcmp(arg, "on") == 0) {
295 SETF(is->flags, ICB_SF_NOBEEP);
296 CLRF(is->flags, ICB_SF_NOBEEP2); /* can't be on and verbose */
297 icb_status(is, STATUS_NOBEEP, "No-Beep on");
298 } else if (strcmp(arg, "verbose") == 0) {
299 SETF(is->flags, ICB_SF_NOBEEP2);
300 CLRF(is->flags, ICB_SF_NOBEEP); /* can't be on and verbose */
301 icb_status(is, STATUS_NOBEEP, "No-Beep on (verbose)");
302 } else if (strcmp(arg, "off") == 0) {
303 CLRF(is->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2);
304 icb_status(is, STATUS_NOBEEP, "No-Beep off");
305 } else
306 icb_error(is, "Invalid nobeep mode");
307}
308
[cd7b81d]309void
310icb_cmd_personal(struct icb_session *is, char *arg)
311{
312 char *p;
313
314 if ((p = strchr(arg, ' ')) == 0) {
315 icb_error(is, "Empty message");
316 return;
317 }
318 *p = '\0';
319 icb_privmsg(is, arg, ++p);
320}
321
322void
[7eb46d4]323icb_cmd_pass(struct icb_session *is, char *arg)
[cd7b81d]324{
[7eb46d4]325 struct icb_group *ig = is->group;
326 struct icb_session *s;
[626f420]327 char whom[ICB_MAXNICKLEN];
[7eb46d4]328
[f3c60e6]329 if (!ig->mod) { /* if there is no mod, try grabbing it */
330 if (icb_modpermit(is, 0) && icb_pass(ig, ig->mod, is) < 0)
[e2fcbc7]331 icb_error(is, "Acquiring group moderation failed.");
332 } else if (icb_ismod(ig, is)) {
[a203cdb]333 if (strlen(arg) == 0) {
334 /* no argument: relinquish moderator */
335 (void)icb_pass(ig, ig->mod, NULL);
336 return;
337 }
[b7bc432]338 icb_vis(whom, arg, ICB_MAXNICKLEN, VIS_SP);
[7eb46d4]339 LIST_FOREACH(s, &ig->sess, entry) {
[626f420]340 if (strcmp(s->nick, whom) == 0)
[7eb46d4]341 break;
342 }
343 if (s == NULL) {
344 icb_status(is, STATUS_NOTIFY, "No such user");
345 return;
346 }
[f3c60e6]347 if (icb_modpermit(s, 0) && icb_pass(ig, ig->mod, s) < 0)
[e2fcbc7]348 icb_error(s, "Acquiring group moderation failed.");
[f3c60e6]349 } else {
350 /*
351 * if group is moderated and we're not the moderator,
352 * but modtab is enabled, then check the permission
353 * and pass moderation if successful.
354 */
355 if (icb_modpermit(is, 1) && icb_pass(ig, ig->mod, is) < 0)
356 icb_error(is, "Acquiring group moderation failed.");
[7eb46d4]357 }
[cd7b81d]358}
359
360void
361icb_cmd_topic(struct icb_session *is, char *arg)
362{
363 struct icb_group *ig = is->group;
[626f420]364 char topic[ICB_MAXTOPICLEN];
[cd7b81d]365
366 if (strlen(arg) == 0) { /* querying the topic */
367 if (strlen(ig->topic) > 0)
368 icb_status(is, STATUS_TOPIC, "The topic is: %s",
369 ig->topic);
370 else
371 icb_status(is, STATUS_TOPIC, "The topic is not set.");
372 } else { /* setting the topic */
[4284008]373 if (!icb_ismod(ig, is)) {
[8886035]374 icb_status(is, STATUS_NOTIFY, "Setting the topic is "
375 "only for moderators.");
376 return;
377 }
[b7bc432]378 icb_vis(topic, arg, ICB_MAXTOPICLEN, 0);
[626f420]379 strlcpy(ig->topic, topic, sizeof ig->topic);
[cd7b81d]380 icb_status_group(ig, NULL, STATUS_TOPIC,
381 "%s changed the topic to \"%s\"", is->nick, ig->topic);
382 }
383}
384
385void
[4284008]386icb_cmd_who(struct icb_session *is, char *arg)
[cd7b81d]387{
[4284008]388 struct icb_group *ig;
[626f420]389 char group[ICB_MAXGRPLEN];
[4284008]390
[b28dd0e]391 while (strlen(arg) && arg[0] == '-') { /* ignore options, for now */
392 /* ircII "set SHOW_CHANNEL_NAMES ON" uses /w -s */
393 while(arg[0] != ' ' && arg[0] != 0)
394 arg++;
395 if(arg[0] == ' ')
396 arg++;
397 }
398
[4284008]399 if (strlen(arg) == 0)
400 return icb_who(is, NULL);
401
[c102bbf]402 /* pidgin-icb treats '.' as the current group */
403 if (strlen(arg) == 1 && arg[0] == '.') {
404 icb_who(is, is->group);
405 return;
406 }
407
[b7bc432]408 icb_vis(group, arg, ICB_MAXGRPLEN, VIS_SP);
[4284008]409 LIST_FOREACH(ig, &groups, entry) {
[626f420]410 if (strcmp(ig->name, group) == 0)
[4284008]411 break;
412 }
413 if (ig == NULL) {
[626f420]414 icb_error(is, "The group %s doesn't exist.", group);
[4284008]415 return;
416 }
417 icb_who(is, ig);
[cd7b81d]418}
Note: See TracBrowser for help on using the repository browser.