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 DESC *d;
01133 char *buf;
01134 dbref aowner;
01135 FLAG aflags;
01136
01137 DESC_ITER_PLAYER(player, d)
01138 {
01139 buf = atr_pget(player, A_TIMEOUT, &aowner, &aflags);
01140 if (buf)
01141 {
01142 d->timeout = mux_atol(buf);
01143 if (d->timeout <= 0)
01144 {
01145 d->timeout = mudconf.idle_timeout;
01146 }
01147 }
01148 free_lbuf(buf);
01149 }
01150 }
01151
01152
01153
01154
01155 int fetch_session(dbref target)
01156 {
01157 DESC *d;
01158 int nCount = 0;
01159 DESC_ITER_PLAYER(target, d)
01160 {
01161 nCount++;
01162 }
01163 return nCount;
01164 }
01165
01166 static DESC *find_least_idle(dbref target)
01167 {
01168 CLinearTimeAbsolute ltaNewestLastTime;
01169
01170 DESC *d;
01171 DESC *dLeastIdle = NULL;
01172 DESC_ITER_PLAYER(target, d)
01173 {
01174 if ( NULL == dLeastIdle
01175 || ltaNewestLastTime < d->last_time)
01176 {
01177 dLeastIdle = d;
01178 ltaNewestLastTime = d->last_time;
01179 }
01180 }
01181 return dLeastIdle;
01182 }
01183
01184 int fetch_height(dbref target)
01185 {
01186 DESC *d = find_least_idle(target);
01187 if (NULL != d)
01188 {
01189 return d->height;
01190 }
01191 return 24;
01192 }
01193
01194 int fetch_width(dbref target)
01195 {
01196 DESC *d = find_least_idle(target);
01197 if (NULL != d)
01198 {
01199 return d->width;
01200 }
01201 return 78;
01202 }
01203
01204
01205
01206
01207 int fetch_idle(dbref target)
01208 {
01209 CLinearTimeAbsolute ltaNow;
01210 ltaNow.GetUTC();
01211
01212 DESC *d = find_least_idle(target);
01213 if (NULL != d)
01214 {
01215 CLinearTimeDelta ltdResult;
01216 ltdResult = ltaNow - d->last_time;
01217 return ltdResult.ReturnSeconds();
01218 }
01219 else
01220 {
01221 return -1;
01222 }
01223 }
01224
01225
01226
01227
01228
01229 void find_oldest(dbref target, DESC *dOldest[2])
01230 {
01231 dOldest[0] = NULL;
01232 dOldest[1] = NULL;
01233
01234 DESC *d;
01235 bool bFound = false;
01236 DESC_ITER_PLAYER(target, d)
01237 {
01238 if ( !bFound
01239 || d->connected_at < dOldest[0]->connected_at)
01240 {
01241 bFound = true;
01242 dOldest[1] = dOldest[0];
01243 dOldest[0] = d;
01244 }
01245 }
01246 }
01247
01248
01249
01250
01251
01252 int fetch_connect(dbref target)
01253 {
01254 DESC *dOldest[2];
01255 find_oldest(target, dOldest);
01256 if (dOldest[0])
01257 {
01258 CLinearTimeAbsolute ltaNow;
01259 CLinearTimeDelta ltdOldest;
01260
01261 ltaNow.GetUTC();
01262 ltdOldest = ltaNow - dOldest[0]->connected_at;
01263 return ltdOldest.ReturnSeconds();
01264 }
01265 else
01266 {
01267 return -1;
01268 }
01269 }
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279 void check_idle(void)
01280 {
01281 DESC *d, *dnext;
01282
01283 CLinearTimeAbsolute ltaNow;
01284 ltaNow.GetUTC();
01285
01286 DESC_SAFEITER_ALL(d, dnext)
01287 {
01288 if ( (d->flags & DS_CONNECTED)
01289 && KeepAlive(d->player))
01290 {
01291
01292
01293
01294 const char aNOP[2] = { NVT_IAC, NVT_NOP };
01295 queue_write_LEN(d, aNOP, sizeof(aNOP));
01296 }
01297 if (d->flags & DS_AUTODARK)
01298 {
01299 continue;
01300 }
01301 if (d->flags & DS_CONNECTED)
01302 {
01303 if (mudconf.idle_timeout <= 0)
01304 {
01305
01306
01307
01308
01309 continue;
01310 }
01311
01312 CLinearTimeDelta ltdIdle = ltaNow - d->last_time;
01313 if (Can_Idle(d->player))
01314 {
01315 if ( mudconf.idle_wiz_dark
01316 && (Flags(d->player) & (WIZARD|DARK)) == WIZARD
01317 && ltdIdle.ReturnSeconds() > mudconf.idle_timeout)
01318 {
01319
01320
01321
01322 DESC *d1;
01323 bool bFound = false;
01324 DESC_ITER_PLAYER(d->player, d1)
01325 {
01326 if (d1 != d)
01327 {
01328 CLinearTimeDelta ltd = ltaNow - d1->last_time;
01329 if (ltd.ReturnSeconds() <= mudconf.idle_timeout)
01330 {
01331 bFound = true;
01332 break;
01333 }
01334 }
01335 }
01336 if (!bFound)
01337 {
01338 db[d->player].fs.word[FLAG_WORD1] |= DARK;
01339 DESC_ITER_PLAYER(d->player, d1)
01340 {
01341 d1->flags |= DS_AUTODARK;
01342 }
01343 }
01344 }
01345 }
01346 else if (ltdIdle.ReturnSeconds() > d->timeout)
01347 {
01348 queue_write(d, "*** Inactivity Timeout ***\r\n");
01349 shutdownsock(d, R_TIMEOUT);
01350 }
01351 }
01352 else if (0 < mudconf.conn_timeout)
01353 {
01354 CLinearTimeDelta ltdIdle = ltaNow - d->connected_at;
01355 if (ltdIdle.ReturnSeconds() > mudconf.conn_timeout)
01356 {
01357 queue_write(d, "*** Login Timeout ***\r\n");
01358 shutdownsock(d, R_TIMEOUT);
01359 }
01360 }
01361 }
01362 }
01363
01364 void check_events(void)
01365 {
01366 dbref thing, parent;
01367 int lev;
01368
01369 CLinearTimeAbsolute ltaNow;
01370 ltaNow.GetLocal();
01371
01372 FIELDEDTIME ft;
01373 if (!ltaNow.ReturnFields(&ft))
01374 {
01375 return;
01376 }
01377
01378
01379
01380 static int iLastHourChecked = 25;
01381 if ( iLastHourChecked == 23
01382 && ft.iHour < iLastHourChecked)
01383 {
01384 mudstate.events_flag &= ~ET_DAILY;
01385 }
01386 iLastHourChecked = ft.iHour;
01387
01388 if ( ft.iHour == mudconf.events_daily_hour
01389 && !(mudstate.events_flag & ET_DAILY))
01390 {
01391 mudstate.events_flag |= ET_DAILY;
01392 DO_WHOLE_DB(thing)
01393 {
01394 if (Going(thing))
01395 {
01396 continue;
01397 }
01398
01399 ITER_PARENTS(thing, parent, lev)
01400 {
01401 if (Flags2(thing) & HAS_DAILY)
01402 {
01403 did_it(Owner(thing), thing, 0, NULL, 0, NULL, A_DAILY, (char **)NULL, 0);
01404 break;
01405 }
01406 }
01407 }
01408 }
01409
01410 }
01411
01412 #define MAX_TRIMMED_NAME_LENGTH 16
01413 static const char *trimmed_name(dbref player, int *pvw)
01414 {
01415 static char cbuff[MBUF_SIZE];
01416
01417 ANSI_TruncateToField(
01418 Moniker(player),
01419 sizeof(cbuff),
01420 cbuff,
01421 MAX_TRIMMED_NAME_LENGTH,
01422 pvw,
01423 ANSI_ENDGOAL_NORMAL
01424 );
01425 return cbuff;
01426 }
01427
01428 static char *trimmed_site(char *szName)
01429 {
01430 static char buff[MBUF_SIZE];
01431
01432 unsigned int nLen = strlen(szName);
01433 if ( mudconf.site_chars <= 0
01434 || nLen <= mudconf.site_chars)
01435 {
01436 return szName;
01437 }
01438 nLen = mudconf.site_chars;
01439 if (nLen > sizeof(buff)-1)
01440 {
01441 nLen = sizeof(buff)-1;
01442 }
01443 memcpy(buff, szName, nLen);
01444 buff[nLen] = '\0';
01445 return buff;
01446 }
01447
01448 static void dump_users(DESC *e, char *match, int key)
01449 {
01450 DESC *d;
01451 int count;
01452 char *buf, *fp, *sp, flist[4], slist[4];
01453 dbref room_it;
01454
01455 if (match)
01456 {
01457 while (mux_isspace(*match))
01458 {
01459 match++;
01460 }
01461
01462 if (!*match)
01463 {
01464 match = NULL;
01465 }
01466 }
01467
01468 if ( (e->flags & (DS_PUEBLOCLIENT|DS_CONNECTED))
01469 && Html(e->player))
01470 {
01471 queue_write(e, "<pre>");
01472 }
01473
01474 buf = alloc_mbuf("dump_users");
01475 if (key == CMD_SESSION)
01476 {
01477 queue_write(e, " ");
01478 queue_write(e, " Characters Input---- Characters Output---\r\n");
01479 }
01480 queue_write(e, "Player Name On For Idle ");
01481 if (key == CMD_SESSION)
01482 {
01483 queue_write(e, "Port Pend Lost Total Pend Lost Total\r\n");
01484 }
01485 else if ( (e->flags & DS_CONNECTED)
01486 && Wizard_Who(e->player)
01487 && key == CMD_WHO)
01488 {
01489 queue_write(e, " Room Cmds Host\r\n");
01490 }
01491 else
01492 {
01493 if ( Wizard_Who(e->player)
01494 || See_Hidden(e->player))
01495 {
01496 queue_write(e, " ");
01497 }
01498 else
01499 {
01500 queue_write(e, " ");
01501 }
01502 queue_string(e, mudstate.doing_hdr);
01503 queue_write_LEN(e, "\r\n", 2);
01504 }
01505 count = 0;
01506
01507 CLinearTimeAbsolute ltaNow;
01508 ltaNow.GetUTC();
01509
01510 DESC_ITER_ALL(d)
01511 {
01512 if (!( ( (e->flags & DS_CONNECTED)
01513 && SiteMon(e->player))
01514 || (d->flags & DS_CONNECTED)))
01515 {
01516 continue;
01517 }
01518 if ( !(d->flags & DS_CONNECTED)
01519 || !Hidden(d->player)
01520 || ( (e->flags & DS_CONNECTED)
01521 && ( Wizard_Who(e->player)
01522 || See_Hidden(e->player))))
01523 {
01524 count++;
01525 if ( match
01526 && ( !(d->flags & DS_CONNECTED)
01527 || string_prefix(Name(d->player), match) == 0))
01528 {
01529 continue;
01530 }
01531 if ( key == CMD_SESSION
01532 && ( !(e->flags & DS_CONNECTED)
01533 || !Wizard_Who(e->player))
01534 && ( !(e->flags & DS_CONNECTED)
01535 || !(d->flags & DS_CONNECTED)
01536 || d->player != e->player))
01537 {
01538 continue;
01539 }
01540
01541
01542
01543 fp = flist;
01544 sp = slist;
01545 if ( (e->flags & DS_CONNECTED)
01546 && Wizard_Who(e->player))
01547 {
01548 if ( (d->flags & DS_CONNECTED)
01549 && Hidden(d->player))
01550 {
01551 if (d->flags & DS_AUTODARK)
01552 {
01553 *fp++ = 'd';
01554 }
01555 else
01556 {
01557 *fp++ = 'D';
01558 }
01559 }
01560 if (d->flags & DS_CONNECTED)
01561 {
01562 if (Hideout(d->player))
01563 {
01564 *fp++ = 'U';
01565 }
01566 else
01567 {
01568 room_it = where_room(d->player);
01569 if (Good_obj(room_it))
01570 {
01571 if (Hideout(room_it))
01572 {
01573 *fp++ = 'u';
01574 }
01575 }
01576 else
01577 {
01578 *fp++ = 'u';
01579 }
01580 }
01581
01582 if (Suspect(d->player))
01583 {
01584 *fp++ = '+';
01585 }
01586 }
01587 if (d->host_info & H_FORBIDDEN)
01588 {
01589 *sp++ = 'F';
01590 }
01591 if (d->host_info & H_REGISTRATION)
01592 {
01593 *sp++ = 'R';
01594 }
01595 if (d->host_info & H_SUSPECT)
01596 {
01597 *sp++ = '+';
01598 }
01599 if (d->host_info & H_GUEST)
01600 {
01601 *sp++ = 'G';
01602 }
01603 }
01604 else if ( (e->flags & DS_CONNECTED)
01605 && (d->flags & DS_CONNECTED)
01606 && See_Hidden(e->player)
01607 && Hidden(d->player))
01608 {
01609 if (d->flags & DS_AUTODARK)
01610 {
01611 *fp++ = 'd';
01612 }
01613 else
01614 {
01615 *fp++ = 'D';
01616 }
01617 }
01618 *fp = '\0';
01619 *sp = '\0';
01620
01621 CLinearTimeDelta ltdConnected = ltaNow - d->connected_at;
01622 CLinearTimeDelta ltdLastTime = ltaNow - d->last_time;
01623
01624 const char *pNameField = "<Unconnected>";
01625 int vwNameField = strlen(pNameField);
01626 if (d->flags & DS_CONNECTED)
01627 {
01628 pNameField = trimmed_name(d->player, &vwNameField);
01629 }
01630
01631
01632
01633 size_t nFill;
01634 if (13 <= vwNameField)
01635 {
01636 nFill = 1;
01637 }
01638 else
01639 {
01640 nFill = 14-vwNameField;
01641 }
01642 char aFill[15];
01643 memset(aFill, ' ', nFill);
01644 aFill[nFill] = '\0';
01645
01646
01647
01648 size_t nOnFor = 25 - nFill - vwNameField;
01649
01650 const char *pTimeStamp1 = time_format_1(ltdConnected.ReturnSeconds(), nOnFor);
01651 const char *pTimeStamp2 = time_format_2(ltdLastTime.ReturnSeconds());
01652
01653 if ( (e->flags & DS_CONNECTED)
01654 && Wizard_Who(e->player)
01655 && key == CMD_WHO)
01656 {
01657 sprintf(buf, "%s%s%s %4s%-3s#%-6d%5d%3s%s\r\n",
01658 pNameField, aFill,
01659 pTimeStamp1,
01660 pTimeStamp2,
01661 flist,
01662 ((d->flags & DS_CONNECTED) ? Location(d->player) : -1),
01663 d->command_count,
01664 slist,
01665 trimmed_site(((d->username[0] != '\0') ? tprintf("%s@%s", d->username, d->addr) : d->addr)));
01666 }
01667 else if (key == CMD_SESSION)
01668 {
01669 sprintf(buf, "%s%s%s %4s%5u%5d%6d%10d%6d%6d%10d\r\n",
01670 pNameField, aFill,
01671 pTimeStamp1,
01672 pTimeStamp2,
01673 d->descriptor,
01674 d->input_size, d->input_lost,
01675 d->input_tot,
01676 d->output_size, d->output_lost,
01677 d->output_tot);
01678 }
01679 else if ( Wizard_Who(e->player)
01680 || See_Hidden(e->player))
01681 {
01682 sprintf(buf, "%s%s%s %4s%-3s%s\r\n",
01683 pNameField, aFill,
01684 pTimeStamp1,
01685 pTimeStamp2,
01686 flist,
01687 d->doing);
01688 }
01689 else
01690 {
01691 sprintf(buf, "%s%s%s %4s %s\r\n",
01692 pNameField, aFill,
01693 pTimeStamp1,
01694 pTimeStamp2,
01695 d->doing);
01696 }
01697 queue_string(e, buf);
01698 }
01699 }
01700
01701
01702
01703 sprintf(buf, "%d Player%slogged in, %d record, %s maximum.\r\n", count,
01704 (count == 1) ? " " : "s ", mudstate.record_players,
01705 (mudconf.max_players == -1) ? "no" : mux_ltoa_t(mudconf.max_players));
01706 queue_write(e, buf);
01707
01708 if ( (e->flags & (DS_PUEBLOCLIENT|DS_CONNECTED))
01709 && Html(e->player))
01710 {
01711 queue_write(e, "</pre>");
01712 }
01713 free_mbuf(buf);
01714 }
01715
01716 #ifdef WOD_REALMS
01717 #define INFO_VERSION "1.1"
01718 #else // WOD_REALMS
01719 #define INFO_VERSION "1"
01720 #endif // WOD_REALMS
01721
01722 static void dump_info(DESC *arg_desc)
01723 {
01724 queue_write(arg_desc, "### Begin INFO " INFO_VERSION "\r\n");
01725
01726 queue_string(arg_desc, tprintf("Name: %s\r\n", mudconf.mud_name));
01727
01728 char *temp = mudstate.start_time.ReturnDateString();
01729 queue_write(arg_desc, tprintf("Uptime: %s\r\n", temp));
01730
01731 DESC *d;
01732 int count = 0;
01733 DESC_ITER_CONN(d)
01734 {
01735 if (!Good_obj(d->player))
01736 {
01737 continue;
01738 }
01739 if ( !Hidden(d->player)
01740 || ( (arg_desc->flags & DS_CONNECTED)
01741 && See_Hidden(arg_desc->player)))
01742 {
01743 count++;
01744 }
01745 }
01746 queue_write(arg_desc, tprintf("Connected: %d\r\n", count));
01747 queue_write(arg_desc, tprintf("Size: %d\r\n", mudstate.db_top));
01748 queue_write(arg_desc, tprintf("Version: %s\r\n", mudstate.short_ver));
01749 #ifdef WOD_REALMS
01750 queue_write(arg_desc, tprintf("Patches: WOD_REALMS\r\n"));
01751 #endif // WOD_REALMS
01752 queue_write(arg_desc, "### End INFO\r\n");
01753 }
01754
01755 static char *MakeCanonicalDoing(char *pDoing, int *pnValidDoing, bool *pbValidDoing)
01756 {
01757 *pnValidDoing = 0;
01758 *pbValidDoing = false;
01759
01760 if (!pDoing)
01761 {
01762 return NULL;
01763 }
01764
01765
01766
01767 char *Buffer = RemoveSetOfCharacters(pDoing, "\r\n\t");
01768
01769
01770
01771 int nVisualWidth;
01772 static char szFittedDoing[SIZEOF_DOING_STRING];
01773 *pnValidDoing = ANSI_TruncateToField
01774 ( Buffer,
01775 SIZEOF_DOING_STRING,
01776 szFittedDoing,
01777 WIDTHOF_DOING_STRING,
01778 &nVisualWidth,
01779 ANSI_ENDGOAL_NORMAL
01780 );
01781 *pbValidDoing = true;
01782 return szFittedDoing;
01783 }
01784
01785
01786
01787
01788
01789 void do_doing(dbref executor, dbref caller, dbref enactor, int key, char *arg)
01790 {
01791 UNUSED_PARAMETER(caller);
01792 UNUSED_PARAMETER(enactor);
01793
01794
01795
01796 static char *Empty = "";
01797 char *szValidDoing = Empty;
01798 bool bValidDoing;
01799 int nValidDoing = 0;
01800 if (arg)
01801 {
01802 szValidDoing = MakeCanonicalDoing(arg, &nValidDoing, &bValidDoing);
01803 if (!bValidDoing)
01804 {
01805 szValidDoing = Empty;
01806 nValidDoing = 0;
01807 }
01808 }
01809
01810 bool bQuiet = ((key & DOING_QUIET) == DOING_QUIET);
01811 key &= DOING_MASK;
01812 if (key == DOING_MESSAGE)
01813 {
01814 DESC *d;
01815 bool bFound = false;
01816 DESC_ITER_PLAYER(executor, d)
01817 {
01818 memcpy(d->doing, szValidDoing, nValidDoing+1);
01819 bFound = true;
01820 }
01821 if (bFound)
01822 {
01823 if ( !bQuiet
01824 && !Quiet(executor))
01825 {
01826 notify(executor, "Set.");
01827 }
01828 }
01829 else
01830 {
01831 notify(executor, "Not connected.");
01832 }
01833 }
01834 else if (key == DOING_UNIQUE)
01835 {
01836 DESC *d;
01837 DESC *dMax = NULL;
01838 CLinearTimeAbsolute ltaMax;
01839 DESC_ITER_PLAYER(executor, d)
01840 {
01841 if ( !dMax
01842 && ltaMax < d->last_time)
01843 {
01844 ltaMax = d->last_time;
01845 dMax = d;
01846 }
01847 }
01848 if (dMax)
01849 {
01850 memcpy(dMax->doing, szValidDoing, nValidDoing+1);
01851 if ( !bQuiet
01852 && !Quiet(executor))
01853 {
01854 notify(executor, "Set.");
01855 }
01856 }
01857 else
01858 {
01859 notify(executor, "Not connected.");
01860 }
01861 }
01862 else if (key == DOING_HEADER)
01863 {
01864 if (!Can_Poll(executor))
01865 {
01866 notify(executor, NOPERM_MESSAGE);
01867 return;
01868 }
01869 if (nValidDoing == 0)
01870 {
01871 strcpy(mudstate.doing_hdr, "Doing");
01872 }
01873 else
01874 {
01875 memcpy(mudstate.doing_hdr, szValidDoing, nValidDoing+1);
01876 }
01877 if ( !bQuiet
01878 && !Quiet(executor))
01879 {
01880 notify(executor, "Set.");
01881 }
01882 }
01883 else
01884 {
01885 notify(executor, tprintf("Poll: %s", mudstate.doing_hdr));
01886 }
01887 }
01888
01889 NAMETAB logout_cmdtable[] =
01890 {
01891 {(char *)"DOING", 5, CA_PUBLIC, CMD_DOING},
01892 {(char *)"LOGOUT", 6, CA_PUBLIC, CMD_LOGOUT},
01893 {(char *)"OUTPUTPREFIX", 12, CA_PUBLIC, CMD_PREFIX|CMD_NOxFIX},
01894 {(char *)"OUTPUTSUFFIX", 12, CA_PUBLIC, CMD_SUFFIX|CMD_NOxFIX},
01895 {(char *)"QUIT", 4, CA_PUBLIC, CMD_QUIT},
01896 {(char *)"SESSION", 7, CA_PUBLIC, CMD_SESSION},
01897 {(char *)"WHO", 3, CA_PUBLIC, CMD_WHO},
01898 {(char *)"PUEBLOCLIENT", 12, CA_PUBLIC, CMD_PUEBLOCLIENT},
01899 {(char *)"INFO", 4, CA_PUBLIC, CMD_INFO},
01900 {NULL, 0, 0, 0}
01901 };
01902
01903 void init_logout_cmdtab(void)
01904 {
01905 NAMETAB *cp;
01906
01907
01908
01909
01910 for (cp = logout_cmdtable; cp->flag; cp++)
01911 {
01912 hashaddLEN(cp->name, strlen(cp->name), cp, &mudstate.logout_cmd_htab);
01913 }
01914 }
01915
01916 static void failconn(const char *logcode, const char *logtype, const char *logreason,
01917 DESC *d, int disconnect_reason,
01918 dbref player, int filecache, char *motd_msg, char *command,
01919 char *user, char *password, char *cmdsave)
01920 {
01921 STARTLOG(LOG_LOGIN | LOG_SECURITY, logcode, "RJCT");
01922 char *buff = alloc_mbuf("failconn.LOG");
01923 sprintf(buff, "[%u/%s] %s rejected to ", d->descriptor, d->addr, logtype);
01924 log_text(buff);
01925 free_mbuf(buff);
01926 if (player != NOTHING)
01927 {
01928 log_name(player);
01929 }
01930 else
01931 {
01932 log_text(user);
01933 }
01934 log_text(" (");
01935 log_text(logreason);
01936 log_text(")");
01937 ENDLOG;
01938 fcache_dump(d, filecache);
01939 if (*motd_msg)
01940 {
01941 queue_string(d, motd_msg);
01942 queue_write_LEN(d, "\r\n", 2);
01943 }
01944 free_lbuf(command);
01945 free_lbuf(user);
01946 free_lbuf(password);
01947 shutdownsock(d, disconnect_reason);
01948 mudstate.debug_cmd = cmdsave;
01949 return;
01950 }
01951
01952 static const char *connect_fail = "Either that player does not exist, or has a different password.\r\n";
01953
01954 static bool check_connect(DESC *d, char *msg)
01955 {
01956 char *buff;
01957 dbref player, aowner;
01958 int aflags, nplayers;
01959 DESC *d2;
01960 const char *p;
01961 bool isGuest = false;
01962
01963 char *cmdsave = mudstate.debug_cmd;
01964 mudstate.debug_cmd = (char *)"< check_connect >";
01965
01966
01967
01968 d->input_tot -= (strlen(msg) + 1);
01969
01970
01971
01972 char *command = alloc_lbuf("check_conn.cmd");
01973 char *user = alloc_lbuf("check_conn.user");
01974 char *password = alloc_lbuf("check_conn.pass");
01975 parse_connect(msg, command, user, password);
01976
01977
01978
01979
01980 if ( strncmp(command, "co", 2) == 0
01981 || strncmp(command, "cd", 2) == 0)
01982 {
01983 if (string_prefix(user, mudconf.guest_prefix))
01984 {
01985 if ( (d->host_info & H_GUEST)
01986 || ( !mudconf.allow_guest_from_registered_site
01987 && (d->host_info & H_REGISTRATION)))
01988 {
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998 failconn("CONN", "Connect", "Guest Site Forbidden", d,
01999 R_GAMEDOWN, NOTHING, FC_CONN_REG, mudconf.downmotd_msg,
02000 command, user, password, cmdsave);
02001 return false;
02002 }
02003 if ( mudconf.guest_char != NOTHING
02004 && (mudconf.control_flags & CF_LOGIN))
02005 {
02006 if (!(mudconf.control_flags & CF_GUEST))
02007 {
02008 queue_write(d, "Guest logins are disabled.\r\n");
02009 free_lbuf(command);
02010 free_lbuf(user);
02011 free_lbuf(password);
02012 return false;
02013 }
02014
02015 if ((p = Guest.Create(d)) == NULL)
02016 {
02017 queue_write(d, "All guests are tied up, please try again later.\r\n");
02018 free_lbuf(command);
02019 free_lbuf(user);
02020 free_lbuf(password);
02021 return false;
02022 }
02023 strcpy(user, p);
02024 strcpy(password, GUEST_PASSWORD);
02025 isGuest = true;
02026 }
02027 }
02028
02029
02030
02031 if (mudconf.max_players < 0)
02032 {
02033 nplayers = mudconf.max_players - 1;
02034 }
02035 else
02036 {
02037 nplayers = 0;
02038 DESC_ITER_CONN(d2)
02039 {
02040 nplayers++;
02041 }
02042 }
02043
02044 player = connect_player(user, password, d->addr, d->username, inet_ntoa((d->address).sin_addr));
02045 if ( player == NOTHING
02046 || (!isGuest && Guest.CheckGuest(player)))
02047 {
02048
02049
02050 queue_write(d, connect_fail);
02051 STARTLOG(LOG_LOGIN | LOG_SECURITY, "CON", "BAD");
02052 buff = alloc_lbuf("check_conn.LOG.bad");
02053 sprintf(buff, "[%u/%s] Failed connect to '%s'", d->descriptor, d->addr, user);
02054 log_text(buff);
02055 free_lbuf(buff);
02056 ENDLOG;
02057 if (--(d->retries_left) <= 0)
02058 {
02059 free_lbuf(command);
02060 free_lbuf(user);
02061 free_lbuf(password);
02062 shutdownsock(d, R_BADLOGIN);
02063 mudstate.debug_cmd = cmdsave;
02064 return false;
02065 }
02066 }
02067 else if ( ( (mudconf.control_flags & CF_LOGIN)
02068 && (nplayers < mudconf.max_players))
02069 || WizRoy(player)
02070 || God(player))
02071 {
02072 if ( strncmp(command, "cd", 2) == 0
02073 && ( Wizard(player)
02074 || God(player)))
02075 {
02076 db[player].fs.word[FLAG_WORD1] |= DARK;
02077 }
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093 if ( Guest(player)
02094 && ( (d->host_info & H_GUEST)
02095 || ( !mudconf.allow_guest_from_registered_site
02096 && (d->host_info & H_REGISTRATION))))
02097 {
02098 failconn("CON", "Connect", "Guest Site Forbidden", d,
02099 R_GAMEDOWN, player, FC_CONN_SITE,
02100 mudconf.downmotd_msg, command, user, password,
02101 cmdsave);
02102 return false;
02103 }
02104
02105
02106
02107 STARTLOG(LOG_LOGIN, "CON", "LOGIN");
02108 buff = alloc_mbuf("check_conn.LOG.login");
02109 sprintf(buff, "[%u/%s] Connected to ", d->descriptor, d->addr);
02110 log_text(buff);
02111 log_name_and_loc(player);
02112 free_mbuf(buff);
02113 ENDLOG;
02114 d->flags |= DS_CONNECTED;
02115 d->connected_at.GetUTC();
02116 d->player = player;
02117
02118
02119
02120
02121 DESC_ITER_PLAYER(player, d2)
02122 {
02123 if (d2->program_data != NULL)
02124 {
02125 d->program_data = d2->program_data;
02126 break;
02127 }
02128 }
02129
02130
02131
02132
02133
02134 if (Guest(player))
02135 {
02136 fcache_dump(d, FC_CONN_GUEST);
02137 }
02138 else
02139 {
02140 buff = atr_get(player, A_LAST, &aowner, &aflags);
02141 if (*buff == '\0')
02142 fcache_dump(d, FC_CREA_NEW);
02143 else
02144 fcache_dump(d, FC_MOTD);
02145 if (Wizard(player))
02146 fcache_dump(d, FC_WIZMOTD);
02147 free_lbuf(buff);
02148 }
02149 announce_connect(player, d);
02150
02151 DESC* dtemp;
02152 int num_con = 0;
02153 DESC_ITER_PLAYER(player, dtemp)
02154 {
02155 num_con++;
02156 }
02157 local_connect(player, 0, num_con);
02158
02159
02160
02161 if (d->program_data != NULL)
02162 {
02163 queue_write_LEN(d, ">\377\371", 3);
02164 }
02165
02166 }
02167 else if (!(mudconf.control_flags & CF_LOGIN))
02168 {
02169 failconn("CON", "Connect", "Logins Disabled", d, R_GAMEDOWN, player, FC_CONN_DOWN,
02170 mudconf.downmotd_msg, command, user, password, cmdsave);
02171 return false;
02172 }
02173 else
02174 {
02175 failconn("CON", "Connect", "Game Full", d, R_GAMEFULL, player, FC_CONN_FULL,
02176 mudconf.fullmotd_msg, command, user, password, cmdsave);
02177 return false;
02178 }
02179 }
02180 else if (strncmp(command, "cr", 2) == 0)
02181 {
02182
02183
02184 if (!(mudconf.control_flags & CF_LOGIN))
02185 {
02186 failconn("CRE", "Create", "Logins Disabled", d, R_GAMEDOWN, NOTHING, FC_CONN_DOWN,
02187 mudconf.downmotd_msg, command, user, password, cmdsave);
02188 return false;
02189 }
02190
02191
02192
02193 if (mudconf.max_players < 0)
02194 {
02195 nplayers = mudconf.max_players;
02196 }
02197 else
02198 {
02199 nplayers = 0;
02200 DESC_ITER_CONN(d2)
02201 {
02202 nplayers++;
02203 }
02204 }
02205 if (nplayers > mudconf.max_players)
02206 {
02207
02208
02209 failconn("CRE", "Create", "Game Full", d,
02210 R_GAMEFULL, NOTHING, FC_CONN_FULL,
02211 mudconf.fullmotd_msg, command, user, password,
02212 cmdsave);
02213 return false;
02214 }
02215 if (d->host_info & H_REGISTRATION)
02216 {
02217 fcache_dump(d, FC_CREA_REG);
02218 }
02219 else
02220 {
02221 const char *pmsg;
02222 player = create_player(user, password, NOTHING, false, &pmsg);
02223 if (player == NOTHING)
02224 {
02225 queue_write(d, pmsg);
02226 queue_write(d, "\r\n");
02227 STARTLOG(LOG_SECURITY | LOG_PCREATES, "CON", "BAD");
02228 buff = alloc_lbuf("check_conn.LOG.badcrea");
02229 sprintf(buff, "[%u/%s] Create of '%s' failed", d->descriptor, d->addr, user);
02230 log_text(buff);
02231 free_lbuf(buff);
02232 ENDLOG;
02233 }
02234 else
02235 {
02236 AddToPublicChannel(player);
02237 STARTLOG(LOG_LOGIN | LOG_PCREATES, "CON", "CREA");
02238 buff = alloc_mbuf("check_conn.LOG.create");
02239 sprintf(buff, "[%u/%s] Created ", d->descriptor, d->addr);
02240 log_text(buff);
02241 log_name(player);
02242 free_mbuf(buff);
02243 ENDLOG;
02244 move_object(player, mudconf.start_room);
02245 d->flags |= DS_CONNECTED;
02246 d->connected_at.GetUTC();
02247 d->player = player;
02248 fcache_dump(d, FC_CREA_NEW);
02249 announce_connect(player, d);
02250
02251
02252
02253
02254 local_connect(player, 1, 0);
02255 }
02256 }
02257 }
02258 else
02259 {
02260 welcome_user(d);
02261 STARTLOG(LOG_LOGIN | LOG_SECURITY, "CON", "BAD");
02262 buff = alloc_mbuf("check_conn.LOG.bad");
02263 msg[150] = '\0';
02264 sprintf(buff, "[%u/%s] Failed connect: '%s'", d->descriptor, d->addr, msg);
02265 log_text(buff);
02266 free_mbuf(buff);
02267 ENDLOG;
02268 }
02269 free_lbuf(command);
02270 free_lbuf(user);
02271 free_lbuf(password);
02272
02273 mudstate.debug_cmd = cmdsave;
02274 return true;
02275 }
02276
02277 static void do_logged_out_internal(DESC *d, int key, char *arg)
02278 {
02279 switch (key)
02280 {
02281 case CMD_QUIT:
02282
02283 shutdownsock(d, R_QUIT);
02284 break;
02285
02286 case CMD_LOGOUT:
02287
02288 shutdownsock(d, R_LOGOUT);
02289 break;
02290
02291 case CMD_WHO:
02292 case CMD_DOING:
02293 case CMD_SESSION:
02294
02295 dump_users(d, arg, key);
02296 break;
02297
02298 case CMD_PREFIX:
02299
02300 set_userstring(&d->output_prefix, arg);
02301 break;
02302
02303 case CMD_SUFFIX:
02304
02305 set_userstring(&d->output_suffix, arg);
02306 break;
02307
02308 case CMD_INFO:
02309
02310 dump_info(d);
02311 break;
02312
02313 case CMD_PUEBLOCLIENT:
02314
02315
02316
02317 d->flags |= DS_PUEBLOCLIENT;
02318
02319 queue_string(d, mudconf.pueblo_msg);
02320 queue_write_LEN(d, "\r\n", 2);
02321 break;
02322
02323 default:
02324
02325 {
02326 char buf[LBUF_SIZE * 2];
02327 STARTLOG(LOG_BUGS, "BUG", "PARSE");
02328 sprintf(buf, "Logged-out command with no handler: '%s'", mudstate.debug_cmd);
02329 log_text(buf);
02330 ENDLOG;
02331 }
02332 }
02333 }
02334
02335 void do_command(DESC *d, char *command)
02336 {
02337 char *cmdsave = mudstate.debug_cmd;
02338 mudstate.debug_cmd = (char *)"< do_command >";
02339
02340 if (d->flags & DS_CONNECTED)
02341 {
02342
02343
02344 d->command_count++;
02345 if (d->output_prefix)
02346 {
02347 queue_string(d, d->output_prefix);
02348 queue_write_LEN(d, "\r\n", 2);
02349 }
02350 mudstate.curr_executor = d->player;
02351 mudstate.curr_enactor = d->player;
02352 for (int i = 0; i < MAX_GLOBAL_REGS; i++)
02353 {
02354 mudstate.global_regs[i][0] = '\0';
02355 mudstate.glob_reg_len[i] = 0;
02356 }
02357
02358 CLinearTimeAbsolute ltaBegin;
02359 ltaBegin.GetUTC();
02360 MuxAlarm.Set(mudconf.max_cmdsecs);
02361
02362 char *log_cmdbuf = process_command(d->player, d->player, d->player,
02363 true, command, (char **)NULL, 0);
02364
02365 CLinearTimeAbsolute ltaEnd;
02366 ltaEnd.GetUTC();
02367 if (MuxAlarm.bAlarmed)
02368 {
02369 notify(d->player, "GAME: Expensive activity abbreviated.");
02370 halt_que(d->player, NOTHING);
02371 s_Flags(d->player, FLAG_WORD1, Flags(d->player) | HALT);
02372 }
02373 MuxAlarm.Clear();
02374
02375 CLinearTimeDelta ltd = ltaEnd - ltaBegin;
02376 if (ltd > mudconf.rpt_cmdsecs)
02377 {
02378 STARTLOG(LOG_PROBLEMS, "CMD", "CPU");
02379 log_name_and_loc(d->player);
02380 char *logbuf = alloc_lbuf("do_command.LOG.cpu");
02381 sprintf(logbuf, " queued command taking %s secs: ",
02382 ltd.ReturnSecondsString(4));
02383 log_text(logbuf);
02384 free_lbuf(logbuf);
02385 log_text(log_cmdbuf);
02386 ENDLOG;
02387 }
02388
02389 mudstate.curr_cmd = (char *) "";
02390 if (d->output_suffix)
02391 {
02392 queue_string(d, d->output_suffix);
02393 queue_write_LEN(d, "\r\n", 2);
02394 }
02395 mudstate.debug_cmd = cmdsave;
02396 return;
02397 }
02398
02399
02400
02401
02402
02403
02404 char *arg = command;
02405 while (*arg && !mux_isspace(*arg))
02406 {
02407 arg++;
02408 }
02409
02410 if (*arg)
02411 {
02412 *arg++ = '\0';
02413 }
02414
02415
02416
02417 NAMETAB *cp = (NAMETAB *)hashfindLEN(command, strlen(command), &mudstate.logout_cmd_htab);
02418 if (cp == NULL)
02419 {
02420
02421
02422 if (*arg)
02423 {
02424
02425
02426 *--arg = ' ';
02427 }
02428 mudstate.curr_executor = NOTHING;
02429 mudstate.curr_enactor = NOTHING;
02430 mudstate.debug_cmd = cmdsave;
02431 check_connect(d, command);
02432 return;
02433 }
02434
02435
02436
02437
02438
02439 d->command_count++;
02440 if (!(cp->flag & CMD_NOxFIX))
02441 {
02442 if (d->output_prefix)
02443 {
02444 queue_string(d, d->output_prefix);
02445 queue_write_LEN(d, "\r\n", 2);
02446 }
02447 }
02448 if (cp->perm != CA_PUBLIC)
02449 {
02450 queue_write(d, "Permission denied.\r\n");
02451 }
02452 else
02453 {
02454 mudstate.debug_cmd = cp->name;
02455 do_logged_out_internal(d, cp->flag & CMD_MASK, arg);
02456 }
02457
02458
02459
02460 if ( ((cp->flag & CMD_MASK) != CMD_QUIT)
02461 && ((cp->flag & CMD_MASK) != CMD_LOGOUT)
02462 && !(cp->flag & CMD_NOxFIX))
02463 {
02464 if (d->output_suffix)
02465 {
02466 queue_string(d, d->output_suffix);
02467 queue_write_LEN(d, "\r\n", 2);
02468 }
02469 }
02470 mudstate.debug_cmd = cmdsave;
02471 }
02472
02473 void logged_out1(dbref executor, dbref caller, dbref enactor, int key, char *arg)
02474 {
02475 UNUSED_PARAMETER(caller);
02476 UNUSED_PARAMETER(enactor);
02477
02478
02479
02480 if (key == CMD_PUEBLOCLIENT)
02481 {
02482 DESC *d;
02483 DESC_ITER_PLAYER(executor, d)
02484 {
02485 do_logged_out_internal(d, key, arg);
02486 }
02487
02488
02489 s_Html(executor);
02490 return;
02491 }
02492
02493
02494
02495
02496 DESC *d;
02497 DESC *dLatest = NULL;
02498 DESC_ITER_PLAYER(executor, d)
02499 {
02500 if ( dLatest == NULL
02501 || dLatest->last_time < d->last_time)
02502 {
02503 dLatest = d;
02504 }
02505 }
02506 if (dLatest != NULL)
02507 {
02508 do_logged_out_internal(dLatest, key, arg);
02509 }
02510 }
02511
02512 void logged_out0(dbref executor, dbref caller, dbref enactor, int key)
02513 {
02514 logged_out1(executor, caller, enactor, key, "");
02515 }
02516
02517 void Task_ProcessCommand(void *arg_voidptr, int arg_iInteger)
02518 {
02519 UNUSED_PARAMETER(arg_iInteger);
02520
02521 DESC *d = (DESC *)arg_voidptr;
02522 if (d)
02523 {
02524 CBLK *t = d->input_head;
02525 if (t)
02526 {
02527 if (d->quota > 0)
02528 {
02529 d->quota--;
02530 d->input_head = (CBLK *) t->hdr.nxt;
02531 if (d->input_head)
02532 {
02533
02534
02535 scheduler.DeferImmediateTask(PRIORITY_SYSTEM, Task_ProcessCommand, d, 0);
02536 }
02537 else
02538 {
02539 d->input_tail = NULL;
02540 }
02541 d->input_size -= strlen(t->cmd);
02542 d->last_time.GetUTC();
02543 if (d->program_data != NULL)
02544 {
02545 handle_prog(d, t->cmd);
02546 }
02547 else
02548 {
02549 do_command(d, t->cmd);
02550 }
02551 free_lbuf(t);
02552 }
02553 else
02554 {
02555
02556
02557 CLinearTimeAbsolute lsaWhen;
02558 lsaWhen.GetUTC();
02559
02560 scheduler.DeferTask(lsaWhen + mudconf.timeslice, PRIORITY_SYSTEM, Task_ProcessCommand, d, 0);
02561 }
02562 }
02563 }
02564 }
02565
02566
02567
02568
02569
02570 int site_check(struct in_addr host, SITE *site_list)
02571 {
02572 SITE *this0;
02573
02574 for (this0 = site_list; this0; this0 = this0->next)
02575 {
02576 if ((host.s_addr & this0->mask.s_addr) == this0->address.s_addr)
02577 {
02578 return this0->flag;
02579 }
02580 }
02581 return 0;
02582 }
02583
02584
02585
02586
02587
02588 #define S_SUSPECT 1
02589 #define S_ACCESS 2
02590
02591 static const char *stat_string(int strtype, int flag)
02592 {
02593 const char *str;
02594
02595 switch (strtype)
02596 {
02597 case S_SUSPECT:
02598 if (flag)
02599 {
02600 str = "Suspected";
02601 }
02602 else
02603 {
02604 str = "Trusted";
02605 }
02606 break;
02607
02608 case S_ACCESS:
02609 switch (flag)
02610 {
02611 case H_FORBIDDEN:
02612 str = "Forbidden";
02613 break;
02614
02615 case H_REGISTRATION:
02616 str = "Registration";
02617 break;
02618
02619 case H_GUEST:
02620 str = "NoGuest";
02621 break;
02622
02623 case H_NOSITEMON:
02624 str = "NoSiteMon";
02625 break;
02626
02627 case 0:
02628 str = "Unrestricted";
02629 break;
02630
02631 default:
02632 str = "Strange";
02633 break;
02634 }
02635 break;
02636
02637 default:
02638 str = "Strange";
02639 break;
02640 }
02641 return str;
02642 }
02643
02644 static void list_sites(dbref player, SITE *site_list, const char *header_txt, int stat_type)
02645 {
02646 char *buff, *buff1, *str;
02647 SITE *this0;
02648
02649 buff = alloc_mbuf("list_sites.buff");
02650 buff1 = alloc_sbuf("list_sites.addr");
02651 sprintf(buff, "----- %s -----", header_txt);
02652 notify(player, buff);
02653 notify(player, "Address Mask Status");
02654 for (this0 = site_list; this0; this0 = this0->next)
02655 {
02656 str = (char *)stat_string(stat_type, this0->flag);
02657 strcpy(buff1, inet_ntoa(this0->mask));
02658 sprintf(buff, "%-20s %-20s %s", inet_ntoa(this0->address), buff1,
02659 str);
02660 notify(player, buff);
02661 }
02662 free_mbuf(buff);
02663 free_sbuf(buff1);
02664 }
02665
02666
02667
02668
02669
02670 void list_siteinfo(dbref player)
02671 {
02672 list_sites(player, mudstate.access_list, "Site Access", S_ACCESS);
02673 list_sites(player, mudstate.suspect_list, "Suspected Sites", S_SUSPECT);
02674 }
02675
02676
02677
02678
02679
02680 void make_ulist(dbref player, char *buff, char **bufc, bool bPorts)
02681 {
02682 DESC *d;
02683 if (bPorts)
02684 {
02685 make_port_ulist(player, buff, bufc);
02686 }
02687 else
02688 {
02689 ITL pContext;
02690 ItemToList_Init(&pContext, buff, bufc, '#');
02691 DESC_ITER_CONN(d)
02692 {
02693 if ( !See_Hidden(player)
02694 && Hidden(d->player))
02695 {
02696 continue;
02697 }
02698 if (!ItemToList_AddInteger(&pContext, d->player))
02699 {
02700 break;
02701 }
02702 }
02703 ItemToList_Final(&pContext);
02704 }
02705 }
02706
02707
02708
02709
02710
02711
02712
02713 dbref find_connected_name(dbref player, char *name)
02714 {
02715 DESC *d;
02716 dbref found = NOTHING;
02717 DESC_ITER_CONN(d)
02718 {
02719 if ( Good_obj(player)
02720 && !See_Hidden(player)
02721 && Hidden(d->player))
02722 {
02723 continue;
02724 }
02725 if (!string_prefix(Name(d->player), name))
02726 {
02727 continue;
02728 }
02729 if ( found != NOTHING
02730 && found != d->player)
02731 {
02732 return NOTHING;
02733 }
02734 found = d->player;
02735 }
02736 return found;
02737 }
02738
02739 FUNCTION(fun_doing)
02740 {
02741 UNUSED_PARAMETER(caller);
02742 UNUSED_PARAMETER(enactor);
02743 UNUSED_PARAMETER(nfargs);
02744 UNUSED_PARAMETER(cargs);
02745 UNUSED_PARAMETER(ncargs);
02746
02747 if (is_rational(fargs[0]))
02748 {
02749 SOCKET s = mux_atol(fargs[0]);
02750 bool bFound = false;
02751 DESC *d;
02752 DESC_ITER_CONN(d)
02753 {
02754 if (d->descriptor == s)
02755 {
02756 bFound = true;
02757 break;
02758 }
02759 }
02760 if ( bFound
02761 && ( d->player == executor
02762 || Wizard_Who(executor)))
02763 {
02764 safe_str(d->doing, buff, bufc);
02765 }
02766 else
02767 {
02768 safe_nothing(buff, bufc);
02769 }
02770 }
02771 else
02772 {
02773 dbref victim = lookup_player(executor, fargs[0], true);
02774 if (victim == NOTHING)
02775 {
02776 safe_str("#-1 PLAYER DOES NOT EXIST", buff, bufc);
02777 return;
02778 }
02779
02780 if ( Wizard_Who(executor)
02781 || !Hidden(victim))
02782 {
02783 DESC *d;
02784 DESC_ITER_CONN(d)
02785 {
02786 if (d->player == victim)
02787 {
02788 safe_str(d->doing, buff, bufc);
02789 return;
02790 }
02791 }
02792 }
02793 safe_str("#-1 NOT A CONNECTED PLAYER", buff, bufc);
02794 }
02795 }
02796
02797
02798
02799
02800 FUNCTION(fun_host)
02801 {
02802 UNUSED_PARAMETER(caller);
02803 UNUSED_PARAMETER(enactor);
02804 UNUSED_PARAMETER(nfargs);
02805 UNUSED_PARAMETER(cargs);
02806 UNUSED_PARAMETER(ncargs);
02807
02808 if (!Wizard_Who(executor))
02809 {
02810 safe_noperm(buff, bufc);
02811 return;
02812 }
02813
02814 bool isPort = is_rational(fargs[0]);
02815 bool bFound = false;
02816 DESC *d;
02817 if (isPort)
02818 {
02819 SOCKET s = mux_atol(fargs[0]);
02820 DESC_ITER_CONN(d)
02821 {
02822 if (d->descriptor == s)
02823 {
02824 bFound = true;
02825 break;
02826 }
02827 }
02828 }
02829 else
02830 {
02831 dbref victim = lookup_player(executor, fargs[0], true);
02832 if (victim == NOTHING)
02833 {
02834 safe_str("#-1 PLAYER DOES NOT EXIST", buff, bufc);
02835 return;
02836 }
02837 DESC_ITER_CONN(d)
02838 {
02839 if (d->player == victim)
02840 {
02841 bFound = true;
02842 break;
02843 }
02844 }
02845 }
02846 if (bFound)
02847 {
02848 char *hostname = ((d->username[0] != '\0') ?
02849 tprintf("%s@%s", d->username, d->addr) : d->addr);
02850 safe_str(hostname, buff, bufc);
02851 return;
02852 }
02853 if (isPort)
02854 {
02855 safe_str("#-1 NOT AN ACTIVE PORT", buff, bufc);
02856 }
02857 else
02858 {
02859 safe_str("#-1 NOT A CONNECTED PLAYER", buff, bufc);
02860 }
02861 }
02862
02863 FUNCTION(fun_poll)
02864 {
02865 UNUSED_PARAMETER(executor);
02866 UNUSED_PARAMETER(caller);
02867 UNUSED_PARAMETER(enactor);
02868 UNUSED_PARAMETER(fargs);
02869 UNUSED_PARAMETER(nfargs);
02870 UNUSED_PARAMETER(cargs);
02871 UNUSED_PARAMETER(ncargs);
02872
02873 safe_str(mudstate.doing_hdr, buff, bufc);
02874 }
02875
02876 FUNCTION(fun_motd)
02877 {
02878 UNUSED_PARAMETER(executor);
02879 UNUSED_PARAMETER(caller);
02880 UNUSED_PARAMETER(enactor);
02881 UNUSED_PARAMETER(fargs);
02882 UNUSED_PARAMETER(nfargs);
02883 UNUSED_PARAMETER(cargs);
02884 UNUSED_PARAMETER(ncargs);
02885
02886 safe_str(mudconf.motd_msg, buff, bufc);
02887 }
02888
02889
02890
02891 int fetch_cmds(dbref target)
02892 {
02893 int sum = 0;
02894 bool bFound = false;
02895
02896 DESC *d;
02897 DESC_ITER_PLAYER(target, d)
02898 {
02899 sum += d->command_count;
02900 bFound = true;
02901 }
02902
02903 if (bFound)
02904 {
02905 return sum;
02906 }
02907 else
02908 {
02909 return -1;
02910 }
02911 }
02912
02913 static void ParseConnectionInfoString(char *pConnInfo, char *pFields[5])
02914 {
02915 MUX_STRTOK_STATE tts;
02916 mux_strtok_src(&tts, pConnInfo);
02917 mux_strtok_ctl(&tts, " ");
02918 for (int i = 0; i < 5; i++)
02919 {
02920 pFields[i] = mux_strtok_parse(&tts);
02921 }
02922 }
02923
02924 void fetch_ConnectionInfoFields(dbref target, long anFields[4])
02925 {
02926 dbref aowner;
02927 int aflags;
02928 char *pConnInfo = atr_get(target, A_CONNINFO, &aowner, &aflags);
02929 char *aFields[5];
02930 ParseConnectionInfoString(pConnInfo, aFields);
02931
02932 for (int i = 0; i < 4; i++)
02933 {
02934 long result;
02935 if ( !aFields[i]
02936 || (result = mux_atol(aFields[i])) < 0)
02937 {
02938 result = 0;
02939 }
02940 anFields[i] = result;
02941 }
02942 free_lbuf(pConnInfo);
02943 }
02944
02945 void put_ConnectionInfoFields
02946 (
02947 dbref target,
02948 long anFields[4],
02949 CLinearTimeAbsolute <aLogout
02950 )
02951 {
02952 char *pConnInfo = alloc_lbuf("put_CIF");
02953 char *p = pConnInfo;
02954 for (int i = 0; i < 4; i++)
02955 {
02956 p += mux_ltoa(anFields[i], p);
02957 *p++ = ' ';
02958 }
02959 p += mux_i64toa(ltaLogout.ReturnSeconds(), p);
02960 *p++ = 0;
02961
02962 atr_add_raw_LEN(target, A_CONNINFO, pConnInfo, p - pConnInfo);
02963 free_lbuf(pConnInfo);
02964 }
02965
02966 long fetch_ConnectionInfoField(dbref target, int iField)
02967 {
02968 dbref aowner;
02969 int aflags;
02970 char *pConnInfo = atr_get(target, A_CONNINFO, &aowner, &aflags);
02971 char *aFields[5];
02972 ParseConnectionInfoString(pConnInfo, aFields);
02973
02974 long result;
02975 if ( !aFields[iField]
02976 || (result = mux_atol(aFields[iField])) < 0)
02977 {
02978 result = 0;
02979 }
02980 free_lbuf(pConnInfo);
02981 return result;
02982 }
02983
02984 #define CIF_LOGOUTTIME 4
02985
02986 CLinearTimeAbsolute fetch_logouttime(dbref target)
02987 {
02988 dbref aowner;
02989 int aflags;
02990 char *pConnInfo = atr_get(target, A_CONNINFO, &aowner, &aflags);
02991 char *aFields[5];
02992 ParseConnectionInfoString(pConnInfo, aFields);
02993
02994 CLinearTimeAbsolute lta;
02995 if (aFields[CIF_LOGOUTTIME])
02996 {
02997 lta.SetSecondsString(aFields[CIF_LOGOUTTIME]);
02998 }
02999 else
03000 {
03001 lta.SetSeconds(0);
03002 }
03003 free_lbuf(pConnInfo);
03004 return lta;
03005 }