home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / t / toaster.zip / Compat / master.c < prev    next >
C/C++ Source or Header  |  1991-12-31  |  11KB  |  423 lines

  1. /*
  2.  * MOVE THIS FILE TO /obj/master.c !
  3.  *
  4.  * This is the LPmud master object, used from version 3.0.
  5.  * It is the second object loaded after void.c.
  6.  * Everything written with 'write()' at startup will be printed on
  7.  * stdout.
  8.  * 1.  reset() will be called first.
  9.  * 2. flag() will be called once for every argument to the flag -f
  10.  *     supplied to 'parse'.
  11.  * 3. epilog() will be called.
  12.  * 4. The game will enter multiuser mode, and enable log in.
  13.  *
  14.  * This version of master.c is specifically designed to be used with mudlib
  15.  * 2.4.6 or earlier. The master.c for mudlib 3.0 will be supplied with
  16.  * that source.
  17.  *
  18.  * One thing is different in the file access permission system in game
  19.  * driver 3.0. The master object can read and write any file.
  20.  * That means that all occurences of such
  21.  * manipulations below must be carefully garded against calls from
  22.  * elsewhere. Always make a comment at the start of a function that is doing
  23.  * such things, to make it easy for other to quickly assert security.
  24.  * The master object can of course not access files above the mudlib
  25.  * directory.
  26.  */
  27.  
  28. #include "master.h"
  29.  
  30. /*
  31.  * To test a new function xx in object yy, do
  32.  * parse "-fcall yy xx arg" "-fshutdown"
  33.  */
  34. void flag(string str) {
  35.     string file, arg;
  36.     int num_arg;
  37.  
  38.     if (sscanf(str, "for %d", num_arg) == 1) {
  39.     write("Got : " + catch(this_object()->xx(num_arg)) + "\n");
  40.     return;
  41.     }
  42.     if (str == "shutdown") {
  43.     shutdown();
  44.     return;
  45.     }
  46.     if (str == "version") {
  47.         write(version() + "\n");
  48.         return;
  49.     }
  50.     if (sscanf(str, "dhrystone %d", arg) == 1) {
  51.     call_other("players/lars/dry", "main", arg);
  52.     return;
  53.     }
  54.     if (sscanf(str, "echo %s", arg) == 1) {
  55.     write(arg + "\n");
  56.     return;
  57.     }
  58.     if (sscanf(str, "call %s %s", file, arg) == 2) {
  59.     arg = (string)call_other(file, arg);
  60.     write("Got " + arg + " back.\n");
  61.     return;
  62.     }
  63.     write("master: Unknown flag " + str + "\n");
  64. }
  65.  
  66. /*
  67.  * This function is called every time a player connects.
  68.  * input_to() can't be called from here.
  69.  */
  70. object connect() {
  71.     object ob;
  72.     string ret;
  73.  
  74.     ret = (string)catch(ob = clone_object("obj/player"));
  75.     write("\n");
  76.     if (ret) {
  77.     write(ret + "\n");
  78.     return 0;
  79.     }
  80.     return ob;
  81. }
  82.  
  83. int xx(int arg)
  84. {
  85.     return 1/arg;
  86. }
  87.  
  88. /*
  89.  * This function is called for a wizard that has dropped a castle.
  90.  * The argument is the file name of the object that called create_wizard().
  91.  * Verify that this object is allowed to do this call.
  92.  */
  93. int verify_create_wizard(object ob) {
  94.     int dummy;
  95.  
  96.     write(typeof(ob)+"\n");
  97.     if (sscanf(file_name(ob), "room/port_castle#%d", dummy) == 1)
  98.     return 1;
  99.     return 0;
  100. }
  101.  
  102. /*
  103.  * Get the owner of a file. This is called from the game driver, so as
  104.  * to be able to know which wizard should have the error.
  105.  */
  106. string get_wiz_name(string file) {
  107.     string name, rest;
  108.  
  109.     if (sscanf(file, "players/%s/%s", name, rest) == 2) {
  110.     return name;
  111.     }
  112.     return 0;
  113. }
  114.  
  115. /*
  116.  * Write an error message into a log file. The error occured in the object
  117.  * 'file', giving the error message 'message'.
  118.  */
  119. void log_error(string file, string message)
  120. {
  121.     string name;
  122.  
  123.     name = get_wiz_name(file);
  124.     if (name == 0)
  125.     name = "log";
  126.     log_file(name, message);
  127. }
  128.  
  129. /* save_ed_setup and restore_ed_setup are called by the ed to maintain
  130.    individual options settings. These functions are located in the master
  131.    object so that the local gods can decide what strategy they want to use.
  132.    suggestions:
  133.     A setup file for every wizard.
  134.         advantages:    transparent to the user
  135.                 independent of wizard count
  136.         disadvantage:    extra file access at ed invocation
  137.     An array in the master object, wizards are searched by member_array
  138.         advantage:    easy to implement
  139.         disadvantage:    performance degradation with high wizard counts
  140.     An AVL-tree to access wizards by name
  141.         advantage:    can fit any need
  142.         disadvantage:    hard to implement, will need more overhead on
  143.                 small and medium muds than it can ever make
  144.                 good by lg(wizcount) complexity
  145.     Dedicated flags in every wizard object, inherited from /obj/living
  146.         advantages:    easy to implement ( as shown here)
  147.                 independent of wizard count
  148.                 Will also work for nonm-wizards.
  149.         disadvantage:    care has to be taken to avoid collision with
  150.                 other uses of the /obj/living flags.          */
  151.  
  152. #if 0 /* Dedicated flags not used. A save file method is used below */
  153.  
  154. #define FIRST_ED_FLAG 0 /* adjust this value so that no flags are clobbered */
  155. #define NUM_ED_FLAGS 10 
  156. int save_ed_setup(object wiz, int setup) {
  157.     int mask,i;
  158.  
  159.     for (mask=1,i=FIRST_ED_FLAG;i<FIRST_ED_FLAG+NUM_ED_FLAGS;mask<<=1,i++) {
  160.     if ( setup & mask ) wiz->set_flag(i);
  161.     else wiz->clear_flag(i);
  162.     }
  163.     return 1; /* function is defined, success */
  164. }
  165.  
  166. int retrieve_ed_setup(object wiz) {
  167.     int i,setup;
  168.  
  169.     for(i=FIRST_ED_FLAG+NUM_ED_FLAGS;i>FIRST_ED_FLAG;) {
  170.     setup+=setup+wiz->test_flag(--i);
  171.     }
  172.     return setup;
  173. }
  174.  
  175. #endif /* 0 */
  176.  
  177. /*
  178.  * The wizard object 'who' wants to save his ed setup. It is saved in the
  179.  * file /players/wiz_name/.edrc . A test should be added to make sure it is
  180.  * a call from a wizard.
  181.  *
  182.  * Don't care to prevent unauthorized access of this file. Only make sure
  183.  * that a number is given as argument.
  184.  */
  185. int save_ed_setup(object who, int code) {
  186.     string file;
  187.  
  188.     if (!intp(code))
  189.     return 0;
  190.     file = "/players/" + lower_case((string)who->query_name()) + "/.edrc";
  191.     rm(file);
  192.     return write_file(file, code + "");
  193. }
  194.  
  195. /*
  196.  * Retrieve the ed setup. No meaning to defend this file read from
  197.  * unauthorized access.
  198.  */
  199. int retrieve_ed_setup(object who) {
  200.     string file;
  201.     int code;
  202.  
  203.     file = "/players/" + lower_case((string)who->query_name()) + "/.edrc";
  204.     if (!exists(file))
  205.     return 0;
  206.     sscanf(read_file(file), "%d", code);
  207.     return code;
  208. }
  209.  
  210. /*
  211.  * Create a home dritectory and a castle for a new wizard. It is called
  212.  * automatically from create_wizard(). We don't use the 'domain' info.
  213.  * The create_wizard() efun is not really needed any longer, as a call
  214.  * could be done to this function directly.
  215.  *
  216.  * This function can create directories and files in /players. It is
  217.  * garded from calls from the wrong places.
  218.  */
  219. string master_create_wizard(string owner, string domain, object caller) {
  220.     string def_castle;
  221.     string dest, castle, wizard, workroom;
  222.     object player;
  223.  
  224.     player = find_player(owner);
  225.     if (!player)
  226.     return 0;
  227.     if (!verify_create_wizard(caller)) {
  228.     tell_object(player, "That is an illegal attempt!\n");
  229.     return 0;
  230.     }
  231.     if (caller != previous_object()) {
  232.     tell_object(player, "Faked call!\n");
  233.     return 0;
  234.     }
  235. #ifdef PLAYER_DIR
  236.     wizard = "/" + PLAYER_DIR + "/" + owner;
  237.     castle = "/" + PLAYER_DIR + "/" + owner + "/castle.c";
  238. #else
  239.     wizard = "/players/" + owner;
  240.     castle = "/players/" + owner + "/castle.c";
  241. #endif
  242. #ifdef DEFAULT_WORKROOM
  243. #ifdef PLAYER_DIR
  244.     workroom = "/" + PLAYER_DIR + "/" + owner + "/workroom.c";
  245. #else
  246.     workroom = "/players/" + owner + "/workroom.c";
  247. #endif
  248. #endif
  249.     if (file_size(wizard) == -1) {
  250.     tell_object(player, "You now have a home drirectory: " +
  251.             wizard + "\n");
  252.     mkdir(wizard);
  253.     }
  254. #ifdef CASTLE_ROOM
  255.     dest = CASTLE_ROOM;
  256. #else
  257.     dest = file_name(environment(player));
  258. #endif
  259.     def_castle = "#define NAME \"" + capitalize(owner) + "\"\n#define DEST \"" +
  260. #ifdef DEFAULT_CASTLE
  261.     dest + "\"\n" + read_file(DEFAULT_CASTLE);
  262. #else
  263.     dest + "\"\n" + read_file("room/def_castle.c");
  264. #endif
  265.     if (file_size(castle) > 0) {
  266.     tell_object(player, "You already had a castle !\n");
  267.     } else {
  268.     /* The master object can do this! */
  269.     if (write_file(castle, def_castle)) {
  270.         tell_object(player, "You now have a castle: " + castle + "\n");
  271. #ifdef INIT_FILE
  272.         if (!write_file(INIT_FILE, extract(castle, 1) + "\n"))
  273. #else
  274.         if (!write_file("/room/init_file", extract(castle, 1) + "\n"))
  275. #endif
  276.         tell_object(player, "It couldn't be loaded automatically!\n");
  277.     } else {
  278.         tell_object(player, "Failed to make a castle for you!\n");
  279.     }
  280.     }
  281. #ifdef DEFAULT_WORKROOM
  282.     if (file_size(workroom) > 0)
  283.     tell_object(player, "You already had a workroom!\n");
  284.     else {
  285.         if(!cp("/" + DEFAULT_WORKROOM, workroom))
  286.             tell_object(player, "Failed to make a workroom for you!\n");
  287.     }
  288. #endif
  289.     return castle;
  290. }
  291.  
  292. /*
  293.  * When an object is destructed, this function is called with every
  294.  * item in that room. We get the chance to save players !
  295.  */
  296. void destruct_environment_of(object ob) {
  297.     if (!ob || !interactive(ob))
  298.     return;
  299.     tell_object(ob, "Everything you see is disolved. Luckily, you are transported somewhere...\n");
  300.     ob->move_player("abruptly#room/void");
  301. }
  302.  
  303. string *define_include_dirs() {
  304. #ifdef COMPAT_FLAG
  305.     return ({"room", "obj", "/worf/lpmud/secure"});
  306. #else
  307.     return ({"room", "sys"});
  308. #endif
  309. }
  310.  
  311. /*
  312.  * The master object is asked if it is ok to shadow object ob. Use
  313.  * previous_object() to find out who is asking.
  314.  *
  315.  * In this example, we allow shadowing as long as the victim object
  316.  * hasn't denied it with a query_prevent_shadow() returning 1, and
  317.  * as long as the shadow doesn't redefine valid_read or valid_write.
  318.  */
  319. int query_allow_shadow(object ob) 
  320. {
  321.    if (function_exists("valid_read",  previous_object()) || 
  322.        function_exists("valid_write", previous_object()))
  323.       return 0; 
  324.    return !ob->query_prevent_shadow(previous_object());
  325. }
  326.  
  327. /*
  328.  * Default language functions used by parse_command() in non -o mode
  329.  */
  330. string *parse_command_id_list()
  331. {
  332.     return ({ "one", "thing" });
  333. }
  334.  
  335. string *parse_command_plural_id_list()
  336. {
  337.     return ({ "ones", "things", "them" });
  338. }
  339.  
  340. string *parse_command_adjectiv_id_list()
  341. {
  342.     return ({ "iffish" });
  343. }
  344.  
  345. string *parse_command_prepos_list()
  346. {
  347.     return ({ "in", "on", "under", "behind", "beside" });
  348. }
  349.  
  350. string parse_command_all_word()
  351. {
  352.     return "all";
  353. }
  354.  
  355. /*
  356.  * Give a file name for edit preferences to be saved in.
  357.  */
  358. string get_ed_buffer_save_file_name(string file) {
  359.     string *file_ar;
  360.  
  361.     file_ar=explode(file,"/");
  362.     file=file_ar[sizeof(file_ar)-1];
  363.     return "/players/"+this_player()->query_real_name()+"/.dead_ed_files/"+file;
  364. }
  365.  
  366. /*
  367.  * Give a path to a simul_efun file. Observe that it is a string returned,
  368.  * not an object. But the object has to be loaded here. Return 0 if this
  369.  * feature isn't wanted.
  370.  */
  371.  
  372. string get_simul_efun() {
  373.     string fname;
  374.     fname = SIMUL_EFUN;
  375.     if (catch(call_other(fname, "??"))) {
  376.     write("Failed to load " + fname + "\n");
  377.     shutdown();
  378.     return 0;
  379.     }
  380.     return fname;
  381. }
  382.  
  383. shut_down_game()
  384. {
  385.    if (previous_object() != find_object("room/church"))
  386.       return;
  387.    shutdown();
  388. }
  389.  
  390. /*
  391.  * returns true if arg can receive a shout.
  392.  */
  393. valid_shout(arg) { return !arg->query_muffled(); }
  394.  
  395.  
  396. /*
  397.  * There are several occasions when the game driver wants to check if
  398.  * a player has permission to specific things.
  399.  *
  400.  * These types are implemented so far:
  401.  * "error messages":    If the player is allowed to see runtime error
  402.  *            messages.
  403.  * "trace":        If the player is allowed to use tracing.
  404.  * "wizard":        Is the player considered at least a "minimal" wizard ?
  405.  * "error messages":    Is the player allowed to get run time error messages ?
  406.  */
  407. int query_player_level(string what) {
  408.     int level;
  409.  
  410.     if (this_player() == 0)
  411.     return 0;
  412.     level = (int)this_player()->query_level();
  413.     switch(what) {
  414.     case "wizard":
  415.     return level >= 20;
  416.     case "error messages":
  417.     return level >= 20;
  418.     case "trace":
  419.     return level >= 100;
  420.     }
  421. }
  422.  
  423.