static lock_list * getlockstruct(dbref thing, lock_type type) { lock_list *ll; dbref p = thing, ancestor = NOTHING; int cmp, count = 0, ancestor_in_chain = 0; if (GoodObject(thing)) ancestor = Ancestor_Parent(thing); do { for (; GoodObject(p); p = Parent(p)) { if (count++ > 100) return NULL; if (p == ancestor) ancestor_in_chain = 1; ll = Locks(p); while (ll && L_TYPE(ll)) { cmp = strcasecmp(L_TYPE(ll), type); if (cmp == 0) return (p != thing && (ll->flags & LF_PRIVATE)) ? NULL : ll; else if (cmp > 0) break; ll = ll->next; } } p = ancestor; } while (!ancestor_in_chain && !Orphan(thing) && GoodObject(ancestor)); return NULL; }
/** 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 flags on a lock (user interface). * \verbatim * This implements @lset. * \endverbatim * \param player the enactor. * \param what string in the form obj/lock. * \param flags list of flags to set. */ void do_lset(dbref player, char *what, char *flags) { dbref thing; lock_list *l; char *lname; int flag; int unset = 0; if ((lname = strchr(what, '/')) == NULL) { notify(player, T("No lock name given.")); return; } *lname++ = '\0'; if ((thing = match_controlled(player, what)) == NOTHING) return; if (*flags == '!') { unset = 1; flags++; } if ((flag = string_to_lockflag(flags)) < 0) { notify(player, T("Unrecognized lock flag.")); return; } l = getlockstruct_noparent(thing, lname); if (!l || !Can_Read_Lock(player, thing, L_TYPE(l))) { notify(player, T("No such lock.")); return; } if (!can_write_lock(player, thing, l)) { notify(player, T("Permission denied.")); return; } if (unset) L_FLAGS(l) &= ~flag; else L_FLAGS(l) |= flag; if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify_format(player, "%s/%s - %s.", Name(thing), L_TYPE(l), unset ? T("lock flags unset") : T("lock flags set")); if (!IsPlayer(thing)) { char lmbuf[1024]; ModTime(thing) = mudtime; snprintf(lmbuf, 1023, "lflags - %s[#%d]", flags, player); lmbuf[strlen(lmbuf)+1] = '\0'; set_lmod(thing, lmbuf); } }
/** Set flags on a lock (user interface). * \verbatim * This implements @lset. * \endverbatim * \param player the enactor. * \param what string in the form obj/lock. * \param flags list of flags to set. */ void do_lset(dbref player, char *what, char *flags) { dbref thing; lock_list *l; char *lname; privbits flag; bool unset = 0; if ((lname = strchr(what, '/')) == NULL) { notify(player, T("No lock name given.")); return; } *lname++ = '\0'; if ((thing = match_controlled(player, what)) == NOTHING) return; if (*flags == '!') { unset = 1; flags++; } if (string_to_lockflag(player, flags, &flag) < 0) { notify(player, T("Unrecognized lock flag.")); return; } l = getlockstruct_noparent(thing, lname); if (!l || !Can_Read_Lock(player, thing, L_TYPE(l))) { notify(player, T("No such lock.")); return; } if (!can_write_lock(player, thing, l)) { notify(player, T("Permission denied.")); return; } if (unset) L_FLAGS(l) &= ~flag; else L_FLAGS(l) |= flag; if (!Quiet(player) && !(Quiet(thing) && (Owner(thing) == player))) notify_format(player, "%s/%s - %s.", AName(thing, AN_SYS, NULL), L_TYPE(l), unset ? T("lock flags unset") : T("lock flags set")); if (!IsPlayer(thing)) ModTime(thing) = mudtime; }
static lock_list * getlockstruct_noparent(dbref thing, lock_type type) { lock_list *ll = Locks(thing); int cmp; while (ll && L_TYPE(ll)) { cmp = strcasecmp(L_TYPE(ll), type); if (cmp == 0) return ll; else if (cmp > 0) break; ll = ll->next; } return NULL; }
/** Copy the locks from one object to another. * \param player the enactor. * \param orig the source object. * \param clone the destination object. */ void clone_locks(dbref player, dbref orig, dbref clone) { lock_list *ll; for (ll = Locks(orig); ll; ll = ll->next) { if (!(L_FLAGS(ll) & LF_NOCLONE)) add_lock(player, clone, L_TYPE(ll), dup_bool(L_KEY(ll)), L_FLAGS(ll)); } }
static void ct_generic(dbref player, dbref i, warn_type flags) { if ((flags & W_LOCK_PROBS)) { lock_list *ll; for (ll = Locks(i); ll; ll = L_NEXT(ll)) { check_lock(player, i, L_TYPE(ll), L_KEY(ll)); } } }
/** Add a lock to an object on db load. * Set the lock type on thing to boolexp. * Used only on db load, when we can't safely test the player's * permissions because they're not loaded yet. * 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 lock creator. * \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. */ int add_lock_raw(dbref player, dbref thing, lock_type type, boolexp key, privbits flags) { lock_list *ll, **t; lock_type real_type = type; if (!GoodObject(thing)) { return 0; } ll = next_free_lock(Locks(thing)); 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 == LF_DEFAULT) { const lock_list *l2 = get_lockproto(real_type); if (l2) ll->flags = l2->flags; else ll->flags = 0; } else { ll->flags = flags; } 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; }