source: code/cmd.c@ 9195a6a

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

add a simple help command

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