#include "os.h" #include "config.h" #include "db.h" #include "externs.h" #include "interface.h" #include "match.h" #include "attrib.h" #include "oldattrib.h" #ifdef MEM_CHECK #include "mem_check.h" #endif /* attribute list */ ATTR attr[] = { {(char *) "AAHEAR", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ACLONE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ACONNECT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ADEATH", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ADESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ADISCONNECT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ADROP", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AEFAIL", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AENTER", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AFAILURE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AHEAR", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ALEAVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AMHEAR", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AMOVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "APAYMENT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ASUCCESS", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AUSE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "AWAY", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "CHARGES", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "CLASS", AF_NOPROG, NULL, 0}, {(char *) "COST", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "DEATH", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "DESCRIBE", AF_NOPROG, NULL, 0}, {(char *) "DOES", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "DROP", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "EALIAS", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "EFAIL", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ENTER", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "FAILURE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "HAVEN", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "IDESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "IDLE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "LALIAS", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "LAST", AF_WIZARD | AF_LOCKED, NULL, 0}, {(char *) "LASTSITE", AF_LOCKED | AF_ODARK, NULL, 0}, {(char *) "LEAVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "LISTEN", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "MOVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ODEATH", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ODESCRIBE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "ODROP", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OEFAIL", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OENTER", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OFAILURE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OLEAVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OMOVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OPAYMENT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OSUCCESS", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OUSE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OXENTER", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "OXLEAVE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "PAYMENT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "QUEUE", AF_ODARK | AF_WIZARD, NULL, 0}, {(char *) "RACE", AF_NOPROG | AF_WIZARD, NULL, 0}, {(char *) "RQUOTA", AF_DARK | AF_WIZARD, NULL, 0}, {(char *) "RUNOUT", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "SEX", AF_NOPROG, NULL, 0}, {(char *) "STARTUP", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "SUCCESS", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "USE", AF_ODARK | AF_NOPROG, NULL, 0}, {(char *) "VA", AF_ODARK, NULL, 0}, {(char *) "VB", AF_ODARK, NULL, 0}, {(char *) "VC", AF_ODARK, NULL, 0}, {(char *) "VD", AF_ODARK, NULL, 0}, {(char *) "VE", AF_ODARK, NULL, 0}, {(char *) "VF", AF_ODARK, NULL, 0}, {(char *) "VG", AF_ODARK, NULL, 0}, {(char *) "VH", AF_ODARK, NULL, 0}, {(char *) "VI", AF_ODARK, NULL, 0}, {(char *) "VJ", AF_ODARK, NULL, 0}, {(char *) "VK", AF_ODARK, NULL, 0}, {(char *) "VL", AF_ODARK, NULL, 0}, {(char *) "VM", AF_ODARK, NULL, 0}, {(char *) "VN", AF_ODARK, NULL, 0}, {(char *) "VO", AF_ODARK, NULL, 0}, {(char *) "VP", AF_ODARK, NULL, 0}, {(char *) "VQ", AF_ODARK, NULL, 0}, {(char *) "VR", AF_ODARK, NULL, 0}, {(char *) "VS", AF_ODARK, NULL, 0}, {(char *) "VT", AF_ODARK, NULL, 0}, {(char *) "VU", AF_ODARK, NULL, 0}, {(char *) "VV", AF_ODARK, NULL, 0}, {(char *) "VW", AF_ODARK, NULL, 0}, {(char *) "VX", AF_ODARK, NULL, 0}, {(char *) "VY", AF_ODARK, NULL, 0}, {(char *) "VZ", AF_ODARK, NULL, 0}, {(char *) "WA", AF_ODARK, NULL, 0}, {(char *) "WB", AF_ODARK, NULL, 0}, {(char *) "WC", AF_ODARK, NULL, 0}, {(char *) "WD", AF_ODARK, NULL, 0}, {(char *) "WE", AF_ODARK, NULL, 0}, {(char *) "WF", AF_ODARK, NULL, 0}, {(char *) "WG", AF_ODARK, NULL, 0}, {(char *) "WH", AF_ODARK, NULL, 0}, {(char *) "WI", AF_ODARK, NULL, 0}, {(char *) "WJ", AF_ODARK, NULL, 0}, {(char *) "WK", AF_ODARK, NULL, 0}, {(char *) "WL", AF_ODARK, NULL, 0}, {(char *) "WM", AF_ODARK, NULL, 0}, {(char *) "WN", AF_ODARK, NULL, 0}, {(char *) "WO", AF_ODARK, NULL, 0}, {(char *) "WP", AF_ODARK, NULL, 0}, {(char *) "WQ", AF_ODARK, NULL, 0}, {(char *) "WR", AF_ODARK, NULL, 0}, {(char *) "WS", AF_ODARK, NULL, 0}, {(char *) "WT", AF_ODARK, NULL, 0}, {(char *) "WU", AF_ODARK, NULL, 0}, {(char *) "WV", AF_ODARK, NULL, 0}, {(char *) "WW", AF_ODARK, NULL, 0}, {(char *) "WX", AF_ODARK, NULL, 0}, {(char *) "WY", AF_ODARK, NULL, 0}, {(char *) "WZ", AF_ODARK, NULL, 0}, {(char *) "XA", AF_ODARK, NULL, 0}, {(char *) "XB", AF_ODARK, NULL, 0}, {(char *) "XC", AF_ODARK, NULL, 0}, {(char *) "XD", AF_ODARK, NULL, 0}, {(char *) "XE", AF_ODARK, NULL, 0}, {(char *) "XF", AF_ODARK, NULL, 0}, {(char *) "XG", AF_ODARK, NULL, 0}, {(char *) "XH", AF_ODARK, NULL, 0}, {(char *) "XI", AF_ODARK, NULL, 0}, {(char *) "XJ", AF_ODARK, NULL, 0}, {(char *) "XK", AF_ODARK, NULL, 0}, {(char *) "XL", AF_ODARK, NULL, 0}, {(char *) "XM", AF_ODARK, NULL, 0}, {(char *) "XN", AF_ODARK, NULL, 0}, {(char *) "XO", AF_ODARK, NULL, 0}, {(char *) "XP", AF_ODARK, NULL, 0}, {(char *) "XQ", AF_ODARK, NULL, 0}, {(char *) "XR", AF_ODARK, NULL, 0}, {(char *) "XS", AF_ODARK, NULL, 0}, {(char *) "XT", AF_ODARK, NULL, 0}, {(char *) "XU", AF_ODARK, NULL, 0}, {(char *) "XV", AF_ODARK, NULL, 0}, {(char *) "XW", AF_ODARK, NULL, 0}, {(char *) "XX", AF_ODARK, NULL, 0}, {(char *) "XY", AF_ODARK, NULL, 0}, {(char *) "XZ", AF_ODARK, NULL, 0}, {(char *) "XYXXY", AF_DARK | AF_NOPROG | AF_LOCKED | AF_WIZARD, NULL, 0}, {NULL, 0, NULL, 0} }; static char *clean_atr_name (char *s) { static char buf[BUFFER_LEN]; char *q = buf; char *a; if (!*s || !s) { sprintf (buf, "NULL"); return buf; } if (!string_compare ("KILL", s)) { sprintf (buf, "DEATH"); return buf; } if (!string_compare ("KILL", s + 1) && (*s == 'o' || *s == 'O' || *s == 'a' || *s == 'A')) { sprintf (buf, "%c%s", *s, s + 1); return buf; } for (a = s; *a; a++) if (isprint ((int)*a) && !isspace ((int)*a)) *q++ = *a; *q = '\0'; return buf; } ATTR *atr_str (char *s) { ATTR *result; ATTR *a = attr; int done = 0; char *q; result = (ATTR *) malloc (sizeof (ATTR)); q = clean_atr_name (s); result->name = (char *) malloc (strlen (q) + 1); #ifdef MEM_CHECK add_check ("attribute"); add_check ("attribute_name"); #endif strcpy (result->name, strupper (q)); result->flags = AF_ODARK; while (a->name && !done) { if (!string_compare (result->name, a->name)) { result->flags = a->flags; done++; } a++; } return result; } struct boolatr *alloc_atr (char *name, char *s) { struct boolatr *a; const char *p; a = (struct boolatr *) malloc (sizeof (struct boolatr)); a->name = (char *) malloc (strlen (name) + 1); strcpy (a->name, name); p = compress (s); a->text = (char *) malloc (strlen (p) + 1); strcpy (a->text, p); #ifdef MEM_CHECK add_check ("bool_atr"); add_check ("bool_atr_name"); add_check ("bool_atr_val"); #endif return a; } void atr_clr (dbref thing, char *atr) { ALIST *ptr = db[thing].list; while (ptr) { if (!string_compare (atr, AL_NAME (ptr))) { AL_DISPOSE (ptr); return; } ptr = AL_NEXT (ptr); } } ALIST *AL_MAKE (char *type, ALIST * next, char *string, dbref owner, dbref flags) { ALIST *ptr; const char *p; ptr = (ALIST *) malloc (sizeof (ALIST)); AL_ATTR (ptr) = atr_str (type); AL_CREATOR (ptr) = owner; p = compress (string); AL_STR (ptr) = (char *) malloc (strlen (p) + 1); #ifdef MEM_CHECK add_check ("ALIST"); add_check ("attribute_value"); #endif strcpy (AL_STR (ptr), p); if (flags != NOTHING) AL_FLAGS (ptr) |= flags; AL_NEXT (ptr) = next; return ptr; } void atr_new_add (dbref thing, char *atr, char *s, dbref player, dbref flags) { s = (char *) compress (s); db[thing].list = AL_MAKE (atr, db[thing].list, s, player, flags); } int atr_add (dbref thing, char *atr, char *s, dbref player, dbref flags) { ALIST *ptr; dbref privs; if (thing == 0) { privs = GOD; /* should only be hit by first couple objects */ db[player].owner = GOD; } else privs = db[player].owner; if (!s) s = (char *) ""; for (ptr = db[thing].list; (ptr && string_compare (atr, AL_NAME (ptr))); ptr = AL_NEXT (ptr)); if (!*s) { if (ptr) if (!Wizard (privs) && ((AL_FLAGS (ptr) & AF_WIZARD) || ((privs != db[AL_CREATOR (ptr)].owner) && (AL_FLAGS (ptr) & AF_LOCKED)))) { return -1; } else { AL_DISPOSE (ptr); return 1; } else return 0; } s = (char *) compress (s); if (!ptr) { db[thing].list = AL_MAKE (atr, db[thing].list, s, privs, flags); return 1; } else { if (!Wizard (privs) && ((AL_FLAGS (ptr) & AF_WIZARD) || ((privs != db[AL_CREATOR (ptr)].owner) && (AL_FLAGS (ptr) & AF_LOCKED)))) { return -1; } else { const char *p; free ((char *) AL_STR (ptr)); #ifdef MEM_CHECK del_check ("attribute_value"); #endif p = compress (s); AL_STR (ptr) = (char *) malloc (strlen (p) + 1); #ifdef MEM_CHECK add_check ("attribute_value"); #endif strcpy (AL_STR (ptr), p); AL_CREATOR (ptr) = db[privs].owner; if (flags != NOTHING) AL_FLAGS (ptr) = flags; if (AL_BAD (ptr)) AL_FLAGS (ptr) &= ~AF_NUKED; return 1; } } /*NOTREACHED*/ return 0; } ATTR *atr_get (dbref thing, char *atr) { ALIST *ptr; if (thing == NOTHING || !atr) return NULL; for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), atr)) { return AL_ATTR (ptr); } } for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), atr)) { return (AL_ATTR (ptr)); } } return (ATTR *) NULL; } void free_attrib (ATTR * thisattr) { if (thisattr) { if (thisattr->name) free ((char *) thisattr->name); if (thisattr->value) free ((char *) thisattr->value); free ((char *) thisattr); } #ifdef MEM_CHECK del_check ("attribute_name"); del_check ("attribute_value"); del_check ("attribute"); #endif } void atr_free (dbref thing) { ALIST *ptr, *next; for (ptr = db[thing].list; ptr; ptr = next) { next = AL_NEXT (ptr); free_attrib (AL_ATTR (ptr)); free ((char *) ptr); #ifdef MEM_CHECK del_check ("ALIST"); #endif } db[thing].list = (ALIST *) NULL; } /* reconstruct an attribute list */ void atr_collect (dbref thing) { ALIST *ptr, *next; ptr = db[thing].list; db[thing].list = NULL; while (ptr) { if (!AL_BAD (ptr)) { db[thing].list = AL_MAKE (AL_NAME (ptr), db[thing].list, AL_STR (ptr), AL_CREATOR (ptr), AL_FLAGS (ptr)); } next = AL_NEXT (ptr); free_attrib (AL_ATTR (ptr)); free ((char *) ptr); #ifdef MEM_CHECK del_check ("ALIST"); #endif ptr = next; } } void atr_cpy (dbref dest, dbref source) { ALIST *ptr; ptr = db[source].list; db[dest].list = NULL; while (ptr) { if (!AL_BAD (ptr)) { db[dest].list = AL_MAKE (AL_NAME (ptr), db[dest].list, AL_STR (ptr), AL_CREATOR (ptr), AL_FLAGS (ptr)); } ptr = AL_NEXT (ptr); } } char *convert_atr (dbref oldatr) { static char result[MAX_COMMAND_LEN]; int factor = 0; switch (oldatr) { case A_OSUCC: return "OSUCCESS"; case A_OFAIL: return "OFAILURE"; case A_FAIL: return "FAILURE"; case A_SUCC: return "SUCCESS"; case A_PASS: return "XYXXY"; case A_DESC: return "DESCRIBE"; case A_SEX: return "SEX"; case A_ODROP: return "ODROP"; case A_DROP: return "DROP"; case A_OKILL: return "OKILL"; case A_KILL: return "KILL"; case A_ASUCC: return "ASUCCESS"; case A_AFAIL: return "AFAILURE"; case A_ADROP: return "ADROP"; case A_AKILL: return "AKILL"; case A_USE: return "DOES"; case A_CHARGES: return "CHARGES"; case A_RUNOUT: return "RUNOUT"; case A_STARTUP: return "STARTUP"; case A_ACLONE: return "ACLONE"; case A_APAY: return "APAYMENT"; case A_OPAY: return "OPAYMENT"; case A_PAY: return "PAYMENT"; case A_COST: return "COST"; case A_RAND: return "RAND"; case A_LISTEN: return "LISTEN"; case A_AAHEAR: return "AAHEAR"; case A_AMHEAR: return "AMHEAR"; case A_AHEAR: return "AHEAR"; case A_LAST: return "LAST"; case A_QUEUE: return "QUEUE"; case A_IDESC: return "IDESCRIBE"; case A_ENTER: return "ENTER"; case A_OXENTER: return "OXENTER"; case A_AENTER: return "AENTER"; case A_ADESC: return "ADESCRIBE"; case A_ODESC: return "ODESCRIBE"; case A_RQUOTA: return "RQUOTA"; case A_ACONNECT: return "ACONNECT"; case A_ADISCONNECT: return "ADISCONNECT"; case A_LEAVE: return "LEAVE"; case A_ALEAVE: return "ALEAVE"; case A_OLEAVE: return "OLEAVE"; case A_OENTER: return "OENTER"; case A_OXLEAVE: return "OXLEAVE"; default: if (oldatr >= 100 && oldatr < 126) factor = 0; else if (oldatr >= 126 && oldatr < 152) factor = 1; else if (oldatr >= 152 && oldatr < 178) factor = 2; else { fprintf (stderr, "ERROR: Invalid attribute number in convert_atr. aborting.\n"); fflush (stderr); abort (); } sprintf ((char *) result, "%c%c", 'V' + factor, oldatr - (100 + (factor * 26)) + 'A'); return result; } /*NOTREACHED*/ return ""; } ATTR *atr_match (char *string) { ATTR *a = attr; while (a->name) { if (!string_compare (string, a->name)) { return a; } a++; } return (ATTR *) NULL; } int atr_comm_match (dbref thing, dbref player, int type, int end, char *str) { ALIST *ptr; int match = 0; char tbuf1[BUFFER_LEN]; char *s; if (thing < 0 || thing >= db_top) return 0; for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) { if (!AL_BAD (ptr) && (*AL_STR (ptr) == type) && !(AL_FLAGS (ptr) & AF_NOPROG)) { strcpy (tbuf1, uncompress (AL_STR (ptr))); for (s = tbuf1 + 1; *s && (*s != end); s++); if (!*s) continue; *s++ = '\0'; if (wild_match (tbuf1 + 1, str)) { match = 1; if ((type == '$') && (!eval_boolexp (player, db[thing].usekey, thing, 0, USELOCK))) notify (player, "Permission denied."); else parse_que (thing, s, player); } } } return match; } void do_atrlock (dbref player, const char *arg1, const char *arg2) { dbref thing; char *p; ALIST *ptr; int status; if (!arg2 || !*arg2) status = 0; else { if (!string_compare (arg2, "on")) { status = 1; } else if (!string_compare (arg2, "off")) { status = 2; } else status = 0; } if (!arg1 || !*arg1) { notify (player, "You need to give an object/attribute pair."); return; } if (!(p = index (arg1, '/')) || !(*(p + 1))) { notify (player, "You need to give an object/attribute pair."); return; } *p++ = '\0'; init_match (player, arg1, NOTYPE); match_everything (); if ((thing = noisy_match_result ()) == NOTHING) return; for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), p)) break; if (!ptr) for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), p)) break; if (ptr) { if (!status) { notify (player, tprintf ("That attribute is %slocked.", (AL_FLAGS (ptr) & AF_LOCKED) ? "" : "un")); return; } else if (!Wizard (player) && (db[AL_CREATOR (ptr)].owner != db[player].owner)) { notify (player, "You need to own the attribute to change its lock."); return; } else { if (status == 1) { AL_FLAGS (ptr) |= AF_LOCKED; notify (player, "Attribute locked."); return; } else if (status == 2) { AL_FLAGS (ptr) &= ~AF_LOCKED; notify (player, "Attribute unlocked."); return; } else { notify (player, "Invalid status on atrlock.. Notify god."); return; } } } else notify (player, "No such attribute."); return; } void do_atrchown (dbref player, const char *arg1, const char *arg2) { dbref thing, new_owner; char *p; ALIST *ptr; if (!arg1 || !*arg1) { notify (player, "You need to give an object/attribute pair."); return; } if (!(p = index (arg1, '/')) || !(*(p + 1))) { notify (player, "You need to give an object/attribute pair."); return; } *p++ = '\0'; init_match (player, arg1, NOTYPE); match_everything (); if ((thing = noisy_match_result ()) == NOTHING) return; if ((!arg2 && !*arg2) || !string_compare (arg2, "me")) new_owner = player; else new_owner = lookup_player (arg2); if (new_owner == NOTHING) { notify (player, "I can't find that player"); return; } for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) if (!AL_BAD (ptr) && !string_compare (AL_NAME (ptr), p)) break; if (!ptr) for (ptr = db[thing].list; ptr; ptr = AL_NEXT (ptr)) if (!AL_BAD (ptr) && string_prefix (AL_NAME (ptr), p)) break; if (ptr) { if ((controls (player, thing) && !(AL_FLAGS (ptr) & AF_LOCKED)) || (db[player].owner == db[AL_CREATOR (ptr)].owner)) { if (new_owner != db[thing].owner && !Wizard (player)) { notify (player, "You can only chown an attribute to the current owner of the object."); return; } AL_CREATOR (ptr) = db[new_owner].owner; notify (player, "Attribute owner changed."); return; } else { notify (player, "You don't have the permission to chown that."); return; } } else notify (player, "No such attribute."); } ATTR *atr_complete_match (dbref player, char *atr, dbref privs) { ATTR *a; char *s = atr; dbref thing; if (*s == '_') s++; if ((a = atr_get (player, s)) != NULL) { if (!controls (privs, player) && db[privs].owner != db[a->creator].owner && (a->flags & AF_ODARK)) { DOLIST (thing, db[player].contents) { if ((a = atr_get (thing, s)) != NULL) { if (!controls (privs, player) && db[privs].owner != db[a->creator].owner && (a->flags & AF_ODARK)) { return NULL; } else { return a; } } } } else { return a; } } return NULL; }