00001 #include "copyright.h"
00002 #include "config.h"
00003
00004 #include <signal.h>
00005 #include "mudconf.h"
00006 #include "config.h"
00007 #include "db.h"
00008 #include "interface.h"
00009 #include "externs.h"
00010 #include "match.h"
00011 #include "command.h"
00012 #include "alloc.h"
00013 #include "attrs.h"
00014 #include "powers.h"
00015 #include "ansi.h"
00016 #include "patchlevel.h"
00017 #include "htab.h"
00018
00019 extern dbref match_thing(dbref, char *);
00020 extern int do_command(DESC *, char *);
00021 extern void dump_database(void);
00022 extern void dump_restart_db(void);
00023
00024 #ifdef NEED_VSPRINTF_DCL
00025 extern char *vsprintf(char *, char *, va_list);
00026
00027 #endif
00028
00029 #ifdef STDC_HEADERS
00030 char *tprintf(const char *format, ...)
00031 #else
00032 char *tprintf(va_alist)
00033 va_dcl
00034 #endif
00035 {
00036 static char buff[LBUF_SIZE];
00037 va_list ap;
00038
00039 #ifdef STDC_HEADERS
00040 va_start(ap, format);
00041 #else
00042 const char *format;
00043
00044 va_start(ap);
00045 format = va_arg(ap, char *);
00046
00047 #endif
00048 vsnprintf(buff, LBUF_SIZE, format, ap);
00049 va_end(ap);
00050 buff[LBUF_SIZE - 1] = '\0';
00051 return buff;
00052 }
00053
00054 #ifdef STDC_HEADERS
00055 void safe_tprintf_str(char *str, char **bp, const char *format, ...)
00056 #else
00057 void safe_tprintf_str(va_alist)
00058 va_dcl
00059 #endif
00060 {
00061 static char buff[LBUF_SIZE];
00062 va_list ap;
00063
00064 #ifdef STDC_HEADERS
00065 va_start(ap, format);
00066 #else
00067 char *str;
00068 char **bp;
00069 const char *format;
00070
00071 va_start(ap);
00072 str = va_arg(ap, char *);
00073 bp = va_arg(ap, char **);
00074 format = va_arg(ap, char *);
00075
00076 #endif
00077
00078
00079
00080
00081 vsnprintf(buff, LBUF_SIZE, format, ap);
00082 va_end(ap);
00083 buff[LBUF_SIZE - 1] = '\0';
00084 safe_str(buff, str, bp);
00085 **bp = '\0';
00086 }
00087
00091 dbref insert_first(dbref head, dbref thing)
00092 {
00093 s_Next(thing, head);
00094 return thing;
00095 }
00096
00097
00098
00099
00100 dbref remove_first(dbref head, dbref thing)
00101 {
00102 dbref prev;
00103
00104 if(head == thing)
00105 return (Next(thing));
00106
00107 DOLIST(prev, head) {
00108 if(Next(prev) == thing) {
00109 s_Next(prev, Next(thing));
00110 return head;
00111 }
00112 }
00113 return head;
00114 }
00115
00119 dbref reverse_list(dbref list)
00120 {
00121 dbref newlist, rest;
00122
00123 newlist = NOTHING;
00124 while (list != NOTHING) {
00125 rest = Next(list);
00126 s_Next(list, newlist);
00127 newlist = list;
00128 list = rest;
00129 }
00130 return newlist;
00131 }
00132
00136 int member(dbref thing, dbref list)
00137 {
00138 DOLIST(list, list) {
00139 if(list == thing)
00140 return 1;
00141 }
00142 return 0;
00143 }
00144
00148 int is_integer(char *str)
00149 {
00150 while (*str && isspace(*str))
00151 str++;
00152
00153
00154 if(*str == '-') {
00155
00156
00157 str++;
00158 if(!*str)
00159 return 0;
00160
00161
00162 }
00163 if(!isdigit(*str))
00164
00165
00166 return 0;
00167 while (*str && isdigit(*str))
00168 str++;
00169
00170
00171 while (*str && isspace(*str))
00172 str++;
00173
00174
00175 return (*str ? 0 : 1);
00176 }
00177
00181 int is_number(char *str)
00182 {
00183 int got_one;
00184
00185 while (*str && isspace(*str))
00186 str++;
00187
00188
00189 if(*str == '-') {
00190
00191
00192 str++;
00193 if(!*str)
00194 return 0;
00195
00196
00197 }
00198 got_one = 0;
00199 if(isdigit(*str))
00200 got_one = 1;
00201
00202
00203 while (*str && isdigit(*str))
00204 str++;
00205
00206
00207 if(*str == '.')
00208 str++;
00209
00210
00211 if(isdigit(*str))
00212 got_one = 1;
00213
00214
00215 while (*str && isdigit(*str))
00216 str++;
00217
00218
00219 while (*str && isspace(*str))
00220 str++;
00221
00222
00223 return ((*str || !got_one) ? 0 : 1);
00224 }
00225
00226 int could_doit(dbref player, dbref thing, int locknum)
00227 {
00228 char *key;
00229 dbref aowner;
00230 int aflags, doit;
00231
00232
00233
00234
00235
00236 if(!isPlayer(player) && Key(thing)) {
00237 return 0;
00238 }
00239 if(Pass_Locks(player))
00240 return 1;
00241
00242 key = atr_get(thing, locknum, &aowner, &aflags);
00243 doit = eval_boolexp_atr(player, thing, thing, key);
00244 free_lbuf(key);
00245 return doit;
00246 }
00247
00248 int can_see(dbref player, dbref thing, int can_see_loc)
00249 {
00250
00251
00252
00253
00254
00255
00256
00257 if(mudconf.dark_sleepers && isPlayer(thing) && !Connected(thing) &&
00258 !Puppet(thing)) {
00259 return 0;
00260 }
00261
00262
00263
00264
00265 if((player == thing) || isExit(thing)) {
00266 return 0;
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 if(can_see_loc) {
00277 return (!Dark(thing) || (mudconf.see_own_dark &&
00278 MyopicExam(player, thing)));
00279 } else {
00280 return ((Light(thing) && !Dark(thing)) || (mudconf.see_own_dark &&
00281 MyopicExam(player,
00282 thing)));
00283 }
00284 }
00285
00286 static int pay_quota(dbref who, int cost)
00287 {
00288 dbref aowner;
00289 int quota, aflags;
00290 char buf[20], *quota_str;
00291
00292
00293
00294
00295
00296 if(cost <= 0)
00297 return 1;
00298
00299
00300
00301
00302
00303 quota = atoi(quota_str = atr_get(Owner(who), A_RQUOTA, &aowner, &aflags));
00304 free_lbuf(quota_str);
00305
00306
00307
00308
00309
00310 quota -= cost;
00311 if((quota < 0) && !Free_Quota(who) && !Free_Quota(Owner(who)))
00312 return 0;
00313
00314
00315
00316
00317 sprintf(buf, "%d", quota);
00318 atr_add_raw(Owner(who), A_RQUOTA, buf);
00319
00320 return 1;
00321 }
00322
00323 int canpayfees(dbref player, dbref who, int pennies, int quota)
00324 {
00325 if(!Wizard(who) && !Wizard(Owner(who)) && !Free_Money(who) &&
00326 !Free_Money(Owner(who)) && (Pennies(Owner(who)) < pennies)) {
00327 if(player == who) {
00328 notify_printf(player, "Sorry, you don't have enough %s.",
00329 mudconf.many_coins);
00330 } else {
00331 notify_printf(player,
00332 "Sorry, that player doesn't have enough %s.",
00333 mudconf.many_coins);
00334 }
00335 return 0;
00336 }
00337 if(mudconf.quotas) {
00338 if(!pay_quota(who, quota)) {
00339 if(player == who) {
00340 notify(player, "Sorry, your building contract has run out.");
00341 } else {
00342 notify(player,
00343 "Sorry, that player's building contract has run out.");
00344 }
00345 return 0;
00346 }
00347 }
00348 payfor(who, pennies);
00349 return 1;
00350 }
00351
00352 int payfor(dbref who, int cost)
00353 {
00354 dbref tmp;
00355
00356 if(Wizard(who) || Wizard(Owner(who)) || Free_Money(who) ||
00357 Free_Money(Owner(who)) || Immortal(who) || Immortal(Owner(who))) {
00358 return 1;
00359 }
00360 who = Owner(who);
00361 if((tmp = Pennies(who)) >= cost) {
00362 s_Pennies(who, tmp - cost);
00363 return 1;
00364 }
00365 return 0;
00366 }
00367
00368 void add_quota(dbref who, int payment)
00369 {
00370 dbref aowner;
00371 int aflags;
00372 char buf[20], *quota;
00373
00374 quota = atr_get(who, A_RQUOTA, &aowner, &aflags);
00375 sprintf(buf, "%d", atoi(quota) + payment);
00376 free_lbuf(quota);
00377 atr_add_raw(who, A_RQUOTA, buf);
00378 }
00379
00383 void giveto(dbref who, int pennies)
00384 {
00385 if(Wizard(who) || Wizard(Owner(who)) || Free_Money(who) ||
00386 Free_Money(Owner(who)) || Immortal(who) || Immortal(Owner(who))) {
00387 return;
00388 }
00389 who = Owner(who);
00390 s_Pennies(who, Pennies(who) + pennies);
00391 }
00392
00393 int ok_name(const char *name)
00394 {
00395 const char *cp;
00396 char new[LBUF_SIZE];
00397
00398
00399 strncpy(new, name, LBUF_SIZE-1);
00400 if(strlen(strip_ansi_r(new,name,strlen(name))) == 0)
00401 return 0;
00402
00403
00404
00405 if(isspace(*name))
00406 return 0;
00407
00408
00409
00410
00411
00412 for(cp = name; cp && *cp; cp++) {
00413 if((!isprint(*cp)) && (*cp != ESC_CHAR))
00414 return 0;
00415 }
00416
00417
00418
00419
00420 cp--;
00421 if(isspace(*cp))
00422 return 0;
00423
00424
00425
00426
00427
00428 return (name && *name && *name != LOOKUP_TOKEN && *name != NUMBER_TOKEN
00429 && *name != NOT_TOKEN && !index(name, ARG_DELIMITER) &&
00430 !index(name, AND_TOKEN) && !index(name, OR_TOKEN) &&
00431 string_compare(name, "me") && string_compare(name, "home") &&
00432 string_compare(name, "here"));
00433 }
00434
00435 int ok_player_name(const char *name)
00436 {
00437 const char *cp, *good_chars;
00438
00439
00440
00441
00442
00443 if(isspace(*name))
00444 return 0;
00445
00446
00447
00448
00449
00450 if(!ok_name(name) || (strlen(name) >= PLAYER_NAME_LIMIT))
00451 return 0;
00452
00453 if(mudconf.name_spaces)
00454 good_chars = " `$_-.,'";
00455 else
00456 good_chars = "`$_-.,'";
00457
00458
00459
00460
00461
00462 for(cp = name; cp && *cp; cp++) {
00463 if(isalnum(*cp))
00464 continue;
00465 if((!index(good_chars, *cp)) || (*cp == ESC_CHAR))
00466 return 0;
00467 }
00468 return 1;
00469 }
00470
00471 int ok_attr_name(const char *attrname)
00472 {
00473 const char *scan;
00474
00475 if(!isalpha(*attrname))
00476 return 0;
00477 for(scan = attrname; *scan; scan++) {
00478 if(isalnum(*scan))
00479 continue;
00480 if(!(index("'?!`/-_.@#$^&~=+<>()%", *scan)))
00481 return 0;
00482 }
00483 return 1;
00484 }
00485
00486 int ok_password(const char *password)
00487 {
00488 const char *scan;
00489
00490 if(*password == '\0')
00491 return 0;
00492
00493 for(scan = password; *scan; scan++) {
00494 if(!(isprint(*scan) && !isspace(*scan))) {
00495 return 0;
00496 }
00497 }
00498
00499
00500
00501
00502 if((strlen(password) == 13) && (password[0] == 'X') &&
00503 (password[1] == 'X'))
00504 return 0;
00505
00506 return 1;
00507 }
00508
00512 void handle_ears(dbref thing, int could_hear, int can_hear)
00513 {
00514 char *buff, *bp;
00515 int gender;
00516 static const char *poss[5] = { "", "its", "her", "his", "their" };
00517
00518 if(!could_hear && can_hear) {
00519 buff = alloc_lbuf("handle_ears.grow");
00520 StringCopy(buff, Name(thing));
00521 if(isExit(thing)) {
00522 for(bp = buff; *bp && (*bp != ';'); bp++);
00523 *bp = '\0';
00524 }
00525 gender = get_gender(thing);
00526 notify_checked(thing, thing,
00527 tprintf("%s grow%s ears and can now hear.", buff,
00528 (gender == 4) ? "" : "s"),
00529 (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00530 free_lbuf(buff);
00531 } else if(could_hear && !can_hear) {
00532 buff = alloc_lbuf("handle_ears.lose");
00533 StringCopy(buff, Name(thing));
00534 if(isExit(thing)) {
00535 for(bp = buff; *bp && (*bp != ';'); bp++);
00536 *bp = '\0';
00537 }
00538 gender = get_gender(thing);
00539 notify_checked(thing, thing,
00540 tprintf("%s lose%s %s ears and become%s deaf.", buff,
00541 (gender == 4) ? "" : "s", poss[gender],
00542 (gender == 4) ? "" : "s"),
00543 (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00544 free_lbuf(buff);
00545 }
00546 }
00547
00548
00549
00550
00551 void do_switch(dbref player, dbref cause, int key, char *expr, char *args[],
00552 int nargs, char *cargs[], int ncargs)
00553 {
00554 int a, any;
00555 char *buff, *bp, *str;
00556
00557 if(!expr || (nargs <= 0))
00558 return;
00559
00560 if(key == SWITCH_DEFAULT) {
00561 if(mudconf.switch_df_all)
00562 key = SWITCH_ANY;
00563 else
00564 key = SWITCH_ONE;
00565 }
00566
00567
00568
00569
00570 any = 0;
00571 buff = bp = alloc_lbuf("do_switch");
00572 for(a = 0; (a < (nargs - 1)) && args[a] && args[a + 1]; a += 2) {
00573 bp = buff;
00574 str = args[a];
00575 exec(buff, &bp, 0, player, cause, EV_FCHECK | EV_EVAL | EV_TOP,
00576 &str, cargs, ncargs);
00577 *bp = '\0';
00578 if(wild_match(buff, expr)) {
00579 wait_que(player, cause, 0, NOTHING, 0, args[a + 1], cargs,
00580 ncargs, mudstate.global_regs);
00581 if(key == SWITCH_ONE) {
00582 free_lbuf(buff);
00583 return;
00584 }
00585 any = 1;
00586 }
00587 }
00588 free_lbuf(buff);
00589 if((a < nargs) && !any && args[a])
00590 wait_que(player, cause, 0, NOTHING, 0, args[a], cargs, ncargs,
00591 mudstate.global_regs);
00592 }
00593
00594 void do_addcommand(dbref player, dbref cause, int key, char *name,
00595 char *command)
00596 {
00597 CMDENT *old, *cmd;
00598 ADDENT *add, *nextp;
00599
00600 dbref thing;
00601 int atr;
00602 char *s;
00603
00604 if(!*name) {
00605 notify(player, "Sorry.");
00606 return;
00607 }
00608 if(!parse_attrib(player, command, &thing, &atr) || (atr == NOTHING)) {
00609 notify(player, "No such attribute.");
00610 return;
00611 }
00612
00613
00614
00615 for(s = name; *s; s++) {
00616 *s = tolower(*s);
00617 }
00618
00619 old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00620
00621 if(old && (old->callseq & CS_ADDED)) {
00622
00623
00624
00625
00626 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00627 nextp = nextp->next) {
00628 if((nextp->thing == thing) && (nextp->atr == atr)) {
00629 notify_printf(player, "%s already added.", name);
00630 return;
00631 }
00632 }
00633
00634
00635
00636 add = (ADDENT *) malloc(sizeof(ADDENT));
00637 add->thing = thing;
00638 add->atr = atr;
00639 add->name = (char *) strdup(name);
00640 add->next = (ADDENT *) old->handler;
00641 old->handler = (void *) add;
00642 } else {
00643 if(old) {
00644
00645 hashdelete(name, &mudstate.command_htab);
00646 }
00647
00648 cmd = (CMDENT *) malloc(sizeof(CMDENT));
00649
00650 cmd->cmdname = (char *) strdup(name);
00651 cmd->switches = NULL;
00652 cmd->perms = 0;
00653 cmd->extra = 0;
00654 if(old && (old->callseq & CS_LEADIN)) {
00655 cmd->callseq = CS_ADDED | CS_ONE_ARG | CS_LEADIN;
00656 } else {
00657 cmd->callseq = CS_ADDED | CS_ONE_ARG;
00658 }
00659 add = (ADDENT *) malloc(sizeof(ADDENT));
00660 add->thing = thing;
00661 add->atr = atr;
00662 add->name = (char *) strdup(name);
00663 add->next = NULL;
00664 cmd->handler = (void *) add;
00665
00666 hashadd(name, (int *) cmd, &mudstate.command_htab);
00667
00668 if(old) {
00669
00670 hashreplall((int *) old, (int *) cmd, &mudstate.command_htab);
00671 hashadd(tprintf("__%s", name), (int *) old,
00672 &mudstate.command_htab);
00673 }
00674 }
00675
00676
00677
00678 set_prefix_cmds();
00679 notify_printf(player, "%s added.", name);
00680 }
00681
00682 void do_listcommands(dbref player, dbref cause, int key, char *name)
00683 {
00684 CMDENT *old;
00685 ADDENT *nextp;
00686 int didit = 0;
00687
00688 char *s, *keyname;
00689
00690
00691
00692 for(s = name; *s; s++) {
00693 *s = tolower(*s);
00694 }
00695
00696 if(*name) {
00697 old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00698
00699 if(old && (old->callseq & CS_ADDED)) {
00700
00701
00702
00703
00704 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00705 nextp = nextp->next) {
00706 notify_printf(player, "%s: #%d/%s", nextp->name,
00707 nextp->thing,
00708 ((ATTR *) atr_num(nextp->atr))->name);
00709 }
00710 } else {
00711 notify_printf(player, "%s not found in command table.", name);
00712 }
00713 return;
00714 } else {
00715 for(keyname = hash_firstkey(&mudstate.command_htab);
00716 keyname != NULL; keyname = hash_nextkey(&mudstate.command_htab)) {
00717
00718 old = (CMDENT *) hashfind(keyname, &mudstate.command_htab);
00719
00720 if(old && (old->callseq & CS_ADDED)) {
00721
00722 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00723 nextp = nextp->next) {
00724 if(strcmp(keyname, nextp->name))
00725 continue;
00726 notify_printf(player, "%s: #%d/%s", nextp->name,
00727 nextp->thing,
00728 ((ATTR *) atr_num(nextp->atr))->name);
00729 didit = 1;
00730 }
00731 }
00732 }
00733 }
00734 if(!didit)
00735 notify(player, "No added commands found in command table.");
00736 }
00737
00738 void do_delcommand(dbref player, dbref cause, int key, char *name,
00739 char *command)
00740 {
00741 CMDENT *old, *cmd;
00742 ADDENT *prev = NULL, *nextp;
00743
00744 dbref thing;
00745 int atr;
00746 char *s;
00747
00748 if(!*name) {
00749 notify(player, "Sorry.");
00750 return;
00751 }
00752
00753 if(*command) {
00754 if(!parse_attrib(player, command, &thing, &atr) || (atr == NOTHING)) {
00755 notify(player, "No such attribute.");
00756 return;
00757 }
00758 }
00759
00760
00761
00762 for(s = name; *s; s++) {
00763 *s = tolower(*s);
00764 }
00765
00766 old = (CMDENT *) hashfind(name, &mudstate.command_htab);
00767
00768 if(old && (old->callseq & CS_ADDED)) {
00769 if(!*command) {
00770 for(prev = (ADDENT *) old->handler; prev != NULL; prev = nextp) {
00771 nextp = prev->next;
00772
00773 free(prev->name);
00774 free(prev);
00775 }
00776 hashdelete(name, &mudstate.command_htab);
00777 if((cmd =
00778 (CMDENT *) hashfind(tprintf("__%s", name),
00779 &mudstate.command_htab)) != NULL) {
00780 hashdelete(tprintf("__%s", name), &mudstate.command_htab);
00781 hashadd(name, (int *) cmd, &mudstate.command_htab);
00782 hashreplall((int *) old, (int *) cmd, &mudstate.command_htab);
00783 }
00784 free(old);
00785 set_prefix_cmds();
00786 notify(player, "Done.");
00787 return;
00788 } else {
00789 for(nextp = (ADDENT *) old->handler; nextp != NULL;
00790 nextp = nextp->next) {
00791 if((nextp->thing == thing) && (nextp->atr == atr)) {
00792
00793 free(nextp->name);
00794 if(!prev) {
00795 if(!nextp->next) {
00796 hashdelete(name, &mudstate.command_htab);
00797 if((cmd =
00798 (CMDENT *) hashfind(tprintf("__%s",
00799 name),
00800 &mudstate.
00801 command_htab)) != NULL) {
00802 hashdelete(tprintf("__%s", name),
00803 &mudstate.command_htab);
00804 hashadd(name, (int *) cmd,
00805 &mudstate.command_htab);
00806 hashreplall((int *) old, (int *) cmd,
00807 &mudstate.command_htab);
00808 }
00809 free(old);
00810 } else {
00811 old->handler = (void *) nextp->next;
00812 free(nextp);
00813 }
00814 } else {
00815 prev->next = nextp->next;
00816 free(nextp);
00817 }
00818 set_prefix_cmds();
00819 notify(player, "Done.");
00820 return;
00821 }
00822 prev = nextp;
00823 }
00824 notify(player, "Command not found in command table.");
00825 }
00826 } else {
00827 notify(player, "Command not found in command table.");
00828 }
00829 }
00830
00837 void handle_prog(DESC * d, char *message)
00838 {
00839 DESC *all;
00840 char *cmd;
00841 dbref aowner;
00842 int aflags, i;
00843
00844
00845
00846
00847
00848 if(*message == '|') {
00849 do_command(d, message + 1);
00850
00851 if(d->program_data != NULL)
00852 queue_string(d, tprintf("%s>%s \377\371", ANSI_HILITE,
00853 ANSI_NORMAL));
00854 return;
00855 }
00856 cmd = atr_get(d->player, A_PROGCMD, &aowner, &aflags);
00857 wait_que(d->program_data->wait_cause, d->player, 0, NOTHING, 0, cmd,
00858 (char **) &message, 1, (char **) d->program_data->wait_regs);
00859
00860
00861
00862
00863 all = (DESC *) rb_find(mudstate.desctree, (void *) d->player);
00864
00865 for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00866 free_lbuf(all->program_data->wait_regs[i]);
00867 }
00868 free(all->program_data);
00869
00870
00871
00872 DESC_ITER_PLAYER(d->player, all)
00873 all->program_data = NULL;
00874
00875 atr_clr(d->player, A_PROGCMD);
00876 free_lbuf(cmd);
00877 }
00878
00879 void do_quitprog(dbref player, dbref cause, int key, char *name)
00880 {
00881 DESC *d;
00882 dbref doer;
00883 int i, isprog = 0;
00884
00885 if(*name) {
00886 doer = match_thing(player, name);
00887 } else {
00888 doer = player;
00889 }
00890
00891 if(!(Prog(player) || Prog(Owner(player))) && (player != doer)) {
00892 notify(player, "Permission denied.");
00893 return;
00894 }
00895 if(!isPlayer(doer) || !Good_obj(doer)) {
00896 notify(player, "That is not a player.");
00897 return;
00898 }
00899 if(!Connected(doer)) {
00900 notify(player, "That player is not connected.");
00901 return;
00902 }
00903 DESC_ITER_PLAYER(doer, d) {
00904 if(d->program_data != NULL) {
00905 isprog = 1;
00906 }
00907 }
00908
00909 if(!isprog) {
00910 notify(player, "Player is not in an @program.");
00911 return;
00912 }
00913
00914 d = (DESC *) rb_find(mudstate.desctree, &doer);
00915
00916 for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00917 free_lbuf(d->program_data->wait_regs[i]);
00918 }
00919 free(d->program_data);
00920
00921
00922
00923 DESC_ITER_PLAYER(doer, d)
00924 d->program_data = NULL;
00925
00926 atr_clr(doer, A_PROGCMD);
00927 notify(player, "@program cleared.");
00928 notify(doer, "Your @program has been terminated.");
00929 }
00930
00931 void do_prog(dbref player, dbref cause, int key, char *name, char *command)
00932 {
00933 DESC *d;
00934 PROG *program;
00935 int i, atr, aflags;
00936 dbref doer, thing, aowner;
00937 ATTR *ap;
00938 char *attrib, *msg;
00939
00940 if(!name || !*name) {
00941 notify(player, "No players specified.");
00942 return;
00943 }
00944 doer = match_thing(player, name);
00945
00946 if(!(Prog(player) || Prog(Owner(player))) && (player != doer)) {
00947 notify(player, "Permission denied.");
00948 return;
00949 }
00950 if(!isPlayer(doer) || !Good_obj(doer)) {
00951 notify(player, "That is not a player.");
00952 return;
00953 }
00954 if(!Connected(doer)) {
00955 notify(player, "That player is not connected.");
00956 return;
00957 }
00958 msg = command;
00959 attrib = parse_to(&msg, ':', 1);
00960
00961 if(msg && *msg) {
00962 notify(doer, msg);
00963 }
00964 parse_attrib(player, attrib, &thing, &atr);
00965 if(atr != NOTHING) {
00966 if(!atr_get_info(thing, atr, &aowner, &aflags)) {
00967 notify(player, "Attribute not present on object.");
00968 return;
00969 }
00970 ap = atr_num(atr);
00971 if(God(player) || (!God(thing) &&
00972 See_attr(player, thing, ap, aowner, aflags) &&
00973 (Wizard(player) || (aowner == Owner(player))))) {
00974 atr_add_raw(doer, A_PROGCMD, atr_get_raw(thing, atr));
00975 } else {
00976 notify(player, "Permission denied.");
00977 return;
00978 }
00979 } else {
00980 notify(player, "No such attribute.");
00981 return;
00982 }
00983
00984
00985
00986
00987 DESC_ITER_PLAYER(doer, d) {
00988 if(d->program_data != NULL) {
00989 notify(player, "Input already pending.");
00990 return;
00991 }
00992 }
00993
00994 program = (PROG *) malloc(sizeof(PROG));
00995 program->wait_cause = player;
00996 for(i = 0; i < MAX_GLOBAL_REGS; i++) {
00997 program->wait_regs[i] = alloc_lbuf("prog_regs");
00998 StringCopy(program->wait_regs[i], mudstate.global_regs[i]);
00999 }
01000
01001
01002
01003
01004 DESC_ITER_PLAYER(doer, d) {
01005 d->program_data = program;
01006
01007
01008
01009
01010 queue_string(d, tprintf("%s>%s \377\371", ANSI_HILITE, ANSI_NORMAL));
01011 }
01012
01013 }
01014
01018 void do_restart(dbref player, dbref cause, int key)
01019 {
01020 if(key && mudstate.dumping) {
01021 notify(player, "Dumping. Please try again later.");
01022 return;
01023 }
01024
01025 ResetSpecialObjects();
01026 raw_broadcast(0, "Game: Restart by %s, please wait.",
01027 Name(Owner(player)));
01028 shutdown_services();
01029
01030 STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT") {
01031 log_text((char *) "Restart by ");
01032 log_name(player);
01033 ENDLOG;
01034 } dump_database_internal(DUMP_RESTART);
01035
01036 dump_restart_db();
01037 dump_restart_db_xdr();
01038 execl(mudstate.executable_path, mudstate.executable_path,
01039 mudconf.config_file, NULL);
01040 }
01041
01045 void do_comment(dbref player, dbref cause, int key)
01046 {
01047 }
01048
01049 static dbref promote_dflt(dbref old, dbref new)
01050 {
01051 switch (new) {
01052 case NOPERM:
01053 return NOPERM;
01054 case AMBIGUOUS:
01055 if(old == NOPERM)
01056 return old;
01057 else
01058 return new;
01059 }
01060
01061 if((old == NOPERM) || (old == AMBIGUOUS))
01062 return old;
01063
01064 return NOTHING;
01065 }
01066
01067 dbref match_possessed(dbref player, dbref thing, char *target, dbref dflt,
01068 int check_enter)
01069 {
01070 dbref result, result1;
01071 int control;
01072 char *buff, *start, *place, *s1, *d1, *temp;
01073
01074
01075
01076
01077
01078 if(Good_obj(dflt))
01079 return dflt;
01080
01081
01082
01083
01084
01085 start = target;
01086 while (*target) {
01087
01088
01089
01090
01091
01092 place = target;
01093 target = (char *) index(place, '\'');
01094 if((target == NULL) || !*target)
01095 return dflt;
01096
01097
01098
01099
01100
01101 if(place == target) {
01102 target++;
01103 continue;
01104 }
01105
01106
01107
01108
01109 temp = target++;
01110 if(!*target)
01111 return dflt;
01112 if((*target != 's') && (*target != 'S') && (*target != ' '))
01113 continue;
01114
01115
01116
01117
01118
01119
01120
01121 if(*target != ' ') {
01122 target++;
01123 if(!*target)
01124 return dflt;
01125 if(*target != ' ')
01126 continue;
01127 }
01128
01129
01130
01131
01132
01133 buff = alloc_lbuf("is_posess");
01134 for(s1 = start, d1 = buff; *s1 && (s1 < temp); *d1++ = (*s1++));
01135 *d1 = '\0';
01136
01137
01138
01139
01140
01141
01142 init_match(thing, buff, NOTYPE);
01143 if(player == thing) {
01144 match_neighbor();
01145 match_possession();
01146 } else {
01147 match_possession();
01148 }
01149 result1 = match_result();
01150
01151 free_lbuf(buff);
01152 if(!Good_obj(result1)) {
01153 dflt = promote_dflt(dflt, result1);
01154 continue;
01155 }
01156
01157
01158
01159
01160
01161 control = Controls(player, result1);
01162 if((Dark(result1) || Opaque(result1)) && !control) {
01163 dflt = promote_dflt(dflt, NOTHING);
01164 continue;
01165 }
01166
01167
01168
01169
01170 if((check_enter) && !Enter_ok(result1) && !control) {
01171 dflt = promote_dflt(dflt, NOPERM);
01172 continue;
01173 }
01174
01175
01176
01177
01178 init_match(result1, target, NOTYPE);
01179 match_possession();
01180 result = match_result();
01181 result =
01182 match_possessed(player, result1, target, result, check_enter);
01183 if(Good_obj(result))
01184 return result;
01185 dflt = promote_dflt(dflt, result);
01186 }
01187 return dflt;
01188 }
01189
01193 void parse_range(char **name, dbref * low_bound, dbref * high_bound)
01194 {
01195 char *buff1, *buff2;
01196
01197 buff1 = *name;
01198 if(buff1 && *buff1)
01199 *name = parse_to(&buff1, ',', EV_STRIP_TS);
01200 if(buff1 && *buff1) {
01201 buff2 = parse_to(&buff1, ',', EV_STRIP_TS);
01202 if(buff1 && *buff1) {
01203 while (*buff1 && isspace(*buff1))
01204 buff1++;
01205 if(*buff1 == NUMBER_TOKEN)
01206 buff1++;
01207 *high_bound = atoi(buff1);
01208 if(*high_bound >= mudstate.db_top)
01209 *high_bound = mudstate.db_top - 1;
01210 } else {
01211 *high_bound = mudstate.db_top - 1;
01212 }
01213 while (*buff2 && isspace(*buff2))
01214 buff2++;
01215 if(*buff2 == NUMBER_TOKEN)
01216 buff2++;
01217 *low_bound = atoi(buff2);
01218 if(*low_bound < 0)
01219 *low_bound = 0;
01220 } else {
01221 *low_bound = 0;
01222 *high_bound = mudstate.db_top - 1;
01223 }
01224 }
01225
01226 int parse_thing_slash(dbref player, char *thing, char **after, dbref * it)
01227 {
01228 char *str;
01229
01230
01231
01232
01233 for(str = thing; *str && (*str != '/'); str++);
01234
01235
01236
01237
01238
01239 if(!*str) {
01240 *after = NULL;
01241 *it = NOTHING;
01242 return 0;
01243 }
01244 *str++ = '\0';
01245 *after = str;
01246
01247
01248
01249
01250
01251 init_match(player, thing, NOTYPE);
01252 match_everything(MAT_EXIT_PARENTS);
01253 *it = match_result();
01254
01255
01256
01257
01258
01259 return (Good_obj(*it));
01260 }
01261
01262 extern NAMETAB lock_sw[];
01263
01264 int get_obj_and_lock(dbref player, char *what, dbref * it, ATTR ** attr,
01265 char *errmsg, char **bufc)
01266 {
01267 char *str, *tbuf;
01268 int anum;
01269
01270 tbuf = alloc_lbuf("get_obj_and_lock");
01271 StringCopy(tbuf, what);
01272 if(parse_thing_slash(player, tbuf, &str, it)) {
01273
01274
01275
01276
01277
01278 anum = search_nametab(player, lock_sw, str);
01279 if(anum < 0) {
01280 free_lbuf(tbuf);
01281 safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01282 return 0;
01283 }
01284 } else {
01285
01286
01287
01288
01289
01290 *it = match_thing(player, what);
01291 if(!Good_obj(*it)) {
01292 free_lbuf(tbuf);
01293 safe_str("#-1 NOT FOUND", errmsg, bufc);
01294 return 0;
01295 }
01296 anum = A_LOCK;
01297 }
01298
01299
01300
01301
01302
01303 free_lbuf(tbuf);
01304 *attr = atr_num(anum);
01305 if(!(*attr)) {
01306 safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01307 return 0;
01308 }
01309 return 1;
01310 }
01311
01316 dbref where_is(dbref what)
01317 {
01318 dbref loc;
01319
01320 if(!Good_obj(what))
01321 return NOTHING;
01322
01323 switch (Typeof(what)) {
01324 case TYPE_PLAYER:
01325 case TYPE_THING:
01326 loc = Location(what);
01327 break;
01328 case TYPE_EXIT:
01329 loc = Exits(what);
01330 break;
01331 default:
01332 loc = NOTHING;
01333 break;
01334 }
01335 return loc;
01336 }
01337
01342 dbref where_room(dbref what)
01343 {
01344 int count;
01345
01346 for(count = mudconf.ntfy_nest_lim; count > 0; count--) {
01347 if(!Good_obj(what))
01348 break;
01349 if(isRoom(what))
01350 return what;
01351 if(!Has_location(what))
01352 break;
01353 what = Location(what);
01354 }
01355 return NOTHING;
01356 }
01357
01358 int locatable(dbref player, dbref it, dbref cause)
01359 {
01360 dbref loc_it, room_it;
01361 int findable_room;
01362
01363
01364
01365
01366
01367 if(!Good_obj(it))
01368 return 0;
01369
01370 loc_it = where_is(it);
01371
01372
01373
01374
01375
01376
01377
01378
01379 if(Examinable(player, it) || Find_Unfindable(player) ||
01380 (loc_it == player) || ((loc_it != NOTHING) &&
01381 (Examinable(player, loc_it)
01382 || loc_it == where_is(player)))
01383 || Wizard(cause) || (it == cause))
01384 return 1;
01385
01386 room_it = where_room(it);
01387 if(Good_obj(room_it))
01388 findable_room = !Hideout(room_it);
01389 else
01390 findable_room = 1;
01391
01392
01393
01394
01395
01396
01397 if(((room_it != NOTHING) && Examinable(player, room_it)) ||
01398 Find_Unfindable(player) || (Findable(it) && findable_room))
01399 return 1;
01400
01401
01402
01403
01404
01405 return 0;
01406 }
01407
01412 int nearby(dbref player, dbref thing)
01413 {
01414 int thing_loc, player_loc;
01415
01416 if(!Good_obj(player) || !Good_obj(thing))
01417 return 0;
01418 thing_loc = where_is(thing);
01419 if(thing_loc == player)
01420 return 1;
01421 player_loc = where_is(player);
01422 if((thing_loc == player_loc) || (thing == player_loc))
01423 return 1;
01424 return 0;
01425 }
01426
01430 int exit_visible(dbref exit, dbref player, int key)
01431 {
01432 if(key & VE_LOC_XAM)
01433 return 1;
01434 if(Examinable(player, exit))
01435 return 1;
01436 if(Light(exit))
01437 return 1;
01438 if(key & (VE_LOC_DARK | VE_BASE_DARK))
01439 return 0;
01440 if(Dark(exit))
01441 return 0;
01442 return 1;
01443 }
01444
01448 int exit_displayable(dbref exit, dbref player, int key)
01449 {
01450 if(Dark(exit))
01451 return 0;
01452 if(Light(exit))
01453 return 1;
01454 if(key & (VE_LOC_DARK | VE_BASE_DARK))
01455 return 0;
01456 return 1;
01457 }
01458
01462 dbref next_exit(dbref player, dbref this, int exam_here)
01463 {
01464 if(isRoom(this))
01465 return NOTHING;
01466 if(isExit(this) && exam_here)
01467 return this;
01468
01469 while ((this != NOTHING) && Dark(this) && !Light(this) &&
01470 !Examinable(player, this))
01471 this = Next(this);
01472
01473 return this;
01474 }
01475
01479 void did_it(dbref player, dbref thing, int what, const char *def, int owhat,
01480 const char *odef, int awhat, char *args[], int nargs)
01481 {
01482 char *d, *buff, *act, *charges, *bp, *str;
01483 dbref loc, aowner;
01484 int num, aflags;
01485
01486
01487
01488
01489
01490 if(what > 0) {
01491 d = atr_pget(thing, what, &aowner, &aflags);
01492 if(*d) {
01493 buff = bp = alloc_lbuf("did_it.1");
01494 str = d;
01495 exec(buff, &bp, 0, thing, player,
01496 EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
01497 *bp = '\0';
01498 notify(player, buff);
01499 free_lbuf(buff);
01500 } else if(def) {
01501 notify(player, def);
01502 }
01503 free_lbuf(d);
01504 } else if((what < 0) && def) {
01505 notify(player, def);
01506 }
01507
01508
01509
01510
01511 if((owhat > 0) && Has_location(player) &&
01512 Good_obj(loc = Location(player))) {
01513 d = atr_pget(thing, owhat, &aowner, &aflags);
01514 if(*d) {
01515 buff = bp = alloc_lbuf("did_it.2");
01516 str = d;
01517 exec(buff, &bp, 0, thing, player,
01518 EV_EVAL | EV_FIGNORE | EV_TOP, &str, args, nargs);
01519 *bp = '\0';
01520 if(*buff)
01521 notify_except2(loc, player, player, thing, tprintf("%s %s",
01522 Name
01523 (player),
01524 buff));
01525 free_lbuf(buff);
01526 } else if(odef) {
01527 notify_except2(loc, player, player, thing, tprintf("%s %s",
01528 Name(player),
01529 odef));
01530 }
01531 free_lbuf(d);
01532 } else if((owhat < 0) && odef && Has_location(player) &&
01533 Good_obj(loc = Location(player))) {
01534 notify_except2(loc, player, player, thing, tprintf("%s %s",
01535 Name(player),
01536 odef));
01537 }
01538
01539
01540
01541
01542 if(awhat > 0) {
01543 if(*(act = atr_pget(thing, awhat, &aowner, &aflags))) {
01544 charges = atr_pget(thing, A_CHARGES, &aowner, &aflags);
01545 if(*charges) {
01546 num = atoi(charges);
01547 if(num > 0) {
01548 buff = alloc_sbuf("did_it.charges");
01549 sprintf(buff, "%d", num - 1);
01550 atr_add_raw(thing, A_CHARGES, buff);
01551 free_sbuf(buff);
01552 } else if(*(buff =
01553 atr_pget(thing, A_RUNOUT, &aowner, &aflags))) {
01554 free_lbuf(act);
01555 act = buff;
01556 } else {
01557 free_lbuf(act);
01558 free_lbuf(buff);
01559 free_lbuf(charges);
01560 return;
01561 }
01562 }
01563 free_lbuf(charges);
01564 wait_que(thing, player, 0, NOTHING, 0, act, args, nargs,
01565 mudstate.global_regs);
01566 }
01567 free_lbuf(act);
01568 }
01569 }
01570
01574 void do_verb(dbref player, dbref cause, int key, char *victim_str,
01575 char *args[], int nargs)
01576 {
01577 dbref actor, victim, aowner;
01578 int what, owhat, awhat, nxargs, restriction, aflags, i;
01579 ATTR *ap;
01580 const char *whatd, *owhatd;
01581 char *xargs[10];
01582
01583
01584
01585
01586
01587 if(!victim_str || !*victim_str) {
01588 notify(player, "Nothing to do.");
01589 return;
01590 }
01591
01592
01593
01594
01595 init_match(player, victim_str, NOTYPE);
01596 match_everything(MAT_EXIT_PARENTS);
01597 victim = noisy_match_result();
01598 if(!Good_obj(victim))
01599 return;
01600
01601
01602
01603
01604
01605 if((nargs >= 1) && args[0] && *args[0]) {
01606 init_match(player, args[0], NOTYPE);
01607 match_everything(MAT_EXIT_PARENTS);
01608 actor = noisy_match_result();
01609 if(!Good_obj(actor))
01610 return;
01611 } else {
01612 actor = cause;
01613 }
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623
01624 if(!controls(player, actor)) {
01625 notify_quiet(player, "Permission denied,");
01626 return;
01627 }
01628 restriction = !controls(player, victim);
01629
01630 what = -1;
01631 owhat = -1;
01632 awhat = -1;
01633 whatd = NULL;
01634 owhatd = NULL;
01635 nxargs = 0;
01636
01637
01638
01639
01640
01641 if(nargs >= 2) {
01642 ap = atr_str(args[1]);
01643 if(ap && (ap->number > 0))
01644 what = ap->number;
01645 }
01646
01647
01648
01649
01650 if((nargs >= 3) && args[2] && *args[2]) {
01651 whatd = args[2];
01652 }
01653
01654
01655
01656
01657 if(nargs >= 4) {
01658 ap = atr_str(args[3]);
01659 if(ap && (ap->number > 0))
01660 owhat = ap->number;
01661 }
01662
01663
01664
01665
01666 if((nargs >= 5) && args[4] && *args[4]) {
01667 owhatd = args[4];
01668 }
01669
01670
01671
01672
01673 if(nargs >= 6) {
01674 ap = atr_str(args[5]);
01675 if(ap)
01676 awhat = ap->number;
01677 }
01678
01679
01680
01681
01682 if(nargs >= 7) {
01683 parse_arglist(victim, actor, args[6], '\0',
01684 EV_STRIP_LS | EV_STRIP_TS, xargs, 10, (char **) NULL,
01685 0);
01686 for(nxargs = 0; (nxargs < 10) && xargs[nxargs]; nxargs++);
01687 }
01688
01689
01690
01691
01692 if(restriction) {
01693 ap = NULL;
01694 if(what != -1) {
01695 atr_get_info(victim, what, &aowner, &aflags);
01696 ap = atr_num(what);
01697 }
01698 if(!ap || !Read_attr(player, victim, ap, aowner, aflags) ||
01699 ((ap->number == A_DESC) && !mudconf.read_rem_desc &&
01700 !Examinable(player, victim) && !nearby(player, victim)))
01701 what = -1;
01702
01703 ap = NULL;
01704 if(owhat != -1) {
01705 atr_get_info(victim, owhat, &aowner, &aflags);
01706 ap = atr_num(owhat);
01707 }
01708 if(!ap || !Read_attr(player, victim, ap, aowner, aflags) ||
01709 ((ap->number == A_DESC) && !mudconf.read_rem_desc &&
01710 !Examinable(player, victim) && !nearby(player, victim)))
01711 owhat = -1;
01712
01713 awhat = 0;
01714 }
01715
01716
01717
01718
01719 did_it(actor, victim, what, whatd, owhat, owhatd, awhat, xargs, nxargs);
01720
01721
01722
01723
01724
01725 for(i = 0; i < nxargs; i++)
01726 free_lbuf(xargs[i]);
01727
01728 }