*
* Past and present PennMUSH development team members:
* T. Alexander Popiel, Ralph Melton, Thorvald Natvig, Luuk de Waard,
- * Shawn Wagner, Ervin Hearn III, Alan "Javelin" Schwartz
+ * Shawn Wagner, Ervin Hearn III, Alan "Javelin" Schwartz, Greg Millam
* Past and present PennMUSH porters:
* Nick Gammon, Sylvia, Dan Williams, Ervin Hearn III
* TinyMUSH 2.2, TinyMUSH 3.0, TinyMUX 2, and RhostMUSH developers
boolexp key, int flags);
void free_locks(lock_list *ll);
int eval_lock(dbref player, dbref thing, lock_type ltype);
+int eval_lock_with(dbref player, dbref thing, lock_type ltype, dbref env0,
+ dbref env1);
int fail_lock(dbref player, dbref thing, lock_type ltype, const char *def,
dbref loc);
void do_unlock(dbref player, const char *name, lock_type type);
if (!s)
continue;
*s++ = '\0';
+ if (type == '^' && !AF_Ahear(ptr)) {
+ if ((thing == player && !AF_Mhear(ptr))
+ || (thing != player && AF_Mhear(ptr)))
+ continue;
+ }
if (AF_Regexp(ptr)) {
/* Turn \: into : */
int start, count;
int powered = !(strchr(called_as, 'M') != NULL) && Priv_Who(executor);
int xwho = *called_as == 'X';
- int objid = strchr(called_as, 'D') != NULL;
+ int objid = (index(called_as, 'D') != NULL);
first = 1;
if(!xwho && nargs && args[0] && *args[0]) {
dbref zone, victim;
int first;
int powered = (strcmp(called_as, "ZMWHO") && Priv_Who(executor));
+ int objid = (index(called_as, 'D') != NULL);
first = 1;
zone = match_thing(executor, args[0]);
return;
}
- if (!GoodObject(zone) || !(eval_lock(victim, zone, Zone_Lock) || CanSee(victim,zone))) {
+ if (!GoodObject(zone) || (!Priv_Who(executor) && !(eval_lock(victim, zone, Zone_Lock) || CanSee(victim,zone)))) {
safe_str(T(e_perm), buff, bp);
return;
}
DESC_ITER_CONN(d) {
if (Zone(Location(d->player)) == zone &&
- (!Hidden(d) || (powered && CanSee(victim, d->player))) ) {
- if (first) {
- first = 0;
- } else {
- safe_chr(' ', buff, bp);
- }
- safe_dbref(d->player, buff, bp);
+ (!Hidden(d) || (powered && CanSee(victim, d->player))) ) {
+ if (first) {
+ first = 0;
+ } else {
+ safe_chr(' ', buff, bp);
+ }
+ safe_dbref(d->player, buff, bp);
+ if (objid) {
+ safe_chr(':', buff, bp);
+ safe_integer(CreTime(d->player), buff, bp);
+ }
}
}
}
safe_str(ls, commandraw, &c2);
}
if (cmd->type & CMD_T_EQSPLIT) {
- safe_chr('=', commandraw, &c2);
- if (cmd->type & CMD_T_RS_ARGS) {
- int rsa_index;
- /* This is counterintuitive, but rsa[]
- * starts at 1. */
- if (rsa[1]) {
- safe_str(rsa[1], commandraw, &c2);
- for (rsa_index = 2; rsa[rsa_index]; rsa_index++) {
- safe_chr(',', commandraw, &c2);
- safe_str(rsa[rsa_index], commandraw, &c2);
- }
- }
- } else {
- safe_str(rs, commandraw, &c2);
+ if(rhs_present) {
+ safe_chr('=', commandraw, &c2);
+ if (cmd->type & CMD_T_RS_ARGS) {
+ int rsa_index;
+ /* This is counterintuitive, but rsa[]
+ * starts at 1. */
+ if (rsa[1]) {
+ safe_str(rsa[1], commandraw, &c2);
+ for (rsa_index = 2; rsa[rsa_index]; rsa_index++) {
+ safe_chr(',', commandraw, &c2);
+ safe_str(rsa[rsa_index], commandraw, &c2);
+ }
+ }
+ }
}
#ifdef NEVER
/* We used to do this, but we're not sure why */
* This does nothing more than notify the player
* with "This command has not been implemented"
*/
-COMMAND (cmd_unimplemented) {
+COMMAND(cmd_unimplemented) {
char *saveregs[NUMQ];
if (strcmp(cmd->name, "UNIMPLEMENTED_COMMAND") != 0 &&
/** Type definition for a qsort comparison function */
typedef int (*comp_func) (const void *, const void *);
static void sane_qsort(void **array, int left, int right, comp_func compare);
+enum itemfun_op { IF_DELETE, IF_REPLACE, IF_INSERT };
static void do_itemfuns(char *buff, char **bp, char *str, char *num,
- char *word, char *sep, int flag);
+ char *word, char *sep, enum itemfun_op flag);
char *iter_rep[MAX_ITERS]; /**< itext values */
int iter_place[MAX_ITERS]; /**< inum numbers */
* \param num string containing the element number to operate on.
* \param word string to insert/delete/replace.
* \param sep separator string.
- * \param flag operation to perform: 0 - delete, 1 - replace, 2 - insert
+ * \param flag operation to perform: IF_DELETE, IF_REPLACE, IF_INSERT
*/
static void
do_itemfuns(char *buff, char **bp, char *str, char *num, char *word,
- char *sep, int flag)
+ char *sep, enum itemfun_op flag)
{
char c;
int el, count, len = -1;
c = ' ';
/* we can't remove anything before the first position */
- if ((el < 1 && flag != 2) || el == 0) {
+ if ((el < 1 && flag != IF_INSERT) || el == 0) {
safe_str(str, buff, bp);
return;
}
sptr[-1] = '\0';
switch (flag) {
- case 0:
+ case IF_DELETE:
/* deletion */
if (!eptr) { /* last element in the string */
if (el != 1)
safe_str(eptr, buff, bp);
}
break;
- case 1:
+ case IF_REPLACE:
/* replacing */
if (!eptr) { /* last element in string */
if (el != 1) {
safe_str(eptr, buff, bp);
}
break;
- case 2:
+ case IF_INSERT:
/* insertion */
if (sptr == str) { /* first element in string */
safe_str(word, buff, bp);
safe_str(str, buff, bp);
safe_chr(c, buff, bp);
safe_str(word, buff, bp);
- safe_chr(c, buff, bp);
- safe_str(sptr, buff, bp);
+ if (sptr && *sptr) { /* Don't add an osep to the end of the list */
+ safe_chr(c, buff, bp);
+ safe_str(sptr, buff, bp);
+ }
}
break;
}
{
/* delete a word at position X of a list */
- do_itemfuns(buff, bp, args[0], args[1], NULL, args[2], 0);
+ do_itemfuns(buff, bp, args[0], args[1], NULL, args[2], IF_DELETE);
}
/* ARGSUSED */
{
/* replace a word at position X of a list */
- do_itemfuns(buff, bp, args[0], args[1], args[2], args[3], 1);
+ do_itemfuns(buff, bp, args[0], args[1], args[2], args[3], IF_REPLACE);
}
/* ARGSUSED */
{
/* insert a word at position X of a list */
- do_itemfuns(buff, bp, args[0], args[1], args[2], args[3], 2);
+ do_itemfuns(buff, bp, args[0], args[1], args[2], args[3], IF_INSERT);
}
/* ARGSUSED */
} else {
/* Always make time(player) return a time,
* even if player's TZ is unset or wonky */
- a = atr_get(thing, "TZ");
- if (a) {
- ptr = atr_value(a);
- if(is_strict_number(ptr)) {
- utc = 1;
- tz = strtod(ptr, NULL);
- if (tz >= -24.0 || tz <= 24.0) {
- mytime += (int) (tz * 3600);
- }
- } else setenv("TZ", ptr, 1);
- }
+ a = atr_get(thing, "TZ");
+ if (a) {
+ ptr = atr_value(a);
+ if(is_strict_number(ptr)) {
+ utc = 1;
+ tz = strtod(ptr, NULL);
+ if (tz >= -24.0 && tz <= 24.0) {
+ mytime += (int) (tz * 3600);
+ }
+ } else setenv("TZ", ptr, 1);
+ }
}
}
} else if (!strcmp("UTCTIME", called_as)) {
}
-/* ARGSUSED */
-FUNCTION(fun_stringsecs)
-{
- int secs;
- if (etime_to_secs(args[0], &secs))
- safe_integer(secs, buff, bp);
- else
- safe_str(T("#-1 INVALID TIMESTRING"), buff, bp);
-}
-
/** Convert an elapsed time string (3d 2h 1m 10s) to seconds.
* \param str1 a time string.
* \param secs pointer to an int to fill with number of seconds.
}
+/* ARGSUSED */
+FUNCTION(fun_stringsecs)
+{
+ /* parse the result from timestring() back into a number of seconds */
+
+ int secs = 0;
+ char *str1 = args[0];
+ char str2[BUFFER_LEN];
+ int i;
+
+ while (str1 && *str1) {
+ while (*str1 == ' ')
+ str1++;
+ i = 0;
+ while (isdigit((unsigned char) *str1)) {
+ str2[i] = *str1;
+ str1++;
+ i++;
+ }
+ if (i == 0) {
+ safe_str(T("#-1 INVALID TIMESTRING"), buff, bp); // no numbers
+ return;
+ }
+ str2[i] = '\0';
+ if (!*str1) {
+ secs += parse_integer(str2); // no more chars, just add seconds and stop
+ break;
+ }
+ switch (*str1) {
+ case 'd':
+ case 'D':
+ secs += (parse_integer(str2) * 86400); // days
+ break;
+ case 'h':
+ case 'H':
+ secs += (parse_integer(str2) * 3600); // hours
+ break;
+ case 'm':
+ case 'M':
+ secs += (parse_integer(str2) * 60); // minutes
+ break;
+ case 's':
+ case 'S':
+ case ' ':
+ secs += parse_integer(str2); // seconds
+ break;
+ default:
+ safe_str(T("#-1 INVALID TIMESTRING"), buff, bp);
+ return;
+ }
+ str1++; // move past the time char
+ }
+ safe_integer(secs, buff, bp);
+}
+
/* ARGSUSED */
FUNCTION(fun_timestring)
{
{
struct tm *t;
t = localtime(&mudtime);
- strftime(tbuf1, sizeof tbuf1, "%I:%M%p ", t);
+ strftime(tbuf1, sizeof tbuf1, "Server uptime: %I:%M%p ", t);
nl = tbuf1 + strlen(tbuf1);
}
/* System uptime */
(options.warn_counter - mudtime) % 60, tbuf1);
}
+ notify_format(player,
+ T
+ ("PennMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"),
+ (mudtime - globals.first_start_time) / 86400,
+ ((mudtime - globals.first_start_time) % 86400) / 3600,
+ (((mudtime - globals.first_start_time) % 86400) % 3600) / 60,
+ (((mudtime - globals.first_start_time) % 86400) % 3600) % 60);
+
/* Mortals, go no further! */
if (!Site(player) || mortal)
return;
return eval_boolexp(player, getlock(thing, ltype), thing, NULL);
}
+/** Evaluate a lock.
+ * Evaluate lock ltype on thing for player, passing dbrefs for %0/%1.
+ * \param player dbref attempting to pass the lock.
+ * \param thing object containing the lock.
+ * \param ltype type of lock to check.
+ * \retval 1 player passes the lock.
+ * \retval 0 player does not pass the lock.
+ */
+int
+eval_lock_with(dbref player, dbref thing, lock_type ltype, dbref env0,
+ dbref env1)
+{
+ char *myenv[10] = { NULL };
+ char e0[SBUF_LEN], e1[SBUF_LEN], *ep;
+ char *preserves[10];
+ int result;
+
+ if (env0 != NOTHING) {
+ ep = e0;
+ safe_dbref(env0, e0, &ep);
+ *ep = '\0';
+ myenv[0] = e0;
+ }
+
+ if (env1 != NOTHING) {
+ ep = e1;
+ safe_dbref(env1, e1, &ep);
+ *ep = '\0';
+ myenv[1] = e1;
+ }
+
+ save_global_env("eval_lock_save", preserves);
+ restore_global_env("eval_lock", myenv);
+
+ boolexp b = getlock(thing, ltype);
+ log_activity(LA_LOCK, thing, unparse_boolexp(player, b, UB_DBREF));
+ result = eval_boolexp(player, b, thing, NULL);
+ restore_global_env("eval_lock_save", preserves);
+ return result;
+}
+
/** Active a lock's failure attributes.
* \param player dbref failing to pass the lock.
* \param thing object containing the lock.
a = atr_get(loc, "EXITFORMAT");
if (a) {
char *wsave[10], *rsave[NUMQ];
- char *arg, *buff, *bp, *save;
+ char *arg, *arg2, *buff, *bp, *save;
char const *sp;
int j;
arg = (char *) mush_malloc(BUFFER_LEN, "string");
+ arg2 = (char *) mush_malloc(BUFFER_LEN, "string");
buff = (char *) mush_malloc(BUFFER_LEN, "string");
- if (!arg || !buff)
+ if (!arg || !buff || !arg2)
mush_panic("Unable to allocate memory in look_exits");
save_global_regs("look_exits", rsave);
for (j = 0; j < 10; j++) {
mush_free((Malloc_t) tbuf2, "string");
mush_free((Malloc_t) nbuf, "string");
mush_free((Malloc_t) arg, "string");
+ mush_free((Malloc_t) arg2, "string");
mush_free((Malloc_t) buff, "string");
return;
}
{
int ok;
if (!strcasecmp(direction, "home")) {
- ok = !Fixed(player);
- ok = ok && command_check_byname(player, "HOME");
+ ok = command_check_byname(player, "HOME");
} else {
/* otherwise match on exits - don't use GoodObject here! */
ok = (match_result(player, direction, TYPE_EXIT, MAT_ENGLISH | MAT_EXIT) !=
}
}
/* if object is flagged LISTENER, check for ^ listen patterns
- * * these are like AHEAR - object cannot trigger itself.
* * unlike normal @listen, don't pass the message on.
* */
- if ((speaker != target) && (ThingListen(target) || RoomListen(target))
- && eval_lock(speaker, target, Listen_Lock)
+ if ((ThingListen(target) || RoomListen(target))
+ && eval_lock(speaker, target, Listen_Lock)
)
atr_comm_match(target, speaker, '^', ':',
(char *) notify_makestring(msgbuf, messages, NA_ASCII), 0,
break;
case '$': /* Dollar subs for regedit() */
if ((eflags & (PE_DOLLAR | PE_EVALUATE)) == (PE_DOLLAR | PE_EVALUATE) &&
- global_eval_context.re_subpatterns >= 0) {
- char obuf[BUFFER_LEN];
- int p = 0;
+ global_eval_context.re_subpatterns >= 0 &&
+ global_eval_context.re_offsets != NULL &&
+ global_eval_context.re_from != NULL) {
+ char obuf[BUFFER_LEN];
+ int p = -1;
char subspace[BUFFER_LEN];
char *named_substring = NULL;
obuf[0] = '\0';
- (*str)++;
- /* Check the first two characters after the $ for a number */
- if (isdigit((unsigned char) **str)) {
- p = **str - '0';
- (*str)++;
- if (isdigit((unsigned char) **str)) {
- p *= 10;
- p += **str - '0';
- (*str)++;
- if (isdigit((unsigned char) **str)) {
- /* More than 100. Treat this as literal. */
- safe_chr('$', buff, bp);
- safe_number(p, buff, bp);
- }
- }
- /* Look for a named subexpression */
- } else if (**str == '<') {
- char *nbuf = subspace;
- (*str)++;
- for (; *str && **str != '>'; (*str)++)
- safe_chr(**str, subspace, &nbuf);
- *nbuf = '\0';
- if (*str)
- (*str)++;
- if (is_strict_integer(subspace))
- p = abs(parse_integer(subspace));
- else
- named_substring = subspace;
- } else {
- safe_chr('$', buff, bp);
- break;
- }
-
- if ((!named_substring && p >= global_eval_context.re_subpatterns) ||
- global_eval_context.re_offsets == NULL ||
- global_eval_context.re_from == NULL) {
- /* It's out of bounds, return */
- safe_chr('$', buff, bp);
- if (named_substring)
- safe_format(buff, bp, "<%s>", named_substring);
- else
- safe_integer(p, buff, bp);
- break;
- }
+ (*str)++;
+ /* Check the first two characters after the $ for a number */
+ if (isdigit((unsigned char) **str)) {
+ p = **str - '0';
+ (*str)++;
+ } else if (**str == '<') {
+ char *nbuf = subspace;
+ (*str)++;
+ for (; *str && **str && **str != '>'; (*str)++)
+ safe_chr(**str, subspace, &nbuf);
+ *nbuf = '\0';
+ if (*str && **str)
+ (*str)++;
+ if (is_strict_integer(subspace))
+ p = abs(parse_integer(subspace));
+ else
+ named_substring = subspace;
+ } else {
+ safe_chr('$', buff, bp);
+ break;
+ }
- if (named_substring) {
- pcre_copy_named_substring(global_eval_context.re_code,
- global_eval_context.re_from,
- global_eval_context.re_offsets,
- global_eval_context.re_subpatterns,
- named_substring, obuf, BUFFER_LEN);
- } else {
- pcre_copy_substring(global_eval_context.re_from,
- global_eval_context.re_offsets,
- global_eval_context.re_subpatterns,
- p, obuf, BUFFER_LEN);
- }
- safe_str(obuf, buff, bp);
+ if (named_substring) {
+ pcre_copy_named_substring(global_eval_context.re_code,
+ global_eval_context.re_from,
+ global_eval_context.re_offsets,
+ global_eval_context.re_subpatterns,
+ named_substring, obuf, BUFFER_LEN);
+ } else {
+ pcre_copy_substring(global_eval_context.re_from,
+ global_eval_context.re_offsets,
+ global_eval_context.re_subpatterns,
+ p, obuf, BUFFER_LEN);
+ }
+ safe_str(obuf, buff, bp);
} else {
safe_chr('$', buff, bp);
(*str)++;
*/
if (player == victim) {
if (Fixed(victim) || RPMODE(victim))
- notify(player, T("You can't do that IC!"));
- else
- safe_tel(victim, HOME, silent);
+ notify(player, T("You can't do that IC!"));
+ else if(command_check_byname(victim, "HOME"))
+ safe_tel(victim, HOME, silent);
return;
} else
destination = Home(victim);
}
if ((spec.owner != ANY_OWNER && spec.owner != Owner(player)
- && !(CanSearch(player, spec.owner) || (spec.type == TYPE_PLAYER)))) {
+ && !(CanSearch(player, spec.owner) || (spec.type == TYPE_PLAYER)) ||
+ (ZMaster(spec.owner) && eval_lock(player, spec.owner, Zone_Lock)))) {
giveto(player, FIND_COST);
notify(player, T("You need a search warrant to do that."));
return -1;