source: code/cmd.c@ 96a2e31

Last change on this file since 96a2e31 was 383d37b, checked in by Mike Belopuhov <mike@…>, 11 years ago

don't allow to boot yourself

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