/** Add a lock to an object (primitive). * Set the lock type on thing to boolexp. * This is a primitive routine, to be called by other routines. * It will go somewhat wonky if given a NULL boolexp. * It will allocate memory if called with a string that is not already * in the lock table. * \param player the enactor, for permission checking. * \param thing object on which to set the lock. * \param type type of lock to set. * \param key lock boolexp pointer (should not be NULL!). * \param flags lock flags. * \retval 0 failure. * \retval 1 success. */ int add_lock(dbref player, dbref thing, lock_type type, boolexp key, int flags) { lock_list *ll, **t; lock_type real_type = type; if (!GoodObject(thing)) { return 0; } ll = getlockstruct_noparent(thing, type); if (ll) { if (!can_write_lock(player, thing, ll)) { free_boolexp(key); return 0; } /* We're replacing an existing lock. */ free_boolexp(ll->key); ll->key = key; ll->creator = player; if (flags != -1) ll->flags = flags; } else { ll = next_free_lock(); if (!ll) { /* Oh, this sucks */ do_log(LT_ERR, 0, 0, "Unable to malloc memory for lock_list!"); } else { real_type = st_insert(type, &lock_names); ll->type = real_type; ll->key = key; ll->creator = player; if (flags == -1) { const lock_list *l2 = get_lockproto(real_type); if (l2) ll->flags = l2->flags; else ll->flags = 0; } else { ll->flags = flags; } if (!can_write_lock(player, thing, ll)) { st_delete(real_type, &lock_names); free_boolexp(key); return 0; } t = &Locks(thing); while (*t && strcasecmp(L_TYPE(*t), L_TYPE(ll)) < 0) t = &L_NEXT(*t); L_NEXT(ll) = *t; *t = ll; } } return 1; }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; /* check for '@lock <object>/<atr>' */ if (strchr(name, '/')) { do_atrlock(player, name, "on"); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, LF_DEFAULT)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), AName(thing, AN_SYS, NULL), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) ModTime(thing) = mudtime; } else { notify(player, T("Permission denied.")); /* Done by a failed add_lock() // free_boolexp(key); */ } } else free_boolexp(key); } }
/* Very primitive. */ static void free_one_lock_list(lock_list *ll) { if (ll == NULL) return; free_boolexp(ll->key); st_delete(ll->type, &lock_names); free_lock(ll); }
HS_DBREF CHSInterface::GetLock(int objnum, HS_LOCKTYPE lock) { #ifdef PENNMUSH // No change in code between versions boolexp boolExp = getlock(objnum, Use_Lock); if (boolExp == TRUE_BOOLEXP) { return NOTHING; } else { return strtodbref(unparse_boolexp(objnum, boolExp, UB_DBREF)); } #endif #if defined(TM3) || defined(MUX) char *value; BOOLEXP *key; int aowner, aflags; dbref lockobj; #ifdef TM3 int alen; value = atr_get((dbref) objnum, A_LUSE, &aowner, &aflags, &alen); #else value = atr_get((dbref) objnum, A_LUSE, &aowner, &aflags); #endif key = parse_boolexp((dbref) objnum, value, 1); free_lbuf(value); if (key == TRUE_BOOLEXP) { free_boolexp(key); return NOTHING; } else { lockobj = key->thing; free_boolexp(key); return lockobj; } #endif }
void free_propnode(PropPtr p) { if (!(PropFlags(p) & PROP_ISUNLOADED)) { if (PropType(p) == PROP_STRTYP) free((void *) PropDataStr(p)); if (PropType(p) == PROP_LOKTYP) free_boolexp(PropDataLok(p)); } free(p); }
void RCLEAR(struct inst *oper, char *file, int line) { int varcnt, j; assert(oper != NULL); assert(file != NULL); assert(line > 0); switch (oper->type) { case PROG_CLEARED: { log_status("WARNING: attempt to re-CLEAR() instruction from %s:%d previously CLEAR()ed at %s:%d", file, line, (char*)oper->data.addr, oper->line); assert(0); /* If debugging, we want to figure out just what is going on, and dump core at this point. This will at least give us some idea of what's going on. */ return; } case PROG_ADD: PROGRAM_DEC_INSTANCES(oper->data.addr->progref); oper->data.addr->links--; break; case PROG_STRING: if (oper->data.string && --oper->data.string->links == 0) free((void *) oper->data.string); break; case PROG_FUNCTION: if (oper->data.mufproc) { free((void*) oper->data.mufproc->procname); varcnt = oper->data.mufproc->vars; if (oper->data.mufproc->varnames) { for (j = 0; j < varcnt; j++) { free((void*)oper->data.mufproc->varnames[j]); } free((void*) oper->data.mufproc->varnames); } free((void*) oper->data.mufproc); } break; case PROG_ARRAY: array_free(oper->data.array); break; case PROG_LOCK: if (oper->data.lock != TRUE_BOOLEXP) free_boolexp(oper->data.lock); break; } oper->line = line; oper->data.addr = (struct prog_addr *) file; oper->type = PROG_CLEARED; }
void clear_propnode(PropPtr p) { if (!(PropFlags(p) & PROP_ISUNLOADED)) { if (PropType(p) == PROP_STRTYP) { free((void *) PropDataStr(p)); PropDataStr(p) = NULL; } if (PropType(p) == PROP_LOKTYP) free_boolexp(PropDataLok(p)); } SetPDataVal(p, 0); SetPFlags(p, (PropFlags(p) & ~PROP_ISUNLOADED)); SetPType(p, PROP_DIRTYP); }
void prim_parselock(PRIM_PROTOTYPE) { struct boolexp *lok; CHECKOP(1); oper1 = POP(); /* string: lock string */ CHECKOFLOW(1); if (oper1->type != PROG_STRING) abort_interp("Invalid argument."); if (oper1->data.string != (struct shared_string *) NULL) { lok = parse_boolexp(fr->descr, ProgUID, oper1->data.string->data, 0); } else { lok = TRUE_BOOLEXP; } CLEAR(oper1); PushLock(lok); free_boolexp(lok); }
// Can be used to set a type of lock on an object void CHSInterface::SetLock(int objnum, int lockto, HS_LOCKTYPE lock) { #ifdef PENNMUSH // No change in code between versions char tmp[32]; sprintf_s(tmp, "#%d", lockto); switch (lock) { case LOCK_USE: add_lock(GOD, objnum, Use_Lock, parse_boolexp(lockto, tmp, Use_Lock), -1); break; case LOCK_ZONE: add_lock(GOD, objnum, Zone_Lock, parse_boolexp(lockto, tmp, Zone_Lock), -1); break; case LOCK_NORMAL: default: break; } #endif #if defined(TM3) || defined(MUX) char tmp[SBUF_SIZE]; BOOLEXP *key; snprintf(tmp, SBUF_SIZE - 1, "#%d", lockto); key = parse_boolexp(objnum, tmp, 1); switch (lock) { case LOCK_USE: atr_add_raw(objnum, A_LUSE, unparse_boolexp_quiet(objnum, key)); break; case LOCK_ZONE: atr_add_raw(objnum, A_LCONTROL, unparse_boolexp_quiet(objnum, key)); case LOCK_NORMAL: break; } free_boolexp(key); #endif }
/** * This is the opposite of alloc_propnode, and is used to free the * PropPtr datastructure. It will free whatever data is associated * with the prop as well as the PropPtr as well. * * @param node the prop to free */ void free_propnode(PropPtr p) { if (!(PropFlags(p) & PROP_ISUNLOADED)) { if (PropType(p) == PROP_STRTYP) free(PropDataStr(p)); if (PropType(p) == PROP_LOKTYP) free_boolexp(PropDataLok(p)); } /* @TODO: The PropPtr object has a 'key' field which is * set up like char key[1]; In alloc_propnode, we use * strncpy to copy the name of the prop to the key field. * * I should think we would need to free the key or we would * have a leak. However, I should have also thought the key * should be a char* ... I don't actually understand how this * works. It seems like it should be segfaulting and/or * leaking memory. I want to review this in greater depth * later. */ free(p); }
dbref db_read(FILE * f, int *db_format, int *db_version, int *db_flags) { dbref i, anum; char ch; const char *tstr; int header_gotten, size_gotten, nextattr_gotten; int read_attribs, read_name, read_zone, read_link, read_key, read_parent; int read_extflags, read_3flags, read_money, read_timestamps, read_new_strings; int read_powers, read_powers_player, read_powers_any; int deduce_version, deduce_name, deduce_zone, deduce_timestamps; int aflags, f1, f2, f3; BOOLEXP *tempbool; header_gotten = 0; size_gotten = 0; nextattr_gotten = 0; g_format = F_UNKNOWN; g_version = 0; g_flags = 0; read_attribs = 1; read_name = 1; read_zone = 0; read_link = 0; read_key = 1; read_parent = 0; read_money = 1; read_extflags = 0; read_3flags = 0; read_timestamps = 0; read_new_strings = 0; read_powers = 0; read_powers_player = 0; read_powers_any = 0; deduce_version = 1; deduce_zone = 1; deduce_name = 1; deduce_timestamps = 1; db_free(); for(i = 0;; i++) { switch (ch = getc(f)) { case '-': /* Misc tag */ switch (ch = getc(f)) { case 'R': /* Record number of players */ mudstate.record_players = getref(f); break; default: (void) getstring_noalloc(f, 0); } break; case '+': /* * MUX and MUSH header */ switch (ch = getc(f)) { /* * 2nd char selects * type */ case 'X': /* * MUX VERSION */ if(header_gotten) { fprintf(stderr, "\nDuplicate MUX version header entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); break; } header_gotten = 1; deduce_version = 0; g_format = F_MUX; g_version = getref(f); /* * Otherwise extract feature flags */ if(g_version & V_GDBM) { read_attribs = 0; read_name = !(g_version & V_ATRNAME); } read_zone = (g_version & V_ZONE); read_link = (g_version & V_LINK); read_key = !(g_version & V_ATRKEY); read_parent = (g_version & V_PARENT); read_money = !(g_version & V_ATRMONEY); read_extflags = (g_version & V_XFLAGS); read_3flags = (g_version & V_3FLAGS); read_powers = (g_version & V_POWERS); read_new_strings = (g_version & V_QUOTED); g_flags = g_version & ~V_MASK; g_version &= V_MASK; deduce_name = 0; deduce_version = 0; deduce_zone = 0; break; case 'S': /* * SIZE */ if(size_gotten) { fprintf(stderr, "\nDuplicate size entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); } else { mudstate.min_size = getref(f); } size_gotten = 1; break; case 'A': /* * USER-NAMED ATTRIBUTE */ anum = getref(f); tstr = getstring_noalloc(f, read_new_strings); if(isdigit(*tstr)) { aflags = 0; while (isdigit(*tstr)) aflags = (aflags * 10) + (*tstr++ - '0'); tstr++; /* * skip ':' */ } else { aflags = mudconf.vattr_flags; } vattr_define((char *) tstr, anum, aflags); break; case 'F': /* * OPEN USER ATTRIBUTE SLOT */ anum = getref(f); break; case 'N': /* * NEXT ATTR TO ALLOC WHEN NO * FREELIST */ if(nextattr_gotten) { fprintf(stderr, "\nDuplicate next free vattr entry at object %d, ignored.\n", i); tstr = getstring_noalloc(f, 0); } else { mudstate.attr_next = getref(f); nextattr_gotten = 1; } break; default: fprintf(stderr, "\nUnexpected character '%c' in MUX header near object #%d, ignored.\n", ch, i); tstr = getstring_noalloc(f, 0); } break; case '!': /* * MUX entry/MUSH entry/MUSE non-zoned entry */ if(deduce_version) { g_format = F_MUX; g_version = 1; deduce_name = 0; deduce_zone = 0; deduce_version = 0; } else if(deduce_zone) { deduce_zone = 0; read_zone = 0; } i = getref(f); db_grow(i + 1); if(read_name) { tstr = getstring_noalloc(f, read_new_strings); if(deduce_name) { if(isdigit(*tstr)) { read_name = 0; s_Location(i, atoi(tstr)); } else { s_Name(i, (char *) tstr); s_Location(i, getref(f)); } deduce_name = 0; } else { s_Name(i, (char *) tstr); s_Location(i, getref(f)); } } else { s_Location(i, getref(f)); } /* * ZONE on MUSE databases and some others */ if(read_zone) s_Zone(i, getref(f)); /* * else * * s_Zone(i, NOTHING); */ /* * CONTENTS and EXITS */ s_Contents(i, getref(f)); s_Exits(i, getref(f)); /* * LINK */ if(read_link) s_Link(i, getref(f)); else s_Link(i, NOTHING); /* * NEXT */ s_Next(i, getref(f)); /* * LOCK */ if(read_key) { tempbool = getboolexp(f); atr_add_raw(i, A_LOCK, unparse_boolexp_quiet(1, tempbool)); free_boolexp(tempbool); } /* * OWNER */ s_Owner(i, getref(f)); /* * PARENT: PennMUSH uses this field for ZONE * (which we use as PARENT if we * didn't already read in a * non-NOTHING parent. */ if(read_parent) { s_Parent(i, getref(f)); } else { s_Parent(i, NOTHING); } /* * PENNIES */ if(read_money) /* * if not fix in * unscraw_foreign */ s_Pennies(i, getref(f)); /* * FLAGS */ f1 = getref(f); if(read_extflags) f2 = getref(f); else f2 = 0; if(read_3flags) f3 = getref(f); else f3 = 0; s_Flags(i, f1); s_Flags2(i, f2); s_Flags3(i, f3); if(read_powers) { f1 = getref(f); f2 = getref(f); s_Powers(i, f1); s_Powers2(i, f2); } /* * ATTRIBUTES */ if(read_attribs) { if(!get_list(f, i, read_new_strings)) { fprintf(stderr, "\nError reading attrs for object #%d\n", i); return -1; } } /* * check to see if it's a player */ if(Typeof(i) == TYPE_PLAYER) { c_Connected(i); } break; case '*': /* * EOF marker */ tstr = getstring_noalloc(f, 0); if(strcmp(tstr, "**END OF DUMP***")) { fprintf(stderr, "\nBad EOF marker at object #%d\n", i); return -1; } else { /* * Fix up bizarro foreign DBs */ *db_version = g_version; *db_format = g_format; *db_flags = g_flags; load_player_names(); return mudstate.db_top; } default: fprintf(stderr, "\nIllegal character '%c' near object #%d\n", ch, i); return -1; } } }
/** Set/lock a lock (user interface). * \verbatim * This implements @lock. * \endverbatim * \param player the enactor. * \param name name of object to lock. * \param keyname key to lock the lock to, as a string. * \param type type of lock to lock. */ void do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; boolexp key; char *sp; /* check for '@lock <object>/<atr>' */ sp = strchr(name, '/'); if (sp) { do_atrlock(player, name, keyname, 0); return; } if (!keyname || !*keyname) { do_unlock(player, name, type); return; } switch (thing = match_result(player, name, NOTYPE, MAT_EVERYTHING)) { case NOTHING: notify(player, T("I don't see what you want to lock!")); return; case AMBIGUOUS: notify(player, T("I don't know which one you want to lock!")); return; default: if (!controls(player, thing)) { notify(player, T("You can't lock that!")); return; } if (IsGarbage(thing)) { notify(player, T("Why would you want to lock garbage?")); return; } break; } key = parse_boolexp(player, keyname, type); /* do the lock */ if (key == TRUE_BOOLEXP) { notify(player, T("I don't understand that key.")); } else { if ((real_type = check_lock_type(player, thing, type)) != NULL) { /* everything ok, do it */ if (add_lock(player, thing, real_type, key, -1)) { if (!AreQuiet(player, thing)) notify_format(player, T("%s(%s) - %s locked."), Name(thing), unparse_dbref(thing), real_type); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "%s lock[#%d]", real_type, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } } else { notify(player, T("Permission denied.")); free_boolexp(key); } } else free_boolexp(key); } }