pennmush/game/
pennmush/game/data/
pennmush/game/log/
pennmush/game/save/
pennmush/game/txt/evt/
pennmush/game/txt/nws/
pennmush/os2/
/* atr_tab.c */

#include "config.h"

#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef I_STDLIB
#include <stdlib.h>
#endif
#include <stdio.h>
#include "conf.h"
#include "externs.h"
#include "atr_tab.h"
#include "htab.h"
#include "privtab.h"
#include "mymalloc.h"
#include "confmagic.h"

typedef struct atr_alias ATRALIAS;

struct atr_alias {
  const char *alias;
  const char *realname;
};

HASHTAB htab_attrib;

PRIV attr_privs[] =
{
  {"no_command", '$', AF_NOPROG, AF_NOPROG},
  {"no_inherit", 'i', AF_PRIVATE, AF_PRIVATE},
  {"private", 'i', AF_PRIVATE, AF_PRIVATE},
  {"no_clone", 'c', AF_NOCOPY, AF_NOCOPY},
  {"wizard", 'w', AF_WIZARD, AF_WIZARD},
  {"visual", 'v', AF_VISUAL, AF_VISUAL},
  {"mortal_dark", 'm', AF_MDARK, AF_MDARK},
  {"hidden", 'm', AF_MDARK, AF_MDARK},
  {"regexp", 'R', AF_REGEXP, AF_REGEXP},
  {NULL, '\0', 0, 0}
};


ATTR *aname_hash_lookup _((const char *name));
void init_aname_hashtab _((void));
extern char *strdup _((const char *));
void do_attribute_access _((dbref player, char *name, char *perms, int retroactive));
void do_attribute_delete _((dbref player, char *name));
void do_attribute_rename _((dbref player, char *old, char *new));
void do_attribute_info _((dbref player, char *name));
void do_list_attribs _((dbref player));


/* this table can be expanded as necessary */

static ATRALIAS atr_alias_tab[] =
{
  {"ACONN", "ACONNECT"},
  {"ACON", "ACONNECT"},
  {"ADEST", "ADESTROY"},
  {"ADESTR", "ADESTROY"},
  {"ADESTRO", "ADESTROY"},
  {"ADESC", "ADESCRIBE"},
  {"ADESCR", "ADESCRIBE"},
  {"ADESCRI", "ADESCRIBE"},
  {"ADISC", "ADISCONNECT"},
  {"ADISCON", "ADISCONNECT"},
  {"ADISCONN", "ADISCONNECT"},
  {"AFAIL", "AFAILURE"},
  {"AIDESC", "AIDESCRIBE"},
  {"AIDESCR", "AIDESCRIBE"},
  {"AIDESCRI", "AIDESCRIBE"},
  {"APAY", "APAYMENT"},
  {"ASUCC", "ASUCCESS"},
  {"DESC", "DESCRIBE"},
  {"DESCR", "DESCRIBE"},
  {"DESCRI", "DESCRIBE"},
  {"FAIL", "FAILURE"},
  {"FILTE", "FILTER"},
  {"FILT", "FILTER"},
  {"FIL", "FILTER"},
  {"IDESC", "IDESCRIBE"},
  {"IDESCR", "IDESCRIBE"},
  {"IDESCRI", "IDESCRIBE"},
  {"INFILTE", "INFILTER"},
  {"INFILT", "INFILTER"},
  {"INFIL", "INFILTER"},
  {"INFI", "INFILTER"},
  {"INF", "INFILTER"},
  {"INPREFI", "INPREFIX"},
  {"INPREF", "INPREFIX"},
  {"INPRE", "INPREFIX"},
  {"INPR", "INPREFIX"},
  {"INP", "INPREFIX"},
#ifdef USE_MAILER
  {"MAILFILTER", "MAILFILTERS"},
  {"MAILFILT", "MAILFILTERS"},
  {"MAILFIL", "MAILFILTERS"},
  {"MAILFI", "MAILFILTERS"},
  {"MAILFOLDER", "MAILFOLDERS"},
  {"MAILFOLD", "MAILFOLDERS"},
  {"MAILFOL", "MAILFOLDERS"},
  {"MAILFO", "MAILFOLDERS"},
  {"MAILSIGNATUR", "MAILSIGNATURE"},
  {"MAILSIGNATU", "MAILSIGNATURE"},
  {"MAILSIGNAT", "MAILSIGNATURE"},
  {"MAILSIGNA", "MAILSIGNATURE"},
  {"MAILSIGN", "MAILSIGNATURE"},
  {"MAILSIG", "MAILSIGNATURE"},
  {"MAILSI", "MAILSIGNATURE"},
#endif
  {"ODESC", "ODESCRIBE"},
  {"ODESCR", "ODESCRIBE"},
  {"ODESCRI", "ODESCRIBE"},
  {"OFAIL", "OFAILURE"},
  {"OIDESC", "OIDESCRIBE"},
  {"OIDESCR", "OIDESCRIBE"},
  {"OIDESCRI", "OIDESCRIBE"},
  {"OPAY", "OPAYMENT"},
  {"OSUCC", "OSUCCESS"},
  {"PAY", "PAYMENT"},
  {"PREFI", "PREFIX"},
  {"PREF", "PREFIX"},
  {"PRE", "PREFIX"},
  {"SUCC", "SUCCESS"},
  {NULL, NULL}
};

/*----------------------------------------------------------------------
 * Hash functions of various sorts
 */


ATTR *
aname_hash_lookup(name)
    const char *name;
{
  /* given an attribute name, look it up in the complete attribute table
   * (real names plus aliases), and return the appropriate real attribute.
   */
  return (ATTR *) hashfind((char *) strupper(name), &htab_attrib);
}

