1 |
/** |
2 |
* main.C: This file contains the main() routine. |
3 |
* |
4 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
5 |
* Rights to this code are as documented in COPYING. |
6 |
* |
7 |
* |
8 |
* Portions of this file were derived from sources bearing the following license: |
9 |
* Copyright © 2005 Atheme Development Group |
10 |
* Rights to this code are documented in doc/pod/license.pod. |
11 |
* |
12 |
* $Id: main.C,v 1.8 2007-09-16 18:54:43 pippijn Exp $ |
13 |
*/ |
14 |
|
15 |
#include "atheme.h" |
16 |
#include "confparse.h" |
17 |
#include <ermyth/module.h> |
18 |
#include "uplink.h" /* XXX direct use of protocol_handler::notice_global_sts () */ |
19 |
|
20 |
static char const rcsid[] = "$Id: main.C,v 1.8 2007-09-16 18:54:43 pippijn Exp $"; |
21 |
|
22 |
REGISTER_MODULE ("global/main", false, "The Ermyth Team <http://ermyth.xinutec.org>"); |
23 |
|
24 |
static void on_config_ready (void); |
25 |
|
26 |
cmdvec g_cmdtree; |
27 |
E cmdvec os_cmdtree; |
28 |
helpvec g_helptree; |
29 |
E helpvec os_helptree; |
30 |
|
31 |
static void g_cmd_global (sourceinfo_t *si, const int parc, char *parv[]); |
32 |
static void g_cmd_help (sourceinfo_t *si, const int parc, char *parv[]); |
33 |
|
34 |
command_t const g_help = { "HELP", N_("Displays contextual help information."), PRIV_GLOBAL, 1, g_cmd_help }; |
35 |
command_t const g_global = { "GLOBAL", N_("Sends a global notice."), PRIV_GLOBAL, 1, g_cmd_global }; |
36 |
|
37 |
/* HELP <command> [params] */ |
38 |
static void |
39 |
g_cmd_help (sourceinfo_t *si, const int parc, char *parv[]) |
40 |
{ |
41 |
char *command = parv[0]; |
42 |
|
43 |
if (!command) |
44 |
{ |
45 |
command_help (si, g_cmdtree); |
46 |
command_success_nodata (si, "For more specific help use \2HELP \37command\37\2."); |
47 |
|
48 |
return; |
49 |
} |
50 |
|
51 |
/* take the command through the hash table */ |
52 |
help_display (si, command, g_helptree); |
53 |
} |
54 |
|
55 |
/* GLOBAL <parameters>|SEND|CLEAR */ |
56 |
static void |
57 |
g_cmd_global (sourceinfo_t *si, const int parc, char *parv[]) |
58 |
{ |
59 |
char *message; |
60 |
static list_t globlist; |
61 |
node_t *n, *tn; |
62 |
char *params = parv[0]; |
63 |
static char *sender = NULL; |
64 |
bool isfirst; |
65 |
char buf[BUFSIZE]; |
66 |
|
67 |
if (!params) |
68 |
{ |
69 |
command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "GLOBAL"); |
70 |
command_fail (si, fault::needmoreparams, _("Syntax: GLOBAL <parameters>|SEND|CLEAR")); |
71 |
return; |
72 |
} |
73 |
|
74 |
if (!strcasecmp ("CLEAR", params)) |
75 |
{ |
76 |
if (!globlist.count) |
77 |
{ |
78 |
command_fail (si, fault::nochange, _("No message to clear.")); |
79 |
return; |
80 |
} |
81 |
|
82 |
/* destroy the list we made */ |
83 |
LIST_FOREACH_SAFE (n, tn, globlist.head) |
84 |
{ |
85 |
message = static_cast<char *> (n->data); |
86 |
node_del (n, &globlist); |
87 |
node_free (n); |
88 |
sfree (message); |
89 |
} |
90 |
|
91 |
sfree (sender); |
92 |
sender = NULL; |
93 |
|
94 |
command_success_nodata (si, "The pending message has been deleted."); |
95 |
|
96 |
return; |
97 |
} |
98 |
|
99 |
if (!strcasecmp ("SEND", params)) |
100 |
{ |
101 |
if (!globlist.count) |
102 |
{ |
103 |
command_fail (si, fault::nosuch_target, _("No message to send.")); |
104 |
return; |
105 |
} |
106 |
|
107 |
isfirst = true; |
108 |
LIST_FOREACH (n, globlist.head) |
109 |
{ |
110 |
message = static_cast<char *> (n->data); |
111 |
|
112 |
snprintf (buf, sizeof buf, "[Network Notice] %s%s%s", isfirst ? si->su->nick : "", isfirst ? " - " : "", message); |
113 |
/* Cannot use si->service->me here, global notices |
114 |
* should come from global even if /os global was |
115 |
* used. */ |
116 |
phandler->notice_global_sts (globsvs.me->me, "*", buf); |
117 |
isfirst = false; |
118 |
/* log everything */ |
119 |
logcommand (si, CMDLOG_ADMIN, "GLOBAL %s", message); |
120 |
} |
121 |
logcommand (si, CMDLOG_ADMIN, "GLOBAL (%d lines sent)", LIST_LENGTH (&globlist)); |
122 |
|
123 |
/* destroy the list we made */ |
124 |
LIST_FOREACH_SAFE (n, tn, globlist.head) |
125 |
{ |
126 |
message = static_cast<char *> (n->data); |
127 |
node_del (n, &globlist); |
128 |
node_free (n); |
129 |
sfree (message); |
130 |
} |
131 |
|
132 |
sfree (sender); |
133 |
sender = NULL; |
134 |
|
135 |
snoop ("GLOBAL: \2%s\2", get_oper_name (si)); |
136 |
|
137 |
command_success_nodata (si, "The global notice has been sent."); |
138 |
|
139 |
return; |
140 |
} |
141 |
|
142 |
if (!sender) |
143 |
sender = sstrdup (si->su->nick); |
144 |
|
145 |
if (irccasecmp (sender, si->su->nick)) |
146 |
{ |
147 |
command_fail (si, fault::noprivs, _("There is already a GLOBAL in progress by \2%s\2."), sender); |
148 |
return; |
149 |
} |
150 |
|
151 |
message = sstrdup (params); |
152 |
|
153 |
n = node_create (); |
154 |
node_add (message, n, &globlist); |
155 |
|
156 |
command_success_nodata (si, "Stored text to be sent as line %d. Use \2GLOBAL SEND\2 " |
157 |
"to send message, \2GLOBAL CLEAR\2 to delete the pending message, " |
158 |
"or \2GLOBAL\2 to store additional lines.", globlist.count); |
159 |
} |
160 |
|
161 |
/* main services client routine */ |
162 |
static void |
163 |
global (sourceinfo_t *si, int parc, char *parv[]) |
164 |
{ |
165 |
char orig[BUFSIZE]; |
166 |
char *cmd; |
167 |
char *text; |
168 |
|
169 |
/* this should never happen */ |
170 |
if (parv[0][0] == '&') |
171 |
{ |
172 |
slog (LG_ERROR, "services(): got parv with local channel: %s", parv[0]); |
173 |
return; |
174 |
} |
175 |
|
176 |
/* make a copy of the original for debugging */ |
177 |
strlcpy (orig, parv[parc - 1], BUFSIZE); |
178 |
|
179 |
/* lets go through this to get the command */ |
180 |
cmd = strtok (parv[parc - 1], " "); |
181 |
text = strtok (NULL, ""); |
182 |
|
183 |
if (!cmd) |
184 |
return; |
185 |
if (*cmd == '\001') |
186 |
{ |
187 |
handle_ctcp_common (si, cmd, text); |
188 |
return; |
189 |
} |
190 |
|
191 |
command_exec_split (si->service, si, cmd, text, g_cmdtree); |
192 |
} |
193 |
|
194 |
static void |
195 |
on_config_ready (void) |
196 |
{ |
197 |
if (globsvs.me) |
198 |
del_service (globsvs.me); |
199 |
|
200 |
globsvs.me = add_service (globsvs.nick, globsvs.user, globsvs.host, globsvs.real, global, g_cmdtree); |
201 |
globsvs.disp = globsvs.me->disp; |
202 |
} |
203 |
|
204 |
bool |
205 |
_modinit (module *m) |
206 |
{ |
207 |
ConfTable::callback.ready.attach (on_config_ready); |
208 |
|
209 |
if (!cold_start) |
210 |
{ |
211 |
globsvs.me = add_service (globsvs.nick, globsvs.user, globsvs.host, globsvs.real, global, g_cmdtree); |
212 |
globsvs.disp = globsvs.me->disp; |
213 |
} |
214 |
|
215 |
g_cmdtree << g_global; |
216 |
os_cmdtree << g_global; |
217 |
|
218 |
help_addentry (os_helptree, "GLOBAL", "help/global/global", NULL); |
219 |
help_addentry (g_helptree, "HELP", "help/global/help", NULL); |
220 |
help_addentry (g_helptree, "GLOBAL", "help/global/global", NULL); |
221 |
|
222 |
g_cmdtree << g_help; |
223 |
|
224 |
return true; |
225 |
} |
226 |
|
227 |
void |
228 |
_moddeinit () |
229 |
{ |
230 |
if (globsvs.me) |
231 |
{ |
232 |
del_service (globsvs.me); |
233 |
globsvs.me = NULL; |
234 |
} |
235 |
|
236 |
g_cmdtree >> g_global; |
237 |
os_cmdtree >> g_global; |
238 |
|
239 |
help_delentry (os_helptree, "GLOBAL"); |
240 |
|
241 |
help_delentry (g_helptree, "GLOBAL"); |
242 |
help_delentry (g_helptree, "HELP"); |
243 |
|
244 |
g_cmdtree >> g_help; |
245 |
|
246 |
ConfTable::callback.ready.detach (on_config_ready); |
247 |
} |