Anope IRC Services  Version 1.8
os_akill.c
Go to the documentation of this file.
1 /* OperServ core functions
2  *
3  * (C) 2003-2014 Anope Team
4  * Contact us at team@anope.org
5  *
6  * Please read COPYING and README for further details.
7  *
8  * Based on the original code of Epona by Lara.
9  * Based on the original code of Services by Andy Church.
10  *
11  *
12  */
13 /*************************************************************************/
14 
15 #include "module.h"
16 
17 static int do_akill(User * u);
18 static int akill_view_callback(SList * slist, int number, void *item,
19  va_list args);
20 static int akill_view(int number, Akill * ak, User * u, int *sent_header);
21 static int akill_list_callback(SList * slist, int number, void *item,
22  va_list args);
23 static int akill_list(int number, Akill * ak, User * u, int *sent_header);
24 static void myOperServHelp(User * u);
25 
32 int AnopeInit(int argc, char **argv)
33 {
34  Command *c;
35 
36  moduleAddAuthor("Anope");
38  (VERSION_STRING);
40  c = createCommand("AKILL", do_akill, is_services_oper, OPER_HELP_AKILL,
41  -1, -1, -1, -1);
43 
45 
46  return MOD_CONT;
47 }
48 
52 void AnopeFini(void)
53 {
54 
55 }
56 
57 
58 
63 static void myOperServHelp(User * u)
64 {
65  if (is_services_oper(u)) {
66  notice_lang(s_OperServ, u, OPER_HELP_CMD_AKILL);
67  }
68 }
69 
75 /* Manage the AKILL list. */
76 
77 static int do_akill(User * u)
78 {
79  char *cmd = strtok(NULL, " ");
80  char breason[BUFSIZE];
81 
82  if (!cmd)
83  cmd = "";
84 
85  if (!stricmp(cmd, "ADD")) {
86  int deleted = 0;
87  char *expiry, *mask, *reason;
88  time_t expires, now = time(NULL);
89 
90  mask = strtok(NULL, " ");
91  if (mask && *mask == '+') {
92  expiry = mask;
93  mask = strtok(NULL, " ");
94  } else {
95  expiry = NULL;
96  }
97 
98  expires = expiry ? dotime(expiry) : AutokillExpiry;
99  /* If the expiry given does not contain a final letter, it's in days,
100  * said the doc. Ah well.
101  */
102  if (expiry && isdigit(expiry[strlen(expiry) - 1]))
103  expires *= 86400;
104  /* Do not allow less than a minute expiry time */
105  if (expires != 0 && expires < 60) {
106  notice_lang(s_OperServ, u, BAD_EXPIRY_TIME);
107  return MOD_CONT;
108  } else if (expires > 0) {
109  expires += time(NULL);
110  }
111 
112  if (mask && (reason = strtok(NULL, ""))) {
113  /* We first do some sanity check on the proposed mask. */
114  if (strchr(mask, '!')) {
115  notice_lang(s_OperServ, u, OPER_AKILL_NO_NICK);
116  return MOD_CONT;
117  }
118 
119  if (!strchr(mask, '@')) {
120  notice_lang(s_OperServ, u, BAD_USERHOST_MASK);
121  return MOD_CONT;
122  }
123 
124  if (mask && strspn(mask, "~@.*?") == strlen(mask)) {
125  notice_lang(s_OperServ, u, USERHOST_MASK_TOO_WIDE, mask);
126  return MOD_CONT;
127  }
128 
134  if (AddAkiller) {
135  snprintf(breason, sizeof(breason), "[%s] %s", u->nick,
136  reason);
137  reason = sstrdup(breason);
138  }
139 
140  deleted = add_akill(u, mask, u->nick, expires, reason);
141  if (deleted < 0) {
142  if (AddAkiller) {
143  free(reason);
144  }
145  return MOD_CONT;
146  } else if (deleted) {
147  notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL,
148  deleted);
149  }
150  notice_lang(s_OperServ, u, OPER_AKILL_ADDED, mask);
151 
152  if (WallOSAkill) {
153  char buf[128];
154 
155  if (!expires) {
156  strcpy(buf, "does not expire");
157  } else {
158  int wall_expiry = expires - now;
159  char *s = NULL;
160 
161  if (wall_expiry >= 86400) {
162  wall_expiry /= 86400;
163  s = "day";
164  } else if (wall_expiry >= 3600) {
165  wall_expiry /= 3600;
166  s = "hour";
167  } else if (wall_expiry >= 60) {
168  wall_expiry /= 60;
169  s = "minute";
170  }
171 
172  snprintf(buf, sizeof(buf), "expires in %d %s%s",
173  wall_expiry, s,
174  (wall_expiry == 1) ? "" : "s");
175  }
176 
178  "%s added an AKILL for %s (%s) (%s)",
179  u->nick, mask, reason, buf);
180  }
181 
182  if (readonly) {
183  notice_lang(s_OperServ, u, READ_ONLY_MODE);
184  }
185  if (AddAkiller) {
186  free(reason);
187  }
188  } else {
189  syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX);
190  }
191 
192  } else if (!stricmp(cmd, "DEL")) {
193 
194  char *mask;
195  int res = 0;
196 
197  mask = strtok(NULL, " ");
198 
199  if (!mask) {
200  syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX);
201  return MOD_CONT;
202  }
203 
204  if (akills.count == 0) {
205  notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY);
206  return MOD_CONT;
207  }
208 
209  if (isdigit(*mask) && strspn(mask, "1234567890,-") == strlen(mask)) {
210  /* Deleting a range */
211  res = slist_delete_range(&akills, mask, NULL);
212  if (res == 0) {
213  notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH);
214  return MOD_CONT;
215  } else if (res == 1) {
216  notice_lang(s_OperServ, u, OPER_AKILL_DELETED_ONE);
217  } else {
218  notice_lang(s_OperServ, u, OPER_AKILL_DELETED_SEVERAL,
219  res);
220  }
221  } else {
222  if ((res = slist_indexof(&akills, mask)) == -1) {
223  notice_lang(s_OperServ, u, OPER_AKILL_NOT_FOUND, mask);
224  return MOD_CONT;
225  }
226 
227  slist_delete(&akills, res);
228  notice_lang(s_OperServ, u, OPER_AKILL_DELETED, mask);
229  }
230 
231  if (readonly)
232  notice_lang(s_OperServ, u, READ_ONLY_MODE);
233 
234  } else if (!stricmp(cmd, "LIST")) {
235  char *mask;
236  int res, sent_header = 0;
237 
238  if (akills.count == 0) {
239  notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY);
240  return MOD_CONT;
241  }
242 
243  mask = strtok(NULL, " ");
244 
245  if (!mask || (isdigit(*mask)
246  && strspn(mask, "1234567890,-") == strlen(mask))) {
247  res =
249  &sent_header);
250  if (res == 0) {
251  notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH);
252  return MOD_CONT;
253  } else {
254  notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill");
255  }
256  } else {
257  int i;
258  char amask[BUFSIZE];
259 
260  for (i = 0; i < akills.count; i++) {
261  snprintf(amask, sizeof(amask), "%s@%s",
262  ((Akill *) akills.list[i])->user,
263  ((Akill *) akills.list[i])->host);
264  if (!stricmp(mask, amask)
265  || match_wild_nocase(mask, amask))
266  akill_list(i + 1, akills.list[i], u, &sent_header);
267  }
268 
269  if (!sent_header)
270  notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH);
271  else {
272  notice_lang(s_OperServ, u, END_OF_ANY_LIST, "Akill");
273  }
274  }
275  } else if (!stricmp(cmd, "VIEW")) {
276  char *mask;
277  int res, sent_header = 0;
278 
279  if (akills.count == 0) {
280  notice_lang(s_OperServ, u, OPER_AKILL_LIST_EMPTY);
281  return MOD_CONT;
282  }
283 
284  mask = strtok(NULL, " ");
285 
286  if (!mask || (isdigit(*mask)
287  && strspn(mask, "1234567890,-") == strlen(mask))) {
288  res =
290  &sent_header);
291  if (res == 0) {
292  notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH);
293  return MOD_CONT;
294  }
295  } else {
296  int i;
297  char amask[BUFSIZE];
298 
299  for (i = 0; i < akills.count; i++) {
300  snprintf(amask, sizeof(amask), "%s@%s",
301  ((Akill *) akills.list[i])->user,
302  ((Akill *) akills.list[i])->host);
303  if (!stricmp(mask, amask)
304  || match_wild_nocase(mask, amask))
305  akill_view(i + 1, akills.list[i], u, &sent_header);
306  }
307 
308  if (!sent_header)
309  notice_lang(s_OperServ, u, OPER_AKILL_NO_MATCH);
310  }
311  } else if (!stricmp(cmd, "CLEAR")) {
312  slist_clear(&akills, 1);
313  notice_lang(s_OperServ, u, OPER_AKILL_CLEAR);
314  } else {
315  syntax_error(s_OperServ, u, "AKILL", OPER_AKILL_SYNTAX);
316  }
317  return MOD_CONT;
318 }
319 
320 static int akill_view(int number, Akill * ak, User * u, int *sent_header)
321 {
322  char mask[BUFSIZE];
323  char timebuf[32], expirebuf[256];
324  struct tm tm;
325 
326  if (!ak)
327  return 0;
328 
329  if (!*sent_header) {
330  notice_lang(s_OperServ, u, OPER_AKILL_VIEW_HEADER);
331  *sent_header = 1;
332  }
333 
334  snprintf(mask, sizeof(mask), "%s@%s", ak->user, ak->host);
335  tm = *localtime(&ak->seton);
336  strftime_lang(timebuf, sizeof(timebuf), u, STRFTIME_SHORT_DATE_FORMAT,
337  &tm);
338  expire_left(u->na, expirebuf, sizeof(expirebuf), ak->expires);
339  notice_lang(s_OperServ, u, OPER_AKILL_VIEW_FORMAT, number, mask,
340  ak->by, timebuf, expirebuf, ak->reason);
341 
342  return 1;
343 }
344 
345 /* Lists an AKILL entry, prefixing it with the header if needed */
346 
347 static int akill_list_callback(SList * slist, int number, void *item,
348  va_list args)
349 {
350  User *u = va_arg(args, User *);
351  int *sent_header = va_arg(args, int *);
352 
353  return akill_list(number, item, u, sent_header);
354 }
355 
356 /* Callback for enumeration purposes */
357 
358 static int akill_view_callback(SList * slist, int number, void *item,
359  va_list args)
360 {
361  User *u = va_arg(args, User *);
362  int *sent_header = va_arg(args, int *);
363 
364  return akill_view(number, item, u, sent_header);
365 }
366 
367 /* Lists an AKILL entry, prefixing it with the header if needed */
368 static int akill_list(int number, Akill * ak, User * u, int *sent_header)
369 {
370  char mask[BUFSIZE];
371 
372  if (!ak)
373  return 0;
374 
375  if (!*sent_header) {
376  notice_lang(s_OperServ, u, OPER_AKILL_LIST_HEADER);
377  *sent_header = 1;
378  }
379 
380  snprintf(mask, sizeof(mask), "%s@%s", ak->user, ak->host);
381  notice_lang(s_OperServ, u, OPER_AKILL_LIST_FORMAT, number, mask,
382  ak->reason);
383 
384  return 1;
385 }
E size_t strspn(const char *s, const char *accept)
Definition: compat.c:106
E int WallOSAkill
Definition: extern.h:454
E int readonly
Definition: extern.h:776
E int match_wild_nocase(const char *pattern, const char *str)
Definition: misc.c:268
static int akill_list_callback(SList *slist, int number, void *item, va_list args)
Definition: os_akill.c:347
char nick[NICKMAX]
Definition: services.h:875
E int snprintf(char *buf, size_t size, const char *fmt,...)
Definition: compat.c:37
E int slist_delete_range(SList *slist, char *range, slist_delcheckcb_t cb,...)
Definition: slist.c:129
char * host
Definition: services.h:1081
E int dotime(const char *s)
Definition: misc.c:364
E int stricmp(const char *s1, const char *s2)
Definition: compat.c:58
E int slist_enum(SList *slist, char *range, slist_enumcb_t cb,...)
Definition: slist.c:203
time_t expires
Definition: services.h:1087
E char * expire_left(NickAlias *na, char *buf, int len, time_t expires)
Definition: misc.c:470
char * reason
Definition: services.h:1084
MDE void moduleAddAuthor(const char *author)
Definition: modules.c:1772
E int add_akill(User *u, char *mask, const char *by, const time_t expires, const char *reason)
Definition: operserv.c:722
static int do_akill(User *u)
Definition: os_akill.c:77
E void syntax_error(char *service, User *u, const char *command, int msgnum)
Definition: language.c:295
E void notice_lang(char *source, User *dest, int message,...)
Definition: send.c:169
MDE void moduleSetType(MODType type)
Definition: modules.c:818
char * user
Definition: services.h:1080
E char * sstrdup(const char *s)
Definition: memory.c:105
E void slist_clear(SList *slist, int free)
Definition: slist.c:70
#define OPERSERV
Definition: modules.h:62
void ** list
Definition: slist.h:21
E char * s_OperServ
Definition: extern.h:289
E int slist_delete(SList *slist, int index)
Definition: slist.c:97
int16 count
Definition: slist.h:23
void AnopeFini(void)
Definition: os_akill.c:52
static int akill_view_callback(SList *slist, int number, void *item, va_list args)
Definition: os_akill.c:358
MDE void moduleAddVersion(const char *version)
Definition: modules.c:1760
Command * c
Definition: ns_recover.c:17
char * by
Definition: services.h:1083
E int slist_indexof(SList *slist, void *item)
Definition: slist.c:317
MDE void moduleSetOperHelp(void(*func)(User *u))
Definition: modules.c:2126
#define MOD_CONT
Definition: modules.h:54
E SList akills
Definition: extern.h:970
int AnopeInit(int argc, char **argv)
Definition: os_akill.c:32
E int AutokillExpiry
Definition: extern.h:439
Definition: modules.h:99
Definition: slist.h:20
MDE Command * createCommand(const char *name, int(*func)(User *u), int(*has_priv)(User *u), int help_all, int help_reg, int help_oper, int help_admin, int help_root)
Definition: modules.c:987
static int akill_view(int number, Akill *ak, User *u, int *sent_header)
Definition: os_akill.c:320
time_t seton
Definition: services.h:1086
E int is_services_oper(User *u)
Definition: operserv.c:606
E int AddAkiller
Definition: extern.h:470
E int strftime_lang(char *buf, int size, User *u, int format, struct tm *tm)
Definition: language.c:240
MDE int moduleAddCommand(CommandHash *cmdTable[], Command *c, int pos)
Definition: modules.c:1082
static void myOperServHelp(User *u)
Definition: os_akill.c:63
#define BUFSIZE
Definition: config.h:47
static int akill_list(int number, Akill *ak, User *u, int *sent_header)
Definition: os_akill.c:368
NickAlias * na
Definition: services.h:892
#define MOD_UNIQUE
Definition: module.h:11
E void anope_cmd_global(char *source, const char *fmt,...)
Definition: ircd.c:506