1 /* OperServ core functions
2  *
3  * (C) 2003-2020 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 #include "module.h"
13 
14 class CommandOSModLoad : public Command
15 {
16  public:
CommandOSModLoad(Module * creator)17 	CommandOSModLoad(Module *creator) : Command(creator, "operserv/modload", 1, 1)
18 	{
19 		this->SetDesc(_("Load a module"));
20 		this->SetSyntax(_("\037modname\037"));
21 	}
22 
Execute(CommandSource & source,const std::vector<Anope::string> & params)23 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
24 	{
25 		const Anope::string &mname = params[0];
26 
27 		ModuleReturn status = ModuleManager::LoadModule(mname, source.GetUser());
28 		if (status == MOD_ERR_OK)
29 		{
30 			Log(LOG_ADMIN, source, this) << "to load module " << mname;
31 			source.Reply(_("Module \002%s\002 loaded."), mname.c_str());
32 		}
33 		else if (status == MOD_ERR_EXISTS)
34 			source.Reply(_("Module \002%s\002 is already loaded."), mname.c_str());
35 		else
36 			source.Reply(_("Unable to load module \002%s\002."), mname.c_str());
37 
38 		return;
39 	}
40 
OnHelp(CommandSource & source,const Anope::string & subcommand)41 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
42 	{
43 		this->SendSyntax(source);
44 		source.Reply(" ");
45 		source.Reply(_("This command loads the module named \037modname\037 from the modules\n"
46 				"directory."));
47 		return true;
48 	}
49 };
50 
51 class CommandOSModReLoad : public Command
52 {
53  public:
CommandOSModReLoad(Module * creator)54 	CommandOSModReLoad(Module *creator) : Command(creator, "operserv/modreload", 1, 1)
55 	{
56 		this->SetDesc(_("Reload a module"));
57 		this->SetSyntax(_("\037modname\037"));
58 	}
59 
Execute(CommandSource & source,const std::vector<Anope::string> & params)60 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
61 	{
62 		const Anope::string &mname = params[0];
63 
64 		Module *m = ModuleManager::FindModule(mname);
65 		if (!m)
66 		{
67 			source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str());
68 			return;
69 		}
70 
71 		if (!m->handle || m->GetPermanent())
72 		{
73 			source.Reply(_("Unable to remove module \002%s\002."), m->name.c_str());
74 			return;
75 		}
76 
77 		Module *protocol = ModuleManager::FindFirstOf(PROTOCOL);
78 		if (m->type == PROTOCOL && m != protocol)
79 		{
80 			source.Reply(_("You can not reload this module directly, instead reload %s."), protocol ? protocol->name.c_str() : "(unknown)");
81 			return;
82 		}
83 
84 		/* Unrecoverable */
85 		bool fatal = m->type == PROTOCOL;
86 		ModuleReturn status = ModuleManager::UnloadModule(m, source.GetUser());
87 
88 		if (status != MOD_ERR_OK)
89 		{
90 			source.Reply(_("Unable to remove module \002%s\002."), mname.c_str());
91 			return;
92 		}
93 
94 		status = ModuleManager::LoadModule(mname, source.GetUser());
95 		if (status == MOD_ERR_OK)
96 		{
97 			Log(LOG_ADMIN, source, this) << "to reload module " << mname;
98 			source.Reply(_("Module \002%s\002 reloaded."), mname.c_str());
99 		}
100 		else
101 		{
102 			if (fatal)
103 			{
104 				Anope::QuitReason = "Unable to reload module " + mname;
105 				Anope::Quitting = true;
106 			}
107 			else
108 				source.Reply(_("Unable to load module \002%s\002."), mname.c_str());
109 		}
110 
111 		return;
112 	}
113 
OnHelp(CommandSource & source,const Anope::string & subcommand)114 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
115 	{
116 		this->SendSyntax(source);
117 		source.Reply(" ");
118 		source.Reply(_("This command reloads the module named \037modname\037."));
119 		return true;
120 	}
121 };
122 
123 class CommandOSModUnLoad : public Command
124 {
125  public:
CommandOSModUnLoad(Module * creator)126 	CommandOSModUnLoad(Module *creator) : Command(creator, "operserv/modunload", 1, 1)
127 	{
128 		this->SetDesc(_("Un-Load a module"));
129 		this->SetSyntax(_("\037modname\037"));
130 	}
131 
Execute(CommandSource & source,const std::vector<Anope::string> & params)132 	void Execute(CommandSource &source, const std::vector<Anope::string> &params) anope_override
133 	{
134 		const Anope::string &mname = params[0];
135 
136 		Module *m = ModuleManager::FindModule(mname);
137 		if (!m)
138 		{
139 			source.Reply(_("Module \002%s\002 isn't loaded."), mname.c_str());
140 			return;
141 		}
142 
143 		if (!m->handle || m->GetPermanent() || m->type == PROTOCOL)
144 		{
145 			source.Reply(_("Unable to remove module \002%s\002."), m->name.c_str());
146 			return;
147 		}
148 
149 		Log(this->owner) << "Trying to unload module [" << mname << "]";
150 
151 		ModuleReturn status = ModuleManager::UnloadModule(m, source.GetUser());
152 
153 		if (status == MOD_ERR_OK)
154 		{
155 			Log(LOG_ADMIN, source, this) << "to unload module " << mname;
156 			source.Reply(_("Module \002%s\002 unloaded."), mname.c_str());
157 		}
158 		else
159 			source.Reply(_("Unable to remove module \002%s\002."), mname.c_str());
160 
161 		return;
162 	}
163 
OnHelp(CommandSource & source,const Anope::string & subcommand)164 	bool OnHelp(CommandSource &source, const Anope::string &subcommand) anope_override
165 	{
166 		this->SendSyntax(source);
167 		source.Reply(" ");
168 		source.Reply(_("This command unloads the module named \037modname\037."));
169 		return true;
170 	}
171 };
172 
173 class OSModule : public Module
174 {
175 	CommandOSModLoad commandosmodload;
176 	CommandOSModReLoad commandosmodreload;
177 	CommandOSModUnLoad commandosmodunload;
178 
179  public:
OSModule(const Anope::string & modname,const Anope::string & creator)180 	OSModule(const Anope::string &modname, const Anope::string &creator) : Module(modname, creator, VENDOR),
181 		commandosmodload(this), commandosmodreload(this), commandosmodunload(this)
182 	{
183 		this->SetPermanent(true);
184 
185 	}
186 };
187 
188 MODULE_INIT(OSModule)
189