void
init_aname_hashtab()
{
  ATTR *ap;
  ATRALIAS *aliasp;

  hashinit(&htab_attrib, 256);

  /* build the basic hash table */
  for (ap = attr; ap->name; ap++)
    hashadd(ap->name, (void *) ap, &htab_attrib);

  /* now add in aliases */
  for (aliasp = atr_alias_tab; aliasp->alias; aliasp++) {
    if ((ap = aname_hash_lookup(aliasp->realname)) != NULL)
      hashadd(aliasp->alias, (void *) ap, &htab_attrib);
    else
      fprintf(stderr,
	    "ATR INIT: attribute alias %s matches no known attribute.\n",
	      aliasp->alias);
  }
}

/* Add an attribute to the hash table, given its name and permissions */
void
do_attribute_access(player, name, perms, retroactive)
    dbref player;
    char *name;
    char *perms;
    int retroactive;
{
  ATTR *ap;
  int flags = 0;
  int i;

  /* Parse name and perms */
  if (!name || !*name) {
    notify(player, "Which attribute do you mean?");
    return;
  }
  flags = string_to_privs(attr_privs, perms, 0);
  if (!flags) {
    notify(player, "I don't understand those permissions.");
    return;
  }
  upcasestr(name);
  /* Is this attribute already in the table? */
  ap = aname_hash_lookup(name);
  if (ap) {
    /* Already in the table, so we must delete before we add */
    hashdelete(name, &htab_attrib);
  } else {
    /* Create fresh */
    ap = (ATTR *) mush_malloc(sizeof(ATTR), "ATTR");
    if (!ap) {
      notify(player, "Critical memory failure - Alert God!");
      do_log(LT_ERR, 0, 0, "do_attribute_access: unable to malloc ATTR");
      return;
    }
    AL_NAME(ap) = strdup(name);
    AL_STR(ap) = NULL;
  }
  AL_FLAGS(ap) = flags;
  AL_CREATOR(ap) = player;
  hashadd(name, (void *) ap, &htab_attrib);
  /* If we've been given the RETROACTIVE switch, we must set these
   * permissions on every object that has the attribute in question.
   */
  for (i = 0; i < db_top; i++) {
    if ((ap = atr_get_noparent(i, name))) {
      AL_FLAGS(ap) = flags;
      AL_CREATOR(ap) = player;
    }
  }
  notify(player, tprintf("%s -- Attribute permissions now: %s", name,
			 privs_to_string(attr_privs, flags)));
}


void
do_attribute_delete(player, name)
    dbref player;
    char *name;
{
  ATTR *ap;
  if (!name || !*name) {
    notify(player, "Which attribute do you mean?");
    return;
  }
  upcasestr(name);
  /* Is this attribute in the table? */
  ap = aname_hash_lookup(name);
  if (!ap) {
    notify(player, "That attribute isn't in the attribute table");
    return;
  }
  /* Ok, take it out */
  hashdelete(name, &htab_attrib);
  notify(player, tprintf("Removed %s from attribute table.", name));
  return;
}

void
do_attribute_rename(player, old, new)
    dbref player;
    char *old;
    char *new;
{
  ATTR *ap;
  if (!old || !*old || !new || !*new) {
    notify(player, "Which attributes do you mean?");
    return;
  }
  upcasestr(old);
  upcasestr(new);
  /* Is the new name already in use? */
  ap = aname_hash_lookup(new);
  if (ap) {
    notify(player, tprintf("The name %s is already used in the attribute table.", new));
    return;
  }
  /* Is the old name a real attribute? */
  ap = aname_hash_lookup(old);
  if (!ap) {
    notify(player, "That attribute isn't in the attribute table");
    return;
  }
  /* Ok, take it out and put it back under the new name */
  hashdelete(old, &htab_attrib);
  hashadd(new, (void *) ap, &htab_attrib);
  notify(player, tprintf("Renamed %s to %s in attribute table.", old, new));
  return;
}

/* Info on an attribute in the table */
void
do_attribute_info(player, name)
    dbref player;
    char *name;
{
  ATTR *ap;
  if (!name || !*name) {
    notify(player, "Which attribute do you mean?");
    return;
  }
  upcasestr(name);
  /* Is this attribute in the table? */
  ap = aname_hash_lookup(name);
  if (!ap) {
    notify(player, "That attribute isn't in the attribute table");
    return;
  }
  notify(player, tprintf("Attribute: %s", AL_NAME(ap)));
  notify(player, tprintf("    Flags: %s", privs_to_string(attr_privs, AL_FLAGS(ap))));
  notify(player, tprintf("  Creator: #%d", AL_CREATOR(ap)));
  return;
}

void
do_list_attribs(player)
    dbref player;
{
  ATTR *ap;
  char *ptrs[BUFFER_LEN / 2];
  char buff[BUFFER_LEN];
  char *bp;
  int nptrs = 0, i;
  HASHTAB temp;

  hashinit(&temp, 256);
  ap = hash_firstentry(&htab_attrib);
  while (ap) {
    hashadd(ap->name, (void *) ap->name, &temp);
    ap = hash_nextentry(&htab_attrib);
  }
  bp = hash_firstentry(&temp);
  while (bp) {
    ptrs[nptrs++] = (char *) bp;
    bp = hash_nextentry(&temp);
  }
  do_gensort(ptrs, nptrs, 0);
  bp = buff;
  safe_str("Attribs:", buff, &bp);
  for (i = 0; i < nptrs; i++) {
    safe_chr(' ', buff, &bp);
    safe_str(ptrs[i], buff, &bp);
  }
  *bp = '\0';
  notify(player, buff);
  hashfree(&temp);
}