static void os_cmd_modunload(sourceinfo_t *si, int parc, char *parv[]) { char *module; int i; module_t *m; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "MODUNLOAD"); command_fail(si, fault_needmoreparams, _("Syntax: MODUNLOAD <module...>")); return; } i = 0; while (i < parc) { module = parv[i++]; m = module_find_published(module); if (!m) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not loaded; it cannot be unloaded."), module); continue; } if (m->can_unload != MODULE_UNLOAD_CAPABILITY_OK) { slog(LG_INFO, "\2%s\2 tried to unload a permanent module", get_oper_name(si)); command_fail(si, fault_noprivs, _("\2%s\2 is a permanent module; it cannot be unloaded."), module); continue; } if (!strcmp(m->name, "operserv/main") || !strcmp(m->name, "operserv/modload") || !strcmp(m->name, "operserv/modunload")) { command_fail(si, fault_noprivs, _("Refusing to unload \2%s\2."), module); continue; } logcommand(si, CMDLOG_ADMIN, "MODUNLOAD: \2%s\2", module); module_unload(m, MODULE_UNLOAD_INTENT_PERM); command_success_nodata(si, _("Module \2%s\2 unloaded."), module); } }
static void os_cmd_modinspect(sourceinfo_t *si, int parc, char *parv[]) { char *mname = parv[0]; module_t *m; if (!mname) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "MODINSPECT"); command_fail(si, fault_needmoreparams, _("Syntax: MODINSPECT <module>")); return; } logcommand(si, CMDLOG_GET, "MODINSPECT %s", mname); m = module_find_published(mname); if (!m) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not loaded."), mname); return; } /* Is there a header? */ if (!m->header) { command_fail(si, fault_unimplemented, _("\2%s\2 cannot be inspected."), mname); return; } command_success_nodata(si, _("Information on \2%s\2:"), mname); command_success_nodata(si, _("Name : %s"), m->header->name); command_success_nodata(si, _("Address : %p"), m->address); command_success_nodata(si, _("Entry point: %p"), m->header->modinit); command_success_nodata(si, _("Exit point : %p"), m->header->deinit); command_success_nodata(si, _("Version : %s"), m->header->version); command_success_nodata(si, _("Vendor : %s"), m->header->vendor); if (m->header->norestart) command_success_nodata(si, _("Permanent : Yes")); else command_success_nodata(si, _("Permanent : No")); command_success_nodata(si, _("*** \2End of Info\2 ***")); }
static bool evaluate_condition(sourceinfo_t *si, const char *s) { char word[80]; char *p, *q; while (*s == ' ' || *s == '\t') s++; if (*s == '!') return !evaluate_condition(si, s + 1); mowgli_strlcpy(word, s, sizeof word); p = strchr(word, ' '); if (p != NULL) { *p++ = '\0'; while (*p == ' ' || *p == '\t') p++; } if (!strcmp(word, "halfops")) return ircd->uses_halfops; else if (!strcmp(word, "owner")) return ircd->uses_owner; else if (!strcmp(word, "protect")) return ircd->uses_protect; else if (!strcmp(word, "anyprivs")) return has_any_privs(si); else if (!strcmp(word, "priv")) { if (p != NULL && (q = strchr(p, ' ')) != NULL) *q = '\0'; return has_priv(si, p); } else if (!strcmp(word, "module")) { if (p != NULL && (q = strchr(p, ' ')) != NULL) *q = '\0'; return module_find_published(p) != NULL; } else if (!strcmp(word, "auth")) return me.auth != AUTH_NONE; else return false; }
static void os_cmd_modinspect(sourceinfo_t *si, int parc, char *parv[]) { char *mname = parv[0]; module_t *m; if (!mname) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "MODINSPECT"); command_fail(si, fault_needmoreparams, _("Syntax: MODINSPECT <module>")); return; } logcommand(si, CMDLOG_GET, "MODINSPECT: \2%s\2", mname); m = module_find_published(mname); if (!m) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not loaded."), mname); return; } /* Is there a header? */ if (!m->header) { command_fail(si, fault_unimplemented, _("\2%s\2 cannot be inspected."), mname); return; } command_success_nodata(si, _("Information on \2%s\2:"), mname); command_success_nodata(si, _("Name : %s"), m->name); command_success_nodata(si, _("Address : %p"), m->address); command_success_nodata(si, _("Entry point: %p"), m->header->modinit); command_success_nodata(si, _("Exit point : %p"), m->header->deinit); command_success_nodata(si, _("SDK Serial : %s"), m->header->serial); command_success_nodata(si, _("Version : %s"), m->header->version); command_success_nodata(si, _("Vendor : %s"), m->header->vendor); command_success_nodata(si, _("Can unload : %s"), m->can_unload == MODULE_UNLOAD_CAPABILITY_OK ? "Yes" : ( m->can_unload == MODULE_UNLOAD_CAPABILITY_NEVER ? "No" : "Reload only")); command_success_nodata(si, _("*** \2End of Info\2 ***")); }
static void os_cmd_modload(sourceinfo_t *si, int parc, char *parv[]) { char *module; module_t *m; int i; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "MODLOAD"); command_fail(si, fault_needmoreparams, _("Syntax: MODLOAD <module...>")); return; } i = 0; while (i < parc) { module = parv[i++]; if (module_find_published(module)) { command_fail(si, fault_nochange, _("\2%s\2 is already loaded."), module); continue; } logcommand(si, CMDLOG_ADMIN, "MODLOAD: \2%s\2", module); m = module_load(module); if (m != NULL) command_success_nodata(si, _("Module \2%s\2 loaded."), module); else command_fail(si, fault_nosuch_target, _("Module \2%s\2 failed to load."), module); } if (conf_need_rehash) { logcommand(si, CMDLOG_ADMIN, "REHASH (MODLOAD)"); wallops("Rehashing \2%s\2 to complete module load by request of \2%s\2.", config_file, get_oper_name(si)); if (!conf_rehash()) command_fail(si, fault_nosuch_target, _("REHASH of \2%s\2 failed. Please correct any errors in the file and try again."), config_file); } }
static void cs_cmd_set_guard(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET GUARD"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { if (MC_GUARD & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "GUARD", mc->name); return; } if (metadata_find(mc, "private:botserv:bot-assigned") && module_find_published("botserv/main")) { command_fail(si, fault_noprivs, _("Channel \2%s\2 already has a BotServ bot assigned to it. You need to unassign it first."), mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GUARD:ON: \2%s\2", mc->name); mc->flags |= MC_GUARD; if (!(mc->flags & MC_INHABIT)) join(mc->name, chansvs.nick); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "GUARD", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_GUARD & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "GUARD", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:GUARD:OFF: \2%s\2", mc->name); mc->flags &= ~MC_GUARD; if (mc->chan != NULL && !(mc->flags & MC_INHABIT) && !(mc->chan->flags & CHAN_LOG)) part(mc->name, chansvs.nick); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "GUARD", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "GUARD"); return; } }
static void ns_cmd_fungroup(sourceinfo_t *si, int parc, char *parv[]) { mynick_t *mn, *mn2 = NULL; myuser_t *mu; hook_user_req_t hdata; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FUNGROUP"); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> [newaccountname]")); return; } mn = mynick_find(parv[0]); if (mn == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[0]); return; } mu = mn->owner; if (!irccasecmp(mn->nick, entity(mu)->name)) { if (MOWGLI_LIST_LENGTH(&mu->nicks) <= 1 || !module_find_published("nickserv/set_accountname")) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is an account name; you may not remove it."), mn->nick); return; } if (is_conf_soper(mu)) { command_fail(si, fault_noprivs, _("You may not modify \2%s\2's account name because their operclass is defined in the configuration file."), entity(mu)->name); return; } if (parc < 2) { command_fail(si, fault_needmoreparams, _("Please specify a new account name for \2%s\2."), entity(mu)->name); command_fail(si, fault_needmoreparams, _("Syntax: FUNGROUP <nickname> <newaccountname>")); return; } mn2 = mynick_find(parv[1]); if (mn2 == NULL) { command_fail(si, fault_nosuch_target, _("Nick \2%s\2 is not registered."), parv[1]); return; } if (mn2 == mn) { command_fail(si, fault_noprivs, _("The new account name must be different from the nick to be ungrouped.")); return; } if (mn2->owner != mu) { command_fail(si, fault_noprivs, _("Nick \2%s\2 is not registered to \2%s\2."), mn2->nick, entity(mu)->name); return; } } else if (parc > 1) { command_fail(si, fault_badparams, _("Nick \2%s\2 is not an account name so no new account name is needed."), mn->nick); return; } if (mn2 != NULL) { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2 (new account name: \2%s\2)", mn->nick, entity(mu)->name, mn2->nick); wallops("%s dropped the nick \2%s\2 from %s, changing account name to \2%s\2", get_oper_name(si), mn->nick, entity(mu)->name, mn2->nick); myuser_rename(mu, mn2->nick); } else { logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FUNGROUP: \2%s\2 from \2%s\2", mn->nick, entity(mu)->name); wallops("%s dropped the nick \2%s\2 from %s", get_oper_name(si), mn->nick, entity(mu)->name); } hdata.si = si; hdata.mu = mu; hdata.mn = mn; hook_call_nick_ungroup(&hdata); holdnick_sts(si->service->me, 0, mn->nick, NULL); if (mn2 != NULL) command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2, name changed to \2%s\2."), mn->nick, entity(mu)->name, mn2->nick); else command_success_nodata(si, _("Nick \2%s\2 has been removed from account \2%s\2."), mn->nick, entity(mu)->name); object_unref(mn); }
/* * Implementation functions: load or unload a perl script. */ static module_t *do_script_load(const char *filename) { /* Remember, this must now be re-entrant. The use of the static * perl_error buffer is still OK, as it's only used immediately after * setting, without control passing from this function. */ perl_script_module_t *m = mowgli_heap_alloc(perl_script_module_heap); mowgli_strlcpy(m->filename, filename, sizeof(m->filename)); snprintf(perl_error, sizeof(perl_error), "Unknown error attempting to load perl script %s", filename); dSP; ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(newRV_noinc((SV*)get_cv("Atheme::Init::load_script", 0))); XPUSHs(sv_2mortal(newSVpv(filename, 0))); PUTBACK; int perl_return_count = call_pv("Atheme::Init::call_wrapper", G_EVAL | G_SCALAR); SPAGAIN; if (SvTRUE(ERRSV)) { mowgli_strlcpy(perl_error, SvPV_nolen(ERRSV), sizeof(perl_error)); goto fail; } if (1 != perl_return_count) { snprintf(perl_error, sizeof(perl_error), "Script load didn't return a package name"); goto fail; } /* load_script should have returned the package name that was just * loaded... */ const char *packagename = POPp; char info_varname[BUFSIZE]; snprintf(info_varname, BUFSIZE, "%s::Info", packagename); /* ... so use that name to grab the script information hash... */ HV *info_hash = get_hv(info_varname, 0); if (!info_hash) { snprintf(perl_error, sizeof(perl_error), "Couldn't get package info hash %s", info_varname); goto fail; } /* ..., extract the canonical name... */ SV **name_var = hv_fetch(info_hash, "name", 4, 0); if (!name_var) { snprintf(perl_error, sizeof(perl_error), "Couldn't find canonical name in package info hash"); goto fail; } mowgli_strlcpy(m->mod.name, SvPV_nolen(*name_var), sizeof(m->mod.name)); /* ... and dependency list. */ SV **deplist_var = hv_fetch(info_hash, "depends", 7, 0); /* Not declaring this is legal... */ if (deplist_var) { /* ... but having it as anything but an arrayref isn't. */ if (!SvROK(*deplist_var) || SvTYPE(SvRV(*deplist_var)) != SVt_PVAV) { snprintf(perl_error, sizeof(perl_error), "$Info::depends must be an array reference"); goto fail; } AV *deplist = (AV*)SvRV(*deplist_var); I32 len = av_len(deplist); /* av_len returns max index, not number of items */ for (I32 i = 0; i <= len; ++i) { SV **item = av_fetch(deplist, i, 0); if (!item) continue; const char *dep_name = SvPV_nolen(*item); if (!module_request(dep_name)) { snprintf(perl_error, sizeof(perl_error), "Dependent module %s failed to load", dep_name); goto fail; } module_t *dep_mod = module_find_published(dep_name); mowgli_node_add(dep_mod, mowgli_node_create(), &m->mod.deplist); mowgli_node_add(m, mowgli_node_create(), &dep_mod->dephost); } } FREETMPS; LEAVE; invalidate_object_references(); /* Now that everything's loaded, do the module housekeeping stuff. */ m->mod.unload_handler = perl_script_module_unload_handler; /* Can't do much better than the address of the module_t here */ m->mod.address = m; m->mod.can_unload = MODULE_UNLOAD_CAPABILITY_OK; return (module_t*)m; fail: slog(LG_ERROR, "Failed to load Perl script %s: %s", filename, perl_error); if (info_hash) SvREFCNT_dec((SV*)info_hash); do_script_unload(filename); mowgli_heap_free(perl_script_module_heap, m); POPs; FREETMPS; LEAVE; invalidate_object_references(); return NULL; }