home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / tinymush.zip / TinyMush / os2src / game.c < prev    next >
Text File  |  1999-08-28  |  36KB  |  1,458 lines

  1. /* game.c -- initialization stuff */
  2.  
  3. #include "autoconf.h"
  4. #include "copyright.h"
  5. #ifndef    lint
  6. static char *RCSid = "$Id: game.c,v 1.9 1995/03/21 00:00:27 ambar Exp $";
  7. USE(RCSid);
  8. #endif
  9.  
  10. #include "interface.h"
  11. #include "file_c.h"
  12. #include "match.h"
  13. #include "flags.h"
  14. #include "attrs.h"
  15. #include "rwho_clilib.h"
  16.  
  17. #ifdef OS2
  18. #include <process.h>
  19. #endif
  20.  
  21. extern void NDECL(init_attrtab);
  22. extern void NDECL(init_cmdtab);
  23. extern void NDECL(cf_init);
  24. extern void NDECL(pcache_init);
  25. extern int FDECL(cf_read, (char *fn));
  26. extern void NDECL(init_functab);
  27. extern void FDECL(close_sockets, (int emergency, char *message));
  28. extern void NDECL(init_version);
  29. extern void NDECL(init_logout_cmdtab);
  30. extern void NDECL(init_timer);
  31. extern void FDECL(raw_notify, (dbref, const char *));
  32. extern void NDECL(do_second);
  33. extern void FDECL(do_dbck, (dbref, dbref, int));
  34.  
  35. void FDECL(fork_and_dump, (int));
  36. void NDECL(dump_database);
  37. void NDECL(pcache_sync);
  38. extern void NDECL(dump_restart_db);
  39. static void FDECL(dump_database_internal, (int));
  40. static void NDECL(init_rlimit);
  41.  
  42. int reserved;
  43.  
  44. /*
  45.  * used to allocate storage for temporary stuff, cleared before command
  46.  * execution
  47.  */
  48.  
  49. void 
  50. do_dump(player, cause, key)
  51.     dbref player, cause;
  52.     int key;
  53. {
  54.     notify(player, "Dumping...");
  55.     fork_and_dump(key);
  56. }
  57.  
  58. /* print out stuff into error file */
  59.  
  60. void 
  61. NDECL(report)
  62. {
  63.     STARTLOG(LOG_BUGS, "BUG", "INFO")
  64.     log_text((char *) "Command: '");
  65.     log_text(mudstate.debug_cmd);
  66.     log_text((char *) "'");
  67.     ENDLOG
  68.     if (Good_obj(mudstate.curr_player)) {
  69.     STARTLOG(LOG_BUGS, "BUG", "INFO")
  70.         log_text((char *) "Player: ");
  71.     log_name_and_loc(mudstate.curr_player);
  72.     if ((mudstate.curr_enactor != mudstate.curr_player) &&
  73.         Good_obj(mudstate.curr_enactor)) {
  74.         log_text((char *) " Enactor: ");
  75.         log_name_and_loc(mudstate.curr_enactor);
  76.     }
  77.     ENDLOG
  78.     }
  79. }
  80.  
  81. /* ----------------------------------------------------------------------
  82.  * regexp_match: Load a regular expression match and insert it into
  83.  * registers.
  84.  */
  85.  
  86. int regexp_match(pattern, str, args, nargs)
  87.     char *pattern;
  88.     char *str;
  89.     char *args[];
  90.     int nargs;
  91. {
  92.     regexp *re;
  93.     int got_match;
  94.     int i, len;
  95.  
  96.     /*
  97.      * Load the regexp pattern. This allocates memory which must be
  98.      * later freed. A free() of the regexp does free all structures
  99.      * under it.
  100.      */
  101.  
  102.     if ((re = regcomp(pattern)) == NULL) {
  103.     /*
  104.      * This is a matching error. We have an error message in
  105.      * regexp_errbuf that we can ignore, since we're doing
  106.      * command-matching.
  107.      */
  108.     return 0;
  109.     }
  110.  
  111.     /* 
  112.      * Now we try to match the pattern. The relevant fields will
  113.      * automatically be filled in by this.
  114.      */
  115.     got_match = regexec(re, str);
  116.     if (!got_match) {
  117.     free(re);
  118.     return 0;
  119.     }
  120.  
  121.     /*
  122.      * Now we fill in our args vector. Note that in regexp matching,
  123.      * 0 is the entire string matched, and the parenthesized strings
  124.      * go from 1 to 9. We DO PRESERVE THIS PARADIGM, for consistency
  125.      * with other languages.
  126.      */
  127.  
  128.     for (i = 0; i < nargs; i++) {
  129.     args[i] = NULL;
  130.     }
  131.  
  132.     /* Convenient: nargs and NSUBEXP are the same.
  133.      * We are also guaranteed that our buffer is going to be LBUF_SIZE
  134.      * so we can copy without fear.
  135.      */
  136.  
  137.     for (i = 0;
  138.      (i < NSUBEXP) && (re->startp[i]) && (re->endp[i]);
  139.      i++) {
  140.     len = re->endp[i] - re->startp[i];
  141.     args[i] = alloc_lbuf("regexp_match");
  142.     strncpy(args[i], re->startp[i], len);
  143.     args[i][len] = '\0';    /* strncpy() does not null-terminate */
  144.     }
  145.     
  146.     free(re);
  147.     return 1;
  148. }
  149.  
  150. /* ----------------------------------------------------------------------
  151.  * atr_match: Check attribute list for wild card matches and queue them.
  152.  */
  153.  
  154. static int 
  155. atr_match1(thing, parent, player, type, str, raw_str, check_exclude,
  156.        hash_insert)
  157.     dbref thing, parent, player;
  158.     char type, *str, *raw_str;
  159.     int check_exclude, hash_insert;
  160. {
  161.     dbref aowner;
  162.     int match, attr, aflags, i;
  163.     char *buff, *s, *as;
  164.     char *args[10];
  165.     ATTR *ap;
  166.  
  167.     /* See if we can do it.  Silently fail if we can't. */
  168.  
  169.     if (!could_doit(player, parent, A_LUSE))
  170.     return -1;
  171.  
  172.     match = 0;
  173.     buff = alloc_lbuf("atr_match1");
  174.     atr_push();
  175.     for (attr = atr_head(parent, &as); attr; attr = atr_next(&as)) {
  176.     ap = atr_num(attr);
  177.  
  178.     /* Never check NOPROG attributes. */
  179.  
  180.     if (!ap || (ap->flags & AF_NOPROG))
  181.         continue;
  182.  
  183.     /* If we aren't the bottom level check if we saw this attr
  184.      * before.  Also exclude it if the attribute type is PRIVATE.
  185.      */
  186.  
  187.     if (check_exclude &&
  188.         ((ap->flags & AF_PRIVATE) ||
  189.          nhashfind(ap->number, &mudstate.parent_htab))) {
  190.         continue;
  191.     }
  192.     atr_get_str(buff, parent, attr, &aowner, &aflags);
  193.  
  194.     /* Skip if private and on a parent */
  195.  
  196.     if (check_exclude && (aflags & AF_PRIVATE)) {
  197.         continue;
  198.     }
  199.     /* If we aren't the top level remember this attr so we exclude
  200.      * it from now on.
  201.      */
  202.  
  203.     if (hash_insert)
  204.         nhashadd(ap->number, (int *) &attr,
  205.              &mudstate.parent_htab);
  206.  
  207.     /* Check for the leadin character after excluding the attrib
  208.      * This lets non-command attribs on the child block commands
  209.      * on the parent.
  210.      */
  211.  
  212.     if ((buff[0] != type) || (aflags & AF_NOPROG))
  213.         continue;
  214.  
  215.     /* decode it: search for first un escaped : */
  216.  
  217.     for (s = buff + 1; *s && (*s != ':'); s++);
  218.     if (!*s)
  219.         continue;
  220.     *s++ = 0;
  221.     if (((aflags & AF_REGEXP) &&
  222.          regexp_match(buff + 1,
  223.               ((aflags & AF_NOPARSE) ? raw_str : str),
  224.               args, 10)) ||
  225.         (wild_match(buff + 1, 
  226.             ((aflags & AF_NOPARSE) ? raw_str : str),
  227.             args, 10, 0))) {
  228.         match = 1;
  229.         wait_que(thing, player, 0, NOTHING, s, args, 10,
  230.              mudstate.global_regs);
  231.         for (i = 0; i < 10; i++) {
  232.         if (args[i])
  233.             free_lbuf(args[i]);
  234.         }
  235.     }
  236.     }
  237.     atr_pop();
  238.     free_lbuf(buff);
  239.     return (match);
  240. }
  241.  
  242. int 
  243. atr_match(thing, player, type, str, raw_str, check_parents)
  244.     dbref thing, player;
  245.     char type, *str, *raw_str;
  246.     int check_parents;
  247. {
  248.     int match, lev, result, exclude, insert;
  249.     dbref parent;
  250.  
  251.     /* If thing is halted, or it doesn't have a COMMANDS flag and we're
  252.      * we're doing a $-match, don't check it.
  253.      */
  254.  
  255.     if (((type == AMATCH_CMD) && 
  256.      !Has_Commands(thing) && mudconf.req_cmds_flag) || Halted(thing))
  257.     return 0;
  258.  
  259.     /* If not checking parents, just check the thing */
  260.  
  261.     match = 0;
  262.     if (!check_parents)
  263.     return atr_match1(thing, thing, player, type, str, raw_str, 0, 0);
  264.  
  265.     /* Check parents, ignoring halted objects */
  266.  
  267.     exclude = 0;
  268.     insert = 1;
  269.     nhashflush(&mudstate.parent_htab, 0);
  270.     ITER_PARENTS(thing, parent, lev) {
  271.     if (!Good_obj(Parent(parent)))
  272.         insert = 0;
  273.     result = atr_match1(thing, parent, player, type, str, raw_str,
  274.                 exclude, insert);
  275.     if (result > 0) {
  276.         match = 1;
  277.     } else if (result < 0) {
  278.         return match;
  279.     }
  280.     exclude = 1;
  281.     }
  282.  
  283.     return match;
  284. }
  285.  
  286. /* ---------------------------------------------------------------------------
  287.  * notify_check: notifies the object #target of the message msg, and
  288.  * optionally notify the contents, neighbors, and location also.
  289.  */
  290.  
  291. int 
  292. check_filter(object, player, filter, msg)
  293.     dbref object, player;
  294.     int filter;
  295.     const char *msg;
  296. {
  297.     int aflags;
  298.     dbref aowner;
  299.     char *buf, *nbuf, *cp, *dp, *preserve[MAX_GLOBAL_REGS];
  300.  
  301.     buf = atr_pget(object, filter, &aowner, &aflags);
  302.     if (!*buf) {
  303.     free_lbuf(buf);
  304.     return (1);
  305.     }
  306.  
  307.     save_global_regs("check_filter_save", preserve);
  308.     dp = nbuf = exec(object, player, EV_FIGNORE | EV_EVAL | EV_TOP, buf,
  309.              (char **) NULL, 0);
  310.     free_lbuf(buf);
  311.     restore_global_regs("check_filter_restore", preserve);
  312.  
  313.     do {
  314.     cp = parse_to(&dp, ',', EV_STRIP);
  315.     if (quick_wild(cp, (char *) msg)) {
  316.         free_lbuf(nbuf);
  317.         return (0);
  318.     }
  319.     } while (dp != NULL);
  320.     free_lbuf(nbuf);
  321.     return (1);
  322. }
  323.  
  324. static char *
  325. add_prefix(object, player, prefix, msg, dflt)
  326.     dbref object, player;
  327.     int prefix;
  328.     const char *msg, *dflt;
  329. {
  330.     int aflags;
  331.     dbref aowner;
  332.     char *buf, *nbuf, *cp, *preserve[MAX_GLOBAL_REGS];
  333.  
  334.     buf = atr_pget(object, prefix, &aowner, &aflags);
  335.     if (!*buf) {
  336.     cp = buf;
  337.     safe_str((char *) dflt, buf, &cp);
  338.     } else {
  339.     save_global_regs("add_prefix_save", preserve);
  340.     nbuf = exec(object, player, EV_FIGNORE | EV_EVAL | EV_TOP, buf,
  341.             (char **) NULL, 0);
  342.     free_lbuf(buf);
  343.     restore_global_regs("add_prefix_restore", preserve);
  344.     buf = nbuf;
  345.     cp = &buf[strlen(buf)];
  346.     }
  347.     if (cp != buf)
  348.     safe_str((char *) " ", buf, &cp);
  349.     safe_str((char *) msg, buf, &cp);
  350.     return (buf);
  351. }
  352.  
  353. static char *
  354. dflt_from_msg(sender, sendloc)
  355.     dbref sender, sendloc;
  356. {
  357.     char *tp, *tbuff;
  358.  
  359.     tp = tbuff = alloc_lbuf("notify_check.fwdlist");
  360.     safe_str((char *) "From ", tbuff, &tp);
  361.     if (Good_obj(sendloc))
  362.     safe_str(Name(sendloc), tbuff, &tp);
  363.     else
  364.     safe_str(Name(sender), tbuff, &tp);
  365.     safe_chr(',', tbuff, &tp);
  366.     return tbuff;
  367. }
  368.  
  369. #ifdef PUEBLO_SUPPORT
  370.  
  371. /* Do HTML escaping, converting < to <, etc.  'dest' needs to be
  372.  * allocated & freed by the caller.
  373.  *
  374.  * If you're using this to append to a string, you can pass in the
  375.  * safe_{str|chr} (char **) so we can just do the append directly, 
  376.  * saving you an alloc_lbuf()...free_lbuf().  If you want us to append
  377.  * from the start of 'dest', just pass in a 0 for 'destp'.
  378.  * 
  379.  * Returns 0 if the copy succeeded, 1 if it failed.
  380.  */
  381. int
  382. html_escape(src, dest, destp)
  383.      const char *src;
  384.      char *dest;
  385.      char **destp;
  386. {
  387.     static char new_buf[LBUF_SIZE * 5];
  388.     const char *msg_orig;
  389.     char *mp_escaped;
  390.     char *temp, *bufp;
  391.  
  392.     if (destp == 0) {
  393.     temp = dest;
  394.     destp = &temp;
  395.     }
  396.  
  397.     for (*new_buf = '\0', bufp = new_buf, msg_orig = src; 
  398.      msg_orig && *msg_orig;
  399.      msg_orig++) {
  400.     switch (*msg_orig) {
  401.       case '<':
  402.         *bufp = '\0';
  403.         strcat(new_buf, (char *) "<");
  404.         bufp += 4;
  405.         break;
  406.       case '>':
  407.         *bufp = '\0';
  408.         strcat(new_buf, (char *) ">"); 
  409.         bufp += 4;
  410.         break;
  411.       case '&':
  412.         *bufp = '\0';
  413.         strcat(new_buf, (char *) "&"); 
  414.         bufp += 5;
  415.         break;
  416.       case '\"':
  417.         *bufp = '\0';
  418.         strcat(new_buf, (char *) """); 
  419.         bufp += 6;
  420.         break;
  421.       default:
  422.         *bufp++ = *msg_orig;
  423.         break;
  424.     }
  425.     }
  426.     *bufp = '\0';
  427.     safe_str(new_buf, dest, destp);
  428.     destp = '\0';
  429.     return;
  430. }
  431.  
  432. #endif /* PUEBLO_SUPPORT */
  433.  
  434. void 
  435. notify_check(target, sender, msg, key)
  436.     dbref target, sender;
  437.     int key;
  438.     const char *msg;
  439. {
  440.     char *msg_ns, *mp, *tbuff, *tp, *buff;
  441.     char *args[10];
  442.     dbref aowner, targetloc, recip, obj;
  443.     int i, nargs, aflags, has_neighbors, pass_listen;
  444.     int check_listens, pass_uselock, is_audible;
  445.     FWDLIST *fp;
  446.  
  447.     /* If speaker is invalid or message is empty, just exit */
  448.  
  449.     if (!Good_obj(target) || !msg || !*msg)
  450.     return;
  451.  
  452.     /* Enforce a recursion limit */
  453.  
  454.     mudstate.ntfy_nest_lev++;
  455.     if (mudstate.ntfy_nest_lev >= mudconf.ntfy_nest_lim) {
  456.     mudstate.ntfy_nest_lev--;
  457.     return;
  458.     }
  459.     /* If we want NOSPOOF output, generate it.  It is only needed if
  460.      * we are sending the message to the target object */
  461.  
  462.     if (key & MSG_ME) {
  463.     mp = msg_ns = alloc_lbuf("notify_check");
  464.     if (Nospoof(target) &&
  465.         (target != sender) &&
  466.         (target != mudstate.curr_enactor) &&
  467.         (target != mudstate.curr_player)) {
  468.  
  469.         /* I'd really like to use tprintf here but I can't
  470.          * because the caller may have.
  471.          * notify(target, tprintf(...)) is quite common in
  472.          * the code.
  473.          */
  474.  
  475.         tbuff = alloc_sbuf("notify_check.nospoof");
  476.         safe_chr('[', msg_ns, &mp);
  477.         safe_str(Name(sender), msg_ns, &mp);
  478.         *tbuff = '(';
  479.         tbuff[1] = '#';
  480.         ltos(&tbuff[2], sender);
  481.         safe_str(tbuff, msg_ns, &mp);
  482.         safe_chr(')', msg_ns, &mp);
  483.  
  484.         if (sender != Owner(sender)) {
  485.         safe_chr('{', msg_ns, &mp);
  486.         safe_str(Name(Owner(sender)), msg_ns, &mp);
  487.         safe_chr('}', msg_ns, &mp);
  488.         }
  489.         if (sender != mudstate.curr_enactor) {
  490.         strcpy(tbuff, (const char *) "<-(#");
  491.         ltos(&tbuff[4], mudstate.curr_enactor);
  492.         safe_str(tbuff, msg_ns, &mp);
  493.         safe_chr(')', msg_ns, &mp);
  494.         }
  495.         safe_str((char *) "] ", msg_ns, &mp);
  496.         free_sbuf(tbuff);
  497.     }
  498.     safe_long_str((char *) msg, msg_ns, &mp);
  499.     } else {
  500.     msg_ns = NULL;
  501.     }
  502.  
  503.     /* msg contains the raw message, msg_ns contains the NOSPOOFed msg */
  504.  
  505.     check_listens = Halted(target) ? 0 : 1;
  506.     switch (Typeof(target)) {
  507.     case TYPE_PLAYER:
  508.  
  509. #ifndef PUEBLO_SUPPORT
  510.     if (key & MSG_ME)
  511.         raw_notify(target, msg_ns);
  512. #else
  513.     if (key & MSG_ME) {
  514.  
  515.         if (key & MSG_HTML) {
  516.         raw_notify_html(target, msg_ns);
  517.         } else {
  518.         if (Html(target)) {
  519.         char *msg_ns_escaped;
  520.  
  521.         msg_ns_escaped = alloc_lbuf("notify_check_escape");
  522.         html_escape(msg_ns, msg_ns_escaped, 0);
  523.         raw_notify(target, msg_ns_escaped);
  524.         free_lbuf(msg_ns_escaped);
  525.         } else {
  526.             raw_notify(target, msg_ns);
  527.         }
  528.         }
  529.     }
  530. #endif /* ! PUEBLO_SUPPORT */
  531.     if (!mudconf.player_listen)
  532.         check_listens = 0;
  533.     case TYPE_THING:
  534.     case TYPE_ROOM:
  535.  
  536.     /* If we're in a pipe, objects can receive raw_notify()
  537.      * if they're not a player and connected (if we didn't
  538.      * do this, they'd be notified twice!)
  539.      */
  540.  
  541.     if (mudstate.inpipe &&
  542.         (!isPlayer(target) ||
  543.          (isPlayer(target) && !Connected(target)))) {
  544.         raw_notify(target, msg_ns);
  545.     }
  546.  
  547.     /* Forward puppet message if it is for me */
  548.  
  549.     has_neighbors = Has_location(target);
  550.     targetloc = where_is(target);
  551.     is_audible = Audible(target);
  552.  
  553.     if ((key & MSG_ME) &&
  554.         Puppet(target) &&
  555.         (target != Owner(target)) &&
  556.         ((key & MSG_PUP_ALWAYS) ||
  557.          ((targetloc != Location(Owner(target))) &&
  558.           (targetloc != Owner(target))))) {
  559.  
  560.         tp = tbuff = alloc_lbuf("notify_check.puppet");
  561.         safe_str(Name(target), tbuff, &tp);
  562.         safe_str((char *) "> ", tbuff, &tp);
  563.         safe_str(msg_ns, tbuff, &tp);
  564.         raw_notify(Owner(target), tbuff);
  565.         free_lbuf(tbuff);
  566.     }
  567.     /* Check for @Listen match if it will be useful */
  568.  
  569.     pass_listen = 0;
  570.     nargs = 0;
  571.     if (check_listens && (key & (MSG_ME | MSG_INV_L)) &&
  572.         H_Listen(target)) {
  573.         tp = atr_get(target, A_LISTEN, &aowner, &aflags);
  574.         if (*tp && wild_match(tp, (char *) msg, args, 10, 0)) {
  575.         for (nargs = 10;
  576.              nargs &&
  577.              (!args[nargs - 1] || !(*args[nargs - 1]));
  578.              nargs--);
  579.         pass_listen = 1;
  580.         }
  581.         free_lbuf(tp);
  582.     }
  583.     /* If we matched the @listen or are monitoring, check the
  584.      * USE lock
  585.      */
  586.  
  587.     pass_uselock = 0;
  588.     if ((key & MSG_ME) && check_listens &&
  589.         (pass_listen || Monitor(target)))
  590.         pass_uselock = could_doit(sender, target, A_LUSE);
  591.  
  592.     /* Process AxHEAR if we pass LISTEN, USElock and it's for me */
  593.  
  594.     if ((key & MSG_ME) && pass_listen && pass_uselock) {
  595.         if (sender != target)
  596.         did_it(sender, target, 0, NULL, 0, NULL,
  597.                A_AHEAR, args, nargs);
  598.         else
  599.         did_it(sender, target, 0, NULL, 0, NULL,
  600.                A_AMHEAR, args, nargs);
  601.         did_it(sender, target, 0, NULL, 0, NULL,
  602.            A_AAHEAR, args, nargs);
  603.     }
  604.     /* Get rid of match arguments. We don't need them anymore */
  605.  
  606.     if (pass_listen) {
  607.         for (i = 0; i < nargs; i++)
  608.         if (args[i] != NULL)
  609.             free_lbuf(args[i]);
  610.     }
  611.     /* Process ^-listens if for me, MONITOR, and we pass USElock */
  612.  
  613.     if ((key & MSG_ME) && pass_uselock && (sender != target) &&
  614.         Monitor(target)) {
  615.         (void) atr_match(target, sender,
  616.                  AMATCH_LISTEN, (char *) msg, (char *) msg, 0);
  617.     }
  618.     /* Deliver message to forwardlist members */
  619.  
  620.     if ((key & MSG_FWDLIST) && Audible(target) &&
  621.         check_filter(target, sender, A_FILTER, msg)) {
  622.         tbuff = dflt_from_msg(sender, target);
  623.         buff = add_prefix(target, sender, A_PREFIX,
  624.                   msg, tbuff);
  625.         free_lbuf(tbuff);
  626.  
  627.         fp = fwdlist_get(target);
  628.         if (fp) {
  629.         for (i = 0; i < fp->count; i++) {
  630.             recip = fp->data[i];
  631.             if (!Good_obj(recip) ||
  632.             (recip == target))
  633.             continue;
  634.             notify_check(recip, sender, buff,
  635.                (MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE));
  636.         }
  637.         }
  638.         free_lbuf(buff);
  639.     }
  640.     /* Deliver message through audible exits */
  641.  
  642.     if (key & MSG_INV_EXITS) {
  643.         DOLIST(obj, Exits(target)) {
  644.         recip = Location(obj);
  645.         if (Audible(obj) && ((recip != target) &&
  646.                 check_filter(obj, sender, A_FILTER, msg))) {
  647.             buff = add_prefix(obj, target,
  648.                       A_PREFIX, msg,
  649.                       "From a distance,");
  650.             notify_check(recip, sender, buff,
  651.              MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE);
  652.             free_lbuf(buff);
  653.         }
  654.         }
  655.     }
  656.     /* Deliver message through neighboring audible exits */
  657.  
  658.     if (has_neighbors &&
  659.         ((key & MSG_NBR_EXITS) ||
  660.          ((key & MSG_NBR_EXITS_A) && is_audible))) {
  661.  
  662.         /* If from inside, we have to add the prefix string of
  663.          * the container.
  664.          */
  665.  
  666.         if (key & MSG_S_INSIDE) {
  667.         tbuff = dflt_from_msg(sender, target);
  668.         buff = add_prefix(target, sender, A_PREFIX,
  669.                   msg, tbuff);
  670.         free_lbuf(tbuff);
  671.         } else {
  672.         buff = (char *) msg;
  673.         }
  674.  
  675.         DOLIST(obj, Exits(Location(target))) {
  676.         recip = Location(obj);
  677.         if (Good_obj(recip) && Audible(obj) &&
  678.             (recip != targetloc) &&
  679.             (recip != target) &&
  680.             check_filter(obj, sender, A_FILTER, msg)) {
  681.             tbuff = add_prefix(obj, target,
  682.                        A_PREFIX, buff,
  683.                        "From a distance,");
  684.             notify_check(recip, sender, tbuff,
  685.              MSG_ME | MSG_F_UP | MSG_F_CONTENTS | MSG_S_INSIDE);
  686.             free_lbuf(tbuff);
  687.         }
  688.         }
  689.         if (key & MSG_S_INSIDE) {
  690.         free_lbuf(buff);
  691.         }
  692.     }
  693.  
  694.     if (Bouncer(target))
  695.         pass_listen = 1;
  696.  
  697.     /* Deliver message to contents */
  698.  
  699.     if (((key & MSG_INV) || ((key & MSG_INV_L) && pass_listen)) &&
  700.         (check_filter(target, sender, A_INFILTER, msg))) {
  701.  
  702.         /* Don't prefix the message if we were given the
  703.          * MSG_NOPREFIX key.
  704.          */
  705.  
  706.         if (key & MSG_S_OUTSIDE) {
  707.         buff = add_prefix(target, sender, A_INPREFIX,
  708.                   msg, "");
  709.         } else {
  710.         buff = (char *) msg;
  711.         }
  712.         DOLIST(obj, Contents(target)) {
  713.         if (obj != target) {
  714. #ifdef PUEBLO_SUPPORT
  715.             notify_check(obj, sender, buff,
  716.                  MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE | (key & MSG_HTML));
  717. #else
  718.             notify_check(obj, sender, buff,
  719.                  MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE);
  720. #endif /* PUEBLO_SUPPORT */
  721.  
  722.         }
  723.         }
  724.         if (key & MSG_S_OUTSIDE)
  725.         free_lbuf(buff);
  726.     }
  727.     /* Deliver message to neighbors */
  728.  
  729.     if (has_neighbors &&
  730.         ((key & MSG_NBR) ||
  731.          ((key & MSG_NBR_A) && is_audible &&
  732.           check_filter(target, sender, A_FILTER, msg)))) {
  733.         if (key & MSG_S_INSIDE) {
  734.         tbuff = dflt_from_msg(sender, target);
  735.         buff = add_prefix(target, sender, A_PREFIX,
  736.                   msg, "");
  737.         free_lbuf(tbuff);
  738.         } else {
  739.         buff = (char *) msg;
  740.         }
  741.         DOLIST(obj, Contents(targetloc)) {
  742.         if ((obj != target) && (obj != targetloc)) {
  743.             notify_check(obj, sender, buff,
  744.                  MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE);
  745.         }
  746.         }
  747.         if (key & MSG_S_INSIDE) {
  748.         free_lbuf(buff);
  749.         }
  750.     }
  751.     /* Deliver message to container */
  752.  
  753.     if (has_neighbors &&
  754.         ((key & MSG_LOC) ||
  755.          ((key & MSG_LOC_A) && is_audible &&
  756.           check_filter(target, sender, A_FILTER, msg)))) {
  757.         if (key & MSG_S_INSIDE) {
  758.         tbuff = dflt_from_msg(sender, target);
  759.         buff = add_prefix(target, sender, A_PREFIX,
  760.                   msg, tbuff);
  761.         free_lbuf(tbuff);
  762.         } else {
  763.         buff = (char *) msg;
  764.         }
  765.         notify_check(targetloc, sender, buff,
  766.              MSG_ME | MSG_F_UP | MSG_S_INSIDE);
  767.         if (key & MSG_S_INSIDE) {
  768.         free_lbuf(buff);
  769.         }
  770.     }
  771.     }
  772.     if (msg_ns)
  773.     free_lbuf(msg_ns);
  774.     mudstate.ntfy_nest_lev--;
  775. }
  776.  
  777. void 
  778. notify_except(loc, player, exception, msg)
  779.     dbref loc, player, exception;
  780.     const char *msg;
  781. {
  782.     dbref first;
  783.  
  784.     if (loc != exception)
  785.     notify_check(loc, player, msg,
  786.           (MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A));
  787.     DOLIST(first, Contents(loc)) {
  788.     if (first != exception) {
  789.         notify_check(first, player, msg,
  790.              (MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE));
  791.     }
  792.     }
  793. }
  794.  
  795. void 
  796. notify_except2(loc, player, exc1, exc2, msg)
  797.     dbref loc, player, exc1, exc2;
  798.     const char *msg;
  799. {
  800.     dbref first;
  801.  
  802.     if ((loc != exc1) && (loc != exc2))
  803.     notify_check(loc, player, msg,
  804.           (MSG_ME_ALL | MSG_F_UP | MSG_S_INSIDE | MSG_NBR_EXITS_A));
  805.     DOLIST(first, Contents(loc)) {
  806.     if (first != exc1 && first != exc2) {
  807.         notify_check(first, player, msg,
  808.              (MSG_ME | MSG_F_DOWN | MSG_S_OUTSIDE));
  809.     }
  810.     }
  811. }
  812.  
  813. void 
  814. do_shutdown(player, cause, key, message)
  815.     dbref player, cause;
  816.     int key;
  817.     char *message;
  818. {
  819.     int fd;
  820.  
  821.     if (key & SHUTDN_COREDUMP) {
  822.     if (player != NOTHING) {
  823.         raw_broadcast(0, "Game: Aborted by %s", Name(Owner(player)));
  824.         STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
  825.         log_text((char *) "Abort and coredump by ");
  826.         log_name(player);
  827.         ENDLOG
  828.     }
  829.     /* Don't bother to even shut down the network or dump. Die. Die now. */
  830.     abort();
  831.     }
  832.  
  833.     if (player != NOTHING) {
  834.     raw_broadcast(0, "Game: Shutdown by %s", Name(Owner(player)));
  835.     STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
  836.         log_text((char *) "Shutdown by ");
  837.     log_name(player);
  838.     ENDLOG
  839.     } else {
  840.     raw_broadcast(0, "Game: Fatal Error: %s", message);
  841.     STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
  842.         log_text((char *) "Fatal error: ");
  843.     log_text(message);
  844.     ENDLOG
  845.     }
  846.     STARTLOG(LOG_ALWAYS, "WIZ", "SHTDN")
  847.     log_text((char *) "Shutdown status: ");
  848.     log_text(message);
  849.     ENDLOG
  850.     fd = tf_open(mudconf.status_file, O_RDWR | O_CREAT | O_TRUNC);
  851.     (void) write(fd, message, strlen(message));
  852.     (void) write(fd, (char *) "\n", 1);
  853.     tf_close(fd);
  854.  
  855.     /* Do we perform a normal or an emergency shutdown?  Normal shutdown
  856.      * is handled by exiting the main loop in shovechars, emergency
  857.      * shutdown is done here.
  858.      */
  859.  
  860.     if (key & SHUTDN_PANIC) {
  861.  
  862.     /* Close down the network interface */
  863.  
  864.     emergency_shutdown();
  865.  
  866.     /* Close the attribute text db and dump the header db */
  867.  
  868.     pcache_sync();
  869.     SYNC;
  870.     CLOSE;
  871.     STARTLOG(LOG_ALWAYS, "DMP", "PANIC")
  872.         log_text((char *) "Panic dump: ");
  873.     log_text(mudconf.crashdb);
  874.     ENDLOG
  875.         dump_database_internal(1);
  876.     STARTLOG(LOG_ALWAYS, "DMP", "DONE")
  877.         log_text((char *) "Panic dump complete: ");
  878.     log_text(mudconf.crashdb);
  879.     ENDLOG
  880.     }
  881.     /* Set up for normal shutdown */
  882.  
  883.     mudstate.shutdown_flag = 1;
  884.     return;
  885. }
  886.  
  887. static void 
  888. dump_database_internal(dump_type)
  889.     int dump_type;
  890. {
  891.     char tmpfile[256], prevfile[256];
  892.     FILE *f;
  893.  
  894.     if (dump_type == 1) {
  895.  
  896.     /* Panic dump! */
  897.  
  898.     unlink(mudconf.crashdb);
  899.     f = tf_fopen(mudconf.crashdb, O_WRONLY | O_CREAT | O_TRUNC);
  900.     if (f != NULL) {
  901.         db_write(f, F_MUSH, OUTPUT_VERSION | OUTPUT_FLAGS);
  902.         tf_fclose(f);
  903.     } else {
  904.         log_perror("DMP", "FAIL", "Opening crash file",
  905.                mudconf.crashdb);
  906.     }
  907.     return;
  908.     }
  909.  
  910.     if (dump_type == 2) {
  911.     
  912.     /* Dump for restart. First, try to write a flatfile. */
  913.  
  914.     f = tf_fopen(mudconf.indb, O_WRONLY | O_CREAT | O_TRUNC);
  915.     if (f != NULL) {
  916.         db_write(f, F_MUSH, OUTPUT_VERSION | OUTPUT_FLAGS);
  917.         tf_fclose(f);
  918.     } else {
  919.         log_perror("DMP", "FAIL", "Opening restart file",
  920.                mudconf.indb);
  921.     }
  922.     }
  923.  
  924.     sprintf(prevfile, "%s.prev", mudconf.outdb);
  925. #ifdef VMS
  926.     sprintf(tmpfile, "%s.-%d-", mudconf.outdb, mudstate.epoch - 1);
  927.     unlink(tmpfile);        /* nuke our predecessor */
  928.     sprintf(tmpfile, "%s.-%d-", mudconf.outdb, mudstate.epoch);
  929. #else
  930.     sprintf(tmpfile, "%s.#%d#", mudconf.outdb, mudstate.epoch - 1);
  931.     unlink(tmpfile);        /* nuke our predecessor */
  932.     sprintf(tmpfile, "%s.#%d#", mudconf.outdb, mudstate.epoch);
  933.  
  934. #endif /* VMS */
  935.  
  936.     f = tf_fopen(tmpfile, O_WRONLY | O_CREAT | O_TRUNC);
  937.     if (f) {
  938.     db_write(f, F_MUSH, OUTPUT_VERSION | OUTPUT_FLAGS);
  939.     tf_fclose(f);
  940. #ifdef OS2
  941.         unlink(prevfile);  /* OS/2 won't rename over an existing file */
  942. #endif /* OS2 */
  943.     rename(mudconf.outdb, prevfile);
  944.     if (rename(tmpfile, mudconf.outdb) < 0)
  945.         log_perror("SAV", "FAIL",
  946.                "Renaming output file to DB file", tmpfile);
  947.     } else {
  948.     log_perror("SAV", "FAIL", "Opening", tmpfile);
  949.     }
  950. }
  951.  
  952. void 
  953. NDECL(dump_database)
  954. {
  955.     char
  956.         *buff;
  957.  
  958.     mudstate.epoch++;
  959.     mudstate.dumping = 1;
  960.     buff = alloc_mbuf("dump_database");
  961. #ifdef VMS
  962.     sprintf(buff, "%s.-%d-", mudconf.outdb, mudstate.epoch);
  963. #else
  964.     sprintf(buff, "%s.#%d#", mudconf.outdb, mudstate.epoch);
  965. #endif /* VMS */
  966.     STARTLOG(LOG_DBSAVES, "DMP", "DUMP")
  967.     log_text((char *) "Dumping: ");
  968.     log_text(buff);
  969.     ENDLOG
  970.     pcache_sync();
  971.     SYNC;
  972.     dump_database_internal(0);
  973.     STARTLOG(LOG_DBSAVES, "DMP", "DONE")
  974.     log_text((char *) "Dump complete: ");
  975.         log_text(buff);
  976.     ENDLOG
  977.     free_mbuf(buff);
  978.     mudstate.dumping = 0;
  979. }
  980.  
  981. void 
  982. fork_and_dump(key)
  983.     int key;
  984. {
  985.     int child;
  986.     char *buff;
  987.  
  988.     if (*mudconf.dump_msg)
  989.     raw_broadcast(0, "%s", mudconf.dump_msg);
  990.     mudstate.epoch++;
  991.     mudstate.dumping = 1;
  992.     buff = alloc_mbuf("fork_and_dump");
  993. #ifdef VMS
  994.     sprintf(buff, "%s.-%d-", mudconf.outdb, mudstate.epoch);
  995. #else
  996.     sprintf(buff, "%s.#%d#", mudconf.outdb, mudstate.epoch);
  997. #endif /* VMS */
  998.     STARTLOG(LOG_DBSAVES, "DMP", "CHKPT")
  999.     if (!key || (key & DUMP_TEXT)) {
  1000.     log_text((char *) "SYNCing");
  1001.     if (!key || (key & DUMP_STRUCT))
  1002.         log_text((char *) " and ");
  1003.     }
  1004.     if (!key || (key & DUMP_STRUCT)) {
  1005.     log_text((char *) "Checkpointing: ");
  1006.     log_text(buff);
  1007.     }
  1008.     ENDLOG
  1009.     free_mbuf(buff);
  1010.     al_store();            /* Save cached modified attribute list */
  1011.     if (!key || (key & DUMP_TEXT))
  1012.     pcache_sync();
  1013.     SYNC;
  1014.     if (!key || (key & DUMP_STRUCT)) {
  1015. #ifndef VMS
  1016.     if (mudconf.fork_dump) {
  1017.         if (mudconf.fork_vfork) {
  1018.         child = vfork();
  1019.         } else {
  1020.         child = fork();
  1021.         }
  1022.     } else {
  1023.         child = 0;
  1024.     }
  1025. #else
  1026.     child = 0;
  1027. #endif /* VMS */
  1028.     if (child == 0) {
  1029.         dump_database_internal(0);
  1030. #ifndef VMS
  1031.         if (mudconf.fork_dump)
  1032.         _exit(0);
  1033. #endif /* VMS */
  1034.     } else if (child < 0) {
  1035.         log_perror("DMP", "FORK", NULL, "fork()");
  1036.     }
  1037.     }
  1038.  
  1039.     if (!mudconf.fork_dump)
  1040.     mudstate.dumping = 0;
  1041.  
  1042.     if (*mudconf.postdump_msg)
  1043.     raw_broadcast(0, "%s", mudconf.postdump_msg);
  1044. }
  1045.  
  1046. static int 
  1047. NDECL(load_game)
  1048. {
  1049.     FILE *f = NULL;
  1050.     char infile[256];
  1051.     int db_format, db_version, db_flags;
  1052.  
  1053.     strcpy(infile, mudconf.indb);
  1054.     if ((f = tf_fopen(mudconf.indb, O_RDONLY)) == NULL)
  1055.     return -1;
  1056.  
  1057.     /* ok, read it in */
  1058.  
  1059.     STARTLOG(LOG_STARTUP, "INI", "LOAD")
  1060.     log_text((char *) "Loading: ");
  1061.     log_text(infile);
  1062.     ENDLOG
  1063.  
  1064.     if (db_read(f, &db_format, &db_version, &db_flags) < 0) {
  1065.     STARTLOG(LOG_ALWAYS, "INI", "FATAL")
  1066.         log_text((char *) "Error loading ");
  1067.     log_text(infile);
  1068.     ENDLOG
  1069.         return -1;
  1070.     }
  1071.     STARTLOG(LOG_STARTUP, "INI", "LOAD")
  1072.     log_text((char *) "Load complete.");
  1073.     ENDLOG
  1074.  
  1075.     /* everything ok */
  1076.  
  1077.     tf_fclose(f);
  1078.     return (0);
  1079. }
  1080.  
  1081. /* ----------------------------------------------------------------------
  1082.  * do_restart:  Routines to gracefully restart.
  1083.  */
  1084.  
  1085. void do_restart(player, cause, key)
  1086.     dbref player, cause;
  1087.     int key;
  1088. {
  1089.     char indb[PBUF_SIZE], outdb[PBUF_SIZE];
  1090.     int stat;
  1091.  
  1092.     if (mudstate.dumping) {
  1093.     notify(player, "Dumping. Please try again later.");
  1094.     return;
  1095.     }
  1096.  
  1097.     raw_broadcast(0, "Game: Restart by %s, please wait.",
  1098.           Name(Owner(player)));
  1099.  
  1100.     STARTLOG(LOG_ALWAYS, "WIZ", "RSTRT")
  1101.     log_text((char *)"Restart by ");
  1102.         log_name(player);
  1103.     ENDLOG
  1104.  
  1105.     dump_database_internal(2);
  1106.  
  1107.     SYNC;
  1108.     CLOSE;
  1109.  
  1110.     alarm(0);
  1111.     dump_restart_db();
  1112.     execl(mudconf.exec_path, mudconf.exec_path, mudconf.config_file,
  1113.       (char *) NULL);
  1114. }
  1115.  
  1116. /* ----------------------------------------------------------------------
  1117.  * Misc. utilities.
  1118.  */
  1119.  
  1120. /* match a list of things */
  1121.  
  1122. int 
  1123. list_check(thing, player, type, str, raw_str, check_parent, stop_status)
  1124.     dbref thing, player;
  1125.     char type, *str, *raw_str;
  1126.     int check_parent;
  1127.     int *stop_status;
  1128. {
  1129.     int match;
  1130.  
  1131.     match = 0;
  1132.     while (thing != NOTHING) {
  1133.     if ((thing != player) &&
  1134.         (atr_match(thing, player, type, str, raw_str, check_parent) > 0)) {
  1135.         match = 1;
  1136.         if (Stop_Match(thing)) {
  1137.         *stop_status = 1;
  1138.         return match;
  1139.         }
  1140.     }
  1141.     thing = Next(thing);
  1142.     }
  1143.     return match;
  1144. }
  1145.  
  1146. int 
  1147. Hearer(thing)
  1148.     dbref thing;
  1149. {
  1150.     char *as, *buff, *s;
  1151.     dbref aowner;
  1152.     int attr, aflags;
  1153.     ATTR *ap;
  1154.  
  1155.     if (Connected(thing) || Puppet(thing))
  1156.     return 1;
  1157.  
  1158.     if (mudstate.inpipe && (thing == mudstate.poutobj))
  1159.     return 1;
  1160.  
  1161.     if (Monitor(thing))
  1162.     buff = alloc_lbuf("Hearer");
  1163.     else
  1164.     buff = NULL;
  1165.     atr_push();
  1166.     for (attr = atr_head(thing, &as); attr; attr = atr_next(&as)) {
  1167.     if (attr == A_LISTEN) {
  1168.         if (buff)
  1169.         free_lbuf(buff);
  1170.         atr_pop();
  1171.         return 1;
  1172.     }
  1173.     if (Monitor(thing)) {
  1174.         ap = atr_num(attr);
  1175.         if (!ap || (ap->flags & AF_NOPROG))
  1176.         continue;
  1177.  
  1178.         atr_get_str(buff, thing, attr, &aowner, &aflags);
  1179.  
  1180.         /* Make sure we can execute it */
  1181.  
  1182.         if ((buff[0] != AMATCH_LISTEN) || (aflags & AF_NOPROG))
  1183.         continue;
  1184.  
  1185.         /* Make sure there's a : in it */
  1186.  
  1187.         for (s = buff + 1; *s && (*s != ':'); s++);
  1188.         if (s) {
  1189.         free_lbuf(buff);
  1190.         atr_pop();
  1191.         return 1;
  1192.         }
  1193.     }
  1194.     }
  1195.     if (buff)
  1196.     free_lbuf(buff);
  1197.     atr_pop();
  1198.     return 0;
  1199. }
  1200.  
  1201. void 
  1202. do_rwho(player, cause, key)
  1203.     dbref player, cause;
  1204.     int key;
  1205. {
  1206. #ifdef RWHO_IN_USE
  1207.     if (key == RWHO_START) {
  1208.     if (!mudstate.rwho_on) {
  1209.         rwhocli_setup(mudconf.rwho_host,
  1210.               mudconf.rwho_info_port,
  1211.               mudconf.rwho_pass, mudconf.mud_name,
  1212.               mudstate.short_ver);
  1213.         rwho_update();
  1214.         if (!Quiet(player))
  1215.         notify(player, "RWHO transmission started.");
  1216.         mudstate.rwho_on = 1;
  1217.     } else {
  1218.         notify(player, "RWHO transmission already on.");
  1219.     }
  1220.     } else if (key == RWHO_STOP) {
  1221.     if (mudstate.rwho_on) {
  1222.         rwhocli_shutdown();
  1223.         if (!Quiet(player))
  1224.         notify(player, "RWHO transmission stopped.");
  1225.         mudstate.rwho_on = 0;
  1226.     } else {
  1227.         notify(player, "RWHO transmission already off.");
  1228.     }
  1229.     } else {
  1230.     notify(player, "Illegal combination of switches.");
  1231.     }
  1232. #else
  1233.     notify(player, "RWHO support has not been compiled in to the server.");
  1234. #endif
  1235.  
  1236. }
  1237.  
  1238. void 
  1239. do_readcache(player, cause, key)
  1240.     dbref player, cause;
  1241.     int key;
  1242. {
  1243.     helpindex_load(player);
  1244.     fcache_load(player);
  1245. }
  1246.  
  1247. static void 
  1248. NDECL(process_preload)
  1249. {
  1250.     dbref thing, parent, aowner;
  1251.     int aflags, lev, i;
  1252.     char *tstr;
  1253.     FWDLIST *fp;
  1254.  
  1255.     fp = (FWDLIST *) alloc_lbuf("process_preload.fwdlist");
  1256.     tstr = alloc_lbuf("process_preload.string");
  1257.     i = 0;
  1258.     DO_WHOLE_DB(thing) {
  1259.  
  1260.     /* Ignore GOING objects */
  1261.  
  1262.     if (Going(thing))
  1263.         continue;
  1264.  
  1265.     do_top(10);
  1266.  
  1267.     /* Look for a STARTUP attribute in parents */
  1268.  
  1269.     ITER_PARENTS(thing, parent, lev) {
  1270.         if (Flags(thing) & HAS_STARTUP) {
  1271.         did_it(Owner(thing), thing, 0, NULL, 0, NULL,
  1272.                A_STARTUP, (char **) NULL, 0);
  1273.         /* Process queue entries as we add them */
  1274.  
  1275.         do_second();
  1276.         do_top(10);
  1277.         cache_reset(0);
  1278.         break;
  1279.         }
  1280.     }
  1281.  
  1282.     /* Look for a FORWARDLIST attribute */
  1283.  
  1284.     if (H_Fwdlist(thing)) {
  1285.         (void) atr_get_str(tstr, thing, A_FORWARDLIST,
  1286.                    &aowner, &aflags);
  1287.         if (*tstr) {
  1288.         fwdlist_load(fp, GOD, tstr);
  1289.         if (fp->count > 0)
  1290.             fwdlist_set(thing, fp);
  1291.         cache_reset(0);
  1292.         }
  1293.     }
  1294.     }
  1295.     free_lbuf(fp);
  1296.     free_lbuf(tstr);
  1297. }
  1298.  
  1299. #ifndef VMS
  1300. void
  1301. #endif /* VMS */
  1302. main(argc, argv)
  1303.     int argc;
  1304.     char *argv[];
  1305. {
  1306.     int mindb;
  1307.  
  1308.     if ((argc > 2) && (!strcmp(argv[1], "-s") && (argc > 3))) {
  1309.     fprintf(stderr, "Usage: %s [-s] [config-file]\n", argv[0]);
  1310.     exit(1);
  1311.     }
  1312. /*
  1313.     fclose(stdin);
  1314.     fclose(stdout);
  1315. */
  1316.     tf_init();
  1317. #ifdef IN_MEM_COMPRESSION
  1318.     init_string_compress();
  1319. #endif
  1320.     mindb = 0;            /* Are we creating a new db? */
  1321.     time(&mudstate.start_time);
  1322.     mudstate.restart_time = mudstate.start_time;
  1323.     pool_init(POOL_LBUF, LBUF_SIZE);
  1324.     pool_init(POOL_MBUF, MBUF_SIZE);
  1325.     pool_init(POOL_SBUF, SBUF_SIZE);
  1326.     pool_init(POOL_BOOL, sizeof(struct boolexp));
  1327.  
  1328.     pool_init(POOL_DESC, sizeof(DESC));
  1329.     pool_init(POOL_QENTRY, sizeof(BQUE));
  1330.     tcache_init();
  1331.     pcache_init();
  1332.     cf_init();
  1333.     init_rlimit();
  1334.     init_cmdtab();
  1335.     init_logout_cmdtab();
  1336.     init_flagtab();
  1337.     init_functab();
  1338.     init_attrtab();
  1339.     init_version();
  1340.     hashinit(&mudstate.player_htab, 511);
  1341.     nhashinit(&mudstate.fwdlist_htab, 57);
  1342.     nhashinit(&mudstate.objstack_htab, 57);
  1343.     nhashinit(&mudstate.parent_htab, 57);
  1344.     nhashinit(&mudstate.desc_htab, 37);
  1345.  
  1346.     if (argc > 1 && !strcmp(argv[1], "-s")) {
  1347.     mindb = 1;
  1348.     if (argc == 3)
  1349.         cf_read(argv[2]);
  1350.     else
  1351.         cf_read((char *) CONF_FILE);
  1352.     } else if (argc == 2) {
  1353.     cf_read(argv[1]);
  1354.     } else {
  1355.     cf_read((char *) CONF_FILE);
  1356.     }
  1357.  
  1358.     /* Note that if either the relative path to the executable or the
  1359.      * relative path to the conf file exceeds the buffer size, that
  1360.      * You Have A Problem -- @restart will not work for you.
  1361.      */
  1362.     strncpy(mudconf.exec_path, argv[0], PBUF_SIZE - 1);
  1363.     mudconf.exec_path[PBUF_SIZE - 1] = '\0';
  1364.  
  1365.     fcache_init();
  1366.     helpindex_init();
  1367.  
  1368.     if (mindb)
  1369.     unlink(mudconf.gdbm);
  1370.     if (init_gdbm_db(mudconf.gdbm) < 0) {
  1371.     STARTLOG(LOG_ALWAYS, "INI", "LOAD")
  1372.         log_text((char *) "Couldn't load text database: ");
  1373.     log_text(mudconf.gdbm);
  1374.     ENDLOG
  1375.         exit(2);
  1376.     }
  1377.     if (mindb)
  1378.     db_make_minimal();
  1379.     else if (load_game() < 0) {
  1380.     STARTLOG(LOG_ALWAYS, "INI", "LOAD")
  1381.         log_text((char *) "Couldn't load: ");
  1382.     log_text(mudconf.indb);
  1383.     ENDLOG
  1384.         exit(2);
  1385.     }
  1386.     srandom(getpid());
  1387.     set_signals();
  1388.  
  1389.     /* Do a consistency check and set up the freelist */
  1390.  
  1391.     do_dbck(NOTHING, NOTHING, 0);
  1392.  
  1393.     /* Reset all the hash stats */
  1394.  
  1395.     hashreset(&mudstate.command_htab);
  1396.     hashreset(&mudstate.logout_cmd_htab);
  1397.     hashreset(&mudstate.func_htab);
  1398.     hashreset(&mudstate.flags_htab);
  1399.     hashreset(&mudstate.attr_name_htab);
  1400.     nhashreset(&mudstate.attr_num_htab);
  1401.     hashreset(&mudstate.player_htab);
  1402.     nhashreset(&mudstate.fwdlist_htab);
  1403.     nhashreset(&mudstate.objstack_htab);
  1404.     hashreset(&mudstate.news_htab);
  1405.     hashreset(&mudstate.help_htab);
  1406.     hashreset(&mudstate.wizhelp_htab);
  1407.     nhashreset(&mudstate.desc_htab);
  1408.  
  1409.     for (mindb = 0; mindb < MAX_GLOBAL_REGS; mindb++)
  1410.     mudstate.global_regs[mindb] = alloc_lbuf("main.global_reg");
  1411.     mudstate.now = time(NULL);
  1412.  
  1413.     process_preload();
  1414.     STARTLOG(LOG_STARTUP, "INI", "LOAD")
  1415.     log_text((char *) "Startup processing complete.");
  1416.     ENDLOG
  1417.  
  1418.     load_restart_db();
  1419.  
  1420.     if (mudconf.rwho_transmit)
  1421.     do_rwho(NOTHING, NOTHING, RWHO_START);
  1422.  
  1423.     /* go do it */
  1424.  
  1425.     mudstate.now = time(NULL);
  1426.     init_timer();
  1427.     shovechars(mudconf.port);
  1428.  
  1429.     close_sockets(0, (char *) "Going down - Bye");
  1430.     dump_database();
  1431.     CLOSE;
  1432.     exit(0);
  1433. }
  1434.  
  1435. static void 
  1436. NDECL(init_rlimit)
  1437. {
  1438. #if defined(HAVE_SETRLIMIT) && defined(RLIMIT_NOFILE)
  1439.     struct rlimit *rlp;
  1440.  
  1441.     rlp = (struct rlimit *) alloc_lbuf("rlimit");
  1442.  
  1443.     if (getrlimit(RLIMIT_NOFILE, rlp)) {
  1444.     log_perror("RLM", "FAIL", NULL, "getrlimit()");
  1445.     free_lbuf(rlp);
  1446.     return;
  1447.     }
  1448.     rlp->rlim_cur = rlp->rlim_max;
  1449.     if (setrlimit(RLIMIT_NOFILE, rlp))
  1450.     log_perror("RLM", "FAIL", NULL, "setrlimit()");
  1451.     free_lbuf(rlp);
  1452. #else
  1453. #if defined(_SEQUENT_) && defined(NUMFDS_LIMIT)
  1454.     setdtablesize(NUMFDS_LIMIT);
  1455. #endif /* Sequent and unlimiting #define'd */
  1456. #endif /* HAVE_SETRLIMIT */
  1457. }
  1458.