00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include "copyright.h"
00011 #include "autoconf.h"
00012 #include "config.h"
00013 #include "externs.h"
00014
00015 #include <time.h>
00016
00017 #include "ansi.h"
00018 #include "attrs.h"
00019 #include "command.h"
00020 #include "comsys.h"
00021 #include "file_c.h"
00022 #include "functions.h"
00023 #include "mguests.h"
00024 #include "powers.h"
00025 #include "svdreport.h"
00026 #ifdef REALITY_LVLS
00027 #include "levels.h"
00028 #endif
00029
00030
00031
00032
00033
00034
00035 void make_portlist(dbref player, dbref target, char *buff, char **bufc)
00036 {
00037 UNUSED_PARAMETER(player);
00038
00039 ITL itl;
00040 ItemToList_Init(&itl, buff, bufc);
00041
00042 DESC *d;
00043 DESC_ITER_CONN(d)
00044 {
00045 if ( d->player == target
00046 && !ItemToList_AddInteger(&itl, d->descriptor))
00047 {
00048 break;
00049 }
00050 }
00051 ItemToList_Final(&itl);
00052 }
00053
00054
00055
00056
00057
00058 void make_port_ulist(dbref player, char *buff, char **bufc)
00059 {
00060 DESC *d;
00061 ITL itl;
00062 char *tmp = alloc_sbuf("make_port_ulist");
00063 ItemToList_Init(&itl, buff, bufc, '#');
00064 DESC_ITER_CONN(d)
00065 {
00066 if ( !See_Hidden(player)
00067 && Hidden(d->player))
00068 {
00069 continue;
00070 }
00071
00072
00073
00074 char *p = tmp;
00075 p += mux_ltoa(d->player, p);
00076 *p++ = ':';
00077 p += mux_ltoa(d->descriptor, p);
00078
00079 size_t n = p - tmp;
00080 if (!ItemToList_AddStringLEN(&itl, n, tmp))
00081 {
00082 break;
00083 }
00084 }
00085 ItemToList_Final(&itl);
00086 free_sbuf(tmp);
00087 }
00088
00089
00090
00091
00092
00093 void update_quotas(CLinearTimeAbsolute& ltaLast, const CLinearTimeAbsolute& ltaCurrent)
00094 {
00095 if (ltaCurrent < ltaLast)
00096 {
00097 ltaLast = ltaCurrent;
00098 return;
00099 }
00100
00101 CLinearTimeDelta ltdDiff = ltaCurrent - ltaLast;
00102 if (ltdDiff < mudconf.timeslice)
00103 {
00104 return;
00105 }
00106
00107 int nSlices = ltdDiff / mudconf.timeslice;
00108 int nExtraQuota = mudconf.cmd_quota_incr * nSlices;
00109
00110 if (nExtraQuota > 0)
00111 {
00112 DESC *d;
00113 DESC_ITER_ALL(d)
00114 {
00115 d->quota += nExtraQuota;
00116 if (d->quota > mudconf.cmd_quota_max)
00117 {
00118 d->quota = mudconf.cmd_quota_max;
00119 }
00120 }
00121 }
00122 ltaLast += mudconf.timeslice * nSlices;
00123 }
00124
00125
00126 void raw_notify_html(dbref player, const char *msg)
00127 {
00128 if (!msg || !*msg)
00129 {
00130 return;
00131 }
00132
00133 if ( mudstate.inpipe
00134 && player == mudstate.poutobj)
00135 {
00136 safe_str(msg, mudstate.poutnew, &mudstate.poutbufc);
00137 return;
00138 }
00139 if ( !Connected(player)
00140 || !Html(player))
00141 {
00142 return;
00143 }
00144
00145 DESC *d;
00146 DESC_ITER_PLAYER(player, d)
00147 {
00148 queue_string(d, msg);
00149 }
00150 }
00151
00152
00153
00154
00155
00156 void raw_notify(dbref player, const char *msg)
00157 {
00158 DESC *d;
00159
00160 if (!msg || !*msg)
00161 {
00162 return;
00163 }
00164
00165 if ( mudstate.inpipe
00166 && player == mudstate.poutobj)
00167 {
00168 safe_str(msg, mudstate.poutnew, &mudstate.poutbufc);
00169 safe_str("\r\n", mudstate.poutnew, &mudstate.poutbufc);
00170 return;
00171 }
00172
00173 if (!Connected(player))
00174 {
00175 return;
00176 }
00177
00178 DESC_ITER_PLAYER(player, d)
00179 {
00180 queue_string(d, msg);
00181 queue_write_LEN(d, "\r\n", 2);
00182 }
00183 }
00184
00185 void raw_notify_newline(dbref player)
00186 {
00187 if ( mudstate.inpipe
00188 && player == mudstate.poutobj)
00189 {
00190 safe_str("\r\n", mudstate.poutnew, &mudstate.poutbufc);
00191 return;
00192 }
00193 if (!Connected(player))
00194 {
00195 return;
00196 }
00197
00198 DESC *d;
00199 DESC_ITER_PLAYER(player, d)
00200 {
00201 queue_write_LEN(d, "\r\n", 2);
00202 }
00203 }
00204
00205
00206
00207
00208
00209 void DCL_CDECL raw_broadcast(int inflags, char *fmt, ...)
00210 {
00211 if (!fmt || !*fmt)
00212 {
00213 return;
00214 }
00215
00216 char buff[LBUF_SIZE];
00217
00218 va_list ap;
00219 va_start(ap, fmt);
00220 mux_vsnprintf(buff, LBUF_SIZE, fmt, ap);
00221 va_end(ap);
00222
00223 DESC *d;
00224 DESC_ITER_CONN(d)
00225 {
00226 if ((Flags(d->player) & inflags) == inflags)
00227 {
00228 queue_string(d, buff);
00229 queue_write_LEN(d, "\r\n", 2);
00230 process_output(d, false);
00231 }
00232 }
00233 }
00234
00235
00236
00237
00238
00239 void clearstrings(DESC *d)
00240 {
00241 if (d->output_prefix)
00242 {
00243 free_lbuf(d->output_prefix);
00244 d->output_prefix = NULL;
00245 }
00246 if (d->output_suffix)
00247 {
00248 free_lbuf(d->output_suffix);
00249 d->output_suffix = NULL;
00250 }
00251 }
00252
00253 static void add_to_output_queue(DESC *d, const char *b, int n)
00254 {
00255 TBLOCK *tp;
00256 int left;
00257
00258
00259
00260 if (d->output_head == NULL)
00261 {
00262 tp = (TBLOCK *)MEMALLOC(OUTPUT_BLOCK_SIZE);
00263 ISOUTOFMEMORY(tp);
00264 tp->hdr.nxt = NULL;
00265 tp->hdr.start = tp->data;
00266 tp->hdr.end = tp->data;
00267 tp->hdr.nchars = 0;
00268 d->output_head = tp;
00269 d->output_tail = tp;
00270 }
00271 else
00272 {
00273 tp = d->output_tail;
00274 }
00275
00276
00277
00278 do
00279 {
00280
00281
00282
00283 left = OUTPUT_BLOCK_SIZE - (tp->hdr.end - (char *)tp + 1);
00284 if (n <= left)
00285 {
00286 memcpy(tp->hdr.end, b, n);
00287 tp->hdr.end += n;
00288 tp->hdr.nchars += n;
00289 n = 0;
00290 }
00291 else
00292 {
00293
00294
00295
00296 if (left > 0)
00297 {
00298 memcpy(tp->hdr.end, b, left);
00299 tp->hdr.end += left;
00300 tp->hdr.nchars += left;
00301 b += left;
00302 n -= left;
00303 }
00304 tp = (TBLOCK *)MEMALLOC(OUTPUT_BLOCK_SIZE);
00305 ISOUTOFMEMORY(tp);
00306 tp->hdr.nxt = NULL;
00307 tp->hdr.start = tp->data;
00308 tp->hdr.end = tp->data;
00309 tp->hdr.nchars = 0;
00310 d->output_tail->hdr.nxt = tp;
00311 d->output_tail = tp;
00312 }
00313 } while (n > 0);
00314 }
00315
00316
00317
00318
00319
00320 void queue_write_LEN(DESC *d, const char *b, int n)
00321 {
00322 if (n <= 0)
00323 {
00324 return;
00325 }
00326
00327 if (d->output_size + n > mudconf.output_limit)
00328 {
00329 process_output(d, false);
00330 }
00331
00332 int left = mudconf.output_limit - d->output_size - n;
00333 if (left < 0)
00334 {
00335 TBLOCK *tp = d->output_head;
00336 if (tp == NULL)
00337 {
00338 STARTLOG(LOG_PROBLEMS, "QUE", "WRITE");
00339 log_text("Flushing when output_head is null!");
00340 ENDLOG;
00341 }
00342 else
00343 {
00344 STARTLOG(LOG_NET, "NET", "WRITE");
00345 char *buf = alloc_lbuf("queue_write.LOG");
00346 sprintf(buf, "[%u/%s] Output buffer overflow, %d chars discarded by ", d->descriptor, d->addr, tp->hdr.nchars);
00347 log_text(buf);
00348 free_lbuf(buf);
00349 if (d->flags & DS_CONNECTED)
00350 {
00351 log_name(d->player);
00352 }
00353 ENDLOG;
00354 d->output_size -= tp->hdr.nchars;
00355 d->output_head = tp->hdr.nxt;
00356 d->output_lost += tp->hdr.nchars;
00357 if (d->output_head == NULL)
00358 {
00359 d->output_tail = NULL;
00360 }
00361 MEMFREE(tp);
00362 tp = NULL;
00363 }
00364 }
00365
00366 add_to_output_queue(d, b, n);
00367 d->output_size += n;
00368 d->output_tot += n;
00369
00370 #ifdef WIN32
00371 if ( platform == VER_PLATFORM_WIN32_NT
00372 && !d->bWritePending
00373 && !d->bConnectionDropped)
00374 {
00375 d->bCallProcessOutputLater = true;
00376 }
00377 #endif
00378 }
00379
00380 void queue_write(DESC *d, const char *b)
00381 {
00382 queue_write_LEN(d, b, strlen(b));
00383 }
00384
00385 static const char *encode_iac(const char *szString)
00386 {
00387 static char Buffer[2*LBUF_SIZE];
00388 char *pBuffer = Buffer;
00389
00390 const char *pString = szString;
00391 if (pString)
00392 {
00393 while (*pString)
00394 {
00395 const char *p = strchr(pString, NVT_IAC);
00396 if (!p)
00397 {
00398
00399
00400 if (pString == szString)
00401 {
00402
00403
00404 return szString;
00405 }
00406 else
00407 {
00408 strcpy(pBuffer, pString);
00409 return Buffer;
00410 }
00411 }
00412 else
00413 {
00414
00415
00416 size_t n = p - pString + 1;
00417 memcpy(pBuffer, pString, n);
00418 pBuffer += n;
00419 pString += n;
00420
00421
00422
00423 *pBuffer++ = NVT_IAC;
00424 }
00425 }
00426 }
00427 *pBuffer = '\0';
00428 return Buffer;
00429 }
00430
00431 void queue_string(DESC *d, const char *s)
00432 {
00433 const char *p = s;
00434
00435 if (d->flags & DS_CONNECTED)
00436 {
00437 if ( !Ansi(d->player)
00438 && strchr(s, ESC_CHAR))
00439 {
00440 p = strip_ansi(p);
00441 }
00442 else if (NoBleed(d->player))
00443 {
00444 p = normal_to_white(p);
00445 }
00446
00447 if (NoAccents(d->player))
00448 {
00449 p = strip_accents(p);
00450 }
00451 }
00452 else
00453 {
00454 if (strchr(s, ESC_CHAR))
00455 {
00456 p = strip_ansi(p);
00457 }
00458 p = strip_accents(p);
00459 }
00460 p = encode_iac(p);
00461 queue_write(d, p);
00462 }
00463
00464 void freeqs(DESC *d)
00465 {
00466 TBLOCK *tb, *tnext;
00467 CBLK *cb, *cnext;
00468
00469 tb = d->output_head;
00470 while (tb)
00471 {
00472 tnext = tb->hdr.nxt;
00473 MEMFREE(tb);
00474 tb = tnext;
00475 }
00476 d->output_head = NULL;
00477 d->output_tail = NULL;
00478
00479 cb = d->input_head;
00480 while (cb)
00481 {
00482 cnext = (CBLK *) cb->hdr.nxt;
00483 free_lbuf(cb);
00484 cb = cnext;
00485 }
00486
00487 d->input_head = NULL;
00488 d->input_tail = NULL;
00489
00490 if (d->raw_input)
00491 {
00492 free_lbuf(d->raw_input);
00493 }
00494 d->raw_input = NULL;
00495
00496 d->raw_input_at = NULL;
00497 d->nOption = 0;
00498 d->raw_input_state = NVT_IS_NORMAL;
00499 d->nvt_sga_him_state = OPTION_NO;
00500 d->nvt_sga_us_state = OPTION_NO;
00501 d->nvt_eor_him_state = OPTION_NO;
00502 d->nvt_eor_us_state = OPTION_NO;
00503 d->nvt_naws_him_state = OPTION_NO;
00504 d->nvt_naws_us_state = OPTION_NO;
00505 d->height = 24;
00506 d->width = 78;
00507 }
00508
00509
00510
00511
00512
00513 void desc_addhash(DESC *d)
00514 {
00515 dbref player = d->player;
00516 DESC *hdesc = (DESC *)hashfindLEN(&player, sizeof(player), &mudstate.desc_htab);
00517 if (hdesc == NULL)
00518 {
00519 d->hashnext = NULL;
00520 hashaddLEN(&player, sizeof(player), d, &mudstate.desc_htab);
00521 }
00522 else
00523 {
00524 d->hashnext = hdesc;
00525 hashreplLEN(&player, sizeof(player), d, &mudstate.desc_htab);
00526 }
00527 }
00528
00529
00530
00531
00532
00533 static void desc_delhash(DESC *d)
00534 {
00535 dbref player = d->player;
00536 DESC *last = NULL;
00537 DESC *hdesc = (DESC *)hashfindLEN(&player, sizeof(player), &mudstate.desc_htab);
00538 while (hdesc != NULL)
00539 {
00540 if (d == hdesc)
00541 {
00542 if (last == NULL)
00543 {
00544 if (d->hashnext == NULL)
00545 {
00546 hashdeleteLEN(&player, sizeof(player), &mudstate.desc_htab);
00547 }
00548 else
00549 {
00550 hashreplLEN(&player, sizeof(player), d->hashnext, &mudstate.desc_htab);
00551 }
00552 }
00553 else
00554 {
00555 last->hashnext = d->hashnext;
00556 }
00557 break;
00558 }
00559 last = hdesc;
00560 hdesc = hdesc->hashnext;
00561 }
00562 d->hashnext = NULL;
00563 }
00564
00565 void welcome_user(DESC *d)
00566 {
00567 if (d->host_info & H_REGISTRATION)
00568 {
00569 fcache_dump(d, FC_CONN_REG);
00570 }
00571 else
00572 {
00573 fcache_dump(d, FC_CONN);
00574 }
00575 }
00576
00577 void save_command(DESC *d, CBLK *command)
00578 {
00579 command->hdr.nxt = NULL;
00580 if (d->input_tail == NULL)
00581 {
00582 d->input_head = command;
00583
00584
00585
00586 scheduler.DeferImmediateTask(PRIORITY_SYSTEM, Task_ProcessCommand, d, 0);
00587 }
00588 else
00589 {
00590 d->input_tail->hdr.nxt = command;
00591 }
00592 d->input_tail = command;
00593 }
00594
00595 static void set_userstring(char **userstring, const char *command)
00596 {
00597 while (mux_isspace(*command))
00598 {
00599 command++;
00600 }
00601
00602 if (!*command)
00603 {
00604 if (*userstring != NULL)
00605 {
00606 free_lbuf(*userstring);
00607 *userstring = NULL;
00608 }
00609 }
00610 else
00611 {
00612 if (*userstring == NULL)
00613 {
00614 *userstring = alloc_lbuf("set_userstring");
00615 }
00616 strcpy(*userstring, command);
00617 }
00618 }
00619
00620 static void parse_connect(const char *msg, char *command, char *user, char *pass)
00621 {
00622 if (strlen(msg) > MBUF_SIZE)
00623 {
00624 *command = '\0';
00625 *user = '\0';
00626 *pass = '\0';
00627 return;
00628 }
00629 while (mux_isspace(*msg))
00630 {
00631 msg++;
00632 }
00633 char *p = command;
00634 while ( *msg
00635 && !mux_isspace(*msg))
00636 {
00637 *p++ = *msg++;
00638 }
00639 *p = '\0';
00640 while (mux_isspace(*msg))
00641 {
00642 msg++;
00643 }
00644 p = user;
00645 if ( mudconf.name_spaces
00646 && *msg == '\"')
00647 {
00648 for (; *msg && (*msg == '\"' || mux_isspace(*msg)); msg++)
00649 {
00650
00651 }
00652 while ( *msg
00653 && *msg != '\"')
00654 {
00655 while ( *msg
00656 && !mux_isspace(*msg)
00657 && *msg != '\"')
00658 {
00659 *p++ = *msg++;
00660 }
00661
00662 if (*msg == '\"')
00663 {
00664 break;
00665 }
00666
00667 while (mux_isspace(*msg))
00668 {
00669 msg++;
00670 }
00671
00672 if ( *msg
00673 && *msg != '\"')
00674 {
00675 *p++ = ' ';
00676 }
00677 }
00678 while ( *msg
00679 && *msg == '\"')
00680 {
00681 msg++;
00682 }
00683 }
00684 else
00685 {
00686 while ( *msg
00687 && !mux_isspace(*msg))
00688 {
00689 *p++ = *msg++;
00690 }
00691 }
00692 *p = '\0';
00693 while (mux_isspace(*msg))
00694 {
00695 msg++;
00696 }
00697 p = pass;
00698 while ( *msg
00699 && !mux_isspace(*msg))
00700 {
00701 *p++ = *msg++;
00702 }
00703 *p = '\0';
00704 }
00705
00706 static void announce_connect(dbref player, DESC *d)
00707 {
00708 desc_addhash(d);
00709
00710 DESC *dtemp;
00711 int count = 0;
00712 DESC_ITER_CONN(dtemp)
00713 {
00714 count++;
00715 }
00716
00717 if (mudstate.record_players < count)
00718 {
00719 mudstate.record_players = count;
00720 }
00721
00722 char *buf = alloc_lbuf("announce_connect");
00723 dbref aowner;
00724 int aflags;
00725 size_t nLen;
00726 atr_pget_str_LEN(buf, player, A_TIMEOUT, &aowner, &aflags, &nLen);
00727 if (nLen)
00728 {
00729 d->timeout = mux_atol(buf);
00730 if (d->timeout <= 0)
00731 {
00732 d->timeout = mudconf.idle_timeout;
00733 }
00734 }
00735
00736 dbref loc = Location(player);
00737 s_Connected(player);
00738
00739 if (d->flags & DS_PUEBLOCLIENT)
00740 {
00741 s_Html(player);
00742 }
00743
00744 raw_notify( player, tprintf("\n%sMOTD:%s %s\n", ANSI_HILITE,
00745 ANSI_NORMAL, mudconf.motd_msg));
00746
00747 if (Wizard(player))
00748 {
00749 raw_notify(player, tprintf("%sWIZMOTD:%s %s\n", ANSI_HILITE,
00750 ANSI_NORMAL, mudconf.wizmotd_msg));
00751
00752 if (!(mudconf.control_flags & CF_LOGIN))
00753 {
00754 raw_notify(player, "*** Logins are disabled.");
00755 }
00756 }
00757 atr_get_str_LEN(buf, player, A_LPAGE, &aowner, &aflags, &nLen);
00758 if (nLen)
00759 {
00760 raw_notify(player, "Your PAGE LOCK is set. You may be unable to receive some pages.");
00761 }
00762 int num = 0;
00763 DESC_ITER_PLAYER(player, dtemp)
00764 {
00765 num++;
00766 }
00767
00768
00769
00770 s_Flags(player, FLAG_WORD2, Flags2(player) & ~VACATION);
00771
00772 char *pRoomAnnounceFmt;
00773 char *pMonitorAnnounceFmt;
00774 if (num < 2)
00775 {
00776 pRoomAnnounceFmt = "%s has connected.";
00777 if (mudconf.have_comsys)
00778 {
00779 do_comconnect(player);
00780 }
00781 if ( Hidden(player)
00782 && Can_Hide(player))
00783 {
00784 pMonitorAnnounceFmt = "GAME: %s has DARK-connected.";
00785 }
00786 else
00787 {
00788 pMonitorAnnounceFmt = "GAME: %s has connected.";
00789 }
00790 if ( Suspect(player)
00791 || (d->host_info & H_SUSPECT))
00792 {
00793 raw_broadcast(WIZARD, "[Suspect] %s has connected.", Moniker(player));
00794 }
00795 }
00796 else
00797 {
00798 pRoomAnnounceFmt = "%s has reconnected.";
00799 pMonitorAnnounceFmt = "GAME: %s has reconnected.";
00800 if ( Suspect(player)
00801 || (d->host_info & H_SUSPECT))
00802 {
00803 raw_broadcast(WIZARD, "[Suspect] %s has reconnected.", Moniker(player));
00804 }
00805 }
00806 sprintf(buf, pRoomAnnounceFmt, Moniker(player));
00807 raw_broadcast(MONITOR, pMonitorAnnounceFmt, Moniker(player));
00808
00809 int key = MSG_INV;
00810 if ( loc != NOTHING
00811 && !( Hidden(player)
00812 && Can_Hide(player)))
00813 {
00814 key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
00815 }
00816
00817 dbref temp = mudstate.curr_enactor;
00818 mudstate.curr_enactor = player;
00819 #ifdef REALITY_LVLS
00820 if(loc == NOTHING)
00821 notify_check(player, player, buf, key);
00822 else
00823 notify_except_rlevel(loc, player, player, buf, 0);
00824 #else
00825 notify_check(player, player, buf, key);
00826 #endif
00827 atr_pget_str_LEN(buf, player, A_ACONNECT, &aowner, &aflags, &nLen);
00828 CLinearTimeAbsolute lta;
00829 dbref zone, obj;
00830 if (nLen)
00831 {
00832 wait_que(player, player, player, false, lta, NOTHING, 0, buf,
00833 (char **)NULL, 0, NULL);
00834 }
00835 if (mudconf.master_room != NOTHING)
00836 {
00837 atr_pget_str_LEN(buf, mudconf.master_room, A_ACONNECT, &aowner,
00838 &aflags, &nLen);
00839 if (nLen)
00840 {
00841 wait_que(mudconf.master_room, player, player, false, lta,
00842 NOTHING, 0, buf, (char **)NULL, 0, NULL);
00843 }
00844 DOLIST(obj, Contents(mudconf.master_room))
00845 {
00846 atr_pget_str_LEN(buf, obj, A_ACONNECT, &aowner, &aflags, &nLen);
00847 if (nLen)
00848 {
00849 wait_que(obj, player, player, false, lta, NOTHING, 0, buf,
00850 (char **)NULL, 0, NULL);
00851 }
00852 }
00853 }
00854
00855
00856
00857 if ( mudconf.have_zones
00858 && Good_obj(zone = Zone(loc)))
00859 {
00860 switch (Typeof(zone))
00861 {
00862 case TYPE_THING:
00863
00864 atr_pget_str_LEN(buf, zone, A_ACONNECT, &aowner, &aflags, &nLen);
00865 if (nLen)
00866 {
00867 wait_que(zone, player, player, false, lta, NOTHING, 0, buf,
00868 (char **)NULL, 0, NULL);
00869 }
00870 break;
00871
00872 case TYPE_ROOM:
00873
00874
00875
00876 DOLIST(obj, Contents(zone))
00877 {
00878 atr_pget_str_LEN(buf, obj, A_ACONNECT, &aowner, &aflags,
00879 &nLen);
00880 if (nLen)
00881 {
00882 wait_que(obj, player, player, false, lta, NOTHING, 0,
00883 buf, (char **)NULL, 0, NULL);
00884 }
00885 }
00886 break;
00887
00888 default:
00889
00890 log_text(tprintf("Invalid zone #%d for %s(#%d) has bad type %d",
00891 zone, Name(player), player, Typeof(zone)));
00892 }
00893 }
00894 free_lbuf(buf);
00895 CLinearTimeAbsolute ltaNow;
00896 ltaNow.GetLocal();
00897 char *time_str = ltaNow.ReturnDateString(7);
00898
00899 record_login(player, true, time_str, d->addr, d->username,
00900 inet_ntoa((d->address).sin_addr));
00901 if (mudconf.have_mailer)
00902 {
00903 check_mail(player, 0, false);
00904 }
00905 look_in(player, Location(player), (LK_SHOWEXIT|LK_OBEYTERSE|LK_SHOWVRML));
00906 mudstate.curr_enactor = temp;
00907 if (Guest(player))
00908 {
00909 db[player].fs.word[FLAG_WORD1] &= ~DARK;
00910 }
00911 }
00912
00913 void announce_disconnect(dbref player, DESC *d, const char *reason)
00914 {
00915 int num = 0, key;
00916 DESC *dtemp;
00917 DESC_ITER_PLAYER(player, dtemp)
00918 {
00919 num++;
00920 }
00921
00922 dbref temp = mudstate.curr_enactor;
00923 mudstate.curr_enactor = player;
00924 dbref loc = Location(player);
00925
00926 if (num < 2)
00927 {
00928 if ( Suspect(player)
00929 || (d->host_info & H_SUSPECT))
00930 {
00931 raw_broadcast(WIZARD, "[Suspect] %s has disconnected.", Moniker(player));
00932 }
00933 char *buf = alloc_lbuf("announce_disconnect.only");
00934
00935 sprintf(buf, "%s has disconnected.", Moniker(player));
00936 key = MSG_INV;
00937 if ( loc != NOTHING
00938 && !( Hidden(player)
00939 && Can_Hide(player)))
00940 {
00941 key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
00942 }
00943 #ifdef REALITY_LVLS
00944 if(loc == NOTHING)
00945 notify_check(player, player, buf, key);
00946 else
00947 notify_except_rlevel(loc, player, player, buf, 0);
00948 #else
00949 notify_check(player, player, buf, key);
00950 #endif
00951
00952 if (mudconf.have_mailer)
00953 {
00954 do_mail_purge(player);
00955 }
00956
00957 raw_broadcast(MONITOR, "GAME: %s has disconnected. <%s>", Moniker(player), reason);
00958
00959 c_Connected(player);
00960
00961 if (mudconf.have_comsys)
00962 {
00963 do_comdisconnect(player);
00964 }
00965
00966 dbref aowner, zone, obj;
00967 int aflags;
00968 size_t nLen;
00969 char *argv[1];
00970 argv[0] = (char *)reason;
00971 CLinearTimeAbsolute lta;
00972 atr_pget_str_LEN(buf, player, A_ADISCONNECT, &aowner, &aflags, &nLen);
00973 if (nLen)
00974 {
00975 wait_que(player, player, player, false, lta, NOTHING, 0, buf,
00976 argv, 1, NULL);
00977 }
00978 if (mudconf.master_room != NOTHING)
00979 {
00980 atr_pget_str_LEN(buf, mudconf.master_room, A_ADISCONNECT, &aowner,
00981 &aflags, &nLen);
00982 if (nLen)
00983 {
00984 wait_que(mudconf.master_room, player, player, false, lta,
00985 NOTHING, 0, buf, (char **)NULL, 0, NULL);
00986 }
00987 DOLIST(obj, Contents(mudconf.master_room))
00988 {
00989 atr_pget_str_LEN(buf, obj, A_ADISCONNECT, &aowner, &aflags,
00990 &nLen);
00991 if (nLen)
00992 {
00993 wait_que(obj, player, player, false, lta, NOTHING, 0,
00994 buf, (char **)NULL, 0, NULL);
00995 }
00996 }
00997 }
00998
00999
01000
01001 if (mudconf.have_zones && Good_obj(zone = Zone(loc)))
01002 {
01003 switch (Typeof(zone))
01004 {
01005 case TYPE_THING:
01006
01007 atr_pget_str_LEN(buf, zone, A_ADISCONNECT, &aowner, &aflags,
01008 &nLen);
01009 if (nLen)
01010 {
01011 wait_que(zone, player, player, false, lta, NOTHING, 0,
01012 buf, (char **)NULL, 0, NULL);
01013 }
01014 break;
01015
01016 case TYPE_ROOM:
01017
01018
01019
01020 DOLIST(obj, Contents(zone))
01021 {
01022 atr_pget_str_LEN(buf, obj, A_ADISCONNECT, &aowner, &aflags,
01023 &nLen);
01024 if (nLen)
01025 {
01026 wait_que(obj, player, player, false, lta, NOTHING,
01027 0, buf, (char **)NULL, 0, NULL);
01028 }
01029 }
01030 break;
01031
01032 default:
01033 log_text(tprintf("Invalid zone #%d for %s(#%d) has bad type %d",
01034 zone, Name(player), player, Typeof(zone)));
01035 }
01036 }
01037 free_lbuf(buf);
01038 if (d->flags & DS_AUTODARK)
01039 {
01040 d->flags &= ~DS_AUTODARK;
01041 db[player].fs.word[FLAG_WORD1] &= ~DARK;
01042 }
01043
01044 if (Guest(player))
01045 {
01046 db[player].fs.word[FLAG_WORD1] |= DARK;
01047 halt_que(NOTHING, player);
01048 }
01049 }
01050 else
01051 {
01052 if ( Suspect(player)
01053 || (d->host_info & H_SUSPECT))
01054 {
01055 raw_broadcast(WIZARD, "[Suspect] %s has partially disconnected.", Moniker(player));
01056 }
01057 char *mbuf = alloc_mbuf("announce_disconnect.partial");
01058 sprintf(mbuf, "%s has partially disconnected.", Moniker(player));
01059 key = MSG_INV;
01060 if ( loc != NOTHING
01061 && !( Hidden(player)
01062 && Can_Hide(player)))
01063 {
01064 key |= (MSG_NBR | MSG_NBR_EXITS | MSG_LOC | MSG_FWDLIST);
01065 }
01066 #ifdef REALITY_LVLS
01067 if(loc == NOTHING)
01068 notify_check(player, player, mbuf, key);
01069 else
01070 notify_except_rlevel(loc, player, player, mbuf, 0);
01071 #else
01072 notify_check(player, player, mbuf, key);
01073 #endif
01074 raw_broadcast(MONITOR, "GAME: %s has partially disconnected.",
01075 Moniker(player));
01076 free_mbuf(mbuf);
01077 }
01078
01079 mudstate.curr_enactor = temp;
01080 desc_delhash(d);
01081
01082 local_disconnect(player, num);
01083 }
01084
01085 int boot_off(dbref player, const char *message)
01086 {
01087 DESC *d, *dnext;
01088 int count = 0;
01089 DESC_SAFEITER_PLAYER(player, d, dnext)
01090 {
01091 if (message && *message)
01092 {
01093 queue_string(d, message);
01094 queue_write_LEN(d, "\r\n", 2);
01095 }
01096 shutdownsock(d, R_BOOT);
01097 count++;
01098 }
01099 return count;
01100 }
01101
01102 int boot_by_port(SOCKET port, bool bGod, const char *message)
01103 {
01104 DESC *d, *dnext;
01105 int count = 0;
01106 DESC_SAFEITER_ALL(d, dnext)
01107 {
01108 if ( d->descriptor == port
01109 && ( bGod
01110 || !(d->flags & DS_CONNECTED)
01111 || !God(d->player)))
01112 {
01113 if ( message
01114 && *message)
01115 {
01116 queue_string(d, message);
01117 queue_write_LEN(d, "\r\n", 2);
01118 }
01119 shutdownsock(d, R_BOOT);
01120 count++;
01121 }
01122 }
01123 return count;
01124 }
01125
01126
01127
01128
01129
01130 void desc_reload(dbref player)
01131 {
01132