src/game.c

Go to the documentation of this file.
00001 /*
00002  * game.c 
00003  */
00004 
00005 #include "copyright.h"
00006 #include "config.h"
00007 
00008 #include <sys/stat.h>
00009 #include <signal.h>
00010 #include <event.h>
00011 #include <regex.h>
00012 
00013 #include "mudconf.h"
00014 #include "config.h"
00015 #include "file_c.h"
00016 #include "db.h"
00017 #include "interface.h"
00018 #include "match.h"
00019 #include "externs.h"
00020 #include "flags.h"
00021 #include "powers.h"
00022 #include "attrs.h"
00023 #include "alloc.h"
00024 #include "vattr.h"
00025 #include "commac.h"
00026 #ifdef SQL_SUPPORT
00027 #include "sqlchild.h"
00028 #endif
00029 
00030 #ifndef NEXT
00031 #endif
00032 
00033 #ifdef HAVE_IEEEFP_H
00034 #include <ieeefp.h>
00035 #endif
00036 #ifdef HAVE_SYS_UCONTEXT_H
00037 #include <sys/ucontext.h>
00038 #endif
00039 
00040 #define NSUBEXP 10
00041 
00042 extern void init_attrtab(void);
00043 extern void init_cmdtab(void);
00044 extern void init_mactab(void);
00045 extern void init_chantab(void);
00046 extern void cf_init(void);
00047 extern void pcache_init(void);
00048 extern int cf_read(char *fn);
00049 extern void init_functab(void);
00050 extern void close_sockets(int emergency, char *message);
00051 extern void init_version(void);
00052 extern void init_logout_cmdtab(void);
00053 extern void init_timer(void);
00054 extern void raw_notify(dbref, const char *);
00055 extern void do_second(void);
00056 extern void do_dbck(dbref, dbref, int);
00057 
00058 #ifdef ARBITRARY_LOGFILES
00059 void logcache_init();
00060 void logcache_destruct();
00061 #endif
00062 
00063 #ifdef HUDINFO_SUPPORT
00064 extern void init_hudinfo(void);
00065 #endif
00066 
00067 void fork_and_dump(int);
00068 void dump_database(void);
00069 void do_dump_optimize(dbref, dbref, int);
00070 void pcache_sync(void);
00071 void dump_database_internal(int);
00072 static void init_rlimit(void);
00073 
00074 int reserved;
00075 
00076 extern int corrupt;
00077 
00078 /*
00079  * used to allocate storage for temporary stuff, cleared before command
00080  * execution
00081  */
00082 
00083 void do_dump(dbref player, dbref cause, int key)
00084 {
00085         notify(player, "Dumping...");
00086 
00087         /*
00088          * DUMP_OPTIMIZE takes advantage of a feature of GDBM to compress  
00089          * unused space in the database, and will not be very useful
00090          * except sparingly, perhaps done every month or so. 
00091          */
00092 
00093         if(key & DUMP_OPTIMIZE)
00094                 do_dump_optimize(player, cause, key);
00095         else
00096                 fork_and_dump(key);
00097 }
00098 
00099 void do_dump_optimize(dbref player, dbref cause, int key)
00100 {
00101         raw_notify(player, "Database is memory based.");
00102 }
00103 
00107 void report(void)
00108 {
00109         STARTLOG(LOG_BUGS, "BUG", "INFO") {
00110                 log_text((char *) "Command: '");
00111                 log_text(mudstate.debug_cmd);
00112                 log_text((char *) "'");
00113                 ENDLOG;
00114         } if(Good_obj(mudstate.curr_player)) {
00115                 STARTLOG(LOG_BUGS, "BUG", "INFO") {
00116                         log_text((char *) "Player: ");
00117                         log_name_and_loc(mudstate.curr_player);
00118                         if((mudstate.curr_enactor != mudstate.curr_player) &&
00119                            Good_obj(mudstate.curr_enactor)) {
00120                                 log_text((char *) " Enactor: ");
00121                                 log_name_and_loc(mudstate.curr_enactor);
00122                         }
00123                         ENDLOG;
00124         }}
00125 }
00126 
00127 /*
00128  * Load a regular expression match and insert it into
00129  * registers.
00130  */
00131 int regexp_match(char *pattern, char *str, char *args[], int nargs)
00132 {
00133         regex_t re;
00134         int got_match;
00135         regmatch_t pmatch[NSUBEXP];
00136         int i, len;
00137 
00138         /*
00139          * Load the regexp pattern. This allocates memory which must be
00140          * later freed. A free() of the regexp does free all structures
00141          * under it.
00142          */
00143 
00144         if(regcomp(&re, pattern, REG_EXTENDED) != 0) {
00145                 /*
00146                  * This is a matching error. We have an error message in
00147                  * regexp_errbuf that we can ignore, since we're doing
00148                  * command-matching.
00149                  */
00150                 return 0;
00151         }
00152 
00153         /* 
00154          * Now we try to match the pattern. The relevant fields will
00155          * automatically be filled in by this.
00156          */
00157         got_match = (regexec(&re, str, NSUBEXP, pmatch, 0) == 0);
00158         if(!got_match) {
00159                 regfree(&re);
00160                 return 0;
00161         }
00162 
00163         /*
00164          * Now we fill in our args vector. Note that in regexp matching,
00165          * 0 is the entire string matched, and the parenthesized strings
00166          * go from 1 to 9. We DO PRESERVE THIS PARADIGM, for consistency
00167          * with other languages.
00168          */
00169 
00170         for(i = 0; i < nargs; i++) {
00171                 args[i] = NULL;
00172         }
00173 
00174         /* Convenient: nargs and NSUBEXP are the same.
00175          * We are also guaranteed that our buffer is going to be LBUF_SIZE
00176          * so we can copy without fear.
00177          */
00178 
00179         for(i = 0; (i < NSUBEXP) && (pmatch[i].rm_so != -1) && (pmatch[i].rm_eo != -1); i++) {
00180                 len = pmatch[i].rm_eo - pmatch[i].rm_so;
00181                 args[i] = alloc_lbuf("regexp_match");
00182         memset(args[i], 0, LBUF_SIZE);
00183                 strncpy(args[i], str + pmatch[i].rm_so, len);
00184                 args[i][len] = '\0';    /* strncpy() does not null-terminate */
00185         }
00186 
00187         regfree(&re);
00188         return 1;
00189 }
00190 
00194 static int atr_match1(dbref thing, dbref parent, dbref player, char type,
00195                                           char *str, int check_exclude, int hash_insert)
00196 {
00197         dbref aowner;
00198         int match, attr, aflags, i;
00199         char buff[LBUF_SIZE], *s, *as;
00200         char *args[10];
00201         ATTR *ap;
00202 
00203     memset(args, 0, sizeof(args));
00204     
00205         /*
00206          * See if we can do it.  Silently fail if we can't. 
00207          */
00208 
00209         if(!could_doit(player, parent, A_LUSE))
00210                 return -1;
00211 
00212         match = 0;
00213         for(attr = atr_head(parent, &as); attr; attr = atr_next(&as)) {
00214                 ap = atr_num(attr);
00215 
00216                 /*
00217                  * Never check NOPROG attributes. 
00218                  */
00219 
00220                 if(!ap || (ap->flags & AF_NOPROG))
00221                         continue;
00222 
00223                 /*
00224                  * If we aren't the bottom level check if we saw this attr *
00225                  * * * * before.  Also exclude it if the attribute type is *
00226                  * * PRIVATE. 
00227                  */
00228 
00229                 if(check_exclude && ((ap->flags & AF_PRIVATE) ||
00230                                                          nhashfind(ap->number, &mudstate.parent_htab))) {
00231                         continue;
00232                 }
00233                 atr_get_str(buff, parent, attr, &aowner, &aflags);
00234 
00235                 /*
00236                  * Skip if private and on a parent 
00237                  */
00238 
00239                 if(check_exclude && (aflags & AF_PRIVATE)) {
00240                         continue;
00241                 }
00242                 /*
00243                  * If we aren't the top level remember this attr so we * * *
00244                  * exclude * it from now on. 
00245                  */
00246 
00247                 if(hash_insert)
00248                         nhashadd(ap->number, (int *) &attr, &mudstate.parent_htab);
00249 
00250                 /*
00251                  * Check for the leadin character after excluding the attrib
00252                  * * * * * This lets non-command attribs on the child block * 
00253                  * *  * commands * on the parent. 
00254                  */
00255 
00256                 if((buff[0] != type) || (aflags & AF_NOPROG))
00257                         continue;
00258 
00259                 /*
00260                  * decode it: search for first un escaped : 
00261                  */
00262 
00263                 for(s = buff + 1; *s && (*s != ':'); s++);
00264                 if(!*s)
00265                         continue;
00266                 *s++ = 0;
00267                 if(((aflags & AF_REGEXP) && regexp_match(buff + 1, str, args, 10))
00268                    || wild(buff + 1, str, args, 10)) {
00269                         match = 1;
00270                         wait_que(thing, player, 0, NOTHING, 0, s, args, 10,
00271                                          mudstate.global_regs);
00272                         for(i = 0; i < 10; i++) {
00273                                 if(args[i])
00274                                         free_lbuf(args[i]);
00275                         }
00276                 }
00277         }
00278         return (match);
00279 }
00280 
00281 int atr_match(dbref thing, dbref player, char type, char *str,
00282                           int check_parents)
00283 {
00284         int match, lev, result, exclude, insert;
00285         dbref parent;
00286 
00287         /*
00288          * If thing is halted, don't check anything 
00289          */
00290 
00291         if(Halted(thing))
00292                 return 0;
00293 
00294         /*
00295          * If not checking parents, just check the thing 
00296          */
00297 
00298         match = 0;
00299         if(!check_parents)
00300                 return atr_match1(thing, thing, player, type, str, 0, 0);
00301 
00302         /*
00303          * Check parents, ignoring halted objects 
00304          */
00305 
00306         exclude = 0;
00307         insert = 1;
00308         nhashflush(&mudstate.parent_htab, 0);
00309         ITER_PARENTS(thing, parent, lev) {
00310                 if(!Good_obj(Parent(parent)))
00311                         insert = 0;
00312                 result =
00313                         atr_match1(thing, parent, player, type, str, exclude, insert);
00314                 if(result > 0) {
00315                         match = 1;
00316                 } else if(result < 0) {
00317                         return match;
00318                 }
00319                 exclude = 1;
00320         }
00321 
00322         return match;
00323 }
00324 
00329 int check_filter(dbref object, dbref player, int filter, const char *msg)
00330 {
00331         int aflags;
00332         dbref aowner;
00333         char *buf, *nbuf, *cp, *dp, *str;
00334 
00335         buf = atr_pget(object, filter, &aowner, &aflags);
00336         if(!*buf) {
00337                 free_lbuf(buf);
00338                 return (1);
00339         }
00340         nbuf = dp = alloc_lbuf("check_filter");
00341         str = buf;
00342         exec(nbuf, &dp, 0, object, player, EV_FIGNORE | EV_EVAL | EV_TOP, &str,
00343                  (char **) NULL, 0);
00344         *dp = '\0';
00345         dp = nbuf;
00346         free_lbuf(buf);
00347         do {
00348                 cp = parse_to(&dp, ',', EV_STRIP);
00349                 if(quick_wild(cp, (char *) msg)) {
00350                         free_lbuf(nbuf);
00351                         return (0);
00352                 }
00353         } while (dp != NULL);
00354         free_lbuf(nbuf);
00355         return (1);
00356 }
00357 
00358 static char *add_prefix(dbref object, dbref player, int prefix,
00359                                                 const char *msg, const char *dflt)
00360 {
00361         int aflags;
00362         dbref aowner;
00363         char *buf, *nbuf, *cp, *bp, *str;
00364 
00365         buf = atr_pget(object, prefix, &aowner, &aflags);
00366         if(!*buf) {
00367                 cp = buf;
00368                 safe_str((char *) dflt, buf, &cp);
00369         } else {
00370                 nbuf = bp = alloc_lbuf("add_prefix");
00371                 str = buf;
00372                 exec(nbuf, &bp, 0, object, player, EV_FIGNORE | EV_EVAL | EV_TOP,
00373                          &str, (char **) NULL, 0);
00374                 *bp = '\0';
00375                 free_lbuf(buf);
00376                 buf = nbuf;
00377                 cp = &buf[strlen(buf)];
00378         }
00379         if(cp != buf)
00380                 safe_str((char *) " ", buf, &cp);
00381         safe_str((char *) msg, buf, &cp);
00382         *cp = '\0';
00383         return (buf);
00384 }
00385 
00386 static char *dflt_from_msg(dbref sender, dbref sendloc)
00387 {
00388         char *tp, *tbuff;
00389 
00390         tp = tbuff = alloc_lbuf("notify_checked.fwdlist");
00391         safe_str((char *) "From ", tbuff, &tp);
00392         if(Good_obj(sendloc))
00393                 safe_str(Name(sendloc), tbuff, &tp);
00394         else
00395                 safe_str(Name(sender), tbuff, &tp);
00396         safe_chr(',', tbuff, &tp);
00397         *tp = '\0';
00398         return tbuff;
00399 }
00400 
00401 char *colorize(dbref player, char *from);
00402 
00403 void notify_checked(dbref target, dbref sender, const char *msg, int key)
00404 {
00405         char *msg_ns, *mp, *tbuff, *tp, *buff, *colbuf = NULL;
00406         char *args[10];
00407         dbref aowner, targetloc, recip, obj;
00408         int i, nargs, aflags, has_neighbors, pass_listen;
00409         int check_listens, pass_uselock, is_audible;
00410         FWDLIST *fp;
00411 
00412         /*
00413          * If speaker is invalid or message is empty, just exit 
00414          */
00415 
00416         if(!Good_obj(target) || !msg || !*msg)
00417                 return;
00418 
00419         /*
00420          * Enforce a recursion limit 
00421          */
00422 
00423         mudstate.ntfy_nest_lev++;
00424         if(mudstate.ntfy_nest_lev >= mudconf.ntfy_nest_lim) {
00425                 mudstate.ntfy_nest_lev--;
00426                 return;
00427         }
00428         /*
00429          * If we want NOSPOOF output, generate it.  It is only needed if 
00430          * we are sending the message to the target object 
00431          */
00432 
00433         if(key & MSG_ME) {
00434                 mp = msg_ns = alloc_lbuf("notify_checked");
00435                 if(Nospoof(target) && (target != sender) &&
00436                    (target != mudstate.curr_enactor) &&
00437                    (target != mudstate.curr_player && Good_obj(sender))) {
00438 
00439                         /*
00440                          * I'd really like to use tprintf here but I can't 
00441                          * because the caller may have.
00442                          * notify(target, tprintf(...)) is quite common 
00443                          * in the code. 
00444                          */
00445 
00446                         tbuff = alloc_sbuf("notify_checked.nospoof");
00447                         safe_chr('[', msg_ns, &mp);
00448                         safe_str(Name(sender), msg_ns, &mp);
00449                         sprintf(tbuff, "(#%d)", sender);
00450                         safe_str(tbuff, msg_ns, &mp);
00451 
00452                         if(sender != Owner(sender)) {
00453                                 safe_chr('{', msg_ns, &mp);
00454                                 safe_str(Name(Owner(sender)), msg_ns, &mp);
00455                                 safe_chr('}', msg_ns, &mp);
00456                         }
00457                         if(sender != mudstate.curr_enactor) {
00458                                 sprintf(tbuff, "<-(#%d)", mudstate.curr_enactor);
00459                                 safe_str(tbuff, msg_ns, &mp);
00460                         }
00461                         safe_str((char *) "] ", msg_ns, &mp);
00462                         free_sbuf(tbuff);
00463                 }
00464                 safe_str((char *) msg, msg_ns, &mp);
00465                 *mp = '\0';
00466         } else {
00467                 msg_ns = NULL;
00468         }
00469 
00470         /*
00471          * msg contains the raw message, msg_ns contains the NOSPOOFed msg 
00472          */
00473 
00474         check_listens = Halted(target) ? 0 : 1;
00475         switch (Typeof(target)) {
00476         case TYPE_PLAYER:
00477                 if(key & MSG_ME) {
00478                         if(key & MSG_COLORIZE)
00479                                 colbuf = colorize(target, msg_ns);
00480                         raw_notify(target, colbuf ? colbuf : msg_ns);
00481 
00482 
00483                 }
00484 
00485                 if(colbuf)
00486                         free_lbuf(colbuf);
00487                 if(!mudconf.player_listen)
00488                         check_listens = 0;
00489         case TYPE_THING:
00490         case TYPE_ROOM:
00491 
00492                 /* If we're in a pipe, objects can receive raw_notify
00493                  * if they're not a player and connected (if we didn't
00494                  * do this, they'd be notified twice! */
00495 
00496                 if(mudstate.inpipe && (!isPlayer(target) || (isPlayer(target) &&
00497                                                                                                          !Connected(target)))) {
00498                         raw_notify(target, msg_ns);
00499                 }
00500 
00501                 /*
00502                  * Forward puppet message if it is for me 
00503                  */
00504 
00505                 has_neighbors = Has_location(target);
00506                 targetloc = where_is(target);
00507                 is_audible = Audible(target);
00508 
00509                 if((key & MSG_ME) && Puppet(target) && (target != Owner(target))
00510                    && ((key & MSG_PUP_ALWAYS) ||
00511                            ((targetloc != Location(Owner(target))) &&
00512                                 (targetloc != Owner(target))))) {
00513                         tp = tbuff = alloc_lbuf("notify_checked.puppet");
00514                         safe_str(Name(target), tbuff, &tp);
00515                         safe_str((char *) "> ", tbuff, &tp);
00516                         if(key & MSG_COLORIZE)
00517                                 colbuf = colorize(Owner(target), msg_ns);
00518                         safe_str(colbuf ? colbuf : msg_ns, tbuff, &tp);
00519                         *tp = '\0';
00520                         raw_notify(Owner(target), tbuff);
00521                         if(colbuf)
00522                                 free_lbuf(colbuf);
00523                         free_lbuf(tbuff);
00524                 }
00525                 /*
00526                  * Check for @Listen match if it will be useful 
00527                  */
00528 
00529                 pass_listen = 0;
00530                 nargs = 0;
00531                 if(check_listens && (key & (MSG_ME | MSG_INV_L)) && H_Listen(target)) {
00532                         tp = atr_get(target, A_LISTEN, &aowner, &aflags);
00533                         if(*tp && wild(tp, (char *) msg, args, 10)) {
00534                                 for(nargs = 10;
00535                                         nargs && (!args[nargs - 1] || !(*args[nargs - 1]));
00536                                         nargs--);
00537                                 pass_listen = 1;
00538                         }
00539                         free_lbuf(tp);
00540                 }
00541                 /*
00542                  * If we matched the @listen or are monitoring, check the * * 
00543                  * USE lock 
00544                  */
00545 
00546                 if(sender < 0)
00547                         sender = GOD;
00548                 pass_uselock = 0;
00549                 if((key & MSG_ME) && check_listens && (pass_listen ||
00550                                                                                            Monitor(target)))
00551                         pass_uselock = could_doit(sender, target, A_LUSE);
00552 
00553                 /*
00554                  * Process AxHEAR if we pass LISTEN, USElock and it's for me 
00555                  */
00556 
00557                 if((key & MSG_ME) && pass_listen && pass_uselock) {
00558                         if(sender != target)
00559                                 did_it(sender, target, 0, NULL, 0, NULL, A_AHEAR, args,
00560                                            nargs);
00561                         else
00562                                 did_it(sender, target, 0, NULL, 0, NULL, A_AMHEAR, args,
00563                                            nargs);
00564                         did_it(sender, target, 0, NULL, 0, NULL, A_AAHEAR, args, nargs);
00565                 }
00566                 /*
00567                  * Get rid of match arguments. We don't need them anymore 
00568                  */
00569 
00570                 if(pass_listen) {
00571                         for(i = 0; i < 10; i++)
00572                                 if(args[i] != NULL)
00573                                         free_lbuf(args[i]);
00574                 }
00575                 /*
00576                  * Process ^-listens if for me, MONITOR, and we pass USElock 
00577                  */
00578                 /*
00579                  * \todo Eventually come up with a cleaner method for making sure
00580                  * the sender isn't the same as the target.
00581                  */
00582                 if((key & MSG_ME) && (sender != target || Staff(target))
00583                    && pass_uselock && Monitor(target)) {
00584                         (void) atr_match(target, sender, AMATCH_LISTEN, (char *) msg, 0);
00585                 }
00586                 /*
00587                  * Deliver message to forwardlist members 
00588                  */
00589 
00590                 if((key & MSG_FWDLIST) && Audible(target) &&
00591                    check_filter(target, sender, A_FILTER, msg)) {
00592                         tbuff = dflt_from_msg(sender, target);
00593                         buff = add_prefix(target, sender, A_PREFIX, msg, tbuff);
00594                         free_lbuf(tbuff);
00595 
00596                         fp = fwdlist_get(target);
00597                         if(fp) {
00598                                 for(i = 0; i < fp->count; i++) {
00599                                         recip = fp->data[i];
00600                                         if(!Good_obj(recip) || (recip == target))
00601                                                 continue;
00602                                         notify_checked(recip, sender, buff,
00603                                                                    (MSG_ME | MSG_F_UP | MSG_F_CONTENTS |
00604                                                                         MSG_S_INSIDE));
00605                                 }
00606                         }
00607                         free_lbuf(buff);
00608                 }
00609                 /*
00610                  * Deliver message through audible exits 
00611                  */
00612 
00613                 if(key & MSG_INV_EXITS) {
00614                         DOLIST(obj, Exits(target)) {
00615                                 recip = Location(obj);
00616                                 if(Audible(obj) && ((recip != target) &&
00617                                                                         check_filter(obj, sender, A_FILTER,
00618                                                                                                  msg))) {
00619                                         buff =
00620                                                 add_prefix(obj, target, A_PREFIX, msg,
00621                                                                    "From a distance,");
00622                                         notify_checked(recip, sender, buff,
00623                                                                    MSG_ME | MSG_F_UP | MSG_F_CONTENTS |
00624                                                                    MSG_S_INSIDE);
00625                                         free_lbuf(buff);
00626                                 }
00627                         }
00628                 }
00629                 /*
00630                  * Deliver message through neighboring audible exits 
00631                  */
00632 
00633                 if(has_neighbors && ((key & MSG_NBR_EXITS) ||
00634                                                          ((key & MSG_NBR_EXITS_A) && is_audible))) {
00635 
00636                         /*
00637                          * If from inside, we have to add the prefix string * 
00638                          * 
00639                          * *  * * of * the container. 
00640                          */
00641 
00642                         if(key & MSG_S_INSIDE) {
00643                                 tbuff = dflt_from_msg(sender, target);
00644                                 buff = add_prefix(target, sender, A_PREFIX, msg, tbuff);
00645                                 free_lbuf(tbuff);
00646                         } else {
00647                                 buff = (char *) msg;
00648                         }
00649 
00650                         DOLIST(obj, Exits(Location(target))) {
00651                                 recip = Location(obj);
00652                                 if(Good_obj(recip) && Audible(obj) && (recip != targetloc)
00653                                    && (recip != target) &&
00654                                    check_filter(obj, sender, A_FILTER, msg)) {
00655                                         tbuff =
00656                                                 add_prefix(obj, target, A_PREFIX, buff,
00657                                                                    "From a distance,");
00658                                         notify_checked(recip, sender, tbuff,
00659                                                                    MSG_ME | MSG_F_UP | MSG_F_CONTENTS |
00660                                                                    MSG_S_INSIDE);
00661                                         free_lbuf(tbuff);
00662                                 }
00663                         }
00664                         if(key & MSG_S_INSIDE) {
00665                                 free_lbuf(buff);
00666                         }
00667                 }
00668                 /*
00669                  * Deliver message to contents 
00670                  */
00671 
00672                 if(((key & MSG_INV) || ((key & MSG_INV_L) && pass_listen)) &&
00673                    (check_filter(target, sender, A_INFILTER, msg))) {
00674 
00675                         /*
00676                          * Don't prefix the message if we were given the * *
00677                          * * * MSG_NOPREFIX key. 
00678                          */
00679 
00680                         if(key & MSG_S_OUTSIDE) {
00681                                 buff = add_prefix(target, sender, A_INPREFIX, msg, "");
00682                         } else {
00683                                 buff = (char *) msg;
00684                         }
00685                         DOLIST(obj, Contents(target)) {
00686                                 if(Slave(obj) && (key & MSG_NO_SLAVE))
00687                                         continue;
00688                                 if(obj != target) {
00689                                         notify_checked(obj, sender, buff,
00690                                                                    MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE );
00691                                 }
00692                         }
00693                         if(key & MSG_S_OUTSIDE)
00694                                 free_lbuf(buff);
00695                 }
00696                 /*
00697                  * Deliver message to neighbors 
00698                  */
00699 
00700                 if(has_neighbors && ((key & MSG_NBR) || ((key & MSG_NBR_A) &&
00701                                                                                                  is_audible &&
00702                                                                                                  check_filter(target, sender,
00703                                                                                                                           A_FILTER,
00704                                                                                                                           msg)))) {
00705                         if(key & MSG_S_INSIDE) {
00706                                 tbuff = dflt_from_msg(sender, target);
00707                                 buff = add_prefix(target, sender, A_PREFIX, msg, "");
00708                                 free_lbuf(tbuff);
00709                         } else {
00710                                 buff = (char *) msg;
00711                         }
00712                         DOLIST(obj, Contents(targetloc)) {
00713                                 if((obj != target) && (obj != targetloc)) {
00714                                         notify_checked(obj, sender, buff,
00715                                                                    MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | (key
00716                                                                                                                                                   &
00717                                                                                                                                                   MSG_COLORIZE));
00718                                 }
00719                         }
00720                         if(key & MSG_S_INSIDE) {
00721                                 free_lbuf(buff);
00722                         }
00723                 }
00724                 /*
00725                  * Deliver message to container 
00726                  */
00727 
00728                 if(has_neighbors && ((key & MSG_LOC) || ((key & MSG_LOC_A) &&
00729                                                                                                  is_audible &&
00730                                                                                                  check_filter(target, sender,
00731                                                                                                                           A_FILTER,
00732                                                                                                                           msg)))) {
00733                         if(key & MSG_S_INSIDE) {
00734                                 tbuff = dflt_from_msg(sender, target);
00735                                 buff = add_prefix(target, sender, A_PREFIX, msg, tbuff);
00736                                 free_lbuf(tbuff);
00737                         } else {
00738                                 buff = (char *) msg;
00739                         }
00740                         notify_checked(targetloc, sender, buff,
00741                                                    MSG_ME | MSG_F_UP | MSG_S_INSIDE);
00742                         if(key & MSG_S_INSIDE) {
00743                                 free_lbuf(buff);
00744                         }
00745                 }
00746         }
00747         if(msg_ns)
00748                 free_lbuf(msg_ns);
00749         mudstate.ntfy_nest_lev--;
00750 }
00751 
00752 void notify_except(dbref loc, dbref player, dbref exception, const char *msg)
00753 {
00754         dbref first;
00755 
00756         if(loc != exception)
00757                 notify_checked(loc, player, msg,
00758                                            (MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE |
00759                                                 MSG_NBR_EXITS_A));
00760         DOLIST(first, Contents(loc)) {
00761                 if(exception == NOSLAVE)
00762                         if(Slave(first))
00763                                 continue;
00764                 if(first != exception)
00765                         notify_checked(first, player, msg,
00766                                                    (MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE |
00767                                                         (exception == NOSLAVE ? MSG_NO_SLAVE : 0)));
00768         }
00769 }
00770 
00771 void notify_except2(dbref loc, dbref player, dbref exc1, dbref exc2,
00772                                         const char *msg)
00773 {
00774         dbref first;
00775 
00776         if((loc != exc1) && (loc != exc2))
00777                 notify_checked(loc, player, msg,
00778                                            (MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE |
00779                                                 MSG_NBR_EXITS_A));
00780         DOLIST(first, Contents(loc)) {
00781                 if(first != exc1 && first != exc2) {
00782                         notify_checked(first, player, msg,
00783                                                    (MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE));
00784                 }
00785         }
00786 }
00787 
00788 void do_shutdown(dbref player, dbref cause, int key, char *message)
00789 {
00790         FILE *fs;
00791 
00792         ResetSpecialObjects();
00793         if(player != NOTHING) {
00794                 raw_broadcast(0, "Game: Shutdown by %s", Name(Owner(player)));
00795                 STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN") {
00796                         log_text((char *) "Shutdown by ");
00797                         log_name(player);
00798                         ENDLOG;
00799                 }
00800         } else {
00801                 raw_broadcast(0, "Game: Fatal Error: %s", message);
00802                 STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN") {
00803                         log_text((char *) "Fatal error: ");
00804                         log_text(message);
00805                         ENDLOG;
00806                 }
00807         }
00808         STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN") {
00809                 log_text((char *) "Shutdown status: ");
00810                 log_text(message);
00811                 ENDLOG;
00812         }
00813 
00814         fs = fopen(mudconf.status_file, "w");
00815         fprintf(fs, "%s\n", message);
00816         fclose(fs);
00817 
00818         /*
00819          * Do we perform a normal or an emergency shutdown?  Normal shutdown
00820          * * * * * is handled by exiting the main loop in shovechars,
00821          * emergency  * * * * shutdown is done here. 
00822          */
00823 
00824         if(key & SHUTDN_PANIC) {
00825 
00826                 /*
00827                  * Close down the network interface 
00828                  */
00829 
00830                 emergency_shutdown();
00831 
00832                 /*
00833                  * Close the attribute text db and dump the header db 
00834                  */
00835 
00836                 pcache_sync();
00837                 STARTLOG(LOG_ALWAYS, "DMP", "PANIC") {
00838                         log_text((char *) "Panic dump: ");
00839                         log_text(mudconf.crashdb);
00840                         ENDLOG;
00841                 } dump_database_internal(DUMP_CRASHED);
00842 
00843                 STARTLOG(LOG_ALWAYS, "DMP", "DONE") {
00844                         log_text((char *) "Panic dump complete: ");
00845                         log_text(mudconf.crashdb);
00846                         ENDLOG;
00847                 }
00848         }
00849         /*
00850          * Set up for normal shutdown 
00851          */
00852 
00853         mudstate.shutdown_flag = 1;
00854         event_loopexit(NULL);
00855         return;
00856 }
00857 
00858 void dump_database_internal(int dump_type)
00859 {
00860         char tmpfile[256], outfn[256], prevfile[256];
00861         FILE *f;
00862 
00863 #ifdef USE_PYTHON
00864         runPythonHook("save");
00865 #endif
00866 
00867         if(dump_type == DUMP_CRASHED) {
00868                 unlink(mudconf.crashdb);
00869                 f = fopen(mudconf.crashdb, "w");
00870                 if(f != NULL) {
00871                         db_write(f, F_MUX, UNLOAD_VERSION | UNLOAD_OUTFLAGS);
00872                         fclose(f);
00873                 } else {
00874                         log_perror("DMP", "FAIL", "Opening crash file", mudconf.crashdb);
00875                 }
00876                 if(mudconf.have_mailer)
00877                         if((f = fopen(mudconf.mail_db, "w"))) {
00878                                 dump_mail(f);
00879                                 fclose(f);
00880                         }
00881                 if(mudconf.have_comsys || mudconf.have_macros)
00882                         save_comsys_and_macros(mudconf.commac_db);
00883                 SaveSpecialObjects(DUMP_CRASHED);
00884                 return;
00885         }
00886 
00887         if(dump_type == DUMP_RESTART) {
00888                 f = fopen(mudconf.indb, "w");
00889                 if(f != NULL) {
00890                         /* Write a flatfile */
00891                         db_write(f, F_MUX, UNLOAD_VERSION | UNLOAD_OUTFLAGS);
00892                         fclose(f);
00893                 } else {
00894                         log_perror("DMP", "FAIL", "Opening restart file", mudconf.indb);
00895                 }
00896                 if(mudconf.have_mailer)
00897                         if((f = fopen(mudconf.mail_db, "w"))) {
00898                                 dump_mail(f);
00899                                 fclose(f);
00900                         }
00901                 if(mudconf.have_comsys || mudconf.have_macros)
00902                         save_comsys_and_macros(mudconf.commac_db);
00903                 if(mudconf.have_specials)
00904                         SaveSpecialObjects(DUMP_RESTART);
00905                 return;
00906         }
00907         if(dump_type == DUMP_KILLED) {
00908                 sprintf(tmpfile, "%s.KILLED", mudconf.indb);
00909                 f = fopen(tmpfile, "w");
00910                 if(f != NULL) {
00911                         /* Write a flatfile */
00912                         db_write(f, F_MUX, UNLOAD_VERSION | UNLOAD_OUTFLAGS);
00913                         fclose(f);
00914                 } else {
00915                         log_perror("DMP", "FAIL", "Opening killed file", mudconf.indb);
00916                 }
00917                 if(mudconf.have_mailer)
00918                         if((f = fopen(mudconf.mail_db, "w"))) {
00919                                 dump_mail(f);
00920                                 fclose(f);
00921                         }
00922                 if(mudconf.have_comsys || mudconf.have_macros)
00923                         save_comsys_and_macros(mudconf.commac_db);
00924                 if(mudconf.have_specials)
00925                         SaveSpecialObjects(DUMP_KILLED);
00926                 return;
00927         }
00928 
00929         sprintf(prevfile, "%s.prev", mudconf.outdb);
00930         sprintf(tmpfile, "%s.#%d#", mudconf.outdb, mudstate.epoch - 1);
00931         unlink(tmpfile);                        /*
00932                                                                  * nuke our predecessor 
00933                                                                  */
00934         sprintf(tmpfile, "%s.#%d#", mudconf.outdb, mudstate.epoch);
00935 
00936         if(mudconf.compress_db) {
00937                 sprintf(tmpfile, "%s.#%d#.gz", mudconf.outdb, mudstate.epoch - 1);
00938                 unlink(tmpfile);
00939                 sprintf(tmpfile, "%s.#%d#.gz", mudconf.outdb, mudstate.epoch);
00940                 StringCopy(outfn, mudconf.outdb);
00941                 strcat(outfn, ".gz");
00942                 f = popen(tprintf("%s > %s", mudconf.compress, tmpfile), "w");
00943                 if(f) {
00944                         db_write(f, F_MUX, OUTPUT_VERSION | OUTPUT_FLAGS);
00945                         pclose(f);
00946                         rename(mudconf.outdb, prevfile);
00947                         if(rename(tmpfile, outfn) < 0)
00948                                 log_perror("SAV", "FAIL",
00949                                                    "Renaming output file to DB file", tmpfile);
00950                 } else {
00951                         log_perror("SAV", "FAIL", "Opening", tmpfile);
00952                 }
00953         } else {
00954                 f = fopen(tmpfile, "w");
00955                 if(f) {
00956                         db_write(f, F_MUX, OUTPUT_VERSION | OUTPUT_FLAGS);
00957                         fclose(f);
00958                         rename(mudconf.outdb, prevfile);
00959                         if(rename(tmpfile, mudconf.outdb) < 0)
00960                                 log_perror("SAV", "FAIL",
00961                                                    "Renaming output file to DB file", tmpfile);
00962                 } else {
00963                         log_perror("SAV", "FAIL", "Opening", tmpfile);
00964                 }
00965                 rename(prevfile, mudconf.indb);
00966         }
00967 
00968         if(mudconf.have_mailer)
00969                 if((f = fopen(mudconf.mail_db, "w"))) {
00970                         dump_mail(f);
00971                         fclose(f);
00972                 }
00973         if(mudconf.have_comsys || mudconf.have_macros)
00974                 save_comsys_and_macros(mudconf.commac_db);
00975         if(mudconf.have_specials)
00976                 SaveSpecialObjects(DUMP_NORMAL);
00977 }
00978 
00979 void dump_database(void)
00980 {
00981         char *buff;
00982 
00983         mudstate.epoch++;
00984         mudstate.dumping = 1;
00985         buff = alloc_mbuf("dump_database");
00986         sprintf(buff, "%s.#%d#", mudconf.outdb, mudstate.epoch);
00987         STARTLOG(LOG_DBSAVES, "DMP", "DUMP") {
00988                 log_text((char *) "Dumping: ");
00989                 log_text(buff);
00990                 ENDLOG;
00991         } pcache_sync();
00992 
00993         dump_database_internal(DUMP_NORMAL);
00994         STARTLOG(LOG_DBSAVES, "DMP", "DONE") {
00995                 log_text((char *) "Dump complete: ");
00996                 log_text(buff);
00997                 ENDLOG;
00998         } free_mbuf(buff);
00999 
01000         mudstate.dumping = 0;
01001 }
01002 
01003 void fork_and_dump(int key)
01004 {
01005         char *buff;
01006 
01007         if(*mudconf.dump_msg)
01008                 raw_broadcast(0, "%s", mudconf.dump_msg);
01009 
01010         check_mail_expiration();
01011         mudstate.epoch++;
01012         mudstate.dumping = 1;
01013         buff = alloc_mbuf("fork_and_dump");
01014         sprintf(buff, "%s.#%d#", mudconf.outdb, mudstate.epoch);
01015    
01016     log_error(LOG_DBSAVES, "DMP", "CHKPT", "Saving database: %s", buff);
01017     
01018     pcache_sync();
01019     
01020         if(!key || (key & DUMP_STRUCT)) {
01021                 if(!fork()) {
01022             dprintk("child database write process starting.");
01023                         unbind_signals();
01024                         dump_database_internal(DUMP_NORMAL);
01025             dprintk("child database write process finished.");
01026             exit(0);
01027                 }
01028         }
01029 
01030         mudstate.dumping = 0;
01031 
01032         if(*mudconf.postdump_msg)
01033                 raw_broadcast(0, "%s", mudconf.postdump_msg);
01034 }
01035 
01036 static int load_game(void)
01037 {
01038         FILE *f;
01039         int compressed;
01040         char infile[256];
01041         struct stat statbuf;
01042         int db_format, db_version, db_flags;
01043 
01044         f = NULL;
01045         compressed = 0;
01046         if(mudconf.compress_db) {
01047                 StringCopy(infile, mudconf.indb);
01048                 strcat(infile, ".gz");
01049                 if(stat(infile, &statbuf) == 0) {
01050                         if((f = popen(tprintf(" %s < %s", mudconf.uncompress,
01051                                                                   infile), "r")) != NULL)
01052                                 compressed = 1;
01053                 }
01054         }
01055         if(compressed == 0) {
01056                 StringCopy(infile, mudconf.indb);
01057                 if((f = fopen(mudconf.indb, "r")) == NULL)
01058                         return -1;
01059         }
01060         /*
01061          * ok, read it in 
01062          */
01063 
01064         STARTLOG(LOG_STARTUP, "INI", "LOAD") {
01065                 log_text((char *) "Loading: ");
01066                 log_text(infile);
01067                 ENDLOG;
01068         };
01069         if(db_read(f, &db_format, &db_version, &db_flags) < 0) {
01070                 STARTLOG(LOG_ALWAYS, "INI", "FATAL") {
01071                         log_text((char *) "Error loading ");
01072                         log_text(infile);
01073                         ENDLOG;
01074                 }
01075                 if(compressed)
01076                         pclose(f);
01077                 else
01078                         fclose(f);
01079                 return -1;
01080         }
01081         if(compressed)
01082                 pclose(f);
01083         else
01084                 fclose(f);
01085 
01086         if(mudconf.have_comsys || mudconf.have_macros)
01087                 load_comsys_and_macros(mudconf.commac_db);
01088 
01089         /* Load the mecha stuff.. */
01090         if(mudconf.have_specials)
01091                 LoadSpecialObjects();
01092 
01093         if(mudconf.have_mailer)
01094                 if((f = fopen(mudconf.mail_db, "r"))) {
01095                         load_mail(f);
01096                         fclose(f);
01097                 }
01098         STARTLOG(LOG_STARTUP, "INI", "LOAD") {
01099                 log_text((char *) "Load complete.");
01100                 ENDLOG;
01101         }
01102         /*
01103          * everything ok 
01104          */
01105         return (0);
01106 }
01107 
01111 int list_check(dbref thing, dbref player, char type, char *str,
01112                            int check_parent)
01113 {
01114         int match, limit;
01115 
01116         match = 0;
01117         limit = mudstate.db_top;
01118         while (thing != NOTHING) {
01119                 if((thing != player) && (!(No_Command(thing)))) {
01120                         if(atr_match(thing, player, type, str, check_parent) > 0)
01121                                 match = 1;
01122                 }
01123                 thing = Next(thing);
01124                 if(--limit < 0)
01125                         return match;
01126         }
01127         return match;
01128 }
01129 
01130 int Hearer(dbref thing)
01131 {
01132         char *as, *buff, *s;
01133         dbref aowner;
01134         int attr, aflags;
01135         ATTR *ap;
01136 
01137         if(mudstate.inpipe && (thing == mudstate.poutobj))
01138                 return 1;
01139 
01140         if(Connected(thing) || Puppet(thing))
01141                 return 1;
01142 
01143         if(Monitor(thing))
01144                 buff = alloc_lbuf("Hearer");
01145         else
01146                 buff = NULL;
01147         for(attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
01148                 if(attr == A_LISTEN) {
01149                         if(buff)
01150                                 free_lbuf(buff);
01151                         return 1;
01152                 }
01153                 if(Monitor(thing)) {
01154                         ap = atr_num(attr);
01155                         if(!ap || (ap->flags & AF_NOPROG))
01156                                 continue;
01157 
01158                         atr_get_str(buff, thing, attr, &aowner, &aflags);
01159 
01160                         /*
01161                          * Make sure we can execute it 
01162                          */
01163 
01164                         if((buff[0] != AMATCH_LISTEN) || (aflags & AF_NOPROG))
01165                                 continue;
01166 
01167                         /*
01168                          * Make sure there's a : in it 
01169                          */
01170 
01171                         for(s = buff + 1; *s && (*s != ':'); s++);
01172                         if(s) {
01173                                 free_lbuf(buff);
01174                                 return 1;
01175                         }
01176                 }
01177         }
01178         if(buff)
01179                 free_lbuf(buff);
01180         return 0;
01181 }
01182 
01183 void do_readcache(dbref player, dbref cause, int key)
01184 {
01185         helpindex_load(player);
01186         fcache_load(player);
01187 }
01188 
01189 static void process_preload(void)
01190 {
01191         dbref thing, parent, aowner;
01192         int aflags, lev, i;
01193         char *tstr;
01194         FWDLIST *fp;
01195 
01196         fp = (FWDLIST *) alloc_lbuf("process_preload.fwdlist");
01197         tstr = alloc_lbuf("process_preload.string");
01198         i = 0;
01199         DO_WHOLE_DB(thing) {
01200 
01201                 /*
01202                  * Ignore GOING objects 
01203                  */
01204 
01205                 if(Going(thing))
01206                         continue;
01207 
01208                 do_top(10);
01209 
01210                 /*
01211                  * Look for a STARTUP attribute in parents 
01212                  */
01213 
01214                 ITER_PARENTS(thing, parent, lev) {
01215                         if(Flags(thing) & HAS_STARTUP) {
01216                                 did_it(Owner(thing), thing, 0, NULL, 0, NULL, A_STARTUP,
01217                                            (char **) NULL, 0);
01218                                 /*
01219                                  * Process queue entries as we add them 
01220                                  */
01221 
01222                                 do_second();
01223                                 do_top(10);
01224                                 break;
01225                         }
01226                 }
01227 
01228                 /*
01229                  * Look for a FORWARDLIST attribute 
01230                  */
01231 
01232                 if(H_Fwdlist(thing)) {
01233                         (void) atr_get_str(tstr, thing, A_FORWARDLIST, &aowner, &aflags);
01234                         if(*tstr) {
01235                                 fwdlist_load(fp, GOD, tstr);
01236                                 if(fp->count > 0)
01237                                         fwdlist_set(thing, fp);
01238                         }
01239                 }
01240         }
01241         free_lbuf(fp);
01242         free_lbuf(tstr);
01243 }
01244 
01245 int main(int argc, char *argv[])
01246 {
01247         int mindb;
01248 
01249         if((argc > 2) && (!strcmp(argv[1], "-s") && (argc > 3))) {
01250                 fprintf(stderr, "Usage: %s [-s] [config-file]\n", argv[0]);
01251                 exit(1);
01252         }
01253 
01254         event_init();
01255 
01256 #if defined(HAVE_IEEEFP_H) && defined(HAVE_SYS_UCONTEXT_H)
01257         /*
01258          * Inhibit IEEE fp exception on overflow 
01259          */
01260 
01261         fpsetmask(fpgetmask() & ~FP_X_OFL);
01262 #endif
01263 
01264         mindb = 0;                                      /* Are we creating a new db? */
01265         corrupt = 0;                            /* Database isn't corrupted. */
01266     memset(&mudstate, 0, sizeof(mudstate));
01267         time(&mudstate.start_time);
01268         time(&mudstate.restart_time);
01269         mudstate.executable_path = strdup(argv[0]);
01270     mudstate.db_top = -1;
01271         tcache_init();
01272         pcache_init();
01273         cf_init();
01274         init_rlimit();
01275         init_cmdtab();
01276         init_mactab();
01277         init_chantab();
01278         init_logout_cmdtab();
01279         init_flagtab();
01280         init_powertab();
01281         init_functab();
01282         init_attrtab();
01283         init_version();
01284 
01285 #ifdef HUDINFO_SUPPORT
01286         init_hudinfo();
01287 #endif
01288 
01289         hashinit(&mudstate.player_htab, 250 * HASH_FACTOR);
01290         nhashinit(&mudstate.mail_htab, 50 * HASH_FACTOR);
01291         nhashinit(&mudstate.fwdlist_htab, 25 * HASH_FACTOR);
01292         nhashinit(&mudstate.parent_htab, 5 * HASH_FACTOR);
01293         mudstate.desctree = rb_init(desc_cmp, NULL);
01294         vattr_init();
01295 
01296         if(argc > 1 && !strcmp(argv[1], "-s")) {
01297                 mindb = 1;
01298                 if(argc == 3)
01299                         cf_read(argv[2]);
01300                 else
01301                         cf_read((char *) CONF_FILE);
01302         } else if(argc == 2) {
01303                 cf_read(argv[1]);
01304         } else {
01305                 cf_read((char *) CONF_FILE);
01306         }
01307 
01308         fcache_init();
01309         helpindex_init();
01310         db_free();
01311 
01312         mudstate.record_players = 0;
01313 
01314         if(mindb)
01315                 db_make_minimal();
01316         else if(load_game() < 0) {
01317                 STARTLOG(LOG_ALWAYS, "INI", "LOAD") {
01318                         log_text((char *) "Couldn't load: ");
01319                         log_text(mudconf.indb);
01320                         ENDLOG;
01321                 } exit(2);
01322         }
01323 #ifdef USE_PYTHON
01324         MUXPy_Init();
01325         runPythonHook("load");
01326 #endif
01327 
01328         /* initialize random.. */
01329         srandom(getpid());
01330         /* set singnals.. */
01331         bind_signals();
01332 
01333         /*
01334          * Do a consistency check and set up the freelist 
01335          */
01336 
01337         do_dbck(NOTHING, NOTHING, 0);
01338 
01339         /*
01340          * Reset all the hash stats 
01341          */
01342 
01343         hashreset(&mudstate.command_htab);
01344         hashreset(&mudstate.macro_htab);
01345         hashreset(&mudstate.channel_htab);
01346         nhashreset(&mudstate.mail_htab);
01347         hashreset(&mudstate.logout_cmd_htab);
01348         hashreset(&mudstate.func_htab);
01349         hashreset(&mudstate.flags_htab);
01350         hashreset(&mudstate.attr_name_htab);
01351         hashreset(&mudstate.player_htab);
01352         nhashreset(&mudstate.fwdlist_htab);
01353         hashreset(&mudstate.news_htab);
01354         hashreset(&mudstate.help_htab);
01355         hashreset(&mudstate.wizhelp_htab);
01356         hashreset(&mudstate.plushelp_htab);
01357         hashreset(&mudstate.wiznews_htab);
01358 
01359         for(mindb = 0; mindb < MAX_GLOBAL_REGS; mindb++) {
01360                 mudstate.global_regs[mindb] = alloc_lbuf("main.global_reg");
01361         memset(mudstate.global_regs[mindb], 0, LBUF_SIZE);
01362         }
01363 
01364         mudstate.now = time(NULL);
01365         process_preload();
01366 
01367         dnschild_init();
01368 
01369     if(!load_restart_db_xdr()) {
01370         load_restart_db();
01371     }
01372 
01373 #ifdef SQL_SUPPORT
01374         sqlchild_init();
01375 #endif
01376 
01377 #ifdef ARBITRARY_LOGFILES
01378         logcache_init();
01379 #endif
01380 
01381 #ifdef MCHECK
01382         mtrace();
01383 #endif
01384 
01385         /*
01386          * go do it 
01387          */
01388 
01389         mudstate.now = time(NULL);
01390         init_timer();
01391         shovechars(mudconf.port);
01392 
01393 #ifdef MCHECK
01394         muntrace();
01395 #endif
01396 
01397         close_sockets(0, (char *) "Going down - Bye");
01398         dump_database();
01399 
01400 #ifdef ARBITRARY_LOGFILES
01401         logcache_destruct();
01402 #endif
01403 #ifdef SQL_SUPPORT
01404         sqlchild_destruct();
01405 #endif
01406 
01407         exit(0);
01408 }
01409 
01410 static void init_rlimit(void)
01411 {
01412 #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
01413         struct rlimit *rlp;
01414 
01415         rlp = (struct rlimit *) alloc_lbuf("rlimit");
01416 
01417         if(getrlimit(RLIMIT_NOFILE, rlp)) {
01418                 log_perror("RLM", "FAIL", NULL, "getrlimit()");
01419                 free_lbuf(rlp);
01420                 return;
01421         }
01422         rlp->rlim_cur = rlp->rlim_max;
01423         if(setrlimit(RLIMIT_NOFILE, rlp))
01424                 log_perror("RLM", "FAIL", NULL, "setrlimit()");
01425         free_lbuf(rlp);
01426 
01427 #endif /*
01428             * HAVE_SETRLIMIT 
01429             */
01430 }

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