/*
* powers.c - power manipulation routines
*/
/*
* $Id: powers.c,v 1.11 2000/01/08 21:08:23 cvs Exp $
*/
#include "copyright.h"
#include "autoconf.h"
#include "db.h"
#include "mudconf.h"
#include "externs.h"
#include "command.h"
#include "powers.h"
#include "alloc.h"
#include "match.h"
#ifndef STANDALONE
extern void FDECL(cf_log_notfound, (dbref, char *, const char *, char *));
/*
* ---------------------------------------------------------------------------
* * ph_any: set or clear indicated bit, no security checking
*/
int ph_any(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (fpowers & POWER_EXT) {
if (reset)
s_Powers2(target, Powers2(target) & ~power);
else
s_Powers2(target, Powers2(target) | power);
} else {
if (reset)
s_Powers(target, Powers(target) & ~power);
else
s_Powers(target, Powers(target) | power);
}
return 1;
}
/*
* ---------------------------------------------------------------------------
* * ph_god: only GOD may set or clear the bit
*/
int ph_god(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/*
* ---------------------------------------------------------------------------
* * ph_wiz: only WIZARDS (or GOD) may set or clear the bit
*/
int ph_wiz(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!Wizard(player) & !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/*
* ---------------------------------------------------------------------------
* * ph_wizroy: only WIZARDS, ROYALTY, (or GOD) may set or clear the bit
*/
int ph_wizroy(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!WizRoy(player) & !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/* ---------------------------------------------------------------------------
* ph_restrict_player: Only Wizards can set this on players, but
* ordinary players can set it on other types of objects.
*/
int ph_restrict_player(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (isPlayer(target) && !Wizard(player) && !God(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/* ---------------------------------------------------------------------------
* ph_privileged: You can set this power on a non-player object, if you
* yourself have this power and are a player who owns themselves (i.e.,
* no robots). Only God can set this on a player.
*/
int ph_privileged(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!God(player)) {
if (!isPlayer(player) || (player != Owner(player)))
return 0;
if (isPlayer(target))
return 0;
if (Powers(player) & power)
return (ph_any(target, player, power, fpowers, reset));
else
return 0;
}
return (ph_any(target, player, power, fpowers, reset));
}
/*
* ---------------------------------------------------------------------------
* * ph_inherit: only players may set or clear this bit.
*/
int ph_inherit(target, player, power, fpowers, reset)
dbref target, player;
POWER power;
int fpowers, reset;
{
if (!Inherits(player))
return 0;
return (ph_any(target, player, power, fpowers, reset));
}
/* *INDENT-OFF* */
POWERENT gen_powers[] =
{
{(char *)"quota", POW_CHG_QUOTAS, 0, 0, ph_wiz},
{(char *)"chown_anything", POW_CHOWN_ANY, 0, 0, ph_wiz},
{(char *)"announce", POW_ANNOUNCE, 0, 0, ph_wiz},
{(char *)"boot", POW_BOOT, 0, 0, ph_wiz},
{(char *)"halt", POW_HALT, 0, 0, ph_wiz},
{(char *)"control_all", POW_CONTROL_ALL,0, 0, ph_god},
{(char *)"expanded_who", POW_WIZARD_WHO, 0, 0, ph_wiz},
{(char *)"see_all", POW_EXAM_ALL, 0, 0, ph_wiz},
{(char *)"prog", POW_PROG, 0, 0, ph_wiz},
{(char *)"find_unfindable", POW_FIND_UNFIND,0, 0, ph_wiz},
{(char *)"free_money", POW_FREE_MONEY, 0, 0, ph_wiz},
{(char *)"free_quota", POW_FREE_QUOTA, 0, 0, ph_wiz},
{(char *)"hide", POW_HIDE, 0, 0, ph_wiz},
{(char *)"idle", POW_IDLE, 0, 0, ph_wiz},
{(char *)"search", POW_SEARCH, 0, 0, ph_wiz},
{(char *)"long_fingers", POW_LONGFINGERS,0, 0, ph_wiz},
{(char *)"comm_all", POW_COMM_ALL, 0, 0, ph_wiz},
{(char *)"see_queue", POW_SEE_QUEUE, 0, 0, ph_wiz},
{(char *)"see_hidden", POW_SEE_HIDDEN, 0, 0, ph_wiz},
{(char *)"monitor", POW_MONITOR, 0, 0, ph_wiz},
{(char *)"poll", POW_POLL, 0, 0, ph_wiz},
{(char *)"no_destroy", POW_NO_DESTROY, 0, 0, ph_wiz},
{(char *)"guest", POW_GUEST, 0, 0, ph_god},
{(char *)"stat_any", POW_STAT_ANY, 0, 0, ph_wiz},
{(char *)"steal_money", POW_STEAL, 0, 0, ph_wiz},
{(char *)"tel_anywhere", POW_TEL_ANYWHR, 0, 0, ph_wiz},
{(char *)"tel_anything", POW_TEL_UNRST, 0, 0, ph_wiz},
{(char *)"unkillable", POW_UNKILLABLE, 0, 0, ph_wiz},
{(char *)"pass_locks", POW_PASS_LOCKS, 0, 0, ph_wiz},
{(char *)"builder", POW_BUILDER, POWER_EXT, 0, ph_wiz},
{(char *)"link_variable", POW_LINKVAR, POWER_EXT, 0, ph_wiz},
{(char *)"link_to_anything", POW_LINKTOANY, POWER_EXT, 0, ph_wiz},
{(char *)"open_anywhere", POW_OPENANYLOC, POWER_EXT, 0, ph_wiz},
{(char *)"use_sql", POW_USE_SQL, POWER_EXT, 0, ph_god},
{NULL, 0, POWER_EXT, 0, 0}};
#endif /* STANDALONE */
/* *INDENT-ON* */
#ifndef STANDALONE
/*
* ---------------------------------------------------------------------------
* * init_powertab: initialize power hash tables.
*/
void NDECL(init_powertab)
{
POWERENT *fp;
char *nbuf, *np, *bp;
hashinit(&mudstate.powers_htab, 15 * HASH_FACTOR);
nbuf = alloc_sbuf("init_powertab");
for (fp = gen_powers; fp->powername; fp++) {
for (np = nbuf, bp = (char *)fp->powername; *bp; np++, bp++)
*np = ToLower(*bp);
*np = '\0';
hashadd(nbuf, (int *)fp, &mudstate.powers_htab);
}
free_sbuf(nbuf);
}
/*
* ---------------------------------------------------------------------------
* * display_powers: display available powers.
*/
void display_powertab(player)
dbref player;
{
char *buf, *bp;
POWERENT *fp;
bp = buf = alloc_lbuf("display_powertab");
safe_str((char *)"Powers:", buf, &bp);
for (fp = gen_powers; fp->powername; fp++) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
safe_chr(' ', buf, &bp);
safe_str((char *)fp->powername, buf, &bp);
}
*bp = '\0';
notify(player, buf);
free_lbuf(buf);
}
POWERENT *find_power(thing, powername)
dbref thing;
char *powername;
{
char *cp;
/*
* Make sure the power name is valid
*/
for (cp = powername; *cp; cp++)
*cp = ToLower(*cp);
return (POWERENT *) hashfind(powername, &mudstate.powers_htab);
}
int decode_power(player, powername, pset)
dbref player;
char *powername;
POWERSET *pset;
{
POWERENT *pent;
pset->word1 = 0;
pset->word2 = 0;
pent = (POWERENT *) hashfind(powername, &mudstate.powers_htab);
if (!pent) {
notify(player, tprintf("%s: Power not found.", powername));
return 0;
}
if (pent->powerpower & POWER_EXT)
pset->word2 = pent->powervalue;
else
pset->word1 = pent->powervalue;
return 1;
}
/*
* ---------------------------------------------------------------------------
* * power_set: Set or clear a specified power on an object.
*/
void power_set(target, player, power, key)
dbref target, player;
char *power;
int key;
{
POWERENT *fp;
int negate, result;
/*
* Trim spaces, and handle the negation character
*/
negate = 0;
while (*power && isspace(*power))
power++;
if (*power == '!') {
negate = 1;
power++;
}
while (*power && isspace(*power))
power++;
/*
* Make sure a power name was specified
*/
if (*power == '\0') {
if (negate)
notify(player, "You must specify a power to clear.");
else
notify(player, "You must specify a power to set.");
return;
}
fp = find_power(target, power);
if (fp == NULL) {
notify(player, "I don't understand that power.");
return;
}
/*
* Invoke the power handler, and print feedback
*/
result = fp->handler(target, player, fp->powervalue,
fp->powerpower, negate);
if (!result)
notify(player, NOPERM_MESSAGE);
else if (!(key & SET_QUIET) && !Quiet(player))
notify(player, (negate ? "Cleared." : "Set."));
return;
}
/*
* ---------------------------------------------------------------------------
* * has_power: does object have power visible to player?
*/
int has_power(player, it, powername)
dbref player, it;
char *powername;
{
POWERENT *fp;
POWER fv;
fp = find_power(it, powername);
if (fp == NULL)
return 0;
if (fp->powerpower & POWER_EXT)
fv = Powers2(it);
else
fv = Powers(it);
if (fv & fp->powervalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
return 0;
if ((fp->listperm & CA_GOD) && !God(player))
return 0;
return 1;
}
return 0;
}
/*
* ---------------------------------------------------------------------------
* * power_description: Return an mbuf containing the type and powers on thing.
*/
char *power_description(player, target)
dbref player, target;
{
char *buff, *bp;
POWERENT *fp;
int otype;
POWER fv;
/*
* Allocate the return buffer
*/
otype = Typeof(target);
bp = buff = alloc_mbuf("power_description");
/*
* Store the header strings and object type
*/
safe_mb_str((char *)"Powers:", buff, &bp);
for (fp = gen_powers; fp->powername; fp++) {
if (fp->powerpower & POWER_EXT)
fv = Powers2(target);
else
fv = Powers(target);
if (fv & fp->powervalue) {
if ((fp->listperm & CA_WIZARD) && !Wizard(player))
continue;
if ((fp->listperm & CA_GOD) && !God(player))
continue;
safe_mb_chr(' ', buff, &bp);
safe_mb_str((char *)fp->powername, buff, &bp);
}
}
/*
* Terminate the string, and return the buffer to the caller
*/
*bp = '\0';
return buff;
}
/*
* ---------------------------------------------------------------------------
* * decompile_powers: Produce commands to set powers on target.
*/
void decompile_powers(player, thing, thingname)
dbref player, thing;
char *thingname;
{
POWER f1, f2;
POWERENT *fp;
/*
* Report generic powers
*/
f1 = Powers(thing);
f2 = Powers2(thing);
for (fp = gen_powers; fp->powername; fp++) {
/*
* Skip if we shouldn't decompile this power
*/
if (fp->listperm & CA_NO_DECOMP)
continue;
/*
* Skip if this power is not set
*/
if (fp->powerpower & POWER_EXT) {
if (!(f2 & fp->powervalue))
continue;
} else {
if (!(f1 & fp->powervalue))
continue;
}
/*
* Skip if we can't see this power
*/
if (!check_access(player, fp->listperm))
continue;
/*
* We made it this far, report this power
*/
notify(player, tprintf("@power %s=%s", strip_ansi(thingname), fp->powername));
}
}
/* ---------------------------------------------------------------------------
* cf_power_access: Modify who can set a power. Basically like
* cf_flag_access.
*/
CF_HAND(cf_power_access)
{
char *fstr, *permstr, *tokst;
POWERENT *fp;
fstr = strtok_r(str, " \t=,", &tokst);
permstr = strtok_r(NULL, " \t=,", &tokst);
if (!fstr || !*fstr) {
return -1;
}
if ((fp = find_power(GOD, fstr)) == NULL) {
cf_log_notfound(player, cmd, "No such power", fstr);
return -1;
}
/* Don't change the handlers on special things. */
if ((fp->handler != ph_any) &&
(fp->handler != ph_wizroy) &&
(fp->handler != ph_wiz) &&
(fp->handler != ph_god) &&
(fp->handler != ph_restrict_player) &&
(fp->handler != ph_privileged)) {
STARTLOG(LOG_CONFIGMODS, "CFG", "PERM")
log_text((char *) "Cannot change access for power: ");
log_text((char *) fp->powername);
ENDLOG
return -1;
}
if (!strcmp(permstr, (char *) "any")) {
fp->handler = ph_any;
} else if (!strcmp(permstr, (char *) "royalty")) {
fp->handler = ph_wizroy;
} else if (!strcmp(permstr, (char *) "wizard")) {
fp->handler = ph_wiz;
} else if (!strcmp(permstr, (char *) "god")) {
fp->handler = ph_god;
} else if (!strcmp(permstr, (char *) "restrict_player")) {
fp->handler = ph_restrict_player;
} else if (!strcmp(permstr, (char *) "privileged")) {
fp->handler = ph_privileged;
} else {
cf_log_notfound(player, cmd, "Power access", permstr);
return -1;
}
return 0;
}
#endif /*
* STANDALONE
*/