/* Cque.c */ #include <ctype.h> #include <fcntl.h> #include <string.h> #ifdef XENIX #include <sys/signal.h> #else #include <signal.h> #endif /* xenix */ #include "config.h" #include "db.h" #include "interface.h" #include "match.h" #include "externs.h" #ifdef MEM_CHECK #include "mem_check.h" #endif #ifdef USE_NALLOC #include "nalloc.h" extern NALLOC *glurp; NALLOC *big = NULL; #endif extern char ccom[]; extern dbref cplr; extern int atoi(); typedef struct bque BQUE; struct bque { BQUE *next; dbref player; /* player who will do command */ dbref cause; /* player causing command (for %N) */ int left; /* seconds left until execution */ char *env[10]; /* environment, from wild match */ char *comm; /* command to be executed */ }; static BQUE *qfirst = NULL, *qlast = NULL, *qwait = NULL; static BQUE *qlfirst = NULL, *qllast = NULL; void parse_que(player, command, cause) dbref player; char *command; dbref cause; /* cause is needed to determine priority */ { char buff[BUFFER_LEN], *s, *r; void big_que(); s = buff; strcpy(buff, command); while (r = parse_up(&s, ';')) { big_que(player, r, cause); } } static int add_to(player, am) dbref player; int am; { int num = 0; ATTR *a; char buff[MAX_COMMAND_LEN]; player = db[player].owner; a = atr_get(player, "QUEUE"); if(a) num = atoi(a->value); num += am; if (num > 0) sprintf(buff, "%d", num); else *buff = 0; (void) atr_add(player, "QUEUE", buff, GOD, NOTHING); return (num); } void big_que(player, command, cause) dbref player; char *command; dbref cause; { int a; BQUE *tmp; #ifdef USE_NALLOC if(!big) big = na_open(sizeof(char)); #endif if ((Typeof(player) != TYPE_PLAYER) && (db[player].flags & HALT)) return; /* make sure player can afford to do it */ if (!payfor(player, QUEUE_COST + (((random() & QUEUE_LOSS) == 0) ? 1 : 0))) { notify(db[player].owner, "Not enough money to queue command."); return; } if (add_to(player, 1) > QUEUE_QUOTA) { notify(db[player].owner, "Run away objects, commands halted"); do_halt(db[player].owner, ""); /* halt means no command execution allowed */ db[player].flags |= HALT; return; } #ifdef USE_NALLOC tmp = (BQUE *) na_alloc(big, sizeof(BQUE)); strcpy((tmp->comm = (char *) na_ualloc(big, strlen(command)+1)), command); #else tmp = (BQUE *) malloc (sizeof(BQUE)); strcpy((tmp->comm = (char *) malloc(strlen(command)+1)), command); #endif #ifdef MEM_CHECK add_check("bqueue"); add_check("bqueue_comm"); #endif tmp->player = player; tmp->next = NULL; tmp->left = 0; tmp->cause = cause; for (a = 0; a < 10; a++) if (!wptr[a]) tmp->env[a] = NULL; else { #ifdef USE_NALLOC strcpy((tmp->env[a] =(char *)na_ualloc(big, strlen(wptr[a])+1)),wptr[a]); #else strcpy((tmp->env[a] = (char *)malloc(strlen(wptr[a])+1)), wptr[a]); #endif #ifdef MEM_CHECK add_check("bqueue_env"); #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) dbref player; int wait; char *command; dbref cause; { BQUE *tmp; int a; /* make sure player can afford to do it */ if (!payfor(player, QUEUE_COST + (((random() & QUEUE_LOSS) == 0) ? 1 : 0))) { notify(player, "Not enough money to queue command."); return; } #ifdef USE_NALLOC tmp = (BQUE *) na_alloc(big, sizeof(BQUE)); strcpy((tmp->comm = (char *)na_ualloc(big, strlen(command)+1)), command); #else tmp = (BQUE *)malloc(sizeof(BQUE)); strcpy((tmp->comm = (char *)malloc(strlen(command)+1)), command); #endif #ifdef MEM_CHECK add_check("bqueue"); add_check("bqueue_comm"); #endif tmp->player = player; tmp->next = qwait; tmp->left = wait; tmp->cause = cause; for (a = 0; a < 10; a++) if (!wptr[a]) tmp->env[a] = NULL; else { #ifdef USE_NALLOC strcpy((tmp->env[a] = (char *)na_ualloc(big,strlen(wptr[a])+1)),wptr[a]); #else strcpy((tmp->env[a] = (char *)malloc(strlen(wptr[a])+1)), wptr[a]); #endif #ifdef MEM_CHECK add_check("bqueue_env"); #endif } qwait = tmp; } /* call every second to check for wait queue commands */ void do_second() { 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 affects on other objects happen only after one seconds */ /* this should allow @halt to be type before getting blown away */ /* by scrolling text */ if (qlfirst) { if (qlast) qlast->next = qlfirst; else qfirst = qlfirst; qlast = qllast; qllast = qlfirst = NULL; } for (point = qwait; point; point = next) /* * Note: this would be 0 except the command is being put in the low * priority queue to be done in one second anyways */ if (point->left-- <= 1) { int a; giveto(point->player, QUEUE_COST); for (a = 0; a < 10; a++) { wptr[a] = point->env[a]; } parse_que(point->player, point->comm, point->cause); if (trail) trail->next = next = point->next; else qwait = next = point->next; for (a = 0; a < 10; a++) if (point->env[a]) { #ifdef USE_NALLOC na_unalloc(big, point->env[a]); #else free((char *)point->env[a]); #endif #ifdef MEM_CHECK del_check("bqueue_env"); #endif } #ifdef USE_NALLOC if (point->comm) na_unalloc(big, point->comm); na_unalloc(big, point); #else if (point->comm) free((char *)point->comm); free((char *)point); #endif #ifdef MEM_CHECK del_check("bqueue_comm"); del_check("bqueue"); #endif } else next = (trail = point)->next; } int test_top() { return (qfirst ? 1 : 0); } /* execute one command off the top of the queue */ int do_top() { int a; int i = 0; BQUE *tmp; dbref player; char tbuf1[BUFFER_LEN], tbuf2[BUFFER_LEN]; char tbuf3[BUFFER_LEN], *s; if (!qfirst) return (0); if (qfirst->player && !(db[qfirst->player].flags & GOING)) { giveto(qfirst->player, QUEUE_COST); cplr = qfirst->player; strcpy(ccom, qfirst->comm); add_to(player = qfirst->player, -1); qfirst->player = 0; if ((Typeof(player) == TYPE_PLAYER) || !(db[player].flags & HALT)) { for (a = 0; a < 10; a++) { wptr[a] = qfirst->env[a]; } strcpy(tbuf2, uncompress(qfirst->comm)); tbuf3[0] = '\0'; for (s = tbuf2; *s; tbuf3[i++] = toupper(*s++)) ; tbuf3[i++] = '\0'; if ((strstr(tbuf3, "@DOL")) == NULL) strcpy(tbuf1, pronoun_substitute(qfirst->cause, tbuf2, player)); else strcpy(tbuf1, tbuf2); if (IS(player, TYPE_THING, THING_VERBOSE)) notify(db[player].owner, tprintf("#%d] %s", player, tbuf1)); process_command(player, tbuf1, qfirst->cause); } } tmp = qfirst->next; for (a = 0; a < 10; a++) if (qfirst->env[a]) { #ifdef USE_NALLOC na_unalloc(big, qfirst->env[a]); #else free((char *) qfirst->env[a]); #endif #ifdef MEM_CHECK del_check("bqueue_env"); #endif } #ifdef USE_NALLOC if (qfirst->comm) na_unalloc(big, qfirst->comm); na_unalloc(big, qfirst); #else if (qfirst->comm) free((char *)qfirst->comm); free((char *)qfirst); #endif #ifdef MEM_CHECK del_check("bqueue_comm"); del_check("bqueue"); #endif if (!(qfirst = tmp)) qlast = NULL; return (1); } /* tell player what commands they have pending in the queue */ void do_queue(player, what) dbref player; const char *what; { BQUE *tmp; dbref victim = NOTHING; int everything = 0; int quick = 0; int pq = 0, oq = 0, wq = 0; int tpq = 0, toq = 0, twq = 0; if (!string_compare(what, "count")) { victim = player; everything = 1; quick = 1; } else if(Wizard(player)) { if(!what || !*what) victim = player; else if(!string_compare(what, "all")) { /* do the whole thing */ victim = player; everything = 1; } else { init_match(player, what, TYPE_PLAYER); match_player(); match_absolute(); match_me(); victim = match_result(); } } 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(everything == 1) notify(player, "Queue for : all"); else notify(player, tprintf("Queue for : %s", db[victim].name)); if (!quick) notify(player,"Player Queue:"); for (tmp = qfirst; tmp; tmp = tmp->next) { tpq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { pq++; if (!quick) notify(player, tprintf("%s:%s", unparse_object(player, tmp->player), tmp->comm)); } } if (!quick) notify(player,"Object Queue:"); for (tmp = qlfirst; tmp; tmp = tmp->next) { toq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { oq++; if (!quick) notify(player, tprintf("%s:%s", unparse_object(player, tmp->player), tmp->comm)); } } if (!quick) notify(player,"Wait Queue:"); for (tmp = qwait; tmp; tmp = tmp->next) { twq++; if ((db[tmp->player].owner == db[victim].owner) || (everything)) { wq++; if (!quick) notify(player, tprintf("[%d]%s:%s", tmp->left, unparse_object(player, tmp->player), tmp->comm)); } } notify(player,"------------ Queue Done ------------"); notify(player, tprintf("Totals: Player...%d/%d Object...%d/%d Wait...%d/%d", pq, tpq, oq, toq, wq, twq)); } } /* remove all queued commands from a certain player */ /* it cannot be called on specific objects */ void do_halt(player, ncom) dbref player; char *ncom; { BQUE *tmp, *trail = NULL, *point, *next; int num = 0; notify(db[player].owner, "Halted."); for (tmp = qfirst; tmp; tmp = tmp->next) if ((tmp->player == player) || (db[tmp->player].owner == player)) { num--; giveto(player, QUEUE_COST); tmp->player = 0; } for (tmp = qlfirst; tmp; tmp = tmp->next) if ((tmp->player == player) || (db[tmp->player].owner == player)) { num--; giveto(player, QUEUE_COST); tmp->player = 0; } /* remove wait q stuff */ for (point = qwait; point; point = next) if ((point->player == player) || (db[point->player].owner == player)) { int a; giveto(player, QUEUE_COST); if (trail) trail->next = next = point->next; else qwait = next = point->next; for (a = 0; a < 10; a++) if (point->env[a]) { #ifdef USE_NALLOC na_unalloc(big, point->env[a]); #else free((char *)point->env[a]); #endif #ifdef MEM_CHECK del_check("bqueue_env"); #endif } #ifdef USE_NALLOC if (point->comm) na_unalloc(big, point->comm); na_unalloc(big, point); #else if (point->comm) free((char *) point->comm); free((char *) point); #endif #ifdef MEM_CHECK del_check("bqueue_comm"); del_check("bqueue"); #endif } else next = (trail = point)->next; if (db[player].owner == player) (void) atr_add(player, "QUEUE", "", GOD, NOTHING); else add_to(player, num); if (*ncom) parse_que(player, ncom, player); } void do_halt1(player, arg1, arg2) dbref player; const char *arg1; const char *arg2; { dbref victim; char temp[BUFFER_LEN]; if (*arg1 == '\0') do_halt(player, ""); else { init_match(player, arg1, NOTYPE); match_neighbor(); match_possession(); match_me(); match_absolute(); match_player(); if ((victim = noisy_match_result()) == NOTHING) return; if ((db[victim].owner != player) && (!Wizard(player))) { notify(player, "Permission denied."); return; } if (Typeof(victim) != TYPE_PLAYER) { sprintf(temp, "#%d", victim); do_set(player, temp, "HALT"); } else { if (victim != player) notify(player, "Halted."); do_halt(victim, arg2); } } } void do_allhalt(player) dbref player; { dbref victim; if(!Wizard(player)) { notify(player, "Sorry, you can only halt your own items."); return; } for(victim = 0;victim <db_top; victim++) { if(Typeof(victim) == TYPE_PLAYER) { notify(victim,tprintf("Your objects have been globally halted by %s", db[player].name)); do_halt(victim,""); } } }