src/db.c

Go to the documentation of this file.
00001 /*
00002  * db.c 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include <sys/file.h>
00009 #include <sys/stat.h>
00010 
00011 #define __DB_C
00012 #include "mudconf.h"
00013 #include "config.h"
00014 #include "externs.h"
00015 #include "db.h"
00016 #include "attrs.h"
00017 #include "vattr.h"
00018 #include "match.h"
00019 #include "alloc.h"
00020 #include "powers.h"
00021 #include "interface.h"
00022 #include "flags.h"
00023 #include "p.comsys.h"
00024 #include "mmdb.h"
00025 
00026 #ifndef O_ACCMODE
00027 #define O_ACCMODE       (O_RDONLY|O_WRONLY|O_RDWR)
00028 #endif
00029 
00030 /*
00031  * Restart definitions 
00032  */
00033 #define RS_CONCENTRATE          0x00000002
00034 #define RS_RECORD_PLAYERS       0x00000004
00035 #define RS_NEW_STRINGS          0x00000008
00036 #define RS_HUDKEY               0x00000010
00037 
00038 OBJ *db = NULL;
00039 NAME *names = NULL;
00040 NAME *purenames = NULL;
00041 
00042 int corrupt;
00043 
00044 extern void desc_addhash(DESC *);
00045 extern void del_commac(dbref);
00046 extern void do_clear_macro(dbref player, char *s);
00047 
00048 #ifdef TEST_MALLOC
00049 int malloc_count = 0;
00050 
00051 #endif /*
00052             * * TEST_MALLOC  
00053             */
00054 
00055 extern VATTR *vattr_rename(char *, char *);
00056 
00057 typedef struct atrcount ATRCOUNT;
00058 struct atrcount {
00059         dbref thing;
00060         int count;
00061 };
00062 
00063 /*
00064  * #define GNU_MALLOC_TEST 1 
00065  */
00066 
00067 #ifdef GNU_MALLOC_TEST
00068 extern unsigned int malloc_sbrk_used;   /* Amount of data space used now */
00069 #endif
00070 
00071 /*
00072  * Check routine forward declaration. 
00073  */
00074 extern int fwdlist_ck(int, dbref, dbref, int, char *);
00075 
00076 extern void pcache_reload(dbref);
00077 extern void desc_reload(dbref);
00078 
00079 // Macro for the flags for character stats/skills attributes.
00080 #define PLSTAT_MODE (AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL)
00081 
00082 /*
00083  * list of attributes 
00084  */
00085 ATTR attr[] = {
00086         {"Aahear", A_AAHEAR, AF_ODARK, NULL},
00087         {"Aclone", A_ACLONE, AF_ODARK, NULL},
00088         {"Aconnect", A_ACONNECT, AF_ODARK, NULL},
00089         {"Adesc", A_ADESC, AF_ODARK, NULL},
00090         {"Adfail", A_ADFAIL, AF_ODARK | AF_NOPROG, NULL},
00091         {"Adisconnect", A_ADISCONNECT, AF_ODARK, NULL},
00092         {"Adrop", A_ADROP, AF_ODARK, NULL},
00093         {"Aefail", A_AEFAIL, AF_ODARK | AF_NOPROG, NULL},
00094         {"Aenter", A_AENTER, AF_ODARK, NULL},
00095         {"Afail", A_AFAIL, AF_ODARK | AF_NOPROG, NULL},
00096         {"Agfail", A_AGFAIL, AF_ODARK | AF_NOPROG, NULL},
00097         {"Ahear", A_AHEAR, AF_ODARK, NULL},
00098         {"Akill", A_AKILL, AF_ODARK, NULL},
00099         {"Aleave", A_ALEAVE, AF_ODARK, NULL},
00100         {"Alfail", A_ALFAIL, AF_ODARK | AF_NOPROG, NULL},
00101         {"Alias", A_ALIAS, AF_NOPROG | AF_NOCMD | AF_GOD, NULL},
00102         {"Allowance", A_ALLOWANCE, AF_MDARK | AF_NOPROG | AF_WIZARD, NULL},
00103         {"Amail", A_AMAIL, AF_ODARK | AF_NOPROG, NULL},
00104         {"Amhear", A_AMHEAR, AF_ODARK, NULL},
00105         {"Amove", A_AMOVE, AF_ODARK, NULL},
00106         {"Apay", A_APAY, AF_ODARK, NULL},
00107         {"Arfail", A_ARFAIL, AF_ODARK | AF_NOPROG, NULL},
00108         {"Asucc", A_ASUCC, AF_ODARK, NULL},
00109         {"Atfail", A_ATFAIL, AF_ODARK | AF_NOPROG, NULL},
00110         {"Atport", A_ATPORT, AF_ODARK | AF_NOPROG, NULL},
00111         {"Atofail", A_ATOFAIL, AF_ODARK | AF_NOPROG, NULL},
00112         {"Aufail", A_AUFAIL, AF_ODARK | AF_NOPROG, NULL},
00113         {"Ause", A_AUSE, AF_ODARK, NULL},
00114         {"Away", A_AWAY, AF_ODARK | AF_NOPROG, NULL},
00115         {"Buildcoord", A_BUILDCOORD, AF_MDARK | AF_WIZARD, NULL},
00116         {"Buildentrance", A_BUILDENTRANCE, AF_MDARK | AF_WIZARD, NULL},
00117         {"Buildlinks", A_BUILDLINKS, AF_MDARK | AF_WIZARD, NULL},
00118         {"Charges", A_CHARGES, AF_ODARK | AF_NOPROG, NULL},
00119         {"Comment", A_COMMENT, AF_MDARK | AF_WIZARD, NULL},
00120         {"Contactoptions", A_CONTACTOPT, AF_ODARK, NULL},
00121         {"Cost", A_COST, AF_ODARK, NULL},
00122         {"Daily", A_DAILY, AF_ODARK, NULL},
00123         {"HHourly", A_HOURLY, AF_MDARK, NULL},
00124         {"Desc", A_DESC, AF_NOPROG, NULL},
00125         {"DefaultLock", A_LOCK, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00126          NULL},
00127         {"Destroyer", A_DESTROYER, AF_MDARK | AF_WIZARD | AF_NOPROG, NULL},
00128         {"Dfail", A_DFAIL, AF_ODARK | AF_NOPROG, NULL},
00129         {"Drop", A_DROP, AF_ODARK | AF_NOPROG, NULL},
00130         {"DropLock", A_LDROP, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00131          NULL},
00132         {"Ealias", A_EALIAS, AF_ODARK | AF_NOPROG, NULL},
00133         {"Efail", A_EFAIL, AF_ODARK | AF_NOPROG, NULL},
00134         {"Enter", A_ENTER, AF_ODARK, NULL},
00135         {"EnterLock", A_LENTER, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00136          NULL},
00137         {"Faction", A_FACTION, AF_MDARK | AF_WIZARD, NULL},
00138         {"Fail", A_FAIL, AF_ODARK | AF_NOPROG, NULL},
00139         {"Filter", A_FILTER, AF_ODARK | AF_NOPROG, NULL},
00140         {"Forwardlist", A_FORWARDLIST, AF_ODARK | AF_NOPROG, fwdlist_ck},
00141         {"Gfail", A_GFAIL, AF_ODARK | AF_NOPROG, NULL},
00142         {"GiveLock", A_LGIVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00143         {"Idesc", A_IDESC, AF_ODARK | AF_NOPROG, NULL},
00144         {"Idle", A_IDLE, AF_ODARK | AF_NOPROG, NULL},
00145         {"Infilter", A_INFILTER, AF_ODARK | AF_NOPROG, NULL},
00146         {"Inprefix", A_INPREFIX, AF_ODARK | AF_NOPROG, NULL},
00147         {"Job", A_JOB, AF_MDARK | AF_WIZARD, NULL},
00148         {"Kill", A_KILL, AF_ODARK, NULL},
00149         {"Lalias", A_LALIAS, AF_ODARK | AF_NOPROG, NULL},
00150         {"Last", A_LAST, AF_WIZARD | AF_NOCMD | AF_NOPROG, NULL},
00151         {"Lastname", A_LASTNAME, AF_WIZARD | AF_NOPROG | AF_MDARK, NULL},
00152         {"Lastpage", A_LASTPAGE, AF_INTERNAL | AF_NOCMD | AF_NOPROG | AF_GOD | AF_PRIVATE, NULL},
00153         {"Lastsite", A_LASTSITE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_GOD, NULL},
00154         {"Leave", A_LEAVE, AF_ODARK, NULL},
00155         {"LeaveLock", A_LLEAVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00156         {"Lfail", A_LFAIL, AF_ODARK | AF_NOPROG, NULL},
00157         {"LinkLock", A_LLINK, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00158         {"Listen", A_LISTEN, AF_ODARK, NULL},
00159 
00160         {"Logindata", A_LOGINDATA, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00161         {"LRSheight", A_LRSHEIGHT, AF_ODARK, NULL},
00162         {"Unused1", A_UNUSED1, AF_WIZARD | AF_MDARK, NULL},
00163         {"Mailcurf", A_MAILCURF, AF_MDARK | AF_WIZARD | AF_NOPROG, NULL},
00164         {"Mailflags", A_MAILFLAGS, AF_MDARK | AF_WIZARD | AF_NOPROG, NULL},
00165         {"Mailfolders", A_MAILFOLDERS, AF_MDARK | AF_WIZARD | AF_NOPROG, NULL},
00166         {"Mailmsg", A_MAILMSG, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00167         {"Mailsub", A_MAILSUB, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00168         {"Mailsucc", A_MAIL, AF_ODARK | AF_NOPROG, NULL},
00169         {"Mailto", A_MAILTO, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00170         {"Mapcolor", A_MAPCOLOR, AF_ODARK, NULL},
00171         {"Mapvis", A_MAPVIS, AF_MDARK | AF_WIZARD, NULL},
00172         {"Mechdesc", A_MECHDESC, AF_MDARK, NULL},
00173         {"Mechname", A_MECHNAME, AF_MDARK, NULL},
00174         {"Mechstatus", A_MECHSTATUS, AF_MDARK | AF_WIZARD, NULL},
00175         {"Mechtype", A_MECHTYPE, AF_MDARK, NULL},
00176         {"MechPrefID", A_MECHPREFID, AF_MDARK | AF_WIZARD, NULL},
00177         {"Mechskills", A_MECHSKILLS, AF_MDARK, NULL},
00178         {"Mwtemplate", A_MWTEMPLATE, AF_MDARK, NULL},
00179         {"Move", A_MOVE, AF_ODARK, NULL},
00180         {"Name", A_NAME, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00181         {"Odesc", A_ODESC, AF_ODARK | AF_NOPROG, NULL},
00182         {"Odfail", A_ODFAIL, AF_ODARK | AF_NOPROG, NULL},
00183         {"Odrop", A_ODROP, AF_ODARK | AF_NOPROG, NULL},
00184         {"Oefail", A_OEFAIL, AF_ODARK | AF_NOPROG, NULL},
00185         {"Oenter", A_OENTER, AF_ODARK, NULL},
00186         {"Ofail", A_OFAIL, AF_ODARK | AF_NOPROG, NULL},
00187         {"Ogfail", A_OGFAIL, AF_ODARK | AF_NOPROG, NULL},
00188         {"Okill", A_OKILL, AF_ODARK, NULL},
00189         {"Amechdest", A_AMECHDEST, AF_MDARK, NULL},
00190         {"Aminetrigger", A_AMINETRIGGER, AF_MDARK, NULL},
00191         {"Oleave", A_OLEAVE, AF_ODARK, NULL},
00192         {"Olfail", A_OLFAIL, AF_ODARK | AF_NOPROG, NULL},
00193         {"Omove", A_OMOVE, AF_ODARK, NULL},
00194         {"Opay", A_OPAY, AF_ODARK, NULL},
00195         {"Orfail", A_ORFAIL, AF_ODARK | AF_NOPROG, NULL},
00196         {"Osucc", A_OSUCC, AF_ODARK | AF_NOPROG, NULL},
00197         {"Otfail", A_OTFAIL, AF_ODARK | AF_NOPROG, NULL},
00198         {"Otport", A_OTPORT, AF_ODARK | AF_NOPROG, NULL},
00199         {"Otofail", A_OTOFAIL, AF_ODARK | AF_NOPROG, NULL},
00200         {"Oufail", A_OUFAIL, AF_ODARK | AF_NOPROG, NULL},
00201         {"Ouse", A_OUSE, AF_ODARK, NULL},
00202         {"Oxenter", A_OXENTER, AF_ODARK, NULL},
00203         {"Oxleave", A_OXLEAVE, AF_ODARK, NULL},
00204         {"Oxtport", A_OXTPORT, AF_ODARK | AF_NOPROG, NULL},
00205         {"PageLock", A_LPAGE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00206         {"ParentLock", A_LPARENT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00207         {"Pay", A_PAY, AF_ODARK, NULL},
00208         {"PCequip", A_PCEQUIP, AF_MDARK, NULL},
00209         {"Pilot", A_PILOTNUM, AF_MDARK, NULL},
00210         {"Prefix", A_PREFIX, AF_ODARK | AF_NOPROG, NULL},
00211         {"ProgCmd", A_PROGCMD, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL, NULL},
00212         {"QueueMax", A_QUEUEMAX, AF_MDARK | AF_WIZARD | AF_NOPROG, NULL},
00213         {"Quota", A_QUOTA, AF_MDARK | AF_NOPROG | AF_GOD | AF_NOCMD, NULL},
00214         {"Ranknum", A_RANKNUM, AF_MDARK | AF_WIZARD, NULL},
00215         {"ReceiveLock", A_LRECEIVE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK, NULL},
00216         {"Reject", A_REJECT, AF_ODARK | AF_NOPROG, NULL},
00217         {"Rfail", A_RFAIL, AF_ODARK | AF_NOPROG, NULL},
00218         {"Rquota", A_RQUOTA, AF_MDARK | AF_NOPROG | AF_GOD | AF_NOCMD, NULL},
00219         {"Runout", A_RUNOUT, AF_ODARK, NULL},
00220 
00221         {"Semaphore", A_SEMAPHORE,
00222          AF_ODARK | AF_NOPROG | AF_WIZARD | AF_NOCMD, NULL},
00223         {"Sex", A_SEX, AF_NOPROG, NULL},
00224         {"Signature", A_SIGNATURE, AF_ODARK | AF_NOPROG, NULL},
00225         {"SpeechLock", A_LSPEECH, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00226          NULL},
00227         {"Startup", A_STARTUP, AF_ODARK, NULL},
00228         {"Succ", A_SUCC, AF_ODARK | AF_NOPROG, NULL},
00229         {"Tacsize", A_TACSIZE, AF_ODARK, NULL},
00230         {"TeloutLock", A_LTELOUT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00231          NULL},
00232         {"Tfail", A_TFAIL, AF_ODARK | AF_NOPROG, NULL},
00233         {"Timeout", A_TIMEOUT, AF_MDARK | AF_NOPROG | AF_WIZARD, NULL},
00234         {"Tport", A_TPORT, AF_ODARK | AF_NOPROG, NULL},
00235         {"TportLock", A_LTPORT, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00236          NULL},
00237         {"Tofail", A_TOFAIL, AF_ODARK | AF_NOPROG, NULL},
00238         {"Tz", A_TZ, AF_NOPROG, NULL},
00239         {"Ufail", A_UFAIL, AF_ODARK | AF_NOPROG, NULL},
00240         {"Use", A_USE, AF_ODARK, NULL},
00241         {"UseLock", A_LUSE, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00242          NULL},
00243         {"UserLock", A_LUSER, AF_ODARK | AF_NOPROG | AF_NOCMD | AF_IS_LOCK,
00244          NULL},
00245         {"VA", A_VA, AF_ODARK, NULL},
00246         {"VB", A_VA + 1, AF_ODARK, NULL},
00247         {"VC", A_VA + 2, AF_ODARK, NULL},
00248         {"VD", A_VA + 3, AF_ODARK, NULL},
00249         {"VE", A_VA + 4, AF_ODARK, NULL},
00250         {"VF", A_VA + 5, AF_ODARK, NULL},
00251         {"VG", A_VA + 6, AF_ODARK, NULL},
00252         {"VH", A_VA + 7, AF_ODARK, NULL},
00253         {"VI", A_VA + 8, AF_ODARK, NULL},
00254         {"VJ", A_VA + 9, AF_ODARK, NULL},
00255         {"VK", A_VA + 10, AF_ODARK, NULL},
00256         {"VL", A_VA + 11, AF_ODARK, NULL},
00257         {"VM", A_VA + 12, AF_ODARK, NULL},
00258         {"VN", A_VA + 13, AF_ODARK, NULL},
00259         {"VO", A_VA + 14, AF_ODARK, NULL},
00260         {"VP", A_VA + 15, AF_ODARK, NULL},
00261         {"VQ", A_VA + 16, AF_ODARK, NULL},
00262         {"VR", A_VA + 17, AF_ODARK, NULL},
00263         {"VS", A_VA + 18, AF_ODARK, NULL},
00264         {"VT", A_VA + 19, AF_ODARK, NULL},
00265         {"VU", A_VA + 20, AF_ODARK, NULL},
00266         {"VV", A_VA + 21, AF_ODARK, NULL},
00267         {"VW", A_VA + 22, AF_ODARK, NULL},
00268         {"VX", A_VA + 23, AF_ODARK, NULL},
00269         {"VY", A_VA + 24, AF_ODARK, NULL},
00270         {"VZ", A_VA + 25, AF_ODARK, NULL},
00271         {"Xtype", A_XTYPE, AF_MDARK | AF_WIZARD, NULL},
00272         {"*Password", A_PASS, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL,
00273          NULL},
00274         {"*Privileges", A_PRIVS, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL,
00275          NULL},
00276         {"*Money", A_MONEY, AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL,
00277          NULL},
00278         {"Techtime", A_TECHTIME, AF_MDARK | AF_WIZARD,
00279          NULL},
00280         {"*EconParts", A_ECONPARTS,
00281          AF_DARK | AF_NOPROG | AF_NOCMD | AF_INTERNAL,
00282          NULL},
00283         {"PLHEALTH", A_HEALTH, PLSTAT_MODE, NULL},
00284         {"PLATTRS", A_ATTRS, PLSTAT_MODE, NULL},
00285         {"PLADVS", A_ADVS, PLSTAT_MODE, NULL},
00286         {"PLSKILLS", A_SKILLS, PLSTAT_MODE, NULL},
00287 
00288         {NULL, 0, 0, NULL}
00289 };
00290 
00291 /*
00292  * ---------------------------------------------------------------------------
00293  * * fwdlist_set, fwdlist_clr: Manage cached forwarding lists
00294  */
00295 void fwdlist_set(dbref thing, FWDLIST * ifp)
00296 {
00297         FWDLIST *fp, *xfp;
00298         int i;
00299 
00300         /*
00301          * If fwdlist is null, clear 
00302          */
00303 
00304         if(!ifp || (ifp->count <= 0)) {
00305                 fwdlist_clr(thing);
00306                 return;
00307         }
00308         /*
00309          * Copy input forwardlist to a correctly-sized buffer 
00310          */
00311 
00312         fp = (FWDLIST *) XMALLOC(sizeof(int) * ((ifp->count) + 1), "fwdlist_set");
00313 
00314         for(i = 0; i < ifp->count; i++) {
00315                 fp->data[i] = ifp->data[i];
00316         }
00317         fp->count = ifp->count;
00318 
00319         /*
00320          * Replace an existing forwardlist, or add a new one 
00321          */
00322 
00323         xfp = fwdlist_get(thing);
00324         if(xfp) {
00325                 XFREE(xfp, "fwdlist_set");
00326                 nhashrepl(thing, (int *) fp, &mudstate.fwdlist_htab);
00327         } else {
00328                 nhashadd(thing, (int *) fp, &mudstate.fwdlist_htab);
00329         }
00330 }
00331 
00332 void fwdlist_clr(dbref thing)
00333 {
00334         FWDLIST *xfp;
00335 
00336         /*
00337          * If a forwardlist exists, delete it 
00338          */
00339 
00340         xfp = fwdlist_get(thing);
00341         if(xfp) {
00342                 XFREE(xfp, "fwdlist_clr");
00343                 nhashdelete(thing, &mudstate.fwdlist_htab);
00344         }
00345 }
00346 
00347 /*
00348  * ---------------------------------------------------------------------------
00349  * * fwdlist_load: Load text into a forwardlist.
00350  */
00351 int fwdlist_load(FWDLIST * fp, dbref player, char *atext)
00352 {
00353         dbref target;
00354         char *tp, *bp, *dp;
00355         int count, errors, fail;
00356 
00357         count = 0;
00358         errors = 0;
00359         bp = tp = alloc_lbuf("fwdlist_load.str");
00360         StringCopy(tp, atext);
00361         
00362         do {
00363                 for(; *bp && isspace(*bp); bp++);       /*
00364                                                          * skip spaces 
00365                                                          */
00366                 for(dp = bp; *bp && !isspace(*bp); bp++);       /*
00367                                                                  * remember string
00368                                                                  */
00369                 if(*bp)
00370                         *bp++ = '\0';                           /*
00371                                                                  * terminate string 
00372                                                                  */
00373                 if((*dp++ == '#') && isdigit(*dp)) {
00374                         target = atoi(dp);
00375                         fail = (!Good_obj(target) || (!God(player) &&
00376                             !controls(player, target) && (!Link_ok(target) || !could_doit(player, target,
00377                             A_LLINK))));
00378                         if(fail) {
00379                                 notify_printf(player,
00380                                     "Cannot forward to #%d: Permission denied.", target);
00381                                 errors++;
00382                         } else {
00383                                 fp->data[count++] = target;
00384                         }
00385                 }
00386         } while (*bp);
00387         
00388         free_lbuf(tp);
00389         fp->count = count;
00390         return errors;
00391 }
00392 
00393 /*
00394  * ---------------------------------------------------------------------------
00395  * * fwdlist_rewrite: Generate a text string from a FWDLIST buffer.
00396  */
00397 int fwdlist_rewrite(FWDLIST * fp, char *atext)
00398 {
00399         char *tp, *bp;
00400         int i, count;
00401 
00402         if(fp && fp->count) {
00403                 count = fp->count;
00404                 tp = alloc_sbuf("fwdlist_rewrite.errors");
00405                 bp = atext;
00406                 for(i = 0; i < fp->count; i++) {
00407                         if(Good_obj(fp->data[i])) {
00408                                 sprintf(tp, "#%d ", fp->data[i]);
00409                                 safe_str(tp, atext, &bp);
00410                         } else {
00411                                 count--;
00412                         }
00413                 }
00414                 *bp = '\0';
00415                 free_sbuf(tp);
00416         } else {
00417                 count = 0;
00418                 *atext = '\0';
00419         }
00420         return count;
00421 }
00422 
00423 /*
00424  * ---------------------------------------------------------------------------
00425  * * fwdlist_ck:  Check a list of dbref numbers to forward to for AUDIBLE
00426  */
00427 
00428 int fwdlist_ck(int key, dbref player, dbref thing, int anum, char *atext)
00429 {
00430         FWDLIST *fp;
00431         int count;
00432 
00433         count = 0;
00434 
00435         if(atext && *atext) {
00436                 fp = (FWDLIST *) alloc_lbuf("fwdlist_ck.fp");
00437                 fwdlist_load(fp, player, atext);
00438         } else {
00439                 fp = NULL;
00440         }
00441 
00442         /*
00443          * Set the cached forwardlist 
00444          */
00445 
00446         fwdlist_set(thing, fp);
00447         count = fwdlist_rewrite(fp, atext);
00448         if(fp)
00449                 free_lbuf(fp);
00450         return ((count > 0) || !atext || !*atext);
00451 }
00452 
00453 FWDLIST *fwdlist_get(dbref thing)
00454 {
00455         FWDLIST *fp;
00456 
00457         fp = ((FWDLIST *) nhashfind(thing, &mudstate.fwdlist_htab));
00458 
00459         return fp;
00460 }
00461 
00462 static char *set_string(char **ptr, char *new)
00463 {
00464         /*
00465          * if pointer not null unalloc it 
00466          */
00467 
00468         if(*ptr)
00469                 XFREE(*ptr, "set_string");
00470 
00471         /*
00472          * if new string is not null allocate space for it and copy it 
00473          */
00474 
00475         if(!new)                                        /*
00476                                                                  * * || !*new  
00477                                                                  */
00478                 return (*ptr = NULL);   /*
00479                                                                  * Check with GAC about this 
00480                                                                  */
00481         *ptr = (char *) XMALLOC(strlen(new) + 1, "set_string");
00482         StringCopy(*ptr, new);
00483         return (*ptr);
00484 }
00485 
00486 /*
00487  * ---------------------------------------------------------------------------
00488  * * Name, s_Name: Get or set an object's name.
00489  */
00490 INLINE char *Name(dbref thing)
00491 {
00492         dbref aowner;
00493         int aflags;
00494         char *buff;
00495         static char *tbuff[MBUF_SIZE];
00496         char buffer[MBUF_SIZE];
00497 
00498         if(mudconf.cache_names) {
00499                 if(thing > mudstate.db_top || thing < 0) {
00500                         return "#-1 INVALID DBREF";
00501                 }
00502                 if(!purenames[thing]) {
00503                         buff = atr_get(thing, A_NAME, &aowner, &aflags);
00504                         strip_ansi_r(buffer, buff, MBUF_SIZE);
00505                         set_string(&purenames[thing], buffer);
00506                         free_lbuf(buff);
00507                 }
00508         }
00509 
00510         atr_get_str((char *) tbuff, thing, A_NAME, &aowner, &aflags);
00511         return ((char *) tbuff);
00512 }
00513 
00514 INLINE char *PureName(dbref thing)
00515 {
00516         dbref aowner;
00517         int aflags;
00518         char *buff;
00519         static char *tbuff[LBUF_SIZE];
00520         char new[LBUF_SIZE];
00521 
00522         if(mudconf.cache_names) {
00523                 if(thing > mudstate.db_top || thing < 0) {
00524                         return "#-1 INVALID DBREF";
00525                 }
00526                 if(!purenames[thing]) {
00527                         buff = atr_get(thing, A_NAME, &aowner, &aflags);
00528                         strncpy(new, buff, LBUF_SIZE-1);
00529                         set_string(&purenames[thing], strip_ansi_r(new,buff,strlen(buff)));
00530                         free_lbuf(buff);
00531                 }
00532                 return purenames[thing];
00533         }
00534 
00535         atr_get_str((char *) tbuff, thing, A_NAME, &aowner, &aflags);
00536         strncpy(new, (char *) tbuff,LBUF_SIZE-1);
00537         return (strip_ansi_r(new,(char *) tbuff,strlen((char *) tbuff)));
00538 }
00539 
00540 INLINE void s_Name(dbref thing, char *s)
00541 {
00542         char new[MBUF_SIZE];
00543         /* Truncate the name if we have to */
00544 
00545         strncpy(new,s,MBUF_SIZE-1);
00546         if(s && (strlen(s) > MBUF_SIZE))
00547                 s[MBUF_SIZE] = '\0';
00548 
00549         atr_add_raw(thing, A_NAME, (char *) s);
00550 
00551         if(mudconf.cache_names) {
00552 
00553                 set_string(&purenames[thing], strip_ansi_r(new,s,strlen(s)));
00554         }
00555 }
00556 
00557 void s_Pass(dbref thing, const char *s)
00558 {
00559         atr_add_raw(thing, A_PASS, (char *) s);
00560 }
00561 
00562 /*
00563  * ---------------------------------------------------------------------------
00564  * * do_attrib: Manage user-named attributes.
00565  */
00566 
00567 extern NAMETAB attraccess_nametab[];
00568 
00569 void do_attribute(dbref player, dbref cause, int key, char *aname,
00570                                   char *value)
00571 {
00572         int success, negate, f;
00573         char *buff, *sp, *p, *q;
00574         VATTR *va;
00575         ATTR *va2;
00576 
00577         /*
00578          * Look up the user-named attribute we want to play with 
00579          */
00580 
00581         buff = alloc_sbuf("do_attribute");
00582         for(p = buff, q = aname; *q && ((p - buff) < (SBUF_SIZE - 1)); p++, q++)
00583                 *p = ToUpper(*q);
00584         *p = '\0';
00585 
00586         va = (VATTR *) vattr_find(buff);
00587         if(!va) {
00588                 notify(player, "No such user-named attribute.");
00589                 free_sbuf(buff);
00590                 return;
00591         }
00592         switch (key) {
00593         case ATTRIB_ACCESS:
00594 
00595                 /*
00596                  * Modify access to user-named attribute 
00597                  */
00598 
00599                 for(sp = value; *sp; sp++)
00600                         *sp = ToUpper(*sp);
00601                 sp = strtok(value, " ");
00602                 success = 0;
00603                 while (sp != NULL) {
00604 
00605                         /*
00606                          * Check for negation 
00607                          */
00608 
00609                         negate = 0;
00610                         if(*sp == '!') {
00611                                 negate = 1;
00612                                 sp++;
00613                         }
00614                         /*
00615                          * Set or clear the appropriate bit 
00616                          */
00617 
00618                         f = search_nametab(player, attraccess_nametab, sp);
00619                         if(f > 0) {
00620                                 success = 1;
00621                                 if(negate)
00622                                         va->flags &= ~f;
00623                                 else
00624                                         va->flags |= f;
00625                         } else {
00626                                 notify_printf(player, "Unknown permission: %s.", sp);
00627                         }
00628 
00629                         /*
00630                          * Get the next token 
00631                          */
00632 
00633                         sp = strtok(NULL, " ");
00634                 }
00635                 if(success && !Quiet(player))
00636                         notify(player, "Attribute access changed.");
00637                 break;
00638 
00639         case ATTRIB_RENAME:
00640 
00641                 /*
00642                  * Make sure the new name doesn't already exist 
00643                  */
00644 
00645                 va2 = atr_str(value);
00646                 if(va2) {
00647                         notify(player, "An attribute with that name already exists.");
00648                         free_sbuf(buff);
00649                         return;
00650                 }
00651                 if(vattr_rename(va->name, value) == NULL)
00652                         notify(player, "Attribute rename failed.");
00653                 else
00654                         notify(player, "Attribute renamed.");
00655                 break;
00656 
00657         case ATTRIB_DELETE:
00658 
00659                 /*
00660                  * Remove the attribute 
00661                  */
00662 
00663                 vattr_delete(buff);
00664                 notify(player, "Attribute deleted.");
00665                 break;
00666         }
00667         free_sbuf(buff);
00668         return;
00669 }
00670 
00671 /*
00672  * ---------------------------------------------------------------------------
00673  * * do_fixdb: Directly edit database fields
00674  */
00675 
00676 void do_fixdb(dbref player, dbref cause, int key, char *arg1, char *arg2)
00677 {
00678         dbref thing, res;
00679 
00680         init_match(player, arg1, NOTYPE);
00681         match_everything(0);
00682         thing = noisy_match_result();
00683         if(thing == NOTHING)
00684                 return;
00685 
00686         res = NOTHING;
00687         switch (key) {
00688         case FIXDB_OWNER:
00689         case FIXDB_LOC:
00690         case FIXDB_CON:
00691         case FIXDB_EXITS:
00692         case FIXDB_NEXT:
00693                 init_match(player, arg2, NOTYPE);
00694                 match_everything(0);
00695                 res = noisy_match_result();
00696                 break;
00697         case FIXDB_PENNIES:
00698                 res = atoi(arg2);
00699                 break;
00700         }
00701 
00702         switch (key) {
00703         case FIXDB_OWNER:
00704                 s_Owner(thing, res);
00705                 if(!Quiet(player))
00706                         notify_printf(player, "Owner set to #%d", res);
00707                 break;
00708         case FIXDB_LOC:
00709                 s_Location(thing, res);
00710                 if(!Quiet(player))
00711                         notify_printf(player, "Location set to #%d", res);
00712                 break;
00713         case FIXDB_CON:
00714                 s_Contents(thing, res);
00715                 if(!Quiet(player))
00716                         notify_printf(player, "Contents set to #%d", res);
00717                 break;
00718         case FIXDB_EXITS:
00719                 s_Exits(thing, res);
00720                 if(!Quiet(player))
00721                         notify_printf(player, "Exits set to #%d", res);
00722                 break;
00723         case FIXDB_NEXT:
00724                 s_Next(thing, res);
00725                 if(!Quiet(player))
00726                         notify_printf(player, "Next set to #%d", res);
00727                 break;
00728         case FIXDB_PENNIES:
00729                 s_Pennies(thing, res);
00730                 if(!Quiet(player))
00731                         notify_printf(player, "Pennies set to %d", res);
00732                 break;
00733         case FIXDB_NAME:
00734                 if(Typeof(thing) == TYPE_PLAYER) {
00735                         if(!ok_player_name(arg2)) {
00736                                 notify(player, "That's not a good name for a player.");
00737                                 return;
00738                         }
00739                         if(lookup_player(NOTHING, arg2, 0) != NOTHING) {
00740                                 notify(player, "That name is already in use.");
00741                                 return;
00742                         }
00743                         STARTLOG(LOG_SECURITY, "SEC", "CNAME") {
00744                                 log_name(thing), log_text((char *) " renamed to ");
00745                                 log_text(arg2);
00746                                 ENDLOG;
00747                         } if(Suspect(player)) {
00748                                 send_channel("Suspect", "%s renamed to %s",
00749                                                          Name(thing), arg2);
00750                         }
00751                         delete_player_name(thing, Name(thing));
00752 
00753                         s_Name(thing, arg2);
00754                         add_player_name(thing, arg2);
00755                 } else {
00756                         if(!ok_name(arg2)) {
00757                                 notify(player, "Warning: That is not a reasonable name.");
00758                         }
00759                         s_Name(thing, arg2);
00760                 }
00761                 if(!Quiet(player))
00762                         notify_printf(player, "Name set to %s", arg2);
00763                 break;
00764         }
00765 }
00766 
00767 /*
00768  * ---------------------------------------------------------------------------
00769  * * init_attrtab: Initialize the attribute hash tables.
00770  */
00771 
00772 void init_attrtab(void)
00773 {
00774         ATTR *a;
00775         char *buff, *p, *q;
00776 
00777         hashinit(&mudstate.attr_name_htab, 512);
00778         buff = alloc_sbuf("init_attrtab");
00779         for(a = attr; a->number; a++) {
00780                 anum_extend(a->number);
00781                 anum_set(a->number, a);
00782                 for(p = buff, q = (char *) a->name; *q; p++, q++)
00783                         *p = ToUpper(*q);
00784                 *p = '\0';
00785                 hashadd(buff, (int *) a, &mudstate.attr_name_htab);
00786         }
00787         free_sbuf(buff);
00788 }
00789 
00790 /*
00791  * ---------------------------------------------------------------------------
00792  * * atr_str: Look up an attribute by name.
00793  */
00794 
00795 ATTR *atr_str(char *s)
00796 {
00797         char *buff, *p, *q;
00798         ATTR *a;
00799         VATTR *va;
00800         static ATTR tattr;
00801 
00802         if(!s || !*s) {
00803                 return (NULL);
00804         }
00805 
00806         /*
00807          * Convert the buffer name to lowercase 
00808          */
00809 
00810         buff = alloc_sbuf("atr_str");
00811         for(p = buff, q = s; *q && ((p - buff) < (SBUF_SIZE - 1)); p++, q++)
00812                 *p = ToUpper(*q);
00813         *p = '\0';
00814 
00815         /*
00816          * Look for a predefined attribute 
00817          */
00818 
00819         a = (ATTR *) hashfind(buff, &mudstate.attr_name_htab);
00820         if(a != NULL) {
00821                 free_sbuf(buff);
00822                 return a;
00823         }
00824         /*
00825          * Nope, look for a user attribute 
00826          */
00827 
00828         va = (VATTR *) vattr_find(buff);
00829         free_sbuf(buff);
00830 
00831         /*
00832          * If we got one, load tattr and return a pointer to it. 
00833          */
00834 
00835         if(va != NULL) {
00836                 tattr.name = va->name;
00837                 tattr.number = va->number;
00838                 tattr.flags = va->flags;
00839                 tattr.check = NULL;
00840                 return &tattr;
00841         }
00842         /*
00843          * All failed, return NULL 
00844          */
00845 
00846         return NULL;
00847 }
00848 
00849 /*
00850  * ---------------------------------------------------------------------------
00851  * * anum_extend: Grow the attr num lookup table.
00852  */
00853 
00854 ATTR **anum_table = NULL;
00855 int anum_alc_top = 0;
00856 
00857 void anum_extend(int newtop)
00858 {
00859         ATTR **anum_table2;
00860         int delta, i;
00861 
00862         delta = mudconf.init_size;
00863 
00864         if(newtop <= anum_alc_top)
00865                 return;
00866         if(newtop < anum_alc_top + delta)
00867                 newtop = anum_alc_top + delta;
00868         if(anum_table == NULL) {
00869                 anum_table = (ATTR **) malloc((newtop + 1) * sizeof(ATTR *));
00870                 for(i = 0; i <= newtop; i++)
00871                         anum_table[i] = NULL;
00872         } else {
00873                 anum_table2 = (ATTR **) malloc((newtop + 1) * sizeof(ATTR *));
00874                 for(i = 0; i <= anum_alc_top; i++)
00875                         anum_table2[i] = anum_table[i];
00876                 for(i = anum_alc_top + 1; i <= newtop; i++)
00877                         anum_table2[i] = NULL;
00878                 free((char *) anum_table);
00879                 anum_table = anum_table2;
00880         }
00881         anum_alc_top = newtop;
00882 }
00883 
00884 /*
00885  * ---------------------------------------------------------------------------
00886  * * atr_num: Look up an attribute by number.
00887  */
00888 
00889 ATTR *atr_num(int anum)
00890 {
00891         VATTR *va;
00892         static ATTR tattr;
00893 
00894         /*
00895          * Look for a predefined attribute 
00896          */
00897 
00898         if(anum < A_USER_START)
00899                 return anum_get(anum);
00900 
00901         if(anum >= anum_alc_top)
00902                 return NULL;
00903 
00904         /*
00905          * It's a user-defined attribute, we need to copy data 
00906          */
00907 
00908         va = (VATTR *) anum_get(anum);
00909         if(va != NULL) {
00910                 tattr.name = va->name;
00911                 tattr.number = va->number;
00912                 tattr.flags = va->flags;
00913                 tattr.check = NULL;
00914                 return &tattr;
00915         }
00916         /*
00917          * All failed, return NULL 
00918          */
00919 
00920         return NULL;
00921 }
00922 
00923 /*
00924  * ---------------------------------------------------------------------------
00925  * * mkattr: Lookup attribute by name, creating if needed.
00926  */
00927 
00928 int mkattr(char *buff)
00929 {
00930         ATTR *ap;
00931         VATTR *va;
00932 
00933         if(!(ap = atr_str(buff))) {
00934 
00935                 /*
00936                  * Unknown attr, create a new one 
00937                  */
00938 
00939                 va = vattr_alloc(buff, mudconf.vattr_flags);
00940                 if(!va || !(va->number))
00941                         return -1;
00942                 return va->number;
00943         }
00944         if(!(ap->number))
00945                 return -1;
00946         return ap->number;
00947 }
00948 
00949 /*
00950  * ---------------------------------------------------------------------------
00951  * * Commer: check if an object has any $-commands in its attributes.
00952  */
00953 
00954 int Commer(dbref thing)
00955 {
00956         char *s, *as, c;
00957         int attr, aflags;
00958         dbref aowner;
00959         ATTR *ap;
00960 
00961         for(attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
00962                 ap = atr_num(attr);
00963                 if(!ap || (ap->flags & AF_NOPROG))
00964                         continue;
00965 
00966                 s = atr_get(thing, attr, &aowner, &aflags);
00967                 c = *s;
00968                 free_lbuf(s);
00969                 if((c == '$') && !(aflags & AF_NOPROG)) {
00970                         return 1;
00971                 }
00972         }
00973         return 0;
00974 }
00975 
00976 /*
00977  * routines to handle object attribute lists 
00978  */
00979 
00980 /*
00981  * ---------------------------------------------------------------------------
00982  * * atr_encode: Encode an attribute string.
00983  */
00984 static char *atr_encode(char *iattr, dbref thing, dbref owner, int flags,
00985                                                 int atr, char *dest_buffer)
00986 {
00987 
00988         /*
00989          * If using the default owner and flags (almost all attributes will),
00990          * * * * * * * just store the string. 
00991          */
00992 
00993         if(((owner == Owner(thing)) || (owner == NOTHING)) && !flags) {
00994         memset(dest_buffer, 0, LBUF_SIZE);
00995         strncpy(dest_buffer, iattr, LBUF_SIZE-1);
00996                 return dest_buffer;
00997     }
00998 
00999         /*
01000          * Encode owner and flags into the attribute text 
01001          */
01002 
01003         if(owner == NOTHING)
01004                 owner = Owner(thing);
01005     memset(dest_buffer, 0, LBUF_SIZE);
01006     snprintf(dest_buffer, LBUF_SIZE - 1, "%c%d:%d:%s", ATR_INFO_CHAR, owner, flags, iattr);
01007     return dest_buffer;
01008 }
01009 
01010 /*
01011  * ---------------------------------------------------------------------------
01012  * * atr_decode: Decode an attribute string.
01013  */
01014 
01015 static void atr_decode(char *iattr, char *oattr, dbref thing, dbref * owner,
01016                                            int *flags, int atr)
01017 {
01018         char *cp;
01019         int neg;
01020 
01021         /*
01022          * See if the first char of the attribute is the special character 
01023          */
01024 
01025         if(*iattr == ATR_INFO_CHAR) {
01026 
01027                 /*
01028                  * It is, crack the attr apart 
01029                  */
01030 
01031                 cp = &iattr[1];
01032 
01033                 /*
01034                  * Get the attribute owner 
01035                  */
01036 
01037                 *owner = 0;
01038                 neg = 0;
01039                 if(*cp == '-') {
01040                         neg = 1;
01041                         cp++;
01042                 }
01043                 while (isdigit(*cp)) {
01044                         *owner = (*owner * 10) + (*cp++ - '0');
01045                 }
01046                 if(neg)
01047                         *owner = 0 - *owner;
01048 
01049                 /*
01050                  * If delimiter is not ':', just return attribute 
01051                  */
01052 
01053                 if(*cp++ != ':') {
01054                         *owner = Owner(thing);
01055                         *flags = 0;
01056                         if(oattr) {
01057                                 StringCopy(oattr, iattr);
01058                         }
01059                         return;
01060                 }
01061                 /*
01062                  * Get the attribute flags 
01063                  */
01064 
01065                 *flags = 0;
01066                 while (isdigit(*cp)) {
01067                         *flags = (*flags * 10) + (*cp++ - '0');
01068                 }
01069 
01070                 /*
01071                  * If delimiter is not ':', just return attribute 
01072                  */
01073 
01074                 if(*cp++ != ':') {
01075                         *owner = Owner(thing);
01076                         *flags = 0;
01077                         if(oattr) {
01078                                 StringCopy(oattr, iattr);
01079                         }
01080                 }
01081                 /*
01082                  * Get the attribute text 
01083                  */
01084 
01085                 if(oattr) {
01086                         StringCopy(oattr, cp);
01087                 }
01088                 if(*owner == NOTHING)
01089                         *owner = Owner(thing);
01090         } else {
01091 
01092                 /*
01093                  * Not the special character, return normal info 
01094                  */
01095 
01096                 *owner = Owner(thing);
01097                 *flags = 0;
01098                 if(oattr) {
01099                         StringCopy(oattr, iattr);
01100                 }
01101         }
01102 }
01103 
01104 /*
01105  * ---------------------------------------------------------------------------
01106  * * atr_clr: clear an attribute in the list.
01107  */
01108 
01109 void atr_clr(dbref thing, int atr)
01110 {
01111         ATRLIST *list;
01112         int hi, lo, mid;
01113 
01114         if(!db[thing].at_count || !db[thing].ahead)
01115                 return;
01116 
01117         if(db[thing].at_count < 0)
01118                 abort();
01119 
01120         /*
01121          * Binary search for the attribute. 
01122          */
01123         lo = 0;
01124         hi = db[thing].at_count - 1;
01125         list = db[thing].ahead;
01126         while (lo <= hi) {
01127                 mid = ((hi - lo) >> 1) + lo;
01128                 if(list[mid].number == atr) {
01129                         free(list[mid].data);
01130                         db[thing].at_count -= 1;
01131                         if(mid != db[thing].at_count)
01132                                 bcopy((char *) (list + mid + 1), (char *) (list + mid),
01133                                           (db[thing].at_count - mid) * sizeof(ATRLIST));
01134                         break;
01135                 } else if(list[mid].number > atr) {
01136                         hi = mid - 1;
01137                 } else {
01138                         lo = mid + 1;
01139                 }
01140         }
01141 
01142         switch (atr) {
01143         case A_STARTUP:
01144                 s_Flags(thing, Flags(thing) & ~HAS_STARTUP);
01145                 break;
01146         case A_DAILY:
01147                 s_Flags2(thing, Flags2(thing) & ~HAS_DAILY);
01148                 break;
01149         case A_HOURLY:
01150                 s_Flags2(thing, Flags2(thing) & ~HAS_HOURLY);
01151                 break;
01152         case A_FORWARDLIST:
01153                 s_Flags2(thing, Flags2(thing) & ~HAS_FWDLIST);
01154                 break;
01155         case A_LISTEN:
01156                 s_Flags2(thing, Flags2(thing) & ~HAS_LISTEN);
01157                 break;
01158         case A_TIMEOUT:
01159                 desc_reload(thing);
01160                 break;
01161         case A_QUEUEMAX:
01162                 pcache_reload(thing);
01163                 break;
01164         }
01165 }
01166 
01167 /*
01168  * ---------------------------------------------------------------------------
01169  * * atr_add_raw, atr_add: add attribute of type atr to list
01170  */
01171 
01172 void atr_add_raw(dbref thing, int atr, char *buff)
01173 {
01174         ATRLIST *list;
01175         char *text;
01176         int found = 0;
01177         int hi, lo, mid;
01178 
01179         if(!buff || !*buff) {
01180                 atr_clr(thing, atr);
01181                 return;
01182         }
01183         if(strlen(buff) >= LBUF_SIZE) {
01184                 buff[LBUF_SIZE - 1] = '\0';
01185         }
01186         if((text = (char *) malloc(strlen(buff) + 1)) == NULL) {
01187                 return;
01188         }
01189         StringCopy(text, buff);
01190 
01191         if(!db[thing].ahead) {
01192                 if((list = (ATRLIST *) malloc(sizeof(ATRLIST))) == NULL) {
01193                         free(text);
01194                         return;
01195                 }
01196                 db[thing].ahead = list;
01197                 db[thing].at_count = 1;
01198                 list[0].number = atr;
01199                 list[0].data = text;
01200                 list[0].size = strlen(text) + 1;
01201                 found = 1;
01202         } else {
01203 
01204                 /*
01205                  * Binary search for the attribute 
01206                  */
01207                 lo = 0;
01208                 hi = db[thing].at_count - 1;
01209 
01210                 list = db[thing].ahead;
01211                 while (lo <= hi) {
01212                         mid = ((hi - lo) >> 1) + lo;
01213                         if(list[mid].number == atr) {
01214                                 free(list[mid].data);
01215                                 list[mid].data = text;
01216                                 list[mid].size = strlen(text) + 1;
01217                                 found = 1;
01218                                 break;
01219                         } else if(list[mid].number > atr) {
01220                                 hi = mid - 1;
01221                         } else {
01222                                 lo = mid + 1;
01223                         }
01224                 }
01225 
01226                 if(!found) {
01227                         /*
01228                          * If we got here, we didn't find it, so lo = hi + 1, 
01229                          * and the attribute should be inserted between them. 
01230                          */
01231 
01232                         list =
01233                                 (ATRLIST *) realloc(db[thing].ahead,
01234                                                                         (db[thing].at_count +
01235                                                                          1) * sizeof(ATRLIST));
01236 
01237                         if(!list)
01238                                 return;
01239 
01240                         /*
01241                          * Move the stuff upwards one slot 
01242                          */
01243                         if(lo < db[thing].at_count)
01244                                 bcopy((char *) (list + lo), (char *) (list + lo + 1),
01245                                           (db[thing].at_count - lo) * sizeof(ATRLIST));
01246 
01247                         list[lo].data = text;
01248                         list[lo].number = atr;
01249                         list[lo].size = strlen(text) + 1;
01250                         db[thing].at_count++;
01251                         db[thing].ahead = list;
01252                 }
01253         }
01254 
01255         switch (atr) {
01256         case A_STARTUP:
01257                 s_Flags(thing, Flags(thing) | HAS_STARTUP);
01258                 break;
01259         case A_DAILY:
01260                 s_Flags2(thing, Flags2(thing) | HAS_DAILY);
01261                 break;
01262         case A_HOURLY:
01263                 s_Flags2(thing, Flags2(thing) | HAS_HOURLY);
01264                 break;
01265         case A_FORWARDLIST:
01266                 s_Flags2(thing, Flags2(thing) | HAS_FWDLIST);
01267                 break;
01268         case A_LISTEN:
01269                 s_Flags2(thing, Flags2(thing) | HAS_LISTEN);
01270                 break;
01271         case A_TIMEOUT:
01272                 desc_reload(thing);
01273                 break;
01274         case A_QUEUEMAX:
01275                 pcache_reload(thing);
01276                 break;
01277         }
01278 }
01279 
01280 void atr_add(dbref thing, int atr, char *buff, dbref owner, int flags)
01281 {
01282         char *tbuff;
01283     char buffer[LBUF_SIZE];
01284 
01285         if(!buff || !*buff) {
01286                 atr_clr(thing, atr);
01287         } else {
01288                 tbuff = atr_encode(buff, thing, owner, flags, atr, buffer);
01289                 atr_add_raw(thing, atr, tbuff);
01290         }
01291 }
01292 
01293 void atr_set_owner(dbref thing, int atr, dbref owner)
01294 {
01295         dbref aowner;
01296         int aflags;
01297         char *buff;
01298 
01299         buff = atr_get(thing, atr, &aowner, &aflags);
01300         atr_add(thing, atr, buff, owner, aflags);
01301         free_lbuf(buff);
01302 }
01303 
01304 void atr_set_flags(dbref thing, int atr, dbref flags)
01305 {
01306         dbref aowner;
01307         int aflags;
01308         char *buff;
01309 
01310         buff = atr_get(thing, atr, &aowner, &aflags);
01311         atr_add(thing, atr, buff, aowner, flags);
01312         free_lbuf(buff);
01313 }
01314 
01315 /*
01316  * ---------------------------------------------------------------------------
01317  * * get_atr,atr_get_raw, atr_get_str, atr_get: Get an attribute from the database.
01318  */
01319 
01320 int get_atr(char *name)
01321 {
01322         ATTR *ap;
01323 
01324         if(!(ap = atr_str(name)))
01325                 return 0;
01326         if(!(ap->number))
01327                 return -1;
01328         return ap->number;
01329 }
01330 
01331 char *atr_get_raw(dbref thing, int atr)
01332 {
01333         int lo, mid, hi;
01334         ATRLIST *list;
01335 
01336         if(thing < 0)
01337                 return NULL;
01338 
01339         /*
01340          * Binary search for the attribute 
01341          */
01342         lo = 0;
01343         hi = db[thing].at_count - 1;
01344         list = db[thing].ahead;
01345         if(!list)
01346                 return NULL;
01347 
01348         while (lo <= hi) {
01349                 mid = ((hi - lo) >> 1) + lo;
01350                 if(list[mid].number == atr) {
01351 
01352                         return list[mid].data;
01353                 } else if(list[mid].number > atr) {
01354                         hi = mid - 1;
01355                 } else {
01356                         lo = mid + 1;
01357                 }
01358         }
01359         return NULL;
01360 }
01361 
01362 char *atr_get_str(char *s, dbref thing, int atr, dbref * owner, int *flags)
01363 {
01364         char *buff;
01365 
01366         buff = atr_get_raw(thing, atr);
01367         if(!buff) {
01368                 *owner = Owner(thing);
01369                 *flags = 0;
01370                 *s = '\0';
01371         } else {
01372                 atr_decode(buff, s, thing, owner, flags, atr);
01373         }
01374         return s;
01375 }
01376 
01377 char *atr_get(dbref thing, int atr, dbref * owner, int *flags)
01378 {
01379         char *buff;
01380 
01381         buff = alloc_lbuf("atr_get");
01382         return atr_get_str(buff, thing, atr, owner, flags);
01383 }
01384 
01385 int atr_get_info(dbref thing, int atr, dbref * owner, int *flags)
01386 {
01387         char *buff;
01388 
01389         buff = atr_get_raw(thing, atr);
01390         if(!buff) {
01391                 *owner = Owner(thing);
01392                 *flags = 0;
01393                 return 0;
01394         }
01395         atr_decode(buff, NULL, thing, owner, flags, atr);
01396         return 1;
01397 }
01398 
01399 char *atr_pget_str(char *s, dbref thing, int atr, dbref * owner, int *flags)
01400 {
01401         char *buff;
01402         dbref parent;
01403         int lev;
01404 
01405         ATTR *ap;
01406 
01407         ITER_PARENTS(thing, parent, lev) {
01408                 buff = atr_get_raw(parent, atr);
01409                 if(buff && *buff) {
01410                         atr_decode(buff, s, thing, owner, flags, atr);
01411                         if((lev == 0) || !(*flags & AF_PRIVATE))
01412                                 return s;
01413                 }
01414                 if((lev == 0) && Good_obj(Parent(parent))) {
01415                         ap = atr_num(atr);
01416                         if(!ap || ap->flags & AF_PRIVATE)
01417                                 break;
01418                 }
01419         }
01420         *owner = Owner(thing);
01421         *flags = 0;
01422         *s = '\0';
01423         return s;
01424 }
01425 
01426 char *atr_pget(dbref thing, int atr, dbref * owner, int *flags)
01427 {
01428         char *buff;
01429 
01430         buff = alloc_lbuf("atr_pget");
01431         return atr_pget_str(buff, thing, atr, owner, flags);
01432 }
01433 
01434 int atr_pget_info(dbref thing, int atr, dbref * owner, int *flags)
01435 {
01436         char *buff;
01437         dbref parent;
01438         int lev;
01439         ATTR *ap;
01440 
01441         ITER_PARENTS(thing, parent, lev) {
01442                 buff = atr_get_raw(parent, atr);
01443                 if(buff && *buff) {
01444                         atr_decode(buff, NULL, thing, owner, flags, atr);
01445                         if((lev == 0) || !(*flags & AF_PRIVATE))
01446                                 return 1;
01447                 }
01448                 if((lev == 0) && Good_obj(Parent(parent))) {
01449                         ap = atr_num(atr);
01450                         if(!ap || ap->flags & AF_PRIVATE)
01451                                 break;
01452                 }
01453         }
01454         *owner = Owner(thing);
01455         *flags = 0;
01456         return 0;
01457 }
01458 
01459 /*
01460  * ---------------------------------------------------------------------------
01461  * * atr_free: Return all attributes of an object.
01462  */
01463 
01464 void atr_free(dbref thing)
01465 {
01466         free(db[thing].ahead);
01467         db[thing].ahead = NULL;
01468 }
01469 
01470 /*
01471  * garbage collect an attribute list 
01472  */
01473 void atr_collect(dbref thing)
01474 {
01475         /*
01476          * Nada.  gdbm takes care of us.  I hope ;-) 
01477          */
01478 }
01479 
01480 /*
01481  * ---------------------------------------------------------------------------
01482  * * atr_cpy: Copy all attributes from one object to another.  Takes the
01483  * * player argument to ensure that only attributes that COULD be set by
01484  * * the player are copied.
01485  */
01486 
01487 void atr_cpy(dbref player, dbref dest, dbref source)
01488 {
01489         int attr, aflags;
01490         dbref owner, aowner;
01491         char *as, *buf;
01492         ATTR *at;
01493 
01494         owner = Owner(dest);
01495         for(attr = atr_head(source, &as); attr; attr = atr_next(&as)) {
01496                 buf = atr_get(source, attr, &aowner, &aflags);
01497                 if(!(aflags & AF_LOCK))
01498                         aowner = owner;         /*
01499                                                                  * chg owner 
01500                                                                  */
01501                 at = atr_num(attr);
01502                 if(attr && at) {
01503                         if(Write_attr(owner, dest, at, aflags))
01504                                 /*
01505                                  * Only set attrs that owner has perm to set 
01506                                  */
01507                                 atr_add(dest, attr, buf, aowner, aflags);
01508                 }
01509                 free_lbuf(buf);
01510         }
01511 }
01512 
01513 /*
01514  * ---------------------------------------------------------------------------
01515  * * atr_chown: Change the ownership of the attributes of an object to the
01516  * * current owner if they are not locked.
01517  */
01518 
01519 void atr_chown(dbref obj)
01520 {
01521         int attr, aflags;
01522         dbref owner, aowner;
01523         char *as, *buf;
01524 
01525         owner = Owner(obj);
01526         for(attr = atr_head(obj, &as); attr; attr = atr_next(&as)) {
01527                 buf = atr_get(obj, attr, &aowner, &aflags);
01528                 if((aowner != owner) && !(aflags & AF_LOCK))
01529                         atr_add(obj, attr, buf, owner, aflags);
01530                 free_lbuf(buf);
01531         }
01532 }
01533 
01534 /*
01535  * ---------------------------------------------------------------------------
01536  * * atr_next: Return next attribute in attribute list.
01537  */
01538 
01539 int atr_next(char **attrp)
01540 {
01541         ATRCOUNT *atr;
01542 
01543         if(!attrp || !*attrp) {
01544                 return 0;
01545         } else {
01546                 atr = (ATRCOUNT *) * attrp;
01547                 if(atr->count > db[atr->thing].at_count) {
01548                         free(atr);
01549                         return 0;
01550                 }
01551                 atr->count++;
01552                 return db[atr->thing].ahead[atr->count - 2].number;
01553         }
01554 }
01555 
01556 /*
01557  * ---------------------------------------------------------------------------
01558  * * atr_head: Returns the head of the attr list for object 'thing'
01559  */
01560 
01561 int atr_head(dbref thing, char **attrp)
01562 {
01563         ATRCOUNT *atr;
01564 
01565         if(db[thing].at_count) {
01566                 atr = (ATRCOUNT *) malloc(sizeof(ATRCOUNT));
01567                 atr->thing = thing;
01568                 atr->count = 2;
01569                 *attrp = (char *) atr;
01570                 return db[thing].ahead[0].number;
01571         }
01572         return 0;
01573 }
01574 
01575 /*
01576  * ---------------------------------------------------------------------------
01577  * * db_grow: Extend the struct database.
01578  */
01579 
01580 #define SIZE_HACK       1                       /*
01581                                                                  * * So mistaken refs to #-1 won't die.  
01582                                                                  */
01583 
01584 void initialize_objects(dbref first, dbref last)
01585 {
01586         dbref thing;
01587 
01588         for(thing = first; thing < last; thing++) {
01589         memset(&db[thing], 0, sizeof(db[0]));
01590                 s_Owner(thing, GOD);
01591                 s_Flags(thing, (TYPE_GARBAGE | GOING));
01592                 s_Flags2(thing, 0);
01593                 s_Flags3(thing, 0);
01594                 s_Powers(thing, 0);
01595                 s_Powers2(thing, 0);
01596                 s_Location(thing, NOTHING);
01597                 s_Contents(thing, NOTHING);
01598                 s_Exits(thing, NOTHING);
01599                 s_Link(thing, NOTHING);
01600                 s_Next(thing, NOTHING);
01601                 s_Zone(thing, NOTHING);
01602                 s_Parent(thing, NOTHING);
01603                 s_Stack(thing, NULL);
01604                 db[thing].ahead = NULL;
01605                 db[thing].at_count = 0;
01606         }
01607 }
01608 
01609 void db_grow(dbref newtop)
01610 {
01611         int newsize, marksize, delta, i;
01612         MARKBUF *newmarkbuf;
01613         OBJ *newdb;
01614         NAME *newpurenames;
01615 
01616         char *cp;
01617 
01618         delta = mudconf.init_size;
01619 
01620         /*
01621          * Determine what to do based on requested size, current top and  * * 
01622          * 
01623          * *  * *  * *  * * size.  Make sure we grow in reasonable-sized
01624          * chunks to * * prevent *  * *  * frequent reallocations of the db
01625          * array. 
01626          */
01627 
01628         /*
01629          * If requested size is smaller than the current db size, ignore it 
01630          */
01631 
01632         if(newtop <= mudstate.db_top) {
01633                 return;
01634         }
01635         /*
01636          * If requested size is greater than the current db size but smaller
01637          * * * * * * * than the amount of space we have allocated, raise the
01638          * db  * *  * size * * and * initialize the new area. 
01639          */
01640 
01641         if(newtop <= mudstate.db_size) {
01642                 for(i = mudstate.db_top; i < newtop; i++) {
01643                         if(mudconf.cache_names)
01644                                 purenames[i] = NULL;
01645                 }
01646                 initialize_objects(mudstate.db_top, newtop);
01647                 mudstate.db_top = newtop;
01648                 return;
01649         }
01650         /*
01651          * Grow by a minimum of delta objects 
01652          */
01653 
01654         if(newtop <= mudstate.db_size + delta) {
01655                 newsize = mudstate.db_size + delta;
01656         } else {
01657                 newsize = newtop;
01658         }
01659 
01660         /*
01661          * Enforce minimumdatabase size 
01662          */
01663 
01664         if(newsize < mudstate.min_size)
01665                 newsize = mudstate.min_size + delta;;
01666 
01667         /*
01668          * Grow the name tables 
01669          */
01670 
01671         if(mudconf.cache_names) {
01672                 newpurenames =
01673                         (NAME *) XMALLOC((newsize + SIZE_HACK) * sizeof(NAME),
01674                                                          "db_grow.purenames");
01675 
01676                 if(!newpurenames) {
01677                         LOG_SIMPLE(LOG_ALWAYS, "ALC", "DB",
01678                                            tprintf
01679                                            ("Could not allocate space for %d item name cache.",
01680                                                 newsize));
01681                         abort();
01682                 }
01683                 bzero((char *) newpurenames, (newsize + SIZE_HACK) * sizeof(NAME));
01684 
01685                 if(purenames) {
01686 
01687                         /*
01688                          * An old name cache exists.  Copy it. 
01689                          */
01690 
01691                         purenames -= SIZE_HACK;
01692                         bcopy((char *) purenames, (char *) newpurenames,
01693                                   (newtop + SIZE_HACK) * sizeof(NAME));
01694                         cp = (char *) purenames;
01695                         XFREE(cp, "db_grow.purename");
01696                 } else {
01697 
01698                         /*
01699                          * Creating a brand new struct database.  Fill in the
01700                          * 'reserved' area in case it gets referenced.  
01701                          */
01702 
01703                         purenames = newpurenames;
01704                         for(i = 0; i < SIZE_HACK; i++) {
01705                                 purenames[i] = NULL;
01706                         }
01707                 }
01708                 purenames = newpurenames + SIZE_HACK;
01709                 newpurenames = NULL;
01710         }
01711         /*
01712          * Grow the db array 
01713          */
01714 
01715         newdb = (OBJ *)
01716                 XMALLOC((newsize + SIZE_HACK) * sizeof(OBJ), "db_grow.db");
01717         if(!newdb) {
01718 
01719                 LOG_SIMPLE(LOG_ALWAYS, "ALC", "DB",
01720                                    tprintf
01721                                    ("Could not allocate space for %d item struct database.",
01722                                         newsize));
01723                 abort();
01724         }
01725         if(db) {
01726 
01727                 /*
01728                  * An old struct database exists.  Copy it to the new buffer 
01729                  */
01730 
01731                 db -= SIZE_HACK;
01732                 bcopy((char *) db, (char *) newdb,
01733                           (mudstate.db_top + SIZE_HACK) * sizeof(OBJ));
01734                 cp = (char *) db;
01735                 XFREE(cp, "db_grow.db");
01736         } else {
01737 
01738                 /*
01739                  * Creating a brand new struct database.  Fill in the * * * * 
01740                  * 
01741                  * *  * * 'reserved' area in case it gets referenced. 
01742                  */
01743 
01744                 db = newdb;
01745                 for(i = 0; i < SIZE_HACK; i++) {
01746                         s_Owner(i, GOD);
01747                         s_Flags(i, (TYPE_GARBAGE | GOING));
01748                         s_Powers(i, 0);
01749                         s_Powers2(i, 0);
01750                         s_Location(i, NOTHING);
01751                         s_Contents(i, NOTHING);
01752                         s_Exits(i, NOTHING);
01753                         s_Link(i, NOTHING);
01754                         s_Next(i, NOTHING);
01755                         s_Zone(i, NOTHING);
01756                         s_Parent(i, NOTHING);
01757                         s_Stack(i, NULL);
01758                         db[i].ahead = NULL;
01759                         db[i].at_count = 0;
01760                 }
01761         }
01762         db = newdb + SIZE_HACK;
01763         newdb = NULL;
01764 
01765         for(i = mudstate.db_top; i < newtop; i++) {
01766                 if(mudconf.cache_names) {
01767                         purenames[i] = NULL;
01768                 }
01769         }
01770         initialize_objects(mudstate.db_top, newtop);
01771         mudstate.db_top = newtop;
01772         mudstate.db_size = newsize;
01773 
01774         /*
01775          * Grow the db mark buffer 
01776          */
01777 
01778         marksize = (newsize + 7) >> 3;
01779         newmarkbuf = (MARKBUF *) XMALLOC(marksize, "db_grow");
01780         bzero((char *) newmarkbuf, marksize);
01781         if(mudstate.markbits) {
01782                 marksize = (newtop + 7) >> 3;
01783                 bcopy((char *) mudstate.markbits, (char *) newmarkbuf, marksize);
01784                 cp = (char *) mudstate.markbits;
01785                 XFREE(cp, "db_grow");
01786         }
01787         mudstate.markbits = newmarkbuf;
01788 }
01789 
01790 void db_free(void)
01791 {
01792         char *cp;
01793 
01794         if(db != NULL) {
01795                 db -= SIZE_HACK;
01796                 cp = (char *) db;
01797                 XFREE(cp, "db_grow");
01798                 db = NULL;
01799         }
01800         mudstate.db_top = 0;
01801         mudstate.db_size = 0;
01802         mudstate.freelist = NOTHING;
01803 }
01804 
01805 void db_make_minimal(void)
01806 {
01807         dbref obj;
01808 
01809         db_free();
01810         db_grow(1);
01811         s_Name(0, "Limbo");
01812         s_Flags(0, TYPE_ROOM);
01813         s_Powers(0, 0);
01814         s_Powers2(0, 0);
01815         s_Location(0, NOTHING);
01816         s_Exits(0, NOTHING);
01817         s_Link(0, NOTHING);
01818         s_Parent(0, NOTHING);
01819         s_Zone(0, NOTHING);
01820         s_Pennies(0, 1);
01821         s_Owner(0, 1);
01822         db[0].ahead = NULL;
01823         db[0].at_count = 0;
01824         /*
01825          * should be #1 
01826          */
01827         load_player_names();
01828         obj =
01829                 create_player((char *) "Wizard", (char *) "potrzebie", NOTHING, 0, 0);
01830         s_Flags(obj, Flags(obj) | WIZARD);
01831         s_Powers(obj, 0);
01832         s_Powers2(obj, 0);
01833         s_Pennies(obj, 1000);
01834 
01835         /*
01836          * Manually link to Limbo, just in case 
01837          */
01838         s_Location(obj, 0);
01839         s_Next(obj, NOTHING);
01840         s_Contents(0, obj);
01841         s_Link(obj, 0);
01842 }
01843 
01844 dbref parse_dbref(const char *s)
01845 {
01846         const char *p;
01847         int x;
01848 
01849         /*
01850          * Enforce completely numeric dbrefs 
01851          */
01852 
01853         for(p = s; *p; p++) {
01854                 if(!isdigit(*p))
01855                         return NOTHING;
01856         }
01857 
01858         x = atoi(s);
01859         return ((x >= 0) ? x : NOTHING);
01860 }
01861 
01862 void putref(FILE * f, dbref ref)
01863 {
01864         fprintf(f, "%d\n", ref);
01865 }
01866 
01867 void putstring(FILE * f, const char *s)
01868 {
01869         putc('"', f);
01870 
01871         while (s && *s) {
01872                 switch (*s) {
01873                 case '\\':
01874                 case '"':
01875                         putc('\\', f);
01876                 default:
01877                         putc(*s, f);
01878                 }
01879                 s++;
01880         }
01881         putc('"', f);
01882         putc('\n', f);
01883 }
01884 
01885 const char *getstring_noalloc(FILE * f, int new_strings)
01886 {
01887         static char buf[LBUF_SIZE];
01888         char *p;
01889         int c, lastc;
01890 
01891         p = buf;
01892         c = fgetc(f);
01893         if(!new_strings || (c != '"')) {
01894                 ungetc(c, f);
01895                 c = '\0';
01896                 for(;;) {
01897                         lastc = c;
01898                         c = fgetc(f);
01899 
01900                         /*
01901                          * If EOF or null, return 
01902                          */
01903 
01904                         if(!c || (c == EOF)) {
01905                                 *p = '\0';
01906                                 return buf;
01907                         }
01908                         /*
01909                          * If a newline, return if prior char is not a cr. *
01910                          * * * Otherwise * keep on truckin' 
01911                          */
01912 
01913                         if((c == '\n') && (lastc != '\r')) {
01914                                 *p = '\0';
01915                                 return buf;
01916                         }
01917                         safe_chr(c, buf, &p);
01918                 }
01919         } else {
01920                 for(;;) {
01921                         c = fgetc(f);
01922                         if(c == '"') {
01923                                 if((c = fgetc(f)) != '\n')
01924                                         ungetc(c, f);
01925                                 *p = '\0';
01926                                 return buf;
01927                         } else if(c == '\\') {
01928                                 c = fgetc(f);
01929                         }
01930                         if((c == '\0') || (c == EOF)) {
01931                                 *p = '\0';
01932                                 return buf;
01933                         }
01934                         safe_chr(c, buf, &p);
01935                 }
01936         }
01937 }
01938 
01939 dbref getref(FILE * f)
01940 {
01941         static char buf[SBUF_SIZE];
01942 
01943         fgets(buf, sizeof(buf), f);
01944         return (atoi(buf));
01945 }
01946 
01947 void free_boolexp(BOOLEXP * b)
01948 {
01949         if(b == TRUE_BOOLEXP)
01950                 return;
01951 
01952         switch (b->type) {
01953         case BOOLEXP_AND:
01954         case BOOLEXP_OR:
01955                 free_boolexp(b->sub1);
01956                 free_boolexp(b->sub2);
01957                 free_bool(b);
01958                 break;
01959         case BOOLEXP_NOT:
01960         case BOOLEXP_CARRY:
01961         case BOOLEXP_IS:
01962         case BOOLEXP_OWNER:
01963         case BOOLEXP_INDIR:
01964                 free_boolexp(b->sub1);
01965                 free_bool(b);
01966                 break;
01967         case BOOLEXP_CONST:
01968                 free_bool(b);
01969                 break;
01970         case BOOLEXP_ATR:
01971         case BOOLEXP_EVAL:
01972                 free((char *) b->sub1);
01973                 free_bool(b);
01974                 break;
01975         }
01976 }
01977 
01978 BOOLEXP *dup_bool(BOOLEXP * b)
01979 {
01980         BOOLEXP *r;
01981 
01982         if(b == TRUE_BOOLEXP)
01983                 return (TRUE_BOOLEXP);
01984 
01985         r = alloc_bool("dup_bool");
01986         switch (r->type = b->type) {
01987         case BOOLEXP_AND:
01988         case BOOLEXP_OR:
01989                 r->sub2 = dup_bool(b->sub2);
01990         case BOOLEXP_NOT:
01991         case BOOLEXP_CARRY:
01992         case BOOLEXP_IS:
01993         case BOOLEXP_OWNER:
01994         case BOOLEXP_INDIR:
01995                 r->sub1 = dup_bool(b->sub1);
01996         case BOOLEXP_CONST:
01997                 r->thing = b->thing;
01998                 break;
01999         case BOOLEXP_EVAL:
02000         case BOOLEXP_ATR:
02001                 r->thing = b->thing;
02002                 r->sub1 = (BOOLEXP *) strsave((char *) b->sub1);
02003                 break;
02004         default:
02005                 fprintf(stderr, "bad bool type!!\n");
02006                 return (TRUE_BOOLEXP);
02007         }
02008         return (r);
02009 }
02010 
02011 void clone_object(dbref a, dbref b)
02012 {
02013         bcopy((char *) &db[b], (char *) &db[a], sizeof(struct object));
02014 }
02015 
02016 /*
02017  * check_zone - checks back through a zone tree for control 
02018  */
02019 int check_zone(dbref player, dbref thing)
02020 {
02021         mudstate.zone_nest_num++;
02022 
02023         if(!mudconf.have_zones || (Zone(thing) == NOTHING) ||
02024            (mudstate.zone_nest_num == mudconf.zone_nest_lim) ||
02025            (isPlayer(thing))) {
02026                 mudstate.zone_nest_num = 0;
02027                 return 0;
02028         }
02029 
02030         /*
02031          * If the zone doesn't have an enterlock, DON'T allow control. 
02032          */
02033 
02034         if(atr_get_raw(Zone(thing), A_LENTER) &&
02035            could_doit(player, Zone(thing), A_LENTER)) {
02036                 mudstate.zone_nest_num = 0;
02037                 return 1;
02038         } else {
02039                 return check_zone(player, Zone(thing));
02040         }
02041 
02042 }
02043 
02044 int check_zone_for_player(dbref player, dbref thing)
02045 {
02046         mudstate.zone_nest_num++;
02047 
02048         if(!mudconf.have_zones || (Zone(thing) == NOTHING) ||
02049            (mudstate.zone_nest_num == mudconf.zone_nest_lim) ||
02050            !(isPlayer(thing))) {
02051                 mudstate.zone_nest_num = 0;
02052                 return 0;
02053         }
02054 
02055         if(atr_get_raw(Zone(thing), A_LENTER) &&
02056            could_doit(player, Zone(thing), A_LENTER)) {
02057                 mudstate.zone_nest_num = 0;
02058                 return 1;
02059         } else {
02060                 return check_zone(player, Zone(thing));
02061         }
02062 
02063 }
02064 
02065 void toast_player(dbref player)
02066 {
02067         do_clearcom(player, player, 0);
02068         do_channelnuke(player);
02069         del_commac(player);
02070         do_clear_macro(player, NULL);
02071 }
02072 
02073 /*
02074  * ---------------------------------------------------------------------------
02075  * * dump_restart_db: Writes out socket information.
02076  */
02077 
02078 
02079 void dump_restart_db(void)
02080 {
02081         FILE *f;
02082         DESC *d;
02083     OBJQE *obq;
02084         int version = 0;
02085 
02086         /* We maintain a version number for the restart database,
02087            so we can restart even if the format of the restart db
02088            has been changed in the new executable. */
02089 
02090         version |= RS_RECORD_PLAYERS;
02091         version |= RS_NEW_STRINGS;
02092         version |= RS_HUDKEY;
02093 
02094         f = fopen("restart.db", "w");
02095         fprintf(f, "+V%d\n", version);
02096         putref(f, mudstate.start_time);
02097         putstring(f, mudstate.doing_hdr);
02098         putref(f, mudstate.record_players);
02099         for (d = descriptor_list ; d && d->next ; d = d->next);
02100         for(; d != NULL ; d = d->prev) {
02101                 dprintk("d: %p dnext: %p dprev: %p", d, d->next, d->prev);
02102                 putref(f, d->descriptor);
02103                 putref(f, d->flags);
02104                 putref(f, d->connected_at);
02105                 putref(f, d->command_count);
02106                 putref(f, d->timeout);
02107                 putref(f, d->host_info);
02108                 putref(f, d->player);
02109                 putref(f, d->last_time);
02110                 putstring(f, d->output_prefix);
02111                 putstring(f, d->output_suffix);
02112                 putstring(f, d->addr);
02113                 putstring(f, d->doing);
02114                 putstring(f, d->username);
02115                 putstring(f, d->hudkey);
02116         }
02117         putref(f, 0);
02118         fclose(f);
02119 }
02120 
02121 #define RESTART_MAGIC 0x0001D1ED
02122 void dump_restart_db_xdr(void)
02123 {
02124         struct mmdb_t *mmdb;
02125     DESC *d;
02126         int version = 0;
02127 
02128         /* We maintain a version number for the restart database,
02129            so we can restart even if the format of the restart db
02130            has been changed in the new executable. */
02131 
02132         version |= RS_RECORD_PLAYERS;
02133         version |= RS_NEW_STRINGS;
02134         version |= RS_HUDKEY;
02135 
02136    
02137     mmdb = mmdb_open_write("restart.xdr");
02138     mmdb_write_uint32(mmdb, RESTART_MAGIC);
02139     mmdb_write_uint32(mmdb, 1);
02140     mmdb_write_uint32(mmdb, version);
02141     mmdb_write_uint32(mmdb, mudstate.start_time);
02142    mmdb_write_string(mmdb, mudstate.doing_hdr);
02143         mmdb_write_uint32(mmdb, mudstate.record_players);
02144             for (d = descriptor_list; d && d->next; d = d->next) ;
02145             
02146         for (; d != NULL; d = d->prev) {
02147                 dprintk("XDR!! d: %p dnext: %p dprev: %p", d, d->next, d->prev);
02148                 mmdb_write_uint32(mmdb, d->descriptor);
02149                 mmdb_write_uint32(mmdb, d->flags);
02150                 mmdb_write_uint32(mmdb, d->connected_at);
02151                 mmdb_write_uint32(mmdb, d->command_count);
02152                 mmdb_write_uint32(mmdb, d->timeout);
02153                 mmdb_write_uint32(mmdb, d->host_info);
02154                 mmdb_write_uint32(mmdb, d->player);
02155                 mmdb_write_uint32(mmdb, d->last_time);
02156                 mmdb_write_string(mmdb, d->output_prefix);
02157                 mmdb_write_string(mmdb, d->output_suffix);
02158                 mmdb_write_string(mmdb, d->addr);
02159                 mmdb_write_string(mmdb, d->doing);
02160                 mmdb_write_string(mmdb, d->username);
02161                 mmdb_write_string(mmdb, d->hudkey);
02162         }
02163     mmdb_write_uint32(mmdb, 0);
02164     cque_dump_restart(mmdb); 
02165     mmdb_close(mmdb);
02166 }
02167 
02168 void accept_client_input(int fd, short event, void *arg);
02169 
02170 void bsd_write_callback(struct bufferevent *bufev, void *arg);
02171 void bsd_read_callback(struct bufferevent *bufev, void *arg);
02172 void bsd_error_callback(struct bufferevent *bufev, short whut, void *arg);
02173 
02174 void load_restart_db()
02175 {
02176         FILE *f;
02177         DESC *d;
02178         DESC *p;
02179     struct stat statbuffer;
02180 
02181         int val, version, new_strings = 0;
02182         char *temp, buf[8];
02183 
02184         f = fopen("restart.db", "r");
02185         if(!f) {
02186                 mudstate.restarting = 0;
02187                 return;
02188         }
02189         mudstate.restarting = 1;
02190 
02191         fgets(buf, 3, f);
02192         if(strncmp(buf, "+V", 2)) {
02193                 abort();
02194         }
02195         version = getref(f);
02196 
02197         if(version & RS_NEW_STRINGS)
02198                 new_strings = 1;
02199 
02200         mudstate.start_time = getref(f);
02201         time(&mudstate.restart_time);
02202         strcpy(mudstate.doing_hdr, getstring_noalloc(f, new_strings));
02203 
02204         if(version & RS_RECORD_PLAYERS) {
02205                 mudstate.record_players = getref(f);
02206         }
02207 
02208         while ((val = getref(f)) != 0) {
02209                 d = malloc(sizeof(DESC));
02210                 memset(d, 0, sizeof(DESC));
02211                 d->descriptor = val;
02212                 d->flags = getref(f);
02213                 d->connected_at = getref(f);
02214                 d->command_count = getref(f);
02215                 d->timeout = getref(f);
02216                 d->host_info = getref(f);
02217                 d->player = getref(f);
02218                 d->last_time = getref(f);
02219                 temp = (char *) getstring_noalloc(f, new_strings);
02220                 if(*temp) {
02221                         d->output_prefix = alloc_lbuf("set_userstring");
02222                         strcpy(d->output_prefix, temp);
02223                 } else {
02224                         d->output_prefix = NULL;
02225                 }
02226                 temp = (char *) getstring_noalloc(f, new_strings);
02227                 if(*temp) {
02228                         d->output_suffix = alloc_lbuf("set_userstring");
02229                         strcpy(d->output_suffix, temp);
02230                 } else {
02231                         d->output_suffix = NULL;
02232                 }
02233 
02234                 strcpy(d->addr, getstring_noalloc(f, new_strings));
02235                 strcpy(d->doing, getstring_noalloc(f, new_strings));
02236                 strcpy(d->username, getstring_noalloc(f, new_strings));
02237 
02238                 if(version & RS_HUDKEY)
02239                         strncpy(d->hudkey, getstring_noalloc(f, new_strings), HUDKEYLEN);
02240                 else
02241                         d->hudkey[0] = '\0';
02242 
02243                 d->output_size = 0;
02244                 d->output_tot = 0;
02245                 d->output_lost = 0;
02246                 d->input_size = 0;
02247                 d->input_tot = 0;
02248                 d->input_lost = 0;
02249                 memset(d->input, 0, sizeof(d->input));
02250         d->input_tail = 0;
02251                 d->quota = mudconf.cmd_quota_max;
02252                 d->program_data = NULL;
02253                 d->hashnext = NULL;
02254         d->refcount = 1;
02255 
02256                 d->saddr_len = sizeof(d->saddr);
02257                 getpeername(d->descriptor, (struct sockaddr *) &d->saddr,
02258                                         (socklen_t *) & d->saddr_len);
02259                 d->outstanding_dnschild_query = dnschild_request(d);
02260         
02261 
02262 
02263          if (descriptor_list)
02264                  descriptor_list->prev = d;
02265          d->next = descriptor_list;
02266          d->prev = NULL;
02267          descriptor_list = d;
02268                    
02269         d->sock_buff = bufferevent_new(d->descriptor, bsd_write_callback,
02270                                                                            bsd_read_callback, bsd_error_callback,
02271                                                                            NULL);
02272 
02273                 bufferevent_disable(d->sock_buff, EV_READ);
02274                 bufferevent_enable(d->sock_buff, EV_WRITE);
02275 
02276                 event_set(&d->sock_ev, d->descriptor, EV_READ | EV_PERSIST,
02277                                   accept_client_input, d);
02278                 event_add(&d->sock_ev, NULL);
02279 
02280                 desc_addhash(d);
02281                 if(isPlayer(d->player))
02282                         s_Flags2(d->player, Flags2(d->player) | CONNECTED);
02283         }
02284 
02285     DESC_ITER_CONN(d) {
02286         if(!isPlayer(d->player) || fstat(d->descriptor, &statbuffer) < 0) {
02287             dprintk("dropping descriptor %d.\n", d->descriptor);
02288             shutdownsock(d, R_QUIT);
02289         }
02290 
02291     }
02292 
02293         fclose(f);
02294         remove("restart.db");
02295         raw_broadcast(0, "Game: Restart finished.");
02296 }
02297 
02298 int load_restart_db_xdr()
02299 {
02300         struct mmdb_t *mmdb;
02301     DESC *d;
02302         DESC *p;
02303     struct stat statbuffer;
02304 
02305         int val, version, new_strings = 0;
02306         char *temp, buf[8];
02307 
02308         mmdb = mmdb_open_read("restart.xdr");
02309     if(!mmdb) return 0;
02310 
02311     val = mmdb_read_uint32(mmdb); // RESTART_MAGIC
02312     if(val != RESTART_MAGIC) {
02313         printk("restart database had invalid magic.");
02314         printk("read %08x expected %08x.", val, RESTART_MAGIC);
02315         return 0;
02316     }
02317     mmdb_read_uint32(mmdb); // VERSION
02318     mmdb_read_uint32(mmdb); // VERSION
02319     mudstate.start_time = mmdb_read_uint32(mmdb);
02320     mmdb_read_opaque(mmdb, mudstate.doing_hdr, sizeof(mudstate.doing_hdr));
02321     mudstate.record_players = mmdb_read_uint32(mmdb);
02322 
02323         mudstate.restarting = 1;
02324 
02325     while( (val = mmdb_read_uint32(mmdb)) != 0) {
02326         dprintk("loading descriptor %d\n", val);
02327                 d = malloc(sizeof(DESC));
02328                 memset(d, 0, sizeof(DESC));
02329                 d->descriptor = val;
02330                 d->flags = mmdb_read_uint32(mmdb);
02331                 d->connected_at = mmdb_read_uint32(mmdb);
02332                 d->command_count = mmdb_read_uint32(mmdb);
02333                 d->timeout = mmdb_read_uint32(mmdb);
02334                 d->host_info = mmdb_read_uint32(mmdb);
02335                 d->player = mmdb_read_uint32(mmdb);
02336                 d->last_time = mmdb_read_uint32(mmdb);
02337         
02338         d->output_prefix = mmdb_read_string(mmdb);
02339         d->output_suffix = mmdb_read_string(mmdb);
02340         mmdb_read_opaque(mmdb, d->addr, sizeof(d->addr));
02341         mmdb_read_opaque(mmdb, d->doing, sizeof(d->doing));
02342         mmdb_read_opaque(mmdb, d->username, sizeof(d->username));
02343         mmdb_read_opaque(mmdb, d->hudkey, sizeof(d->hudkey));
02344 
02345                 d->output_size = 0;
02346                 d->output_tot = 0;
02347                 d->output_lost = 0;
02348                 d->input_size = 0;
02349                 d->input_tot = 0;
02350                 d->input_lost = 0;
02351                 memset(d->input, 0, sizeof(d->input));
02352         d->input_tail = 0;
02353                 d->quota = mudconf.cmd_quota_max;
02354                 d->program_data = NULL;
02355                 d->hashnext = NULL;
02356         d->refcount = 1;
02357 
02358                 d->saddr_len = sizeof(d->saddr);
02359                 getpeername(d->descriptor, (struct sockaddr *) &d->saddr,
02360                                         (socklen_t *) & d->saddr_len);
02361                 d->outstanding_dnschild_query = dnschild_request(d);
02362 
02363 
02364 
02365 
02366          if (descriptor_list)
02367                  descriptor_list->prev = d;
02368          d->next = descriptor_list;
02369          d->prev = NULL;
02370          descriptor_list = d;
02371                            
02372         d->sock_buff = bufferevent_new(d->descriptor, bsd_write_callback,
02373                                                                            bsd_read_callback, bsd_error_callback,
02374                                                                            NULL);
02375                 bufferevent_disable(d->sock_buff, EV_READ);
02376                 bufferevent_enable(d->sock_buff, EV_WRITE);
02377 
02378                 event_set(&d->sock_ev, d->descriptor, EV_READ | EV_PERSIST,
02379                                   accept_client_input, d);
02380                 event_add(&d->sock_ev, NULL);
02381 
02382                 desc_addhash(d);
02383                 if(isPlayer(d->player))
02384                         s_Flags2(d->player, Flags2(d->player) | CONNECTED);
02385         }
02386 
02387         DESC_ITER_CONN(d) {
02388                 if(!isPlayer(d->player) || fstat(d->descriptor, &statbuffer) < 0) {
02389             dprintk("dropping descriptor %d.\n", d->descriptor);
02390                         shutdownsock(d, R_QUIT);
02391                 }
02392 
02393         }
02394     cque_load_restart(mmdb);
02395     mmdb_close(mmdb);
02396     remove("restart.xdr");
02397     remove("restart.db");
02398         raw_broadcast(0, "Game: Restart finished.");
02399     return 1;
02400 }

Generated on Mon May 28 04:25:19 2007 for BattletechMUX by  doxygen 1.4.7