/* cque.c */
#include "copyrite.h"
#include "config.h"
#include <ctype.h>
#include <fcntl.h>
#ifdef I_STRING
#include <string.h>
#else
#include <strings.h>
#endif
#ifdef I_SYS_TIME
#include <sys/time.h>
#else
#include <time.h>
#endif
#include <signal.h>
#include "conf.h"
#include "mushdb.h"
#include "intrface.h"
#include "match.h"
#include "externs.h"
#ifdef MEM_CHECK
#include "memcheck.h"
#endif
#include "parse.h"
#include "mymalloc.h"
#include "confmagic.h"
extern char ccom[];
extern dbref cplr;
extern time_t mudtime;
char *wenv[10]; /* working environment (wptr/rptr equiv) */
char renv[10][BUFFER_LEN];
char *wnxt[10], *rnxt[10]; /* stuff to be shoved into the queue */
typedef struct bque BQUE;
struct bque {
BQUE *next;
dbref player; /* player who will do command */
dbref cause; /* player causing command (for %N) */
dbref sem; /* semaphore object to block on */
int left; /* seconds left until execution */
char *env[10]; /* environment, from wild match */
char *rval[10]; /* environment, from setq() */
char *comm; /* command to be executed */
};
static BQUE *qfirst = NULL, *qlast = NULL, *qwait = NULL;
static BQUE *qlfirst = NULL, *qllast = NULL;
static BQUE *qsemfirst = NULL, *qsemlast = NULL;
void parse_que _((dbref player, const char *command, dbref cause));
static int add_to_generic _((dbref player, int am, int key));
static int add_to _((dbref player, int am));
static int add_to_sem _((dbref player, int am));
static int queue_limit _((dbref player));
void free_qentry _((BQUE *point));
static int pay_queue _((dbref player));
void wait_que _((dbref player, int wait, char *command, dbref cause, dbref sem));
void do_second _((void));
int test_top _((void));
int do_top _((int ncom));
int que_next _((void));
int nfy_que _((dbref sem, int key, int count));
void do_notify _((dbref player, dbref cause, int key, char *what, char *count));
void do_wait _((dbref player, dbref cause, char *arg1, char *cmd));
static void show_queue _((dbref player, dbref victim, int q_type, int q_quiet, int q_all, BQUE *q_ptr, int *tot, int *self, int *del));
void do_queue _((dbref player, const char *what, int flag));
void do_halt _((dbref owner, const char *ncom, int victim));
void do_halt1 _((dbref player, const char *arg1, const char *arg2));
void do_allhalt _((dbref player));
void do_allrestart _((dbref player));
static void do_raw_restart _((dbref victim));
void do_restart_com _((dbref player, const char *arg1));
static int
add_to_generic(player, am, key)
dbref player;
int am;
int key;
/* 0 for queue, 1 for semaphore */
{
int num = 0;
ATTR *a;
const char *atrname;
char buff[MAX_COMMAND_LEN];
if (key == 0) {
atrname = "QUEUE";
player = Owner(player);
} else {
atrname = "SEMAPHORE";
}
a = atr_get_noparent(player, atrname); /* don't get from the parent! */
if (a)
num = atoi(uncompress(a->value));
num += am;
if (num)
sprintf(buff, "%d", num);
else
*buff = '\0';
(void) atr_add(player, atrname, buff, GOD, NOTHING);
return (num);
}
static int
add_to(player, am)
dbref player;
int am;
{
return (add_to_generic(player, am, 0));
}
static int
add_to_sem(player, am)
dbref player;
int am;
{
return (add_to_generic(player, am, 1));
}
static int
queue_limit(player)
dbref player;
{
/* returns 1 if player has exceeded his queue limit */
if (HugeQueue(player)) {
if (add_to(player, 1) > (QUEUE_QUOTA + db_top))
return 1;
else
return 0;
} else {
if (add_to(player, 1) > QUEUE_QUOTA)
return 1;
else
return 0;
}
return 0; /* NOTREACHED */
}
void
free_qentry(point)
BQUE *point;
{
int a;
for (a = 0; a < 10; a++)
if (point->env[a]) {
mush_free((Malloc_t) point->env[a], "bqueue_env");
}
for (a = 0; a < 10; a++)
if (point->rval[a]) {
mush_free((Malloc_t) point->rval[a], "bqueue_rval");
}
if (point->comm)
mush_free((Malloc_t) point->comm, "bqueue_comm");
mush_free((Malloc_t) point, "BQUE");
}
static int
pay_queue(player)
dbref player;
{
if (!payfor(player,
QUEUE_COST + ((getrandom(QUEUE_LOSS) == 1) ? 1 : 0))) {
notify(Owner(player), "Not enough money to queue command.");
return 0;
}
if (queue_limit(QUEUE_PER_OWNER ? Owner(player) : player)) {
notify(Owner(player),
tprintf("Runaway object: %s(#%d). Commands halted.",
Name(player), player));
/* wipe out that object's queue and set it HALT */
do_halt(Owner(player), "", player);
Flags(player) |= HALT;
return 0;
}
return 1;
}
void
parse_que(player, command, cause)
dbref player;
const char *command;
dbref cause;
{
int a;
BQUE *tmp;
if ((Typeof(player) != TYPE_PLAYER) && (Halted(player)))
return;
if (!pay_queue(player)) /* make sure player can afford to do it */
return;
tmp = (BQUE *) mush_malloc(sizeof(BQUE), "BQUE");
tmp->comm = (char *) strdup(command);
#ifdef MEM_CHECK
add_check("bqueue_comm");
#endif
tmp->player = player;
tmp->next = NULL;
tmp->left = 0;
tmp->cause = cause;
for (a = 0; a < 10; a++)
if (!wnxt[a])
tmp->env[a] = NULL;
else {
tmp->env[a] = (char *) strdup(wnxt[a]);
#ifdef MEM_CHECK
add_check("bqueue_env");
#endif
}
for (a = 0; a < 10; a++)
if (!rnxt[a] || !rnxt[a][0])
tmp->rval[a] = NULL;
else {
tmp->rval[a] = (char *) strdup(rnxt[a]);
#ifdef MEM_CHECK
add_check("bqueue_rval");
#endif
}
if (Typeof(cause) == TYPE_PLAYER) {
if (qlast) {
qlast->next = tmp;
qlast = tmp;
} else
qlast = qfirst = tmp;
} else {
if (qllast) {
qllast->next = tmp;
qllast = tmp;
} else
qllast = qlfirst = tmp;
}
}
void
wait_que(player, wait, command, cause, sem)
dbref player;
int wait;
char *command;
dbref cause;
dbref sem;
{
BQUE *tmp, *point, *trail;
int a;
if (wait == 0) {
if (sem != NOTHING)
add_to_sem(sem, -1);
parse_que(player, command, cause);
return;
}
if (!pay_queue(player)) /* make sure player can afford to do it */
return;
tmp = (BQUE *) mush_malloc(sizeof(BQUE), "BQUE");
tmp->comm = (char *) strdup(command);
#ifdef MEM_CHECK
add_check("bqueue_comm");
#endif
tmp->player = player;
tmp->cause = cause;
for (a = 0; a < 10; a++) {
if (!wnxt[a])
tmp->env[a] = NULL;
else {
tmp->env[a] = (char *) strdup(wnxt[a]);
#ifdef MEM_CHECK
add_check("bqueue_env");
#endif
}
if (!rnxt[a] || !rnxt[a][0])
tmp->rval[a] = NULL;
else {
tmp->rval[a] = (char *) strdup(rnxt[a]);
#ifdef MEM_CHECK
add_check("bqueue_rval");
#endif
}
}
if (wait >= 0)
tmp->left = mudtime + wait;
else
tmp->left = 0; /* semaphore wait without a timeout */
tmp->sem = sem;
if (sem == NOTHING) {
/* No semaphore, put on normal wait queue, sorted by time */
for (point = qwait, trail = NULL;
point && (point->left <= tmp->left);
point = point->next)
trail = point;
tmp->next = point;
if (trail != NULL)
trail->next = tmp;
else
qwait = tmp;
} else {
/* Put it on the semaphore queue */
tmp->next = NULL;
if (qsemlast != NULL)
qsemlast->next = tmp;
else
qsemfirst = tmp;
qsemlast = tmp;
}
}
void
do_second()
{
/* call every second to check for wait queue commands */
BQUE *trail = NULL, *point, *next;
/* move contents of low priority queue onto end of normal one
* this helps to keep objects from getting out of control since
* its effects on other objects happen only after one second
* this should allow @halt to be typed before getting blown away
* by scrolling text.
*/
if (qlfirst) {
if (qlast)
qlast->next = qlfirst;
else
qfirst = qlfirst;
qlast = qllast;
qllast = qlfirst = NULL;
}
/* check regular wait queue */
while (qwait && qwait->left <= mudtime) {
point = qwait;
qwait = point->next;
point->next = NULL;
point->left = 0;
if (Typeof(point->cause) == TYPE_PLAYER) {
if (qlast) {
qlast->next = point;
qlast = point;
} else
qlast = qfirst = point;
} else {
if (qllast) {
qllast->next = point;
qllast = point;
} else
qllast = qlfirst = point;
}
}
/* check for semaphore timeouts */
for (point = qsemfirst, trail = NULL; point; point = next) {
if (point->left == 0) {
next = (trail = point)->next;
continue; /* skip non-timed waits */
}
if (point->left <= mudtime) {
if (trail != NULL)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
add_to_sem(point->sem, -1);
point->sem = NOTHING;
point->next = NULL;
if (Typeof(point->cause) == TYPE_PLAYER) {
if (qlast) {
qlast->next = point;
qlast = point;
} else
qlast = qfirst = point;
} else {
if (qllast) {
qllast->next = point;
qllast = point;
} else
qllast = qlfirst = point;
}
} else
next = (trail = point)->next;
}
}
int
test_top()
{
return (qfirst ? 1 : 0);
}
int
do_top(ncom)
int ncom;
{
/* execute ncom commands off the top of the queue */
int a, i;
BQUE *tmp;
char tbuf[BUFFER_LEN];
char *r;
char const *s;
for (i = 0; i < ncom; i++) {
if (!qfirst)
return i;
if (GoodObject(qfirst->player) && !Destroyed(qfirst->player)) {
cplr = qfirst->player;
giveto(cplr, QUEUE_COST);
add_to(cplr, -1);
qfirst->player = 0;
if ((Typeof(cplr) == TYPE_PLAYER) || !Halted(cplr)) {
for (a = 0; a < 10; a++) {
wenv[a] = qfirst->env[a];
if (qfirst->rval[a])
strcpy(renv[a], qfirst->rval[a]);
else
renv[a][0] = '\0';
}
s = qfirst->comm;
while (*s) {
r = ccom;
process_expression(ccom, &r, &s, cplr, qfirst->cause, qfirst->cause,
PE_NOTHING, PT_SEMI, NULL);
*r = '\0';
if (*s == ';')
s++;
strcpy(tbuf, ccom);
process_command(cplr, tbuf, qfirst->cause, 0);
}
}
}
tmp = qfirst->next;
free_qentry(qfirst);
if (!(qfirst = tmp))
qlast = NULL;
}
return i;
}
int
que_next()
{
int min, curr;
BQUE *point;
/* If there are commands in the player queue, they should be run
* immediately.
*/
if (qfirst != NULL)
return 0;
/* If there are commands in the object queue, they should be run in
* one second.
*/
if (qlfirst != NULL)
return 1;
/* Check out the wait and semaphore queues, looking for the smallest
* wait value. Return that - 1, since commands get moved to the player
* queue when they have one second to go.
*/
min = 5;
for (point = qwait; point; point = point->next) {
curr = point->left - mudtime;
if (curr <= 2)
return 1;
if (curr < min)
min = curr;
}
for (point = qsemfirst; point; point = point->next) {
if (point->left == 0) /* no timeout */
continue;
curr = point->left - mudtime;
if (curr <= 2)
return 1;
if (curr < min)
min = curr;
}
return (min - 1);
}
int
nfy_que(sem, key, count)
dbref sem;
int key;
int count;
/* 0 is normal, 1 is all, 2 is drain */
{
BQUE *point, *trail, *next;
int num;
ATTR *a;
if ((a = atr_get_noparent(sem, "SEMAPHORE")) != NULL)
num = atoi(uncompress(a->value));
else
num = 0;
if (num > 0) {
num = 0;
for (point = qsemfirst, trail = NULL; point; point = next) {
if (point->sem == sem) {
num++;
if (trail)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
/* run or discard the command */
if (key != 2) {
point->next = NULL;
if (Typeof(point->cause) == TYPE_PLAYER) {
if (qlast) {
qlast->next = point;
qlast = point;
} else
qlast = qfirst = point;
} else {
if (qllast) {
qllast->next = point;
qllast = point;
} else
qllast = qlfirst = point;
}
} else {
giveto(point->player, QUEUE_COST);
add_to(point->player, -1);
free_qentry(point);
}
} else {
next = (trail = point)->next;
}
/* if we've notified enough, exit. Note that we don't have to check
* for the case of @notify/all, since we don't break out of this
* loop "manually" unless the key is standard @notify.
*/
if ((key == 0) && (num >= count))
next = NULL;
}
} else {
num = 0;
}
/* update the semaphore waiter's count */
if (key == 0)
add_to_sem(sem, -count);
else
atr_clr(sem, "SEMAPHORE", GOD);
return num;
}
void
do_notify(player, cause, key, what, count)
dbref player;
dbref cause;
int key; /* 0 is normal, 1 is all, 2 is drain */
char *what;
char *count;
{
dbref thing;
int i;
/* find it */
if ((thing = noisy_match_result(player, what, NOTYPE, MAT_EVERYTHING)) == NOTHING)
return;
/* must control something or have it link_ok in order to use it as
* as a semaphore.
*/
if (!controls(player, thing) && !LinkOk(thing)) {
notify(player, "Permission denied.");
return;
}
/* find how many times to notify */
if (count && *count)
i = atoi(count);
else
i = 1;
if (i > 0)
nfy_que(thing, key, i);
if (key != 2) {
quiet_notify(player, "Notified.");
} else {
quiet_notify(player, "Drained.");
}
}
void
do_wait(player, cause, arg1, cmd)
dbref player;
dbref cause;
char *arg1;
char *cmd;
{
dbref thing;
char *tcount;
int waitfor, num;
ATTR *a;
char *arg2;
int j;
for (j = 0; j < 10; j++) {
wnxt[j] = wenv[j];
rnxt[j] = renv[j];
}
arg2 = strip_braces(cmd);
if (is_strict_number(arg1)) {
/* normal wait */
wait_que(player, atoi(arg1), arg2, cause, NOTHING);
mush_free(arg2, "strip_braces.buff");
return;
}
/* semaphore wait with optional timeout */
/* find the thing to wait on */
tcount = (char *) index(arg1, '/');
if (tcount)
*tcount++ = '\0';
if ((thing = noisy_match_result(player, arg1, NOTYPE, MAT_EVERYTHING)) == NOTHING) {
mush_free(arg2, "strip_braces.buff");
return;
}
if (!controls(player, thing) && !LinkOk(thing)) {
notify(player, "Permission denied.");
mush_free(arg2, "strip_braces.buff");
return;
}
/* get timeout, default of -1 */
if (tcount && *tcount)
waitfor = atol(tcount);
else
waitfor = -1;
add_to_sem(thing, 1);
a = atr_get_noparent(thing, "SEMAPHORE");
if (a)
num = atoi(uncompress(a->value));
else
num = 0;
if (num <= 0) {
thing = NOTHING;
waitfor = -1; /* just in case there was a timeout given */
}
wait_que(player, waitfor, arg2, cause, thing);
mush_free(arg2, "strip_braces.buff");
}
static void
show_queue(player, victim, q_type, q_quiet, q_all, q_ptr, tot, self, del)
dbref player;
dbref victim;
int q_type;
int q_quiet;
int q_all;
BQUE *q_ptr;
int *tot;
int *self;
int *del;
{
BQUE *tmp;
for (tmp = q_ptr; tmp; tmp = tmp->next) {
(*tot)++;
if (!GoodObject(tmp->player))
(*del)++;
else if (q_all || (Owner(tmp->player) == victim)) {
(*self)++;
if (!q_quiet &&
(LookQueue(player) || Owns(tmp->player, player))) {
switch (q_type) {
case 1: /* wait queue */
notify(player, tprintf("[%d]%s:%s", tmp->left - mudtime,
unparse_object(player, tmp->player),
tmp->comm));
break;
case 2: /* semaphore queue */
if (tmp->left != 0) {
notify(player,
tprintf("[#%d/%d]%s:%s", tmp->sem,
tmp->left - mudtime,
unparse_object(player, tmp->player),
tmp->comm));
} else {
notify(player,
tprintf("[#%d]%s:%s", tmp->sem,
unparse_object(player, tmp->player),
tmp->comm));
}
break;
default: /* player or object queue */
notify(player, tprintf("%s:%s",
unparse_object(player, tmp->player),
tmp->comm));
}
}
}
}
}
void
do_queue(player, what, flag)
dbref player;
const char *what;
int flag; /* 0 - normal, 1 - all, 2 - summary, 3 - quick */
{
/* tell player what commands they have pending in the queue (@ps) */
dbref victim = NOTHING;
int all = 0;
int quick = 0;
int dpq = 0, doq = 0, dwq = 0, dsq = 0;
int pq = 0, oq = 0, wq = 0, sq = 0;
int tpq = 0, toq = 0, twq = 0, tsq = 0;
if (flag == 2 || flag == 3)
quick = 1;
if (flag == 1 || flag == 2) {
all = 1;
victim = player;
} else if (LookQueue(player)) {
if (!what || !*what)
victim = player;
else {
victim = match_result(player, what, TYPE_PLAYER,
MAT_PLAYER | MAT_ABSOLUTE | MAT_ME);
}
} else {
victim = player;
}
switch (victim) {
case NOTHING:
notify(player, "I couldn't find that player.");
break;
case AMBIGUOUS:
notify(player, "I don't know who you mean!");
break;
default:
if (!quick) {
if (all == 1)
notify(player, "Queue for : all");
else
notify(player,
tprintf("Queue for : %s", Name(victim)));
}
victim = Owner(victim);
if (!quick)
notify(player, "Player Queue:");
show_queue(player, victim, 0, quick, all, qfirst, &tpq, &pq, &dpq);
if (!quick)
notify(player, "Object Queue:");
show_queue(player, victim, 0, quick, all, qlfirst, &toq, &oq, &doq);
if (!quick)
notify(player, "Wait Queue:");
show_queue(player, victim, 1, quick, all, qwait, &twq, &wq, &dwq);
if (!quick)
notify(player, "Semaphore Queue:");
show_queue(player, victim, 2, quick, all, qsemfirst, &tsq, &sq, &dsq);
if (!quick)
notify(player, "------------ Queue Done ------------");
notify(player,
tprintf(
"Totals: Player...%d/%d[%ddel] Object...%d/%d[%ddel] Wait...%d/%d Semaphore...%d/%d",
pq, tpq, dpq, oq, toq, doq, wq, twq, sq, tsq));
}
}
void
do_halt(owner, ncom, victim)
dbref owner;
const char *ncom;
dbref victim;
{
BQUE *tmp, *trail = NULL, *point, *next;
int num = 0;
dbref player;
if (victim == NOTHING)
player = owner;
else
player = victim;
quiet_notify(Owner(player), tprintf("Halted: %s(#%d).", Name(player), player));
for (tmp = qfirst; tmp; tmp = tmp->next)
if (GoodObject(tmp->player) &&
((tmp->player == player) || (Owner(tmp->player) == player))) {
num--;
giveto(player, QUEUE_COST);
tmp->player = NOTHING;
}
for (tmp = qlfirst; tmp; tmp = tmp->next)
if (GoodObject(tmp->player) &&
((tmp->player == player) || (Owner(tmp->player) == player))) {
num--;
giveto(player, QUEUE_COST);
tmp->player = NOTHING;
}
/* remove wait q stuff */
for (point = qwait; point; point = next) {
if (((point->player == player) || (Owner(point->player) == player))) {
num--;
giveto(player, QUEUE_COST);
if (trail)
trail->next = next = point->next;
else
qwait = next = point->next;
free_qentry(point);
} else
next = (trail = point)->next;
}
/* clear semaphore queue */
for (point = qsemfirst, trail = NULL; point; point = next) {
if (((point->player == player) || (Owner(point->player) == player))) {
num--;
giveto(player, QUEUE_COST);
if (trail)
trail->next = next = point->next;
else
qsemfirst = next = point->next;
if (point == qsemlast)
qsemlast = trail;
add_to_sem(point->sem, -1);
free_qentry(point);
} else
next = (trail = point)->next;
}
if (Owner(player) == player)
(void) atr_clr(player, "QUEUE", GOD);
else
add_to(player, num);
if (ncom && *ncom) {
int j;
for (j = 0; j < 10; j++) {
wnxt[j] = wenv[j];
rnxt[j] = renv[j];
}
parse_que(player, ncom, player);
}
}
void
do_halt1(player, arg1, arg2)
dbref player;
const char *arg1;
const char *arg2;
{
dbref victim;
if (*arg1 == '\0')
do_halt(player, "", player);
else {
if ((victim = noisy_match_result(player, arg1, NOTYPE, MAT_OBJECTS)) == NOTHING)
return;
if (!Owns(player, victim) && !HaltAny(player)) {
notify(player, "Permission denied.");
return;
}
if (arg2 && *arg2 && !controls(player, victim)) {
notify(player, "You may not use @halt obj=command on this object.");
return;
}
/* if not player and no new command provided, set it HALT */
if ((Typeof(victim) != TYPE_PLAYER) && (*arg2 == '\0')) {
Flags(victim) |= HALT;
}
if (Owner(victim) != player) {
if (Typeof(victim) == TYPE_PLAYER) {
notify(player, tprintf("All objects for %s have been halted.",
Name(victim)));
notify(victim, tprintf("All of your objects have been halted by %s.",
Name(player)));
} else {
notify(player, tprintf("Halted: %s's %s(#%d)",
Name(Owner(victim)), Name(victim),
victim));
notify(Owner(victim),
tprintf("Halted: %s(#%d), by %s", Name(victim),
victim, Name(player)));
}
} else {
if (victim == player)
notify(player, "All of your objects have been halted.");
else
notify(player, tprintf("Halted: %s(#%d)", Name(victim), victim));
}
do_halt(player, arg2, victim);
}
}
void
do_allhalt(player)
dbref player;
{
dbref victim;
if (!HaltAny(player)) {
notify(player, "You do not have the power to bring the world to a halt.");
return;
}
for (victim = 0; victim < db_top; victim++) {
if (Typeof(victim) == TYPE_PLAYER) {
notify(victim, tprintf("Your objects have been globally halted by %s",
Name(player)));
do_halt(victim, "", victim);
}
}
}
void
do_allrestart(player)
dbref player;
{
dbref thing;
ATTR *s;
char *r;
if (!HaltAny(player)) {
notify(player, "You do not have the power to restart the world.");
return;
}
do_allhalt(player);
for (thing = 0; thing < db_top; thing++) {
if (!Destroyed(thing) &&
(Flags(thing) & STARTUP) && !(Flags(thing) & HALT)) {
s = atr_get_noparent(thing, "STARTUP");
if (!s)
continue;
r = safe_uncompress(s->value);
parse_que(thing, r, thing);
free((Malloc_t) r);
}
if (Typeof(thing) == TYPE_PLAYER) {
notify(thing, tprintf("Your objects are being globally restarted by %s",
Name(player)));
}
}
}
static void
do_raw_restart(victim)
dbref victim;
{
ATTR *s;
char *r;
dbref thing;
if (Typeof(victim) == TYPE_PLAYER) {
for (thing = 0; thing < db_top; thing++) {
if ((Owner(thing) == victim) && !Destroyed(thing) &&
(Flags(thing) & STARTUP) && !(Flags(thing) & HALT)) {
s = atr_get_noparent(thing, "STARTUP");
if (!s)
continue;
r = safe_uncompress(s->value);
parse_que(thing, r, thing);
free((Malloc_t) r);
}
}
} else {
/* A single object */
if (!Destroyed(victim) &&
(Flags(victim) & STARTUP) && !(Flags(victim) & HALT)) {
s = atr_get_noparent(victim, "STARTUP");
if (!s)
return;
r = safe_uncompress(s->value);
parse_que(victim, r, victim);
free((Malloc_t) r);
}
}
}
void
do_restart_com(player, arg1)
dbref player;
const char *arg1;
{
dbref victim;
if (*arg1 == '\0') {
do_halt(player, "", player);
do_raw_restart(player);
} else {
if ((victim = noisy_match_result(player, arg1, NOTYPE, MAT_OBJECTS)) == NOTHING)
return;
if (!Owns(player, victim) && !HaltAny(player)) {
notify(player, "Permission denied.");
return;
}
if (Owner(victim) != player) {
if (Typeof(victim) == TYPE_PLAYER) {
notify(player, tprintf("All objects for %s are being restarted.",
Name(victim)));
notify(victim, tprintf("All of your objects are being restarted by %s.",
Name(player)));
} else {
notify(player, tprintf("Restarting: %s's %s(#%d)",
Name(Owner(victim)), Name(victim),
victim));
notify(Owner(victim),
tprintf("Restarting: %s(#%d), by %s", Name(victim),
victim, Name(player)));
}
} else {
if (victim == player)
notify(player, "All of your objects are being restarted.");
else
notify(player, tprintf("Restarting: %s(#%d)", Name(victim), victim));
}
do_halt(player, "", victim);
do_raw_restart(victim);
}
}