*
* 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;
}
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) {
+ if(rhs_present) {
safe_chr('=', commandraw, &c2);
if (cmd->type & CMD_T_RS_ARGS) {
int rsa_index;
safe_str(rsa[rsa_index], commandraw, &c2);
}
}
+ }
} else {
safe_str(rs, commandraw, &c2);
}
* 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 */
if(is_strict_number(ptr)) {
utc = 1;
tz = strtod(ptr, NULL);
- if (tz >= -24.0 || tz <= 24.0) {
+ if (tz >= -24.0 && tz <= 24.0) {
mytime += (int) (tz * 3600);
}
} else setenv("TZ", ptr, 1);
}
-/* 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))
+ if ((ThingListen(target) || RoomListen(target))
&& eval_lock(speaker, target, Listen_Lock)
)
atr_comm_match(target, speaker, '^', ':',
break;
case '$': /* Dollar subs for regedit() */
if ((eflags & (PE_DOLLAR | PE_EVALUATE)) == (PE_DOLLAR | PE_EVALUATE) &&
- global_eval_context.re_subpatterns >= 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 = 0;
+ int p = -1;
char subspace[BUFFER_LEN];
char *named_substring = NULL;
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)++)
+ for (; *str && **str && **str != '>'; (*str)++)
safe_chr(**str, subspace, &nbuf);
*nbuf = '\0';
- if (*str)
+ if (*str && **str)
(*str)++;
if (is_strict_integer(subspace))
p = abs(parse_integer(subspace));
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;
- }
-
if (named_substring) {
pcre_copy_named_substring(global_eval_context.re_code,
global_eval_context.re_from,
if (player == victim) {
if (Fixed(victim) || RPMODE(victim))
notify(player, T("You can't do that IC!"));
- else
+ else if(command_check_byname(victim, "HOME"))
safe_tel(victim, HOME, silent);
return;
} else
}
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;