source: code/cmd.c@ bf02a60

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

add 'beep' and 'nobeep' support

  • Property mode set to 100644
File size: 7.9 KB
RevLine 
[cd7b81d]1/*
2 * Copyright (c) 2009, 2010 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 <event.h>
25
26#include "icb.h"
27
28extern int creategroups;
29
[bf02a60]30void icb_cmd_beep(struct icb_session *, char *);
[cd7b81d]31void icb_cmd_boot(struct icb_session *, char *);
32void icb_cmd_change(struct icb_session *, char *);
33void icb_cmd_name(struct icb_session *, char *);
[bf02a60]34void icb_cmd_nobeep(struct icb_session *, char *);
[cd7b81d]35void icb_cmd_personal(struct icb_session *, char *);
36void icb_cmd_pass(struct icb_session *, char *);
37void icb_cmd_topic(struct icb_session *, char *);
38void icb_cmd_who(struct icb_session *, char *);
39
40void *
41icb_cmd_lookup(char *cmd)
42{
43 struct {
44 const char *cmd;
45 void (*handler)(struct icb_session *, char *);
46 } cmdtab[] = {
[bf02a60]47 { "beep", icb_cmd_beep },
[cd7b81d]48 { "boot", icb_cmd_boot },
49 { "g", icb_cmd_change },
50 { "m", icb_cmd_personal },
51 { "msg", icb_cmd_personal },
52 { "name", icb_cmd_name },
[bf02a60]53 { "nobeep", icb_cmd_nobeep },
[cd7b81d]54 { "pass", icb_cmd_pass },
55 { "topic", icb_cmd_topic },
56 { "w", icb_cmd_who },
57 { NULL, NULL }
58 };
59 int i;
60
61 for (i = 0; cmdtab[i].cmd != NULL; i++)
62 if (strcasecmp(cmdtab[i].cmd, cmd) == 0)
63 return (cmdtab[i].handler);
64 return (NULL);
65}
66
[bf02a60]67void
68icb_cmd_beep(struct icb_session *is, char *arg)
69{
70 struct icb_group *ig = is->group;
71 struct icb_session *s;
72
73 if (strlen(arg) == 0) {
74 icb_error(is, "Invalid user");
75 return;
76 }
77
78 LIST_FOREACH(s, &ig->sess, entry) {
79 if (strcmp(s->nick, arg) == 0)
80 break;
81 }
82 if (s == NULL) {
83 icb_status(is, STATUS_NOTIFY, "%s is not signed on", arg);
84 return;
85 }
86
87 if (ISSETF(s->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2)) {
88 icb_error(is, "User has nobeep enabled");
89 if (ISSETF(s->flags, ICB_SF_NOBEEP2))
90 icb_status(s, STATUS_NOBEEP,
91 "%s attempted to beep you", is->nick);
92 return;
93 }
94
95 icb_sendfmt(s, "%c%s", ICB_M_BEEP, is->nick);
96}
97
[cd7b81d]98void
99icb_cmd_boot(struct icb_session *is, char *arg)
100{
101 struct icb_group *ig;
102 struct icb_session *s;
103
104 /* to boot or not to boot, that is the question */
105 ig = is->group;
106 if (!icb_ismoder(ig, is)) {
107 icb_status(is, STATUS_NOTIFY, "Sorry, booting is a privilege "
108 "you don't possess");
109 return;
110 }
111
112 /* who would be a target then? */
113 LIST_FOREACH(s, &ig->sess, entry) {
114 if (strcmp(s->nick, arg) == 0)
115 break;
116 }
117 if (s == NULL) {
118 icb_status(is, STATUS_NOTIFY, "No such user");
119 return;
120 }
121
122 /* okay, here we go, but first, be polite and notify a user */
123 icb_status(s, STATUS_BOOT, "%s booted you", is->nick);
124 icb_status_group(s->group, s, STATUS_BOOT, "%s was booted", s->nick);
125 icb_drop(s, "booted");
126}
127
128void
129icb_cmd_change(struct icb_session *is, char *arg)
130{
131 struct icb_group *ig;
132 struct icb_session *s;
133 int changing = 0;
134
135 if (strlen(arg) == 0) {
136 icb_error(is, "Invalid group");
137 return;
138 }
139
140 LIST_FOREACH(ig, &groups, entry) {
141 if (strcmp(ig->name, arg) == 0)
142 break;
143 }
144 if (ig == NULL) {
145 if (!creategroups) {
146 icb_error(is, "Invalid group");
147 return;
148 } else {
149 if ((ig = icb_addgroup(is, arg, NULL)) == NULL) {
150 icb_error(is, "Can't create group");
151 return;
152 }
153 icb_log(NULL, LOG_DEBUG, "%s created group %s",
154 is->nick, arg);
155 }
156 }
157
[4d92f03]158 /* see if we're changing to the same group */
[cd7b81d]159 if (is->group && is->group == ig) {
[4d92f03]160 icb_error(is, "You are already in that group");
[cd7b81d]161 return;
162 }
163
164 LIST_FOREACH(s, &ig->sess, entry) {
165 if (strcmp(s->nick, is->nick) == 0) {
166 icb_error(is, "Nick is already in use");
167 return;
168 }
169 }
170
171 if (is->group) {
172 changing = 1;
173 if (icb_ismoder(is->group, is))
174 (void)icb_pass(is->group, is, NULL);
175 LIST_REMOVE(is, entry);
176 icb_status_group(is->group, NULL, STATUS_DEPART,
177 "%s (%s@%s) just left", is->nick, is->client, is->host);
178 }
179
180 is->group = ig;
181 LIST_INSERT_HEAD(&ig->sess, is, entry);
182
183 /* notify group */
184 icb_status_group(ig, is, changing ? STATUS_ARRIVE : STATUS_SIGNON,
185 "%s (%s@%s) entered group", is->nick, is->client, is->host);
186
187 /* acknowledge successful join */
188 icb_status(is, STATUS_STATUS, "You are now in group %s%s", ig->name,
189 icb_ismoder(ig, is) ? " as moderator" : "");
190
191 /* send user a topic name */
192 if (strlen(ig->topic) > 0)
193 icb_status(is, STATUS_TOPIC, "The topic is: %s", ig->topic);
194}
195
196void
197icb_cmd_name(struct icb_session *is, char *arg)
198{
199 struct icb_group *ig = is->group;
200 struct icb_session *s;
201
202 if (strlen(arg) == 0) {
203 icb_status(is, STATUS_NAME, "Your nickname is %s",
204 is->nick);
205 return;
206 }
207 if (strcasecmp(arg, "admin") == 0) {
208 icb_error(is, "Wuff wuff!");
209 return;
210 }
211 /* sanitize user input */
212 if (strlen(arg) > ICB_MAXNICKLEN)
213 arg[ICB_MAXNICKLEN - 1] = '\0';
214 LIST_FOREACH(s, &ig->sess, entry) {
215 if (strcmp(s->nick, arg) == 0) {
216 icb_error(is, "Nick is already in use");
217 return;
218 }
219 }
220 icb_status_group(ig, NULL, STATUS_NAME,
221 "%s changed nickname to %s", is->nick, arg);
222 strlcpy(is->nick, arg, sizeof is->nick);
223}
224
[bf02a60]225void
226icb_cmd_nobeep(struct icb_session *is, char *arg)
227{
228 if (strlen(arg) == 0) {
229 /* fail if we have verbose turned on */
230 if (ISSETF(is->flags, ICB_SF_NOBEEP2)) {
231 icb_error(is, "Can't toggle your nobeep status");
232 return;
233 }
234 /* otherwise toggle the status */
235 if (ISSETF(is->flags, ICB_SF_NOBEEP))
236 CLRF(is->flags, ICB_SF_NOBEEP);
237 else
238 SETF(is->flags, ICB_SF_NOBEEP);
239 icb_status(is, STATUS_NOBEEP, "No-Beep %s",
240 ISSETF(is->flags, ICB_SF_NOBEEP) ? "on" : "off");
241 return;
242 }
243
244 if (strcmp(arg, "on") == 0) {
245 SETF(is->flags, ICB_SF_NOBEEP);
246 CLRF(is->flags, ICB_SF_NOBEEP2); /* can't be on and verbose */
247 icb_status(is, STATUS_NOBEEP, "No-Beep on");
248 } else if (strcmp(arg, "verbose") == 0) {
249 SETF(is->flags, ICB_SF_NOBEEP2);
250 CLRF(is->flags, ICB_SF_NOBEEP); /* can't be on and verbose */
251 icb_status(is, STATUS_NOBEEP, "No-Beep on (verbose)");
252 } else if (strcmp(arg, "off") == 0) {
253 CLRF(is->flags, ICB_SF_NOBEEP | ICB_SF_NOBEEP2);
254 icb_status(is, STATUS_NOBEEP, "No-Beep off");
255 } else
256 icb_error(is, "Invalid nobeep mode");
257}
258
[cd7b81d]259void
260icb_cmd_personal(struct icb_session *is, char *arg)
261{
262 char *p;
263
264 if ((p = strchr(arg, ' ')) == 0) {
265 icb_error(is, "Empty message");
266 return;
267 }
268 *p = '\0';
269 icb_privmsg(is, arg, ++p);
270}
271
272void
[7eb46d4]273icb_cmd_pass(struct icb_session *is, char *arg)
[cd7b81d]274{
[7eb46d4]275 struct icb_group *ig = is->group;
276 struct icb_session *s;
277
278 if (!ig->moder) /* if there is no mod, let anyone grab it */
279 (void)icb_pass(ig, ig->moder, is);
280 else if (icb_ismoder(ig, is)) {
281 LIST_FOREACH(s, &ig->sess, entry) {
282 if (strcmp(s->nick, arg) == 0)
283 break;
284 }
285 if (s == NULL) {
286 icb_status(is, STATUS_NOTIFY, "No such user");
287 return;
288 }
289 (void)icb_pass(ig, ig->moder, s);
290 }
[cd7b81d]291}
292
293void
294icb_cmd_topic(struct icb_session *is, char *arg)
295{
296 struct icb_group *ig = is->group;
297
298 if (strlen(arg) == 0) { /* querying the topic */
299 if (strlen(ig->topic) > 0)
300 icb_status(is, STATUS_TOPIC, "The topic is: %s",
301 ig->topic);
302 else
303 icb_status(is, STATUS_TOPIC, "The topic is not set.");
304 } else { /* setting the topic */
[8886035]305 if (!icb_ismoder(ig, is)) {
306 icb_status(is, STATUS_NOTIFY, "Setting the topic is "
307 "only for moderators.");
308 return;
309 }
[cd7b81d]310 strlcpy(ig->topic, arg, sizeof ig->topic);
311 icb_status_group(ig, NULL, STATUS_TOPIC,
312 "%s changed the topic to \"%s\"", is->nick, ig->topic);
313 }
314}
315
316void
317icb_cmd_who(struct icb_session *is, char *arg __attribute__((unused)))
318{
319 icb_who(is, NULL);
320}
Note: See TracBrowser for help on using the repository browser.