parent $root object $sys var $root child_index 1 var $root owners [$sys] var $root fertile 0 var $root inited 1 var $root owned [$sys] var $root manager $sys var $root writable [$sys] var $root readable ['parameters, 'methods, 'code] var $root info ["The system object has special server-granted permissions, and performs tasks which require these permisions. It receives the 'heartbeat message, as well as being pivitol in such tasks as generating new connections and creating objects."] var $root dbref 'sys var $sys admins [] var $sys new_user_class $admin var $sys starting_room $creation var $sys exit_starting_room $void var $sys server_port 1138 var $sys current_receiver 0 var $sys backup_interval 3600 var $sys last_backup 784687240 var $sys startup_time 784684815 var $sys startup_objects [] var $sys agents [$housekeeper, $sys, $scheduler, $old_connection, $root, $daemon] var $sys default_heartbeat_interval 5 var $sys default_port 1138 var $sys user_starting_quota 75000 var $sys server_address #[['ip, ""], ['hostname, "somewhere"]] var $sys anonymous_class $guest var $sys system_email_addresses #[['default, "somebody@somewhere"]] var $sys core_version "1.1" method startup arg args; var opt, str, obj; args = sublist(args, 3); catch any { if (sender() != 0) throw(~perm, "Sender is not the server."); // Get rid of any lingering connection objects. for obj in ($old_connection.children()) { catch any { obj.destroy(); } with handler { .log($parse.traceback(traceback(), -1, "")); } } // Look for a port specification -- this will go away opt = "-p" in args; if (opt) { server_port = opt ? (| toint(args[ind + 1]) |) | default_port; args = (| delete(args, opt) |); args = (| delete(args, opt) |); } // Bind to the port. catch ~socket, ~bind { bind(server_port, $sys); } with handler { .log(("Can't bind to port " + tostr(server_port)) + ", exiting..."); shutdown(); } // Initialize variables and log startup message. .new_connection(); log((("Server starting on port " + tostr(server_port)) + " ") + ($time.date())); // Set up five-second heartbeat. set_heartbeat_freq(default_heartbeat_interval); // set the startup time. startup_time = time(); // tell objects who should know, that we are up. for obj in (startup_objects) { .log(("Calling " + (obj.dbref())) + ".startup()"); (| obj.startup(@args) |); } } with handler { .log(("Startup ERROR at " + ctime()) + ":"); .log($parse.traceback(traceback(), -1, "")); } . method uptime return time() - startup_time; . method startup_time return startup_time; . method new_connection // will move this to the new network heirarchy if ((sender() != this()) || (caller() != definer())) throw(~perm, "Invalid call to private method."); current_receiver = $old_connection.spawn(); current_receiver.set_manager(current_receiver); bind(server_port, current_receiver); . method new_user_class return new_user_class; . method set_new_user_class arg obj; if (!(.is_admin(sender()))) throw(~perm, "Sender not an admin."); if (!(obj.has_ancestor($user))) throw(~type, "Argument is not a user object."); new_user_class = obj; . method create_user arg name, password, email, [type]; var user; if ((!(| .perms(caller(), $old_connection) |)) && (!(| .perms(sender(), 'system) |))) throw(~perm, "caller and sender are not allowed to call this method."); type = [@type, 'new_user_class][1]; catch any { user = .(type)().spawn(name); user.set_name(name); if (type == 'new_user_class) user.set_password(password); else user.set_password(crypt(substr(crypt("", substr(name, 1, 2)), 1, random(13))) + "12"); user.set_manager(user); user.set_email(email); user.chown([user]); } with handler { // Failed to initialize the child; destroy it. if (!(| user.destroy() |)) { (| user.uninitialize() |); (| del_name(user.dbref('symbol)) |); (| del_name(tosym(name)) |); (| destroy(user) |); } rethrow(error()); } return user; . method connection_starting // will move this to the new network heirarchy if (caller() != $old_connection) throw(~perm, "Caller is not $old_connection."); .new_connection(); . method admins return admins; . method is_admin arg obj; return (obj == $sys) || (obj in admins); . method binary_dump if (!($sys.is_admin(sender()))) throw(~perm, "Sender is not an admin."); return binary_dump(); . method shutdown arg [why]; var line1, line2; if ((!($sys.is_admin(sender()))) || (definer() != this())) throw(~perm, "Sender is not an admin."); why = [@why, ""][1]; // tell everybody everything line1 = "*** SHUTDOWN called by " + (sender().namef('ref)); if (why) { line1 = line1 + " because:"; line2 = ("*** " + why) + " ***"; } .log(line1 + " ***"); $channels.announce('all, line1 + " ***"); if (why) { .log(line2); $channels.announce('all, line2); } return shutdown(); . method change_sender_parents arg parents; var p; if (caller() != $root) throw(~perm, "Caller is not $root."); (> chparents(sender(), parents) <); . method spawn_sender arg suffix, manager, [owners]; var namestr; (> .perms(caller(), $root, $sys) <); if (!owners) owners = [manager]; namestr = (tostr(sender().dbref('symbol)) + "_") + suffix; return .create([sender()], tosym(namestr), manager, owners); . method assign_dbref arg name; var keepers, x; (> .perms(caller(), $root, $sys) <); if (type(name) != 'symbol) throw(~type, "Name must be given as a symbol."); // don't run this for now--tosym is fucked. if (0) { // yeah, we change it to a string, but they don't have to know that. name = tostr(name); // lowercase all names: name = lowercase(name); // If it isn't a keeper toss the good old error keepers = "abcdefghijklmnopqrstuvwxyz1234567890_"; for x in [1 .. strlen(name)] { if (!((name[x]) in keepers)) throw(~type, "Name has one or more non-alphanumeric characters."); } name = tosym(name); } // make sure nobody has it yet if ((| get_name(name) |) != ~namenf) throw(~perm, "Name already assigned to " + (get_name(name).namef('ref))); // woo woo, i'm filled with joy, lets give them the name. set_name(name, sender()); . method destroy_sender (> .perms(caller(), $root) <); del_name(sender().dbref('symbol)); destroy(sender()); . method is_system arg obj; return (obj in admins) || (obj in agents); . method log arg text; var l; if ((!(| .perms(sender(), 'system) |)) && (!(| .perms(caller(), 'system) |))) throw(~perm, "NOT"); if (type(text) == 'list) { for l in (text) .log(l); } else { log((($time.time_stamp()) + "> ") + text); } . method connect arg [args]; (> .perms(caller(), $network_root) <); (> connect(@args) <); . method heartbeat if (sender() != 0) throw(~perm, "Sender is not the server."); // personally I prefer more granularity, so changed it. // if (time() / backup_interval > last_backup / backup_interval) if (time() > (last_backup + backup_interval)) .do_backup(this()); $scheduler.pulse(); . method do_backup arg who; var line, name; .perms(sender(), 'system); catch any { name = who.namef('ref); .log(("BACKUP (" + name) + ") "); line = (("It is: " + ($time.ltime())) + " -- BACKUP -- called by ") + name; $channels.announce('System, line); } last_backup = time(); pause(); pause(); .text_dump(); . method backup_interval return backup_interval; . method set_backup_interval arg val; if (!(.is_admin(sender()))) throw(~perm, "Sender not an admin"); backup_interval = val; . method sender_data var output, i; if (caller() != $root) throw(~perm, "Caller is not $root."); return data(sender()); . method get_system_email arg what; var email; // email directory for system services, such as arch admins. email = (| system_email_addresses[what] |); if (!email) email = (| system_email_addresses['default] |) || "<no email set>"; return email; . method new_admin if (caller() != $admin) throw(~perm, "Caller is not $admin."); admins = setadd(admins, sender()); . method admin_going_away if (caller != $admin) throw(~perm, "Caller is not $admin."); admins = setremove(admins, sender()); . method add_startup_object arg obj; (> .perms(sender(), 'manager) <); startup_objects = setadd(startup_objects, obj); . method agents return agents; . method text_dump .perms(sender(), 'this); pause(); return text_dump(); . method del_startup_object arg obj; (> .perms(sender(), 'manager) <); startup_objects = setremove(startup_objects, obj); . method server_address arg [type]; type = [@type, 'hostname][1]; return server_address[type]; . method user_starting_quota return user_starting_quota; . method execute arg script, args, [background]; (> .perms(sender(), @admins) <); (> run_script(script, args, @background) <); . method anonymous_class return anonymous_class; . method create arg parents, name, manager, [owners]; var new; .perms(sender(), 'system); new = create(parents); catch any { new.set_dbref(name); new.initialize(); new.set_manager(manager); new.chown([@owners, [new]][1]); } with handler { // Failed to initialize the child; destroy it. if (!(| new.destroy() |)) { (| new.uninitialize() |); (| del_name(new.dbref('symbol)) |); (| del_name(tosym(name)) |); (| destroy(new) |); } rethrow(error()); } return new; . method system return admins + agents; . method run_script arg script, args, [background]; .perms(sender(), @admins); (> run_script(script, args, @background) <); . method bind arg port, obj; (> .perms(caller(), $network_root) <); (> bind(port, obj) <); . method deassign_dbref arg name; if (caller() != $root) throw(~perm, "Caller is not $root."); del_name(name); . method del_system_email arg key; (> .perms(sender(), 'manager) <); system_email_addresses = dict_del(system_email_addresses, key); . method add_system_email arg key, email; (> .perms(sender(), 'manager) <); if (type(key) != 'symbol) throw(~type, "Key is not a symbol."); if (type(email) != 'string) throw(~type, "Email address is not a string."); system_email_addresses = dict_add(system_email_addresses, key, email); . method compile arg code, name; var line; (> .perms(sender()) <); line = ("SYSTEM: ." + tostr(name)) + "() MODIFIED"; line = (line + " by ") + (sender().namef('ref)); .log(line); return (> pass(code, name) <); . method unbind arg port, obj; (> .perms(caller(), $network_root) <); (> unbind(port) <); . method version arg [args]; var ver; args = [@args, 'driver][1]; switch (args) { case 'driver: ver = version(); return (((tostr(ver[1]) + ".") + tostr(ver[2])) + "-") + tostr(ver[3]); case 'core: return core_version; } . method startup_objects return startup_objects; . method last_backup return last_backup; .