00001
00002
00003
00004
00005
00006 #include "copyright.h"
00007 #include "autoconf.h"
00008 #include "config.h"
00009 #include "externs.h"
00010
00011 #include <signal.h>
00012
00013 #include "ansi.h"
00014 #include "attrs.h"
00015 #include "command.h"
00016 #include "interface.h"
00017 #include "powers.h"
00018 #ifdef REALITY_LVLS
00019 #include "levels.h"
00020 #endif
00021
00022 char * DCL_CDECL tprintf(const char *fmt,...)
00023 {
00024 static char buff[LBUF_SIZE];
00025 va_list ap;
00026 va_start(ap, fmt);
00027 mux_vsnprintf(buff, LBUF_SIZE, fmt, ap);
00028 va_end(ap);
00029 return buff;
00030 }
00031
00032 void DCL_CDECL safe_tprintf_str(char *str, char **bp, const char *fmt,...)
00033 {
00034 va_list ap;
00035 va_start(ap, fmt);
00036 size_t nAvailable = LBUF_SIZE - (*bp - str);
00037 size_t len = mux_vsnprintf(*bp, (int)nAvailable, fmt, ap);
00038 va_end(ap);
00039 *bp += len;
00040 }
00041
00042
00043
00044
00045
00046 dbref insert_first(dbref head, dbref thing)
00047 {
00048 s_Next(thing, head);
00049 return thing;
00050 }
00051
00052 dbref remove_first(dbref head, dbref thing)
00053 {
00054 if (head == thing)
00055 {
00056 return Next(thing);
00057 }
00058
00059 dbref prev;
00060
00061 DOLIST(prev, head)
00062 {
00063 if (Next(prev) == thing)
00064 {
00065 s_Next(prev, Next(thing));
00066 return head;
00067 }
00068 }
00069 return head;
00070 }
00071
00072
00073
00074
00075
00076 dbref reverse_list(dbref list)
00077 {
00078 dbref newlist, rest;
00079
00080 newlist = NOTHING;
00081 while (list != NOTHING)
00082 {
00083 rest = Next(list);
00084 s_Next(list, newlist);
00085 newlist = list;
00086 list = rest;
00087 }
00088 return newlist;
00089 }
00090
00091
00092
00093
00094
00095 bool member(dbref thing, dbref list)
00096 {
00097 DOLIST(list, list)
00098 {
00099 if (list == thing)
00100 {
00101 return true;
00102 }
00103 }
00104 return false;
00105 }
00106
00107 bool could_doit(dbref player, dbref thing, int locknum)
00108 {
00109 if (thing == HOME)
00110 {
00111 return true;
00112 }
00113
00114
00115
00116 if ( !isPlayer(player)
00117 && Key(thing))
00118 {
00119 return false;
00120 }
00121 if (Pass_Locks(player))
00122 {
00123 return true;
00124 }
00125
00126 dbref aowner;
00127 int aflags;
00128 char *key = atr_get(thing, locknum, &aowner, &aflags);
00129 bool doit = eval_boolexp_atr(player, thing, thing, key);
00130 free_lbuf(key);
00131 return doit;
00132 }
00133
00134 bool can_see(dbref player, dbref thing, bool can_see_loc)
00135 {
00136
00137
00138
00139
00140 if ( mudconf.dark_sleepers
00141 && isPlayer(thing)
00142 && !Connected(thing)
00143 && !Puppet(thing))
00144 {
00145 return false;
00146 }
00147
00148
00149
00150 if ( player == thing
00151 || isExit(thing))
00152 {
00153 return false;
00154 }
00155
00156
00157
00158
00159
00160
00161 if (can_see_loc)
00162 {
00163 #ifdef REALITY_LVLS
00164 return ((!Dark(thing) && IsReal(player, thing)) ||
00165 #else
00166 return (!Dark(thing) ||
00167 #endif
00168 (mudconf.see_own_dark && MyopicExam(player, thing)));
00169 }
00170 else
00171 {
00172 #ifdef REALITY_LVLS
00173 return ((Light(thing) && !Dark(thing) && IsReal(player, thing)) ||
00174 #else
00175 return ((Light(thing) && !Dark(thing)) ||
00176 #endif
00177 (mudconf.see_own_dark && MyopicExam(player, thing)));
00178 }
00179 }
00180
00181 static bool pay_quota(dbref who, int cost)
00182 {
00183
00184
00185 if (cost <= 0)
00186 {
00187 return true;
00188 }
00189
00190
00191
00192 dbref aowner;
00193 int aflags;
00194 char *quota_str = atr_get(Owner(who), A_RQUOTA, &aowner, &aflags);
00195 int quota = mux_atol(quota_str);
00196 free_lbuf(quota_str);
00197
00198
00199
00200 quota -= cost;
00201 if ( quota < 0
00202 && !Free_Quota(who)
00203 && !Free_Quota(Owner(who)))
00204 {
00205 return false;
00206 }
00207
00208
00209
00210 char buf[20];
00211 mux_ltoa(quota, buf);
00212 atr_add_raw(Owner(who), A_RQUOTA, buf);
00213
00214 return true;
00215 }
00216
00217 bool canpayfees(dbref player, dbref who, int pennies, int quota)
00218 {
00219 if ( !Wizard(who)
00220 && !Wizard(Owner(who))
00221 && !Free_Money(who)
00222 && !Free_Money(Owner(who))
00223 && (Pennies(Owner(who)) < pennies))
00224 {
00225 if (player == who)
00226 {
00227 notify(player, tprintf("Sorry, you don't have enough %s.",
00228 mudconf.many_coins));
00229 }
00230 else
00231 {
00232 notify(player, tprintf("Sorry, that player doesn't have enough %s.",
00233 mudconf.many_coins));
00234 }
00235 return false;
00236 }
00237 if (mudconf.quotas)
00238 {
00239 if (!pay_quota(who, quota))
00240 {
00241 if (player == who)
00242 {
00243 notify(player, "Sorry, your building contract has run out.");
00244 }
00245 else
00246 {
00247 notify(player,
00248 "Sorry, that player's building contract has run out.");
00249 }
00250 return false;
00251 }
00252 }
00253 payfor(who, pennies);
00254 return true;
00255 }
00256
00257 bool payfor(dbref who, int cost)
00258 {
00259 if ( Wizard(who)
00260 || Wizard(Owner(who))
00261 || Free_Money(who)
00262 || Free_Money(Owner(who)))
00263 {
00264 return true;
00265 }
00266 who = Owner(who);
00267 int tmp;
00268 if ((tmp = Pennies(who)) >= cost)
00269 {
00270 s_Pennies(who, tmp - cost);
00271 return true;
00272 }
00273 return false;
00274 }
00275
00276 void add_quota(dbref who, int payment)
00277 {
00278 dbref aowner;
00279 int aflags;
00280 char buf[20];
00281
00282 char *quota = atr_get(who, A_RQUOTA, &aowner, &aflags);
00283 mux_ltoa(mux_atol(quota) + payment, buf);
00284 free_lbuf(quota);
00285 atr_add_raw(who, A_RQUOTA, buf);
00286 }
00287
00288 void giveto(dbref who, int pennies)
00289 {
00290 if ( Wizard(who)
00291 || Wizard(Owner(who))
00292 || Free_Money(who)
00293 || Free_Money(Owner(who)))
00294 {
00295 return;
00296 }
00297 who = Owner(who);
00298 s_Pennies(who, Pennies(who) + pennies);
00299 }
00300
00301
00302
00303
00304
00305 char *MakeCanonicalObjectName(const char *pName, int *pnName, bool *pbValid)
00306 {
00307 static char Buf[MBUF_SIZE];
00308
00309 *pnName = 0;
00310 *pbValid = false;
00311
00312 if (!pName)
00313 {
00314 return NULL;
00315 }
00316
00317
00318
00319
00320 int nVisualWidth;
00321 int nBuf = ANSI_TruncateToField(pName, sizeof(Buf), Buf, MBUF_SIZE,
00322 &nVisualWidth, ANSI_ENDGOAL_NORMAL);
00323
00324
00325
00326
00327 if (nVisualWidth <= 0)
00328 {
00329 return NULL;
00330 }
00331
00332
00333
00334 size_t nStripped;
00335 char *pStripped = strip_ansi(Buf, &nStripped);
00336
00337
00338
00339
00340 if ( strchr("*!#", *pStripped)
00341 || mux_isspace(pStripped[0])
00342 || mux_isspace(pStripped[nStripped-1]))
00343 {
00344 return NULL;
00345 }
00346
00347
00348
00349
00350 for (unsigned int i = 0; i < nStripped; i++)
00351 {
00352 if (!mux_ObjectNameSet(pStripped[i]))
00353 {
00354 return NULL;
00355 }
00356 }
00357
00358
00359
00360 if ( (nStripped == 2 && memcmp("me", pStripped, 2) == 0)
00361 || (nStripped == 4 && ( memcmp("home", pStripped, 4) == 0
00362 || memcmp("here", pStripped, 4) == 0)))
00363 {
00364 return NULL;
00365 }
00366
00367 *pnName = nBuf;
00368 *pbValid = true;
00369 return Buf;
00370 }
00371
00372
00373
00374 char *MakeCanonicalExitName(const char *pName, int *pnName, bool *pbValid)
00375 {
00376 static char Buf[MBUF_SIZE];
00377 static char Out[MBUF_SIZE];
00378
00379 *pnName = 0;
00380 *pbValid = false;
00381
00382 if (!pName)
00383 {
00384 return NULL;
00385 }
00386
00387
00388
00389
00390 char *pStripped = strip_ansi(pName);
00391 char *pBuf = Buf;
00392 safe_mb_str(pStripped, Buf, &pBuf);
00393 *pBuf = '\0';
00394
00395 size_t nBuf = pBuf - Buf;
00396 pBuf = Buf;
00397
00398 bool bHaveDisplay = false;
00399
00400 char *pOut = Out;
00401
00402 for (; nBuf;)
00403 {
00404
00405
00406
00407 char *q = strchr(pBuf, ';');
00408 size_t n;
00409 if (q)
00410 {
00411 *q = '\0';
00412 n = q - pBuf;
00413 q = pBuf;
00414 pBuf += n + 1;
00415 nBuf -= n + 1;
00416 }
00417 else
00418 {
00419 n = nBuf;
00420 q = pBuf;
00421 pBuf += nBuf;
00422 nBuf = 0;
00423 }
00424
00425 if (bHaveDisplay)
00426 {
00427
00428
00429
00430
00431 int nN;
00432 bool bN;
00433 char *pN = MakeCanonicalObjectName(q, &nN, &bN);
00434 if ( bN
00435 && nN < MBUF_SIZE - (pOut - Out) - 1)
00436 {
00437 safe_mb_chr(';', Out, &pOut);
00438 safe_mb_str(pN, Out, &pOut);
00439 }
00440 }
00441 else
00442 {
00443
00444
00445
00446
00447
00448
00449 int vw;
00450 ANSI_TruncateToField(pName, sizeof(Out), Out, n, &vw,
00451 ANSI_ENDGOAL_NORMAL);
00452
00453
00454
00455 if ((size_t)vw == n)
00456 {
00457 int nN;
00458 bool bN;
00459 char *pN = MakeCanonicalObjectName(Out, &nN, &bN);
00460 if ( bN
00461 && nN <= MBUF_SIZE - 1)
00462 {
00463 safe_mb_str(pN, Out, &pOut);
00464 bHaveDisplay = true;
00465 }
00466 }
00467 }
00468 }
00469 if (bHaveDisplay)
00470 {
00471 *pnName = pOut - Out;
00472 *pbValid = true;
00473 *pOut = '\0';
00474 return Out;
00475 }
00476 else
00477 {
00478 return NULL;
00479 }
00480 }
00481
00482
00483
00484
00485
00486 bool ValidatePlayerName(const char *pName)
00487 {
00488 if (!pName)
00489 {
00490 return false;
00491 }
00492 size_t nName = strlen(pName);
00493
00494
00495
00496 if ( nName <= 0
00497 || PLAYER_NAME_LIMIT <= nName)
00498 {
00499 return false;
00500 }
00501
00502
00503
00504
00505 if ( strchr("*!#", *pName)
00506 || mux_isspace(pName[0])
00507 || mux_isspace(pName[nName-1]))
00508 {
00509 return false;
00510 }
00511
00512 if ( mudstate.bStandAlone
00513 || mudconf.name_spaces)
00514 {
00515 mux_PlayerNameSet[(unsigned char)' '] = 1;
00516 }
00517 else
00518 {
00519 mux_PlayerNameSet[(unsigned char)' '] = 0;
00520 }
00521
00522
00523
00524
00525 for (unsigned int i = 0; i < nName; i++)
00526 {
00527 if (!mux_PlayerNameSet(pName[i]))
00528 {
00529 return false;
00530 }
00531 }
00532
00533
00534
00535 if ( (nName == 2 && memcmp("me", pName, 2) == 0)
00536 || (nName == 4 && ( memcmp("home", pName, 4) == 0
00537 || memcmp("here", pName, 4) == 0)))
00538 {
00539 return false;
00540 }
00541 return true;
00542 }
00543
00544 bool ok_password(const char *password, const char **pmsg)
00545 {
00546 *pmsg = NULL;
00547
00548 if (*password == '\0')
00549 {
00550 *pmsg = "Null passwords are not allowed.";
00551 return false;
00552 }
00553
00554 const char *scan;
00555 int num_upper = 0;
00556 int num_special = 0;
00557 int num_lower = 0;
00558
00559 for (scan = password; *scan; scan++)
00560 {
00561 if ( !mux_isprint(*scan)
00562 || mux_isspace(*scan))
00563 {
00564 *pmsg = "Illegal character in password.";
00565 return false;
00566 }
00567 if (mux_isupper(*scan))
00568 {
00569 num_upper++;
00570 }
00571 else if (mux_islower(*scan))
00572 {
00573 num_lower++;
00574 }
00575 else if ( *scan != '\''
00576 && *scan != '-')
00577 {
00578 num_special++;
00579 }
00580 }
00581
00582 if ( !mudstate.bStandAlone
00583 && mudconf.safer_passwords)
00584 {
00585 if (num_upper < 1)
00586 {
00587 *pmsg = "The password must contain at least one capital letter.";
00588 return false;
00589 }
00590 if (num_lower < 1)
00591 {
00592 *pmsg = "The password must contain at least one lowercase letter.";
00593 return false;
00594 }
00595 if (num_special < 1)
00596 {
00597 *pmsg = "The password must contain at least one number or a symbol other than the apostrophe or dash.";
00598 return false;
00599 }
00600 }
00601 return true;
00602 }
00603
00604
00605
00606
00607
00608 void handle_ears(dbref thing, bool could_hear, bool can_hear)
00609 {
00610 char *buff, *bp;
00611 int gender;
00612 static const char *poss[5] =
00613 {"", "its", "her", "his", "their"};
00614
00615 if (could_hear != can_hear)
00616 {
00617 buff = alloc_lbuf("handle_ears");
00618 strcpy(buff, Name(thing));
00619 if (isExit(thing))
00620 {
00621 for (bp = buff; *bp && *bp != ';'; bp++)
00622 {
00623 ;
00624 }
00625 *bp = '\0';
00626 }
00627 gender = get_gender(thing);
00628
00629 if (can_hear)
00630 {
00631 notify_check(thing, thing,
00632 tprintf("%s grow%s ears and can now hear.",
00633 buff, (gender == 4) ? "" : "s"),
00634 (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00635 }
00636 else
00637 {
00638 notify_check(thing, thing,
00639 tprintf("%s lose%s %s ears and become%s deaf.",
00640 buff, (gender == 4) ? "" : "s",
00641 poss[gender], (gender == 4) ? "" : "s"),
00642 (MSG_ME | MSG_NBR | MSG_LOC | MSG_INV));
00643 }
00644 free_lbuf(buff);
00645 }
00646 }
00647
00648
00649
00650 void do_switch
00651 (
00652 dbref player,
00653 dbref caller,
00654 dbref enactor,
00655 int key,
00656 char *expr,
00657 char *args[],
00658 int nargs,
00659 char *cargs[],
00660 int ncargs
00661 )
00662 {
00663 if ( !expr
00664 || nargs <= 0)
00665 {
00666 return;
00667 }
00668
00669 if (key == SWITCH_DEFAULT)
00670 {
00671 if (mudconf.switch_df_all)
00672 {
00673 key = SWITCH_ANY;
00674 }
00675 else
00676 {
00677 key = SWITCH_ONE;
00678 }
00679 }
00680
00681
00682
00683 bool any = false;
00684 int a;
00685 char *buff, *bp, *str;
00686 buff = bp = alloc_lbuf("do_switch");
00687 CLinearTimeAbsolute lta;
00688 for ( a = 0;
00689 a < nargs - 1
00690 && args[a]
00691 && args[a + 1];
00692 a += 2)
00693 {
00694 bp = buff;
00695 str = args[a];
00696 mux_exec(buff, &bp, player, caller, enactor, EV_FCHECK | EV_EVAL | EV_TOP,
00697 &str, cargs, ncargs);
00698 *bp = '\0';
00699 if (wild_match(buff, expr))
00700 {
00701 char *tbuf = replace_tokens(args[a+1], NULL, NULL, expr);
00702 wait_que(player, caller, enactor, false, lta, NOTHING, 0,
00703 tbuf, cargs, ncargs, mudstate.global_regs);
00704 free_lbuf(tbuf);
00705 if (key == SWITCH_ONE)
00706 {
00707 free_lbuf(buff);
00708 return;
00709 }
00710 any = true;
00711 }
00712 }
00713 free_lbuf(buff);
00714 if ( a < nargs
00715 && !any
00716 && args[a])
00717 {
00718 char *tbuf = replace_tokens(args[a], NULL, NULL, expr);
00719 wait_que(player, caller, enactor, false, lta, NOTHING, 0, tbuf,
00720 cargs, ncargs, mudstate.global_regs);
00721 free_lbuf(tbuf);
00722 }
00723 }
00724
00725
00726
00727
00728 void do_if
00729 (
00730 dbref player,
00731 dbref caller,
00732 dbref enactor,
00733 int key,
00734 char *expr,
00735 char *args[],
00736 int nargs,
00737 char *cargs[],
00738 int ncargs
00739 )
00740 {
00741 UNUSED_PARAMETER(key);
00742
00743 if ( !expr
00744 || nargs <= 0)
00745 {
00746 return;
00747 }
00748
00749 char *buff, *bp;
00750 CLinearTimeAbsolute lta;
00751 buff = bp = alloc_lbuf("do_if");
00752
00753 mux_exec(buff, &bp, player, caller, enactor, EV_FCHECK | EV_EVAL | EV_TOP,
00754 &expr, cargs, ncargs);
00755 *bp = '\0';
00756
00757 int a = !xlate(buff);
00758 free_lbuf(buff);
00759
00760 if (a < nargs)
00761 {
00762 wait_que(player, caller, enactor, false, lta, NOTHING, 0, args[a],
00763 cargs, ncargs, mudstate.global_regs);
00764 }
00765 }
00766
00767 void do_addcommand
00768 (
00769 dbref player,
00770 dbref caller,
00771 dbref enactor,
00772 int key,
00773 int nargs,
00774 char *name,
00775 char *command
00776 )
00777 {
00778 UNUSED_PARAMETER(caller);
00779 UNUSED_PARAMETER(enactor);
00780 UNUSED_PARAMETER(key);
00781
00782
00783
00784 char *pName = NULL;
00785 if (1 <= nargs)
00786 {
00787 char *pStripped = strip_ansi(name);
00788 pName = RemoveSetOfCharacters(pStripped, "\r\n\t ");
00789 mux_strlwr(pName);
00790 }
00791 if ( !pName
00792 || pName[0] == '\0'
00793 || ( pName[0] == '_'
00794 && pName[1] == '_'))
00795 {
00796 notify(player, "That is not a valid command name.");
00797 return;
00798 }
00799
00800
00801
00802 dbref thing;
00803 ATTR *pattr;
00804 if ( !parse_attrib(player, command, &thing, &pattr)
00805 || !pattr)
00806 {
00807 notify(player, "No such attribute.");
00808 return;
00809 }
00810 if (!See_attr(player, thing, pattr))
00811 {
00812 notify(player, NOPERM_MESSAGE);
00813 return;
00814 }
00815
00816 CMDENT *old = (CMDENT *)hashfindLEN(pName, strlen(pName),
00817 &mudstate.command_htab);
00818
00819 CMDENT *cmd;
00820 ADDENT *add, *nextp;
00821
00822 if ( old
00823 && (old->callseq & CS_ADDED))
00824 {
00825
00826
00827 for (nextp = old->addent; nextp != NULL; nextp = nextp->next)
00828 {
00829 if ( nextp->thing == thing
00830 && nextp->atr == pattr->number)
00831 {
00832 notify(player, tprintf("%s already added.", pName));
00833 return;
00834 }
00835 }
00836
00837
00838
00839 add = (ADDENT *)MEMALLOC(sizeof(ADDENT));
00840 ISOUTOFMEMORY(add);
00841 add->thing = thing;
00842 add->atr = pattr->number;
00843 add->name = StringClone(pName);
00844 add->next = old->addent;
00845 old->addent = add;
00846 }
00847 else
00848 {
00849 if (old)
00850 {
00851
00852
00853
00854 hashdeleteLEN(pName, strlen(pName), &mudstate.command_htab);
00855 }
00856
00857 cmd = (CMDENT *)MEMALLOC(sizeof(CMDENT));
00858 ISOUTOFMEMORY(cmd);
00859 cmd->cmdname = StringClone(pName);
00860 cmd->switches = NULL;
00861 cmd->perms = 0;
00862 cmd->extra = 0;
00863 if ( old
00864 && (old->callseq & CS_LEADIN))
00865 {
00866 cmd->callseq = CS_ADDED|CS_ONE_ARG|CS_LEADIN;
00867 }
00868 else
00869 {
00870 cmd->callseq = CS_ADDED|CS_ONE_ARG;
00871 }
00872 cmd->hookmask = 0;
00873 add = (ADDENT *)MEMALLOC(sizeof(ADDENT));
00874 ISOUTOFMEMORY(add);
00875 add->thing = thing;
00876 add->atr = pattr->number;
00877 add->name = StringClone(pName);
00878 add->next = NULL;
00879 cmd->addent = add;
00880
00881 hashaddLEN(pName, strlen(pName), cmd, &mudstate.command_htab);
00882
00883 if ( old
00884 && strcmp(pName, old->cmdname) == 0)
00885 {
00886
00887
00888
00889
00890 char *p = tprintf("__%s", pName);
00891 hashdeleteLEN(p, strlen(p), &mudstate.command_htab);
00892 hashreplall(old, cmd, &mudstate.command_htab);
00893 hashaddLEN(p, strlen(p), old, &mudstate.command_htab);
00894 }
00895 }
00896
00897
00898
00899 set_prefix_cmds();
00900 notify(player, tprintf("Command %s added.", pName));
00901 }
00902
00903 void do_listcommands(dbref player, dbref caller, dbref enactor, int key,
00904 char *name)
00905 {
00906 UNUSED_PARAMETER(caller);
00907 UNUSED_PARAMETER(enactor);
00908 UNUSED_PARAMETER(key);
00909
00910 CMDENT *old;
00911 ADDENT *nextp;
00912 bool didit = false;
00913
00914
00915
00916 mux_strlwr(name);
00917
00918 if (*name)
00919 {
00920 old = (CMDENT *)hashfindLEN(name, strlen(name), &mudstate.command_htab);
00921
00922 if ( old
00923 && (old->callseq & CS_ADDED))
00924 {
00925
00926
00927
00928 for (nextp = old->addent; nextp != NULL; nextp = nextp->next)
00929 {
00930 ATTR *ap = (ATTR *)atr_num(nextp->atr);
00931 const char *pName = "(WARNING: Bad Attribute Number)";
00932 if (ap)
00933 {
00934 pName = ap->name;
00935 }
00936 notify(player, tprintf("%s: #%d/%s", nextp->name, nextp->thing, pName));
00937 }
00938 }
00939 else
00940 {
00941 notify(player, tprintf("%s not found in command table.",name));
00942 }
00943 return;
00944 }
00945 else
00946 {
00947 char *pKeyName;
00948 int nKeyName;
00949 for (old = (CMDENT *)hash_firstkey(&mudstate.command_htab, &nKeyName, &pKeyName);
00950 old != NULL;
00951 old = (CMDENT *)hash_nextkey(&mudstate.command_htab, &nKeyName, &pKeyName))
00952 {
00953 if (old->callseq & CS_ADDED)
00954 {
00955 pKeyName[nKeyName] = '\0';
00956 for (nextp = old->addent; nextp != NULL; nextp = nextp->next)
00957 {
00958 if (strcmp(pKeyName, nextp->name) != 0)
00959 {
00960 continue;
00961 }
00962 ATTR *ap = (ATTR *)atr_num(nextp->atr);
00963 const char *pName = "(WARNING: Bad Attribute Number)";
00964 if (ap)
00965 {
00966 pName = ap->name;
00967 }
00968 notify(player, tprintf("%s: #%d/%s", nextp->name,
00969 nextp->thing, pName));
00970 didit = true;
00971 }
00972 }
00973 }
00974 }
00975 if (!didit)
00976 {
00977 notify(player, "No added commands found in command table.");
00978 }
00979 }
00980
00981 void do_delcommand
00982 (
00983 dbref player,
00984 dbref caller,
00985 dbref enactor,
00986 int key,
00987 int nargs,
00988 char *name,
00989 char *command
00990 )
00991 {
00992 UNUSED_PARAMETER(caller);
00993 UNUSED_PARAMETER(enactor);
00994 UNUSED_PARAMETER(key);
00995 UNUSED_PARAMETER(nargs);
00996
00997 if (!*name)
00998 {
00999 notify(player, "Sorry.");
01000 return;
01001 }
01002
01003 dbref thing = NOTHING;
01004 int atr = NOTHING;
01005 ATTR *pattr;
01006 if (*command)
01007 {
01008 if ( !parse_attrib(player, command, &thing, &pattr)
01009 || !pattr)
01010 {
01011 notify(player, "No such attribute.");
01012 return;
01013 }
01014 if (!See_attr(player, thing, pattr))
01015 {
01016 notify(player, NOPERM_MESSAGE);
01017 return;
01018 }
01019 atr = pattr->number;
01020 }
01021
01022
01023
01024 mux_strlwr(name);
01025
01026 CMDENT *old, *cmd;
01027 ADDENT *prev = NULL, *nextp;
01028 size_t nName = strlen(name);
01029 old = (CMDENT *)hashfindLEN(name, nName, &mudstate.command_htab);
01030
01031 if ( old
01032 && (old->callseq & CS_ADDED))
01033 {
01034 char *p__Name = tprintf("__%s", name);
01035 size_t n__Name = strlen(p__Name);
01036
01037 if (command[0] == '\0')
01038 {
01039
01040
01041 for (prev = old->addent; prev != NULL; prev = nextp)
01042 {
01043 nextp = prev->next;
01044 MEMFREE(prev->name);
01045 prev->name = NULL;
01046 MEMFREE(prev);
01047 prev = NULL;
01048 }
01049 hashdeleteLEN(name, nName, &mudstate.command_htab);
01050 cmd = (CMDENT *)hashfindLEN(p__Name, n__Name, &mudstate.command_htab);
01051 if (cmd)
01052 {
01053 hashaddLEN(cmd->cmdname, strlen(cmd->cmdname), cmd,
01054 &mudstate.command_htab);
01055 if (strcmp(name, cmd->cmdname) != 0)
01056 {
01057 hashaddLEN(name, nName, cmd, &mudstate.command_htab);
01058 }
01059
01060 hashdeleteLEN(p__Name, n__Name, &mudstate.command_htab);
01061 hashaddLEN(p__Name, n__Name, cmd, &mudstate.command_htab);
01062 hashreplall(old, cmd, &mudstate.command_htab);
01063 }
01064 else
01065 {
01066
01067
01068 }
01069 MEMFREE(old->cmdname);
01070 old->cmdname = NULL;
01071 MEMFREE(old);
01072 old = NULL;
01073 set_prefix_cmds();
01074 notify(player, "Done.");
01075 }
01076 else
01077 {
01078
01079
01080 for (nextp = old->addent; nextp != NULL; nextp = nextp->next)
01081 {
01082 if ( nextp->thing == thing
01083 && nextp->atr == atr)
01084 {
01085 MEMFREE(nextp->name);
01086 nextp->name = NULL;
01087 if (!prev)
01088 {
01089 if (!nextp->next)
01090 {
01091 hashdeleteLEN(name, nName, &mudstate.command_htab);
01092 cmd = (CMDENT *)hashfindLEN(p__Name, n__Name,
01093 &mudstate.command_htab);
01094 if (cmd)
01095 {
01096 hashaddLEN(cmd->cmdname, strlen(cmd->cmdname),
01097 cmd, &mudstate.command_htab);
01098 if (strcmp(name, cmd->cmdname) != 0)
01099 {
01100 hashaddLEN(name, nName, cmd,
01101 &mudstate.command_htab);
01102 }
01103
01104 hashdeleteLEN(p__Name, n__Name,
01105 &mudstate.command_htab);
01106 hashaddLEN(p__Name, n__Name, cmd,
01107 &mudstate.command_htab);
01108 hashreplall(old, cmd,
01109 &mudstate.command_htab);
01110 }
01111 MEMFREE(old->cmdname);
01112 old->cmdname = NULL;
01113 MEMFREE(old);
01114 old = NULL;
01115 }
01116 else
01117 {
01118 old->addent = nextp->next;
01119 MEMFREE(nextp);
01120 nextp = NULL;
01121 }
01122 }
01123 else
01124 {
01125 prev->next = nextp->next;
01126 MEMFREE(nextp);
01127 nextp = NULL;
01128 }
01129 set_prefix_cmds();
01130 notify(player, "Done.");
01131 return;
01132 }
01133 prev = nextp;
01134 }
01135 notify(player, "Command not found in command table.");
01136 }
01137 }
01138 else
01139 {
01140 notify(player, "Command not found in command table.");
01141 }
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151 void handle_prog(DESC *d, char *message)
01152 {
01153
01154
01155 if (*message == '|')
01156 {
01157 do_command(d, message + 1);
01158
01159 if (d->program_data != NULL)
01160 {
01161 queue_string(d, tprintf("%s>%s ", ANSI_HILITE, ANSI_NORMAL));
01162
01163 if (OPTION_YES == UsState(d, TELNET_EOR))
01164 {
01165
01166
01167 const char aEOR[2] = { NVT_IAC, NVT_EOR };
01168 queue_write_LEN(d, aEOR, sizeof(aEOR));
01169 }
01170 else if (OPTION_YES != UsState(d, TELNET_SGA))
01171 {
01172
01173
01174 const char aGoAhead[2] = { NVT_IAC, NVT_GA };
01175 queue_write_LEN(d, aGoAhead, sizeof(aGoAhead));
01176 }
01177 }
01178 return;
01179 }
01180 dbref aowner;
01181 int aflags, i;
01182 char *cmd = atr_get(d->player, A_PROGCMD, &aowner, &aflags);
01183 CLinearTimeAbsolute lta;
01184 wait_que(d->program_data->wait_enactor, d->player, d->player, false, lta,
01185 NOTHING, 0, cmd, (char **)&message, 1,
01186 (char **)d->program_data->wait_regs);
01187
01188
01189
01190 DESC *all = (DESC *)hashfindLEN(&(d->player), sizeof(d->player), &mudstate.desc_htab) ;
01191
01192 if (all && all->program_data)
01193 {
01194 for (i = 0; i < MAX_GLOBAL_REGS; i++)
01195 {
01196 if (all->program_data->wait_regs[i])
01197 {
01198 free_lbuf(all->program_data->wait_regs[i]);
01199 all->program_data->wait_regs[i] = NULL;
01200 }
01201 }
01202
01203 MEMFREE(all->program_data);
01204 all->program_data = NULL;
01205
01206
01207
01208 DESC_ITER_PLAYER(d->player, all)
01209 all->program_data = NULL;
01210 }
01211 atr_clr(d->player, A_PROGCMD);
01212 free_lbuf(cmd);
01213 }
01214
01215 void do_quitprog(dbref player, dbref caller, dbref enactor, int key, char *name)
01216 {
01217 UNUSED_PARAMETER(caller);
01218 UNUSED_PARAMETER(enactor);
01219 UNUSED_PARAMETER(key);
01220
01221 dbref doer;
01222
01223 if (*name)
01224 {
01225 doer = match_thing(player, name);
01226 }
01227 else
01228 {
01229 doer = player;
01230 }
01231
01232 if ( !( Prog(player)
01233 || Prog(Owner(player)))
01234 && player != doer)
01235 {
01236 notify(player, NOPERM_MESSAGE);
01237 return;
01238 }
01239 if ( !Good_obj(doer)
01240 || !isPlayer(doer))
01241 {
01242 notify(player, "That is not a player.");
01243 return;
01244 }
01245 if (!Connected(doer))
01246 {
01247 notify(player, "That player is not connected.");
01248 return;
01249 }
01250 DESC *d;
01251 bool isprog = false;
01252 DESC_ITER_PLAYER(doer, d)
01253 {
01254 if (d->program_data != NULL)
01255 {
01256 isprog = true;
01257 }
01258 }
01259
01260 if (!isprog)
01261 {
01262 notify(player, "Player is not in an @program.");
01263 return;
01264 }
01265
01266 d = (DESC *)hashfindLEN(&doer, sizeof(doer), &mudstate.desc_htab);
01267 int i;
01268
01269 if (d && d->program_data)
01270 {
01271 for (i = 0; i < MAX_GLOBAL_REGS; i++)
01272 {
01273 if (d->program_data->wait_regs[i])
01274 {
01275 free_lbuf(d->program_data->wait_regs[i]);
01276 d->program_data->wait_regs[i] = NULL;
01277 }
01278 }
01279 MEMFREE(d->program_data);
01280 d->program_data = NULL;
01281
01282
01283
01284 DESC_ITER_PLAYER(doer, d)
01285 {
01286 d->program_data = NULL;
01287 }
01288 }
01289
01290 atr_clr(doer, A_PROGCMD);
01291 notify(player, "@program cleared.");
01292 notify(doer, "Your @program has been terminated.");
01293 }
01294
01295 void do_prog
01296 (
01297 dbref player,
01298 dbref caller,
01299 dbref enactor,
01300 int key,
01301 int nargs,
01302 char *name,
01303 char *command
01304 )
01305 {
01306 UNUSED_PARAMETER(caller);
01307 UNUSED_PARAMETER(enactor);
01308 UNUSED_PARAMETER(key);
01309 UNUSED_PARAMETER(nargs);
01310
01311 if ( !name
01312 || !*name)
01313 {
01314 notify(player, "No players specified.");
01315 return;
01316 }
01317
01318 dbref doer = match_thing(player, name);
01319 if ( !( Prog(player)
01320 || Prog(Owner(player)))
01321 && player != doer)
01322 {
01323 notify(player, NOPERM_MESSAGE);
01324 return;
01325 }
01326 if ( !Good_obj(doer)
01327 || !isPlayer(doer))
01328 {
01329 notify(player, "That is not a player.");
01330 return;
01331 }
01332 if (!Connected(doer))
01333 {
01334 notify(player, "That player is not connected.");
01335 return;
01336 }
01337 char *msg = command;
01338 char *attrib = parse_to(&msg, ':', 1);
01339
01340 if (msg && *msg)
01341 {
01342 notify(doer, msg);
01343 }
01344
01345 dbref thing;
01346 ATTR *ap;
01347 if (!parse_attrib(player, attrib, &thing, &ap))
01348 {
01349 notify(player, NOMATCH_MESSAGE);
01350 return;
01351 }
01352 if (ap)
01353 {
01354 dbref aowner;
01355 int aflags;
01356 int lev;
01357 dbref parent;
01358 char *pBuffer = NULL;
01359 bool bFound = false;
01360 ITER_PARENTS(thing, parent, lev)
01361 {
01362 pBuffer = atr_get(parent, ap->number, &aowner, &aflags);
01363 if (pBuffer[0])
01364 {
01365 bFound = true;
01366 break;
01367 }
01368 free_lbuf(pBuffer);
01369 }
01370 if (bFound)
01371 {
01372 if ( ( God(player)
01373 || !God(thing))
01374 && See_attr(player, thing, ap))
01375 {
01376 atr_add_raw(doer, A_PROGCMD, pBuffer);
01377 }
01378 else
01379 {
01380 notify(player, NOPERM_MESSAGE);
01381 free_lbuf(pBuffer);
01382 return;
01383 }
01384 free_lbuf(pBuffer);
01385 }
01386 else
01387 {
01388 notify(player, "Attribute not present on object.");
01389 return;
01390 }
01391 }
01392 else
01393 {
01394 notify(player, "No such attribute.");
01395 return;
01396 }
01397
01398
01399
01400 DESC *d;
01401 DESC_ITER_PLAYER(doer, d)
01402 {
01403 if (d->program_data != NULL)
01404 {
01405 notify(player, "Input already pending.");
01406 return;
01407 }
01408 }
01409
01410 PROG *program = (PROG *)MEMALLOC(sizeof(PROG));
01411 ISOUTOFMEMORY(program);
01412 program->wait_enactor = player;
01413 for (int i = 0; i < MAX_GLOBAL_REGS; i++)
01414 {
01415 program->wait_regs[i] = alloc_lbuf("prog_regs");
01416 memcpy(program->wait_regs[i], mudstate.global_regs[i], mudstate.glob_reg_len[i]+1);
01417 }
01418
01419
01420
01421 DESC_ITER_PLAYER(doer, d)
01422 {
01423 d->program_data = program;
01424
01425 queue_string(d, tprintf("%s>%s ", ANSI_HILITE, ANSI_NORMAL));
01426
01427 if (OPTION_YES == UsState(d, TELNET_EOR))
01428 {
01429
01430
01431 const char aEOR[2] = { NVT_IAC, NVT_EOR };
01432 queue_write_LEN(d, aEOR, sizeof(aEOR));
01433 }
01434 else if (OPTION_YES != UsState(d, TELNET_SGA))
01435 {
01436
01437
01438 const char aGoAhead[2] = { NVT_IAC, NVT_GA };
01439 queue_write_LEN(d, aGoAhead, sizeof(aGoAhead));
01440 }
01441 }
01442 }
01443
01444
01445
01446
01447 void do_restart(dbref executor, dbref caller, dbref enactor, int key)
01448 {
01449 UNUSED_PARAMETER(caller);
01450 UNUSED_PARAMETER(enactor);
01451 UNUSED_PARAMETER(key);
01452
01453 if (!Can_SiteAdmin(executor))
01454 {
01455 notify(executor, NOPERM_MESSAGE);
01456 return;
01457 }
01458
01459 bool bDenied = false;
01460 #ifndef WIN32
01461 if (mudstate.dumping)
01462 {
01463 notify(executor, "Dumping. Please try again later.");
01464 bDenied = true;
01465 }
01466 #endif // !WIN32
01467
01468
01469 if (!mudstate.bCanRestart)
01470 {
01471 notify(executor, "Server just started. Please try again in a few seconds.");
01472 bDenied = true;
01473 }
01474 if (bDenied)
01475 {
01476 STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT");
01477 log_text("Restart requested but not executed by ");
01478 log_name(executor);
01479 ENDLOG;
01480 return;
01481 }
01482
01483 raw_broadcast(0, "GAME: Restart by %s, please wait.", Name(Owner(executor)));
01484 STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT");
01485 log_text("Restart by ");
01486 log_name(executor);
01487 ENDLOG;
01488
01489 local_presync_database();
01490
01491 #ifndef MEMORY_BASED
01492 al_store();
01493 #endif
01494 pcache_sync();
01495 dump_database_internal(DUMP_I_RESTART);
01496 SYNC;
01497 CLOSE;
01498
01499 #ifdef WIN32 // WIN32
01500
01501 WSACleanup();
01502 exit(12345678);
01503
01504 #else // WIN32
01505
01506 dump_restart_db();
01507
01508 CleanUpSlaveSocket();
01509 CleanUpSlaveProcess();
01510
01511 Log.StopLogging();
01512
01513 #ifdef GAME_DOOFERMUX
01514 execl("bin/netmux", mudconf.mud_name, "-c", mudconf.config_file, "-p", mudconf.pid_file, NULL);
01515 #else
01516 execl("bin/netmux", "netmux", "-c", mudconf.config_file, "-p", mudconf.pid_file, NULL);
01517 #endif // GAME_DOOFERMUX
01518 #endif // !WIN32
01519 }
01520
01521
01522
01523
01524
01525
01526
01527 #ifdef WIN32
01528
01529 void do_backup(dbref player, dbref caller, dbref enactor, int key)
01530 {
01531 UNUSED_PARAMETER(caller);
01532 UNUSED_PARAMETER(enactor);
01533 UNUSED_PARAMETER(key);
01534
01535 notify(player, "This feature is not yet available on Win32-hosted MUX.");
01536 }
01537
01538 #else // WIN32
01539
01540 void do_backup(dbref player, dbref caller, dbref enactor, int key)
01541 {
01542 #ifndef WIN32
01543 if (mudstate.dumping)
01544 {
01545 notify(player, "Dumping. Please try again later.");
01546 }
01547 #endif // !WIN32
01548
01549 raw_broadcast(0, "GAME: Backing up database. Please wait.");
01550 STARTLOG(LOG_ALWAYS, "WIZ", "BACK");
01551 log_text("Backup by ");
01552 log_name(player);
01553 ENDLOG;
01554
01555 #ifdef MEMORY_BASED
01556
01557
01558
01559 dump_database_internal(DUMP_I_FLAT);
01560 system(tprintf("./_backupflat.sh %s.FLAT 1>&2", mudconf.indb));
01561 #else // MEMORY_BASED
01562
01563
01564
01565 dump_database_internal(DUMP_I_NORMAL);
01566 system(tprintf("./_backupflat.sh 1>&2"));
01567 #endif // MEMORY_BASED
01568 raw_broadcast(0, "GAME: Backup finished.");
01569 }
01570 #endif // WIN32
01571
01572
01573
01574
01575
01576 void do_comment(dbref player, dbref caller, dbref enactor, int key)
01577 {
01578 UNUSED_PARAMETER(player);
01579 UNUSED_PARAMETER(caller);
01580 UNUSED_PARAMETER(enactor);
01581 UNUSED_PARAMETER(key);
01582 }
01583
01584 static dbref promote_dflt(dbref old, dbref new0)
01585 {
01586 if ( old == NOPERM
01587 || new0 == NOPERM)
01588 {
01589 return NOPERM;
01590 }
01591 if ( old == AMBIGUOUS
01592 || new0 == AMBIGUOUS)
01593 {
01594 return AMBIGUOUS;
01595 }
01596 return NOTHING;
01597 }
01598
01599 dbref match_possessed(dbref player, dbref thing, char *target, dbref dflt, bool check_enter)
01600 {
01601
01602
01603 if (Good_obj(dflt))
01604 {
01605 return dflt;
01606 }
01607
01608
01609
01610 dbref result, result1;
01611 char *buff, *place, *s1, *d1, *temp;
01612 char *start = target;
01613 while (*target)
01614 {
01615
01616
01617 place = target;
01618 target = strchr(place, '\'');
01619 if ( target == NULL
01620 || !*target)
01621 {
01622 return dflt;
01623 }
01624
01625
01626
01627 if (place == target)
01628 {
01629 target++;
01630 continue;
01631 }
01632
01633
01634
01635 temp = target++;
01636 if (!*target)
01637 {
01638 return dflt;
01639 }
01640 if ( *target != 's'
01641 && *target != 'S'
01642 && *target != ' ')
01643 {
01644 continue;
01645 }
01646
01647
01648
01649
01650 if (*target != ' ')
01651 {
01652 target++;
01653 if (!*target)
01654 {
01655 return dflt;
01656 }
01657 if (*target != ' ')
01658 {
01659 continue;
01660 }
01661 }
01662
01663
01664
01665 buff = alloc_lbuf("is_posess");
01666 for (s1 = start, d1 = buff; *s1 && (s1 < temp); *d1++ = (*s1++))
01667 {
01668 ;
01669 }
01670 *d1 = '\0';
01671
01672
01673
01674
01675 init_match(thing, buff, NOTYPE);
01676 if (player == thing)
01677 {
01678 match_neighbor();
01679 match_possession();
01680 }
01681 else
01682 {
01683 match_possession();
01684 }
01685 result1 = match_result();
01686
01687 free_lbuf(buff);
01688 if (!Good_obj(result1))
01689 {
01690 dflt = promote_dflt(dflt, result1);
01691 continue;
01692 }
01693
01694
01695
01696 bool control = Controls(player, result1);
01697 if ( ( Dark(result1)
01698 || Opaque(result1))
01699 && !control)
01700 {
01701 dflt = promote_dflt(dflt, NOTHING);
01702 continue;
01703 }
01704
01705
01706
01707 if ( check_enter
01708 && !Enter_ok(result1)
01709 && !control)
01710 {
01711 dflt = promote_dflt(dflt, NOPERM);
01712 continue;
01713 }
01714
01715
01716
01717 init_match(result1, target, NOTYPE);
01718 match_possession();
01719 result = match_result();
01720 result = match_possessed(player, result1, target, result, check_enter);
01721 if (Good_obj(result))
01722 {
01723 return result;
01724 }
01725 dflt = promote_dflt(dflt, result);
01726 }
01727 return dflt;
01728 }
01729
01730
01731
01732
01733
01734 void parse_range(char **name, dbref *low_bound, dbref *high_bound)
01735 {
01736 char *buff1 = *name;
01737 if (buff1 && *buff1)
01738 {
01739 *name = parse_to(&buff1, ',', EV_STRIP_TS);
01740 }
01741 if (buff1 && *buff1)
01742 {
01743 char *buff2 = parse_to(&buff1, ',', EV_STRIP_TS);
01744 if (buff1 && *buff1)
01745 {
01746 while (mux_isspace(*buff1))
01747 {
01748 buff1++;
01749 }
01750
01751 if (*buff1 == NUMBER_TOKEN)
01752 {
01753 buff1++;
01754 }
01755
01756 *high_bound = mux_atol(buff1);
01757 if (*high_bound >= mudstate.db_top)
01758 {
01759 *high_bound = mudstate.db_top - 1;
01760 }
01761 }
01762 else
01763 {
01764 *high_bound = mudstate.db_top - 1;
01765 }
01766
01767 while (mux_isspace(*buff2))
01768 {
01769 buff2++;
01770 }
01771
01772 if (*buff2 == NUMBER_TOKEN)
01773 {
01774 buff2++;
01775 }
01776
01777 *low_bound = mux_atol(buff2);
01778 if (*low_bound < 0)
01779 {
01780 *low_bound = 0;
01781 }
01782 }
01783 else
01784 {
01785 *low_bound = 0;
01786 *high_bound = mudstate.db_top - 1;
01787 }
01788 }
01789
01790 bool parse_thing_slash(dbref player, char *thing, char **after, dbref *it)
01791 {
01792
01793
01794 char *str = thing;
01795 while ( *str != '\0'
01796 && *str != '/')
01797 {
01798 str++;
01799 }
01800
01801
01802
01803 if (*str == '\0')
01804 {
01805 *after = NULL;
01806 *it = NOTHING;
01807 return false;
01808 }
01809 *str++ = '\0';
01810 *after = str;
01811
01812
01813
01814 init_match(player, thing, NOTYPE);
01815 match_everything(MAT_EXIT_PARENTS);
01816 *it = match_result();
01817
01818
01819
01820 return Good_obj(*it);
01821 }
01822
01823 bool get_obj_and_lock(dbref player, char *what, dbref *it, ATTR **attr, char *errmsg, char **bufc)
01824 {
01825 char *str, *tbuf;
01826 int anum;
01827
01828 tbuf = alloc_lbuf("get_obj_and_lock");
01829 strcpy(tbuf, what);
01830 if (parse_thing_slash(player, tbuf, &str, it))
01831 {
01832
01833
01834 if (!search_nametab(player, lock_sw, str, &anum))
01835 {
01836 free_lbuf(tbuf);
01837 safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01838 return false;
01839 }
01840 }
01841 else
01842 {
01843
01844
01845 *it = match_thing_quiet(player, what);
01846 if (!Good_obj(*it))
01847 {
01848 free_lbuf(tbuf);
01849 safe_match_result(*it, errmsg, bufc);
01850 return false;
01851 }
01852 anum = A_LOCK;
01853 }
01854
01855
01856
01857 free_lbuf(tbuf);
01858 *attr = atr_num(anum);
01859 if (!(*attr))
01860 {
01861 safe_str("#-1 LOCK NOT FOUND", errmsg, bufc);
01862 return false;
01863 }
01864 return true;
01865 }
01866
01867
01868
01869
01870
01871 bool bCanReadAttr(dbref executor, dbref target, ATTR *tattr, bool bCheckParent)
01872 {
01873 if (!tattr)
01874 {
01875 return false;
01876 }
01877
01878 dbref aowner;
01879 int aflags;
01880
01881 if ( !mudstate.bStandAlone
01882 && bCheckParent)
01883 {
01884 atr_pget_info(target, tattr->number, &aowner, &aflags);
01885 }
01886 else
01887 {
01888 atr_get_info(target, tattr->number, &aowner, &aflags);
01889 }
01890
01891 int mAllow = AF_VISUAL;
01892 if ( (tattr->flags & mAllow)
01893 || (aflags & mAllow))
01894 {
01895 if ( mudstate.bStandAlone
01896 || tattr->number != A_DESC
01897 || mudconf.read_rem_desc
01898 || nearby(executor, target))
01899 {
01900 return true;
01901 }
01902 }
01903 int mDeny = 0;
01904 if (WizRoy(executor))
01905 {
01906 if (God(executor))
01907 {
01908 mDeny = AF_INTERNAL;
01909 }
01910 else
01911 {
01912 mDeny = AF_INTERNAL|AF_DARK;
01913 }
01914 }
01915 else if ( Owner(executor) == aowner
01916 || Examinable(executor, target))
01917 {
01918 mDeny = AF_INTERNAL|AF_DARK|AF_MDARK;
01919 }
01920 if (mDeny)
01921 {
01922 if ( (tattr->flags & mDeny)
01923 || (aflags & mDeny))
01924 {
01925 return false;
01926 }
01927 else
01928 {
01929 return true;
01930 }
01931 }
01932 return false;
01933 }
01934
01935 bool bCanSetAttr(dbref executor, dbref target, ATTR *tattr)
01936 {
01937 if (!tattr)
01938 {
01939 return false;
01940 }
01941
01942 int mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST;
01943 if (!God(executor))
01944 {
01945 if (God(target))
01946 {
01947 return false;
01948 }
01949 if (Wizard(executor))
01950 {
01951 mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST|AF_LOCK|AF_GOD;
01952 }
01953 else if (Controls(executor, target))
01954 {
01955 mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST|AF_LOCK|AF_WIZARD|AF_GOD;
01956 }
01957 else
01958 {
01959 return false;
01960 }
01961 }
01962
01963 dbref aowner;
01964 int aflags;
01965 if ( (tattr->flags & mDeny)
01966 #ifdef FIRANMUX
01967 || Immutable(target)
01968 #endif
01969 || ( atr_get_info(target, tattr->number, &aowner, &aflags)
01970 && (aflags & mDeny)))
01971 {
01972 return false;
01973 }
01974 else
01975 {
01976 return true;
01977 }
01978 }
01979
01980 bool bCanLockAttr(dbref executor, dbref target, ATTR *tattr)
01981 {
01982 if (!tattr)
01983 {
01984 return false;
01985 }
01986
01987 int mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST;
01988 if (!God(executor))
01989 {
01990 if (God(target))
01991 {
01992 return false;
01993 }
01994 if (Wizard(executor))
01995 {
01996 mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST|AF_GOD;
01997 }
01998 else
01999 {
02000 mDeny = AF_INTERNAL|AF_IS_LOCK|AF_CONST|AF_WIZARD|AF_GOD;
02001 }
02002 }
02003
02004 dbref aowner;
02005 int aflags;
02006 if ( (tattr->flags & mDeny)
02007 || !atr_get_info(target, tattr->number, &aowner, &aflags)
02008 || (aflags & mDeny))
02009 {
02010 return false;
02011 }
02012 else if ( Wizard(executor)
02013 || Owner(executor) == aowner)
02014 {
02015 return true;
02016 }
02017 else
02018 {
02019 return false;
02020 }
02021 }
02022
02023
02024
02025
02026
02027
02028 dbref where_is(dbref what)
02029 {
02030 if (!Good_obj(what))
02031 {
02032 return NOTHING;
02033 }
02034
02035 dbref loc;
02036 switch (Typeof(what))
02037 {
02038 case TYPE_PLAYER:
02039 case TYPE_THING:
02040 loc = Location(what);
02041 break;
02042
02043 case TYPE_EXIT:
02044 loc = Exits(what);
02045 break;
02046
02047 default:
02048 loc = NOTHING;
02049 break;
02050 }
02051 return loc;
02052 }
02053
02054
02055
02056
02057
02058
02059 dbref where_room(dbref what)
02060 {
02061 for (int count = mudconf.ntfy_nest_lim; count > 0; count--)
02062 {
02063 if (!Good_obj(what))
02064 {
02065 break;
02066 }
02067 if (isRoom(what))
02068 {
02069 return what;
02070 }
02071 if (!Has_location(what))
02072 {
02073 break;
02074 }
02075 what = Location(what);
02076 }
02077 return NOTHING;
02078 }
02079
02080 bool locatable(dbref player, dbref it, dbref enactor)
02081 {
02082
02083
02084 if (!Good_obj(it))
02085 {
02086 return false;
02087 }
02088
02089 dbref loc_it = where_is(it);
02090
02091
02092
02093
02094
02095 if ( Examinable(player, it)
02096 || Find_Unfindable(player)
02097 || loc_it == player
02098 || ( loc_it != NOTHING
02099 && ( Examinable(player, loc_it)
02100 || loc_it == where_is(player)))
02101 || Wizard(enactor)
02102 || it == enactor)
02103 {
02104 return true;
02105 }
02106
02107 dbref room_it = where_room(it);
02108 bool findable_room;
02109 if (Good_obj(room_it))
02110 {
02111 findable_room = Findable(room_it);
02112 }
02113 else
02114 {
02115 findable_room = true;
02116 }
02117
02118
02119
02120
02121 if ( ( room_it != NOTHING
02122 && Examinable(player, room_it))
02123 || Find_Unfindable(player)
02124 || ( Findable(it)
02125 && findable_room))
02126 {
02127 return true;
02128 }
02129
02130
02131
02132 return false;
02133 }
02134
02135
02136
02137
02138
02139
02140 bool nearby(dbref player, dbref thing)
02141 {
02142 if ( !Good_obj(player)
02143 || !Good_obj(thing))
02144 {
02145 return false;
02146 }
02147 if ( Can_Hide(thing)
02148 && Hidden(thing)
02149 && !See_Hidden(player))
02150 {
02151 return false;
02152 }
02153 dbref thing_loc = where_is(thing);
02154 if (thing_loc == player)
02155 {
02156 return true;
02157 }
02158 dbref player_loc = where_is(player);
02159 if ( thing_loc == player_loc
02160 || thing == player_loc)
02161 {
02162 return true;
02163 }
02164 return false;
02165 }
02166
02167
02168
02169
02170
02171 bool exit_visible(dbref exit, dbref player, int key)
02172 {
02173 #ifdef WOD_REALMS
02174 if (!mudstate.bStandAlone)
02175 {
02176 int iRealmDirective = DoThingToThingVisibility(player, exit,
02177 ACTION_IS_STATIONARY);
02178 if (REALM_DO_HIDDEN_FROM_YOU == iRealmDirective)
02179 {
02180 return false;
02181 }
02182 }
02183 #endif // WOD_REALMS
02184
02185 #ifdef REALITY_LVLS
02186 if (!mudstate.bStandAlone)
02187 {
02188 if (!IsReal(player, exit))
02189 return 0;
02190 }
02191 #endif
02192
02193
02194
02195 if ( (key & VE_LOC_XAM)
02196 || Examinable(player, exit)
02197 || Light(exit))
02198 {
02199 return true;
02200 }
02201
02202
02203
02204 if ( (key & (VE_LOC_DARK | VE_BASE_DARK))
02205 || Dark(exit))
02206 {
02207 return false;
02208 }
02209
02210
02211
02212 return true;
02213 }
02214
02215
02216
02217 bool exit_displayable(dbref exit, dbref player, int key)
02218 {
02219
02220
02221 if (Dark(exit))
02222 {
02223 return false;
02224 }
02225
02226 #ifdef WOD_REALMS
02227 if (!mudstate.bStandAlone)
02228 {
02229 int iRealmDirective = DoThingToThingVisibility(player, exit,
02230 ACTION_IS_STATIONARY);
02231 if (REALM_DO_HIDDEN_FROM_YOU == iRealmDirective)
02232 {
02233 return false;
02234 }
02235 }
02236 #endif // WOD_REALMS
02237
02238
02239
02240 if (Light(exit))
02241 {
02242 return true;
02243 }
02244
02245
02246
02247 if (key & (VE_LOC_DARK | VE_BASE_DARK))
02248 {
02249 return false;
02250 }
02251
02252
02253
02254 return true;
02255 }
02256
02257
02258
02259
02260
02261 void did_it(dbref player, dbref thing, int what, const char *def, int owhat,
02262 const char *odef, int awhat, char *args[], int nargs)
02263 {
02264 if (MuxAlarm.bAlarmed)
02265 {
02266 return;
02267 }
02268
02269 char *d, *buff, *act, *charges, *bp, *str;
02270 dbref loc, aowner;
02271 int num, aflags;
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283 bool need_pres = false;
02284 char **preserve = NULL;
02285 int *preserve_len = NULL;
02286
02287
02288
02289 if (what > 0)
02290 {
02291 d = atr_pget(thing, what, &aowner, &aflags);
02292 if (*d)
02293 {
02294 need_pres = true;
02295 preserve = PushPointers(MAX_GLOBAL_REGS);
02296 preserve_len = PushIntegers(MAX_GLOBAL_REGS);
02297 save_global_regs("did_it_save", preserve, preserve_len);
02298 buff = bp = alloc_lbuf("did_it.1");
02299 str = d;
02300 mux_exec(buff, &bp, thing, player, player,
02301 EV_EVAL | EV_FIGNORE | EV_FCHECK | EV_TOP, &str, args, nargs);
02302 *bp = '\0';
02303 if ( (aflags & AF_HTML)
02304 && Html(player))
02305 {
02306 safe_str("\r\n", buff, &bp);
02307 *bp = '\0';
02308 notify_html(player, buff);
02309 }
02310 else
02311 {
02312 notify(player, buff);
02313 }
02314 free_lbuf(buff);
02315 }
02316 else if (def)
02317 {
02318 notify(player, def);
02319 }
02320 free_lbuf(d);
02321 }
02322 if (what < 0 && def)
02323 {
02324 notify(player, def);
02325 }
02326
02327
02328
02329 if ( owhat > 0
02330 && Has_location(player)
02331 && Good_obj(loc = Location(player)))
02332 {
02333 d = atr_pget(thing, owhat, &aowner, &aflags);
02334 if (*d)
02335 {
02336 if (!need_pres)
02337 {
02338 need_pres = true;
02339 preserve = PushPointers(MAX_GLOBAL_REGS);
02340 preserve_len = PushIntegers(MAX_GLOBAL_REGS);
02341 save_global_regs("did_it_save", preserve, preserve_len);
02342 }
02343 buff = bp = alloc_lbuf("did_it.2");
02344 str = d;
02345 mux_exec(buff, &bp, thing, player, player,
02346 EV_EVAL | EV_FIGNORE | EV_FCHECK | EV_TOP, &str, args, nargs);
02347 *bp = '\0';
02348 if (*buff)
02349 {
02350 #ifdef REALITY_LVLS
02351 notify_except2_rlevel(loc, player, player, thing, tprintf("%s %s", Name(player), buff));
02352 #else
02353 notify_except2(loc, player, player, thing, tprintf("%s %s", Name(player), buff));
02354 #endif
02355 }
02356 free_lbuf(buff);
02357 }
02358 else if (odef)
02359 {
02360 #ifdef REALITY_LVLS
02361 notify_except2_rlevel(loc, player, player, thing, tprintf("%s %s", Name(player), odef));
02362 #else
02363 notify_except2(loc, player, player, thing, tprintf("%s %s", Name(player), odef));
02364 #endif
02365 }
02366 free_lbuf(d);
02367 }
02368 if ( owhat < 0
02369 && odef
02370 && Has_location(player)
02371 && Good_obj(loc = Location(player)))
02372 {
02373 #ifdef REALITY_LVLS
02374 notify_except2_rlevel(loc, player, player, thing, tprintf("%s %s", Name(player), odef));
02375 #else
02376 notify_except2(loc, player, player, thing, tprintf("%s %s", Name(player), odef));
02377 #endif
02378 }
02379
02380
02381
02382 if (need_pres)
02383 {
02384 restore_global_regs("did_it_restore", preserve, preserve_len);
02385 PopIntegers(preserve_len, MAX_GLOBAL_REGS);
02386 PopPointers(preserve, MAX_GLOBAL_REGS);
02387 }
02388
02389
02390
02391 #ifdef REALITY_LVLS
02392 if (awhat > 0 && IsReal(thing, player))
02393 #else
02394 if (awhat > 0)
02395 #endif
02396 {
02397 if (*(act = atr_pget(thing, awhat, &aowner, &aflags)))
02398 {
02399 charges = atr_pget(thing, A_CHARGES, &aowner, &aflags);
02400 if (*charges)
02401 {
02402 num = mux_atol(charges);
02403 if (num > 0)
02404 {
02405 buff = alloc_sbuf("did_it.charges");
02406 mux_ltoa(num-1, buff);
02407 atr_add_raw(thing, A_CHARGES, buff);
02408 free_sbuf(buff);
02409 }
02410 else if (*(buff = atr_pget(thing, A_RUNOUT, &aowner, &aflags)))
02411 {
02412 free_lbuf(act);
02413 act = buff;
02414 }
02415 else
02416 {
02417 free_lbuf(act);
02418 free_lbuf(buff);
02419 free_lbuf(charges);
02420 return;
02421 }
02422 }
02423 free_lbuf(charges);
02424 CLinearTimeAbsolute lta;
02425 wait_que(thing, player, player, false, lta, NOTHING, 0, act,
02426 args, nargs, mudstate.global_regs);
02427 }
02428 free_lbuf(act);
02429 }
02430 }
02431
02432
02433
02434
02435
02436 void do_verb(dbref executor, dbref caller, dbref enactor, int key,
02437 char *victim_str, char *args[], int nargs)
02438 {
02439 UNUSED_PARAMETER(caller);
02440 UNUSED_PARAMETER(key);
02441
02442
02443
02444 if ( !victim_str
02445 || !*victim_str)
02446 {
02447 notify(executor, "Nothing to do.");
02448 return;
02449 }
02450
02451
02452
02453 init_match(executor, victim_str, NOTYPE);
02454 match_everything(MAT_EXIT_PARENTS);
02455 dbref victim = noisy_match_result();
02456 if (!Good_obj(victim))
02457 {
02458 return;
02459 }
02460
02461
02462
02463 dbref actor;
02464 if ( nargs >= 1
02465 && args[0] && *args[0])
02466 {
02467 init_match(executor, args[0], NOTYPE);
02468 match_everything(MAT_EXIT_PARENTS);
02469 actor = noisy_match_result();
02470 if (!Good_obj(actor))
02471 {
02472 return;
02473 }
02474 }
02475 else
02476 {
02477 actor = enactor;
02478 }
02479
02480
02481
02482
02483
02484
02485
02486
02487
02488
02489 if (!Controls(executor, actor))
02490 {
02491 notify_quiet(executor, "Permission denied,");
02492 return;
02493 }
02494
02495 ATTR *ap;
02496 int what = -1;
02497 int owhat = -1;
02498 int awhat = -1;
02499 const char *whatd = NULL;
02500 const char *owhatd = NULL;
02501 int nxargs = 0;
02502 dbref aowner = NOTHING;
02503 int aflags = NOTHING;
02504 char *xargs[10];
02505
02506 switch (nargs)
02507 {
02508 case 7:
02509
02510
02511 parse_arglist(victim, actor, actor, args[6], '\0',
02512 EV_STRIP_LS | EV_STRIP_TS, xargs, 10, (char **)NULL, 0, &nxargs);
02513
02514 case 6:
02515
02516
02517 ap = atr_str(args[5]);
02518 if (ap)
02519 {
02520 awhat = ap->number;
02521 }
02522
02523 case 5:
02524
02525
02526 if (args[4] && *args[4])
02527 {
02528 owhatd = args[4];
02529 }
02530
02531 case 4:
02532
02533
02534 ap = atr_str(args[3]);
02535 if (ap && (ap->number > 0))
02536 {
02537 owhat = ap->number;
02538 }
02539
02540 case 3:
02541
02542
02543 if (args[2] && *args[2])
02544 {
02545 whatd = args[2];
02546 }
02547
02548 case 2:
02549
02550
02551 ap = atr_str(args[1]);
02552 if (ap && (ap->number > 0))
02553 {
02554 what = ap->number;
02555 }
02556 }
02557
02558
02559
02560 if (!Controls(executor, victim))
02561 {
02562 ap = NULL;
02563 if (what != -1)
02564 {
02565 atr_get_info(victim, what, &aowner, &aflags);
02566 ap = atr_num(what);
02567 }
02568 if ( !ap
02569 || !bCanReadAttr(executor, victim, ap, false)
02570 || ( ap->number == A_DESC
02571 && !mudconf.read_rem_desc
02572 && !Examinable(executor, victim)
02573 && !nearby(executor, victim)))
02574 {
02575 what = -1;
02576 }
02577
02578 ap = NULL;
02579 if (owhat != -1)
02580 {
02581 atr_get_info(victim, owhat, &aowner, &aflags);
02582 ap = atr_num(owhat);
02583 }
02584 if ( !ap
02585 || !bCanReadAttr(executor, victim, ap, false)
02586 || ( ap->number == A_DESC
02587 && !mudconf.read_rem_desc
02588 && !Examinable(executor, victim)
02589 && !nearby(executor, victim)))
02590 {
02591 owhat = -1;
02592 }
02593
02594 awhat = 0;
02595 }
02596
02597
02598
02599 did_it(actor, victim, what, whatd, owhat, owhatd, awhat, xargs, nxargs);
02600
02601
02602
02603 for (int i = 0; i < nxargs; i++)
02604 {
02605 free_lbuf(xargs[i]);
02606 }
02607 }
02608
02609
02610
02611
02612 void OutOfMemory(const char *SourceFile, unsigned int LineNo)
02613 {
02614 Log.tinyprintf("%s(%u): Out of memory." ENDLINE, SourceFile, LineNo);
02615 Log.Flush();
02616 if ( !mudstate.bStandAlone
02617 && mudstate.bCanRestart)
02618 {
02619 do_restart(GOD, GOD, GOD, 0);
02620 }
02621 else
02622 {
02623 abort();
02624 }
02625 }
02626
02627
02628
02629
02630 bool AssertionFailed(const char *SourceFile, unsigned int LineNo)
02631 {
02632 Log.tinyprintf("%s(%u): Assertion failed." ENDLINE, SourceFile, LineNo);
02633 Log.Flush();
02634 if ( !mudstate.bStandAlone
02635 && mudstate.bCanRestart)
02636 {
02637 do_restart(GOD, GOD, GOD, 0);
02638 }
02639 else
02640 {
02641 abort();
02642 }
02643 return false;
02644 }