/** * main.C: This file contains the main() routine. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * Copyright © 2005 Atheme Development Group * Rights to this code are documented in doc/pod/license.pod. * * $Id: main.C,v 1.9 2007/09/22 14:27:27 pippijn Exp $ */ #include "atheme.h" #include "confparse.h" #include #include "uplink.h" /* XXX direct use of protocol_handler::notice_global_sts () */ static char const rcsid[] = "$Id: main.C,v 1.9 2007/09/22 14:27:27 pippijn Exp $"; REGISTER_MODULE ("global/main", false, "The Ermyth Team "); static void on_config_ready (void); cmdvec g_cmdtree; E cmdvec os_cmdtree; helpvec g_helptree; E helpvec os_helptree; static void g_cmd_global (sourceinfo_t *si, const int parc, char *parv[]); static void g_cmd_help (sourceinfo_t *si, const int parc, char *parv[]); command_t const g_help = { "HELP", N_("Displays contextual help information."), PRIV_GLOBAL, 1, g_cmd_help }; command_t const g_global = { "GLOBAL", N_("Sends a global notice."), PRIV_GLOBAL, 1, g_cmd_global }; /* HELP [params] */ static void g_cmd_help (sourceinfo_t *si, const int parc, char *parv[]) { char *command = parv[0]; if (!command) { command_help (si, g_cmdtree); command_success_nodata (si, "For more specific help use \2HELP \37command\37\2."); return; } /* take the command through the hash table */ help_display (si, command, g_helptree); } /* GLOBAL |SEND|CLEAR */ static void g_cmd_global (sourceinfo_t *si, const int parc, char *parv[]) { char *message; static list_t globlist; node_t *n, *tn; char *params = parv[0]; static char *sender = NULL; bool isfirst; char buf[BUFSIZE]; if (!params) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "GLOBAL"); command_fail (si, fault::needmoreparams, _("Syntax: GLOBAL |SEND|CLEAR")); return; } if (!strcasecmp ("CLEAR", params)) { if (!globlist.count) { command_fail (si, fault::nochange, _("No message to clear.")); return; } /* destroy the list we made */ LIST_FOREACH_SAFE (n, tn, globlist.head) { message = static_cast (n->data); node_del (n, &globlist); node_free (n); sfree (message); } sfree (sender); sender = NULL; command_success_nodata (si, "The pending message has been deleted."); return; } if (!strcasecmp ("SEND", params)) { if (!globlist.count) { command_fail (si, fault::nosuch_target, _("No message to send.")); return; } isfirst = true; LIST_FOREACH (n, globlist.head) { message = static_cast (n->data); snprintf (buf, sizeof buf, "[Network Notice] %s%s%s", isfirst ? si->su->nick : "", isfirst ? " - " : "", message); /* Cannot use si->service->me here, global notices * should come from global even if /os global was * used. */ phandler->notice_global_sts (globsvs.me->me, "*", buf); isfirst = false; /* log everything */ logcommand (si, CMDLOG_ADMIN, "GLOBAL %s", message); } logcommand (si, CMDLOG_ADMIN, "GLOBAL (%d lines sent)", LIST_LENGTH (&globlist)); /* destroy the list we made */ LIST_FOREACH_SAFE (n, tn, globlist.head) { message = static_cast (n->data); node_del (n, &globlist); node_free (n); sfree (message); } sfree (sender); sender = NULL; snoop ("GLOBAL: \2%s\2", get_oper_name (si)); command_success_nodata (si, "The global notice has been sent."); return; } if (!sender) sender = sstrdup (si->su->nick); if (irccasecmp (sender, si->su->nick)) { command_fail (si, fault::noprivs, _("There is already a GLOBAL in progress by \2%s\2."), sender); return; } message = sstrdup (params); n = node_create (); node_add (message, n, &globlist); command_success_nodata (si, "Stored text to be sent as line %d. Use \2GLOBAL SEND\2 " "to send message, \2GLOBAL CLEAR\2 to delete the pending message, " "or \2GLOBAL\2 to store additional lines.", globlist.count); } /* main services client routine */ static void global (sourceinfo_t *si, int parc, char *parv[]) { char orig[BUFSIZE]; char *cmd; char *text; /* this should never happen */ if (parv[0][0] == '&') { slog (LG_ERROR, "services(): got parv with local channel: %s", parv[0]); return; } /* make a copy of the original for debugging */ strlcpy (orig, parv[parc - 1], BUFSIZE); /* lets go through this to get the command */ cmd = strtok (parv[parc - 1], " "); text = strtok (NULL, ""); if (!cmd) return; if (*cmd == '\001') { handle_ctcp_common (si, cmd, text); return; } command_exec_split (si->service, si, cmd, text, g_cmdtree); } static void on_config_ready (void) { if (globsvs.me) del_service (globsvs.me); globsvs.me = add_service (globsvs.nick, globsvs.user, globsvs.host, globsvs.real, global, g_cmdtree); globsvs.disp = globsvs.me->disp; } bool _modinit (module *m) { ConfTable::callback.ready.attach (on_config_ready); if (!cold_start) { globsvs.me = add_service (globsvs.nick, globsvs.user, globsvs.host, globsvs.real, global, g_cmdtree); globsvs.disp = globsvs.me->disp; } g_cmdtree << g_global; os_cmdtree << g_global; help_addentry (os_helptree, "GLOBAL", "help/global/global", NULL); help_addentry (g_helptree, "HELP", "help/global/help", NULL); help_addentry (g_helptree, "GLOBAL", "help/global/global", NULL); g_cmdtree << g_help; return true; } void _moddeinit () { if (globsvs.me) { del_service (globsvs.me); globsvs.me = NULL; } g_cmdtree >> g_global; os_cmdtree >> g_global; help_delentry (os_helptree, "GLOBAL"); help_delentry (g_helptree, "GLOBAL"); help_delentry (g_helptree, "HELP"); g_cmdtree >> g_help; ConfTable::callback.ready.detach (on_config_ready); }