AmigaMUD, Copyright 1997 by Chris Gray CGMud, Copyright 2001 by Chris Gray The 'MUDServ' Program MUDServ is the CGMud server program. It is the largest and most complex part of the system, but it is quite easy to use. MUDServ runs all of the CGMud scenario code, maintains the database files, responds to client requests, provides all of the builtin functions that can be used, provides for interaction between clients, runs the "machines", etc. A system is hosting an CGMud if and only if it is running MUDServ. A system will normally only run one copy of CGMud at a time, but it is possible to run more for testing purposes. This can be handy for having a production MUD as well as a development one. MUDServ expects the MUD database files to be present in the directory which it is run from, or in a directory specified by a command line parameter. These are: MUD.data - the raw data of the scenario. This includes the data for characters, rooms, objects, monsters, etc. as well as the CGMud code that governs them. The system should be able to support an arbitrary sized file, but so far, the standard scenario (30,000 lines of source yielding hundreds of locations, dozens of commands and objects, etc.) has not grown much over 700K bytes. MUD.index - this is an index into MUD.data which allows mapping from a unique constant identifier for something onto a perhaps changing position in the MUD.data file. MUDServ will also create and write a 'MUD.log' file. This file can be deleted at will, but most people running servers will want to scan through it before deleting it. It often contains some interesting information. Also, there are commands in the standard scenario, such as 'bug', 'gripe' and 'typo' which let players put short complaints about things into the MUD.log file. Valid database files are either copied from another source or are produced by the 'MUDCre' program and expanded via MUDServ. The files are in a binary format, and are not intended to be read by humans. Mess around editing them at your own risk. MUDServ assumes they are valid - it may crash your system if they are not, just like an invalid program might. Warning MUDServ maintains an in-memory cache of the most recently used database items. When items are changed, as a result of player actions, machine actions or timed events, the changes are NOT immediately written out to the on-disk copy of the database. This behavior is required in order to get reasonable performance from the system without having continual disk I/O even on a fast hard drive. Because of this behavior, you must not simply shut off or reboot the host machine when you are through playing. You must properly flush the database and shut the server down. This can be done by interrupting the MUDServ program, e.g. by typing a control-C at the shell window it is running from. The standard scenario included with CGMud contains a SysAdmin-only command, "backup", which can be used to make automatic periodic (or one-shot) backups of the database. It will atomically flush the database and copy the database files to a "backup" directory within the directory containing the original database files. The scenario also contains code to recover from inconsistent situations created by running from such a backup, when the backup is taken while some characters, etc. are in non-normal states (such as entering a letter). This backup facility is strongly recommended. The following command-line flags are accepted by the MUDServ program: -W - any connections by "SysAdmin" (the CGMud system administrator character) will be forced into "wizard" mode. This is useful if SysAdmin messes up and gets into a state where he can't otherwise get into wizard mode. This can happen if an invalid input handler is installed, or if SysAdmin ends up in an invalid room. Note: only the 'smud' client can actually put someone into wizard mode. -Q - by default, MUDServ will display occasional messages to standard output, to allow interested MUD administrators to see what is happening. Specifying -Q prevents that. The default state is to produce that output, so that first-time users of CGMud can get positive feedback that things are working. -D - this flag enables some debug messages to the standard output if the debug stuff is compiled in to the server. -N - has no effect - oops! -c - specifies the size of the in-memory database cache. This cache holds the most recently accessed or written parts of the database in memory, so that they can be accessed more quickly. Larger cache sizes reduce the amount of disk I/O needed during operation. The minimum cache size is 32768 bytes. The default cache size is 100000 bytes. I find a cache size of 1000000 bytes to be quite adequate. One disadvantage of a large cache is that it takes a while to flush it to disk, so players would notice a brief period of non-responsiveness whenever it had to be flushed out. -m - specifies the amount of memory that the server should try to limit itself to. This does not include the cache, cache index data structures, the in-memory copy of the MUD.index file, or messages allocated to send to clients. It does include memory for CGMud functions, in-memory copies of symbol tables and grammars, client structures, machine structures, a write-back use-count cache, etc. The value given is not a hard limit - the server will try to keep under it, but will often exceed it. Providing a small memory limit will require more database accesses, putting more stress on the database cache, and requiring more disk I/O operations. The default limit is 1000000000 bytes, which is effectively no limit. -r - specifies a limit on the number of requests (messages) that the server should observe. Requests are CGMud messages between the server and the clients. When it needs to send a message, the server will try to get one from its pool of free ones. If the pool is empty, then it will allocate one from the system. When it receives a message that does not need a reply, the server adds the message to its pool of free messages. If that pool contains more than the given number of messages, it will free the new one back to the system. The expense of having a small limit is one of CPU time and not disk I/O. The default limit is 100. -b - this flag specifies the port number to use for the binary (Java client) connections. Default is 16667. -t[:|] - this flag specifies the port to use for one of the telnet connection ports. The telnet flags are the bitwise OR of the following values: 0x0001 - negotiate binary - negotiate a binary (8-bit) connection with the telnet clients 0x0002 - negotiate echo - enable negotiation of echo with the telnet clients 0x0004 - negotiate pseudo-line-mode with the telnet clients 0x0008 - negotiate supress go-ahead (SUPGA) with the telnet clients 0x0010 - negotiate end-of-record mode with the telnet clients 0x0020 - negotiate ttytype with the telnet clients 0x0040 - negotiate NAWS with the telnet clients. This allows the server to know the client window size 0x0080 - initial echo - start echoing right away 0x0100 - inital eormode - start up sending EORs 0x0200 - send go-aheads 0x0400 - attempt to do password blanking 0x0800 - use SUPGA when trying to do password blanking 0x1000 - attempt to do prompt erasure on output. If no 'which' or 'flags' is given, or if 't' is given, then the flags are: (B_NEG_BINARY | B_NEG_PSEUDO | B_NEG_SUPGA | B_NEG_EORMODE | B_NEG_TTYTYPE | B_NEG_NAWS | B_ERASE_PROMPT | B_PW_BLANK | B_PW_BLANK_SUPGA) If 'which' is 's', then all flags are 0. If 'which' is 'l' (as close as we can get to being like an LPMud server), then the flags are: (B_NEG_BINARY | B_NEG_TTYTYPE | B_NEG_NAWS | B_SEND_GA | B_PW_BLANK) See the "telnet.txt" file for more info. -M - do not activate any machines on startup, and do not let any machines operate by themselves. This is useful when some machine or machines have gotten out of hand, for example when running the "wanderers" on a system that just isn't fast enough to handle them. -F - force the use of the TCP_NODELAY option on all sockets, not just sockets local to the server machine. If a parameter without a leading '-' is given, then it is taken as a path to where the database files can be found, and MUDServ will change directories to that directory. Shutting MUDServ Down MUDServ uses write-back caching for the database. This means that changes made to the database are not immediately written to disk. Instead, the changes are kept in the in-memory cache, and only written to disk when that cache is "flushed". This flushing is done on shutdown, in response to calling the 'Flush' builtin, or whenever the database code cannot find a large enough slot for a new value. Because of this, the on-disk copy of the database is not accurate and consistent except immediately after a flush of the in-memory cache. This means that you cannot safely shut down MUDServ by simply rebooting or turning off your server. Doing so will leave you with a scrambled database. Using write-through caching, where all changes are written to disk immediately, would be hopelessly slow - almost everything done in CGMud changes the database, often in several ways. For example, a character walking from one room to another changes the record of which room the character is in. This is also true for 'machines', such as the randomly generated monsters in the standard scenario. There are two safe ways to shut down MUDServ. In all of these ways, it will not actually shut down until all clients have disconnected. It will, however, remember that it is supposed to shut down and do so as soon as it can. When the special privileged character SysAdmin is connected and in "wizard" mode (working directly with the CGMud programming language, rather than playing the scenario), he can enter a line reading "ShutDown(true).". This line is a call to the 'ShutDown' builtin function, and tells the server that it should shut down as soon as possible. Of course, it cannot do so until SysAdmin logs out. There is a "shutdown" command in the standard scenario which SysAdmin can use to do this. A line reading "ShutDown(false)." will cancel all previous requests to shut down. The MUDServ process can also be sent a control-C signal, which will ask it to shut down. A Few Basic Wizarding Procedures Repeated here for those who miss it in "Intro.txt", the default password for SysAdmin is "SysAdminPassword". The standard scenario contains a few commands that can be used by SysAdmin only. They are: 'backup' - discussed earlier in the "Warning" section 'shutdown' - this command sets the internal server flag indicating that the MUD is being shut down. It will no longer accept new client connections, and will terminate when the last current client goes away. The 'shutdown' command broadcasts a simple message to everyone on the MUD. If 'shutdown' is followed by some text, that text will accompany the message. E.g. shutdown System going down for harddrive replacement. would result in everyone connected to the MUD seeing: **** System going down for harddrive replacement. SysAdmin has started shutdown of the MUD. **** 'freeposes' - this command accepts a yes/no parameter, and will default to 'yes' if no parameter is given. The scenario has several built-in poses, such as "wave", which will appear directly on other player's screens. The generic pose command, however (abbreviated ':') by default puts a " => " between the name of the posing player and the pose itself. This lets other players know that the output they are seeing is a pose, and not some normal output from the system. E.g. if player "Sam" types :gives Fred 10000 blutos. other players would see: Sam => gives Fred 10000 blutos. Some players prefer to have free arbitrary poses, however. This can be globally enabled in the CGMud scenario using the 'freeposes' command. The above example would then show: Sam gives Fred 10000 blutos. 'allowshout' - this enables the "shout" command, which lets users shout messages which are heard by all players currently connected to the server. 'freebuilding' - this command can be used to allow all players to be builders, without SysAdmin having to enable them separately. Technically, if this command is in effect when a new player first enters the game, then that player will be made a full builder at that time. By default, players are not full builders, and can only build in the Playpen. 'makeapprentice ' - this command allows SysAdmin to make a given player an apprentice, thus having access to "wizard mode", and to programming within the CGMud system. Use this command carefully, since an out-of-control apprentice can ruin your MUD, and make it unusable. 'cast makebuilder ' - this command allows SysAdmin to make an individual player a builder. The change will take place right away if possible, else it will be scheduled to take place when the player next connects to the MUD. 'cast unmakebuilder ' - make a player not a builder. SysAdmin, or any other wizard, can enter wizard mode from the standard scenario by typing the "wizard" command. In wizard mode, user input is not handled by the scenario, but is either one of a very few wizard- mode commands, or is a statement in the CGMud programming language. For reference, the way for a wizard to get back into playing mode from wizard mode is to type the following: Normal()$ on an input line by itself, when the prompt is "> ". Note that this input line, as well as all of the following ones, ends in a dollar sign. This dollar sign is required, to indicate the end of the statement. If you forget it, the prompt will switch to ": ", and nothing will happen. You must then type the dollar sign to execute the statement. Note also that the capitalization of these input statements must be as shown. The standard scenario sets the "creation password" to an empty string. This means that no special password or permission is needed to create a new character. A creation password can be installed by using the following line while in wizard mode (only SysAdmin can do this): NewCreationPassword()$ The system will prompt for the new password. If the password begins with an asterisk ('*'), then automatic character creation is not allowed at all. In that case, SysAdmin will have to manually create all new characters. This is done in wizard mode as follows: CreateCharacter("characterName", "characterPassword")$ The character will be created with the given name and password. As usual, do not include spaces or punctuation in the name. A character can be removed from the system using: DestroyCharacter("characterName")$ Note that the above can leave unreachable junk in the database, if the character is carrying complicated objects such as containers. A character can be booted off of the system with: use Characters BootClient(characterName)$ If something prevents that from working, and it is truly necessary to get rid of the character right away, the following can be used: use Characters NukeClient(characterName)$ This is a rather drastic method, however, so avoid it whenever possible. When the character reconnects, he/she will likely have to move around a bit and do some "looks" to get the graphics to come back properly. This is because "NukeClient" is so abrupt that it does not allow the client to execute the scenario shutdown code. If SysAdmin wishes to make a character into a wizard or apprentice, this can be done in wizard mode as follows: use Characters MakeApprentice(CharacterName, false)$ or MakeWizard(CharacterName, false)$ The "use Characters" needs to be done only once per connection. Note that here the character name is not quoted - it is known directly because the "Characters" table is in-use. Note also that this method will not work if the character name has spaces or punctuation marks in it. The "false" in the above tells the system to not immediately change the mode of the player. If the player is currently connected and "true" is used instead, then the player will be immediately placed into wizard mode. A wizard or apprentice can be demoted back to a normal character using: MakeNormal(CharacterName)$ MUDServ places an execution time limit on the CGMud code run in response to any input line or mouse-click. The execution is aborted if this limit is exceeded. The standard scenario sets this limit to 10 seconds. Other limits can be set as follows: RunLimit(new-limit)$ where 'new-limit' is the new execution time limit in seconds. The old limit will be printed out. Do not make the limit too large, as this can cause MUDServ to hang if erroneous wizard code is encountered. Note: not implemented in the C/Unix version of the server. Messages in MUD.log Many different messages can appear in the MUD.log file. Some are just informational, but others can indicate problems, either with the system as a whole or with the scenario. I will attempt to explain some of them here, but there are many that are not explained, either because they are (hopefully) obvious, or because they are coming through some obscure path that I miss. Most lines in the log file will be prefixed by the date and time they are produced. Note: some of these are out-of-date for the C/Unix server. Player SysAdmin enters the game Player SysAdmin leaves the game Messages of this type are produced whenever a player enters or leaves the game. External programs can then be run to keep track of who is using the game and when, and perhaps to add up the amount of time various players are spending in the game. Setting WIZARD mode Clearing WIZARD mode These messages occur whenever a wizard or apprentice goes in or out of wizard (programming) mode. They can be useful in tracking down the causes of problems created in the scenario. expandIndexTable This message indicates than it was necessary for the database code to increase the size of its index array. A number of these will occur when compiling the standard scenario, and occasional ones can occur when running. They are indications of increasing memory usage. Server shutdown request via message - currently 0 clients Shutting down, 1 client serviced Machines: 11 created, 0 deleted Things: 785 created, 0 destroyed Messages: 27448 processed, 2174 sent Allocator: used: 2158592 limit: 1000000000 allocs: 187602 frees: 187602 reclaims: 0 panics: 0 cre 5819 del 5 rd 27117 rep 2371 shr 2 exp 8047 dir 6693 frd 446 fwt 1718 fsk 1976 MUD server V1.0 Copyright 1995 by Chris Gray shut down These messages are typical of shutting down the server. This particular set came after compiling the current version of the standard scenario. Normally, the memory usage figure will be much smaller. The server will not shut down when there are active clients, so the shutdown request (which can come via a message sent by the MUDShut program, a shell 'break' signal to the server process, or by SysAdmin calling the 'ShutDown(true)' builtin) can be quite a ways before the actual shutdown. Machines are the 'robots' or NPC's (Non-Player-Characters) in the CGMud system. During active playing in the standard scenario's combat area, the number created and destroyed can be much higher, perhaps in the tens or hundreds of thousands. Things are the basic entities in the CGMud system. They represent characters, machines, rooms, objects, etc. Messages are the means by which player input is sent to the server and player output is sent from the server. Again, the numbers would normally be quite a bit higher with active players. The memory used by the allocator does not include the database cache and an in-memory copy of the MUD.index file. It also does not include the various Exec messages that the server may have had to allocate. The next line gives some statistics on the database activities: cre: database entries (things, characters, strings, tables, machines, procedures, property structures, etc.) that were created in this run del: database entries deleted rd: database entries read (on long, intensive runs, I've seen this number over 20,000,000) rep: database entries replaced shr: database entries shrunk (e.g. when properties are removed from a thing, or elements are deleted from a list) exp: database entries expanded dir: database entries dirtied (a change made which doesn't involve changing the size of the entry) The next line indicates the number of actual disk I/O operations that the database code had to make. The ratio between the above numbers and these numbers is an indication of how effective the database cache has been: frd: number of actual file reads fwt: number of actual file writes fsk: number of file seeks DataSize 605678=>605678 IndexCurrent 7027=>7021 On occasions, the database code will scan through the highest indexed database entries, attempting to merge and free them. This line indicates the success of doing so. 'DataSize' indicates the total used size of the MUD.data file. 'IndexCurrent' indicates the total used size of the MUD.index file. BootClient for player SysAdmin This indicates that a request was generated to shut down the indicated client. The client will exit as soon as its current activity in the server is done. In this case, it was generated by the scenario calling the 'Quit' builtin as a result of the player entering the 'bye' command. Agent shutdown for player SysAdmin The MUDAgent program has shut down a connection for some reason. This could be loss of carrier, activity timeout, failure to communicate, etc. NukeClient for player SysAdmin This is a record of a more severe method of shutting down a given client. In this case, the system tries to shut the client down right away, and does not wait for anything. This is done by SysAdmin via the 'NukeClient' builtin. SysAdmin has set the shutdown flag. SysAdmin has cleared the shutdown flag. These appear in response to SysAdmin using the ShutDown builtin. Name1 changed name to Name2 A system administrator will sometimes want to keep track of which characters are played by which real people. This message helps by logging when a character changes name. It comes from the 'ChangeName' builtin. New player when no entry action! This message indicates that a person has tried to connect and create a new character when there is not yet an 'entry-action' routine in the scenario. This is the routine, set by the 'SetNewCharacterAction' builtin, which is called to setup a new character. no memory for server request This will be immediately followed by an abort. The server could not allocate memory for a message, and so cannot proceed. serverMessage: got unexpected type NN from server MUDState NNNN > 1000 Can't find local offset XXXXXXXX in 'readExec' can't find ref key in 'readExec' invalid request type client not found client already editing can't find name for builtin in subPublicProc can't find Characters in public symbol table can't find Builtin in public symbol table These should not happen, and will cause an abort. If they happen, something serious is wrong with your CGMud system. This could be an invalid program, a damaged database, failing hardware, etc. You should not continue to run such a system, since it is possible that important data on your hard disk could be damaged. can't create MUD port can't allocate interrupt can't open timer device can't allocate timer request can't create timer port These messages indicate that MUDServ could not start up because it could not do all of its initialization. They usually indicate that they system does not have enough free memory. MUD port already exits This can happen if you try to start two servers using the same port name. If you get this message when you are sure that there is no other copy of MUDServ running, then you will have to reboot your system to clear the condition. Fail to seek to end to expand The database code needed to expand MUD.data, but could not seek to the current end of the file in order to write more to it. This should not happen. Fail to write NN bytes to expand Fail to write block to expand Fail to write NNN bytes to flush buffer can't write index to index file This can happen if your disk is full. In this case you will have to go back to a backup of your database files, since the current ones are no longer internally consistent. This kind of symptom can also happen if the disk or partition in use becomes write protected. Fail to seek to NNNNNN to flush buffer Fail to seek to write direct Fail to write NNN bytes direct This is a similar seek failure. It should not happen. If it does, there is something wrong with your system. Fail to seek to NNNNNN to read direct Fail to read NNN bytes direct Fail to seek to NNNNNN to fill buffer Fail to read enough into buffer This can indicate a filesystem failure or a corrupt database. In either case, you will need to restore from a backup. can't write XXXXX to index file can't open/create new index file The MUD.index file has several special values at its beginning. One of them couldn't be written when flushing the database. This will yield a corrupt set of database files. It is also possible that this kind of symptom could occur if the disk that CGMud is running on becomes write protected. offset > SORT_BUCKETS XXXXXXXX CacheLRUHead ~= next in ioFlush No cache slot len NNN for item invalid type to ioCreate key XXXXXXXX not in cache for ioDirty key XXXXXXXX not in cache for ioExpand new len < oldlen on ioExpand of XXXXXXXX assumption failed in ioExpand! ioShrink, newLen 0 Key XXXXXXXX not in cache for 'ioShrink' new len > old len on ioShrink of XXXXXXXX ioReplace, newLen = 0 ioDelete(XXXXXXXX) - already deleted! I've got a bug. Let me know. If you get any of these, then the database code will have aborted. This leaves you with an inconsistent set of database files and you must go back to a backup of them. Cannot create cache slot len NNN for item The database code uses a non-write-through cache to hold the most recently referenced database items. This abort indicates that it needed to create such a cache slot for an item, and was not able to find a hole large enough (the items must be stored in one contiguous slot). In such cases it simply cannot continue executing, because it has no knowledge about the state of the upper-level code that is using it. Hence the abort. With this abort, like those listed above, the database files are now unusable. Run with a larger database cache to avoid this abort. Too few cache entries to make one for len NNN This abort is similar to the previous one, except that in this case, there are a small number of large entries that seem to be using up all of the space. Again, the database will be corrupt, and you should run with a larger database cache. database overflow - too many entries!!! The system thinks you have more than 2 ** 24 entries (over 16 million). I can't believe that! expansion failed An attempt was made to expand the in-memory copy of MUD.index. A region of memory big enough could not be allocated. You will have to restore from backup files, and attempt to make more free memory available for running. CGMud code running in the scenario can also add lines to the log file. The content of those lines is entirely up to the scenario. In the standard scenario, they are user-generated comments about bugs or typos, or just plain complaints.