00001
00002
00003
00004
00005
00006
00007
00008
00009 #include "copyright.h"
00010 #include "autoconf.h"
00011 #include "config.h"
00012 #include "externs.h"
00013
00014 #include "attrs.h"
00015 #include "command.h"
00016 #include "comsys.h"
00017 #include "interface.h"
00018 #include "powers.h"
00019 #include "vattr.h"
00020 #include "ansi.h"
00021
00022 #ifndef O_ACCMODE
00023 #define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR)
00024 #endif // O_ACCMODE
00025
00026 OBJ *db = NULL;
00027
00028 typedef struct atrcount ATRCOUNT;
00029 struct atrcount
00030 {
00031 dbref thing;
00032 int count;
00033 };
00034
00035
00036
00037 ATTR attr[] =
00038 {
00039 {"Aahear", A_AAHEAR, AF_ODARK | AF_NOPROG},
00040 {"Aclone", A_ACLONE, AF_ODARK | AF_NOPROG},
00041 {"Aconnect", A_ACONNECT, AF_ODARK | AF_NOPROG},
00042 {"Adesc", A_ADESC, AF_ODARK | AF_NOPROG},
00043 {"Adfail", A_ADFAIL, AF_ODARK | AF_NOPROG},
00044 {"Adisconnect", A_ADISCONNECT, AF_ODARK | AF_NOPROG},
00045 {"Adrop", A_ADROP, AF_ODARK | AF_NOPROG},
00046 {"Aefail", A_AEFAIL, AF_ODARK | AF_NOPROG},
00047 {"Aenter", A_AENTER, AF_ODARK | AF_NOPROG},
00048 {"Afail", A_AFAIL, AF_ODARK | AF_NOPROG},
00049 {"Agfail", A_AGFAIL, AF_ODARK | AF_NOPROG},
00050 {"Ahear", A_AHEAR, AF_ODARK | AF_NOPROG},
00051 {"Akill", A_AKILL, AF_ODARK | AF_NOPROG},
00052 {"Aleave", A_ALEAVE, AF_ODARK | AF_NOPROG},
00053 {"Alfail", A_ALFAIL, AF_ODARK | AF_NOPROG},
00054 {"Alias", A_ALIAS, AF_NOPROG | AF_NOCMD | AF_NOCLONE | AF_PRIVATE | AF_CONST | AF_VISUAL},
00055 {"Allowance", A_ALLOWANCE, AF_MDARK | AF_NOPROG | AF_WIZARD},
00056 {"Amail", A_AMAIL, AF_ODARK | AF_NOPROG},
00057 {"Amhear", A_AMHEAR, AF_ODARK | AF_NOPROG},
00058 {"Amove", A_AMOVE, AF_ODARK | AF_NOPROG},
00059 {"Apay", A_APAY, AF_ODARK | AF_NOPROG},
00060 {"Arfail", A_ARFAIL, AF_ODARK | AF_NOPROG},
00061 {"Asucc", A_ASUCC, AF_ODARK | AF_NOPROG},
00062 {"Atfail", A_ATFAIL, AF_ODARK | AF_NOPROG},
00063 {"Atport", A_ATPORT, AF_ODARK | AF_NOPROG},
00064 {"Atofail", A_ATOFAIL, AF_ODARK | AF_NOPROG},
00065 {"Aufail", A_AUFAIL, AF_ODARK | AF_NOPROG},
00066 {"Ause", A_AUSE, AF_ODARK | AF_NOPROG},
00067 {"Away", A_AWAY, AF_ODARK | AF_NOPROG},
00068 {"Charges", A_CHARGES, AF_ODARK | AF_NOPROG},
00069 {"CmdCheck", A_CMDCHECK, AF_DARK | AF_NOPROG | AF_NOCMD | AF_NOCLONE | AF_PRIVATE | AF_CONST},
00070 {"Comment", A_COMMENT, AF_MDARK | AF_WIZARD},
00071 {"ConFormat", A_CONFORMAT, AF_ODARK | AF_NOPROG},
00072 {"Cost", A_COST, AF_ODARK | AF_NOPROG},
00073 {"Created", A_CREATED, AF_GOD | AF_VISUAL | AF_NOPROG | AF_NOCMD},
00074 {"Daily", A_DAILY, AF_ODARK | AF_NOPROG},
00075 {"Desc", A_DESC, AF_VISUAL | AF_NOPROG},
00076 {"DefaultLock", A_LOCK, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00077 {"DescFormat", A_DESCFORMAT, AF_ODARK | AF_NOPROG},
00078 {"Destroyer", A_DESTROYER, AF_MDARK | AF_WIZARD | AF_NOPROG},
00079 {"Dfail", A_DFAIL, AF_ODARK | AF_NOPROG},
00080 {"Drop", A_DROP, AF_ODARK | AF_NOPROG},
00081 {"DropLock", A_LDROP, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00082 {"Ealias", A_EALIAS, AF_ODARK | AF_NOPROG},
00083 {"Efail", A_EFAIL, AF_ODARK | AF_NOPROG},
00084 {"Enter", A_ENTER, AF_ODARK | AF_NOPROG},
00085 {"EnterLock", A_LENTER, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00086 {"ExitFormat", A_EXITFORMAT, AF_ODARK | AF_NOPROG},
00087 {"ExitTo", A_EXITVARDEST, AF_ODARK | AF_NOPROG | AF_WIZARD},
00088 {"Fail", A_FAIL, AF_ODARK | AF_NOPROG},
00089 {"Filter", A_FILTER, AF_ODARK | AF_NOPROG},
00090 {"Forwardlist", A_FORWARDLIST, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_CONST},
00091 {"GetFromLock", A_LGET, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00092 {"Gfail", A_GFAIL, AF_ODARK | AF_NOPROG},
00093 {"GiveLock", A_LGIVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00094 {"Idesc", A_IDESC, AF_ODARK | AF_NOPROG},
00095 {"Idle", A_IDLE, AF_ODARK | AF_NOPROG},
00096 {"IdleTimeout", A_IDLETMOUT, AF_ODARK | AF_NOPROG},
00097 {"Infilter", A_INFILTER, AF_ODARK | AF_NOPROG},
00098 {"Inprefix", A_INPREFIX, AF_ODARK | AF_NOPROG},
00099 {"Kill", A_KILL, AF_ODARK | AF_NOPROG},
00100 {"Lalias", A_LALIAS, AF_ODARK | AF_NOPROG},
00101 {"Last", A_LAST, AF_WIZARD | AF_NOCMD | AF_NOPROG | AF_NOCLONE},
00102 {"Lastpage", A_LASTPAGE, AF_INTERNAL | AF_NOCMD | AF_NOPROG | AF_GOD | AF_PRIVATE},
00103 {"Lastsite", A_LASTSITE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_NOCLONE | AF_GOD},
00104 {"LastIP", A_LASTIP, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_GOD},
00105 {"Leave", A_LEAVE, AF_ODARK | AF_NOPROG},
00106 {"LeaveLock", A_LLEAVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00107 {"Lfail", A_LFAIL, AF_ODARK | AF_NOPROG},
00108 {"LinkLock", A_LLINK, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00109 {"Listen", A_LISTEN, AF_ODARK | AF_NOPROG},
00110 {"Logindata", A_LOGINDATA, AF_MDARK | AF_NOPROG | AF_NOCMD | AF_CONST},
00111 {"Mailcurf", A_MAILCURF, AF_MDARK | AF_WIZARD | AF_NOPROG | AF_NOCLONE},
00112 {"Mailflags", A_MAILFLAGS, AF_MDARK | AF_WIZARD | AF_NOPROG | AF_NOCLONE},
00113 {"Mailfolders", A_MAILFOLDERS, AF_MDARK | AF_WIZARD | AF_NOPROG | AF_NOCLONE},
00114 {"MailLock", A_LMAIL, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00115 {"Mailmsg", A_MAILMSG, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00116 {"Mailsub", A_MAILSUB, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00117 {"Mailsucc", A_MAIL, AF_ODARK | AF_NOPROG},
00118 {"Mailto", A_MAILTO, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00119 {"Mfail", A_MFAIL, AF_ODARK | AF_NOPROG},
00120 {"Modified", A_MODIFIED, AF_GOD | AF_VISUAL | AF_NOPROG | AF_NOCMD},
00121 {"Moniker", A_MONIKER, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_CONST},
00122 {"Move", A_MOVE, AF_ODARK | AF_NOPROG},
00123 {"Name", A_NAME, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00124 {"NameFormat", A_NAMEFORMAT, AF_ODARK | AF_NOPROG | AF_WIZARD},
00125 {"Odesc", A_ODESC, AF_ODARK | AF_NOPROG},
00126 {"Odfail", A_ODFAIL, AF_ODARK | AF_NOPROG},
00127 {"Odrop", A_ODROP, AF_ODARK | AF_NOPROG},
00128 {"Oefail", A_OEFAIL, AF_ODARK | AF_NOPROG},
00129 {"Oenter", A_OENTER, AF_ODARK | AF_NOPROG},
00130 {"Ofail", A_OFAIL, AF_ODARK | AF_NOPROG},
00131 {"Ogfail", A_OGFAIL, AF_ODARK | AF_NOPROG},
00132 {"Okill", A_OKILL, AF_ODARK | AF_NOPROG},
00133 {"Oleave", A_OLEAVE, AF_ODARK | AF_NOPROG},
00134 {"Olfail", A_OLFAIL, AF_ODARK | AF_NOPROG},
00135 {"Omove", A_OMOVE, AF_ODARK | AF_NOPROG},
00136 {"Opay", A_OPAY, AF_ODARK | AF_NOPROG},
00137 {"OpenLock", A_LOPEN, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00138 {"Orfail", A_ORFAIL, AF_ODARK | AF_NOPROG},
00139 {"Osucc", A_OSUCC, AF_ODARK | AF_NOPROG},
00140 {"Otfail", A_OTFAIL, AF_ODARK | AF_NOPROG},
00141 {"Otport", A_OTPORT, AF_ODARK | AF_NOPROG},
00142 {"Otofail", A_OTOFAIL, AF_ODARK | AF_NOPROG},
00143 {"Oufail", A_OUFAIL, AF_ODARK | AF_NOPROG},
00144 {"Ouse", A_OUSE, AF_ODARK | AF_NOPROG},
00145 {"Oxenter", A_OXENTER, AF_ODARK | AF_NOPROG},
00146 {"Oxleave", A_OXLEAVE, AF_ODARK | AF_NOPROG},
00147 {"Oxtport", A_OXTPORT, AF_ODARK | AF_NOPROG},
00148 {"PageLock", A_LPAGE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00149 {"ParentLock", A_LPARENT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00150 {"Pay", A_PAY, AF_ODARK | AF_NOPROG},
00151 {"Prefix", A_PREFIX, AF_ODARK | AF_NOPROG},
00152 {"ProgCmd", A_PROGCMD, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00153 {"QueueMax", A_QUEUEMAX, AF_MDARK | AF_WIZARD | AF_NOPROG},
00154 {"Quota", A_QUOTA, AF_MDARK | AF_NOPROG | AF_GOD | AF_NOCMD | AF_NOCLONE},
00155 {"ReceiveLock", A_LRECEIVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00156 {"Reject", A_REJECT, AF_ODARK | AF_NOPROG},
00157 {"Rfail", A_RFAIL, AF_ODARK | AF_NOPROG},
00158 {"Rquota", A_RQUOTA, AF_MDARK | AF_NOPROG | AF_GOD | AF_NOCMD | AF_NOCLONE},
00159 {"Runout", A_RUNOUT, AF_ODARK | AF_NOPROG},
00160 {"SayString", A_SAYSTRING, AF_ODARK | AF_NOPROG},
00161 {"Semaphore", A_SEMAPHORE, AF_ODARK | AF_NOPROG | AF_WIZARD | AF_NOCMD | AF_NOCLONE},
00162 {"Sex", A_SEX, AF_VISUAL | AF_NOPROG},
00163 {"Signature", A_SIGNATURE, AF_ODARK | AF_NOPROG},
00164 {"SpeechMod", A_SPEECHMOD, AF_ODARK | AF_NOPROG},
00165 {"SpeechLock", A_LSPEECH, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00166 {"Startup", A_STARTUP, AF_ODARK | AF_NOPROG},
00167 {"Succ", A_SUCC, AF_ODARK | AF_NOPROG},
00168 {"TeloutLock", A_LTELOUT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00169 {"Tfail", A_TFAIL, AF_ODARK | AF_NOPROG},
00170 {"Timeout", A_TIMEOUT, AF_MDARK | AF_NOPROG | AF_WIZARD},
00171 {"Tport", A_TPORT, AF_ODARK | AF_NOPROG},
00172 {"TportLock", A_LTPORT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00173 {"Tofail", A_TOFAIL, AF_ODARK | AF_NOPROG},
00174 {"Ufail", A_UFAIL, AF_ODARK | AF_NOPROG},
00175 {"Use", A_USE, AF_ODARK | AF_NOPROG},
00176 {"UseLock", A_LUSE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00177 {"UserLock", A_LUSER, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK},
00178 {"VA", A_VA, AF_ODARK},
00179 {"VB", A_VA + 1, AF_ODARK},
00180 {"VC", A_VA + 2, AF_ODARK},
00181 {"VD", A_VA + 3, AF_ODARK},
00182 {"VE", A_VA + 4, AF_ODARK},
00183 {"VF", A_VA + 5, AF_ODARK},
00184 {"VG", A_VA + 6, AF_ODARK},
00185 {"VH", A_VA + 7, AF_ODARK},
00186 {"VI", A_VA + 8, AF_ODARK},
00187 {"VJ", A_VA + 9, AF_ODARK},
00188 {"VK", A_VA + 10, AF_ODARK},
00189 {"VL", A_VA + 11, AF_ODARK},
00190 {"VM", A_VA + 12, AF_ODARK},
00191 {"VN", A_VA + 13, AF_ODARK},
00192 {"VO", A_VA + 14, AF_ODARK},
00193 {"VP", A_VA + 15, AF_ODARK},
00194 {"VQ", A_VA + 16, AF_ODARK},
00195 {"VR", A_VA + 17, AF_ODARK},
00196 {"VS", A_VA + 18, AF_ODARK},
00197 {"VT", A_VA + 19, AF_ODARK},
00198 {"VU", A_VA + 20, AF_ODARK},
00199 {"VV", A_VA + 21, AF_ODARK},
00200 {"VW", A_VA + 22, AF_ODARK},
00201 {"VX", A_VA + 23, AF_ODARK},
00202 {"VY", A_VA + 24, AF_ODARK},
00203 {"VZ", A_VA + 25, AF_ODARK},
00204 {"VRML_URL", A_VRML_URL, AF_ODARK | AF_NOPROG},
00205 {"HTDesc", A_HTDESC, AF_NOPROG},
00206
00207
00208 {"Reason", A_REASON, AF_PRIVATE | AF_MDARK | AF_NOPROG | AF_NOCMD | AF_GOD},
00209 #ifdef GAME_DOOFERMUX
00210 {"RegInfo", A_REGINFO, AF_PRIVATE | AF_MDARK | AF_NOPROG | AF_NOCMD | AF_WIZARD},
00211 #endif // GAME_DOOFERMUX
00212 {"ConnInfo", A_CONNINFO, AF_PRIVATE | AF_MDARK | AF_NOPROG | AF_NOCMD | AF_GOD},
00213 {"*Password", A_PASS, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00214 {"*Privileges", A_PRIVS, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00215 {"*Money", A_MONEY, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00216 #ifdef REALITY_LVLS
00217 {"Rlevel", A_RLEVEL, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL},
00218 #endif
00219 {NULL, 0, 0}
00220 };
00221
00222 char *aszSpecialDBRefNames[1-NOPERM] =
00223 {
00224 "", "*NOTHING*", "*AMBIGUOUS*", "*HOME*", "*NOPERMISSION*"
00225 };
00226
00227
00228
00229
00230
00231 void fwdlist_set(dbref thing, FWDLIST *ifp)
00232 {
00233 FWDLIST *fp, *xfp;
00234 int i;
00235
00236
00237
00238 if (!ifp || (ifp->count <= 0))
00239 {
00240 fwdlist_clr(thing);
00241 return;
00242 }
00243
00244
00245
00246 fp = (FWDLIST *)MEMALLOC(sizeof(int) * ((ifp->count) + 1));
00247 ISOUTOFMEMORY(fp);
00248
00249 for (i = 0; i < ifp->count; i++)
00250 {
00251 fp->data[i] = ifp->data[i];
00252 }
00253 fp->count = ifp->count;
00254
00255
00256
00257 xfp = fwdlist_get(thing);
00258 if (xfp)
00259 {
00260 MEMFREE(xfp);
00261 xfp = NULL;
00262 hashreplLEN(&thing, sizeof(thing), fp, &mudstate.fwdlist_htab);
00263 }
00264 else
00265 {
00266 hashaddLEN(&thing, sizeof(thing), fp, &mudstate.fwdlist_htab);
00267 }
00268 }
00269
00270 void fwdlist_clr(dbref thing)
00271 {
00272
00273
00274 FWDLIST *xfp = fwdlist_get(thing);
00275 if (xfp)
00276 {
00277 MEMFREE(xfp);
00278 xfp = NULL;
00279 hashdeleteLEN(&thing, sizeof(thing), &mudstate.fwdlist_htab);
00280 }
00281 }
00282
00283
00284
00285
00286
00287 int fwdlist_load(FWDLIST *fp, dbref player, char *atext)
00288 {
00289 dbref target;
00290 char *tp, *bp, *dp;
00291 bool fail;
00292
00293 int count = 0;
00294 int errors = 0;
00295 bp = tp = alloc_lbuf("fwdlist_load.str");
00296 strcpy(tp, atext);
00297 do
00298 {
00299
00300
00301 for (; mux_isspace(*bp); bp++)
00302 {
00303 ;
00304 }
00305
00306
00307
00308 for (dp = bp; *bp && !mux_isspace(*bp); bp++)
00309 {
00310 ;
00311 }
00312
00313
00314
00315 if (*bp)
00316 {
00317 *bp++ = '\0';
00318 }
00319
00320 if ( *dp++ == '#'
00321 && mux_isdigit(*dp))
00322 {
00323 target = mux_atol(dp);
00324 if (mudstate.bStandAlone)
00325 {
00326 fail = !Good_obj(target);
00327 }
00328 else
00329 {
00330 fail = ( !Good_obj(target)
00331 || ( !God(player)
00332 && !Controls(player, target)
00333 && ( !Link_ok(target)
00334 || !could_doit(player, target, A_LLINK))));
00335 }
00336 if (fail)
00337 {
00338 if (!mudstate.bStandAlone)
00339 {
00340 notify(player,
00341 tprintf("Cannot forward to #%d: Permission denied.",
00342 target));
00343 }
00344 errors++;
00345 }
00346 else
00347 {
00348 if (count < 1000)
00349 {
00350 fp->data[count++] = target;
00351 }
00352 }
00353 }
00354 } while (*bp);
00355 free_lbuf(tp);
00356 fp->count = count;
00357 return errors;
00358 }
00359
00360
00361
00362
00363
00364 int fwdlist_rewrite(FWDLIST *fp, char *atext)
00365 {
00366 int count = 0;
00367 atext[0] = '\0';
00368
00369 if (fp && fp->count)
00370 {
00371 char *bp = atext;
00372 ITL pContext;
00373 ItemToList_Init(&pContext, atext, &bp, '#');
00374 for (int i = 0; i < fp->count; i++)
00375 {
00376 if ( Good_obj(fp->data[i])
00377 && ItemToList_AddInteger(&pContext, fp->data[i]))
00378 {
00379 count++;
00380 }
00381 }
00382 ItemToList_Final(&pContext);
00383 }
00384 return count;
00385 }
00386
00387
00388
00389
00390 bool fwdlist_ck(dbref player, dbref thing, int anum, char *atext)
00391 {
00392 UNUSED_PARAMETER(anum);
00393
00394 if (mudstate.bStandAlone)
00395 {
00396 return true;
00397 }
00398
00399 FWDLIST *fp;
00400 int count = 0;
00401
00402 if (atext && *atext)
00403 {
00404 fp = (FWDLIST *) alloc_lbuf("fwdlist_ck.fp");
00405 fwdlist_load(fp, player, atext);
00406 }
00407 else
00408 {
00409 fp = NULL;
00410 }
00411
00412
00413
00414 fwdlist_set(thing, fp);
00415 count = fwdlist_rewrite(fp, atext);
00416 if (fp)
00417 {
00418 free_lbuf(fp);
00419 }
00420 return ((count > 0) || !atext || !*atext);
00421 }
00422
00423 FWDLIST *fwdlist_get(dbref thing)
00424 {
00425 static FWDLIST *fp = NULL;
00426 if (mudstate.bStandAlone)
00427 {
00428 if (!fp)
00429 {
00430 fp = (FWDLIST *) alloc_lbuf("fwdlist_get");
00431 }
00432 dbref aowner;
00433 int aflags;
00434 char *tp = atr_get(thing, A_FORWARDLIST, &aowner, &aflags);
00435 fwdlist_load(fp, GOD, tp);
00436 free_lbuf(tp);
00437 }
00438 else
00439 {
00440 fp = (FWDLIST *) hashfindLEN(&thing, sizeof(thing),
00441 &mudstate.fwdlist_htab);
00442 }
00443 return fp;
00444 }
00445
00446
00447
00448
00449
00450 const char *Name(dbref thing)
00451 {
00452 if (thing < 0)
00453 {
00454 return aszSpecialDBRefNames[-thing];
00455 }
00456
00457 dbref aowner;
00458 int aflags;
00459 #ifdef MEMORY_BASED
00460 static char tbuff[LBUF_SIZE];
00461 atr_get_str(tbuff, thing, A_NAME, &aowner, &aflags);
00462 return tbuff;
00463 #else // MEMORY_BASED
00464 if (!db[thing].name)
00465 {
00466 size_t len;
00467 char *pName = atr_get_LEN(thing, A_NAME, &aowner, &aflags, &len);
00468 db[thing].name = StringCloneLen(pName, len);
00469 free_lbuf(pName);
00470 }
00471 return db[thing].name;
00472 #endif // MEMORY_BASED
00473 }
00474
00475 const char *PureName(dbref thing)
00476 {
00477 if (thing < 0)
00478 {
00479 return aszSpecialDBRefNames[-thing];
00480 }
00481
00482 dbref aowner;
00483 int aflags;
00484
00485 char *pName, *pPureName;
00486 if (mudconf.cache_names)
00487 {
00488 if (!db[thing].purename)
00489 {
00490 size_t nName;
00491 size_t nPureName;
00492 #ifdef MEMORY_BASED
00493 pName = atr_get_LEN(thing, A_NAME, &aowner, &aflags, &nName);
00494 pPureName = strip_ansi(pName, &nPureName);
00495 free_lbuf(pName);
00496 db[thing].purename = StringCloneLen(pPureName, nPureName);
00497 #else // MEMORY_BASED
00498 if (!db[thing].name)
00499 {
00500 pName = atr_get_LEN(thing, A_NAME, &aowner, &aflags, &nName);
00501 db[thing].name = StringCloneLen(pName, nName);
00502 free_lbuf(pName);
00503 }
00504 else
00505 {
00506 nName = strlen(db[thing].name);
00507 }
00508 pName = db[thing].name;
00509 pPureName = strip_ansi(pName, &nPureName);
00510 if (nPureName == nName)
00511 {
00512 db[thing].purename = pName;
00513 }
00514 else
00515 {
00516 db[thing].purename = StringCloneLen(pPureName, nPureName);
00517 }
00518 #endif // MEMORY_BASED
00519 }
00520 return db[thing].purename;
00521 }
00522 pName = atr_get(thing, A_NAME, &aowner, &aflags);
00523 pPureName = strip_ansi(pName);
00524 free_lbuf(pName);
00525 return pPureName;
00526 }
00527
00528 const char *Moniker(dbref thing)
00529 {
00530 if (thing < 0)
00531 {
00532 return aszSpecialDBRefNames[-thing];
00533 }
00534 if (db[thing].moniker)
00535 {
00536 return db[thing].moniker;
00537 }
00538
00539
00540
00541
00542 const char *pPureName = strip_accents(PureName(thing));
00543 char *pPureNameCopy = StringClone(pPureName);
00544
00545 size_t nMoniker;
00546 dbref aowner;
00547 int aflags;
00548 char *pMoniker = atr_get_LEN(thing, A_MONIKER, &aowner, &aflags,
00549 &nMoniker);
00550 char *pPureMoniker = strip_accents(strip_ansi(pMoniker));
00551
00552 const char *pReturn = NULL;
00553 static char tbuff[LBUF_SIZE];
00554 if (strcmp(pPureNameCopy, pPureMoniker) == 0)
00555 {
00556
00557
00558
00559
00560 if (mudconf.cache_names)
00561 {
00562 #ifdef MEMORY_BASED
00563 db[thing].moniker = StringCloneLen(pMoniker, nMoniker);
00564 #else // MEMORY_BASED
00565 if (strcmp(pMoniker, Name(thing)) == 0)
00566 {
00567 db[thing].moniker = db[thing].name;
00568 }
00569 else
00570 {
00571 db[thing].moniker = StringCloneLen(pMoniker, nMoniker);
00572 }
00573 #endif // MEMORY_BASED
00574 pReturn = db[thing].moniker;
00575 }
00576 else
00577 {
00578 memcpy(tbuff, pMoniker, nMoniker+1);
00579 pReturn = tbuff;
00580 }
00581 }
00582 else
00583 {
00584
00585
00586
00587 #ifdef MEMORY_BASED
00588 if (mudconf.cache_names)
00589 {
00590 db[thing].moniker = StringClone(Name(thing));
00591 pReturn = db[thing].moniker;
00592 }
00593 else
00594 {
00595 pReturn = Name(thing);
00596 }
00597 #else // MEMORY_BASED
00598 if (mudconf.cache_names)
00599 {
00600 db[thing].moniker = db[thing].name;
00601 pReturn = db[thing].moniker;
00602 }
00603 else
00604 {
00605 pReturn = Name(thing);
00606 }
00607 #endif // MEMORY_BASED
00608 }
00609 free_lbuf(pMoniker);
00610 MEMFREE(pPureNameCopy);
00611
00612 return pReturn;
00613 }
00614
00615 void s_Name(dbref thing, const char *s)
00616 {
00617 atr_add_raw(thing, A_NAME, s);
00618 #ifndef MEMORY_BASED
00619 if (db[thing].name)
00620 {
00621 if (mudconf.cache_names)
00622 {
00623 if (db[thing].name == db[thing].purename)
00624 {
00625 db[thing].purename = NULL;
00626 }
00627 if (db[thing].name == db[thing].moniker)
00628 {
00629 db[thing].moniker = NULL;
00630 }
00631 }
00632 MEMFREE(db[thing].name);
00633 db[thing].name = NULL;
00634 }
00635 if (s)
00636 {
00637 db[thing].name = StringClone(s);
00638 }
00639 #endif // !MEMORY_BASED
00640 if (mudconf.cache_names)
00641 {
00642 if (db[thing].purename)
00643 {
00644 MEMFREE(db[thing].purename);
00645 db[thing].purename = NULL;
00646 }
00647 if (db[thing].moniker)
00648 {
00649 MEMFREE(db[thing].moniker);
00650 db[thing].moniker = NULL;
00651 }
00652 }
00653 }
00654
00655 void s_Moniker(dbref thing, const char *s)
00656 {
00657 atr_add_raw(thing, A_MONIKER, s);
00658 if (mudconf.cache_names)
00659 {
00660 #ifndef MEMORY_BASED
00661 if (db[thing].name == db[thing].moniker)
00662 {
00663 db[thing].moniker = NULL;
00664 }
00665 #endif // !MEMORY_BASED
00666 if (db[thing].moniker)
00667 {
00668 MEMFREE(db[thing].moniker);
00669 db[thing].moniker = NULL;
00670 }
00671 }
00672 }
00673
00674 void s_Pass(dbref thing, const char *s)
00675 {
00676 atr_add_raw(thing, A_PASS, s);
00677 }
00678
00679
00680
00681
00682
00683 void do_attribute
00684 (
00685 dbref executor,
00686 dbref caller,
00687 dbref enactor,
00688 int key,
00689 int nargs,
00690 char *aname,
00691 char *value
00692 )
00693 {
00694 UNUSED_PARAMETER(caller);
00695 UNUSED_PARAMETER(enactor);
00696 UNUSED_PARAMETER(nargs);
00697
00698
00699
00700 int nName;
00701 bool bValid;
00702 ATTR *va;
00703 char *pName = MakeCanonicalAttributeName(aname, &nName, &bValid);
00704 if (bValid)
00705 {
00706 va = (ATTR *)vattr_find_LEN(pName, nName);
00707 if (!va)
00708 {
00709 bValid = false;
00710 }
00711 }
00712
00713 if (!bValid)
00714 {
00715 notify(executor, "No such user-named attribute.");
00716 return;
00717 }
00718
00719 int f;
00720 char *sp;
00721 ATTR *va2;
00722 bool negate, success;
00723
00724 switch (key)
00725 {
00726 case ATTRIB_ACCESS:
00727
00728
00729
00730 mux_strupr(value);
00731 MUX_STRTOK_STATE tts;
00732 mux_strtok_src(&tts, value);
00733 mux_strtok_ctl(&tts, " ");
00734 sp = mux_strtok_parse(&tts);
00735 success = false;
00736 while (sp != NULL)
00737 {
00738
00739
00740 negate = false;
00741 if (*sp == '!')
00742 {
00743 negate = true;
00744 sp++;
00745 }
00746
00747
00748
00749 if (search_nametab(executor, attraccess_nametab, sp, &f))
00750 {
00751 success = true;
00752 if (negate)
00753 va->flags &= ~f;
00754 else
00755 va->flags |= f;
00756 }
00757 else
00758 {
00759 notify(executor, tprintf("Unknown permission: %s.", sp));
00760 }
00761
00762
00763
00764 sp = mux_strtok_parse(&tts);
00765 }
00766 if (success && !Quiet(executor))
00767 notify(executor, "Attribute access changed.");
00768 break;
00769
00770 case ATTRIB_RENAME:
00771
00772 {
00773
00774
00775 char OldName[SBUF_SIZE];
00776 int nOldName = nName;
00777 memcpy(OldName, pName, nName+1);
00778
00779
00780
00781
00782 va2 = atr_str(value);
00783 if (va2)
00784 {
00785 notify(executor, "An attribute with that name already exists.");
00786 return;
00787 }
00788 pName = MakeCanonicalAttributeName(value, &nName, &bValid);
00789 if (!bValid || vattr_rename_LEN(OldName, nOldName, pName, nName) == NULL)
00790 notify(executor, "Attribute rename failed.");
00791 else
00792 notify(executor, "Attribute renamed.");
00793 }
00794 break;
00795
00796 case ATTRIB_DELETE:
00797
00798
00799
00800 vattr_delete_LEN(pName, nName);
00801 notify(executor, "Attribute deleted.");
00802 break;
00803 }
00804 }
00805
00806
00807
00808
00809
00810 void do_fixdb
00811 (
00812 dbref executor,
00813 dbref caller,
00814 dbref enactor,
00815 int key,
00816 int nargs,
00817 char *arg1,
00818 char *arg2
00819 )
00820 {
00821 UNUSED_PARAMETER(caller);
00822 UNUSED_PARAMETER(enactor);
00823 UNUSED_PARAMETER(nargs);
00824
00825 init_match(executor, arg1, NOTYPE);
00826 match_everything(0);
00827 dbref thing = noisy_match_result();
00828 if (thing == NOTHING)
00829 {
00830 return;
00831 }
00832
00833 dbref res = NOTHING;
00834 switch (key)
00835 {
00836 case FIXDB_OWNER:
00837 case FIXDB_LOC:
00838 case FIXDB_CON:
00839 case FIXDB_EXITS:
00840 case FIXDB_NEXT:
00841 init_match(executor, arg2, NOTYPE);
00842 match_everything(0);
00843 res = noisy_match_result();
00844 break;
00845 case FIXDB_PENNIES:
00846 res = mux_atol(arg2);
00847 break;
00848 }
00849
00850 char *pValidName;
00851 switch (key)
00852 {
00853 case FIXDB_OWNER:
00854
00855 s_Owner(thing, res);
00856 if (!Quiet(executor))
00857 notify(executor, tprintf("Owner set to #%d", res));
00858 break;
00859
00860 case FIXDB_LOC:
00861
00862 s_Location(thing, res);
00863 if (!Quiet(executor))
00864 notify(executor, tprintf("Location set to #%d", res));
00865 break;
00866
00867 case FIXDB_CON:
00868
00869 s_Contents(thing, res);
00870 if (!Quiet(executor))
00871 notify(executor, tprintf("Contents set to #%d", res));
00872 break;
00873
00874 case FIXDB_EXITS:
00875
00876 s_Exits(thing, res);
00877 if (!Quiet(executor))
00878 notify(executor, tprintf("Exits set to #%d", res));
00879 break;
00880
00881 case FIXDB_NEXT:
00882
00883 s_Next(thing, res);
00884 if (!Quiet(executor))
00885 notify(executor, tprintf("Next set to #%d", res));
00886 break;
00887
00888 case FIXDB_PENNIES:
00889
00890 s_Pennies(thing, res);
00891 if (!Quiet(executor))
00892 notify(executor, tprintf("Pennies set to %d", res));
00893 break;
00894
00895 case FIXDB_NAME:
00896
00897 if (isPlayer(thing))
00898 {
00899 if (!ValidatePlayerName(arg2))
00900 {
00901 notify(executor, "That's not a good name for a player.");
00902 return;
00903 }
00904 pValidName = arg2;
00905 if (lookup_player(NOTHING, pValidName, false) != NOTHING)
00906 {
00907 notify(executor, "That name is already in use.");
00908 return;
00909 }
00910 STARTLOG(LOG_SECURITY, "SEC", "CNAME");
00911 log_name(thing),
00912 log_text(" renamed to ");
00913 log_text(pValidName);
00914 ENDLOG;
00915 if (Suspect(executor))
00916 {
00917 raw_broadcast(WIZARD, "[Suspect] %s renamed to %s",
00918 Name(thing), pValidName);
00919 }
00920 delete_player_name(thing, Name(thing));
00921 s_Name(thing, pValidName);
00922 add_player_name(thing, pValidName);
00923 }
00924 else
00925 {
00926 int nTmp;
00927 bool bValid;
00928 pValidName = MakeCanonicalObjectName(arg2, &nTmp, &bValid);
00929 if (!bValid)
00930 {
00931 notify(executor, "That is not a reasonable name.");
00932 return;
00933 }
00934 s_Name(thing, pValidName);
00935 }
00936 if (!Quiet(executor))
00937 {
00938 notify(executor, tprintf("Name set to %s", pValidName));
00939 }
00940 break;
00941 }
00942 }
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 char *MakeCanonicalAttributeName(const char *pName, int *pnName, bool *pbValid)
00955 {
00956 static char Buffer[SBUF_SIZE];
00957
00958 if ( !pName
00959 || !mux_AttrNameInitialSet(*pName))
00960 {
00961 *pnName = 0;
00962 *pbValid = false;
00963 return NULL;
00964 }
00965 int nLeft = SBUF_SIZE-1;
00966 char *p = Buffer;
00967 while (*pName && nLeft)
00968 {
00969 if (!mux_AttrNameSet(*pName))
00970 {
00971 *pnName = 0;
00972 *pbValid = false;
00973 return Buffer;
00974 }
00975 *p = mux_toupper(*pName);
00976 p++;
00977 pName++;
00978 nLeft--;
00979 }
00980 *p = '\0';
00981
00982
00983
00984
00985
00986
00987 while (*pName)
00988 {
00989 if (!mux_AttrNameSet(*pName))
00990 {
00991 *pnName = 0;
00992 *pbValid = false;
00993 return Buffer;
00994 }
00995 pName++;
00996 }
00997
00998
00999
01000 *pnName = p - Buffer;
01001 *pbValid = true;
01002 return Buffer;
01003 }
01004
01005
01006
01007 char *MakeCanonicalAttributeCommand(const char *pName, int *pnName, bool *pbValid)
01008 {
01009 if (!pName)
01010 {
01011 *pnName = 0;
01012 *pbValid = false;
01013 return NULL;
01014 }
01015
01016 static char Buffer[SBUF_SIZE];
01017 int nLeft = SBUF_SIZE-2;
01018 char *p = Buffer;
01019
01020 *p++ = '@';
01021 while (*pName && nLeft)
01022 {
01023 *p = mux_tolower(*pName);
01024 p++;
01025 pName++;
01026 nLeft--;
01027 }
01028 *p = '\0';
01029
01030
01031
01032 *pnName = p - Buffer;
01033
01034
01035
01036 *pbValid = (*pnName > 1);
01037
01038
01039
01040 return Buffer;
01041 }
01042
01043
01044
01045
01046
01047 void init_attrtab(void)
01048 {
01049 ATTR *a;
01050
01051
01052
01053
01054
01055 const unsigned char star = '*';
01056 mux_AttrNameSet[star] = true;
01057 mux_AttrNameInitialSet[star] = true;
01058 for (a = attr; a->number; a++)
01059 {
01060 int nLen;
01061 bool bValid;
01062 char *buff = MakeCanonicalAttributeName(a->name, &nLen, &bValid);
01063 if (!bValid)
01064 {
01065 continue;
01066 }
01067 anum_extend(a->number);
01068 anum_set(a->number, a);
01069 hashaddLEN(buff, nLen, a, &mudstate.attr_name_htab);
01070 }
01071 mux_AttrNameInitialSet[star] = false;
01072 mux_AttrNameSet[star] = false;
01073 }
01074
01075
01076
01077
01078
01079 ATTR *atr_str(char *s)
01080 {
01081
01082
01083 int nBuffer;
01084 bool bValid;
01085 char *buff = MakeCanonicalAttributeName(s, &nBuffer, &bValid);
01086 if (!bValid)
01087 {
01088 return NULL;
01089 }
01090
01091
01092
01093 ATTR *a = (ATTR *)hashfindLEN(buff, nBuffer, &mudstate.attr_name_htab);
01094 if (a != NULL)
01095 {
01096 return a;
01097 }
01098
01099
01100
01101 a = vattr_find_LEN(buff, nBuffer);
01102 return a;
01103 }
01104
01105
01106
01107
01108
01109 ATTR **anum_table = NULL;
01110 int anum_alc_top = 0;
01111
01112 void anum_extend(int newtop)
01113 {
01114 ATTR **anum_table2;
01115 int delta, i;
01116
01117 if (mudstate.bStandAlone)
01118 {
01119 delta = 1000;
01120 }
01121 else
01122 {
01123 delta = mudconf.init_size;
01124 }
01125 if (newtop <= anum_alc_top)
01126 {
01127 return;
01128 }
01129 if (newtop < anum_alc_top + delta)
01130 {
01131 newtop = anum_alc_top + delta;
01132 }
01133 if (anum_table == NULL)
01134 {
01135 anum_table = (ATTR **) MEMALLOC((newtop + 1) * sizeof(ATTR *));
01136 ISOUTOFMEMORY(anum_table);
01137 for (i = 0; i <= newtop; i++)
01138 {
01139 anum_table[i] = NULL;
01140 }
01141 }
01142 else
01143 {
01144 anum_table2 = (ATTR **) MEMALLOC((newtop + 1) * sizeof(ATTR *));
01145 ISOUTOFMEMORY(anum_table2);
01146 for (i = 0; i <= anum_alc_top; i++)
01147 {
01148 anum_table2[i] = anum_table[i];
01149 }
01150 for (i = anum_alc_top + 1; i <= newtop; i++)
01151 {
01152 anum_table2[i] = NULL;
01153 }
01154 MEMFREE((char *)anum_table);
01155 anum_table = anum_table2;
01156 }
01157 anum_alc_top = newtop;
01158 }
01159
01160
01161
01162
01163 ATTR *atr_num(int anum)
01164 {
01165 if (anum > anum_alc_top)
01166 {
01167 return NULL;
01168 }
01169 return anum_get(anum);
01170 }
01171
01172 static void SetupThrottle(dbref executor)
01173 {
01174 CLinearTimeAbsolute tNow;
01175 CLinearTimeDelta ltdHour;
01176
01177 ltdHour.SetSeconds(60*60);
01178 tNow.GetUTC();
01179
01180 db[executor].tThrottleExpired = tNow + ltdHour;
01181 s_ThAttrib(executor, mudconf.vattr_per_hour);
01182 s_ThMail(executor, mudconf.mail_per_hour);
01183 }
01184
01185 static void SetupGlobalThrottle(void)
01186 {
01187 CLinearTimeAbsolute tNow;
01188 CLinearTimeDelta ltdHour;
01189
01190 ltdHour.SetSeconds(60*60);
01191 tNow.GetUTC();
01192
01193 mudstate.tThrottleExpired = tNow + ltdHour;
01194 mudstate.pcreates_this_hour = mudconf.pcreate_per_hour;
01195 }
01196
01197 bool ThrottlePlayerCreate(void)
01198 {
01199 if (0 < mudstate.pcreates_this_hour)
01200 {
01201 mudstate.pcreates_this_hour--;
01202 return false;
01203 }
01204 CLinearTimeAbsolute tNow;
01205 tNow.GetUTC();
01206 if (mudstate.tThrottleExpired <= tNow)
01207 {
01208 SetupGlobalThrottle();
01209 return false;
01210 }
01211 return true;
01212 }
01213
01214 bool ThrottleAttributeNames(dbref executor)
01215 {
01216 if (0 < ThAttrib(executor))
01217 {
01218 s_ThAttrib(executor, ThAttrib(executor)-1);
01219 return false;
01220 }
01221 CLinearTimeAbsolute tNow;
01222 tNow.GetUTC();
01223 if (db[executor].tThrottleExpired <= tNow)
01224 {
01225 SetupThrottle(executor);
01226 return false;
01227 }
01228 return true;
01229 }
01230
01231 bool ThrottleMail(dbref executor)
01232 {
01233 if (0 < ThMail(executor))
01234 {
01235 s_ThMail(executor, ThMail(executor)-1);
01236 return false;
01237 }
01238 CLinearTimeAbsolute tNow;
01239 tNow.GetUTC();
01240 if (db[executor].tThrottleExpired <= tNow)
01241 {
01242 SetupThrottle(executor);
01243 return false;
01244 }
01245 return true;
01246 }
01247
01248
01249
01250
01251
01252 int mkattr(dbref executor, char *buff)
01253 {
01254 ATTR *ap = atr_str(buff);
01255 if (!ap)
01256 {
01257
01258
01259 int nName;
01260 bool bValid;
01261 char *pName = MakeCanonicalAttributeName(buff, &nName, &bValid);
01262 ATTR *va;
01263 if (bValid)
01264 {
01265 if ( !Wizard(executor)
01266 && ThrottleAttributeNames(executor))
01267 {
01268 return -1;
01269 }
01270 int aflags = mudconf.vattr_flags;
01271 if (pName[0] == '_')
01272 {
01273
01274
01275
01276
01277 aflags |= AF_MDARK | AF_WIZARD;
01278 }
01279 va = vattr_alloc_LEN(pName, nName, aflags);
01280 if (va && va->number)
01281 {
01282 return va->number;
01283 }
01284 }
01285 return -1;
01286 }
01287 else if (ap->number)
01288 {
01289 return ap->number;
01290 }
01291 return -1;
01292 }
01293
01294 #ifndef MEMORY_BASED
01295
01296
01297
01298
01299
01300 static int al_decode(char **app)
01301 {
01302 char *ap = *app;
01303
01304 int atrnum = 0, atrshft = 0;
01305 for (;;)
01306 {
01307 int ch = *ap++;
01308 int bits = ch & 0x7F;
01309
01310 if (atrshft > 0)
01311 atrnum |= (bits << atrshft);
01312 else
01313 atrnum = bits;
01314
01315 if ((ch & 0x80) == 0)
01316 {
01317 *app = ap;
01318 return atrnum;
01319 }
01320 atrshft += 7;
01321 }
01322 }
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 static char *al_code(char *ap, int atrnum)
01333 {
01334 int bits;
01335 for (;;)
01336 {
01337 bits = atrnum & 0x7F;
01338 if (atrnum <= 0x7F)
01339 {
01340 break;
01341 }
01342 atrnum >>= 7;
01343 bits |= 0x80;
01344 *ap++ = (char)bits;
01345 }
01346 *ap++ = (char)bits;
01347 return ap;
01348 }
01349
01350 #endif // MEMORY_BASED
01351
01352
01353
01354
01355
01356 bool Commer(dbref thing)
01357 {
01358 if (mudstate.bfNoCommands.IsSet(thing))
01359 {
01360
01361
01362 return false;
01363 }
01364 else if (mudstate.bfCommands.IsSet(thing))
01365 {
01366
01367
01368 return true;
01369 }
01370
01371 bool bFoundListens = false;
01372
01373 char *as;
01374 atr_push();
01375 char *buff = alloc_lbuf("Commer");
01376 for (int atr = atr_head(thing, &as); atr; atr = atr_next(&as))
01377 {
01378 ATTR *ap = atr_num(atr);
01379 if ( !ap
01380 || (ap->flags & AF_NOPROG))
01381 {
01382 continue;
01383 }
01384
01385 int aflags;
01386 dbref aowner;
01387
01388 atr_get_str(buff, thing, atr, &aowner, &aflags);
01389
01390 if (aflags & AF_NOPROG)
01391 {
01392 continue;
01393 }
01394
01395 if ( AMATCH_CMD != buff[0]
01396 && AMATCH_LISTEN != buff[0])
01397 {
01398 continue;
01399 }
01400
01401
01402
01403 char *s = strchr(buff+1, ':');
01404 if (!s)
01405 {
01406 continue;
01407 }
01408
01409 if (AMATCH_CMD == buff[0])
01410 {
01411 free_lbuf(buff);
01412 atr_pop();
01413 mudstate.bfCommands.Set(thing);
01414 if (bFoundListens)
01415 {
01416 mudstate.bfListens.Set(thing);
01417 mudstate.bfNoListens.Clear(thing);
01418 }
01419 return true;
01420 }
01421 else
01422 {
01423 bFoundListens = true;
01424 }
01425 }
01426 free_lbuf(buff);
01427 atr_pop();
01428 mudstate.bfNoCommands.Set(thing);
01429 if (bFoundListens)
01430 {
01431 mudstate.bfListens.Set(thing);
01432 mudstate.bfNoListens.Clear(thing);
01433 }
01434 else
01435 {
01436 mudstate.bfNoListens.Set(thing);
01437 mudstate.bfListens.Clear(thing);
01438 }
01439 return false;
01440 }
01441
01442
01443
01444
01445 #ifndef MEMORY_BASED
01446
01447
01448
01449
01450
01451
01452 static void al_extend(char **buffer, size_t *bufsiz, size_t len, bool copy)
01453 {
01454 if (len > *bufsiz)
01455 {
01456 int newsize = len + ATR_BUF_CHUNK;
01457 char *tbuff = (char *)MEMALLOC(newsize);
01458 ISOUTOFMEMORY(tbuff);
01459 if (*buffer)
01460 {
01461 if (copy)
01462 {
01463 memcpy(tbuff, *buffer, *bufsiz);
01464 }
01465 MEMFREE(*buffer);
01466 *buffer = NULL;
01467 }
01468 *buffer = tbuff;
01469 *bufsiz = newsize;
01470 }
01471 }
01472
01473
01474
01475 void al_store(void)
01476 {
01477 if (mudstate.mod_al_id != NOTHING)
01478 {
01479 if (mudstate.mod_alist_len)
01480 {
01481 atr_add_raw_LEN(mudstate.mod_al_id, A_LIST, mudstate.mod_alist, mudstate.mod_alist_len);
01482 }
01483 else
01484 {
01485 atr_clr(mudstate.mod_al_id, A_LIST);
01486 }
01487 }
01488 mudstate.mod_al_id = NOTHING;
01489 }
01490
01491
01492
01493 static char *al_fetch(dbref thing)
01494 {
01495
01496
01497 if (mudstate.mod_al_id == thing)
01498 {
01499 return mudstate.mod_alist;
01500 }
01501
01502
01503
01504 al_store();
01505 size_t len;
01506 const char *astr = atr_get_raw_LEN(thing, A_LIST, &len);
01507 if (astr)
01508 {
01509 al_extend(&mudstate.mod_alist, &mudstate.mod_size, len+1, false);
01510 memcpy(mudstate.mod_alist, astr, len+1);
01511 mudstate.mod_alist_len = len;
01512 }
01513 else
01514 {
01515 al_extend(&mudstate.mod_alist, &mudstate.mod_size, 1, false);
01516 *mudstate.mod_alist = '\0';
01517 mudstate.mod_alist_len = 0;
01518 }
01519 mudstate.mod_al_id = thing;
01520 return mudstate.mod_alist;
01521 }
01522
01523
01524
01525 static bool al_add(dbref thing, int attrnum)
01526 {
01527 char *abuf = al_fetch(thing);
01528 char *cp = abuf;
01529 int anum;
01530
01531
01532
01533 while (*cp)
01534 {
01535 anum = al_decode(&cp);
01536 if (anum == attrnum)
01537 {
01538 return true;
01539 }
01540 }
01541
01542
01543
01544 int iPosition = cp - abuf;
01545
01546
01547
01548 if (iPosition + ATR_BUF_INCR >= LBUF_SIZE)
01549 {
01550 return false;
01551 }
01552
01553
01554
01555 al_extend(&mudstate.mod_alist, &mudstate.mod_size, (iPosition + ATR_BUF_INCR), true);
01556 if (mudstate.mod_alist != abuf)
01557 {
01558
01559
01560 cp = mudstate.mod_alist + iPosition;
01561 }
01562
01563
01564
01565 cp = al_code(cp, attrnum);
01566 *cp = '\0';
01567 mudstate.mod_alist_len = cp - mudstate.mod_alist;
01568 return true;
01569 }
01570
01571
01572
01573 static void al_delete(dbref thing, int attrnum)
01574 {
01575 int anum;
01576 char *abuf, *cp, *dp;
01577
01578
01579
01580 if (attrnum == A_LIST)
01581 {
01582 return;
01583 }
01584 abuf = al_fetch(thing);
01585 if (!abuf)
01586 {
01587 return;
01588 }
01589
01590 cp = abuf;
01591 while (*cp)
01592 {
01593 dp = cp;
01594 anum = al_decode(&cp);
01595 if (anum == attrnum)
01596 {
01597 while (*cp)
01598 {
01599 anum = al_decode(&cp);
01600 dp = al_code(dp, anum);
01601 }
01602 *dp = '\0';
01603 mudstate.mod_alist_len = dp - mudstate.mod_alist;
01604 return;
01605 }
01606 }
01607 return;
01608 }
01609
01610 static DCL_INLINE void makekey(dbref thing, int atr, Aname *abuff)
01611 {
01612 abuff->object = thing;
01613 abuff->attrnum = atr;
01614 return;
01615 }
01616 #endif // !MEMORY_BASED
01617
01618
01619
01620
01621
01622 static char *atr_encode(char *iattr, dbref thing, dbref owner, int flags, int atr)
01623 {
01624 UNUSED_PARAMETER(atr);
01625
01626
01627
01628
01629 if (((owner == Owner(thing)) || (owner == NOTHING)) && !flags)
01630 return iattr;
01631
01632
01633
01634 if (owner == NOTHING)
01635 owner = Owner(thing);
01636 return tprintf("%c%d:%d:%s", ATR_INFO_CHAR, owner, flags, iattr);
01637 }
01638
01639
01640
01641
01642 static const char *atr_decode_flags_owner(const char *iattr, dbref *owner, int *flags)
01643 {
01644
01645
01646 *flags = 0;
01647 if (*iattr != ATR_INFO_CHAR)
01648 {
01649 return iattr;
01650 }
01651
01652
01653
01654 const char *cp = iattr + 1;
01655
01656
01657
01658 bool neg = false;
01659 if (*cp == '-')
01660 {
01661 neg = true;
01662 cp++;
01663 }
01664 int tmp_owner = 0;
01665 unsigned int ch = *cp;
01666 while (mux_isdigit(ch))
01667 {
01668 cp++;
01669 tmp_owner = 10*tmp_owner + (ch-'0');
01670 ch = *cp;
01671 }
01672 if (neg)
01673 {
01674 tmp_owner = -tmp_owner;
01675 }
01676
01677
01678
01679 if (*cp++ != ':')
01680 {
01681 return iattr;
01682 }
01683
01684
01685
01686 int tmp_flags = 0;
01687 ch = *cp;
01688 while (mux_isdigit(ch))
01689 {
01690 cp++;
01691 tmp_flags = 10*tmp_flags + (ch-'0');
01692 ch = *cp;
01693 }
01694
01695
01696
01697 if (*cp++ != ':')
01698 {
01699 return iattr;
01700 }
01701
01702
01703
01704 if (tmp_owner != NOTHING)
01705 {
01706 *owner = tmp_owner;
01707 }
01708 *flags = tmp_flags;
01709 return cp;
01710 }
01711
01712
01713
01714
01715 static void atr_decode_LEN(const char *iattr, int nLen, char *oattr,
01716 dbref thing, dbref *owner, int *flags, size_t *pLen)
01717 {
01718
01719
01720 *owner = Owner(thing);
01721
01722
01723
01724 const char *cp = atr_decode_flags_owner(iattr, owner, flags);
01725
01726
01727
01728 *pLen = nLen - (cp - iattr);
01729 if (oattr)
01730 {
01731 memcpy(oattr, cp, (*pLen) + 1);
01732 }
01733 }
01734
01735
01736
01737
01738
01739 void atr_clr(dbref thing, int atr)
01740 {
01741 #ifdef MEMORY_BASED
01742
01743 if ( !db[thing].nALUsed
01744 || !db[thing].pALHead)
01745 {
01746 return;
01747 }
01748
01749 mux_assert(0 <= db[thing].nALUsed);
01750
01751
01752
01753 int lo = 0;
01754 int mid;
01755 int hi = db[thing].nALUsed - 1;
01756 ATRLIST *list = db[thing].pALHead;
01757 while (lo <= hi)
01758 {
01759 mid = ((hi - lo) >> 1) + lo;
01760 if (list[mid].number > atr)
01761 {
01762 hi = mid - 1;
01763 }
01764 else if (list[mid].number < atr)
01765 {
01766 lo = mid + 1;
01767 }
01768 else
01769 {
01770 MEMFREE(list[mid].data);
01771 list[mid].data = NULL;
01772 db[thing].nALUsed--;
01773 if (mid != db[thing].nALUsed)
01774 {
01775 memmove( list + mid,
01776 list + mid + 1,
01777 (db[thing].nALUsed - mid) * sizeof(ATRLIST));
01778 }
01779 break;
01780 }
01781 }
01782 #else // MEMORY_BASED
01783 Aname okey;
01784
01785 makekey(thing, atr, &okey);
01786 cache_del(&okey);
01787 al_delete(thing, atr);
01788 #endif // MEMORY_BASED
01789
01790 switch (atr)
01791 {
01792 case A_STARTUP:
01793
01794 db[thing].fs.word[FLAG_WORD1] &= ~HAS_STARTUP;
01795 break;
01796
01797 case A_DAILY:
01798
01799 db[thing].fs.word[FLAG_WORD2] &= ~HAS_DAILY;
01800 break;
01801
01802 case A_FORWARDLIST:
01803
01804 db[thing].fs.word[FLAG_WORD2] &= ~HAS_FWDLIST;
01805 if (!mudstate.bStandAlone)
01806 {
01807
01808
01809 fwdlist_clr(thing);
01810 }
01811 break;
01812
01813 case A_LISTEN:
01814
01815 db[thing].fs.word[FLAG_WORD2] &= ~HAS_LISTEN;
01816 break;
01817
01818 case A_TIMEOUT:
01819
01820 desc_reload(thing);
01821 break;
01822
01823 case A_QUEUEMAX:
01824
01825 pcache_reload(thing);
01826 break;
01827
01828 default:
01829
01830
01831
01832
01833 mudstate.bfListens.Clear(thing);
01834 mudstate.bfCommands.Clear(thing);
01835 break;
01836 }
01837 }
01838
01839
01840
01841
01842
01843 void atr_add_raw_LEN(dbref thing, int atr, const char *szValue, int nValue)
01844 {
01845 if ( !szValue
01846 || '\0' == szValue[0])
01847 {
01848 atr_clr(thing, atr);
01849 return;
01850 }
01851
01852 #ifdef MEMORY_BASED
01853 ATRLIST *list;
01854 bool found = false;
01855 int hi, lo, mid;
01856 char *text = StringCloneLen(szValue, nValue);
01857
01858 if (!db[thing].pALHead)
01859 {
01860 db[thing].nALAlloc = INITIAL_ATRLIST_SIZE;
01861 list = (ATRLIST *)MEMALLOC(db[thing].nALAlloc*sizeof(ATRLIST));
01862 ISOUTOFMEMORY(list);
01863 db[thing].pALHead = list;
01864 db[thing].nALUsed = 1;
01865 list[0].number = atr;
01866 list[0].data = text;
01867 list[0].size = nValue + 1;
01868 found = true;
01869 }
01870 else
01871 {
01872
01873
01874 lo = 0;
01875 hi = db[thing].nALUsed - 1;
01876
01877 list = db[thing].pALHead;
01878 while (lo <= hi)
01879 {
01880 mid = ((hi - lo) >> 1) + lo;
01881 if (list[mid].number > atr)
01882 {
01883 hi = mid - 1;
01884 }
01885 else if (list[mid].number < atr)
01886 {
01887 lo = mid + 1;
01888 }
01889 else
01890 {
01891 MEMFREE(list[mid].data);
01892 list[mid].data = text;
01893 list[mid].size = nValue + 1;
01894 found = true;
01895 break;
01896 }
01897 }
01898
01899 if (!found)
01900 {
01901
01902
01903
01904 if (db[thing].nALUsed < db[thing].nALAlloc)
01905 {
01906 memmove( list + lo + 1,
01907 list + lo,
01908 (db[thing].nALUsed - lo) * sizeof(ATRLIST));
01909 }
01910 else
01911 {
01912
01913
01914 db[thing].nALAlloc += ATRLIST_CHUNK;
01915 list = (ATRLIST *)MEMALLOC(db[thing].nALAlloc
01916 * sizeof(ATRLIST));
01917 ISOUTOFMEMORY(list);
01918
01919
01920
01921 if (lo > 0)
01922 {
01923 memcpy(list, db[thing].pALHead, lo * sizeof(ATRLIST));
01924 }
01925
01926
01927
01928 if (lo < db[thing].nALUsed)
01929 {
01930 memcpy( list + lo + 1,
01931 db[thing].pALHead + lo,
01932 (db[thing].nALUsed - lo) * sizeof(ATRLIST));
01933 }
01934 MEMFREE(db[thing].pALHead);
01935 db[thing].pALHead = list;
01936 }
01937 db[thing].nALUsed++;
01938 list[lo].data = text;
01939 list[lo].number = atr;
01940 list[lo].size = nValue + 1;
01941 }
01942 }
01943
01944 #else // MEMORY_BASED
01945
01946 if (nValue > LBUF_SIZE-1)
01947 {
01948 nValue = LBUF_SIZE-1;
01949 }
01950
01951 Aname okey;
01952 makekey(thing, atr, &okey);
01953 if (atr == A_LIST)
01954 {
01955
01956
01957 cache_put(&okey, szValue, nValue+1);
01958 }
01959 else
01960 {
01961 if (!al_add(thing, atr))
01962 {
01963 return;
01964 }
01965 cache_put(&okey, szValue, nValue+1);
01966 }
01967 #endif // MEMORY_BASED
01968
01969 switch (atr)
01970 {
01971 case A_STARTUP:
01972
01973 db[thing].fs.word[FLAG_WORD1] |= HAS_STARTUP;
01974 break;
01975
01976 case A_DAILY:
01977
01978 db[thing].fs.word[FLAG_WORD2] |= HAS_DAILY;
01979 break;
01980
01981 case A_FORWARDLIST:
01982
01983 db[thing].fs.word[FLAG_WORD2] |= HAS_FWDLIST;
01984 break;
01985
01986 case A_LISTEN:
01987
01988 db[thing].fs.word[FLAG_WORD2] |= HAS_LISTEN;
01989 break;
01990
01991 case A_TIMEOUT:
01992
01993 desc_reload(thing);
01994 break;
01995
01996 case A_QUEUEMAX:
01997
01998 pcache_reload(thing);
01999 break;
02000 }
02001 }
02002
02003 void atr_add_raw(dbref thing, int atr, const char *szValue)
02004 {
02005 atr_add_raw_LEN(thing, atr, szValue, szValue ? strlen(szValue) : 0);
02006 }
02007
02008 void atr_add(dbref thing, int atr, char *buff, dbref owner, int flags)
02009 {
02010 set_modified(thing);
02011
02012 if (!buff || !*buff)
02013 {
02014 atr_clr(thing, atr);
02015 }
02016 else
02017 {
02018 switch (buff[0])
02019 {
02020 case AMATCH_LISTEN:
02021
02022
02023
02024
02025 mudstate.bfNoListens.Clear(thing);
02026 break;
02027
02028 case AMATCH_CMD:
02029
02030
02031
02032
02033 mudstate.bfNoCommands.Clear(thing);
02034 break;
02035 }
02036
02037
02038
02039
02040 mudstate.bfListens.Clear(thing);
02041 mudstate.bfCommands.Clear(thing);
02042
02043 char *tbuff = atr_encode(buff, thing, owner, flags, atr);
02044 atr_add_raw(thing, atr, tbuff);
02045 }
02046 }
02047
02048 void atr_set_flags(dbref thing, int atr, dbref flags)
02049 {
02050 dbref aowner;
02051 int aflags;
02052 char *buff = atr_get(thing, atr, &aowner, &aflags);
02053 atr_add(thing, atr, buff, aowner, flags);
02054 free_lbuf(buff);
02055 }
02056
02057
02058
02059
02060
02061 int get_atr(char *name)
02062 {
02063 ATTR *ap = atr_str(name);
02064
02065 if (!ap)
02066 return 0;
02067 if (!(ap->number))
02068 return -1;
02069 return ap->number;
02070 }
02071
02072 #ifdef MEMORY_BASED
02073 const char *atr_get_raw_LEN(dbref thing, int atr, size_t *pLen)
02074 {
02075 if (!Good_obj(thing))
02076 {
02077 return NULL;
02078 }
02079
02080
02081
02082 ATRLIST *list = db[thing].pALHead;
02083 if (!list)
02084 {
02085 return NULL;
02086 }
02087
02088 int lo = 0;
02089 int hi = db[thing].nALUsed - 1;
02090 int mid;
02091 while (lo <= hi)
02092 {
02093 mid = ((hi - lo) >> 1) + lo;
02094 if (list[mid].number > atr)
02095 {
02096 hi = mid - 1;
02097 }
02098 else if (list[mid].number < atr)
02099 {
02100 lo = mid + 1;
02101 }
02102 else
02103 {
02104 *pLen = list[mid].size - 1;
02105 return list[mid].data;
02106 }
02107 }
02108 *pLen = 0;
02109 return NULL;
02110 }
02111
02112 #else // MEMORY_BASED
02113
02114 const char *atr_get_raw_LEN(dbref thing, int atr, size_t *pLen)
02115 {
02116 Aname okey;
02117
02118 makekey(thing, atr, &okey);
02119 int nLen;
02120 const char *a = cache_get(&okey, &nLen);
02121 nLen = a ? (nLen-1) : 0;
02122 *pLen = nLen;
02123 return a;
02124 }
02125 #endif // MEMORY_BASED
02126
02127 const char *atr_get_raw(dbref thing, int atr)
02128 {
02129 size_t Len;
02130 return atr_get_raw_LEN(thing, atr, &Len);
02131 }
02132
02133 char *atr_get_str_LEN(char *s, dbref thing, int atr, dbref *owner, int *flags,
02134 size_t *pLen)
02135 {
02136 const char *buff = atr_get_raw_LEN(thing, atr, pLen);
02137 if (!buff)
02138 {
02139 *owner = Owner(thing);
02140 *flags = 0;
02141 *pLen = 0;
02142 *s = '\0';
02143 }
02144 else
02145 {
02146 atr_decode_LEN(buff, *pLen, s, thing, owner, flags, pLen);
02147 }
02148 return s;
02149 }
02150
02151 char *atr_get_str(char *s, dbref thing, int atr, dbref *owner, int *flags)
02152 {
02153 size_t nLen;
02154 return atr_get_str_LEN(s, thing, atr, owner, flags, &nLen);
02155 }
02156
02157 char *atr_get_LEN(dbref thing, int atr, dbref *owner, int *flags, size_t *pLen)
02158 {
02159 char *buff = alloc_lbuf("atr_get");
02160 return atr_get_str_LEN(buff, thing, atr, owner, flags, pLen);
02161 }
02162
02163 char *atr_get_real(dbref thing, int atr, dbref *owner, int *flags,
02164 const char *file, const int line)
02165 {
02166 size_t nLen;
02167 char *buff = pool_alloc_lbuf("atr_get", file, line);
02168 return atr_get_str_LEN(buff, thing, atr, owner, flags, &nLen);
02169 }
02170
02171 bool atr_get_info(dbref thing, int atr, dbref *owner, int *flags)
02172 {
02173 size_t nLen;
02174 const char *buff = atr_get_raw_LEN(thing, atr, &nLen);
02175 if (!buff)
02176 {
02177 *owner = Owner(thing);
02178 *flags = 0;
02179 return false;
02180 }
02181 atr_decode_LEN(buff, nLen, NULL, thing, owner, flags, &nLen);
02182 return true;
02183 }
02184
02185 char *atr_pget_str_LEN(char *s, dbref thing, int atr, dbref *owner, int *flags, size_t *pLen)
02186 {
02187 dbref parent;
02188 int lev;
02189 ATTR *ap;
02190 const char *buff;
02191
02192 ITER_PARENTS(thing, parent, lev)
02193 {
02194 buff = atr_get_raw_LEN(parent, atr, pLen);
02195 if (buff && *buff)
02196 {
02197 atr_decode_LEN(buff, *pLen, s, thing, owner, flags, pLen);
02198 if ( lev == 0
02199 || !(*flags & AF_PRIVATE))
02200 {
02201 return s;
02202 }
02203 }
02204 if ( lev == 0
02205 && Good_obj(Parent(parent)))
02206 {
02207 ap = atr_num(atr);
02208 if (!ap || ap->flags & AF_PRIVATE)
02209 {
02210 break;
02211 }
02212 }
02213 }
02214 *owner = Owner(thing);
02215 *flags = 0;
02216 *s = '\0';
02217 *pLen = 0;
02218 return s;
02219 }
02220
02221 char *atr_pget_str(char *s, dbref thing, int atr, dbref *owner, int *flags)
02222 {
02223 size_t nLen;
02224 return atr_pget_str_LEN(s, thing, atr, owner, flags, &nLen);
02225 }
02226
02227 char *atr_pget_LEN(dbref thing, int atr, dbref *owner, int *flags, size_t *pLen)
02228 {
02229 char *buff = alloc_lbuf("atr_pget");
02230 return atr_pget_str_LEN(buff, thing, atr, owner, flags, pLen);
02231 }
02232
02233 char *atr_pget_real(dbref thing, int atr, dbref *owner, int *flags,
02234 const char *file, const int line)
02235 {
02236 size_t nLen;
02237 char *buff = pool_alloc_lbuf("atr_pget", file, line);
02238 return atr_pget_str_LEN(buff, thing, atr, owner, flags, &nLen);
02239 }
02240
02241 bool atr_pget_info(dbref thing, int atr, dbref *owner, int *flags)
02242 {
02243 dbref parent;
02244 int lev;
02245 ATTR *ap;
02246
02247 ITER_PARENTS(thing, parent, lev)
02248 {
02249 size_t nLen;
02250 const char *buff = atr_get_raw_LEN(parent, atr, &nLen);
02251 if (buff && *buff)
02252 {
02253 atr_decode_LEN(buff, nLen, NULL, thing, owner, flags, &nLen);
02254 if ((lev == 0) || !(*flags & AF_PRIVATE))
02255 {
02256 return true;
02257 }
02258 }
02259 if ((lev == 0) && Good_obj(Parent(parent)))
02260 {
02261 ap = atr_num(atr);
02262 if (!ap || ap->flags & AF_PRIVATE)
02263 break;
02264 }
02265 }
02266 *owner = Owner(thing);
02267 *flags = 0;
02268 return false;
02269 }
02270
02271
02272
02273
02274
02275 void atr_free(dbref thing)
02276 {
02277 #ifdef MEMORY_BASED
02278 if (db[thing].pALHead)
02279 {
02280 MEMFREE(db[thing].pALHead);
02281 }
02282 db[thing].pALHead = NULL;
02283 db[thing].nALAlloc = 0;
02284 db[thing].nALUsed = 0;
02285 #else // MEMORY_BASED
02286 char *as;
02287 atr_push();
02288 for (int atr = atr_head(thing, &as); atr; atr = atr_next(&as))
02289 {
02290 atr_clr(thing, atr);
02291 }
02292 atr_pop();
02293 if (mudstate.mod_al_id == thing)
02294 {
02295 al_store();
02296 }
02297 atr_clr(thing, A_LIST);
02298 #endif // MEMORY_BASED
02299
02300 mudstate.bfCommands.Clear(thing);
02301 mudstate.bfNoCommands.Set(thing);
02302 mudstate.bfListens.Clear(thing);
02303 mudstate.bfNoListens.Set(thing);
02304 }
02305
02306
02307
02308
02309
02310 void atr_cpy(dbref dest, dbref source, bool bInternal)
02311 {
02312 dbref owner = Owner(dest);
02313
02314 char *as;
02315 atr_push();
02316 for (int atr = atr_head(source, &as); atr; atr = atr_next(&as))
02317 {
02318 int aflags;
02319 dbref aowner;
02320 char *buf = atr_get(source, atr, &aowner, &aflags);
02321
02322 if (!(aflags & AF_LOCK))
02323 {
02324
02325
02326 aowner = owner;
02327 }
02328
02329 ATTR *at = atr_num(atr);
02330 if ( atr
02331 && at)
02332 {
02333 if ( !(at->flags & (AF_INTERNAL|AF_NOCLONE))
02334 && ( bInternal
02335 || God(owner)
02336 || ( !God(dest)
02337 && !(aflags & AF_LOCK)
02338 && ( ( Controls(owner, dest)
02339 && !(at->flags & (AF_WIZARD|AF_GOD))
02340 && !(aflags & (AF_WIZARD|AF_GOD)))
02341 || ( Wizard(owner)
02342 && !(at->flags & AF_GOD))))))
02343 {
02344
02345
02346 atr_add(dest, atr, buf, aowner, aflags);
02347 }
02348 }
02349 free_lbuf(buf);
02350 }
02351 atr_pop();
02352 }
02353
02354
02355
02356
02357
02358
02359 void atr_chown(dbref obj)
02360 {
02361 dbref owner = Owner(obj);
02362
02363 char *as;
02364 atr_push();
02365 for (int atr = atr_head(obj, &as); atr; atr = atr_next(&as))
02366 {
02367 int aflags;
02368 dbref aowner;
02369 char *buf = atr_get(obj, atr, &aowner, &aflags);
02370 if ( aowner != owner
02371 && !(aflags & AF_LOCK))
02372 {
02373 atr_add(obj, atr, buf, owner, aflags);
02374 }
02375 free_lbuf(buf);
02376 }
02377 atr_pop();
02378 }
02379
02380
02381
02382
02383
02384 int atr_next(char **attrp)
02385 {
02386 #ifdef MEMORY_BASED
02387 ATRCOUNT *atr;
02388
02389 if (!attrp || !*attrp)
02390 {
02391 return 0;
02392 }
02393 else
02394 {
02395 atr = (ATRCOUNT *) * attrp;
02396 if (atr->count >= db[atr->thing].nALUsed)
02397 {
02398 MEMFREE(atr);
02399 atr = NULL;
02400 return 0;
02401 }
02402 atr->count++;
02403 return db[atr->thing].pALHead[atr->count - 1].number;
02404 }
02405
02406 #else // MEMORY_BASED
02407 if (!*attrp || !**attrp)
02408 {
02409 return 0;
02410 }
02411 else
02412 {
02413 return al_decode(attrp);
02414 }
02415 #endif // MEMORY_BASED
02416 }
02417
02418
02419
02420
02421
02422 void atr_push(void)
02423 {
02424 #ifndef MEMORY_BASED
02425 ALIST *new_alist = (ALIST *) alloc_sbuf("atr_push");
02426 new_alist->data = mudstate.iter_alist.data;
02427 new_alist->len = mudstate.iter_alist.len;
02428 new_alist->next = mudstate.iter_alist.next;
02429
02430 mudstate.iter_alist.data = NULL;
02431 mudstate.iter_alist.len = 0;
02432 mudstate.iter_alist.next = new_alist;
02433 #endif // !MEMORY_BASED
02434 }
02435
02436 void atr_pop(void)
02437 {
02438 #ifndef MEMORY_BASED
02439 ALIST *old_alist = mudstate.iter_alist.next;
02440
02441 if (mudstate.iter_alist.data)
02442 {
02443 MEMFREE(mudstate.iter_alist.data);
02444 mudstate.iter_alist.data = NULL;
02445 }
02446 if (old_alist)
02447 {
02448 mudstate.iter_alist.data = old_alist->data;
02449 mudstate.iter_alist.len = old_alist->len;
02450 mudstate.iter_alist.next = old_alist->next;
02451 char *cp = (char *)old_alist;
02452 free_sbuf(cp);
02453 }
02454 else
02455 {
02456 mudstate.iter_alist.data = NULL;
02457 mudstate.iter_alist.len = 0;
02458 mudstate.iter_alist.next = NULL;
02459 }
02460 #endif // !MEMORY_BASED
02461 }
02462
02463
02464
02465
02466
02467 int atr_head(dbref thing, char **attrp)
02468 {
02469 #ifdef MEMORY_BASED
02470 if (db[thing].nALUsed)
02471 {
02472 ATRCOUNT *atr = (ATRCOUNT *) MEMALLOC(sizeof(ATRCOUNT));
02473 ISOUTOFMEMORY(atr);
02474 atr->thing = thing;
02475 atr->count = 1;
02476 *attrp = (char *)atr;
02477 return db[thing].pALHead[0].number;
02478 }
02479 return 0;
02480 #else // MEMORY_BASED
02481 const char *astr;
02482 size_t alen;
02483
02484
02485
02486 if (thing == mudstate.mod_al_id)
02487 {
02488 astr = mudstate.mod_alist;
02489 alen = mudstate.mod_alist_len;
02490 }
02491 else
02492 {
02493 astr = atr_get_raw_LEN(thing, A_LIST, &alen);
02494 }
02495
02496
02497
02498 if (!alen)
02499 {
02500 return 0;
02501 }
02502
02503
02504
02505 al_extend(&mudstate.iter_alist.data, &mudstate.iter_alist.len, alen+1, false);
02506 memcpy(mudstate.iter_alist.data, astr, alen+1);
02507 *attrp = mudstate.iter_alist.data;
02508 return atr_next(attrp);
02509 #endif // MEMORY_BASED
02510 }
02511
02512
02513
02514
02515
02516
02517 #define SIZE_HACK 1 // So mistaken refs to #-1 won't die.
02518
02519 static void initialize_objects(dbref first, dbref last)
02520 {
02521 dbref thing;
02522
02523 for (thing = first; thing < last; thing++)
02524 {
02525 s_Owner(thing, GOD);
02526 s_Flags(thing, FLAG_WORD1, (TYPE_GARBAGE | GOING));
02527 s_Powers(thing, 0);
02528 s_Powers2(thing, 0);
02529 s_Location(thing, NOTHING);
02530 s_Contents(thing, NOTHING);
02531 s_Exits(thing, NOTHING);
02532 s_Link(thing, NOTHING);
02533 s_Next(thing, NOTHING);
02534 s_Zone(thing, NOTHING);
02535 s_Parent(thing, NOTHING);
02536 s_Stack(thing, NULL);
02537 db[thing].cpu_time_used.Set100ns(0);
02538 db[thing].tThrottleExpired.Set100ns(0);
02539 s_ThAttrib(thing, 0);
02540 s_ThMail(thing, 0);
02541
02542 #ifdef MEMORY_BASED
02543 db[thing].pALHead = NULL;
02544 db[thing].nALAlloc = 0;
02545 db[thing].nALUsed = 0;
02546 #else
02547 db[thing].name = NULL;
02548 #endif // MEMORY_BASED
02549 db[thing].purename = NULL;
02550 db[thing].moniker = NULL;
02551 }
02552 }
02553
02554 void db_grow(dbref newtop)
02555 {
02556 mudstate.bfCommands.Resize(newtop);
02557 mudstate.bfNoCommands.Resize(newtop);
02558 mudstate.bfListens.Resize(newtop);
02559 mudstate.bfNoListens.Resize(newtop);
02560
02561 int delta;
02562 if (mudstate.bStandAlone)
02563 {
02564 delta = 1000;
02565 }
02566 else
02567 {
02568 delta = mudconf.init_size;
02569 }
02570
02571
02572
02573
02574
02575
02576
02577 if (newtop <= mudstate.db_top)
02578 {
02579 return;
02580 }
02581
02582
02583
02584
02585
02586 if (newtop <= mudstate.db_size)
02587 {
02588 initialize_objects(mudstate.db_top, newtop);
02589 mudstate.db_top = newtop;
02590 return;
02591 }
02592
02593
02594
02595 int newsize;
02596 if (newtop <= mudstate.db_size + delta)
02597 {
02598 newsize = mudstate.db_size + delta;
02599 }
02600 else
02601 {
02602 newsize = newtop;
02603 }
02604
02605
02606
02607 if (newsize < mudstate.min_size)
02608 {
02609 newsize = mudstate.min_size + delta;
02610 }
02611
02612
02613
02614
02615
02616
02617
02618
02619 OBJ *newdb = (OBJ *)MEMALLOC((newsize + SIZE_HACK) * sizeof(OBJ));
02620 ISOUTOFMEMORY(newdb);
02621 if (db)
02622 {
02623
02624
02625 db -= SIZE_HACK;
02626 memcpy(newdb, db, (mudstate.db_top + SIZE_HACK) * sizeof(OBJ));
02627 MEMFREE(db);
02628 }
02629 else
02630 {
02631
02632
02633
02634 db = newdb;
02635 initialize_objects(0, SIZE_HACK);
02636 }
02637 db = newdb + SIZE_HACK;
02638 newdb = NULL;
02639
02640 initialize_objects(mudstate.db_top, newtop);
02641 mudstate.db_top = newtop;
02642 mudstate.db_size = newsize;
02643
02644
02645
02646 int marksize = (newsize + 7) >> 3;
02647 MARKBUF *newmarkbuf = (MARKBUF *)MEMALLOC(marksize);
02648 ISOUTOFMEMORY(newmarkbuf);
02649 memset(newmarkbuf, 0, marksize);
02650 if (mudstate.markbits)
02651 {
02652 marksize = (newtop + 7) >> 3;
02653 memcpy(newmarkbuf, mudstate.markbits, marksize);
02654 MEMFREE(mudstate.markbits);
02655 }
02656 mudstate.markbits = newmarkbuf;
02657 }
02658
02659 void db_free(void)
02660 {
02661 char *cp;
02662
02663 if (db != NULL)
02664 {
02665 db -= SIZE_HACK;
02666 cp = (char *)db;
02667 MEMFREE(cp);
02668 cp = NULL;
02669 db = NULL;
02670 }
02671 mudstate.db_top = 0;
02672 mudstate.db_size = 0;
02673 mudstate.freelist = NOTHING;
02674 }
02675
02676 void db_make_minimal(void)
02677 {
02678 db_free();
02679 db_grow(1);
02680 s_Name(0, "Limbo");
02681 s_Flags(0, FLAG_WORD1, TYPE_ROOM);
02682 s_Flags(0, FLAG_WORD2, 0);
02683 s_Flags(0, FLAG_WORD3, 0);
02684 s_Powers(0, 0);
02685 s_Powers2(0, 0);
02686 s_Location(0, NOTHING);
02687 s_Exits(0, NOTHING);
02688 s_Link(0, NOTHING);
02689 s_Parent(0, NOTHING);
02690 s_Zone(0, NOTHING);
02691 s_Pennies(0, 0);
02692 s_Owner(0, 1);
02693
02694
02695
02696 load_player_names();
02697 const char *pmsg;
02698 dbref obj = create_player("Wizard", "potrzebie", NOTHING, false, &pmsg);
02699 s_Flags(obj, FLAG_WORD1, Flags(obj) | WIZARD);
02700 s_Powers(obj, 0);
02701 s_Powers2(obj, 0);
02702 s_Pennies(obj, 1000);
02703
02704
02705
02706 s_Location(obj, 0);
02707 s_Next(obj, NOTHING);
02708 s_Contents(0, obj);
02709 s_Link(obj, 0);
02710 }
02711
02712 dbref parse_dbref(const char *s)
02713 {
02714
02715
02716 const char *p = s;
02717 if (p[0])
02718 {
02719 do
02720 {
02721 if (!mux_isdigit(*p))
02722 {
02723 return NOTHING;
02724 }
02725 p++;
02726 } while (*p);
02727 }
02728 else
02729 {
02730 return NOTHING;
02731 }
02732 int x = mux_atol(s);
02733 return ((x >= 0) ? x : NOTHING);
02734 }
02735
02736
02737 void putref(FILE *f, dbref ref)
02738 {
02739 char buf[SBUF_SIZE];
02740 int n = mux_ltoa(ref, buf);
02741 buf[n] = '\n';
02742 fwrite(buf, sizeof(char), n+1, f);
02743 }
02744
02745
02746
02747
02748
02749
02750
02751
02752
02753
02754 static const unsigned char decode_table[256] =
02755 {
02756 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02757 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02758 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02759 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02760 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
02761 0, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
02762 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 5, 0,
02763 0, 0, 6, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02764 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02765 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02766 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02767 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02768 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02769 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02770 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02771 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
02772 };
02773
02774 #define STATE_START 0
02775 #define STATE_HAVE_ESC 1
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789 static const int action_table[2][8] =
02790 {
02791
02792 { 0, 1, 3, 4, 0, 0, 0, 0},
02793 { 2, 1, 2, 2, 5, 6, 7, 8}
02794 };
02795
02796 char *getstring_noalloc(FILE *f, int new_strings)
02797 {
02798 static char buf[2*LBUF_SIZE + 20];
02799 int c = fgetc(f);
02800 if (new_strings && c == '"')
02801 {
02802 int nBufferLeft = sizeof(buf)-10;
02803 int iState = STATE_START;
02804 char *pOutput = buf;
02805 for (;;)
02806 {
02807
02808
02809 char *pInput = pOutput + 6;
02810 if (fgets(pInput, nBufferLeft, f) == NULL)
02811 {
02812
02813
02814 *pOutput = 0;
02815 return buf;
02816 }
02817
02818 int nOutput = 0;
02819
02820
02821
02822
02823 for (;;)
02824 {
02825 char ch = *pInput++;
02826 if (iState == STATE_START)
02827 {
02828 if (decode_table[(unsigned char)ch] == 0)
02829 {
02830
02831
02832 char *p = pOutput;
02833 do
02834 {
02835 *pOutput++ = ch;
02836 ch = *pInput++;
02837 } while (decode_table[(unsigned char)ch] == 0);
02838 nOutput = pOutput - p;
02839 }
02840 }
02841 int iAction = action_table[iState][decode_table[(unsigned char)ch]];
02842 if (iAction <= 2)
02843 {
02844 if (iAction == 1)
02845 {
02846
02847
02848 break;
02849 }
02850 else
02851 {
02852
02853
02854
02855 *pOutput++ = ch;
02856 nOutput++;
02857 iState = STATE_START;
02858 }
02859 }
02860 else if (iAction == 3)
02861 {
02862
02863
02864 *pOutput = 0;
02865 return buf;
02866 }
02867 else if (iAction == 4)
02868 {
02869
02870
02871 iState = STATE_HAVE_ESC;
02872 }
02873 else if (iAction == 5)
02874 {
02875 *pOutput++ = ESC_CHAR;
02876 nOutput++;
02877 iState = STATE_START;
02878 }
02879 else if (iAction == 6)
02880 {
02881 *pOutput++ = '\n';
02882 nOutput++;
02883 iState = STATE_START;
02884 }
02885 else if (iAction == 7)
02886 {
02887 *pOutput++ = '\r';
02888 nOutput++;
02889 iState = STATE_START;
02890 }
02891 else
02892 {
02893
02894 *pOutput++ = '\t';
02895 nOutput++;
02896 iState = STATE_START;
02897 }
02898 }
02899
02900 nBufferLeft -= nOutput;
02901
02902
02903
02904 if (nBufferLeft <= 0)
02905 {
02906 *pOutput = 0;
02907 return buf;
02908 }
02909 }
02910 }
02911 else
02912 {
02913 ungetc(c, f);
02914
02915 char *p = buf;
02916 for (;;)
02917 {
02918
02919
02920 if (fgets(p, LBUF_SIZE, f) == NULL)
02921 {
02922
02923
02924 p[0] = 0;
02925 }
02926 else
02927 {
02928
02929
02930 int nLine = strlen(p);
02931 if (nLine >= 2)
02932 {
02933 if (p[nLine-2] == '\r')
02934 {
02935
02936
02937 p += nLine;
02938 continue;
02939 }
02940
02941
02942
02943 p[nLine-1] = '\0';
02944 }
02945 }
02946 return buf;
02947 }
02948 }
02949 }
02950
02951
02952
02953
02954
02955
02956 static const unsigned char encode_table[256] =
02957 {
02958 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02959 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02960 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02961 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02962 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02963 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0,
02964 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02965 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02966 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02967 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02968 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02969 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02970 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02971 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02972 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
02973 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
02974 };
02975
02976 void putstring(FILE *f, const char *pRaw)
02977 {
02978 static char aBuffer[2*LBUF_SIZE+4];
02979 char *pBuffer = aBuffer;
02980
02981
02982
02983
02984 *pBuffer++ = '"';
02985
02986 if (pRaw)
02987 {
02988 for (;;)
02989 {
02990 char ch;
02991 while ((ch = encode_table[(unsigned char)*pRaw]) == 0)
02992 {
02993 *pBuffer++ = *pRaw++;
02994 }
02995 if (ch == 1)
02996 {
02997 break;
02998 }
02999 *pBuffer++ = '\\';
03000 *pBuffer++ = *pRaw++;
03001 }
03002 }
03003
03004 *pBuffer++ = '"';
03005 *pBuffer++ = '\n';
03006
03007 fwrite(aBuffer, sizeof(char), pBuffer - aBuffer, f);
03008 }
03009
03010 int getref(FILE *f)
03011 {
03012 static char buf[SBUF_SIZE];
03013 fgets(buf, sizeof(buf), f);
03014 return mux_atol(buf);
03015 }
03016
03017 void free_boolexp(BOOLEXP *b)
03018 {
03019 if (b == TRUE_BOOLEXP)
03020 return;
03021
03022 switch (b->type)
03023 {
03024 case BOOLEXP_AND:
03025 case BOOLEXP_OR:
03026 free_boolexp(b->sub1);
03027 free_boolexp(b->sub2);
03028 free_bool(b);
03029 break;
03030 case BOOLEXP_NOT:
03031 case BOOLEXP_CARRY:
03032 case BOOLEXP_IS:
03033 case BOOLEXP_OWNER:
03034 case BOOLEXP_INDIR:
03035 free_boolexp(b->sub1);
03036 free_bool(b);
03037 break;
03038 case BOOLEXP_CONST:
03039 free_bool(b);
03040 break;
03041 case BOOLEXP_ATR:
03042 case BOOLEXP_EVAL:
03043 MEMFREE(b->sub1);
03044 b->sub1 = NULL;
03045 free_bool(b);
03046 break;
03047 }
03048 }
03049
03050 static BOOLEXP *dup_bool(BOOLEXP *b)
03051 {
03052 if (b == TRUE_BOOLEXP)
03053 return (TRUE_BOOLEXP);
03054
03055 BOOLEXP *r = alloc_bool("dup_bool");
03056 switch (r->type = b->type)
03057 {
03058 case BOOLEXP_AND:
03059 case BOOLEXP_OR:
03060 r->sub2 = dup_bool(b->sub2);
03061 case BOOLEXP_NOT:
03062 case BOOLEXP_CARRY:
03063 case BOOLEXP_IS:
03064 case BOOLEXP_OWNER:
03065 case BOOLEXP_INDIR:
03066 r->sub1 = dup_bool(b->sub1);
03067 case BOOLEXP_CONST:
03068 r->thing = b->thing;
03069 break;
03070 case BOOLEXP_EVAL:
03071 case BOOLEXP_ATR:
03072 r->thing = b->thing;
03073 r->sub1 = (BOOLEXP *)StringClone((char *)b->sub1);
03074 break;
03075 default:
03076 Log.WriteString("Bad bool type!" ENDLINE);
03077 return TRUE_BOOLEXP;
03078 }
03079 return (r);
03080 }
03081
03082 #ifndef MEMORY_BASED
03083 int init_dbfile(char *game_dir_file, char *game_pag_file, int nCachePages)
03084 {
03085 if (mudstate.bStandAlone)
03086 {
03087 Log.tinyprintf("Opening (%s,%s)" ENDLINE, game_dir_file, game_pag_file);
03088 }
03089 int cc = cache_init(game_dir_file, game_pag_file, nCachePages);
03090 if (cc != HF_OPEN_STATUS_ERROR)
03091 {
03092 if (mudstate.bStandAlone)
03093 {
03094 Log.tinyprintf("Done opening (%s,%s)." ENDLINE, game_dir_file,
03095 game_pag_file);
03096 }
03097 else
03098 {
03099 STARTLOG(LOG_ALWAYS, "INI", "LOAD");
03100 Log.tinyprintf("Using game db files: (%s,%s).", game_dir_file,
03101 game_pag_file);
03102 ENDLOG;
03103 }
03104 db_free();
03105 }
03106 return cc;
03107 }
03108 #endif // !MEMORY_BASED
03109
03110
03111
03112 bool check_zone_handler(dbref player, dbref thing, bool bPlayerCheck)
03113 {
03114 mudstate.zone_nest_num++;
03115
03116 if ( !mudconf.have_zones
03117 || !Good_obj(Zone(thing))
03118 || mudstate.zone_nest_num >= mudconf.zone_nest_lim
03119 || isPlayer(thing) != bPlayerCheck)
03120 {
03121 mudstate.zone_nest_num = 0;
03122 return false;
03123 }
03124
03125
03126
03127 if ( atr_get_raw(Zone(thing), A_LENTER)
03128 && could_doit(player, Zone(thing), A_LENTER))
03129 {
03130 mudstate.zone_nest_num = 0;
03131 return true;
03132 }
03133 else if (thing == Zone(thing))
03134 {
03135 return false;
03136 }
03137 return check_zone_handler(player, Zone(thing), false);
03138 }
03139
03140
03141
03142
03143
03144
03145 void ReleaseAllResources(dbref obj)
03146 {
03147 if (mudconf.have_comsys)
03148 {
03149 do_comdisconnect(obj);
03150 do_clearcom(obj, obj, obj, 0);
03151 do_channelnuke(obj);
03152 del_comsys(obj);
03153 }
03154 if (mudconf.have_mailer)
03155 {
03156 do_mail_clear(obj, NULL);
03157 do_mail_purge(obj);
03158 malias_cleanup(obj);
03159 }
03160 }
03161
03162 #ifndef WIN32
03163
03164
03165
03166 void dump_restart_db(void)
03167 {
03168 FILE *f;
03169 DESC *d;
03170 int version = 2;
03171
03172 f = fopen("restart.db", "wb");
03173 fprintf(f, "+V%d\n", version);
03174 putref(f, nMainGamePorts);
03175 for (int i = 0; i < nMainGamePorts; i++)
03176 {
03177 putref(f, aMainGamePorts[i].port);
03178 putref(f, aMainGamePorts[i].socket);
03179 }
03180 putref(f, mudstate.start_time.ReturnSeconds());
03181 putstring(f, mudstate.doing_hdr);
03182 putref(f, mudstate.record_players);
03183 DESC_ITER_ALL(d)
03184 {
03185 putref(f, d->descriptor);
03186 putref(f, d->flags);
03187 putref(f, d->connected_at.ReturnSeconds());
03188 putref(f, d->command_count);
03189 putref(f, d->timeout);
03190 putref(f, d->host_info);
03191 putref(f, d->player);
03192 putref(f, d->last_time.ReturnSeconds());
03193 putref(f, d->raw_input_state);
03194 putref(f, d->nvt_sga_him_state);
03195 putref(f, d->nvt_sga_us_state);
03196 putref(f, d->nvt_eor_him_state);
03197 putref(f, d->nvt_eor_us_state);
03198 putref(f, d->nvt_naws_him_state);
03199 putref(f, d->nvt_naws_us_state);
03200 putref(f, d->height);
03201 putref(f, d->width);
03202 putstring(f, d->output_prefix);
03203 putstring(f, d->output_suffix);
03204 putstring(f, d->addr);
03205 putstring(f, d->doing);
03206 putstring(f, d->username);
03207 }
03208 putref(f, 0);
03209
03210 fclose(f);
03211 }
03212
03213 void load_restart_db(void)
03214 {
03215 DESC *d;
03216 DESC *p;
03217
03218 int val;
03219 char *temp, buf[8];
03220
03221 FILE *f = fopen("restart.db", "r");
03222 if (!f)
03223 {
03224 mudstate.restarting = false;
03225 return;
03226 }
03227 DebugTotalFiles++;
03228 mudstate.restarting = true;
03229
03230 fgets(buf, 3, f);
03231 mux_assert(strncmp(buf, "+V", 2) == 0);
03232 int version = getref(f);
03233 if ( 1 == version
03234 || 2 == version)
03235 {
03236
03237
03238
03239 nMainGamePorts = getref(f);
03240 for (int i = 0; i < nMainGamePorts; i++)
03241 {
03242 aMainGamePorts[i].port = getref(f);
03243 mux_assert(aMainGamePorts[i].port > 0);
03244 aMainGamePorts[i].socket = getref(f);
03245 if (maxd <= aMainGamePorts[i].socket)
03246 {
03247 maxd = aMainGamePorts[i].socket + 1;
03248 }
03249 }
03250 }
03251 else
03252 {
03253
03254
03255
03256
03257 mux_assert(0);
03258 }
03259 DebugTotalSockets += nMainGamePorts;
03260
03261 mudstate.start_time.SetSeconds(getref(f));
03262 strcpy(mudstate.doing_hdr, getstring_noalloc(f, true));
03263 mudstate.record_players = getref(f);
03264 if (mudconf.reset_players)
03265 {
03266 mudstate.record_players = 0;
03267 }
03268
03269 while ((val = getref(f)) != 0)
03270 {
03271 ndescriptors++;
03272 DebugTotalSockets++;
03273 d = alloc_desc("restart");
03274 d->descriptor = val;
03275 d->flags = getref(f);
03276 d->connected_at.SetSeconds(getref(f));
03277 d->command_count = getref(f);
03278 d->timeout = getref(f);
03279 d->host_info = getref(f);
03280 d->player = getref(f);
03281 d->last_time.SetSeconds(getref(f));
03282 if (2 == version)
03283 {
03284 d->raw_input_state = getref(f);
03285 d->nvt_sga_him_state = getref(f);
03286 d->nvt_sga_us_state = getref(f);
03287 d->nvt_eor_him_state = getref(f);
03288 d->nvt_eor_us_state = getref(f);
03289 d->nvt_naws_him_state = getref(f);
03290 d->nvt_naws_us_state = getref(f);
03291 d->height = getref(f);
03292 d->width = getref(f);
03293 }
03294 else
03295 {
03296 d->raw_input_state = NVT_IS_NORMAL;
03297 d->nvt_sga_him_state = OPTION_NO;
03298 d->nvt_sga_us_state = OPTION_NO;
03299 d->nvt_eor_him_state = OPTION_NO;
03300 d->nvt_eor_us_state = OPTION_NO;
03301 d->nvt_naws_him_state = OPTION_NO;
03302 d->nvt_naws_us_state = OPTION_NO;
03303 d->height = 24;
03304 d->width = 78;
03305 }
03306
03307 temp = getstring_noalloc(f, true);
03308 if (*temp)
03309 {
03310 d->output_prefix = alloc_lbuf("set_userstring");
03311 strcpy(d->output_prefix, temp);
03312 }
03313 else
03314 {
03315 d->output_prefix = NULL;
03316 }
03317 temp = getstring_noalloc(f, true);
03318 if (*temp)
03319 {
03320 d->output_suffix = alloc_lbuf("set_userstring");
03321 strcpy(d->output_suffix, temp);
03322 }
03323 else
03324 {
03325 d->output_suffix = NULL;
03326 }
03327
03328 strcpy(d->addr, getstring_noalloc(f, true));
03329 strcpy(d->doing, getstring_noalloc(f, true));
03330 strcpy(d->username, getstring_noalloc(f, true));
03331
03332 d->output_size = 0;
03333 d->output_tot = 0;
03334 d->output_lost = 0;
03335 d->output_head = NULL;
03336 d->output_tail = NULL;
03337 d->input_head = NULL;
03338 d->input_tail = NULL;
03339 d->input_size = 0;
03340 d->input_tot = 0;
03341 d->input_lost = 0;
03342 d->raw_input = NULL;
03343 d->raw_input_at = NULL;
03344 d->nOption = 0;
03345 d->quota = mudconf.cmd_quota_max;
03346 d->program_data = NULL;
03347 d->hashnext = NULL;
03348
03349 if (descriptor_list)
03350 {
03351 for (p = descriptor_list; p->next; p = p->next) ;
03352 d->prev = &p->next;
03353 p->next = d;
03354 d->next = NULL;
03355 }
03356 else
03357 {
03358 d->next = descriptor_list;
03359 d->prev = &descriptor_list;
03360 descriptor_list = d;
03361 }
03362
03363 if (maxd <= d->descriptor)
03364 {
03365 maxd = d->descriptor + 1;
03366 }
03367 desc_addhash(d);
03368 if (isPlayer(d->player))
03369 {
03370 s_Connected(d->player);
03371 }
03372 }
03373
03374 DESC_ITER_CONN(d)
03375 {
03376 if (!isPlayer(d->player))
03377 {
03378 shutdownsock(d, R_QUIT);
03379 }
03380 }
03381
03382 if (fclose(f) == 0)
03383 {
03384 DebugTotalFiles--;
03385 }
03386 remove("restart.db");
03387 raw_broadcast(0, "GAME: Restart finished.");
03388 }
03389 #endif // !WIN32
03390
03391 #ifdef WIN32
03392
03393 int ReplaceFile(char *old_name, char *new_name)
03394 {
03395 DeleteFile(new_name);
03396 if (MoveFile(old_name, new_name))
03397 {
03398 return 0;
03399 }
03400 else
03401 {
03402 Log.tinyprintf("MoveFile %s to %s fails with GetLastError() of %d" ENDLINE,
03403 old_name, new_name, GetLastError());
03404 }
03405 return -1;
03406 }
03407
03408 void RemoveFile(char *name)
03409 {
03410 DeleteFile(name);
03411 }
03412
03413 #else // WIN32
03414
03415 int ReplaceFile(char *old_name, char *new_name)
03416 {
03417 if (rename(old_name, new_name) == 0)
03418 {
03419 return 0;
03420 }
03421 else
03422 {
03423 Log.tinyprintf("rename %s to %s fails with errno of %s(%d)" ENDLINE, old_name, new_name, strerror(errno), errno);
03424 }
03425 return -1;
03426 }
03427
03428 void RemoveFile(char *name)
03429 {
03430 unlink(name);
03431 }
03432 #endif // WIN32
03433