This is patch12 to PennMUSH 1.7.7. After applying this patch, you will have version 1.7.7p12 To apply this patch, save it to a file in your top-level MUSH directory, and do the following: patch -p1 < 1.7.7-patch12 mv CHANGES CHANGES.177 ./Configure -S make versions make install If 'make versions' fails with an error about Sort::Versions, you can instead download game-txt-hlp-177p12.tar.gz from the ftp site and unpack that from your pennmush/ directory. If you use GNU patch 2.2, you probably want the above to be 'patch -b -p1', not just 'patch -p1'. Unix (or cygwin) users need not worry about failed hunks in src/switchinc.c, hdrs/switches.h, hdrs/cmds.h, or hdrs/funs.h. These files are automatically rebuilt on compile. Then @shutdown and restart your MUSH. - Alan/Javelin In this patch: Commands: * @channel/buffer creates a buffer for a channel to store the most recent messages broadcast on the channel. @channel/recall can be used to recall them. These are not stored across reboots and should be set up by #1's @startup. Functions/Substitutions: * accname() gives the accented name of an object (applying @nameaccent). * %~ gives the accented name of the enactor. Minor Changes: * The chat-related commands and functions have been moved out of bsd.c and funmisc.c and into extchat.c. Patch by Vadiv@M*U*S*H. * The notification stuff has been moved out of bsd.c and into a new notify.c file. * @name no longer requires a password for changing player names, and ignores one if given. Suggested by Ambrosia@M*U*S*H (and others). * @hook can not be used on the @password or @newpassword commands. * The dump_complete message is also shown after a forking dump, if one is defined. Suggested by Nathan Schuette. * @lock/leave on a room now prevents people within it from leaving via exits or via @tel. Suggested by Peter Bengtson, patch by BlaZe@M*U*S*H. Fixes: * Fixes from 1.7.6p8 * Cleanup of a few new db[x] mentions in the source to use dbdefs.h macros. Inspired by Vadiv@M*U*S*H. * @command/restrict didn't work properly for most flags, especially new ones. Reported by Caesar and Sholevi@M*U*S*H. * @pemit/list didn't honor NOSPOOF. Patch by Cheetah@M*U*S*H. Prereq: 1.7.7p11 rm -rf CHANGES*~ CHANGES*bak utils/mkvershlp.pl game/txt/hlp CHANGES* *** 1_7_7.231/Patchlevel Sat, 22 Feb 2003 15:29:30 -0600 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.13 600) --- 1_7_7.308(w)/Patchlevel Sat, 22 Mar 2003 10:44:14 -0600 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.14 600) *************** *** 1,2 **** Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.7.7p11 --- 1,2 ---- Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.7.7p12 *** 1_7_7.231/CHANGES Sat, 22 Feb 2003 15:29:30 -0600 dunemush (pennmush/g/23_CHANGES 1.48.1.23 600) --- 1_7_7.308(w)/CHANGES.177 Mon, 24 Mar 2003 12:09:06 -0600 dunemush (pennmush/g/23_CHANGES 1.48.1.41 600) *************** *** 18,23 **** --- 18,55 ---- ========================================================================== + Version 1.7.7 patchlevel 12 March 21, 2003 + + Commands: + * @channel/buffer creates a buffer for a channel to store the most + recent messages broadcast on the channel. @channel/recall can be + used to recall them. These are not stored across reboots and should + be set up by #1's @startup. + Functions/Substitutions: + * accname() gives the accented name of an object (applying @nameaccent). + * %~ gives the accented name of the enactor. + Minor Changes: + * The chat-related commands and functions have been moved out + of bsd.c and funmisc.c and into extchat.c. Patch by Vadiv@M*U*S*H. + * The notification stuff has been moved out of bsd.c and into a new + notify.c file. + * @name no longer requires a password for changing player names, + and ignores one if given. Suggested by Ambrosia@M*U*S*H (and others). + * @hook can not be used on the @password or @newpassword commands. + * The dump_complete message is also shown after a forking dump, + if one is defined. Suggested by Nathan Schuette. + * @lock/leave on a room now prevents people within it from leaving + via exits or via @tel. Suggested by Peter Bengtson, patch by + BlaZe@M*U*S*H. + Fixes: + * Fixes from 1.7.6p8 + * Cleanup of a few new db[x] mentions in the source to use dbdefs.h + macros. Inspired by Vadiv@M*U*S*H. + * @command/restrict didn't work properly for most flags, especially + new ones. Reported by Caesar and Sholevi@M*U*S*H. + * @pemit/list didn't honor NOSPOOF. Patch by Cheetah@M*U*S*H. + + Version 1.7.7 patchlevel 11 February 22, 2003 Commands: *** 1_7_7.231/game/txt/hlp/penntop.hlp Tue, 04 Feb 2003 22:13:06 -0600 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.5 600) --- 1_7_7.308(w)/game/txt/hlp/penntop.hlp Thu, 06 Mar 2003 10:50:57 -0600 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.6 600) *************** *** 1699,1709 **** Zone master rooms are a subset of zones. If a room is used as a zone master, it is a zone master room (ZMR). ZMRs are like local "master" rooms. Exits in the ZMR are global to that zone, and $commands on ! objects in the ZMR are global to that zone. Zone master rooms are ! only defined if globals are used. Zone master rooms are best used for ! very large zones which have a lot of global exits, or for zones with ! restricted commands that can go on a separate use-locked object from ! general ones. See also: ZONES, MASTER ROOM, EVALUATION & ZONE MASTERS --- 1699,1714 ---- Zone master rooms are a subset of zones. If a room is used as a zone master, it is a zone master room (ZMR). ZMRs are like local "master" rooms. Exits in the ZMR are global to that zone, and $commands on ! objects in the ZMR are global to that zone ($commands on the ZMR itself, ! like $commands on the master room, are ignored). If a ZMR is a player's ! personal zone, objects in the ZMR are checked for commands that the ! player can use anywhere (but exits are not checked unless the player ! is in a zoned room). ! ! Zone master rooms are only defined if globals are used. Zone master ! rooms are best used for very large zones which have a lot of global ! exits, or for zones with restricted commands that can go on a separate ! use-locked object from general ones. See also: ZONES, MASTER ROOM, EVALUATION & ZONE MASTERS *** 1_7_7.231/game/txt/hlp/pennfunc.hlp Wed, 12 Feb 2003 15:05:43 -0600 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.8 600) --- 1_7_7.308(w)/game/txt/hlp/pennfunc.hlp Tue, 18 Mar 2003 15:58:45 -0600 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.2 600) *************** *** 1263,1268 **** --- 1263,1275 ---- > say [foreach(is_alphanum,jt1o+)] You say, "1 1 1 1 0 " + & ACCNAME() + accname() + + accname() returns the name of object , applying the object's + @nameaccent, if any. + + Related functions: NAME(), ACCNAME(), INAME() & FULLNAME() fullname() *************** *** 1273,1279 **** >"[fullname(south)] You say, "South;sout;sou;so;s" ! Related functions: NAME(), INAME() & FUNCTIONS() functions() --- 1280,1286 ---- >"[fullname(south)] You say, "South;sout;sou;so;s" ! Related functions: NAME(), ACCNAME(), INAME() & FUNCTIONS() functions() *************** *** 2342,2348 **** error, but enough old code has been written that expects this behavior that it will continue to do this for the time being. Don't rely on it. ! Related functions: FULLNAME(), INAME() & NAND() nand(, ,...) --- 2349,2355 ---- error, but enough old code has been written that expects this behavior that it will continue to do this for the time being. Don't rely on it. ! Related functions: FULLNAME(), ACCNAME(), INAME() & NAND() nand(, ,...) *************** *** 3535,3546 **** attribute, %# refers to the original enactor and not the 'calling' object; 'me' refers to the object that supplied the attribute. ! However, unlike the u() function, the global registers r(0) through r(9) ! (%q0 - %q9) are preserved in their initial state. This means that functions ! "below" the level of the u() can reset global registers for temporary ! calculations, without needing to worry about "clobbering" the original ! values. ! This makes ulocal() particularly useful for global or shared code which calls arbitrary u() functions, where global register values need to be preserved from accidental user clobbering. --- 3542,3553 ---- attribute, %# refers to the original enactor and not the 'calling' object; 'me' refers to the object that supplied the attribute. ! However, unlike the u() function, the global registers r(0)-r(9) and ! r(A)-r(Z) (%q0-%q9, %qa-%qz) are preserved in their initial state. This ! means that functions "below" the level of the u() can reset global ! registers for temporary calculations, without needing to worry about ! "clobbering" the original values. ! This makes ulocal() particularly useful for global or shared code which calls arbitrary u() functions, where global register values need to be preserved from accidental user clobbering. *** 1_7_7.231/game/txt/hlp/pennflag.hlp Tue, 04 Feb 2003 22:25:42 -0600 dunemush (pennmush/17_pennflag.h 1.1.1.1.1.2.1.1.1.2.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.4.1.2.1.4 600) --- 1_7_7.308(w)/game/txt/hlp/pennflag.hlp Sat, 15 Mar 2003 20:28:51 -0600 dunemush (pennmush/17_pennflag.h 1.1.1.1.1.2.1.1.1.2.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.4.1.2.2.2 600) *************** *** 47,59 **** V - Visual W - Wizard X - Safe Z - Shared, Z_Tel ! a - Audible b - Debug c - Connected, Cloudy d - Destroy_Ok e - Enter_Ok g - Gagged h - Halt j - Jury_Ok l - Light m - Myopic, Mistrust n - No_Command o - On-Vacation p - Puppet, Paranoid r - Royalty s - Suspect t - Transparent u - Uninspected v - Verbose ! w - No_Warn x - Terse ? - Unregistered ^ - Listen_Parent ~ - Noaccents --------------------------------------------------------------------- Some flags may not be enabled on some MUSHes. @flag/list will show --- 47,59 ---- V - Visual W - Wizard X - Safe Z - Shared, Z_Tel ! a - Audible b - Debug c - Connected d - Destroy_Ok e - Enter_Ok g - Gagged h - Halt j - Jury_Ok l - Light m - Myopic, Mistrust n - No_Command o - On-Vacation p - Puppet, Paranoid r - Royalty s - Suspect t - Transparent u - Uninspected v - Verbose ! w - No_Warn x - Terse, Cloudy ? - Unregistered ^ - Listen_Parent ~ - Noaccents --------------------------------------------------------------------- Some flags may not be enabled on some MUSHes. @flag/list will show *** 1_7_7.231/game/txt/hlp/penncmd.hlp Sat, 22 Feb 2003 14:01:23 -0600 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.4.1.6 600) --- 1_7_7.308(w)/game/txt/hlp/penncmd.hlp Wed, 12 Mar 2003 12:25:37 -0600 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.1.1.4 600) *************** *** 1936,1942 **** @lock/speech Who can speak/pose/emit in this room @lock/listen Who can trigger my @ahear/^-pattern actions @lock/command Who can trigger my $-pattern commands ! @lock/leave Who can leave this object @lock/drop Who can drop this object or in this room @lock/give Who can give this object @lock/follow Who can follow this object --- 1936,1942 ---- @lock/speech Who can speak/pose/emit in this room @lock/listen Who can trigger my @ahear/^-pattern actions @lock/command Who can trigger my $-pattern commands ! @lock/leave Who can leave this object (or room, via exits/@tel) @lock/drop Who can drop this object or in this room @lock/give Who can give this object @lock/follow Who can follow this object *************** *** 2043,2053 **** See also: go, @omove, @oxmove, @amove & @name ! @name = [] Changes the name of , which can be a thing, player, exit, or room. You can refer to object by name, DBREF number, or as "me" ! or "here". For a player, it requires the player's password. & @newpassword @newpassword = --- 2043,2057 ---- See also: go, @omove, @oxmove, @amove & @name ! @name = Changes the name of , which can be a thing, player, exit, or room. You can refer to object by name, DBREF number, or as "me" ! or "here". ! ! When changing a player's name on games that support multi-word player ! names, the name should be enclosed in quotes: ! @name me = "James Bond" & @newpassword @newpassword = *************** *** 2541,2547 **** @remit[/switches] = . Sends the message to all contents of , which can be a room, ! thing, or player. (The TinyMUSH equivalent is @pemit/contents). The /silent switch stops the remitter from getting feedback if they're in a different location than the target. --- 2545,2552 ---- @remit[/switches] = . Sends the message to all contents of , which can be a room, ! thing, or player. The message is also sent to the itself. ! (The TinyMUSH equivalent is @pemit/contents). The /silent switch stops the remitter from getting feedback if they're in a different location than the target. *** 1_7_7.231/game/txt/hlp/pennchat.hlp Sun, 15 Sep 2002 15:53:06 -0500 dunemush (pennmush/19_pennchat.h 1.2.1.4.1.4 600) --- 1_7_7.308(w)/game/txt/hlp/pennchat.hlp Sun, 16 Mar 2003 16:54:10 -0600 dunemush (pennmush/19_pennchat.h 1.2.1.4.1.5 600) *************** *** 58,72 **** Wizards may add and remove other players from channels by providing a player name as a second argument. ! Some channels may be restricted in who can join them and/or speak ! on them. If the Extended Chat System is enabled, @channel/list will ! show you the channel's name, number of users, number of message ! since last restart, access information, and your status. See ! "help channel-list" for an explanation of how to read the listing. @channel/what will show you the channel's name, access information, and a description of the channel's purpose. ! More details are provided in "help @channel2". See also: chat & @channel2 @channel/who @channel/hide = --- 58,73 ---- Wizards may add and remove other players from channels by providing a player name as a second argument. ! Channels may be restricted in who can join them and/or speak on ! them. @channel/list will show you the channel's name, number of users, ! number of message since last restart, access information, and your ! status. See "help channel-list" for an explanation of how to read ! the listing. ! @channel/what will show you the channel's name, access information, and a description of the channel's purpose. ! More commands are provided in "help @channel2". See also: chat & @channel2 @channel/who @channel/hide = *************** *** 88,109 **** & @channel3 @channel/mute = @channel/gag = ! Some channels broadcast messages when players connect or disconnect ! from the MUSH. If you're on such a channel and don't want to hear ! those messages, use @channel/mute =yes. To resume hearing ! the messages, use @channel/mute =no. You can also use ! @channel/unmute . If you want to remain on a channel but not receive any messages on the channel, use @channel/gag =yes. To resume hearing, ! use @channel/gag =no (or @channel/ungag ). If you ! disconnect, the channel will be automatically ungagged for you. If the ! channel does not have the "open" priv, you can not speak on it while ! you are gagged. ! ! If you do not specify a channel with these commands, you mute or ! gag (or unmute or ungag) all channels at once. See "help @channel4" for more. & @channel4 --- 89,113 ---- & @channel3 @channel/mute = @channel/gag = + @channel/recall [ = ] ! Some channels broadcast messages when players connect or disconnect from ! the MUSH. If you don't want to hear those messages, use @channel/mute ! =yes. To resume hearing the messages, use @channel/mute ! =no or @channel/unmute . Leave out ! to mute or unmute all channels. If you want to remain on a channel but not receive any messages on the channel, use @channel/gag =yes. To resume hearing, ! use @channel/gag =no (or @channel/ungag ). When ! you disconnect, the channel will be automatically ungagged for you. ! Leave out to gag or ungag all channels. If the channel does ! not have the "open" priv, you can not speak on it while you are gagged. ! ! @channel/recall shows you the most recent messages on the channel; ! the number of messages depends on how the channel is configured, but ! can be limited by specifying . You must be on a channel to ! recall from it. See "help @channel4" for more. & @channel4 *************** *** 134,145 **** --- 138,153 ---- @channel/priv = @channel/quiet = @channel/wipe + @channel/buffer = @channel/decompile[/brief] @channel/chown = The "priv" switch changes the channel's access privileges. The "quiet" switch turns the quiet status of a channel on and off. The "wipe" switch clears a channel of players without deleting it. + The "buffer" switch sets the maximum number of full-length lines that + the channel will buffer for @chan/recall. Many more shorter lines may + actually be buffered. Setting it to 0 turns off buffering. The "decompile" and "chown" switches can only be used by Wizards. @channel/decompile produces a decompile of matching channels. If the *************** *** 149,174 **** & channel-list Here's the legend for reading the @channel/list output: ! Channel Name Num Users Num Msgs Access Locks Status ! Sample 1 0 [DPOWQHo jsmvh*] [On QH] ! ||||||| |||||| | || ! Channel is DISABLED----------------------------/|||||| |||||| | || ! Channel allows PLAYERS--------------------------/||||| |||||| | || ! Channel allows OBJECTS---------------------------/|||| |||||| | || ! Channel is Wizard-only (W) or Admin-only (A)------/||| |||||| | || ! Channel is QUIET-----------------------------------/|| |||||| | || ! Channel is HIDE_OK----------------------------------/| |||||| | || ! Channel is OPEN (non-members can speak on it)--------/ |||||| | || ! Channel has @clock/join set----------------------------|||||| | || ! Channel has @clock/speak set----------------------------/|||| | || ! Channel has @clock/mod set-------------------------------/||| | || ! Channel has @clock/see set--------------------------------/|| | || ! Channel has @clock/hide set--------------------------------/| | || ! Player is the owner of the channel--------------------------/ | || ! Player is currently on/off/gagging the channel------------------/ || ! If on, player has the channel muted---------------------------------/| ! If on, player is hiding on the channel-------------------------------/ ! & @clock @clock/join [= ] @clock/speak [= ] --- 157,182 ---- & channel-list Here's the legend for reading the @channel/list output: ! Channel Name Num Users Num Msgs Access Locks Status Buf ! Sample 1 0 [DPOWQHo jsmvh*] [On QH] 4 ! ||||||| |||||| | || | ! Channel is DISABLED----------------------------/|||||| |||||| | || | ! Channel allows PLAYERS--------------------------/||||| |||||| | || | ! Channel allows OBJECTS---------------------------/|||| |||||| | || | ! Channel is Wizard-only (W) or Admin-only (A)------/||| |||||| | || | ! Channel is QUIET-----------------------------------/|| |||||| | || | ! Channel is HIDE_OK----------------------------------/| |||||| | || | ! Channel is OPEN (non-members can speak on it)--------/ |||||| | || | ! Channel has @clock/join set----------------------------|||||| | || | ! Channel has @clock/speak set----------------------------/|||| | || | ! Channel has @clock/mod set-------------------------------/||| | || | ! Channel has @clock/see set--------------------------------/|| | || | ! Channel has @clock/hide set--------------------------------/| | || | ! Player is the owner of the channel--------------------------/ | || | ! Player is currently on/off/gagging the channel------------------/ || | ! If on, player has the channel muted---------------------------------/| | ! If on, player is hiding on the channel-------------------------------/ | ! Size of the channel buffer in full-length lines---------------------------/ & @clock @clock/join [= ] @clock/speak [= ] *** 1_7_7.231/src/SWITCHES Tue, 14 Jan 2003 22:56:21 -0600 dunemush (pennmush/b/22_SWITCHES 1.12.1.3.1.2 600) --- 1_7_7.308(w)/src/SWITCHES Sun, 16 Mar 2003 16:02:11 -0600 dunemush (pennmush/b/22_SWITCHES 1.12.1.3.1.4 600) *************** *** 9,14 **** --- 9,15 ---- BEFORE BLIND BRIEF + BUFFER CHECK CHOWN CLEAR *************** *** 88,93 **** --- 89,95 ---- QUIET READ REBOOT + RECALL REMOVE RENAME REGISTER *** 1_7_7.231/src/wiz.c Thu, 06 Feb 2003 11:14:31 -0600 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.3 660) --- 1_7_7.308(w)/src/wiz.c Tue, 25 Mar 2003 16:22:38 -0600 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.4 660) *************** *** 470,476 **** * player. */ /* now check to see if the absolute room is set NO_TEL */ ! if (NoTel(absroom) && !controls(player, absroom) && !Tel_Anywhere(player)) { notify(player, T("Teleports are not allowed in this room.")); --- 470,476 ---- * player. */ /* now check to see if the absolute room is set NO_TEL */ ! if ((NoTel(absroom) || !eval_lock(player, absroom, Leave_Lock)) && !controls(player, absroom) && !Tel_Anywhere(player)) { notify(player, T("Teleports are not allowed in this room.")); *** 1_7_7.231/src/help.c Mon, 27 Jan 2003 09:40:07 -0600 dunemush (pennmush/f/32_help.c 1.4.1.2.1.1.1.3.2.2.1.1.2.1.1.2.1.2.1.2.1.3.1.9 660) --- 1_7_7.308(w)/src/help.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/f/32_help.c 1.4.1.2.1.1.1.3.2.2.1.1.2.1.1.2.1.2.1.2.1.3.1.10 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file help.c + * + * \brief The PennMUSH help system. + * + * + */ #include "config.h" #include #include *************** *** 31,39 **** static void help_build_index(help_file *h, int restricted); typedef struct TLIST { ! char topic[TOPIC_NAME_LEN + 1]; ! struct TLIST *next; } tlist; tlist *top = NULL; --- 38,47 ---- static void help_build_index(help_file *h, int restricted); + /** Linked list of help topic names. */ typedef struct TLIST { ! char topic[TOPIC_NAME_LEN + 1]; /**< Name of topic */ ! struct TLIST *next; /**< Pointer to next list entry */ } tlist; tlist *top = NULL; *************** *** 41,47 **** unsigned num_topics = 0; unsigned top_topics = 0; ! void write_topic(long int p); #define TRUE 1 #define FALSE 0 --- 49,55 ---- unsigned num_topics = 0; unsigned top_topics = 0; ! static void write_topic(long int p); #define TRUE 1 #define FALSE 0 *************** *** 59,76 **** do_new_spitfile(player, arg_left, h, h->admin); } void ! init_help_files() { hash_init(&help_files, 8, sizeof(help_file)); help_init = 1; } void ! add_help_file(command_name, filename, admin) ! const char *command_name; ! const char *filename; ! int admin; { help_file *h; char newfilename[256] = "\0"; --- 67,92 ---- do_new_spitfile(player, arg_left, h, h->admin); } + /** Initialize the helpfile hashtable, which contains the names of the + * help files. + */ void ! init_help_files(void) { hash_init(&help_files, 8, sizeof(help_file)); help_init = 1; } + /** Add new help command. This function is + * the basis for the help_command directive in mush.cnf. It creates + * a new help entry for the hash table, builds a help index, + * and adds the new command to the command table. + * \param command_name name of help command to add. + * \param filename name of the help file to use for this command. + * \param admin if 1, this command reads admin topics, rather than standard. + */ void ! add_help_file(const char *command_name, const char *filename, int admin) { help_file *h; char newfilename[256] = "\0"; *************** *** 113,121 **** hashadd(h->command, h, &help_files); } void ! help_reindex(player) ! dbref player; { help_file *curr; --- 129,142 ---- hashadd(h->command, h, &help_files); } + /** Rebuild a help file index. + * \verbatim + * This command implements @readcache. + * \endverbatim + * \param player the enactor. + */ void ! help_reindex(dbref player) { help_file *curr; *************** *** 136,146 **** } static void ! do_new_spitfile(player, arg1, help_dat, restricted) ! dbref player; ! char *arg1; ! help_file *help_dat; ! int restricted; /* 1 = admin help, 0 = regular help */ { help_indx *entry = NULL; FILE *fp; --- 157,163 ---- } static void ! do_new_spitfile(dbref player, char *arg1, help_file *help_dat, int restricted) { help_indx *entry = NULL; FILE *fp; *************** *** 265,273 **** notify_format(player, T("%s output truncated."), help_dat->command); } ! void ! write_topic(p) ! long int p; { tlist *cur, *nextptr; help_indx *temp; --- 282,289 ---- notify_format(player, T("%s output truncated."), help_dat->command); } ! static void ! write_topic(long int p) { tlist *cur, *nextptr; help_indx *temp; *************** *** 303,311 **** } static void ! help_build_index(h, restricted) ! help_file *h; ! int restricted; { long bigpos, pos = 0; int in_topic; --- 319,325 ---- } static void ! help_build_index(help_file *h, int restricted) { long bigpos, pos = 0; int in_topic; *** 1_7_7.231/src/htab.c Sun, 01 Dec 2002 21:14:41 -0600 dunemush (pennmush/b/30_htab.c 1.8.1.6 660) --- 1_7_7.308(w)/src/htab.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/30_htab.c 1.8.1.10 660) *************** *** 1,8 **** ! /* htab.c - table hashing routines */ ! ! /* This code is ripped out of TinyMUSH 2.2. */ ! /* Minor tweaking to make in Penn-compatible by Trivian (xeno@mix.hive.no) */ ! #include "config.h" #include "copyrite.h" --- 1,12 ---- ! /** ! * \file htab.c ! * ! * \brief Hashtable routines. ! * This code is largely ripped out of TinyMUSH 2.2.5, with tweaks ! * to make it Penn-compatible by Trivian. ! * ! * ! */ #include "config.h" #include "copyrite.h" *************** *** 15,20 **** --- 19,26 ---- #include "mymalloc.h" #include "confmagic.h" + static HASHENT *hash_new(HASHTAB *htab, const char *key); + /* --------------------------------------------------------------------------- * hash_val: Compute hash value of a string for a hash table. */ *************** *** 42,50 **** /* The whole new hash function */ int ! hash_val(k, mask) ! register const char *k; /* the key */ ! int mask; { register u4 a, b, c; /* the internal state */ u4 len, length; /* how many key bytes still need mixing */ --- 48,54 ---- /* The whole new hash function */ int ! hash_val(register const char *k, int mask) { register u4 a, b, c; /* the internal state */ u4 len, length; /* how many key bytes still need mixing */ *************** *** 100,119 **** #else /* NEW_HASH_FUN */ int ! hash_val(key, hashmask) ! const char *key; ! int hashmask; { int hash = 0; const char *sp; - /* - * If the string pointer is null, return 0. If not, add up the - * numeric value of all the characters and return the sum, - * modulo the size of the hash table. - */ - if (!key || !*key) return 0; for (sp = key; *sp; sp++) --- 104,123 ---- #else /* NEW_HASH_FUN */ + /** Compute a hash value for mask-style hashing. + * Given a null key, return 0. Otherwise, add up the numeric value + * of all the characters and return the sum modulo the size of the + * hash table. + * \param key key to hash. + * \param hashmask hash table size to use as modulus. + * \return hash value. + */ int ! hash_val(const char *key, int hashmask) { int hash = 0; const char *sp; if (!key || !*key) return 0; for (sp = key; *sp; sp++) *************** *** 126,154 **** * hash_getmask: Get hash mask for mask-style hashing. */ int ! hash_getmask(size) ! int *size; { int tsize; if (!size || !*size) return 0; - /* Get next power-of-two >= size, return power-1 as the mask - * for ANDing - */ - for (tsize = 1; tsize < *size; tsize = tsize << 1) ; *size = tsize; return tsize - 1; } void ! hash_init(htab, size, data_size) ! HASHTAB *htab; ! int size; ! int data_size; { int i; --- 130,160 ---- * hash_getmask: Get hash mask for mask-style hashing. */ + /** Get the hash mask for mask-style hashing. + * Given the data size, return closest power-of-two less than that size. + * \param size data size. + * \return hash mask. + */ int ! hash_getmask(int *size) { int tsize; if (!size || !*size) return 0; for (tsize = 1; tsize < *size; tsize = tsize << 1) ; *size = tsize; return tsize - 1; } + /** Initialize a hashtable. + * \param htab pointer to hash table to initialize. + * \param size size of hashtable. + * \param data_size size of an individual datum to store in the table. + */ void ! hash_init(HASHTAB *htab, int size, int data_size) { int i; *************** *** 162,171 **** htab->entry_size = data_size; } HASHENT * ! hash_find(htab, key) ! HASHTAB *htab; ! const char *key; { int hval, cmp; HASHENT *hptr; --- 168,180 ---- htab->entry_size = data_size; } + /** Return a hashtable entry given a key. + * \param htab pointer to hash table to search. + * \param key key to look up in the table. + * \return pointer to hash table entry for given key. + */ HASHENT * ! hash_find(HASHTAB *htab, const char *key) { int hval, cmp; HASHENT *hptr; *************** *** 184,192 **** return NULL; } void * ! hash_value(entry) ! HASHENT *entry; { if (entry) return entry->data; --- 193,204 ---- return NULL; } + /** Return the value stored in a hash entry. + * \param entry pointer to a hash table entry. + * \return generic pointer to the stored value. + */ void * ! hash_value(HASHENT *entry) { if (entry) return entry->data; *************** *** 194,202 **** return NULL; } char * ! hash_key(entry) ! HASHENT *entry; { if (entry) return entry->key; --- 206,217 ---- return NULL; } + /** Return the key stored in a hash entry. + * \param entry pointer to a hash table entry. + * \return pointer to the stored key. + */ char * ! hash_key(HASHENT *entry) { if (entry) return entry->key; *************** *** 204,213 **** return NULL; } void ! hash_resize(htab, size) ! HASHTAB *htab; ! int size; { int i; HASHENT **oldarr; --- 219,230 ---- return NULL; } + /** Resize a hash table. + * \param htab pointer to hashtable. + * \param size new size. + */ void ! hash_resize(HASHTAB *htab, int size) { int i; HASHENT **oldarr; *************** *** 261,267 **** return; } ! HASHENT * hash_new(HASHTAB *htab, const char *key) { int hval; --- 278,284 ---- return; } ! static HASHENT * hash_new(HASHTAB *htab, const char *key) { int hval; *************** *** 308,319 **** return hptr; } int ! hash_add(htab, key, hashdata, extra_size) ! HASHTAB *htab; ! const char *key; ! void *hashdata; ! int extra_size __attribute__ ((__unused__)); { HASHENT *hptr; --- 325,341 ---- return hptr; } + /** Add an entry to a hash table. + * \param htab pointer to hash table. + * \param key key string to store data under. + * \param hashdata void pointer to data to be stored. + * \param extra_size unused. + * \retval -1 failure. + * \retval 0 success. + */ int ! hash_add(HASHTAB *htab, const char *key, void *hashdata, ! int extra_size __attribute__ ((__unused__))) { HASHENT *hptr; *************** *** 331,340 **** return 0; } void ! hash_delete(htab, entry) ! HASHTAB *htab; ! HASHENT *entry; { int hval; HASHENT *hptr, *last; --- 353,364 ---- return 0; } + /** Delete an entry in a hash table. + * \param htab pointer to hash table. + * \param entry pointer to hash entry to delete (and free). + */ void ! hash_delete(HASHTAB *htab, HASHENT *entry) { int hval; HASHENT *hptr, *last; *************** *** 360,369 **** hash_resize(htab, htab->hashsize >> 1); } void ! hash_flush(htab, size) ! HASHTAB *htab; ! int size; { HASHENT *hent, *thent; int i; --- 384,395 ---- hash_resize(htab, htab->hashsize >> 1); } + /** Flush a hash table, freeing all entries. + * \param htab pointer to a hash table. + * \param size size of hash table. + */ void ! hash_flush(HASHTAB *htab, int size) { HASHENT *hent, *thent; int i; *************** *** 391,399 **** } } void * ! hash_firstentry(htab) ! HASHTAB *htab; { int hval; --- 417,430 ---- } } + /** Return the first entry of a hash table. + * This function is used with hash_nextentry() to iterate through a + * hash table. + * \param htab pointer to hash table. + * \return first hash table entry. + */ void * ! hash_firstentry(HASHTAB *htab) { int hval; *************** *** 406,414 **** return NULL; } void * ! hash_nextentry(htab) ! HASHTAB *htab; { int hval; HASHENT *hptr; --- 437,451 ---- return NULL; } + /** Return the next entry of a hash table. + * This function is used with hash_firstentry() to iterate through a + * hash table. hash_firstentry() must be called before calling + * this function. + * \param htab pointer to hash table. + * \return next hash table entry. + */ void * ! hash_nextentry(HASHTAB *htab) { int hval; HASHENT *hptr; *************** *** 431,451 **** return NULL; } void ! hash_stats_header(player) ! dbref player; { notify_format(player, "Table Buckets Entries LChain ECh 1Ch 2Ch 3Ch 4+Ch AvgCh ~Memory"); } void ! hash_stats(player, htab, hname) ! dbref player; ! HASHTAB *htab; ! const char *hname; { - /* Report some statistics on the hash table */ int longest = 0, n; int lengths[5]; double chainlens = 0.0; --- 468,491 ---- return NULL; } + /** Display a header for a stats listing. + * \param player player to notify with header. + */ void ! hash_stats_header(dbref player) { notify_format(player, "Table Buckets Entries LChain ECh 1Ch 2Ch 3Ch 4+Ch AvgCh ~Memory"); } + /** Display stats on a hashtable. + * \param player player to notify with stats. + * \param htab pointer to the hash table. + * \param hname name of the hash table. + */ void ! hash_stats(dbref player, HASHTAB *htab, const char *hname) { int longest = 0, n; int lengths[5]; double chainlens = 0.0; *** 1_7_7.231/src/switchinc.c Thu, 09 Jan 2003 21:37:52 -0600 dunemush (pennmush/b/32_switchinc. 1.3.1.2.1.6.1.18.1.2.1.2.2.5.1.4.2.4.1.1.1.2.1.5.1.2.1.5.2.1.1.31.3.4.1.2.1.4.1.2 660) --- 1_7_7.308(w)/src/switchinc.c Tue, 25 Mar 2003 16:22:38 -0600 dunemush (pennmush/b/32_switchinc. 1.3.1.2.1.6.1.18.1.2.1.2.2.5.1.4.2.4.1.1.1.2.1.5.1.2.1.5.2.1.1.31.3.4.1.5.1.4 660) *************** *** 11,16 **** --- 11,17 ---- {"BEFORE", SWITCH_BEFORE}, {"BLIND", SWITCH_BLIND}, {"BRIEF", SWITCH_BRIEF}, + {"BUFFER", SWITCH_BUFFER}, {"CHECK", SWITCH_CHECK}, {"CHOWN", SWITCH_CHOWN}, {"CLEAR", SWITCH_CLEAR}, *************** *** 82,88 **** {"PARANOID", SWITCH_PARANOID}, {"PLAYERS", SWITCH_PLAYERS}, {"PORT", SWITCH_PORT}, - {"POSE", SWITCH_POSE}, {"PRESERVE", SWITCH_PRESERVE}, {"PRINT", SWITCH_PRINT}, {"PRIVS", SWITCH_PRIVS}, --- 83,88 ---- *************** *** 91,96 **** --- 91,97 ---- {"QUIET", SWITCH_QUIET}, {"READ", SWITCH_READ}, {"REBOOT", SWITCH_REBOOT}, + {"RECALL", SWITCH_RECALL}, {"REGISTER", SWITCH_REGISTER}, {"REMOVE", SWITCH_REMOVE}, {"RENAME", SWITCH_RENAME}, *************** *** 99,105 **** {"RETROACTIVE", SWITCH_RETROACTIVE}, {"ROOM", SWITCH_ROOM}, {"ROOMS", SWITCH_ROOMS}, - {"ROYALTY", SWITCH_ROYALTY}, {"SEE", SWITCH_SEE}, {"SEEFLAG", SWITCH_SEEFLAG}, {"SELF", SWITCH_SELF}, --- 100,105 ---- *** 1_7_7.231/src/speech.c Mon, 03 Feb 2003 11:05:37 -0600 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.2.3 660) --- 1_7_7.308(w)/src/speech.c Tue, 25 Mar 2003 16:22:38 -0600 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.3.2 660) *************** *** 847,853 **** /* Figure out the 'name' of the player */ if (PAGE_ALIASES && (a = atr_get_noparent(player, "ALIAS"))) ! current = tprintf("%s(%s)", Name(player), uncompress(a->value)); else current = (char *) Name(player); --- 847,853 ---- /* Figure out the 'name' of the player */ if (PAGE_ALIASES && (a = atr_get_noparent(player, "ALIAS"))) ! current = tprintf("%s (%s)", Name(player), uncompress(a->value)); else current = (char *) Name(player); *** 1_7_7.231/src/set.c Tue, 14 Jan 2003 22:56:21 -0600 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.3 660) --- 1_7_7.308(w)/src/set.c Tue, 25 Mar 2003 16:22:38 -0600 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.5 660) *************** *** 110,126 **** password++; } } ! /* check for null password */ ! if (!God(player) && !*password) { ! notify(player, ! T("You must specify a password to change a player name.")); ! notify(player, T("E.g.: @name player = newname password")); ! return; ! } else if (!God(player) && !password_check(thing, password)) { ! notify(player, T("Incorrect password.")); ! return; ! } else if (strcasecmp(newname, Name(thing)) ! && !ok_player_name(newname)) { /* strcasecmp allows changing foo to Foo, etc. */ notify(player, T("You can't give a player that name.")); return; --- 110,117 ---- password++; } } ! if (strcasecmp(newname, Name(thing)) ! && !ok_player_name(newname)) { /* strcasecmp allows changing foo to Foo, etc. */ notify(player, T("You can't give a player that name.")); return; *** 1_7_7.231/src/player.c Sun, 16 Feb 2003 22:20:24 -0600 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.8 660) --- 1_7_7.308(w)/src/player.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.9 660) *************** *** 366,372 **** Home(player) = PLAYER_START; Owner(player) = player; Parent(player) = NOTHING; ! db[player].type = TYPE_PLAYER; flags = string_to_bits(options.player_flags); copy_flag_bitmask(Flags(player), flags); destroy_flag_bitmask(flags); --- 366,372 ---- Home(player) = PLAYER_START; Owner(player) = player; Parent(player) = NOTHING; ! Type(player) = TYPE_PLAYER; flags = string_to_bits(options.player_flags); copy_flag_bitmask(Flags(player), flags); destroy_flag_bitmask(flags); *** 1_7_7.231/src/parse.c Sun, 22 Dec 2002 18:01:26 -0600 dunemush (pennmush/b/48_parse.c 1.23.1.10.1.2.1.1.1.1.1.2.1.2.1.9 660) --- 1_7_7.308(w)/src/parse.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/48_parse.c 1.23.1.10.1.2.1.1.1.1.1.2.1.2.1.10 660) *************** *** 547,552 **** --- 547,555 ---- safe_str("0 0", buff, bp); } break; + case '~': /* enactor accented name */ + safe_str(accented_name(enactor), buff, bp); + break; case '0': case '1': case '2': *** 1_7_7.231/src/mymalloc.c Wed, 24 Jan 2001 16:56:43 -0600 dunemush (pennmush/b/49_mymalloc.c 1.2 660) --- 1_7_7.308(w)/src/mymalloc.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/49_mymalloc.c 1.3 660) *************** *** 1,4 **** ! /* A wrapper for the various malloc package options. See options.h * for descriptions of each. * Each package's source code must include config.h, mymalloc.h, * and confmagic.h. --- 1,9 ---- ! /** ! * \file mymalloc.c ! * ! * \brief Malloc wrapper file. ! * ! * A wrapper for the various malloc package options. See options.h * for descriptions of each. * Each package's source code must include config.h, mymalloc.h, * and confmagic.h. *** 1_7_7.231/src/mycrypt.c Sun, 01 Dec 2002 21:14:41 -0600 dunemush (pennmush/b/50_mycrypt.c 1.9 660) --- 1_7_7.308(w)/src/mycrypt.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/50_mycrypt.c 1.10 660) *************** *** 1,5 **** ! /* This file defines the function mush_crypt(key) used for password ! * encryption, depending on the system. */ #include "config.h" --- 1,11 ---- ! /** ! * \file mycrypt.c ! * ! * \brief Password encryption for PennMUSH ! * ! * This file defines the function mush_crypt(key) used for password ! * encryption, depending on the system. Actually, we pretty much ! * expect to use SHS. */ #include "config.h" *************** *** 12,17 **** --- 18,28 ---- #include "confmagic.h" char *mush_crypt(const char *key); + + /** Encrypt a password and return ciphertext. + * \param key plaintext to encrypt. + * \return encrypted password. + */ char * mush_crypt(const char *key) { *** 1_7_7.231/src/move.c Wed, 12 Feb 2003 17:02:38 -0600 dunemush (pennmush/b/51_move.c 1.1.1.18.1.5.1.13.1.3.1.9.1.1.1.1.1.2.1.1.1.1.1.12 660) --- 1_7_7.308(w)/src/move.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/b/51_move.c 1.1.1.18.1.5.1.13.1.3.1.9.1.1.1.1.1.2.1.1.1.1.1.14 660) *************** *** 1,4 **** ! /* move.c */ #include "copyrite.h" #include "config.h" --- 1,10 ---- ! /** ! * \file move.c ! * ! * \brief Movement commands for PennMUSH. ! * ! * ! */ #include "copyrite.h" #include "config.h" *************** *** 38,57 **** static int is_following(dbref follower, dbref leader); static void follower_command(dbref leader, dbref loc, const char *com); void ! moveto(what, where) ! dbref what; ! dbref where; { enter_room(what, where, 0); } void ! moveit(what, where, nomovemsgs) ! dbref what; ! dbref where; ! int nomovemsgs; { dbref loc, old; dbref absloc, absold; --- 44,67 ---- static int is_following(dbref follower, dbref leader); static void follower_command(dbref leader, dbref loc, const char *com); + /** A convenience wrapper for enter_room(). + * \param what object to move. + * \param where location to move it to. + */ void ! moveto(dbref what, dbref where) { enter_room(what, where, 0); } + /** Send an object somewhere. + * \param what object to move. + * \param where location to move it to. + * \param nomovemsgs if 1, don't show movement messages. + */ void ! moveit(dbref what, dbref where, int nomovemsgs) { dbref loc, old; dbref absloc, absold; *************** *** 126,134 **** #define Dropper(thing) (Hearer(thing) && Connected(Owner(thing))) static void ! send_contents(loc, dest) ! dbref loc; ! dbref dest; { dbref first; dbref rest; --- 136,142 ---- #define Dropper(thing) (Hearer(thing) && Connected(Owner(thing))) static void ! send_contents(dbref loc, dbref dest) { dbref first; dbref rest; *************** *** 154,162 **** } static void ! maybe_dropto(loc, dropto) ! dbref loc; ! dbref dropto; { dbref thing; if (loc == dropto) --- 162,168 ---- } static void ! maybe_dropto(dbref loc, dbref dropto) { dbref thing; if (loc == dropto) *************** *** 173,183 **** send_contents(loc, dropto); } void ! enter_room(player, loc, nomovemsgs) ! dbref player; ! dbref loc; ! int nomovemsgs; { dbref old; dbref dropto; --- 179,191 ---- send_contents(loc, dropto); } + /** Enter a container. + * \param player object entering the container. + * \param loc container to enter. + * \param nomovemsgs if 1, don't give movement messages. + */ void ! enter_room(dbref player, dbref loc, int nomovemsgs) { dbref old; dbref dropto; *************** *** 237,248 **** } ! /* teleports player to location while removing items they shouldnt take */ void ! safe_tel(player, dest, nomovemsgs) ! dbref player; ! dbref dest; ! int nomovemsgs; { dbref first; dbref rest; --- 245,257 ---- } ! /** Teleport player to location while removing items they shouldn't take. ! * \param player player to teleport. ! * \param dest location to teleport player to. ! * \param nomovemsgs if 1, don't show movement messages ! */ void ! safe_tel(dbref player, dbref dest, int nomovemsgs) { dbref first; dbref rest; *************** *** 280,293 **** enter_room(player, dest, nomovemsgs); } ! /* This checks to see if there's a go-able direction. It doesn't * check whether the GOTO command is restricted. That should be * done by the command parser. */ int ! can_move(player, direction) ! dbref player; ! const char *direction; { if (!strcasecmp(direction, "home") && !Fixed(player)) return 1; --- 289,303 ---- enter_room(player, dest, nomovemsgs); } ! /** Can a player go in a given direction? ! * This checks to see if there's a go-able direction. It doesn't * check whether the GOTO command is restricted. That should be * done by the command parser. + * \param player dbref of mover. + * \param direction name of direction to move. */ int ! can_move(dbref player, const char *direction) { if (!strcasecmp(direction, "home") && !Fixed(player)) return 1; *************** *** 298,306 **** } static dbref ! find_var_dest(player, exit_obj) ! dbref player; ! dbref exit_obj; { /* This is used to evaluate the u-function DESTINATION on an exit with * a VARIABLE (ambiguous) link. --- 308,314 ---- } static dbref ! find_var_dest(dbref player, dbref exit_obj) { /* This is used to evaluate the u-function DESTINATION on an exit with * a VARIABLE (ambiguous) link. *************** *** 336,341 **** --- 344,354 ---- } + /** The move command. + * \param player the enactor. + * \param direction name of direction to move. + * \param type type of motion to check (global, zone, neither). + */ void do_move(dbref player, const char *direction, enum move_type type) { *************** *** 384,389 **** --- 397,407 ---- default: /* we got one */ /* check to see if we're allowed to pass */ + if (!eval_lock(player, Location(player), Leave_Lock)) { + notify(player, T("You can't go that way.")); + return; + } + if (could_doit(player, exit_m)) { switch (Location(exit_m)) { case HOME: *************** *** 452,461 **** } } void ! do_firstexit(player, what) ! dbref player; ! const char *what; { dbref thing; dbref loc; --- 470,484 ---- } } + /** Move an exit to the first position in the room's exit list. + * \verbatim + * This implements @firstexit. + * \endverbatim + * \param player the enactor. + * \param what name of exit to promote. + */ void ! do_firstexit(dbref player, const char *what) { dbref thing; dbref loc; *************** *** 475,484 **** } void ! do_get(player, what) ! dbref player; ! const char *what; { dbref loc = Location(player); dbref thing; --- 498,509 ---- } + /** The get command. + * \param player the enactor. + * \param what name of object to get. + */ void ! do_get(dbref player, const char *what) { dbref loc = Location(player); dbref thing; *************** *** 595,604 **** } void ! do_drop(player, name) ! dbref player; ! const char *name; { dbref loc; dbref thing; --- 620,631 ---- } + /** Drop an object. + * \param player the enactor. + * \param name name of object to drop. + */ void ! do_drop(dbref player, const char *name) { dbref loc; dbref thing; *************** *** 653,662 **** } void ! do_enter(player, what) ! dbref player; ! const char *what; { dbref thing; dbref loc; --- 680,691 ---- } + /** The enter command. + * \param player the enactor. + * \param what name of object to enter. + */ void ! do_enter(dbref player, const char *what) { dbref thing; dbref loc; *************** *** 699,707 **** } } void ! do_leave(player) ! dbref player; { dbref loc; loc = Location(player); --- 728,738 ---- } } + /** The leave command. + * \param player the enactor. + */ void ! do_leave(dbref player) { dbref loc; loc = Location(player); *************** *** 718,750 **** follower_command(player, loc, "leave"); } int ! global_exit(player, direction) ! dbref player; ! const char *direction; { return (GoodObject (match_result(player, direction, TYPE_EXIT, MAT_GLOBAL | MAT_EXIT))); } int ! remote_exit(player, direction) ! dbref player; ! const char *direction; { return (GoodObject (match_result(player, direction, TYPE_EXIT, MAT_REMOTES | MAT_EXIT))); } void ! move_wrapper(player, command) ! dbref player; ! const char *command; { - /* check local exit, then zone exit, then global. If nothing is - * matched, treat it as local so player will get an error message. - */ - if (!Mobile(player)) return; if (!strcasecmp(command, "home") && Fixed(player)) { --- 749,789 ---- follower_command(player, loc, "leave"); } + /** Is direction a global exit? + * \param player looker. + * \param direction name of exit. + * \retval 1 direction is a global exit. + * \retval 0 direction is not a global exit. + */ int ! global_exit(dbref player, const char *direction) { return (GoodObject (match_result(player, direction, TYPE_EXIT, MAT_GLOBAL | MAT_EXIT))); } + /** Is direction a remote exit? + * \param player looker. + * \param direction name of exit. + * \retval 1 direction is a remote exit. + * \retval 0 direction is not a remote exit. + */ int ! remote_exit(dbref player, const char *direction) { return (GoodObject (match_result(player, direction, TYPE_EXIT, MAT_REMOTES | MAT_EXIT))); } + /** Wrapper for exit movement. + * We check local exit, then zone exit, then global. If nothing is + * matched, treat it as local so player will get an error message. + * \param player the mover. + * \param command direction to move. + */ void ! move_wrapper(dbref player, const char *command) { if (!Mobile(player)) return; if (!strcasecmp(command, "home") && Fixed(player)) { *************** *** 764,776 **** /* Routines for dealing with the follow commands */ ! /* follow tries to start following * follow alone lists who you're following */ void ! do_follow(player, arg) ! dbref player; ! const char *arg; { dbref leader; if (arg && *arg) { --- 803,816 ---- /* Routines for dealing with the follow commands */ ! /** The follow command. ! * follow tries to start following * follow alone lists who you're following + * \param the enactor. + * \param arg name of object to follow. */ void ! do_follow(dbref player, const char *arg) { dbref leader; if (arg && *arg) { *************** *** 816,828 **** } } ! /* unfollow removes someone from your following list ! * unfollow alone removes everyone from your following list. (1.7.4p3) */ void ! do_unfollow(player, arg) ! dbref player; ! const char *arg; { dbref leader; if (arg && *arg) { --- 856,869 ---- } } ! /** The unfollow command. ! * unfollow removes someone from your following list ! * unfollow alone removes everyone from your following list. ! * \param player the enactor. ! * \parma arg object to stop following. */ void ! do_unfollow(dbref player, const char *arg) { dbref leader; if (arg && *arg) { *************** *** 851,863 **** } ! /* dismiss removes someone from your followers list * dismiss alone removes everyone from your followers list. */ void ! do_dismiss(player, arg) ! dbref player; ! const char *arg; { dbref follower; if (arg && *arg) { --- 892,905 ---- } ! /** The dismiss command. ! * dismiss removes someone from your followers list * dismiss alone removes everyone from your followers list. + * \param player the enactor. + * \param arg name of object to dismiss. */ void ! do_dismiss(dbref player, const char *arg) { dbref follower; if (arg && *arg) { *************** *** 881,893 **** } } ! /* desert removes someone from your followers and following list * desert alone removes everyone from both lists */ void ! do_desert(player, arg) ! dbref player; ! const char *arg; { dbref who; if (arg && *arg) { --- 923,936 ---- } } ! /** The desert command. ! * desert removes someone from your followers and following list * desert alone removes everyone from both lists + * \param player the enactor. + * \param arg name of object to desert. */ void ! do_desert(dbref player, const char *arg) { dbref who; if (arg && *arg) { *************** *** 917,925 **** /* Add someone to a player's FOLLOWERS attribute */ static void ! add_follower(leader, follower) ! dbref leader; ! dbref follower; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 960,966 ---- /* Add someone to a player's FOLLOWERS attribute */ static void ! add_follower(dbref leader, dbref follower) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 939,947 **** /* Add someone to a player's FOLLOWING attribute */ static void ! add_following(follower, leader) ! dbref follower; ! dbref leader; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 980,986 ---- /* Add someone to a player's FOLLOWING attribute */ static void ! add_following(dbref follower, dbref leader) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 960,969 **** } static void ! add_follow(leader, follower, noisy) ! dbref leader; ! dbref follower; ! int noisy; { char msg[BUFFER_LEN]; add_follower(leader, follower); --- 999,1005 ---- } static void ! add_follow(dbref leader, dbref follower, int noisy) { char msg[BUFFER_LEN]; add_follower(leader, follower); *************** *** 979,987 **** /* Delete someone from a player's FOLLOWERS attribute */ static void ! del_follower(leader, follower) ! dbref leader; ! dbref follower; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 1015,1021 ---- /* Delete someone from a player's FOLLOWERS attribute */ static void ! del_follower(dbref leader, dbref follower) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 998,1006 **** /* Delete someone from a player's FOLLOWING attribute */ static void ! del_following(follower, leader) ! dbref follower; ! dbref leader; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 1032,1038 ---- /* Delete someone from a player's FOLLOWING attribute */ static void ! del_following(dbref follower, dbref leader) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 1016,1025 **** } static void ! del_follow(leader, follower, noisy) ! dbref leader; ! dbref follower; ! int noisy; { char msg[BUFFER_LEN]; del_follower(leader, follower); --- 1048,1054 ---- } static void ! del_follow(dbref leader, dbref follower, int noisy) { char msg[BUFFER_LEN]; del_follower(leader, follower); *************** *** 1034,1041 **** /* Return a list of names of players who are my followers, comma-separated */ static char * ! list_followers(player) ! dbref player; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 1063,1069 ---- /* Return a list of names of players who are my followers, comma-separated */ static char * ! list_followers(dbref player) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 1066,1073 **** /* Return a list of names of players who I'm following, comma-separated */ static char * ! list_following(player) ! dbref player; { ATTR *a; char tbuf1[BUFFER_LEN]; --- 1094,1100 ---- /* Return a list of names of players who I'm following, comma-separated */ static char * ! list_following(dbref player) { ATTR *a; char tbuf1[BUFFER_LEN]; *************** *** 1098,1106 **** /* Is follower following leader? */ static int ! is_following(follower, leader) ! dbref follower; ! dbref leader; { ATTR *a; char *s, *sp; --- 1125,1131 ---- /* Is follower following leader? */ static int ! is_following(dbref follower, dbref leader) { ATTR *a; char *s, *sp; *************** *** 1121,1130 **** return 0; } void ! clear_followers(leader, noisy) ! dbref leader; ! int noisy; { ATTR *a; char *s, *sp; --- 1146,1157 ---- return 0; } + /** Clear a player's followers list. + * \param leader dbref of player whose list is to be cleared. + * \param noisy if 1, notify the player. + */ void ! clear_followers(dbref leader, int noisy) { ATTR *a; char *s, *sp; *************** *** 1147,1156 **** (void) atr_clr(leader, "FOLLOWERS", GOD); } void ! clear_following(follower, noisy) ! dbref follower; ! int noisy; { ATTR *a; char *s, *sp; --- 1174,1185 ---- (void) atr_clr(leader, "FOLLOWERS", GOD); } + /** Clear a player's following list. + * \param follower dbref of player whose list is to be cleared. + * \param noisy if 1, notify the player. + */ void ! clear_following(dbref follower, int noisy) { ATTR *a; char *s, *sp; *** 1_7_7.231/src/memcheck.c Sun, 01 Dec 2002 21:14:41 -0600 dunemush (pennmush/c/1_memcheck.c 1.8.1.4 660) --- 1_7_7.308(w)/src/memcheck.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/1_memcheck.c 1.8.1.5 660) *************** *** 1,3 **** --- 1,13 ---- + /** + * \file memcheck.c + * + * \brief A simple memory allocation tracker for PennMUSH. + * + * This code isn't usually compiled in, but it's handy to debug + * memory leaks sometimes. + * + * + */ #include "config.h" #include "conf.h" #include "copyrite.h" *************** *** 16,25 **** typedef struct mem_check MEM; struct mem_check { ! int ref_count; ! MEM *next; ! char ref_name[BUFFER_LEN]; }; static MEM *my_check = NULL; --- 26,36 ---- typedef struct mem_check MEM; + /** A linked list for storing memory allocation counts */ struct mem_check { ! int ref_count; /**< Number of allocations of this type. */ ! MEM *next; /**< Pointer to next in linked list. */ ! char ref_name[BUFFER_LEN]; /**< Name of this allocation type. */ }; static MEM *my_check = NULL; *************** *** 28,36 **** *** AN INFINITE LOOP. DANGER, WILL ROBINSON! ***/ void ! add_check(ref) ! const char *ref; { MEM *loop, *newcheck, *prev = NULL; size_t reflen; --- 39,49 ---- *** AN INFINITE LOOP. DANGER, WILL ROBINSON! ***/ + /** Add an allocation check. + * \param ref type of allocation. + */ void ! add_check(const char *ref) { MEM *loop, *newcheck, *prev = NULL; size_t reflen; *************** *** 57,65 **** return; } void ! del_check(ref) ! const char *ref; { MEM *loop, *prev = NULL; int cmp; --- 70,80 ---- return; } + /** Remove an allocation check. + * \param ref type of allocation to remove. + */ void ! del_check(const char *ref) { MEM *loop, *prev = NULL; int cmp; *************** *** 85,95 **** ref); } void ! list_mem_check(player) ! dbref player; { - MEM *loop; for (loop = my_check; loop; loop = loop->next) { --- 100,111 ---- ref); } + /** List allocations. + * \param player the enactor. + */ void ! list_mem_check(dbref player) { MEM *loop; for (loop = my_check; loop; loop = loop->next) { *************** *** 97,106 **** } } void ! log_mem_check() { - MEM *loop; for (loop = my_check; loop; loop = loop->next) { --- 113,123 ---- } } + /** Log all allocations. + */ void ! log_mem_check(void) { MEM *loop; for (loop = my_check; loop; loop = loop->next) { *** 1_7_7.231/src/match.c Wed, 12 Feb 2003 17:02:38 -0600 dunemush (pennmush/c/2_match.c 1.24.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.16 660) --- 1_7_7.308(w)/src/match.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/2_match.c 1.24.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.18 660) *************** *** 1,7 **** ! /* match.c */ ! /* Routines for parsing arguments */ ! ! /*********************************************************************** * These are the PennMUSH name-matching routines, fully re-entrant. * match_result(who,name,type,flags) - return match, AMBIGUOUS, or NOTHING * noisy_match_result(who,name,type,flags) - return match or NOTHING, --- 1,8 ---- ! /** ! * \file match.c ! * ! * \brief Matching of object names. ! * * These are the PennMUSH name-matching routines, fully re-entrant. * match_result(who,name,type,flags) - return match, AMBIGUOUS, or NOTHING * noisy_match_result(who,name,type,flags) - return match or NOTHING, *************** *** 67,73 **** extern int check_alias(const char *command, const char *list); /* game.c */ ! /* A wrapper for returning a match, AMBIGUOUS, or NOTHING */ dbref match_result(const dbref who, const char *name, const int type, --- 68,81 ---- extern int check_alias(const char *command, const char *list); /* game.c */ ! /** A wrapper for returning a match, AMBIGUOUS, or NOTHING. ! * This function attempts to match a name for who, and ! * can return the matched dbref, AMBIGUOUS, or NOTHING. ! * \param who the looker. ! * \param name name to try to match. ! * \param type type of object to match. ! * \param flags match flags. ! * \return dbref of matched object, or AMBIGUOUS, or NOTHING. */ dbref match_result(const dbref who, const char *name, const int type, *************** *** 76,84 **** return match_result_internal(who, name, type, flags); } ! /* A wrapper for returning a match or NOTHING ! * Ambiguous matches return NOTHING ! * It will also notify the player of non-matches or ambiguous matches */ dbref noisy_match_result(const dbref who, const char *name, const int type, --- 84,99 ---- return match_result_internal(who, name, type, flags); } ! /** A noisy wrapper for returning a match or NOTHING. ! * This function attempts to match a name for who, and ! * can return the matched dbref or NOTHING (in ambiguous cases, ! * NOTHING is returned). If no match is made, the looker is notified ! * of the failure to match or ambiguity. ! * \param who the looker. ! * \param name name to try to match. ! * \param type type of object to match. ! * \param flags match flags. ! * \return dbref of matched object, or NOTHING. */ dbref noisy_match_result(const dbref who, const char *name, const int type, *************** *** 87,94 **** return match_result_internal(who, name, type, flags | MAT_NOISY); } ! /* A wrapper for returning a match or NOTHING ! * Ambiguous matches return the last matched thing */ dbref last_match_result(const dbref who, const char *name, const int type, --- 102,116 ---- return match_result_internal(who, name, type, flags | MAT_NOISY); } ! /** A noisy wrapper for returning a match or NOTHING. ! * This function attempts to match a name for who, and ! * can return the matched dbref or NOTHING. In ambiguous cases, ! * the last matched thing is returned. ! * \param who the looker. ! * \param name name to try to match. ! * \param type type of object to match. ! * \param flags match flags. ! * \return dbref of matched object, or NOTHING. */ dbref last_match_result(const dbref who, const char *name, const int type, *************** *** 97,103 **** return match_result_internal(who, name, type, flags | MAT_LAST); } ! /* Wrapper for a noisy match with control checks */ dbref match_controlled(dbref player, const char *name) { --- 119,133 ---- return match_result_internal(who, name, type, flags | MAT_LAST); } ! /** Wrapper for a noisy match with control checks. ! * This function performs a noisy_match_result() and then checks that ! * the looker controls the matched object before returning it. ! * If the control check fails, the looker is notified and NOTHING ! * is returned. ! * \param player the looker. ! * \param name name to try to match. ! * \return dbref of matched controlled object, or NOTHING. ! */ dbref match_controlled(dbref player, const char *name) { *** 1_7_7.231/src/malias.c Sun, 08 Dec 2002 22:10:45 -0600 dunemush (pennmush/c/3_malias.c 1.36.1.2 660) --- 1_7_7.308(w)/src/malias.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/3_malias.c 1.36.1.5 660) *************** *** 1,5 **** ! /*-------------------------------------------------------------------* ! * malias.c - Global @mail aliases/lists * * This code implements an extension to extended @mail which allows * admin (and others who are so em@powered) to create mail aliases --- 1,9 ---- ! /** ! * \file malias.c ! * ! * \brief Global mail aliases/lists ! * ! * \verbatim * * This code implements an extension to extended @mail which allows * admin (and others who are so em@powered) to create mail aliases *************** *** 25,31 **** * @malias/stat * @malias/chown !name=owner (Admin only) * @malias/nuke (Admin only) ! *-------------------------------------------------------------------*/ #define MA_INC 3 #include "config.h" --- 29,37 ---- * @malias/stat * @malias/chown !name=owner (Admin only) * @malias/nuke (Admin only) ! * ! * \endverbatim ! */ #define MA_INC 3 #include "config.h" *************** *** 66,71 **** --- 72,78 ---- int ma_top = 0; struct mail_alias *malias; + /** Privilege table for maliases. */ static PRIV malias_priv_table[] = { {"Admin", 'A', ALIAS_ADMIN, ALIAS_ADMIN}, {"Members", 'M', ALIAS_MEMBERS, ALIAS_MEMBERS}, *************** *** 73,79 **** {NULL, '\0', 0, 0} }; - static const char *get_privs(int flags); static const char *get_shortprivs(struct mail_alias *m); --- 80,85 ---- *************** *** 82,92 **** ***********************************************************/ void ! do_malias(player, arg1, arg2) ! dbref player; ! char *arg1; ! char *arg2; { if (!arg1 || !*arg1) { if (arg2 && *arg2) { --- 88,103 ---- ***********************************************************/ + /** List or create a malias. + * \verbatim + * This implements the @malias command (with no switches). + * \endverbatim + * \param player the enactor. + * \param arg1 name of malias to create or list, or NULL to list all. + * \param arg2 parameters for creation, or NULL to list. + */ void ! do_malias(dbref player, char *arg1, char *arg2) { if (!arg1 || !*arg1) { if (arg2 && *arg2) { *************** *** 107,117 **** } void ! do_malias_create(player, alias, tolist) ! dbref player; ! char *alias; ! char *tolist; { char *head, *tail, spot; struct mail_alias *m; --- 118,133 ---- } + /** Create a malias. + * \verbatim + * This implements the @malias/create command. + * \endverbatim + * \param player the enactor. + * \param arg1 name of malias to create. + * \param arg2 parameters for creation. + */ void ! do_malias_create(dbref player, char *alias, char *tolist) { char *head, *tail, spot; struct mail_alias *m; *************** *** 245,254 **** } ! void ! do_malias_list(player) ! dbref player; { struct mail_alias *m; int i = 0; --- 261,274 ---- } ! /** List maliases. ! * \verbatim ! * This function implements @malias/list. ! * \endverbatim ! * \param player the enactor. ! */ void ! do_malias_list(dbref player) { struct mail_alias *m; int i = 0; *************** *** 275,284 **** notify(player, T("***** End of Mail Aliases *****")); } void ! do_malias_members(player, alias) ! dbref player; ! char *alias; { struct mail_alias *m; int i = 0; --- 295,309 ---- notify(player, T("***** End of Mail Aliases *****")); } + /** List malias members. + * \verbatim + * This function implements @malias/members. + * \endverbatim + * \param player the enactor. + * \param alias name of the alias to list members of. + */ void ! do_malias_members(dbref player, char *alias) { struct mail_alias *m; int i = 0; *************** *** 311,322 **** } ! void ! do_malias_desc(player, alias, desc) ! dbref player; ! char *alias; ! char *desc; { struct mail_alias *m; --- 336,351 ---- } ! /** Describe a malias. ! * \verbatim ! * This implements the @malias/desc command. ! * \endverbatim ! * \param player the enactor. ! * \param alias name of the malias to describe. ! * \param desc description to set. ! */ void ! do_malias_desc(dbref player, char *alias, char *desc) { struct mail_alias *m; *************** *** 334,344 **** } void ! do_malias_chown(player, alias, owner) ! dbref player; ! char *alias; ! char *owner; { struct mail_alias *m; dbref no = NOTHING; --- 363,378 ---- } + /** Change ownership of a malias. + * \verbatim + * This implements the @malias/chown command. + * \endverbatim + * \param player the enactor. + * \param alias name of the malias to chown. + * \param owner name of the new owner. + */ void ! do_malias_chown(dbref player, char *alias, char *owner) { struct mail_alias *m; dbref no = NOTHING; *************** *** 363,373 **** void ! do_malias_rename(player, alias, newname) ! dbref player; ! char *alias; ! char *newname; { struct mail_alias *m; --- 397,412 ---- + /** Change name of a malias. + * \verbatim + * This implements the @malias/rename command. + * \endverbatim + * \param player the enactor. + * \param alias name of the malias to rename. + * \param newname new name for the malias. + */ void ! do_malias_rename(dbref player, char *alias, char *newname) { struct mail_alias *m; *************** *** 398,407 **** void ! do_malias_destroy(player, alias) ! dbref player; ! char *alias; { struct mail_alias *m; m = get_malias(player, alias); --- 437,451 ---- + /** Delete a malias. + * \verbatim + * This implements the @malias/destroy command. + * \endverbatim + * \param player the enactor. + * \param alias name of the malias to destroy. + */ void ! do_malias_destroy(dbref player, char *alias) { struct mail_alias *m; m = get_malias(player, alias); *************** *** 426,436 **** } void ! do_malias_set(player, alias, tolist) ! dbref player; ! char *alias; ! char *tolist; { struct mail_alias *m; int i = 0; --- 470,485 ---- } + /** Set the membership list for a malias. + * \verbatim + * This implements the @malias/set command. + * \endverbatim + * \param player the enactor. + * \param alias name of the malias to set members for. + * \param tolist space-separated list of players to set as members. + */ void ! do_malias_set(dbref player, char *alias, char *tolist) { struct mail_alias *m; int i = 0; *************** *** 524,532 **** void ! do_malias_all(player) ! dbref player; { struct mail_alias *m; int i; --- 573,586 ---- + /** List all maliases. + * \verbatim + * This implements the @malias/list command. + * \endverbatim + * \param player the enactor. + */ void ! do_malias_all(dbref player) { struct mail_alias *m; int i; *************** *** 552,560 **** void ! do_malias_stats(player) ! dbref player; { if (!Hasprivs(player)) notify(player, T("MAIL: Permission denied.")); --- 606,619 ---- + /** Statistics on maliases. + * \verbatim + * This implements the @malias/stat command. + * \endverbatim + * \param player the enactor. + */ void ! do_malias_stats(dbref player) { if (!Hasprivs(player)) notify(player, T("MAIL: Permission denied.")); *************** *** 565,573 **** } } void ! do_malias_nuke(player) ! dbref player; { struct mail_alias *m; int i; --- 624,637 ---- } } + /** Remove all maliases. + * \verbatim + * This implements the @malias/nuke command. + * \endverbatim + * \param player the enactor. + */ void ! do_malias_nuke(dbref player) { struct mail_alias *m; int i; *************** *** 593,605 **** } ! void ! do_malias_privs(player, alias, privs, type) ! dbref player; ! char *alias; ! char *privs; ! int type; /* 0 = nprivs, 1 = mprivs */ { struct mail_alias *m; int *p; --- 657,673 ---- } ! /** Set permisions on maliases. ! * \verbatim ! * This implements @malias/use and @malias/see ! * \endverbatim ! * \param player the enactor. ! * \param alias name of the malias. ! * \param privs string of privs to set. ! * \param type if 1, setting nprivs, if 0, mprivs. ! */ void ! do_malias_privs(dbref player, char *alias, char *privs, int type) { struct mail_alias *m; int *p; *************** *** 620,701 **** } void ! do_malias_mprivs(player, alias, privs) ! dbref player; ! char *alias; ! char *privs; ! { ! const char TYPES[] = " everyone admin members owner"; ! struct mail_alias *m; ! char *ch; ! ! if (!(m = get_malias(player, alias))) { ! notify(player, T("MAIL: I cannot find that alias!")); ! return; ! } ! if (!Wizard(player) && (m->owner != player)) { ! notify(player, T("MAIL: Permission denied.")); ! return; ! } ! if (!strchr("=+-", *privs)) { ! notify(player, ! T ! ("MAIL: First character of permisisons must be one of '=', '+', '-',")); ! notify(player, T(" to set, add, remove permissions, respectively.")); ! return; ! } ! ch = strstr(TYPES, tprintf(" %s", privs + 1)); ! if (!ch) { ! notify_format(player, T("MAIL: Unknown permission type '%s'."), privs + 1); ! notify(player, ! T ! ("Must be one of 'everyone', 'members', 'admin', 'owner' (can be abbreviated).")); ! return; ! } ! if (*privs == '=') { /* setting permissions */ ! if (*ch == 'e') ! m->mflags = 0; ! else if (*ch == 'm') ! m->mflags = ALIAS_MEMBERS; ! else if (*ch == 'a') ! m->mflags = ALIAS_ADMIN; ! else if (*ch == 'o') ! m->mflags = ALIAS_OWNER; ! } else if ((*privs == '+') && m->mflags) { /* adding permissions */ ! if (*ch == 'm') ! m->mflags |= ALIAS_MEMBERS; ! else if (*ch == 'a') ! m->mflags |= ALIAS_ADMIN; ! else if (*ch == 'e') { /* DUMMY */ ! } else if (*ch == 'o') { /* DUMMY */ ! } ! } else if (*privs == '-') { /* removing permissions */ ! if (!m->mflags) ! m->mflags = ALIAS_ADMIN | ALIAS_MEMBERS; ! if (*ch == 'm') ! m->mflags &= ~ALIAS_MEMBERS; ! else if (*ch == 'a') ! m->mflags &= ~ALIAS_ADMIN; ! else if (*ch == 'e') { /* DUMMY */ ! } else if (*ch == 'o') { /* DUMMY */ ! } ! if (!m->mflags) ! m->mflags = ALIAS_OWNER; ! } ! notify_format(player, ! T("MAIL: Permission to list alias '%s' changed to %s"), ! alias, get_privs(m->mflags)); ! } ! ! ! ! ! void ! do_malias_add(player, alias, tolist) ! dbref player; ! char *alias; ! char *tolist; { char *head, *tail, spot; struct mail_alias *m; --- 688,700 ---- } + /** Add players to a malias. + * \param player dbref of enactor. + * \param alias name of malias. + * \param tolist string with list of players to add. + */ void ! do_malias_add(dbref player, char *alias, char *tolist) { char *head, *tail, spot; struct mail_alias *m; *************** *** 797,807 **** void ! do_malias_remove(player, alias, tolist) ! dbref player; ! char *alias; ! char *tolist; { char *head, *tail, spot; struct mail_alias *m; --- 796,808 ---- + /** Remove players from a malias. + * \param player dbref of enactor. + * \param alias name of malias. + * \param tolist string with list of players to remove. + */ void ! do_malias_remove(dbref player, char *alias, char *tolist) { char *head, *tail, spot; struct mail_alias *m; *************** *** 886,917 **** ***********************************************************/ static const char * ! get_privs(flags) ! int flags; ! { ! static char privs[20]; ! privs[0] = '\0'; ! if (!flags) ! strcpy(privs, "EVERYONE"); ! else { ! if (flags & ALIAS_MEMBERS) ! strcpy(privs, "MEMBERS"); ! if (flags & ALIAS_ADMIN) { ! if (*privs) ! strcat(privs, " | "); ! strcat(privs, "ADMIN"); ! } ! if (!(*privs)) ! strcpy(privs, "OWNER"); ! } ! ! return privs; ! } ! ! ! static const char * ! get_shortprivs(m) ! struct mail_alias *m; { static char privs[10]; strcpy(privs, "-- -- "); --- 887,893 ---- ***********************************************************/ static const char * ! get_shortprivs(struct mail_alias *m) { static char privs[10]; strcpy(privs, "-- -- "); *************** *** 942,951 **** } int ! ismember(m, player) ! struct mail_alias *m; ! dbref player; { int i; for (i = 0; i < m->size; i++) { --- 918,931 ---- } + /** Is a player a member of a malias? + * \param m pointer to malias. + * \param player dbref of player. + * \retval 1 player is a member of the malias. + * \retval 0 player is not a member of the malias. + */ int ! ismember(struct mail_alias *m, dbref player) { int i; for (i = 0; i < m->size; i++) { *************** *** 955,964 **** return 0; } ! /* Remove a destroyed player from all maliases */ void ! malias_cleanup(player) ! dbref player; { struct mail_alias *m; int n, i = 0; --- 935,945 ---- return 0; } ! /** Remove a destroyed player from all maliases. ! * \param player player to remove from maliases. ! */ void ! malias_cleanup(dbref player) { struct mail_alias *m; int n, i = 0; *************** *** 972,1013 **** } } struct mail_alias * ! get_malias(player, alias) ! dbref player; ! char *alias; { const char *mal; struct mail_alias *m; int i = 0; - int x = 0; ! if ((*alias == '#') && Hasprivs(player)) { ! x = atoi(alias + 1); ! if (x < 0 || x > (ma_top - 1)) ! return NULL; ! else ! return &malias[x]; ! } else { ! if (*alias != MALIAS_TOKEN) ! return NULL; ! mal = alias + 1; ! for (i = 0; i < ma_top; i++) { ! m = &malias[i]; ! if ((m->owner == player) || (m->nflags == 0) || ! /* ((m->nflags & ALIAS_ADMIN) && Hasprivs(player)) || */ ! Hasprivs(player) || ! ((m->nflags & ALIAS_MEMBERS) && ismember(m, player))) { #ifdef macintosh ! if (!strcasecmp(mal, (char *) (m->name))) #else ! if (!strcasecmp(mal, m->name)) #endif ! return m; ! } } } return NULL; --- 953,988 ---- } } + /** Get a malias pointer with permission checking. + * \param player player dbref, for permission check. + * \param alias name of malias to retrieve. + * \return pointer to malias structure, or NULL if player can't see it. + */ struct mail_alias * ! get_malias(dbref player, char *alias) { const char *mal; struct mail_alias *m; int i = 0; ! if (*alias != MALIAS_TOKEN) ! return NULL; ! mal = alias + 1; ! for (i = 0; i < ma_top; i++) { ! m = &malias[i]; ! if ((m->owner == player) || (m->nflags == 0) || ! /* ((m->nflags & ALIAS_ADMIN) && Hasprivs(player)) || */ ! Hasprivs(player) || ! ((m->nflags & ALIAS_MEMBERS) && ismember(m, player))) { #ifdef macintosh ! if (!strcasecmp(mal, (char *) (m->name))) #else ! if (!strcasecmp(mal, m->name)) #endif ! return m; } } return NULL; *************** *** 1017,1033 **** - - - /*********************************************************** ***** Loading and saving of mail-aliases ***** ***********************************************************/ ! void ! load_malias(fp) ! FILE *fp; { int i, j; char buffer[BUFFER_LEN]; --- 992,1006 ---- /*********************************************************** ***** Loading and saving of mail-aliases ***** ***********************************************************/ ! /** Load maliases from the mail db. ! * \param fp file pointer to read from. ! */ void ! load_malias(FILE * fp) { int i, j; char buffer[BUFFER_LEN]; *************** *** 1076,1085 **** } } ! void ! save_malias(fp) ! FILE *fp; { int i, j; struct mail_alias *m; --- 1049,1059 ---- } } ! /** Write maliases to the maildb ! * \param fp file pointer to write to. ! */ void ! save_malias(FILE * fp) { int i, j; struct mail_alias *m; *************** *** 1110,1119 **** #else /* MAIL_ALIASES */ void ! load_malias(fp) /* Skip mail aliases, */ ! FILE *fp; /* when they shall not be used, */ ! { char buffer[BUFFER_LEN]; char *s; --- 1084,1096 ---- #else /* MAIL_ALIASES */ + /** Dummy function to read and discard malias data in a maildb. + * When MAIL_ALIASES isn't defined, we use this. + * \param fp file pointer to read from. + */ void ! load_malias(FILE * fp) ! { /* Skip mail aliases, */ char buffer[BUFFER_LEN]; char *s; *** 1_7_7.231/src/look.c Sat, 22 Feb 2003 13:33:43 -0600 dunemush (pennmush/c/4_look.c 1.21.1.2.1.9.1.1.1.1.1.2 660) --- 1_7_7.308(w)/src/look.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/4_look.c 1.21.1.2.1.9.1.1.1.1.1.4 660) *************** *** 1,9 **** ! /* look.c */ #include "config.h" #include "copyrite.h" - /* commands which look at things */ #include #include "conf.h" --- 1,14 ---- ! /** ! * \file look.c ! * ! * \brief Commands that look at things. ! * ! * ! */ #include "config.h" #include "copyrite.h" #include #include "conf.h" *************** *** 28,33 **** --- 33,39 ---- extern void decompile_flags(dbref player, dbref thing, const char *name); /* from flags.c */ extern void decompile_powers(dbref player, dbref thing, const char *name); /* from flags.c */ + extern const char *channel_description(dbref player); extern PRIV attr_privs[]; static void look_exits(dbref player, dbref loc, const char *exit_name); *************** *** 42,50 **** (dbref player, dbref thing, char const *pattern, ATTR *atr, void *args); static int look_helper_veiled (dbref player, dbref thing, char const *pattern, ATTR *atr, void *args); - #ifdef CHAT_SYSTEM - static const char *channel_description(dbref player); - #endif void decompile_atrs(dbref player, dbref thing, const char *name, const char *pattern, const char *prefix, int skipdef); void decompile_locks(dbref player, dbref thing, const char *name, int skipdef); --- 48,53 ---- *************** *** 393,408 **** } } void look_room(dbref player, dbref loc, enum look_type style) { - /* look at a room. Flag value of this function: - * 0 -- normal look, caused by "look" command. - * 1 -- remote look, done through a TRANSPARENTED exit. - * 2 -- auto-look, caused by moving. Obey TERSE. - * 3 -- remote look, through a CLOUDY TRANSPARENTED exit: desc only - * 4 -- remote look, though a CLOUDY (!TRANS) exit: contents only - */ PUEBLOBUFF; ATTR *a; --- 396,414 ---- } } + /** Look at a room. + * The style parameter tells you what kind of look it is: + * LOOK_NORMAL (caused by "look"), LOOK_TRANS (look through a transparent + * exit), LOOK_AUTO (automatic look, by moving), + * LOOK_CLOUDY (look through a cloudy exit - contents only), LOOK_CLOUDYTRANS + * (look through a cloudy transparent exit - desc only). + * \param player the looker. + * \param loc room being looked at. + * \param style how the room is being looked at. + */ void look_room(dbref player, dbref loc, enum look_type style) { PUEBLOBUFF; ATTR *a; *************** *** 523,528 **** --- 529,537 ---- restore_global_env("look_desc_save", preserves); } + /** An automatic look (due to motion). + * \param player the looker. + */ void do_look_around(dbref player) { *************** *** 532,540 **** look_room(player, loc, LOOK_AUTO); /* auto-look. Obey TERSE. */ } void do_look_at(dbref player, const char *name, int key) - /* 0 is normal, 1 is "outside" */ { dbref thing; dbref loc; --- 541,553 ---- look_room(player, loc, LOOK_AUTO); /* auto-look. Obey TERSE. */ } + /** Look at something. + * \param player the looker. + * \param name name of object to look at. + * \param key 0 for normal look, 1 for look/outside. + */ void do_look_at(dbref player, const char *name, int key) { dbref thing; dbref loc; *************** *** 620,647 **** } ! #ifdef CHAT_SYSTEM ! static const char * ! channel_description(dbref player) ! { ! static char buf[BUFFER_LEN]; ! char *bp; ! CHANLIST *c; ! ! if ((c = Chanlist(player))) { ! bp = buf; ! safe_str(T("Channels:"), buf, &bp); ! for (; c; c = c->next) { ! safe_chr(' ', buf, &bp); ! safe_str(ChanName(c->chan), buf, &bp); ! } ! *bp = '\0'; ! } else ! strcpy(buf, T("Channels: *NONE*")); ! return buf; ! } ! #endif ! void do_examine(dbref player, const char *name, int brief, int all) { --- 633,644 ---- } ! /** Examine an object. ! * \param player the enactor doing the examining. ! * \param name name of object to examine. ! * \param brief if 1, a brief examination. ! * \param all if 1, include veiled attributes. ! */ void do_examine(dbref player, const char *name, int brief, int all) { *************** *** 739,746 **** notify_format(player, T("Powers: %s"), power_description(thing)); #ifdef CHAT_SYSTEM ! if (IsPlayer(thing) || Chanlist(thing)) ! notify(player, channel_description(thing)); #endif /* CHAT_SYSTEM */ notify_format(player, T("Warnings checked: %s"), unparse_warnings(thing)); --- 736,742 ---- notify_format(player, T("Powers: %s"), power_description(thing)); #ifdef CHAT_SYSTEM ! notify(player, channel_description(thing)); #endif /* CHAT_SYSTEM */ notify_format(player, T("Warnings checked: %s"), unparse_warnings(thing)); *************** *** 855,860 **** --- 851,859 ---- mush_free((Malloc_t) tbuf, "string"); } + /** The score command: check a player's money. + * \param player the enactor. + */ void do_score(dbref player) { *************** *** 864,869 **** --- 863,871 ---- Pennies(player), Pennies(player) == 1 ? MONEY : MONIES); } + /** The inventory command. + * \param player the enactor. + */ void do_inventory(dbref player) { *************** *** 880,885 **** --- 882,892 ---- do_score(player); } + /** The find command. + * \param player the enactor. + * \param name name pattern to search for. + * \param argv array of additional arguments (for dbref ranges) + */ void do_find(dbref player, const char *name, char *argv[]) { *************** *** 925,931 **** notify_format(player, T("*** %d objects found ***"), count); } ! /* check the current location for bugs */ void do_sweep(dbref player, const char *arg1) { --- 932,944 ---- notify_format(player, T("*** %d objects found ***"), count); } ! /** Sweep the current location for bugs. ! * \verbatim ! * This implements @sweep. ! * \endverbatim ! * \param player the enactor. ! * \param arg1 optional area to sweep. ! */ void do_sweep(dbref player, const char *arg1) { *************** *** 1046,1051 **** --- 1059,1071 ---- } } + /** Locate a player. + * \verbatim + * This implements @whereis. + * \endverbatim + * \param player the enactor. + * \param name name of player to locate. + */ void do_whereis(dbref player, const char *name) { *************** *** 1072,1077 **** --- 1092,1107 ---- } + /** Find the entrances to a room. + * \verbatim + * This implements @entrances, which finds things linked to an object + * (typically exits, but can be any type). + * \endverbatim + * \param player the enactor. + * \param where name of object to find entrances on. + * \param argv array of arguments for dbref range limitation. + * \param val what type of 'entrances' to find. + */ void do_entrances(dbref player, const char *where, char *argv[], enum ent_type val) { *************** *** 1187,1196 **** } } struct dh_args { ! char const *prefix; ! char const *name; ! int skipdef; }; static int --- 1217,1227 ---- } } + /** Store arguments for decompile_helper() */ struct dh_args { ! char const *prefix; /**< Decompile/tf prefix */ ! char const *name; /**< Decompile object name */ ! int skipdef; /**< Skip default flags on attributes if true */ }; static int *************** *** 1241,1246 **** --- 1272,1285 ---- return 1; } + /** Decompile attributes on an object. + * \param player the enactor. + * \param thing object with attributes to decompile. + * \param name name to refer to object by in decompile. + * \param pattern pattern to match attributes to decompile. + * \param prefix prefix to use for decompile/tf. + * \param skipdef if true, skip showing default attribute flags. + */ void decompile_atrs(dbref player, dbref thing, const char *name, const char *pattern, const char *prefix, int skipdef) *************** *** 1254,1259 **** --- 1293,1304 ---- notify(player, T("@@ No attributes found. @@")); } + /** Decompile locks on an object. + * \param player the enactor. + * \param thing object with attributes to decompile. + * \param name name to refer to object by in decompile. + * \param skipdef if true, skip showing default lock flags. + */ void decompile_locks(dbref player, dbref thing, const char *name, int skipdef) { *************** *** 1283,1288 **** --- 1328,1342 ---- } } + /** Decompile. + * \verbatim + * This implements @decompile. + * \endverbatim + * \param player the enactor. + * \param name name of object to decompile. + * \param dbflag flag for type of decompile to perform. + * \param skipdef if true, skip showing default flags on attributes/locks. + */ void do_decompile(dbref player, const char *name, enum dec_type dbflag, int skipdef) { *** 1_7_7.231/src/log.c Thu, 26 Dec 2002 14:20:42 -0600 dunemush (pennmush/c/5_log.c 1.10.1.2.2.4.1.1.2.2 660) --- 1_7_7.308(w)/src/log.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/5_log.c 1.10.1.2.2.4.1.1.2.2.1.3 660) *************** *** 1,4 **** ! /* log.c */ #include "copyrite.h" #include "config.h" --- 1,10 ---- ! /** ! * \file log.c ! * ! * \brief Logging for PennMUSH. ! * ! * ! */ #include "copyrite.h" #include "config.h" *************** *** 24,32 **** #include "log.h" #include "confmagic.h" ! char *quick_unparse(dbref object); ! void start_log(FILE ** fp, const char *filename); ! void end_log(FILE * fp); #ifdef macintosh #include "PMInit.h" --- 30,38 ---- #include "log.h" #include "confmagic.h" ! static char *quick_unparse(dbref object); ! static void start_log(FILE ** fp, const char *filename); ! static void end_log(FILE * fp); #ifdef macintosh #include "PMInit.h" *************** *** 40,48 **** FILE *cmdlog_fp; ! char * ! quick_unparse(object) ! dbref object; { static char buff[BUFFER_LEN], *bp; --- 46,53 ---- FILE *cmdlog_fp; ! static char * ! quick_unparse(dbref object) { static char buff[BUFFER_LEN], *bp; *************** *** 66,75 **** return buff; } ! void ! start_log(fp, filename) ! FILE **fp; ! const char *filename; { char newfilename[256] = "\0"; --- 71,78 ---- return buff; } ! static void ! start_log(FILE ** fp, const char *filename) { char newfilename[256] = "\0"; *************** *** 91,98 **** fflush(*fp); } void ! start_all_logs() { #ifndef SINGLE_LOGFILE start_log(&connlog_fp, CONNLOG); --- 94,103 ---- fflush(*fp); } + /** Open all logfiles. + */ void ! start_all_logs(void) { #ifndef SINGLE_LOGFILE start_log(&connlog_fp, CONNLOG); *************** *** 105,113 **** #endif /* SINGLE_LOGFILE */ } ! void ! end_log(fp) ! FILE *fp; { if (fp != stderr) { fprintf(fp, "END OF LOG.\n"); --- 110,117 ---- #endif /* SINGLE_LOGFILE */ } ! static void ! end_log(FILE * fp) { if (fp != stderr) { fprintf(fp, "END OF LOG.\n"); *************** *** 116,123 **** } } void ! end_all_logs() { #ifndef SINGLE_LOGFILE /* close up the log files */ --- 120,129 ---- } } + /** Close all logfiles. + */ void ! end_all_logs(void) { #ifndef SINGLE_LOGFILE /* close up the log files */ *************** *** 130,141 **** } void WIN32_CDECL do_rawlog(int logtype, const char *fmt, ...) { - /* take a log type and format list and args, write to appropriate logfile. - * log types are defined in log.h - */ struct tm *ttm; char timebuf[18]; char tbuf1[BUFFER_LEN + 50]; --- 136,150 ---- } + /** Log a raw message. + * take a log type and format list and args, write to appropriate logfile. + * log types are defined in log.h + * \param logtype type of log to print message to. + * \param fmt format string for message. + */ void WIN32_CDECL do_rawlog(int logtype, const char *fmt, ...) { struct tm *ttm; char timebuf[18]; char tbuf1[BUFFER_LEN + 50]; *************** *** 185,197 **** fflush(f); } void WIN32_CDECL do_log(int logtype, dbref player, dbref object, const char *fmt, ...) { - /* take a log type and format list and args, write to appropriate logfile. - * log types are defined in mushdb.h - */ - /* tbuf1 had 50 extra chars because we might pass this function * both a label string and a command which could be up to BUFFER_LEN * in length - for example, when logging @forces --- 194,211 ---- fflush(f); } + /** Log a message, with useful information. + * take a log type and format list and args, write to appropriate logfile. + * log types are defined in log.h. Unlike do_rawlog, this version + * tags messages with prefixes, and uses dbref information passed to it. + * \param logtype type of log to print message to. + * \param player dbref that generated the log message. + * \param object second dbref involved in log message (e.g. force logs) + * \param fmt mesage format string. + */ void WIN32_CDECL do_log(int logtype, dbref player, dbref object, const char *fmt, ...) { /* tbuf1 had 50 extra chars because we might pass this function * both a label string and a command which could be up to BUFFER_LEN * in length - for example, when logging @forces *************** *** 262,280 **** } } void ! do_logwipe(player, logtype, str) ! dbref player; ! int logtype; ! char *str; { - /* Wipe out a game log. This is intended for those emergencies where - * the log has grown out of bounds, overflowing the disk quota, etc. - * Because someone with the god password can use this command to wipe - * out 'intrusion' traces, we also require the log_wipe_passwd given - * in mush.cnf - */ - if (strcmp(str, LOG_WIPE_PASSWD)) { const char *lname; switch (logtype) { --- 276,293 ---- } } + /** Wipe out a game log. This is intended for those emergencies where + * the log has grown out of bounds, overflowing the disk quota, etc. + * Because someone with the god password can use this command to wipe + * out 'intrusion' traces, we also require the log_wipe_passwd given + * in mush.cnf + * \param player the enactor. + * \param logtype type of log to wipe. + * \param str password for wiping logs. + */ void ! do_logwipe(dbref player, int logtype, char *str) { if (strcmp(str, LOG_WIPE_PASSWD)) { const char *lname; switch (logtype) { *** 1_7_7.231/src/lock.c Thu, 23 Jan 2003 10:24:07 -0600 dunemush (pennmush/c/6_lock.c 1.17.1.13.1.1.1.4 660) --- 1_7_7.308(w)/src/lock.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/6_lock.c 1.17.1.13.1.1.1.8 660) *************** *** 1,8 **** ! /* lock.c */ ! ! /* * This is the core of Ralph Melton's rewrite of the @lock system. ! * These are some of my underlying assumptions: * * 1) Locks are checked many more times than they are set, so it is * quite worthwhile to spend time when setting locks if it expedites --- 1,12 ---- ! /** ! * \file lock.c ! * ! * \brief Locks for PennMUSH. ! * ! * \verbatim ! * * This is the core of Ralph Melton's rewrite of the @lock system. ! * These are some of the underlying assumptions: * * 1) Locks are checked many more times than they are set, so it is * quite worthwhile to spend time when setting locks if it expedites *************** *** 19,24 **** --- 23,30 ---- * than for people to check for locks in MUSHcode. Therefore, it is * reasonable to incur a minor slowdown for checking locks in MUSHcode * in order to speed up the server's checking. + * + * \endverbatim */ #include "copyrite.h" *************** *** 118,123 **** --- 124,131 ---- static lock_type check_lock_type(dbref player, dbref thing, lock_type name); static int delete_lock(dbref player, dbref thing, lock_type type); static int can_write_lock(dbref player, dbref thing, lock_list *lock); + static lock_list *getlockstruct(dbref thing, lock_type type); + static lock_list *getlockstruct_noparent(dbref thing, lock_type type); /* Assuming 4096 byte pages */ #define LOCKS_PER_PAGE 200 *************** *** 126,137 **** --- 134,154 ---- static lock_list *next_free_lock(void); static void free_lock(lock_list *ll); + + /** Return a list of lock flag characters. + * \param ll pointer to a lock. + * \return string of lock flag characters. + */ const char * lock_flags(lock_list *ll) { return privs_to_letters(lock_privs, L_FLAGS(ll)); } + /** Return a list of lock flag names. + * \param ll pointer to a lock. + * \return string of lock flag names, space-separated. + */ const char * lock_flags_long(lock_list *ll) { *************** *** 151,156 **** --- 168,174 ---- return f; } + /** Initialize the lock strtree. */ void init_locks(void) { *************** *** 226,233 **** free_list = ll; } ! /* Given a lock type, find a lock. ! * This depends on the implementation of lock_type as a string. */ struct boolexp * getlock(dbref thing, lock_type type) --- 244,253 ---- free_list = ll; } ! /** Given a lock type, find a lock, possibly checking parents. ! * \param thing object on which lock is to be found. ! * \param type type of lock to find. ! * \return pointer to boolexp of lock. */ struct boolexp * getlock(dbref thing, lock_type type) *************** *** 239,244 **** --- 259,269 ---- return L_KEY(ll); } + /** Given a lock type, find a lock without checking parents. + * \param thing object on which lock is to be found. + * \param type type of lock to find. + * \return pointer to boolexp of lock. + */ struct boolexp * getlock_noparent(dbref thing, lock_type type) { *************** *** 249,255 **** return L_KEY(ll); } ! lock_list * getlockstruct(dbref thing, lock_type type) { lock_list *ll; --- 274,280 ---- return L_KEY(ll); } ! static lock_list * getlockstruct(dbref thing, lock_type type) { lock_list *ll; *************** *** 273,279 **** return NULL; } ! lock_list * getlockstruct_noparent(dbref thing, lock_type type) { lock_list *ll = Locks(thing); --- 298,304 ---- return NULL; } ! static lock_list * getlockstruct_noparent(dbref thing, lock_type type) { lock_list *ll = Locks(thing); *************** *** 291,297 **** } ! /* Is this lock in our set of canonical locks? */ lock_type match_lock(lock_type type) { --- 316,325 ---- } ! /** Determine if a lock type is one of the standard types or not. ! * \param type type of lock to check. ! * \return canonical lock type or NULL ! */ lock_type match_lock(lock_type type) { *************** *** 304,310 **** return NULL; } ! /* Return the proper entry from lock_types, or NULL */ const lock_list * get_lockproto(lock_type type) { --- 332,341 ---- return NULL; } ! /** Return the proper entry from lock_types, or NULL. ! * \param type of lock to look up. ! * \return lock_types entry for lock. ! */ const lock_list * get_lockproto(lock_type type) { *************** *** 318,328 **** } ! /* Set the lock type on thing to boolexp. * This is a primitive routine, to be called by other routines. * It will go somewhat wonky if given a NULL boolexp. * It will allocate memory if called with a string that is not already * in the lock table. */ int add_lock(dbref player, dbref thing, lock_type type, struct boolexp *key, --- 349,367 ---- } ! /** Add a lock to an object (primitive). ! * Set the lock type on thing to boolexp. * This is a primitive routine, to be called by other routines. * It will go somewhat wonky if given a NULL boolexp. * It will allocate memory if called with a string that is not already * in the lock table. + * \param player the enactor, for permission checking. + * \param thing object on which to set the lock. + * \param type type of lock to set. + * \param key lock boolexp pointer (should not be NULL!). + * \param flags lock flags. + * \retval 0 failure. + * \retval 1 success. */ int add_lock(dbref player, dbref thing, lock_type type, struct boolexp *key, *************** *** 382,390 **** return 1; } ! /* Set the lock type on thing to boolexp. * Used only on db load, when we can't safely test the player's * permissions because they're not loaded yet. */ int add_lock_raw(dbref player, dbref thing, lock_type type, struct boolexp *key, --- 421,440 ---- return 1; } ! /** Add a lock to an object on db load. ! * Set the lock type on thing to boolexp. * Used only on db load, when we can't safely test the player's * permissions because they're not loaded yet. + * This is a primitive routine, to be called by other routines. + * It will go somewhat wonky if given a NULL boolexp. + * It will allocate memory if called with a string that is not already + * in the lock table. + * \param player lock creator. + * \param thing object on which to set the lock. + * \param type type of lock to set. + * \param key lock boolexp pointer (should not be NULL!). + * \param flags lock flags. + * \retval 0 failure. */ int add_lock_raw(dbref player, dbref thing, lock_type type, struct boolexp *key, *************** *** 435,441 **** free_lock(ll); } ! /* Another primitive routine. */ int delete_lock(dbref player, dbref thing, lock_type type) { --- 485,496 ---- free_lock(ll); } ! /** Delete a lock from an object (primitive). ! * Another primitive routine. ! * \param player the enactor, for permission checking. ! * \param thing object on which to remove the lock. ! * \param type type of lock to remove. ! */ int delete_lock(dbref player, dbref thing, lock_type type) { *************** *** 459,467 **** return 1; } void ! free_locks(ll) ! lock_list *ll; { lock_list *ll2; while (ll) { --- 514,525 ---- return 1; } + /** Free all locks in a list. + * Used by the object destruction routines. + * \param ll pointer to list of locks. + */ void ! free_locks(lock_list *ll) { lock_list *ll2; while (ll) { *************** *** 472,478 **** } ! /* Check to see that the lock type is a valid type. * If it's not in our lock table, it's not valid, * unless it begins with 'user:' or an abbreviation thereof, * in which case the lock type is the part after the :. --- 530,536 ---- } ! /** Check to see that the lock type is a valid type. * If it's not in our lock table, it's not valid, * unless it begins with 'user:' or an abbreviation thereof, * in which case the lock type is the part after the :. *************** *** 480,485 **** --- 538,548 ---- * will confuse our db-reading routines. * * Might destructively modify name. + * + * \param player the enactor, for notification. + * \param thing object on which to check the lock. + * \param name name of lock type. + * \return lock type, or NULL. */ static lock_type check_lock_type(dbref player, dbref thing, lock_type name) *************** *** 522,527 **** --- 585,598 ---- return sp; } + /** Unlock a lock (user interface). + * \verbatim + * This implements @unlock. + * \endverbatim + * \param player the enactor. + * \param name name of object to unlock. + * \param type type of lock to unlock. + */ void do_unlock(dbref player, const char *name, lock_type type) { *************** *** 550,561 **** } } void ! do_lock(player, name, keyname, type) ! dbref player; ! const char *name; ! const char *keyname; ! lock_type type; { lock_type real_type; dbref thing; --- 621,637 ---- } } + /** Set/lock a lock (user interface). + * \verbatim + * This implements @lock. + * \endverbatim + * \param player the enactor. + * \param name name of object to lock. + * \param keyname key to lock the lock to, as a string. + * \param type type of lock to lock. + */ void ! do_lock(dbref player, const char *name, const char *keyname, lock_type type) { lock_type real_type; dbref thing; *************** *** 609,614 **** --- 685,695 ---- } } + /** Copy the locks from one object to another. + * \param player the enactor. + * \param orig the source object. + * \param clone the destination object. + */ void clone_locks(dbref player, dbref orig, dbref clone) { *************** *** 620,632 **** } ! /* Evaluate lock ltype on thing for player */ int eval_lock(dbref player, dbref thing, lock_type ltype) { return eval_boolexp(player, getlock(thing, ltype), thing); } int lock_visual(dbref thing, lock_type ltype) { --- 701,726 ---- } ! /** Evaluate a lock. ! * Evaluate lock ltype on thing for player. ! * \param player dbref attempting to pass the lock. ! * \param thing object containing the lock. ! * \param ltype type of lock to check. ! * \retval 1 player passes the lock. ! * \retval 0 player does not pass the lock. ! */ int eval_lock(dbref player, dbref thing, lock_type ltype) { return eval_boolexp(player, getlock(thing, ltype), thing); } + /** Determine if a lock is visual. + * \param thing object containing the lock. + * \param ltype type of lock to check. + * \retval (non-zero) lock is visual. + * \retval 0 lock is not visual. + */ int lock_visual(dbref thing, lock_type ltype) { *************** *** 637,642 **** --- 731,744 ---- return 0; } + /** Set flags on a lock (user interface). + * \verbatim + * This implements @lset. + * \endverbatim + * \param player the enactor. + * \param what string in the form obj/lock. + * \param flags list of flags to set. + */ void do_lset(dbref player, char *what, char *flags) { *** 1_7_7.231/src/info_slave.c Sun, 09 Feb 2003 14:38:28 -0600 dunemush (pennmush/c/7_info_slave 1.9.1.4.1.3 660) --- 1_7_7.308(w)/src/info_slave.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/7_info_slave 1.9.1.4.1.4 660) *************** *** 1,4 **** ! /* info_slave.c */ #include "copyrite.h" #include "config.h" --- 1,14 ---- ! /** ! * \file info_slave.c ! * ! * \brief The information slave process. ! * ! * When running PennMUSH under Unix, a second process (info_slave) is ! * started and the server farms out DNS and ident lookups to the ! * info_slave, and reads responses from the info_slave asynchronously. ! * Communication between server and slave is by means of a local socket. ! * ! */ #include "copyrite.h" #include "config.h" *** 1_7_7.231/src/ident.c Sun, 01 Dec 2002 21:14:41 -0600 dunemush (pennmush/c/8_ident.c 1.19.1.4.1.12 660) --- 1_7_7.308(w)/src/ident.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/8_ident.c 1.19.1.4.1.13 660) *************** *** 1,11 **** ! /* ! ** ident.c High-level calls to the ident lib ! ** ! ** Author: Pär Emanuelsson ! ** Hacked by: Peter Eriksson ! ! ** Many changes by Shawn Wagner to be protocol independent ! ** for PennMUSH */ #include "config.h" --- 1,13 ---- ! /** ! * \file ident.c ! * ! * \brief High-level calls to the ident library. ! * ! * Author: Pär Emanuelsson ! * Hacked by: Peter Eriksson ! * ! * Many changes by Shawn Wagner to be protocol independent ! * for PennMUSH */ #include "config.h" *************** *** 64,72 **** /* Low-level calls and macros */ typedef struct { ! int fd; ! char buf[IDBUFSIZE]; } ident_t; --- 66,75 ---- /* Low-level calls and macros */ + /** Structure to track an ident connection. */ typedef struct { ! int fd; /**< file descriptor to read from. */ ! char buf[IDBUFSIZE]; /**< buffer to hold ident data. */ } ident_t; *************** *** 105,110 **** --- 108,121 ---- return ident_query(&localaddr.addr, llen, &remoteaddr.addr, rlen, timeout); } + /** Perform an ident query and return the result. + * \param laddr local socket address data. + * \param llen local socket address data length. + * \param raddr remote socket address data. + * \param rlen remote socket address data length. + * \param timeout pointer to timeout value for query. + * \return ident responses in IDENT pointer, or NULL. + */ IDENT * ident_query(struct sockaddr *laddr, socklen_t llen, struct sockaddr *raddr, socklen_t rlen, int *timeout) *************** *** 152,157 **** --- 163,175 ---- return ident; /* At last! */ } + /** Perform an ident lookup and return the remote identifier as a + * newly allocated string. This function allocates memory that + * should be freed by the caller. + * \param fd socket to use for ident lookup. + * \param timeout pointer to timeout value for lookup. + * \return allocated string containing identifier, or NULL. + */ char * ident_id(int fd, int *timeout) { *************** *** 166,171 **** --- 184,192 ---- return id; } + /** Free an IDENT structure and all elements. + * \param id pointer to IDENT structure to free. + */ void ident_free(IDENT *id) { *** 1_7_7.231/src/game.c Wed, 19 Feb 2003 10:08:06 -0600 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.2.1.16 660) --- 1_7_7.308(w)/src/game.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.2 660) *************** *** 1,4 **** ! /* game.c */ #include "copyrite.h" #include "config.h" --- 1,10 ---- ! /** ! * \file game.c ! * ! * \brief The main game driver. ! * ! * ! */ #include "copyrite.h" #include "config.h" *************** *** 124,130 **** void do_dolist(dbref player, char *list, char *command, dbref cause, unsigned int flags); void do_uptime(dbref player, int mortal); ! char *make_new_epoch_file(const char *basename, int the_epoch); void dest_info(dbref thing, dbref tt); #ifdef HAS_GETRUSAGE void rusage_stats(void); --- 130,136 ---- void do_dolist(dbref player, char *list, char *command, dbref cause, unsigned int flags); void do_uptime(dbref player, int mortal); ! static char *make_new_epoch_file(const char *basename, int the_epoch); void dest_info(dbref thing, dbref tt); #ifdef HAS_GETRUSAGE void rusage_stats(void); *************** *** 148,158 **** Pid_t forked_dump_pid = -1; ! /* ! * used to allocate storage for temporary stuff, cleared before command ! * execution */ - void do_dump(dbref player, char *num, enum dump_type flag) { --- 154,167 ---- Pid_t forked_dump_pid = -1; ! /** User command to dump the database. ! * \verbatim ! * This implements the @dump command. ! * \endverbatim ! * \param player the enactor, for permission checking. ! * \param num checkpoint interval, as a string. ! * \param flag type of dump. */ void do_dump(dbref player, char *num, enum dump_type flag) { *************** *** 208,216 **** } ! /* print out stuff into error file */ void ! report() { if (GoodObject(cplr)) do_rawlog(LT_TRACE, T("TRACE: Cmd:%s\tdepth:%d\tby #%d at #%d"), ccom, --- 217,227 ---- } ! /** Print global variables to the trace log. ! * This function is used for error reporting. ! */ void ! report(void) { if (GoodObject(cplr)) do_rawlog(LT_TRACE, T("TRACE: Cmd:%s\tdepth:%d\tby #%d at #%d"), ccom, *************** *** 220,227 **** } #ifdef HAS_GETRUSAGE void ! rusage_stats() { struct rusage usage; int pid; --- 231,240 ---- } #ifdef HAS_GETRUSAGE + /** Log process statistics to the error log. + */ void ! rusage_stats(void) { struct rusage usage; int pid; *************** *** 252,257 **** --- 265,277 ---- #endif /* HAS_GETRUSAGE */ + /** User interface to shut down the MUSH. + * \verbatim + * This implements the @shutdown command. + * \endverbatim + * \param player the enactor, for permission checking. + * \param flag type of shutdown to perform. + */ void do_shutdown(dbref player, enum shutdown_type flag) { *************** *** 288,294 **** jmp_buf db_err; static int ! dump_database_internal() { char realdumpfile[2048]; char realtmpfl[2048]; --- 308,314 ---- jmp_buf db_err; static int ! dump_database_internal(void) { char realdumpfile[2048]; char realtmpfl[2048]; *************** *** 402,407 **** --- 422,434 ---- return 0; } + /** Crash gracefully. + * This function is called when something disastrous happens - typically + * a failure to malloc memory or a signal like segfault. + * It logs the fault, does its best to dump a panic database, and + * exits abruptly. This function does not return. + * \param message message to log to the error log. + */ void panic(const char *message) { *************** *** 447,454 **** } } void ! dump_database() { epoch++; --- 474,485 ---- } } + /** Dump the database. + * This function is a wrapper for dump_database_internal() that does + * a little logging before and after the dump. + */ void ! dump_database(void) { epoch++; *************** *** 457,462 **** --- 488,502 ---- do_rawlog(LT_ERR, "DUMPING: %s.#%d# (done)", dumpfile, epoch); } + /** Dump a database, possibly by forking the process. + * This function calls dump_database_internal() to dump the MUSH + * databases. If we're configured to do so, it forks first, so that + * the child process can perform the dump while the parent continues + * to run the MUSH for the players. If we can't fork, this function + * warns players online that a dump is taking place and the game + * may pause. + * \param forking if 1, attempt a forking dump. + */ void fork_and_dump(int forking) { *************** *** 524,531 **** } } void ! do_restart() { dbref thing; ATTR *s; --- 564,576 ---- } } + /** Start up the MUSH. + * This function does all of the work that's necessary to start up + * MUSH objects and code for the game. It sets up player aliases, + * fixes null object names, and triggers all object startups. + */ void ! do_restart(void) { dbref thing; ATTR *s; *************** *** 573,578 **** --- 618,630 ---- extern void init_names(void); extern struct db_stat_info current_state; + /** Initialize game structures and read the most of the configuration file. + * This function runs before we read in the databases. It is responsible + * for recording the MUSH start time, setting up all the hash and + * prefix tables and similar structures, and reading the portions of the + * config file that don't require database load. + * \param conf file name of the configuration file. + */ void init_game_config(const char *conf) { *************** *** 615,626 **** config_file_startup(conf, 0); } ! /* Code that should be run after dbs are loaded (usually because we ! * need to have the flag table loaded, or because they run last. */ void init_game_postdb(const char *conf) { /* Commands and functions require the flag table for restrictions */ command_init_preconfig(); command_init_postconfig(); --- 667,688 ---- config_file_startup(conf, 0); } ! /** Post-db-load configuration. ! * This function contains code that should be run after dbs are loaded ! * (usually because we need to have the flag table loaded, or because they ! * run last). It reads in the portions of the config file that rely ! * on flags being defined. ! * \param conf file name of the configuration file. */ void init_game_postdb(const char *conf) { + /* access file stuff */ + read_access_file(); + /* initialize random number generator */ + initialize_mt(); + /* set up signal handlers for the timer */ + init_timer(); /* Commands and functions require the flag table for restrictions */ command_init_preconfig(); command_init_postconfig(); *************** *** 634,641 **** } int ! init_game_dbs() { FILE *f; --- 696,708 ---- } + /** Read the game databases. + * This function reads in the object, mail, and chat databases. + * \retval -1 error. + * \retval 0 success. + */ int ! init_game_dbs(void) { FILE *f; *************** *** 764,782 **** if (panicdb) db_close(f); - /* now do access file stuff */ - read_access_file(); - - /* initialize random number generator */ - initialize_mt(); - /* set up dumper */ strcpy(dumpfile, outfile); - init_timer(); return 0; } void do_readcache(dbref player) { --- 831,848 ---- if (panicdb) db_close(f); /* set up dumper */ strcpy(dumpfile, outfile); return 0; } + /** Read cached text files. + * \verbatim + * This implements the @readcache function. + * \endverbatim + * \param player the enactor, for permission checking. + */ void do_readcache(dbref player) { *************** *** 791,802 **** #define list_match(x) list_check(x, player, '$', ':', cptr, 0) #define cmd_match(x) atr_comm_match(x, player, '$', ':', cptr, 0, NULL, NULL); void process_command(dbref player, char *command, dbref cause, int from_port) - /* from_port = 1 if this is direct input from a port (i.e. typed - * directly by a player). attrib sets - * don't get parsed then. - */ { int a; char *p; /* utility */ --- 857,881 ---- #define list_match(x) list_check(x, player, '$', ':', cptr, 0) #define cmd_match(x) atr_comm_match(x, player, '$', ':', cptr, 0, NULL, NULL); + /** Attempt to match and execute a command. + * This function performs some sanity checks and then attempts to + * run a command. It checks, in order: home, built-in commands, + * enter aliases, leave aliases, $commands on neighboring objects or + * the player, $commands on the container, $commands on inventory, + * exits in the zone master room, $commands on objects in the ZMR, + * $commands on the ZMO, $commands on the player's zone, exits in the + * master room, and $commands on objectrs in the master room. + * + * When a command is directly input from a socket, we don't parse + * the value in attribute sets. + * + * \param player the enactor. + * \param command command to match and execute. + * \param cause object which caused the command to be executed. + * \param from_port if 1, the command was direct input from a socket. + */ void process_command(dbref player, char *command, dbref cause, int from_port) { int a; char *p; /* utility */ *************** *** 916,954 **** /* now do check on zones */ if ((!a) && (Zone(Location(player)) != NOTHING)) { if (IsRoom(Zone(Location(player)))) { ! ! /* zone of player's location is a zone master room */ ! ! if (Location(player) != Zone(player)) { ! ! /* check zone master room exits */ ! if (remote_exit(player, cptr)) { ! if (!Mobile(player)) ! goto done; ! else { ! do_move(player, cptr, 2); ! goto done; ! } ! } else ! /* check commands in the zone master room if no exits ! * can match more than one $command in zone master room ! */ ! a += list_match(Contents(Zone(Location(player)))); ! } /* end of zone master room check */ ! } else ! /* try matching commands on area zone object if GLOBALS ! * aren't in use or zone object isn't a room */ ! if ((!a) && (Zone(Location(player)) != NOTHING)) a += cmd_match(Zone(Location(player))); } - /* end of matching on zone of player's location */ /* if nothing matched with zone master room/zone object, try * matching zone commands on the player's personal zone */ if ((!a) && (Zone(player) != NOTHING) && (Zone(Location(player)) != Zone(player))) { ! a += cmd_match(Zone(player)); } /* end of zone stuff */ /* check global exits only if no other commands are matched */ --- 995,1028 ---- /* now do check on zones */ if ((!a) && (Zone(Location(player)) != NOTHING)) { if (IsRoom(Zone(Location(player)))) { ! /* zone of player's location is a zone master room, ! * so we check for exits and commands */ ! /* check zone master room exits */ ! if (remote_exit(player, cptr)) { ! if (!Mobile(player)) ! goto done; ! else { ! do_move(player, cptr, 2); ! goto done; ! } ! } else ! a += list_match(Contents(Zone(Location(player)))); ! } else a += cmd_match(Zone(Location(player))); } /* if nothing matched with zone master room/zone object, try * matching zone commands on the player's personal zone */ if ((!a) && (Zone(player) != NOTHING) && (Zone(Location(player)) != Zone(player))) { ! if (IsRoom(Zone(player))) ! /* Player's personal zone is a zone master room, so we ! * also check commands on objects in that room ! */ ! a += list_match(Contents(Zone(player))); ! else ! a += cmd_match(Zone(player)); } /* end of zone stuff */ /* check global exits only if no other commands are matched */ *************** *** 974,979 **** --- 1048,1054 ---- do_log(LT_HUH, player, 0, "%s", unp); } } + /* command has been executed. Free up memory. */ done: *************** *** 985,990 **** --- 1060,1071 ---- #undef list_match #undef cmd_match + /** Check to see if a string matches part of a semicolon-separated list. + * \param command string to match. + * \param list semicolon-separated list of aliases to match against. + * \retval 1 string matched an alias. + * \retval 0 string failed to match an alias. + */ int check_alias(const char *command, const char *list) { *************** *** 1008,1014 **** return 0; } ! /* match a list of things */ int list_check(dbref thing, dbref player, char type, char end, char *str, int just_match) --- 1089,1107 ---- return 0; } ! /** Match a command or listen pattern against a list of things. ! * This function iterates through a list of things (using the object ! * Next pointer, so typically this is a list of contents of an object), ! * and checks each for an attribute matching a command/listen pattern. ! * \param thing first object on list. ! * \param player the enactor. ! * \param type type of attribute to match ('$' or '^') ! * \param end character that signals the end of the matchable portion (':') ! * \param str string to match against the attributes. ! * \param just_match if 1, don't execute the command on match. ! * \retval 1 a match was made. ! * \retval 0 no match was made. ! */ int list_check(dbref thing, dbref player, char type, char end, char *str, int just_match) *************** *** 1023,1028 **** --- 1116,1131 ---- return (match); } + /** Match a command against an attribute of aliases. + * This function iterates through a list of things (using the object + * Next pointer, so typically this is a list of contents of an object), + * and checks each for an attribute of aliases that might be matched + * (as in EALIAS). + * \param thing first object on list. + * \param command command to attempt to match. + * \param type name of attribute of aliases to match against. + * \return dbref of first matching object, or -1 if none. + */ int alias_list_check(dbref thing, const char *command, const char *type) { *************** *** 1041,1046 **** --- 1144,1157 ---- return -1; } + /** Check a command against a list of aliases on a location + * (as for LALIAS). + * \param loc location with attribute of aliases. + * \param command command to attempt to match. + * \param type name of attribute of aliases to match against. + * \retval 1 successful match. + * \retval 0 failure. + */ int loc_alias_check(dbref loc, const char *command, const char *type) { *************** *** 1054,1059 **** --- 1165,1178 ---- return 0; } + /** Can an object hear? + * This function determines if a given object can hear. A Hearer is: + * a connected player, a puppet, an AUDIBLE object with a FORWARDLIST + * attribute, or an object with a LISTEN attribute. + * \param thing object to check. + * \retval 1 object can hear. + * \retval 0 object can't hear. + */ int Hearer(dbref thing) { *************** *** 1078,1083 **** --- 1197,1210 ---- return 0; } + /** Might an object be responsive to commands? + * This function determines if a given object might pick up a $command. + * That is, if it has any attributes with $commands on them that are + * not set no_command. + * \param thing object to check. + * \retval 1 object responds to commands. + * \retval 0 object doesn't respond to commands. + */ int Commer(dbref thing) { *************** *** 1094,1099 **** --- 1221,1233 ---- return (0); } + /** Is an object listening? + * This function determines if a given object is a Listener. A Listener + * is a thing or room that has the MONITOR flag set. + * \param thing object to check. + * \retval 1 object is a Listener. + * \retval 0 object isn't listening with ^patterns. + */ int Listener(dbref thing) { *************** *** 1103,1108 **** --- 1237,1250 ---- return (ThingListen(thing) || RoomListen(thing)); } + /** Reset all players' money. + * \verbatim + * This function implements the @poor command. It probably belongs in + * rob.c, though. + * \endverbatim + * \param player the enactor, for permission checking. + * \param arg1 the amount of money to reset all players to. + */ void do_poor(dbref player, char *arg1) { *************** *** 1123,1128 **** --- 1265,1278 ---- } + /** User interface to write a message to a log. + * \verbatim + * This function implements @log. + * \endverbatim + * \param player the enactor. + * \param str message to write to the log. + * \param ltype type of log to write to. + */ void do_writelog(dbref player, char *str, int ltype) { *************** *** 1136,1143 **** notify(player, "Logged."); } ! /* Bind occurences of '##' in "action" to "arg", then run "action" */ ! void bind_and_queue(dbref player, dbref cause, char *action, const char *arg, const char *placestr) --- 1286,1298 ---- notify(player, "Logged."); } ! /** Bind occurences of '##' in "action" to "arg", then run "action". ! * \param player the enactor. ! * \param cause object that caused command to run. ! * \param action command string which may contain tokens. ! * \param arg value for ## token. ! * \param placestr value for #@ token. ! */ void bind_and_queue(dbref player, dbref cause, char *action, const char *arg, const char *placestr) *************** *** 1163,1175 **** (Can_Examine(p,x) && \ ((num = atr_comm_match(x, p, '$', ':', command, 1, atrname, &ptr)) != 0)) char * scan_list(dbref player, char *command) { - /* scan for possible matches of user-def'd commands from the - * viewpoint of player, and return as a string. - * Assumes that atr_comm_match returns atrname with a leading space. - */ static char tbuf[BUFFER_LEN]; char *tp; dbref thing; --- 1318,1334 ---- (Can_Examine(p,x) && \ ((num = atr_comm_match(x, p, '$', ':', command, 1, atrname, &ptr)) != 0)) + /** Scan for matches of $commands. + * This function scans for possible matches of user-def'd commands from the + * viewpoint of player, and return as a string. + * It assumes that atr_comm_match() returns atrname with a leading space. + * \param player the object from whose viewpoint to scan. + * \param command the command to scan for matches to. + * \return string of obj/attrib pairs with matching $commands. + */ char * scan_list(dbref player, char *command) { static char tbuf[BUFFER_LEN]; char *tp; dbref thing; *************** *** 1228,1240 **** safe_str(atrname, tbuf, &tp); } } ! ptr = atrname; ! if ((Zone(player) != NOTHING) && (Zone(player) != Zone(Location(player)))) { ! /* check the player's personal zone */ ! if (ScanFind(player, Zone(player))) { ! *ptr = '\0'; ! safe_str(atrname, tbuf, &tp); } } } ptr = atrname; --- 1387,1409 ---- safe_str(atrname, tbuf, &tp); } } ! } ! ptr = atrname; ! if ((Zone(player) != NOTHING) && (Zone(player) != Zone(Location(player)))) { ! /* check the player's personal zone */ ! if (IsRoom(Zone(player))) { ! if (Location(player) != Zone(player)) { ! DOLIST(thing, Contents(Zone(player))) { ! if (ScanFind(player, thing)) { ! *ptr = '\0'; ! safe_str(atrname, tbuf, &tp); ! ptr = atrname; ! } ! } } + } else if (ScanFind(player, Zone(player))) { + *ptr = '\0'; + safe_str(atrname, tbuf, &tp); } } ptr = atrname; *************** *** 1256,1261 **** --- 1425,1438 ---- return tbuf; } + /** User interface to scan for $command matches. + * \verbatim + * This function implements @scan. + * \endverbatim + * \param player the enactor. + * \param command command to scan for matches to. + * \param flag bitflags for where to scan. + */ void do_scan(dbref player, char *command, int flag) { *************** *** 1341,1355 **** num, atrname); } } ! ptr = atrname; ! if ((Zone(player) != NOTHING) ! && (Zone(player) != Zone(Location(player)))) { ! /* check the player's personal zone */ ! if (ScanFind(player, Zone(player))) { ! *ptr = '\0'; ! notify_format(player, T("Matched personal zone: %s [%d:%s]"), ! unparse_object(player, Zone(player)), num, atrname); } } } } --- 1518,1543 ---- num, atrname); } } ! } ! ptr = atrname; ! if ((Zone(player) != NOTHING) && (Zone(player) != Zone(Location(player)))) { ! /* check the player's personal zone */ ! if (IsRoom(Zone(player))) { ! if (Location(player) != Zone(player)) { ! notify(player, T("Matches on personal zone master room:")); ! DOLIST(thing, Contents(Zone(player))) { ! if (ScanFind(player, thing)) { ! *ptr = '\0'; ! notify_format(player, "%s [%d:%s]", ! unparse_object(player, thing), num, atrname); ! ptr = atrname; ! } ! } } + } else if (ScanFind(player, Zone(player))) { + *ptr = '\0'; + notify_format(player, T("Matched personal zone: %s [%d:%s]"), + unparse_object(player, Zone(player)), num, atrname); } } } *************** *** 1375,1380 **** --- 1563,1578 ---- #define DOL_NOTIFY 2 #define DOL_DELIM 4 + /** Execute a command for each element of a list. + * \verbatim + * This function implements @dolist. + * \endverbatim + * \param player the enactor. + * \param list string containing the list to iterate over. + * \param command command to run for each list element. + * \param cause object which caused this command to be run. + * \param flags command switch flags. + */ void do_dolist(dbref player, char *list, char *command, dbref cause, unsigned int flags) *************** *** 1386,1392 **** char placestr[10]; int j; char delim = ' '; - if (!command || !*command) { notify(player, T("What do you want to do with the list?")); if (flags & DOL_NOTIFY) --- 1584,1589 ---- *************** *** 1409,1424 **** wnxt[j] = wenv[j]; for (j = 0; j < NUMQ; j++) rnxt[j] = renv[j]; - bp = outbuf; - if (flags & DOL_DELIM) list += 2; - place = 0; - objstring = trim_space_sep(list, delim); - if (objstring && !*objstring) { /* Blank list */ if (flags & DOL_NOTIFY) --- 1606,1616 ---- *************** *** 1430,1443 **** curr = split_token(&objstring, delim); place++; sprintf(placestr, "%d", place); - if (!(flags & DOL_MAP)) { /* @dolist, queue command */ bind_and_queue(player, cause, command, curr, placestr); } else { const char *replace[2]; char *ebuf, *ebufptr; - /* it's @map, add to the output list */ if (bp != outbuf) safe_chr(delim, outbuf, &bp); --- 1622,1633 ---- *************** *** 1451,1457 **** } *bp = '\0'; - if (flags & DOL_MAP) { /* if we're doing a @map, copy the list to an attribute */ (void) atr_add(player, "MAPLIST", outbuf, GOD, NOTHING); --- 1641,1646 ---- *************** *** 1490,1496 **** { struct tm *t; t = localtime(&mudtime); - strftime(tbuf1, sizeof tbuf1, "%I:%M%p ", t); nl = tbuf1 + strlen(tbuf1); } --- 1679,1684 ---- *************** *** 1522,1528 **** if (fgets(line, sizeof line, fp)) { double load[3]; char *x, *l = line; - load[0] = strtod(l, &x); l = x; load[1] = strtod(l, &x); --- 1710,1715 ---- *************** *** 1542,1569 **** notify(player, tbuf1); /* do process stats */ - pid = getpid(); psize = getpagesize(); ! notify_format(player, T("\nProcess ID: %10u %10d bytes per page"), pid, psize); /* Linux's getrusage() is mostly unimplemented. Just has times, page faults and swapouts. We use /proc/self/status */ - #ifdef HAS_GETRUSAGE getrusage(RUSAGE_SELF, &usage); notify_format(player, T("Time used: %10ld user %10ld sys"), usage.ru_utime.tv_sec, usage.ru_stime.tv_sec); notify_format(player, ! T("Page faults: %10ld hard %10ld soft %10ld swapouts"), usage.ru_majflt, usage.ru_minflt, usage.ru_nswap); #endif - fp = fopen("/proc/self/status", "r"); if (!fp) return; - /* Skip lines we don't care about. */ while (fgets(line, sizeof line, fp) != NULL) { static const char *fields[] = { --- 1729,1754 ---- notify(player, tbuf1); /* do process stats */ pid = getpid(); psize = getpagesize(); ! notify_format(player, ! T("\nProcess ID: %10u %10d bytes per page"), pid, psize); /* Linux's getrusage() is mostly unimplemented. Just has times, page faults and swapouts. We use /proc/self/status */ #ifdef HAS_GETRUSAGE getrusage(RUSAGE_SELF, &usage); notify_format(player, T("Time used: %10ld user %10ld sys"), usage.ru_utime.tv_sec, usage.ru_stime.tv_sec); notify_format(player, ! T ! ("Page faults: %10ld hard %10ld soft %10ld swapouts"), usage.ru_majflt, usage.ru_minflt, usage.ru_nswap); #endif fp = fopen("/proc/self/status", "r"); if (!fp) return; /* Skip lines we don't care about. */ while (fgets(line, sizeof line, fp) != NULL) { static const char *fields[] = { *************** *** 1571,1577 **** "SigPnd:", "SigBlk:", "SigIgn:", "SigCgt:", NULL }; int n; - for (n = 0; fields[n]; n++) { size_t len = strlen(fields[n]); if (strncmp(line, fields[n], len) == 0) { --- 1756,1761 ---- *************** *** 1642,1658 **** "Integral mem:%10ld shared %10ld private %10ld stack", usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss); notify_format(player, ! T("Page faults: %10ld hard %10ld soft %10ld swapouts"), usage.ru_majflt, usage.ru_minflt, usage.ru_nswap); ! notify_format(player, ! T("Disk I/O: %10ld reads %10ld writes"), usage.ru_inblock, usage.ru_oublock); ! notify_format(player, ! T("Network I/O: %10ld in %10ld out"), usage.ru_msgrcv, ! usage.ru_msgsnd); ! notify_format(player, ! T("Context swi: %10ld vol %10ld forced"), usage.ru_nvcsw, ! usage.ru_nivcsw); notify_format(player, "Signals: %10ld", usage.ru_nsignals); #endif /* HAS_GETRUSAGE */ --- 1826,1840 ---- "Integral mem:%10ld shared %10ld private %10ld stack", usage.ru_ixrss, usage.ru_idrss, usage.ru_isrss); notify_format(player, ! T ! ("Page faults: %10ld hard %10ld soft %10ld swapouts"), usage.ru_majflt, usage.ru_minflt, usage.ru_nswap); ! notify_format(player, T("Disk I/O: %10ld reads %10ld writes"), usage.ru_inblock, usage.ru_oublock); ! notify_format(player, T("Network I/O: %10ld in %10ld out"), ! usage.ru_msgrcv, usage.ru_msgsnd); ! notify_format(player, T("Context swi: %10ld vol %10ld forced"), ! usage.ru_nvcsw, usage.ru_nivcsw); notify_format(player, "Signals: %10ld", usage.ru_nsignals); #endif /* HAS_GETRUSAGE */ *************** *** 1680,1685 **** --- 1862,1874 ---- } + /** Report on server uptime. + * \verbatim + * This command implements @uptime. + * \endverbatim + * \param player the enactor. + * \param mortal if 1, show mortal display, even if player is privileged. + */ void do_uptime(dbref player, int mortal) { *************** *** 1843,1848 **** --- 2032,2045 ---- } } + /* List various goodies. + * \verbatim + * This function implements @list. + * \endverbatim + * \param player the enactor. + * \param arg what to list. + * \param lc if 1, list in lowercase. + */ void do_list(dbref player, char *arg, int lc) { *************** *** 1860,1866 **** notify(player, T("I don't understand what you want to @list.")); } - /* Reports stats on various in-memory data structures */ extern HASHTAB htab_function; extern HASHTAB htab_user_function; extern HASHTAB htab_math; --- 2057,2062 ---- *************** *** 1876,1881 **** --- 2072,2080 ---- extern PTAB ptab_attrib; extern PTAB ptab_flag; + /** Reports stats on various in-memory data structures. + * \param player the enactor. + */ void do_list_memstats(dbref player) { *************** *** 1889,1920 **** hash_stats(player, &htab_reserved_aliases, "Aliases"); hash_stats(player, &help_files, "HelpFiles"); hash_stats(player, &htab_objdata, "ObjData"); - notify(player, "Prefix Trees:"); ptab_stats_header(player); ptab_stats(player, &ptab_attrib, "AttrPerms"); ptab_stats(player, &ptab_command, "Commands"); ptab_stats(player, &ptab_flag, "Flags"); - notify(player, "String Trees:"); st_stats_header(player); - st_stats(player, &atr_names, "AttrNames"); st_stats(player, &object_names, "ObjNames"); st_stats(player, &lock_names, "LockNames"); - #if (COMPRESSION_TYPE >= 3) && defined(COMP_STATS) if (Wizard(player)) { long items, used, total_comp, total_uncomp; double percent; compress_stats(&items, &used, &total_uncomp, &total_comp); notify(player, "---------- Internal attribute compression ----------"); - notify_format(player, "%10ld compression table items used, " - "taking %ld bytes.", items, used); notify_format(player, ! "%10ld bytes in text before compression. ", total_uncomp); ! notify_format(player, ! "%10ld bytes in text AFTER compression. ", total_comp); percent = ((float) (total_comp)) / ((float) total_uncomp) * 100.0; notify_format(player, "%10.0f %% text compression ratio (lower is better). ", --- 2088,2116 ---- hash_stats(player, &htab_reserved_aliases, "Aliases"); hash_stats(player, &help_files, "HelpFiles"); hash_stats(player, &htab_objdata, "ObjData"); notify(player, "Prefix Trees:"); ptab_stats_header(player); ptab_stats(player, &ptab_attrib, "AttrPerms"); ptab_stats(player, &ptab_command, "Commands"); ptab_stats(player, &ptab_flag, "Flags"); notify(player, "String Trees:"); st_stats_header(player); st_stats(player, &atr_names, "AttrNames"); st_stats(player, &object_names, "ObjNames"); st_stats(player, &lock_names, "LockNames"); #if (COMPRESSION_TYPE >= 3) && defined(COMP_STATS) if (Wizard(player)) { long items, used, total_comp, total_uncomp; double percent; compress_stats(&items, &used, &total_uncomp, &total_comp); notify(player, "---------- Internal attribute compression ----------"); notify_format(player, ! "%10ld compression table items used, " ! "taking %ld bytes.", items, used); ! notify_format(player, "%10ld bytes in text before compression. ", ! total_uncomp); ! notify_format(player, "%10ld bytes in text AFTER compression. ", ! total_comp); percent = ((float) (total_comp)) / ((float) total_uncomp) * 100.0; notify_format(player, "%10.0f %% text compression ratio (lower is better). ", *************** *** 1939,1953 **** if (God(player)) list_mem_check(player); #endif - } ! char * make_new_epoch_file(const char *basename, int the_epoch) { static char result[BUFFER_LEN]; /* STATIC! */ /* Unlink the last the_epoch and create a new one */ - sprintf(result, "%s.#%d#", basename, the_epoch - 1); unlink(result); sprintf(result, "%s.#%d#", basename, the_epoch); --- 2135,2147 ---- if (God(player)) list_mem_check(player); #endif } ! static char * make_new_epoch_file(const char *basename, int the_epoch) { static char result[BUFFER_LEN]; /* STATIC! */ /* Unlink the last the_epoch and create a new one */ sprintf(result, "%s.#%d#", basename, the_epoch - 1); unlink(result); sprintf(result, "%s.#%d#", basename, the_epoch); *** 1_7_7.231/src/funufun.c Fri, 05 Jul 2002 12:57:10 -0500 dunemush (pennmush/c/11_funufun.c 1.13 660) --- 1_7_7.308(w)/src/funufun.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/11_funufun.c 1.15 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funufun.c + * + * \brief Evaluation and user-function functions for mushcode. + * + * + */ #include "copyrite.h" *************** *** 81,96 **** PT_DEFAULT, pe_info); } void ! do_userfn(buff, bp, obj, attrib, nargs, args, executor, caller, enactor, ! pe_info) ! char *buff, **bp; ! dbref obj; ! ATTR *attrib; ! int nargs; ! char **args; ! dbref executor, caller __attribute__ ((__unused__)), enactor; ! PE_Info *pe_info; { int j; char *tptr[10]; --- 88,109 ---- PT_DEFAULT, pe_info); } + /** Helper function for ufun and family. + * \param buff string to store result of evaluation. + * \param bp pointer into end of buff. + * \param obj object on which the ufun is stored. + * \param attrib pointer to attribute on which the ufun is stored. + * \param nargs number of arguments passed to the ufun. + * \param args array of arguments passed to the ufun. + * \param executor executor. + * \param caller caller (unused). + * \param enactor enactor. + * \param pe_info pointer to structure for process_expression data. + */ void ! do_userfn(char *buff, char **bp, dbref obj, ATTR *attrib, int nargs, ! char **args, dbref executor, dbref caller ! __attribute__ ((__unused__)), dbref enactor, PE_Info * pe_info) { int j; char *tptr[10]; *** 1_7_7.231/src/funtime.c Sat, 30 Nov 2002 15:49:22 -0600 dunemush (pennmush/c/12_funtime.c 1.11.1.14 660) --- 1_7_7.308(w)/src/funtime.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/12_funtime.c 1.11.1.14.1.2 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funtime.c + * + * \brief Time functions for mushcode. + * + * + */ #include "copyrite.h" #include "config.h" *************** *** 82,89 **** char *s; struct tm *t; ! if ((nargs == 1 && strcasecmp("UTC", args[0]) == 0) || ! strcmp("UTCTIME", called_as) == 0) t = gmtime(&mudtime); else t = localtime(&mudtime); --- 89,102 ---- char *s; struct tm *t; ! if (nargs == 1) { ! if (!strcasecmp("UTC", args[0])) ! t = gmtime(&mudtime); ! else { ! safe_str(T("#-1 INVALID TIME ZONE"), buff, bp); ! return; ! } ! } else if (!strcmp("UTCTIME", called_as)) t = gmtime(&mudtime); else t = localtime(&mudtime); *************** *** 203,212 **** #ifdef HAS_GETDATE int do_convtime_gd(char *str, struct tm *ttm); int ! do_convtime_gd(str, ttm) ! char *str; ! struct tm *ttm; { /* converts time string to a struct tm. Returns 1 on success, 0 on fail. * Formats of the time string are taken from the file listed in the --- 216,231 ---- #ifdef HAS_GETDATE int do_convtime_gd(char *str, struct tm *ttm); + /** Convert a time string to a struct tm using getdate(). + * Formats for the time string are taken from the file referenced in + * the DATEMSK environment variable. + * \param str a time string. + * \param ttm pointer to a struct tm to fill. + * \retval 1 success. + * \retval 0 failure. + */ int ! do_convtime_gd(char *str, struct tm *ttm) { /* converts time string to a struct tm. Returns 1 on success, 0 on fail. * Formats of the time string are taken from the file listed in the *************** *** 247,256 **** "Dec", }; int ! do_convtime(mystr, ttm) ! char *mystr; ! struct tm *ttm; { /* converts time string to a struct tm. Returns 1 on success, 0 on fail. * Time string format is always 24 characters long, in format --- 266,279 ---- "Dec", }; + /** Convert a time string to a struct tm, without getdate(). + * \param mystr a time string. + * \param ttm pointer to a struct tm to fill. + * \retval 1 success. + * \retval 0 failure. + */ int ! do_convtime(char *mystr, struct tm *ttm) { /* converts time string to a struct tm. Returns 1 on success, 0 on fail. * Time string format is always 24 characters long, in format *************** *** 356,368 **** safe_boolean(ltime->tm_isdst > 0, buff, bp); } ! /* Format codes: ! $s - Seconds. $S - Seconds, force 2 digits. ! $m - Minutes. $M - Minutes, force 2 digits. ! $h - Hours. $H - Hours, force 2 digits. ! $d - Days. $D - Days, force 2 digits. ! $$ - Literal $. ! */ void do_timestring(char *buff, char **bp, const char *format, unsigned long secs) { --- 379,398 ---- safe_boolean(ltime->tm_isdst > 0, buff, bp); } ! /** Convert seconds to a formatted time string. ! * \verbatim ! * Format codes: ! * $s - Seconds. $S - Seconds, force 2 digits. ! * $m - Minutes. $M - Minutes, force 2 digits. ! * $h - Hours. $H - Hours, force 2 digits. ! * $d - Days. $D - Days, force 2 digits. ! * $$ - Literal $. ! * \endverbatim ! * \param buff string to store the result in. ! * \param bp pointer into end of buff. ! * \param format format code string. ! * \param secs seconds to convert. ! */ void do_timestring(char *buff, char **bp, const char *format, unsigned long secs) { *** 1_7_7.231/src/funstr.c Sat, 08 Feb 2003 21:20:43 -0600 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.2 660) --- 1_7_7.308(w)/src/funstr.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.3 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funstr.c + * + * \brief String functions for mushcode. + * + * + */ #include "copyrite.h" #include "config.h" *************** *** 36,46 **** void init_tag_hashtab(void); void init_pronouns(void); int get_gender(dbref player) { - /* 0 for neuter, 1 for female, 2 for male, 3 for plural */ - ATTR *a; a = atr_get(player, "SEX"); --- 43,58 ---- void init_tag_hashtab(void); void init_pronouns(void); + /** Return an indicator of a player's gender. + * \param player player whose gender is to be checked. + * \retval 0 neuter. + * \retval 1 female. + * \retval 2 male. + * \retval 3 plural. + */ int get_gender(dbref player) { ATTR *a; a = atr_get(player, "SEX"); *************** *** 72,77 **** --- 84,94 ---- char *obj[4]; char *absp[4]; + /** Initialize the pronoun translation strings. + * This function sets up the values of the arrays of subjective, + * possessive, objective, and absolute possessive pronouns with + * locale-appropriate values. + */ void init_pronouns(void) { *************** *** 1090,1096 **** safe_fill(BEEP_CHAR, k, buff, bp); } ! /* All the safe tags from HTML 4.0 */ void init_tag_hashtab(void) { --- 1107,1113 ---- safe_fill(BEEP_CHAR, k, buff, bp); } ! /** Initialize the html tag hash table with all the safe tags from HTML 4.0 */ void init_tag_hashtab(void) { *** 1_7_7.231/src/funmisc.c Wed, 12 Feb 2003 15:27:53 -0600 dunemush (pennmush/c/14_funmisc.c 1.30.1.1.1.16 660) --- 1_7_7.308(w)/src/funmisc.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/14_funmisc.c 1.30.1.1.1.18 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funmisc.c + * + * \brief Miscellaneous functions for mushcode. + * + * + */ #include "copyrite.h" #include "config.h" *************** *** 8,14 **** #include "case.h" #include "externs.h" #include "version.h" - #include "extchat.h" #include "htab.h" #include "flags.h" #include "match.h" --- 15,20 ---- *************** *** 129,150 **** do_zemit(executor, args[0], args[1]); } - #ifdef CHAT_SYSTEM - /* ARGSUSED */ - FUNCTION(fun_cemit) - { - int noisy = 0; - - if (!command_check_byname(executor, "@cemit") || fun->flags & FN_NOSIDEFX) { - safe_str(T(e_perm), buff, bp); - return; - } - if (nargs == 3 && parse_boolean(args[2])) - noisy = 1; - orator = executor; - do_cemit(executor, args[0], args[1], noisy); - } - #endif extern signed char qreg_indexes[UCHAR_MAX + 1]; --- 135,140 ---- *** 1_7_7.231/src/funmath.c Sat, 30 Nov 2002 15:49:22 -0600 dunemush (pennmush/c/15_funmath.c 1.39.1.1.1.1.1.1.1.10 660) --- 1_7_7.308(w)/src/funmath.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/15_funmath.c 1.39.1.1.1.1.1.1.1.13 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funmath.c + * + * \brief Mathematical functions for mushcode. + * + * + */ #include "copyrite.h" *************** *** 17,26 **** --- 24,36 ---- #endif #ifndef M_PI + /** The ratio of the circumference of a circle to its denominator. */ #define M_PI 3.14159265358979323846264338327 #endif static void do_spellnum(char *num, unsigned int len, char **buff, char ***bp); + static int nval_sort(const void *, const void *); + static NVAL find_median(NVAL *, int); #define MATH_FUNC(func) static void func(char **ptr, int nptr, char *buff, char **bp) *************** *** 28,42 **** HASHTAB htab_math; typedef struct { ! const char *name; ! void (*func) (char **, int, char *, char **); } MATH; static MATH *math_hash_lookup(char *); ! ! NVAL angle_to_rad(NVAL angle, const char *from); ! NVAL rad_to_angle(NVAL angle, const char *to); MATH_PROTO(math_add); MATH_PROTO(math_sub); --- 38,53 ---- HASHTAB htab_math; + /** A math function. */ typedef struct { ! const char *name; /**< Name of the function. */ ! void (*func) (char **, int, char *, char **); /**< Pointer to function code. */ } MATH; + static void math_hash_insert(const char *, MATH *); static MATH *math_hash_lookup(char *); ! static NVAL angle_to_rad(NVAL angle, const char *from); ! static NVAL rad_to_angle(NVAL angle, const char *to); MATH_PROTO(math_add); MATH_PROTO(math_sub); *************** *** 1172,1178 **** } } /* do_spellnum */ ! /* adds zeros to the beginning of the string, untill its length is * a multiple of 3. */ #define add_zeros(p) \ --- 1183,1189 ---- } } /* do_spellnum */ ! /** adds zeros to the beginning of the string, untill its length is * a multiple of 3. */ #define add_zeros(p) \ *************** *** 1917,1925 **** safe_chr('0', buff, bp); } - int nval_sort(const void *, const void *); ! int nval_sort(const void *a, const void *b) { const NVAL *x = a, *y = b; --- 1928,1935 ---- safe_chr('0', buff, bp); } ! static int nval_sort(const void *a, const void *b) { const NVAL *x = a, *y = b; *************** *** 1928,1936 **** return eq ? 0 : (*x > *y ? 1 : -1); } - NVAL find_median(NVAL *, int); ! NVAL find_median(NVAL *numbers, int nargs) { if (nargs == 0) --- 1938,1945 ---- return eq ? 0 : (*x > *y ? 1 : -1); } ! static NVAL find_median(NVAL *numbers, int nargs) { if (nargs == 0) *************** *** 2070,2086 **** return (MATH *) hashfind(strupper(name), &htab_math); } - void math_hash_insert(const char *, MATH *); void init_math_hashtab(void); ! void math_hash_insert(const char *name, MATH *func) { hashadd(name, (void *) func, &htab_math); } void ! init_math_hashtab() { MATH *fp; --- 2079,2094 ---- return (MATH *) hashfind(strupper(name), &htab_math); } void init_math_hashtab(void); ! static void math_hash_insert(const char *name, MATH *func) { hashadd(name, (void *) func, &htab_math); } void ! init_math_hashtab(void) { MATH *fp; *************** *** 2089,2095 **** math_hash_insert(fp->name, (MATH *) fp); } ! NVAL angle_to_rad(NVAL angle, const char *from) { if (!from) --- 2097,2103 ---- math_hash_insert(fp->name, (MATH *) fp); } ! static NVAL angle_to_rad(NVAL angle, const char *from) { if (!from) *************** *** 2109,2115 **** } } ! NVAL rad_to_angle(NVAL angle, const char *to) { if (!to) --- 2117,2123 ---- } } ! static NVAL rad_to_angle(NVAL angle, const char *to) { if (!to) *** 1_7_7.231/src/funlist.c Fri, 07 Feb 2003 20:17:06 -0600 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.5.1.1.1.1.1.1.1.1.1.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.1.1.12.1.4 660) --- 1_7_7.308(w)/src/funlist.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/16_funlist.c 1.3.1.1.1.5.1.2.1.1.1.1.1.4.1.2.1.2.1.19.1.2.1.1.1.2.1.5.1.1.1.1.1.1.1.1.1.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.1.1.12.1.6 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file funlist.c + * + * \brief List-handling functions for mushcode. + * + * + */ #include "copyrite.h" #include "config.h" *************** *** 37,42 **** --- 44,50 ---- static void sane_qsort(void **array, int left, int right, comp_func compare); static void do_itemfuns(char *buff, char **bp, char *str, char *num, char *word, char *sep, int flag); + static int qparse_dbref(const char *s); char *iter_rep[MAX_ITERS]; int iter_place[MAX_ITERS]; *************** *** 61,72 **** return str; } int list2arr(char *r[], int max, char *list, char sep) { - /* chops up a list of words into an array of words. The list is - * destructively modified. - */ char *p; int i; --- 69,86 ---- return str; } + /** Convert list to array. + * Chops up a list of words into an array of words. The list is + * destructively modified. + * \param r pointer to array to store words. + * \param max maximum number of words to split out. + * \param list list of words as a string. + * \param sep separator character between list items. + * \return number of words split out. + */ int list2arr(char *r[], int max, char *list, char sep) { char *p; int i; *************** *** 77,82 **** --- 91,105 ---- return i; } + /** Convert array to list. + * Takes an array of words and concatenates them into a string, + * using our safe string functions. + * \param r pointer to array of words. + * \param max maximum number of words to concatenate. + * \param list string to fill with word list. + * \param lp pointer into end of list. + * \param sep string to use as separator between words. + */ void arr2list(char *r[], int max, char *list, char **lp, char *sep) { *************** *** 689,699 **** } typedef struct i_record i_rec; struct i_record { ! char *str; ! int num; }; int i_comp(const void *s1, const void *s2) { --- 712,732 ---- } typedef struct i_record i_rec; + /** An integer, for sorting purposes. We store both the string and + * the int forms to make some things more efficient. + */ struct i_record { ! char *str; /**< string representation */ ! int num; /**< integer representation */ }; + /** Integer comparison routine for sorts. + * \param s1 void pointer to an i_record. + * \param s2 void pointer to an i_record. + * \retval <0 s1's integer is < s2's integer. + * \retval 0 s1's integer = s2's integer. + * \retval >0 s1's integer is > s2's integer. + */ int i_comp(const void *s1, const void *s2) { *************** *** 705,713 **** } typedef struct f_record f_rec; struct f_record { ! char *str; ! NVAL num; }; static int --- 738,749 ---- } typedef struct f_record f_rec; + /** A double, for sorting purposes. We store both the string and + * the NVAL forms to make some things more efficient. + */ struct f_record { ! char *str; /**< string representation */ ! NVAL num; /**< numeric representation */ }; static int *************** *** 752,758 **** return n; } ! /* Compare two values based on sort_type */ int gencomp(char *a, char *b, list_type sort_type) { --- 788,801 ---- return n; } ! /** Compare two values based on sort_type. ! * \param a one value. ! * \param b another value. ! * \param sort_type how to compare the values. ! * \retval <0 a < b ! * \retval 0 a = b ! * \retval >0 a > b ! */ int gencomp(char *a, char *b, list_type sort_type) { *************** *** 814,821 **** } } ! int qparse_dbref(const char *s); ! int qparse_dbref(const char *s) { /* Version of parse_dbref() that doesn't do GoodObject checks */ --- 857,863 ---- } } ! static int qparse_dbref(const char *s) { /* Version of parse_dbref() that doesn't do GoodObject checks */ *************** *** 824,829 **** --- 866,876 ---- return parse_integer(s + 1); } + /** A generic sort routine to sort an array in place. + * \param s the array to sort. + * \param n number of elements in array s. + * \param sort_type type of sort. + */ void do_gensort(char *s[], int n, list_type sort_type) { *** 1_7_7.231/src/fundb.c Sun, 09 Feb 2003 14:41:06 -0600 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.3.1.1.2.2.2.1.1.1.1.1.1.4 660) --- 1_7_7.308(w)/src/fundb.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/17_fundb.c 1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.7.1.3.1.3.1.3.1.2.1.2.1.3.2.1.2.1.2.1.1.1.1.4.1.1.1.1.1.1.1.1.1.1.1.3.1.1.2.2.2.1.1.1.1.1.1.8 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file fundb.c + * + * \brief Dbref-related functions for mushcode. + * + * + */ #include "copyrite.h" *************** *** 27,37 **** #pragma warning( disable : 4761) /* NJG: disable warning re conversion */ #endif - #ifdef CHAT_SYSTEM - #include "extchat.h" - extern CHAN *channels; - #endif - extern char ccom[BUFFER_LEN]; /* bsd.c */ extern PRIV attr_privs[]; static const char *do_get_attrib(dbref executor, dbref thing, --- 34,39 ---- *************** *** 74,88 **** return ""; } - /* this function produces a space-separated list of attributes that are - * on an object. - */ struct lh_args { int first; char *buff; char **bp; }; /* ARGSUSED */ static int lattr_helper(player, thing, pattern, atr, args) --- 76,90 ---- return ""; } struct lh_args { int first; char *buff; char **bp; }; + /* this function produces a space-separated list of attributes that are + * on an object. + */ /* ARGSUSED */ static int lattr_helper(player, thing, pattern, atr, args) *************** *** 1411,1416 **** --- 1413,1428 ---- } /* ARGSUSED */ + FUNCTION(fun_accname) + { + dbref it = match_thing(executor, args[0]); + if (GoodObject(it)) + safe_str(accented_name(it), buff, bp); + else + safe_str(T(e_notvis), buff, bp); + } + + /* ARGSUSED */ FUNCTION(fun_iname) { dbref it = match_thing(executor, args[0]); *************** *** 1878,2010 **** safe_str("#-1", buff, bp); } - #ifdef CHAT_SYSTEM - FUNCTION(fun_channels) - { - dbref it; - char sep = ' '; - CHAN *c; - CHANLIST *cl; - CHANUSER *u; - int can_ex; - - /* There are these possibilities: - * no args - just a list of all channels - * 2 args - object, delimiter - * 1 arg - either object or delimiter. If it's longer than 1 char, - * we treat it as an object. - * You can see an object's channels if you can examine it. - * Otherwise you can see only channels that you share with - * it where it's not hidden. - */ - if (nargs >= 1) { - /* Given an argument, return list of channels it's on */ - it = match_result(executor, args[0], NOTYPE, MAT_EVERYTHING); - if (GoodObject(it)) { - int first = 1; - if (!delim_check(buff, bp, nargs, args, 2, &sep)) - return; - can_ex = Can_Examine(executor, it); - for (cl = Chanlist(it); cl; cl = cl->next) { - if (can_ex || ((u = onchannel(it, cl->chan)) &&!Chanuser_Hide(u) - && onchannel(executor, cl->chan))) { - if (!first) - safe_chr(sep, buff, bp); - safe_str(ChanName(cl->chan), buff, bp); - first = 0; - } - } - return; - } else { - /* args[0] didn't match. Maybe it's a delimiter? */ - if (arglens[0] > 1) { - if (it == NOTHING) - notify(executor, T("I can't see that here.")); - else if (it == AMBIGUOUS) - notify(executor, T("I don't know which thing you mean.")); - return; - } else if (!delim_check(buff, bp, nargs, args, 1, &sep)) - return; - } - } - /* No arguments (except maybe delimiter) - return list of all channels */ - for (c = channels; c; c = c->next) { - if (Chan_Can_See(c, executor)) { - if (c != channels) - safe_chr(sep, buff, bp); - safe_str(ChanName(c), buff, bp); - } - } - return; - } - - FUNCTION(fun_clock) - { - CHAN *c = NULL; - char *p = NULL; - struct boolexp *lock_ptr = NULL; - int which_lock = 0; - - if ((p = strchr(args[0], '/'))) { - *p++ = '\0'; - } else { - p = (char *) "JOIN"; - } - - switch (find_channel(args[0], &c, executor)) { - case CMATCH_NONE: - safe_str(T("#-1 NO SUCH CHANNEL"), buff, bp); - return; - case CMATCH_AMBIG: - safe_str("#-2 AMBIGUOUS CHANNEL MATCH", buff, bp); - return; - } - - if (!strcasecmp(p, "JOIN")) { - which_lock = CL_JOIN; - lock_ptr = ChanJoinLock(c); - } else if (!strcasecmp(p, "SPEAK")) { - which_lock = CL_SPEAK; - lock_ptr = ChanSpeakLock(c); - } else if (!strcasecmp(p, "MOD")) { - which_lock = CL_MOD; - lock_ptr = ChanModLock(c); - } else if (!strcasecmp(p, "SEE")) { - which_lock = CL_SEE; - lock_ptr = ChanSeeLock(c); - } else if (!strcasecmp(p, "HIDE")) { - which_lock = CL_HIDE; - lock_ptr = ChanHideLock(c); - } else { - safe_str(T("#-1 NO SUCH LOCK TYPE"), buff, bp); - return; - } - - if (nargs == 2) { - #ifdef FUNCTION_SIDE_EFFECTS - if (!command_check_byname(executor, "@clock")) { - safe_str(T(e_perm), buff, bp); - return; - } - do_chan_lock(executor, args[0], args[1], which_lock); - return; - #else - safe_str(T(e_disabled), buff, bp); - #endif - } - - if (Chan_Can_Decomp(c, executor)) { - safe_str(unparse_boolexp(executor, lock_ptr, 1), buff, bp); - return; - } else { - safe_str(T(e_perm), buff, bp); - return; - } - } - - #endif /* CHAT_SYSTEM */ - - /* ARGSUSED */ FUNCTION(fun_followers) { --- 1890,1895 ---- *** 1_7_7.231/src/function.c Wed, 12 Feb 2003 15:05:43 -0600 dunemush (pennmush/c/18_function.c 1.29.1.14.1.3.1.6.1.1.1.1.1.14.1.2.1.1.1.7.1.2 660) --- 1_7_7.308(w)/src/function.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/18_function.c 1.29.1.14.1.3.1.6.1.1.1.1.1.14.1.2.1.1.1.7.1.5 660) *************** *** 1,3 **** --- 1,10 ---- + /** + * \file function.c + * + * \brief The function parser. + * + * + */ #include "copyrite.h" #include "config.h" *************** *** 24,30 **** #include "funs.h" #include "confmagic.h" ! void func_hash_insert(const char *name, FUN *func); extern void local_functions(void); USERFN_ENTRY *userfn_tab; --- 31,37 ---- #include "funs.h" #include "confmagic.h" ! static void func_hash_insert(const char *name, FUN *func); extern void local_functions(void); USERFN_ENTRY *userfn_tab; *************** *** 35,40 **** --- 42,51 ---- * Utilities. */ + /** Save a copy of the q-registers. + * \param funcname name of function calling (for memory leak testing) + * \param preserve pointer to array to store the q-registers in. + */ void save_global_regs(funcname, preserve) const char *funcname; *************** *** 52,57 **** --- 63,72 ---- } } + /** Restore the q-registers, freeing the storage array. + * \param funcname name of function calling (for memory leak testing) + * \param preserve pointer to array to restore the q-registers from. + */ void restore_global_regs(funcname, preserve) const char *funcname; *************** *** 68,74 **** } } ! /* Like restore, but doesn't free */ void load_global_regs(preserve) char *preserve[]; --- 83,91 ---- } } ! /** Restore the q-registers, without freeing the storage array. ! * \param preserve pointer to array to restore the q-registers from. ! */ void load_global_regs(preserve) char *preserve[]; *************** *** 83,88 **** --- 100,109 ---- } } + /** Save a copy of the environment (%0-%9) + * \param funcname name of function calling (for memory leak testing) + * \param preserve pointer to array to store %0-%9 in. + */ void save_global_env(funcname, preserve) const char *funcname __attribute__ ((__unused__)); *************** *** 94,99 **** --- 115,124 ---- preserve[i] = wenv[i]; } + /** Restore the environment (%0-%9) + * \param funcname name of function calling (for memory leak testing) + * \param preserve pointer to array to restore %0-%9 from. + */ void restore_global_env(funcname, preserve) const char *funcname __attribute__ ((__unused__)); *************** *** 105,110 **** --- 130,149 ---- wenv[i] = preserve[i]; } + /** Check for a delimiter in an argument of a function call. + * This function checks a given argument of a function call and sees + * if it could be used as a delimiter. A delimiter must be a single + * character. If the argument isn't present or is null, we return + * the default delimiter, a space. + * \param buff unused. + * \param bp unused. + * \param nfargs number of arguments to the function. + * \param fargs array of function arguments. + * \param sep_arg index of the argument to check for a delimiter. + * \param set pointer to separator character, used to return separator. + * \retval 0 illegal separator argument. + * \retval 1 successfully returned a separator (maybe the default one). + */ int delim_check(buff, bp, nfargs, fargs, sep_arg, sep) char *buff; *************** *** 134,145 **** * The actual function handlers */ struct fun_tab { ! const char *name; ! function_func fun; ! int minargs; ! int maxargs; ! int flags; }; typedef struct fun_tab FUNTAB; --- 173,187 ---- * The actual function handlers */ + /** An entry in the function table. + * This structure represents a function's entry in the function table. + */ struct fun_tab { ! const char *name; /**< Name of the function, uppercase. */ ! function_func fun; /**< Pointer to code to call for this function. */ ! int minargs; /**< Minimum args required. */ ! int maxargs; /**< Maximum args, or INT_MAX. If <0, last arg may have commas */ ! int flags; /**< Flags to control how the function is parsed. */ }; typedef struct fun_tab FUNTAB; *************** *** 148,153 **** --- 190,196 ---- {"@@", fun_atat, 1, -1, FN_NOPARSE}, {"ABS", fun_abs, 1, 1, FN_REG}, {"ACCENT", fun_accent, 2, 2, FN_REG}, + {"ACCNAME", fun_accname, 1, 1, FN_REG}, {"ADD", fun_add, 2, INT_MAX, FN_REG}, {"AFTER", fun_after, 2, 2, FN_REG}, {"ALPHAMAX", fun_alphamax, 1, INT_MAX, FN_REG}, *************** *** 508,525 **** {NULL, NULL, 0, 0, 0} }; void ! do_list_functions(player, lc) ! dbref player; ! int lc; { /* lists all built-in functions. */ char *b = list_functions(); notify_format(player, "Functions: %s", lc ? strlower(b) : b); } char * ! list_functions() { FUN *fp; const char *ptrs[BUFFER_LEN / 2]; --- 551,577 ---- {NULL, NULL, 0, 0, 0} }; + /** List all functions. + * \verbatim + * This is the mail interface to @list functions. + * \endverbatim + * \param player the enactor. + * \param lc if 1, return functions in lowercase. + */ void ! do_list_functions(dbref player, int lc) { /* lists all built-in functions. */ char *b = list_functions(); notify_format(player, "Functions: %s", lc ? strlower(b) : b); } + /** Return a list of function names. + * This function returns the list of function names as a string. + * \return list of function names as a static string. + */ char * ! list_functions(void) { FUN *fp; const char *ptrs[BUFFER_LEN / 2]; *************** *** 553,558 **** --- 605,614 ---- */ + /** Look up a function by name. + * \param name name of function to look up. + * \return pointer to function data, or NULL. + */ FUN * func_hash_lookup(const char *name) { *************** *** 563,569 **** return f; } ! void func_hash_insert(name, func) const char *name; FUN *func; --- 619,625 ---- return f; } ! static void func_hash_insert(name, func) const char *name; FUN *func; *************** *** 571,576 **** --- 627,634 ---- hashadd(name, (void *) func, &htab_function); } + /** Initialize the function hash table. + */ void init_func_hashtab(void) { *************** *** 584,589 **** --- 642,652 ---- local_functions(); } + /** Function initization to perform after reading the config file. + * This function performs post-config initialization. Specifically, + * we need the max_globals value from the config file before we + * can allocate the global user function table here. + */ void function_init_postconfig(void) { *************** *** 592,601 **** "userfn_tab"); } int ! check_func(player, fp) ! dbref player; ! FUN *fp; { if (!fp) return 0; --- 655,668 ---- "userfn_tab"); } + /** Check permissions to run a function. + * \param player the executor. + * \param fp pointer to function data. + * \retval 1 executor may use the function. + * \retval 0 permission denied. + */ int ! check_func(dbref player, FUN *fp) { if (!fp) return 0; *************** *** 618,623 **** --- 685,697 ---- return 1; } + /** Add an alias to a function. + * This function adds an alias to a function in the hash table. + * \param function name of function to alias. + * \param function name of the alias to add. + * \retval 0 failure (alias exists, or function doesn't, or is a user fun). + * \retval 1 success. + */ int alias_function(const char *function, const char *alias) { *************** *** 641,646 **** --- 715,727 ---- return 1; } + /** Add a function. + * \param name name of the function to add. + * \param fun pointer to compiled function code. + * \param minargs minimum arguments to function. + * \param maxargs maximum arguments to function. + * \param ftype function evaluation flags. + */ void function_add(const char *name, function_func fun, int minargs, int maxargs, int ftype) *************** *** 661,673 **** * a modification of TinyMUSH 2.0 code. */ char * strip_braces(const char *str) { - /* this is a hack which just strips a level of braces. It malloc()s memory - * which must be free()d later. - */ - char *buff; char *bufc; --- 742,756 ---- * a modification of TinyMUSH 2.0 code. */ + /** Strip a level of braces. + * this is a hack which just strips a level of braces. It malloc()s memory + * which must be free()d later. + * \param str string to strip braces from. + * \return newly allocated string with the first level of braces stripped. + */ char * strip_braces(const char *str) { char *buff; char *bufc; *************** *** 697,705 **** static Size_t userfn_count = 0; ! /* Given a command name and a restriction, apply the restriction to the ! * command in addition to whatever its usual restrictions are. * This is used by the configuration file startup in conf.c * Valid restrictions are: * nobody disable the command * nogagged can't be used by gagged players --- 780,789 ---- static Size_t userfn_count = 0; ! /** Given a function name and a restriction, apply the restriction to the ! * function in addition to whatever its usual restrictions are. * This is used by the configuration file startup in conf.c + * \verbatim * Valid restrictions are: * nobody disable the command * nogagged can't be used by gagged players *************** *** 710,716 **** * god can only be used by god * noplayer can't be used by players, just objects/rooms/exits * nosidefx can't be used to do side-effect thingies ! * Return 1 on success, 0 on failure. */ int restrict_function(const char *name, const char *restriction) --- 794,804 ---- * god can only be used by god * noplayer can't be used by players, just objects/rooms/exits * nosidefx can't be used to do side-effect thingies ! * \endverbatim ! * \param name name of function to restrict. ! * \param restriction name of restriction to apply to function. ! * \retval 1 success. ! * \retval 0 failure (invalid function or restriction name). */ int restrict_function(const char *name, const char *restriction) *************** *** 743,755 **** return 1; } void ! do_function_restrict(player, name, restriction) ! dbref player; ! const char *name; ! const char *restriction; { - if (!Wizard(player)) { notify(player, T("Permission denied.")); return; --- 831,847 ---- return 1; } + /** Softcode interface to restrict a function. + * \verbatim + * This is the implementation of @function/restrict. + * \endverbatim + * \param player the enactor. + * \param name name of function to restrict. + * \param restriction name of restriction to add. + */ void ! do_function_restrict(dbref player, const char *name, const char *restriction) { if (!Wizard(player)) { notify(player, T("Permission denied.")); return; *************** *** 769,782 **** } void do_function(dbref player, char *name, char *argv[]) { - /* Command of format: @function =,[,,] - * or @function =/ - * Adds a new user-defined function. - */ - char tbuf1[BUFFER_LEN]; char *bp = tbuf1; dbref thing; --- 861,879 ---- } + /** Add a user-defined function. + * \verbatim + * This is the implementation of the @function command. If no arguments + * are given, it lists all @functions defined. Otherwise, this adds + * an @function. + * \endverbatim + * \param player the enactor. + * \param name name of function to add. + * \param argv array of arguments. + */ void do_function(dbref player, char *name, char *argv[]) { char tbuf1[BUFFER_LEN]; char *bp = tbuf1; dbref thing; *************** *** 817,824 **** } return; } ! /* otherwise, we are adding a user function. There is NO deletion ! * mechanism. Only those with the Global_Funcs power may add stuff. * If you add a function that is already a user-defined function, * the old function gets over-written. */ --- 914,921 ---- } return; } ! /* otherwise, we are adding a user function. ! * Only those with the Global_Funcs power may add stuff. * If you add a function that is already a user-defined function, * the old function gets over-written. */ *************** *** 940,949 **** } void ! do_function_restore(player, name) ! dbref player; ! const char *name; { FUN *fp; Size_t table_index, i; --- 1037,1054 ---- } + /** Restore an overridden built-in function. + * \verbatim + * If a built-in function is deleted with @function/delete, it can be + * restored with @function/restore. This implements @function/restore. + * If a user-defined function has been added, it will be removed by + * this function. + * \endverbatim + * \param player the enactor. + * \param name name of function to restore. + */ void ! do_function_restore(dbref player, const char *name) { FUN *fp; Size_t table_index, i; *************** *** 1000,1009 **** } } void ! do_function_delete(player, name) ! dbref player; ! char *name; { /* Deletes a user-defined function. * For security, you must control the object the function uses --- 1105,1120 ---- } } + /** Delete a function. + * \verbatim + * This code implements @function/delete, which deletes a function - + * either a built-in or a user-defined one. + * \endverbatim + * \param player the enactor. + * \param name name of the function to delete. + */ void ! do_function_delete(dbref player, char *name) { /* Deletes a user-defined function. * For security, you must control the object the function uses *************** *** 1059,1069 **** notify(player, T("Function deleted.")); } void ! do_function_toggle(player, name, toggle) ! dbref player; ! char *name; ! int toggle; { FUN *fp; --- 1170,1185 ---- notify(player, T("Function deleted.")); } + /** Enable or disable a function. + * \verbatim + * This implements @function/disable and @function/enable. + * \endverbatim + * \param player the enactor. + * \param name name of the function to enable or disable. + * \param toggle if 1, enable; if 0, disable. + */ void ! do_function_toggle(dbref player, char *name, int toggle) { FUN *fp; *************** *** 1087,1096 **** } } void ! do_function_report(player, name) ! dbref player; ! char *name; { FUN *fp; char tbuf[BUFFER_LEN]; --- 1203,1218 ---- } } + /** Get information about a function. + * \verbatim + * This implements the @function command, which reports function + * details to the enactor. + * \endverbatim + * \param player the enactor. + * \param name name of the function. + */ void ! do_function_report(dbref player, char *name) { FUN *fp; char tbuf[BUFFER_LEN]; *** 1_7_7.231/src/funcrypt.c Sat, 12 Oct 2002 17:05:43 -0500 dunemush (pennmush/c/19_funcrypt.c 1.9 660) --- 1_7_7.308(w)/src/funcrypt.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/19_funcrypt.c 1.10 660) *************** *** 1,4 **** ! /* Functions for encrypt/decrypt, and password checking */ #include "copyrite.h" #include "config.h" --- 1,10 ---- ! /** ! * \file funcrypt.c ! * ! * \brief Functions for cryptographic stuff in softcode ! * ! * ! */ #include "copyrite.h" #include "config.h" *** 1_7_7.231/src/flags.c Sun, 16 Feb 2003 21:57:00 -0600 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.3.1.9.1.2.2.1.1.2.1.32 660) --- 1_7_7.308(w)/src/flags.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/20_flags.c 1.1.1.1.1.1.1.1.1.1.1.1.1.6.1.2.1.1.1.1.1.2.2.2.2.1.2.1.1.3.1.2.1.1.1.1.1.1.1.1.1.3.1.9.1.2.2.1.1.2.1.38 660) *************** *** 45,53 **** #include "confmagic.h" ! int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate); static FLAG *letter_to_flagptr(char c, int type); static void flag_add(const char *name, FLAG *f); void decompile_flags(dbref player, dbref thing, const char *name); void decompile_powers(dbref player, dbref thing, const char *name); --- 45,54 ---- #include "confmagic.h" ! static int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate); static FLAG *letter_to_flagptr(char c, int type); static void flag_add(const char *name, FLAG *f); + static int has_flag(dbref thing, FLAG *f); void decompile_flags(dbref player, dbref thing, const char *name); void decompile_powers(dbref player, dbref thing, const char *name); *************** *** 803,809 **** * by computing the appropriate byte, and the appropriate bit within the byte, * and testing it. * \param bitmask a flag bitmask. ! * \param bit the bit to test. * \retval 1 bit is set. * \retval 0 bit is not set. */ --- 804,810 ---- * by computing the appropriate byte, and the appropriate bit within the byte, * and testing it. * \param bitmask a flag bitmask. ! * \param bitpos the bit to test. * \retval 1 bit is set. * \retval 0 bit is not set. */ *************** *** 838,843 **** --- 839,860 ---- return ok; } + /** Test to see if a bitmask is entirely 0 bits. + * \param source the bitmask to test. + * \retval 1 all bits in bitmask are 0. + * \retval 0 at least one bit in bitmask is 1. + */ + int + null_flagmask(object_flag_type source) + { + unsigned int i; + int bad = 0; + unsigned int flagbytes = 1 + flagbits / 8; + for (i = 0; i < flagbytes; i++) + bad |= *(source + i); + return (!bad); + } + /** Test a set of bits in one bitmask against any of those in another. * This function determines if one bitmask contains any * of the bits set in another bitmask. *************** *** 922,927 **** --- 939,953 ---- */ + /** Check an object for a flag. + * This function tests to see if an object has a flag. It is the + * function to use for this purpose from outside of this file. + * \param thing object to check. + * \param flag name of flag to check for (a string). + * \param type allowed types of flags to check for. + * \retval 1 object has the flag. + * \retval 0 object does not have the flag. + */ int has_flag_by_name(dbref thing, const char *flag, int type) { *************** *** 932,938 **** return has_flag(thing, f); } ! int has_flag(dbref thing, FLAG *f) { if (!GoodObject(thing) || IsGarbage(thing)) --- 958,964 ---- return has_flag(thing, f); } ! static int has_flag(dbref thing, FLAG *f) { if (!GoodObject(thing) || IsGarbage(thing)) *************** *** 940,946 **** return has_bit(Flags(thing), f->bitpos); } ! int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate) { /* returns 1 if player can set a flag on thing. */ --- 966,972 ---- return has_bit(Flags(thing), f->bitpos); } ! static int can_set_flag(dbref player, dbref thing, FLAG *flagp, int negate) { /* returns 1 if player can set a flag on thing. */ *************** *** 1012,1017 **** --- 1038,1048 ---- return 1; } + /** Return a list of flag symbols that one object can see on another. + * \param thing object to list flag symbols for. + * \param player looker, for permission checking. + * \return a string containing all the visible type and flag symbols. + */ const char * unparse_flags(dbref thing, dbref player) { *************** *** 1048,1053 **** --- 1079,1089 ---- return buf; } + /** Return the object's type and its flag list for examine. + * \param thing object to list flag symbols for. + * \param player looker, for permission checking. + * \return a string containing all the visible type and flag symbols. + */ const char * flag_description(dbref player, dbref thing) { *************** *** 1064,1070 **** ! /* print out the flags for a decompile */ void decompile_flags(dbref player, dbref thing, const char *name) { --- 1100,1110 ---- ! /** Print out the flags for a decompile. ! * \param player looker, for permission checking. ! * \param thing object being decompiled. ! * \param name name by which object is referred to in the decompile. ! */ void decompile_flags(dbref player, dbref thing, const char *name) { *************** *** 1078,1085 **** } ! /* Set or clear flags on an object, without permissions/hear checking. ! * For server internal use. */ void twiddle_flag_internal(dbref thing, const char *flag, int negate) --- 1118,1129 ---- } ! /** Set or clear flags on an object, without permissions/hear checking. ! * This function is for server internal use, only, when a flag should ! * be set or cleared unequivocally. ! * \param thing object on which to set or clear flag. ! * \param flag name of flag to set or clear. ! * \param negate if 1, clear the flag, if 0, set the flag. */ void twiddle_flag_internal(dbref thing, const char *flag, int negate) *************** *** 1092,1099 **** } ! /* Set or clear flags on an object, with full permissions checking ! * and handling of listening, etc. */ void set_flag(dbref player, dbref thing, const char *flag, int negate, --- 1136,1152 ---- } ! /* Set or clear flags on an object, with full permissions/hear checking. ! * \verbatim ! * This function is used to set and clear flags through @set and the like. ! * It does permission checking and handles the "is now listening" messages. ! * \endverbatim ! * \param player the enactor. ! * \param thing object on which to set or clear flag. ! * \param flag name of flag to set or clear. ! * \param negate if 1, clear the flag, if 0, set the flag. ! * \param hear 1 if object is a hearer. ! * \param listener 1 if object is a listener. */ void set_flag(dbref player, dbref thing, const char *flag, int negate, *************** *** 1244,1255 **** } int ! flaglist_check(player, it, fstr, type) ! dbref player; ! dbref it; ! const char *fstr; ! int type; /* 0 for orflags, 1 for andflags */ { char *s; FLAG *fp; --- 1297,1315 ---- } + /** Check if an object has one or all of a list of flag characters. + * This function is used by orflags and andflags to check to see + * if an object has one or all of the flags signified by a list + * of flag characters. + * \param player the object checking, for permissions + * \param it the object on which to check for flags. + * \param fstr string of flag characters to check for. + * \param type 0=orflags, 1=andflags. + * \retval 1 object has any (or all) flags. + * \retval 0 object has no (or not all) flags. + */ int ! flaglist_check(dbref player, dbref it, const char *fstr, int type) { char *s; FLAG *fp; *************** *** 1319,1330 **** return (ret); } int ! flaglist_check_long(player, it, fstr, type) ! dbref player; ! dbref it; ! const char *fstr; ! int type; /* 0 for orflags, 1 for andflags */ { char *s, *copy, *sp; FLAG *fp; --- 1379,1397 ---- return (ret); } + /** Check if an object has one or all of a list of flag names. + * This function is used by orlflags and andlflags to check to see + * if an object has one or all of the flags signified by a list + * of flag names. + * \param player the object checking, for permissions + * \param it the object on which to check for flags. + * \param fstr string of flag names, space-separated, to check for. + * \param type 0=orlflags, 1=andlflags. + * \retval 1 object has any (or all) flags. + * \retval 0 object has no (or not all) flags. + */ int ! flaglist_check_long(dbref player, dbref it, const char *fstr, int type) { char *s, *copy, *sp; FLAG *fp; *************** *** 1396,1401 **** --- 1463,1475 ---- } + /** Can a player see a flag? + * \param privs looker. + * \param thing object on which to look for flag. + * \param name name of flag to look for. + * \retval 1 object has the flag and looker can see it. + * \retval 0 looker can not see flag on object. + */ int sees_flag(dbref privs, dbref thing, const char *name) { *************** *** 1406,1414 **** return has_flag(thing, f) && Can_See_Flag(privs, thing, f); } - /* A hacker interface for adding a flag, used by the @flag command - */ void add_flag(const char *name, const char letter, int type, int perms, int negate_perms) --- 1480,1499 ---- return has_flag(thing, f) && Can_See_Flag(privs, thing, f); } + /** A hacker interface for adding a flag. + * \verbatim + * This function is used to add a new flag to the game. It's + * called by @flag (via do_flag_add()), and is the right function to + * call in flaglocal.c if you're writing a hardcoded system patch that + * needs to add its own flags. It will not add the same flag twice. + * \endverbatim + * \param name flag name. + * \param letter flag character (or '\0') + * \param type mask of object types to which the flag applies. + * \param perms mask of permissions to see/set the flag. + * \param negate_perms mask of permissions to clear the flag. + */ void add_flag(const char *name, const char letter, int type, int perms, int negate_perms) *************** *** 1431,1436 **** --- 1516,1530 ---- /*-------------------------------------------------------------------------- * MUSHcode interface */ + + /** User interface to list flags. + * \verbatim + * This function implements @flag/list. + * \endverbatim + * \param player the enactor. + * \param arg wildcard pattern of flag names to list, or NULL for all. + * \param lc if 1, list flags in lowercase. + */ void do_list_flags(dbref player, const char *arg, int lc) { *************** *** 1438,1444 **** notify_format(player, T("Flags: %s"), lc ? strlower(b) : b); } ! /* Details about a flag */ void do_flag_info(dbref player, const char *name) { --- 1532,1544 ---- notify_format(player, T("Flags: %s"), lc ? strlower(b) : b); } ! /** User interface to show flag detail. ! * \verbatim ! * This function implements @flag . ! * \endverbatim ! * \param player the enactor. ! * \param name name of the flag to describe. ! */ void do_flag_info(dbref player, const char *name) { *************** *** 1460,1468 **** privs_to_string(flag_privs, f->negate_perms)); } ! /* Change the permissions on a flag. * @flag/restrict = , * If no comma is given, use for both. */ void do_flag_restrict(dbref player, const char *name, char *args_right[]) --- 1560,1576 ---- privs_to_string(flag_privs, f->negate_perms)); } ! /** Change the permissions on a flag. ! * \verbatim ! * This is the user-interface to @flag/restrict, which uses this syntax: ! * * @flag/restrict = , + * * If no comma is given, use for both. + * \endverbatim + * \param player the enactor. + * \param name name of flag to modify. + * \param args_right array of arguments on the right of the equal sign. */ void do_flag_restrict(dbref player, const char *name, char *args_right[]) *************** *** 1508,1520 **** notify_format(player, T("Permissions on %s flag set."), f->name); } ! /* Add a new flag * @flag/add = , , , * defaults to none. If given, it must not match an existing * flag character that could apply to the given type * defaults to NOTYPE * defaults to any * defaults to */ void do_flag_add(dbref player, const char *name, char *args_right[]) --- 1616,1636 ---- notify_format(player, T("Permissions on %s flag set."), f->name); } ! /** Add a new flag ! * \verbatim ! * This function implements @flag/add, which uses this syntax: ! * * @flag/add = , , , + * * defaults to none. If given, it must not match an existing * flag character that could apply to the given type * defaults to NOTYPE * defaults to any * defaults to + * \endverbatim + * \param player the enactor. + * \param name name of the flag to add. + * \param args_right array of arguments on the right side of the equal sign. */ void do_flag_add(dbref player, const char *name, char *args_right[]) *************** *** 1601,1606 **** --- 1717,1730 ---- notify(player, T("Unknown failure adding flag.")); } + /** Alias a flag. + * \verbatim + * This function implements the @flag/alias commmand. + * \endverbatim + * \param player the enactor. + * \param name name of the flag to alias. + * \param alias name of the alias. + */ void do_flag_alias(dbref player, const char *name, const char *alias) { *************** *** 1646,1654 **** notify(player, T("Unknown failure adding alias.")); } ! /* Disable a flag. Only God can do this, and it makes the flag effectively * unusuable - it's invisible to all but God, and can't be set, cleared, * or tested against. */ void do_flag_disable(dbref player, const char *name) --- 1770,1784 ---- notify(player, T("Unknown failure adding alias.")); } ! /** Disable a flag. ! * \verbatim ! * This function implements @flag/disable. ! * Only God can do this, and it makes the flag effectively * unusuable - it's invisible to all but God, and can't be set, cleared, * or tested against. + * \endverbatim + * \param player the enactor. + * \param name name of the flag to disable. */ void do_flag_disable(dbref player, const char *name) *************** *** 1672,1680 **** notify_format(player, T("Flag %s disabled."), f->name); } ! /* Delete a flag. Only God can do this, and clears the flag on everyone * and then removes it and its aliases from the tables. * Danger, Will Robinson! */ void do_flag_delete(dbref player, const char *name) --- 1802,1816 ---- notify_format(player, T("Flag %s disabled."), f->name); } ! /** Delete a flag. ! * \verbatim ! * This function implements @flag/delete. ! * Only God can do this, and clears the flag on everyone * and then removes it and its aliases from the tables. * Danger, Will Robinson! + * \endverbatim + * \param player the enactor. + * \param name name of the flag to delete. */ void do_flag_delete(dbref player, const char *name) *************** *** 1724,1730 **** free((Malloc_t) f); } ! /* Enable a flag. Only God can do this, and it reverses /disable. */ void do_flag_enable(dbref player, const char *name) { --- 1860,1873 ---- free((Malloc_t) f); } ! /* Enable a disabled flag. ! * \verbatim ! * This function implements @flag/enable. ! * Only God can do this, and it reverses /disable. ! * \endverbatim ! * \param player the enactor. ! * \param name name of the flag to enable. ! */ void do_flag_enable(dbref player, const char *name) { *************** *** 1774,1780 **** } ! /* Which is a bitwise combination of 0x1 (chars) and 0x2 (names) */ char * list_all_flags(const char *name, dbref privs, int which) { --- 1917,1927 ---- } ! /** Return a list of all flags. ! * \param name wildcard to match against flag names, or NULL for all. ! * \param privs the looker, for permission checking. ! * \param which a bitmask of 0x1 (flag chars) and 0x2 (flag names)u ! */ char * list_all_flags(const char *name, dbref privs, int which) { *************** *** 1829,1834 **** --- 1976,1985 ---- */ + /** Return a list of powers on an object. + * \param thing object on which to list powers. + * \return string containing a list of power names on the object. + */ const char * power_description(dbref thing) { *************** *** 1850,1855 **** --- 2001,2010 ---- return fbuf; } + /** Look up a power in the power (or alias) table. + * \param name name of power to look up. + * \return power value, or -1 if none found. + */ int find_power(const char *name) { *************** *** 1870,1875 **** --- 2025,2035 ---- return -1; } + /** Show the flags and powers associated with a command. + * \param flagmask the command's flagmask. + * \param powers the command's power mask. + * \return string output of powers and flags. + */ const char * show_command_flags(object_flag_type flagmask, int powers) { *************** *** 1898,1903 **** --- 2058,2068 ---- return fbuf; } + /** Convenience function to look up a power by name. + * This function looks up a power by name, and returns 0 if not found. + * \param name name of power to look up. + * \return power value, or 0 if not found. + */ int match_power(const char *name) { *************** *** 1906,1912 **** return ((p > -1) ? p : 0); } ! /* print out the powers for a decompile */ void decompile_powers(dbref player, dbref thing, const char *name) { --- 2071,2081 ---- return ((p > -1) ? p : 0); } ! /** Print out the powers for a decompile. ! * \param player looker to notify. ! * \param thing object to check for powers. ! * \param name name by which object is referenced in decompile. ! */ void decompile_powers(dbref player, dbref thing, const char *name) { *** 1_7_7.231/src/extchat.c Wed, 12 Feb 2003 14:26:12 -0600 dunemush (pennmush/c/23_extchat.c 1.1.1.1.1.1.1.1.1.2.1.1.1.3.1.1.1.5.1.1.1.1.1.5.1.2.1.3.1.3.1.1.1.4.1.2.1.6.1.2.1.1.2.4.2.9.1.2.1.2.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.2.1.1.2.1.1.2.1.1.1.6 660) --- 1_7_7.308(w)/src/extchat.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/23_extchat.c 1.1.1.1.1.1.1.1.1.2.1.1.1.3.1.1.1.5.1.1.1.1.1.5.1.2.1.3.1.3.1.1.1.4.1.2.1.6.1.2.1.1.2.4.2.9.1.2.1.2.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.2.1.1.2.1.1.2.1.1.1.1.1.22 660) *************** *** 14,19 **** --- 14,20 ---- #include #endif #include + #include #include "conf.h" #include "attrib.h" #include "mushdb.h" *************** *** 29,38 **** --- 30,47 ---- #include "log.h" #include "flags.h" #include "dbdefs.h" + #include "function.h" + #include "command.h" #include "confmagic.h" #ifdef CHAT_SYSTEM + extern CHAN *channels; + struct na_cpass { + CHANUSER *u; + int checkquiet; + }; + extern jmp_buf db_err; #define OUTPUT(fun) do { if ((fun) < 0) longjmp(db_err, 1); } while (0) *************** *** 66,71 **** --- 75,88 ---- static void channel_join_self(dbref player, const char *name); static void channel_leave_self(dbref player, const char *name); static void do_channel_who(dbref player, CHAN *chan); + void chat_player_announce(dbref player, char *msg); + static int ok_channel_name(const char *n); + static void channel_allocate_buffer(CHAN *c, int lines); + static void channel_reallocate_buffer(CHAN *c, int lines); + static void channel_free_buffer(CHAN *c); + static void channel_push_buffer(CHAN *c, char *tbuf1); + static void channel_shift_buffer(CHAN *c); + static int channel_buffer_lines(CHAN *c); const char *chan_speak_lock = "ChanSpeakLock"; const char *chan_join_lock = "ChanJoinLock"; *************** *** 215,223 **** --- 232,243 ---- ChanNumUsers(ch) = 0; ChanMaxUsers(ch) = 0; ChanUsers(ch) = NULL; + ChanBuffer(ch) = NULL; + ChanBufferSize(ch) = 0; return ch; } + /* Malloc memory for a new user, and initialize it */ static CHANUSER * new_user(dbref who) *************** *** 1365,1370 **** --- 1385,1394 ---- notify(player, T("The channel needs a shorter name.")); return; } + if (!ok_channel_name(name)) { + notify(player, T("Invalid name for a channel.")); + return; + } if (!Hasprivs(player) && !canstilladd(player)) { notify(player, T("You already own too many channels.")); return; *************** *** 1500,1505 **** --- 1524,1560 ---- } } + static int + ok_channel_name(const char *n) + { + /* is name valid for a channel? */ + const char *p; + char name[BUFFER_LEN]; + + strcpy(name, remove_markup(n, NULL)); + + if (!name || !*name) + return 0; + + /* No leading spaces */ + if (isspace((unsigned char) *name)) + return 0; + + /* only printable characters */ + for (p = name; p && *p; p++) { + if (!isprint((unsigned char) *p)) + return 0; + } + + /* No trailing spaces */ + p--; + if (isspace((unsigned char) *p)) + return 0; + + return 1; + } + + /** Modify a user's settings on a channel. * \verbatim * This is one of top-level functions for @channel. This one *************** *** 1695,1702 **** if (SUPPORT_PUEBLO) notify_noenter(player, tprintf("%cSAMP%c", TAG_START, TAG_END)); ! notify_format(player, "%-30s %-5s %8s %-16s %-8s", ! "Name", "Users", "Msgs", T("Chan Type"), "Status"); for (c = channels; c; c = c->next) { strcpy(cleanname, remove_markup(ChanName(c), NULL)); if (Chan_Can_See(c, player) && string_prefix(cleanname, partname)) { --- 1750,1757 ---- if (SUPPORT_PUEBLO) notify_noenter(player, tprintf("%cSAMP%c", TAG_START, TAG_END)); ! notify_format(player, "%-30s %-5s %8s %-16s %-8s %-3s", ! "Name", "Users", "Msgs", T("Chan Type"), "Status", "Buf"); for (c = channels; c; c = c->next) { strcpy(cleanname, remove_markup(ChanName(c), NULL)); if (Chan_Can_See(c, player) && string_prefix(cleanname, partname)) { *************** *** 1716,1722 **** blanks[0] = '\0'; } notify_format(player, ! "%-30s%s %s %8ld [%c%c%c%c%c%c%c %c%c%c%c%c%c] [%-3s %c%c]", ChanName(c), blanks, numusers, ChanNumMsgs(c), Channel_Disabled(c) ? 'D' : '-', Channel_Player(c) ? 'P' : '-', --- 1771,1777 ---- blanks[0] = '\0'; } notify_format(player, ! "%-30s%s %s %8ld [%c%c%c%c%c%c%c %c%c%c%c%c%c] [%-3s %c%c] %3d", ChanName(c), blanks, numusers, ChanNumMsgs(c), Channel_Disabled(c) ? 'D' : '-', Channel_Player(c) ? 'P' : '-', *************** *** 1735,1741 **** /* User status */ u ? (Chanuser_Gag(u) ? "Gag" : "On") : "Off", (u &&Chanuser_Quiet(u)) ? 'Q' : ' ', ! (u &&Chanuser_Hide(u)) ? 'H' : ' '); } } if (SUPPORT_PUEBLO) --- 1790,1797 ---- /* User status */ u ? (Chanuser_Gag(u) ? "Gag" : "On") : "Off", (u &&Chanuser_Quiet(u)) ? 'Q' : ' ', ! (u &&Chanuser_Hide(u)) ? 'H' : ' ', ! channel_buffer_lines(c)); } } if (SUPPORT_PUEBLO) *************** *** 2206,2211 **** --- 2262,2270 ---- if (ChanTitle(c)) notify_format(player, "@channel/desc %s = %s", ChanName(c), ChanTitle(c)); + if (ChanBuffer(c)) + notify_format(player, "@channel/buffer %s = %d", ChanName(c), + channel_buffer_lines(c)); if (!brief) { for (u = ChanUsers(c); u; u = u->next) { if (!Chanuser_Hide(u) || Priv_Who(player)) *************** *** 2388,2391 **** --- 2447,3019 ---- } + + /** Tell players on a channel when someone connects or disconnects. + * \param player player to announce to. + * \param msg message to announce. + */ + void + chat_player_announce(dbref player, char *msg) + { + CHAN *c; + CHANUSER *u; + + for (c = channels; c; c = c->next) { + u = onchannel(player, c); + if (u) { + if (!Channel_Quiet(c) && (Channel_Admin(c) || Channel_Wizard(c) + || (!Chanuser_Hide(u) && !Dark(player)))) + channel_broadcast(c, player, 1, "<%s> %s", ChanName(c), msg); + CUtype(u) &= ~CU_GAG; + } + } + } + + /** Return a list of channels that the player is on. + * \param player player whose channels are to be shown. + * \return string listing player's channels, prefixed with Channels: + */ + const char * + channel_description(player) + dbref player; + { + static char buf[BUFFER_LEN]; + CHANLIST *c; + + *buf = '\0'; + + if (Chanlist(player)) { + strcpy(buf, T("Channels:")); + for (c = Chanlist(player); c; c = c->next) + sprintf(buf, "%s %s", buf, ChanName(c->chan)); + } else if (IsPlayer(player)) + strcpy(buf, T("Channels: *NONE*")); + return buf; + } + + + FUNCTION(fun_channels) + { + dbref it; + char sep = ' '; + CHAN *c; + CHANLIST *cl; + CHANUSER *u; + int can_ex; + + /* There are these possibilities: + * no args - just a list of all channels + * 2 args - object, delimiter + * 1 arg - either object or delimiter. If it's longer than 1 char, + * we treat it as an object. + * You can see an object's channels if you can examine it. + * Otherwise you can see only channels that you share with + * it where it's not hidden. + */ + if (nargs >= 1) { + /* Given an argument, return list of channels it's on */ + it = match_result(executor, args[0], NOTYPE, MAT_EVERYTHING); + if (GoodObject(it)) { + int first = 1; + if (!delim_check(buff, bp, nargs, args, 2, &sep)) + return; + can_ex = Can_Examine(executor, it); + for (cl = Chanlist(it); cl; cl = cl->next) { + if (can_ex || ((u = onchannel(it, cl->chan)) &&!Chanuser_Hide(u) + && onchannel(executor, cl->chan))) { + if (!first) + safe_chr(sep, buff, bp); + safe_str(ChanName(cl->chan), buff, bp); + first = 0; + } + } + return; + } else { + /* args[0] didn't match. Maybe it's a delimiter? */ + if (arglens[0] > 1) { + if (it == NOTHING) + notify(executor, T("I can't see that here.")); + else if (it == AMBIGUOUS) + notify(executor, T("I don't know which thing you mean.")); + return; + } else if (!delim_check(buff, bp, nargs, args, 1, &sep)) + return; + } + } + /* No arguments (except maybe delimiter) - return list of all channels */ + for (c = channels; c; c = c->next) { + if (Chan_Can_See(c, executor)) { + if (c != channels) + safe_chr(sep, buff, bp); + safe_str(ChanName(c), buff, bp); + } + } + return; + } + + FUNCTION(fun_clock) + { + CHAN *c = NULL; + char *p = NULL; + struct boolexp *lock_ptr = NULL; + int which_lock = 0; + + if ((p = strchr(args[0], '/'))) { + *p++ = '\0'; + } else { + p = (char *) "JOIN"; + } + + switch (find_channel(args[0], &c, executor)) { + case CMATCH_NONE: + safe_str(T("#-1 NO SUCH CHANNEL"), buff, bp); + return; + case CMATCH_AMBIG: + safe_str("#-2 AMBIGUOUS CHANNEL MATCH", buff, bp); + return; + } + + if (!strcasecmp(p, "JOIN")) { + which_lock = CL_JOIN; + lock_ptr = ChanJoinLock(c); + } else if (!strcasecmp(p, "SPEAK")) { + which_lock = CL_SPEAK; + lock_ptr = ChanSpeakLock(c); + } else if (!strcasecmp(p, "MOD")) { + which_lock = CL_MOD; + lock_ptr = ChanModLock(c); + } else if (!strcasecmp(p, "SEE")) { + which_lock = CL_SEE; + lock_ptr = ChanSeeLock(c); + } else if (!strcasecmp(p, "HIDE")) { + which_lock = CL_HIDE; + lock_ptr = ChanHideLock(c); + } else { + safe_str(T("#-1 NO SUCH LOCK TYPE"), buff, bp); + return; + } + + if (nargs == 2) { + #ifdef FUNCTION_SIDE_EFFECTS + if (!command_check_byname(executor, "@clock") || fun->flags & FN_NOSIDEFX) { + safe_str(T(e_perm), buff, bp); + return; + } + do_chan_lock(executor, args[0], args[1], which_lock); + return; + #else + safe_str(T(e_disabled), buff, bp); + #endif + } + + if (Chan_Can_Decomp(c, executor)) { + safe_str(unparse_boolexp(executor, lock_ptr, 1), buff, bp); + return; + } else { + safe_str(T(e_perm), buff, bp); + return; + } + } + + /* ARGSUSED */ + FUNCTION(fun_cemit) + { + int noisy = 0; + + if (!command_check_byname(executor, "@cemit") || fun->flags & FN_NOSIDEFX) { + safe_str(T(e_perm), buff, bp); + return; + } + if (nargs == 3 && parse_boolean(args[2])) + noisy = 1; + orator = executor; + do_cemit(executor, args[0], args[1], noisy); + } + + COMMAND (cmd_cemit) { + do_cemit(player, arg_left, arg_right, SW_ISSET(sw, SWITCH_NOISY)); + } + + COMMAND (cmd_channel) { + if (switches) + do_channel(player, arg_left, arg_right, switches); + else if (SW_ISSET(sw, SWITCH_LIST)) + do_channel_list(player, arg_left); + else if (SW_ISSET(sw, SWITCH_ADD)) + do_chan_admin(player, arg_left, arg_right, 0); + else if (SW_ISSET(sw, SWITCH_DELETE)) + do_chan_admin(player, arg_left, arg_right, 1); + else if (SW_ISSET(sw, SWITCH_NAME)) + do_chan_admin(player, arg_left, arg_right, 2); + else if (SW_ISSET(sw, SWITCH_RENAME)) + do_chan_admin(player, arg_left, arg_right, 2); + else if (SW_ISSET(sw, SWITCH_PRIVS)) + do_chan_admin(player, arg_left, arg_right, 3); + else if (SW_ISSET(sw, SWITCH_QUIET)) + do_chan_admin(player, arg_left, arg_right, 4); + else if (SW_ISSET(sw, SWITCH_NOISY)) + do_chan_admin(player, arg_left, "n", 4); + else if (SW_ISSET(sw, SWITCH_DECOMPILE)) + do_chan_decompile(player, arg_left, SW_ISSET(sw, SWITCH_BRIEF)); + else if (SW_ISSET(sw, SWITCH_DESCRIBE)) + do_chan_desc(player, arg_left, arg_right); + else if (SW_ISSET(sw, SWITCH_TITLE)) + do_chan_title(player, arg_left, arg_right); + else if (SW_ISSET(sw, SWITCH_CHOWN)) + do_chan_chown(player, arg_left, arg_right); + else if (SW_ISSET(sw, SWITCH_WIPE)) + do_chan_wipe(player, arg_left); + else if (SW_ISSET(sw, SWITCH_MUTE)) + do_chan_user_flags(player, arg_left, arg_right, 0, 0); + else if (SW_ISSET(sw, SWITCH_UNMUTE)) + do_chan_user_flags(player, arg_left, "n", 0, 0); + else if (SW_ISSET(sw, SWITCH_HIDE)) + do_chan_user_flags(player, arg_left, arg_right, 1, 0); + else if (SW_ISSET(sw, SWITCH_UNHIDE)) + do_chan_user_flags(player, arg_left, "n", 1, 0); + else if (SW_ISSET(sw, SWITCH_GAG)) + do_chan_user_flags(player, arg_left, arg_right, 2, 0); + else if (SW_ISSET(sw, SWITCH_UNGAG)) + do_chan_user_flags(player, arg_left, "n", 2, 0); + else if (SW_ISSET(sw, SWITCH_WHAT)) + do_chan_what(player, arg_left); + else if (SW_ISSET(sw, SWITCH_RECALL)) + do_chan_recall(player, arg_left, arg_right); + else if (SW_ISSET(sw, SWITCH_BUFFER)) + do_chan_buffer(player, arg_left, arg_right); + else + do_channel(player, arg_left, NULL, arg_right); + } + + COMMAND (cmd_chat) { + do_chat_by_name(player, arg_left, arg_right, 1); + } + + COMMAND (cmd_clock) { + if (SW_ISSET(sw, SWITCH_JOIN)) + do_chan_lock(player, arg_left, arg_right, CL_JOIN); + else if (SW_ISSET(sw, SWITCH_SPEAK)) + do_chan_lock(player, arg_left, arg_right, CL_SPEAK); + else if (SW_ISSET(sw, SWITCH_MOD)) + do_chan_lock(player, arg_left, arg_right, CL_MOD); + else if (SW_ISSET(sw, SWITCH_SEE)) + do_chan_lock(player, arg_left, arg_right, CL_SEE); + else if (SW_ISSET(sw, SWITCH_HIDE)) + do_chan_lock(player, arg_left, arg_right, CL_HIDE); + else + notify(player, T("You must specify a type of lock")); + } + + /** Find the next player on a channel to notify. + * This function is a helper for notify_anything that is used to + * notify all players on a channel. + * \param current next dbref to notify (not used). + * \param data pointer to structure containing channel and chanuser data. + * \return next dbref to notify. + */ + dbref + na_channel(current, data) + dbref current; + void *data; + { + struct na_cpass *nac = data; + CHANUSER *u, *nu; + int cont; + + nu = nac->u; + do { + u = nu; + if (!u) + return NOTHING; + current = CUdbref(u); + nu = u->next; + cont = (!GoodObject(current) || + (nac->checkquiet && Chanuser_Quiet(u)) || + Chanuser_Gag(u) || (IsPlayer(current) && !Connected(current))); + } while (cont); + nac->u = nu; + return current; + } + + /** Broadcast a message to a channel. + * \param channel pointer to channel to broadcast to. + * \param player message speaker. + * \param flags broadcast flag mask (0x1 = checkquiet, 0x2 = nospoof) + * \param fmt message format string. + */ + void WIN32_CDECL + channel_broadcast(CHAN *channel, dbref player, int flags, const char *fmt, ...) + /* flags: 0x1 = checkquiet, 0x2 = nospoof */ + { + va_list args; + #ifdef HAS_VSNPRINTF + char tbuf1[BUFFER_LEN]; + #else + char tbuf1[BUFFER_LEN * 2]; /* Safety margin as per tprintf */ + #endif + struct na_cpass nac; + + /* Make sure we can write to the channel before doing so */ + if (Channel_Disabled(channel)) + return; + + va_start(args, fmt); + + #ifdef HAS_VSNPRINTF + (void) vsnprintf(tbuf1, sizeof tbuf1, fmt, args); + #else + (void) vsprintf(tbuf1, fmt, args); + #endif + va_end(args); + tbuf1[BUFFER_LEN - 1] = '\0'; + + nac.u = ChanUsers(channel); + nac.checkquiet = (flags & CU_QUIET) ? 1 : 0; + notify_anything(player, na_channel, &nac, + (flags & CU_HIDE) ? ns_esnotify : NULL, 0, tbuf1); + channel_push_buffer(channel, tbuf1); + } + + static void + channel_push_buffer(CHAN *c, char *tbuf1) + { + int len = strlen(tbuf1); + int room = len + sizeof(len) + sizeof(time_t) + 1; + if (!ChanBuffer(c)) + return; + if (ChanBufferEnd(c) > ChanBuffer(c)) { + while ((ChanBufferSize(c) - (ChanBufferEnd(c) - ChanBuffer(c))) < room) + channel_shift_buffer(c); + } + memcpy(ChanBufferEnd(c), &len, sizeof(len)); + ChanBufferEnd(c) += sizeof(len); + memcpy(ChanBufferEnd(c), &mudtime, sizeof(time_t)); + ChanBufferEnd(c) += sizeof(time_t); + memcpy(ChanBufferEnd(c), tbuf1, len + 1); + ChanBufferEnd(c) += len + 1; + ChanNumBuffered(c)++; + } + + static void + channel_shift_buffer(CHAN *c) + { + char *p = ChanBuffer(c); + int size; + if (!*p) + return; /* Shouldn't happen */ + /* First 4 bytes is the size of the first string, not including \0 */ + memcpy(&size, p, sizeof(size)); + /* Jump to the start of the next string */ + p += size + sizeof(size) + sizeof(time_t) + 1; + /* Shift everything here and after up to the front */ + memmove(ChanBuffer(c), p, ChanBufferEnd(c) - p); + ChanBufferEnd(c) -= (p - ChanBuffer(c)); + ChanNumBuffered(c)--; + } + + /* Size of buffer in lines */ + static int + channel_buffer_lines(CHAN *c) + { + if (ChanBuffer(c)) + return ChanBufferSize(c) / (BUFFER_LEN + sizeof(int) + sizeof(time_t)); + else + return 0; + } + + /* Allocate a channel buffer and return the size in bytes. + * The channel buffer should hold enough space for the given + * number of lines (in full) plus an initial int for each line + * giving its size + */ + static void + channel_allocate_buffer(CHAN *c, int lines) + { + int bytes = lines * (BUFFER_LEN + sizeof(int) + sizeof(time_t)); + ChanBuffer(c) = (char *) malloc(bytes); + *ChanBuffer(c) = '\0'; + ChanBufferEnd(c) = ChanBuffer(c); + ChanNumBuffered(c) = 0; + ChanBufferSize(c) = bytes; + } + + static void + channel_reallocate_buffer(CHAN *c, int lines) + { + int bytes = lines * (BUFFER_LEN + sizeof(int) + sizeof(time_t)); + /* If we were accidentally called without a buffer, deal */ + if (!ChanBuffer(c)) { + channel_allocate_buffer(c, lines); + return; + } + /* Are we not changing size? */ + if (ChanBufferSize(c) == bytes) + return; + if (ChanBufferSize(c) > bytes) { + /* Shrinking the buffer */ + while ((ChanBufferEnd(c) - ChanBuffer(c)) >= bytes) + channel_shift_buffer(c); + } + ChanBuffer(c) = (char *) realloc(ChanBuffer(c), bytes); + ChanBufferSize(c) = bytes; + } + + static void + channel_free_buffer(CHAN *c) + { + if (ChanBuffer(c)) + free(ChanBuffer(c)); + ChanBuffer(c) = ChanBufferEnd(c) = NULL; + ChanBufferSize(c) = 0; + ChanNumBuffered(c) = 0; + } + + + /** Recall past lines from the channel's buffer. + * We try to recall no more lines that are requested by the player, + * but sometimes we may have fewer to recall. + * \verbatim + * This is the top-level function for @chan/recall. + * \endverbatim + * \param player the enactor. + * \param name the name of the channel. + * \param lines a string given the number of lines to recall (default all). + */ + void + do_chan_recall(dbref player, const char *name, const char *lines) + { + CHAN *chan; + CHANUSER *u; + int num_lines = INT_MAX; + char *p; + int size; + time_t timestamp; + char tbuf1[BUFFER_LEN], *stamp; + + if (!name || !*name) { + notify(player, T("You need to specify a channel.")); + return; + } + if (lines && *lines) { + if (is_integer(lines)) + num_lines = parse_integer(lines); + else { + notify(player, T("How many lines did you want to recall?")); + return; + } + } + if (num_lines < 1) { + notify(player, T("How many lines did you want to recall?")); + return; + } + + test_channel(player, name, chan); + if (!Chan_Can_See(chan, player)) { + if (onchannel(player, chan)) + notify_format(player, + T("CHAT: You can't do that with channel <%s>."), + ChanName(chan)); + else + notify(player, T("CHAT: I don't recognize that channel.")); + return; + } + u = onchannel(player, chan); + if (!u) { + notify(player, T("CHAT: You must join a channel to recall from it.")); + return; + } + if (!ChanBuffer(chan)) { + notify(player, T("CHAT: That channel doesn't have a recall buffer.")); + return; + } + if (ChanBuffer(chan) == ChanBufferEnd(chan)) { + notify(player, T("CHAT: Nothing to recall.")); + return; + } + + p = ChanBuffer(chan); + /* Do we need to skip any lines? */ + if (num_lines < ChanNumBuffered(chan)) { + int skip = ChanNumBuffered(chan) - num_lines; + while (skip) { + memcpy(&size, p, sizeof(size)); + p += sizeof(size) + sizeof(time_t) + size + 1; + skip--; + } + } + /* Now show everything from this point on */ + while (p < ChanBufferEnd(chan)) { + memcpy(&size, p, sizeof(size)); + p += sizeof(size); + memcpy(×tamp, p, sizeof(time_t)); + stamp = (char *) ctime(×tamp); + stamp[strlen(stamp) - 1] = '\0'; + p += sizeof(time_t); + memcpy(tbuf1, p, size + 1); + notify_format(player, "%s %s", stamp, tbuf1); + p += size + 1; + } + } + + /** Set the size of a channel's buffer in maximum lines. + * \verbatim + * This is the top-level function for @chan/buffer. + * \endverbatim + * \param player the enactor. + * \param name the name of the channel. + * \param lines a string given the number of lines to buffer. + */ + void + do_chan_buffer(dbref player, const char *name, const char *lines) + { + CHAN *chan; + int size; + + if (!name || !*name) { + notify(player, T("You need to specify a channel.")); + return; + } + if (!lines || !*lines || !is_integer(lines)) { + notify(player, T("You need to specify the number of lines to buffer.")); + return; + } + size = parse_integer(lines); + if (size < 0 || size > 10) { + notify(player, T("Invalid buffer size.")); + return; + } + test_channel(player, name, chan); + if (!Chan_Can_Modify(chan, player)) { + notify(player, T("Permission denied.")); + return; + } + if (!size) { + /* Remove a channel's buffer */ + if (ChanBuffer(chan)) { + channel_free_buffer(chan); + notify_format(player, + T("CHAT: Channel buffering disabled for channel <%s>."), + ChanName(chan)); + } else { + notify_format(player, + T + ("CHAT: Channel buffering already disabled for channel <%s>."), + ChanName(chan)); + } + } else { + if (ChanBuffer(chan)) { + /* Resize a buffer */ + channel_reallocate_buffer(chan, size); + } else { + /* Start a new buffer */ + channel_allocate_buffer(chan, size); + notify_format(player, + T("CHAT: Buffering enabled on channel <%s>."), + ChanName(chan)); + } + } + } + + + #endif /* CHAT_SYSTEM */ *** 1_7_7.231/src/destroy.c Wed, 12 Feb 2003 14:26:12 -0600 dunemush (pennmush/c/24_destroy.c 1.24.2.2.1.3.1.1.1.1.1.1.1.4.1.13 660) --- 1_7_7.308(w)/src/destroy.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/24_destroy.c 1.24.2.2.1.3.1.1.1.1.1.1.1.4.1.15 660) *************** *** 103,110 **** extern struct db_stat_info current_state; ! #define SetMarked(x) db[x].type |= TYPE_MARKED ! #define ClearMarked(x) db[x].type &= ~TYPE_MARKED /* Section I: do_destroy() and related functions. This section is where --- 103,110 ---- extern struct db_stat_info current_state; ! #define SetMarked(x) Type(x) |= TYPE_MARKED ! #define ClearMarked(x) Type(x) &= ~TYPE_MARKED /* Section I: do_destroy() and related functions. This section is where *************** *** 319,328 **** * \param confirm if 1, called with /override (or nuke). */ void ! do_destroy(player, name, confirm) ! dbref player; ! char *name; ! int confirm; { dbref thing; thing = what_to_destroy(player, name, confirm); --- 319,325 ---- * \param confirm if 1, called with /override (or nuke). */ void ! do_destroy(dbref player, char *name, int confirm) { dbref thing; thing = what_to_destroy(player, name, confirm); *************** *** 723,729 **** break; } ! db[thing].type = TYPE_GARBAGE; destroy_flag_bitmask(Flags(thing)); Flags(thing) = NULL; Location(thing) = NOTHING; --- 720,726 ---- break; } ! Type(thing) = TYPE_GARBAGE; destroy_flag_bitmask(Flags(thing)); Flags(thing) = NULL; Location(thing) = NOTHING; *** 1_7_7.231/src/create.c Wed, 12 Feb 2003 14:26:12 -0600 dunemush (pennmush/c/27_create.c 1.27.1.3.1.1.1.1.1.1.1.2.1.1.1.1.1.18 660) --- 1_7_7.308(w)/src/create.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/27_create.c 1.27.1.3.1.1.1.1.1.1.1.2.1.1.1.1.1.19 660) *************** *** 121,127 **** Owner(new_exit) = Owner(player); Zone(new_exit) = Zone(player); Source(new_exit) = loc; ! db[new_exit].type = TYPE_EXIT; Flags(new_exit) = string_to_bits(options.exit_flags); /* link it in */ --- 121,127 ---- Owner(new_exit) = Owner(player); Zone(new_exit) = Zone(player); Source(new_exit) = loc; ! Type(new_exit) = TYPE_EXIT; Flags(new_exit) = string_to_bits(options.exit_flags); /* link it in */ *************** *** 387,393 **** set_name(room, name); Owner(room) = Owner(player); Zone(room) = Zone(player); ! db[room].type = TYPE_ROOM; Flags(room) = string_to_bits(options.room_flags); notify_format(player, T("%s created with room number %d."), name, room); --- 387,393 ---- set_name(room, name); Owner(room) = Owner(player); Zone(room) = Zone(player); ! Type(room) = TYPE_ROOM; Flags(room) = string_to_bits(options.room_flags); notify_format(player, T("%s created with room number %d."), name, room); *************** *** 450,456 **** Owner(thing) = Owner(player); Zone(thing) = Zone(player); s_Pennies(thing, cost); ! db[thing].type = TYPE_THING; Flags(thing) = string_to_bits(options.thing_flags); /* home is here (if we can link to it) or player's home */ --- 450,456 ---- Owner(thing) = Owner(player); Zone(thing) = Zone(player); s_Pennies(thing, cost); ! Type(thing) = TYPE_THING; Flags(thing) = string_to_bits(options.thing_flags); /* home is here (if we can link to it) or player's home */ *** 1_7_7.231/src/conf.c Sun, 16 Feb 2003 22:17:19 -0600 dunemush (pennmush/c/31_conf.c 1.41.2.3.1.3.1.2.1.15.1.1.1.2.1.2.1.12 660) --- 1_7_7.308(w)/src/conf.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/31_conf.c 1.41.2.3.1.3.1.2.1.15.1.1.1.1.1.2 660) *************** *** 854,861 **** options.player_start = 0; options.master_room = 2; options.base_room = 0; ! options.idle_timeout = 10801; ! options.unconnected_idle_timeout = 10801; options.dump_interval = 3601; strcpy(options.dump_message, T("GAME: Dumping database. Game may freeze for a minute")); --- 854,861 ---- options.player_start = 0; options.master_room = 2; options.base_room = 0; ! options.idle_timeout = 0; ! options.unconnected_idle_timeout = 5; options.dump_interval = 3601; strcpy(options.dump_message, T("GAME: Dumping database. Game may freeze for a minute")); *** 1_7_7.231/src/command.c Sun, 09 Feb 2003 14:41:06 -0600 dunemush (pennmush/c/36_command.c 1.56.1.1.1.1.1.1.1.2.1.1.1.1.1.5.1.2.1.1.1.1.1.2.1.3.1.10.1.1.2.4.2.10 660) --- 1_7_7.308(w)/src/command.c Tue, 25 Mar 2003 16:22:36 -0600 dunemush (pennmush/c/36_command.c 1.56.1.1.1.1.1.1.1.2.1.1.1.1.1.5.1.2.1.1.1.1.1.2.1.3.1.10.1.1.2.4.2.15 660) *************** *** 22,30 **** #include "match.h" #include "attrib.h" #include "extmail.h" - #ifdef CHAT_SYSTEM - #include "extchat.h" - #endif #include "getpgsiz.h" #include "parse.h" #include "access.h" --- 22,27 ---- *************** *** 80,86 **** {"@CEMIT", "NOEVAL NOISY", cmd_cemit, CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, {"@CHANNEL", ! "LIST ADD DELETE RENAME NAME PRIVS QUIET NOISY DECOMPILE DESCRIBE CHOWN WIPE MUTE UNMUTE GAG UNGAG HIDE UNHIDE WHAT TITLE BRIEF", cmd_channel, CMD_T_ANY | CMD_T_SWITCHES | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, {"@CHAT", NULL, cmd_chat, CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, --- 77,83 ---- {"@CEMIT", "NOEVAL NOISY", cmd_cemit, CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, {"@CHANNEL", ! "LIST ADD DELETE RENAME NAME PRIVS QUIET NOISY DECOMPILE DESCRIBE CHOWN WIPE MUTE UNMUTE GAG UNGAG HIDE UNHIDE WHAT TITLE BRIEF RECALL BUFFER", cmd_channel, CMD_T_ANY | CMD_T_SWITCHES | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, {"@CHAT", NULL, cmd_chat, CMD_T_ANY | CMD_T_EQSPLIT | CMD_T_NOGAGGED, 0, 0}, *************** *** 1329,1335 **** { int ok; int check_flags; - object_flag_type nullmask; /* If disabled, return silently */ if (cmd->type & CMD_T_DISABLED) --- 1326,1331 ---- *************** *** 1374,1382 **** * any match, the player is ok to do the command. */ ok = 1; ! nullmask = new_flag_bitmask(); ! check_flags = cmd->flagmask ! && memcmp(nullmask, cmd->flagmask, sizeof(nullmask)); if (!((!cmd->powers && !check_flags) || (cmd->powers && (cmd->powers & Powers(player))) || --- 1370,1376 ---- * any match, the player is ok to do the command. */ ok = 1; ! check_flags = cmd->flagmask && !null_flagmask(cmd->flagmask); if (!((!cmd->powers && !check_flags) || (cmd->powers && (cmd->powers & Powers(player))) || *************** *** 1384,1390 **** notify(player, T("Permission denied.")); ok = 0; } - destroy_flag_bitmask(nullmask); return ok; } --- 1378,1383 ---- *************** *** 1477,1482 **** --- 1470,1479 ---- notify(player, T("No such command.")); return; } + if ((cmd->func == cmd_password) || (cmd->func == cmd_newpassword)) { + notify(player, T("Hooks not allowed with that command.")); + return; + } if (!obj && !attrname) { struct hook_data *h; *** 1_7_7.231/src/cmds.c Wed, 12 Feb 2003 14:26:12 -0600 dunemush (pennmush/c/37_cmds.c 1.33.1.1.1.2.1.2.2.3.1.1.1.2.1.1.1.3.1.8.1.1.2.2.2.8 660) --- 1_7_7.308(w)/src/cmds.c Tue, 25 Mar 2003 16:22:35 -0600 dunemush (pennmush/c/37_cmds.c 1.33.1.1.1.2.1.2.2.3.1.1.1.2.1.1.1.3.1.8.1.1.2.2.2.10 660) *************** *** 22,30 **** #include "attrib.h" #include "extmail.h" #include "malias.h" - #ifdef CHAT_SYSTEM - #include "extchat.h" - #endif #include "getpgsiz.h" #include "parse.h" #include "access.h" --- 22,27 ---- *************** *** 104,168 **** break_called = 1; } - #ifdef CHAT_SYSTEM - COMMAND (cmd_cemit) { - do_cemit(player, arg_left, arg_right, SW_ISSET(sw, SWITCH_NOISY)); - } - - COMMAND (cmd_channel) { - if (switches) - do_channel(player, arg_left, arg_right, switches); - else if (SW_ISSET(sw, SWITCH_LIST)) - do_channel_list(player, arg_left); - - else if (SW_ISSET(sw, SWITCH_ADD)) - do_chan_admin(player, arg_left, arg_right, 0); - else if (SW_ISSET(sw, SWITCH_DELETE)) - do_chan_admin(player, arg_left, arg_right, 1); - else if (SW_ISSET(sw, SWITCH_NAME)) - do_chan_admin(player, arg_left, arg_right, 2); - else if (SW_ISSET(sw, SWITCH_RENAME)) - do_chan_admin(player, arg_left, arg_right, 2); - else if (SW_ISSET(sw, SWITCH_PRIVS)) - do_chan_admin(player, arg_left, arg_right, 3); - else if (SW_ISSET(sw, SWITCH_QUIET)) - do_chan_admin(player, arg_left, arg_right, 4); - else if (SW_ISSET(sw, SWITCH_NOISY)) - do_chan_admin(player, arg_left, "n", 4); - else if (SW_ISSET(sw, SWITCH_DECOMPILE)) - do_chan_decompile(player, arg_left, SW_ISSET(sw, SWITCH_BRIEF)); - else if (SW_ISSET(sw, SWITCH_DESCRIBE)) - do_chan_desc(player, arg_left, arg_right); - else if (SW_ISSET(sw, SWITCH_TITLE)) - do_chan_title(player, arg_left, arg_right); - else if (SW_ISSET(sw, SWITCH_CHOWN)) - do_chan_chown(player, arg_left, arg_right); - else if (SW_ISSET(sw, SWITCH_WIPE)) - do_chan_wipe(player, arg_left); - else if (SW_ISSET(sw, SWITCH_MUTE)) - do_chan_user_flags(player, arg_left, arg_right, 0, 0); - else if (SW_ISSET(sw, SWITCH_UNMUTE)) - do_chan_user_flags(player, arg_left, "n", 0, 0); - else if (SW_ISSET(sw, SWITCH_HIDE)) - do_chan_user_flags(player, arg_left, arg_right, 1, 0); - else if (SW_ISSET(sw, SWITCH_UNHIDE)) - do_chan_user_flags(player, arg_left, "n", 1, 0); - else if (SW_ISSET(sw, SWITCH_GAG)) - do_chan_user_flags(player, arg_left, arg_right, 2, 0); - else if (SW_ISSET(sw, SWITCH_UNGAG)) - do_chan_user_flags(player, arg_left, "n", 2, 0); - else if (SW_ISSET(sw, SWITCH_WHAT)) - do_chan_what(player, arg_left); - else - do_channel(player, arg_left, NULL, arg_right); - } - - COMMAND (cmd_chat) { - do_chat_by_name(player, arg_left, arg_right, 1); - } - - #endif - COMMAND (cmd_chownall) { do_chownall(player, arg_left, arg_right, SW_ISSET(sw, SWITCH_PRESERVE)); } --- 101,106 ---- *************** *** 235,257 **** do_clone(player, arg_left, arg_right, SWITCH_NONE); } - #ifdef CHAT_SYSTEM - COMMAND (cmd_clock) { - if (SW_ISSET(sw, SWITCH_JOIN)) - do_chan_lock(player, arg_left, arg_right, CL_JOIN); - else if (SW_ISSET(sw, SWITCH_SPEAK)) - do_chan_lock(player, arg_left, arg_right, CL_SPEAK); - else if (SW_ISSET(sw, SWITCH_MOD)) - do_chan_lock(player, arg_left, arg_right, CL_MOD); - else if (SW_ISSET(sw, SWITCH_SEE)) - do_chan_lock(player, arg_left, arg_right, CL_SEE); - else if (SW_ISSET(sw, SWITCH_HIDE)) - do_chan_lock(player, arg_left, arg_right, CL_HIDE); - else - notify(player, T("You must specify a type of lock")); - } - #endif - COMMAND (cmd_dbck) { do_dbck(player); } --- 173,178 ---- *************** *** 712,718 **** silent = SILENT_PEMIT ? PEMIT_SILENT : 0; if (SW_ISSET(sw, SWITCH_LIST)) ! do_pemit_list(player, arg_left, arg_right, silent); else if (SW_ISSET(sw, SWITCH_CONTENTS)) do_remit(player, arg_left, arg_right, silent); else --- 633,639 ---- silent = SILENT_PEMIT ? PEMIT_SILENT : 0; if (SW_ISSET(sw, SWITCH_LIST)) ! do_pemit_list(player, arg_left, arg_right, 1); else if (SW_ISSET(sw, SWITCH_CONTENTS)) do_remit(player, arg_left, arg_right, silent); else *** 1_7_7.231/src/bsd.c Sat, 22 Feb 2003 13:49:12 -0600 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.13.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.8.2.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.6 660) --- 1_7_7.308(w)/src/bsd.c Tue, 25 Mar 2003 16:22:35 -0600 dunemush (pennmush/c/38_bsd.c 1.58.1.11.1.2.1.5.1.7.1.14.1.13.1.9.1.4.1.2.1.12.1.1.1.1.1.2.1.1.1.13.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.8.2.1.1.1.1.1.1.1.1.2.1.1.1.1.1.1.1.10 660) *************** *** 106,120 **** #include "mymalloc.h" - #ifdef CHAT_SYSTEM - #include "extchat.h" - extern CHAN *channels; - struct na_cpass { - CHANUSER *u; - int checkquiet; - }; - - #endif #include "extmail.h" #include "attrib.h" #include "game.h" --- 106,111 ---- *************** *** 157,162 **** --- 148,154 ---- static int extrafd; int shutdown_flag = 0; extern int paranoid_dump; /* from game.c */ + extern void chat_player_announce(dbref player, char *msg); static int login_number = 0; static int under_limit = 1; *************** *** 245,251 **** "Unable to register that player with that email address."; static const char *register_success = "Registration successful! You will receive your password by email."; - static const char *flushed_message = "\r\n\x1B[0m\r\n"; static const char *shutdown_message = "Going down - Bye"; static const char *asterisk_line = "**********************************************************************"; --- 237,242 ---- *************** *** 318,323 **** --- 309,315 ---- struct timeval *msec_add(struct timeval *t, int x); struct timeval *update_quotas(struct timeval *last, struct timeval *current); + static int how_many_fds(void); static void shovechars(Port_t port, Port_t sslport); static int test_connection(int newsock); #ifndef INFO_SLAVE *************** *** 347,361 **** void logout_sock(DESC *d); void shutdownsock(DESC *d); DESC *initializesock(int s, char *addr, char *ip); struct text_block *make_text_block(const unsigned char *s, int n); void free_text_block(struct text_block *t); void add_to_queue(struct text_queue *q, const unsigned char *b, int n); int flush_queue(struct text_queue *q, int n); ! static int queue_write(DESC *d, const unsigned char *b, int n); ! static int queue_newwrite(DESC *d, const unsigned char *b, int n); ! static int queue_string(DESC *d, const char *s); ! static int queue_string_eol(DESC *d, const char *s); ! int process_output(DESC *d); void freeqs(DESC *d); void welcome_user(DESC *d); static void dump_info(DESC *call_by); --- 339,355 ---- void logout_sock(DESC *d); void shutdownsock(DESC *d); DESC *initializesock(int s, char *addr, char *ip); + int process_output(DESC *d); + /* Notify.c */ struct text_block *make_text_block(const unsigned char *s, int n); void free_text_block(struct text_block *t); void add_to_queue(struct text_queue *q, const unsigned char *b, int n); int flush_queue(struct text_queue *q, int n); ! int queue_write(DESC *d, const unsigned char *b, int n); ! int queue_eol(DESC *d); ! int queue_newwrite(DESC *d, const unsigned char *b, int n); ! int queue_string(DESC *d, const char *s); ! int queue_string_eol(DESC *d, const char *s); void freeqs(DESC *d); void welcome_user(DESC *d); static void dump_info(DESC *call_by); *************** *** 826,1810 **** } - enum na_type { - NA_ASCII = 0, - NA_ANSI, /* ANSI flag */ - NA_COLOR, /* ANSI and COLOR flags */ - NA_PUEBLO, /* html */ - NA_PASCII, /* Player without any of the above */ - NA_TANSI, /* Like above with telnet-aware client */ - NA_TCOLOR, /* Like above with telnet-aware client */ - NA_TPASCII, /* Like above with telnet-aware client */ - NA_NANSI, /* ANSI and NOACCENTS */ - NA_NCOLOR, /* ANSI, COLOR, NOACCENTS */ - NA_NPUEBLO, /* html & NOACCENTS */ - NA_NPASCII /* 11. NOACCENTS */ - }; - #define TA_BGC 0 - #define TA_FGC 1 - #define TA_BOLD 2 - #define TA_REV 3 - #define TA_BLINK 4 - #define TA_ULINE 5 - - static int na_depth = 0; - - #define MESSAGE_TYPES 12 - - struct notify_strings { - unsigned char *message; - size_t len; - int made; - }; - - static int how_many_fds(void); - static void fillstate(int state[], const unsigned char **f); - static void ansi_change_state(char *t, char **o, int color, int *state, - int *newstate); - static enum na_type notify_type(DESC *d); - static void free_strings(struct notify_strings messages[]); - static void zero_strings(struct notify_strings messages[]); - static unsigned char *notify_makestring(const char *message, - struct notify_strings messages[], - enum na_type type); - - - static void - fillstate(int state[6], const unsigned char **f) - { - const unsigned char *p; - int i; - int n; - p = *f; - p++; - if (*p != '[') { - while (*p && *p != 'm') - p++; - } else { - p++; - while (*p && *p != 'm') { - if ((*p > '9') || (*p < '0')) { - /* Nada */ - } else if (!(*(p + 1)) || (*(p + 1) == 'm') || (*(p + 1) == ';')) { - /* ShortCode */ ; - switch (*p) { - case '0': - for (i = 0; i < 6; i++) - state[i] = 0; - break; - case '1': - state[TA_BOLD] = 1; - break; - case '7': - state[TA_REV] = 1; - break; - case '5': - state[TA_BLINK] = 1; - break; - case '4': - state[TA_ULINE] = 1; - break; - } - } else { - n = (*p - '0') * 10; - p++; - n += (*p - '0'); - if ((n >= 30) && (n <= 37)) - state[TA_FGC] = n - 29; - else if ((n >= 40) && (n <= 47)) - state[TA_BGC] = n - 39; - } - p++; - } - } - if ((p != *f) && (*p != 'm')) - p--; - *f = p; - } - - #define add_ansi_if(x,c) \ - do { \ - if (newstate[(x)] && (newstate[(x)]!=state[(x)])) { \ - if (i) safe_chr(';',t,o); \ - safe_str((c),t,o); \ - i=1; \ - } \ - } while (0) - - static void - ansi_change_state(char *t, char **o, int color, int *state, int *newstate) - { - int i, n; - if ((state[TA_BOLD] && !newstate[TA_BOLD]) || - (state[TA_REV] && !newstate[TA_REV]) || - (state[TA_BLINK] && !newstate[TA_BLINK]) || - (state[TA_ULINE] && !newstate[TA_ULINE]) || - (color && state[TA_FGC] && !newstate[TA_FGC]) || - (color && state[TA_BGC] && !newstate[TA_BGC])) { - for (n = 0; n < 6; n++) - state[n] = 0; - safe_str(ANSI_NORMAL, t, o); - } - if ((newstate[TA_BOLD] && (newstate[TA_BOLD] != state[TA_BOLD])) || - (newstate[TA_REV] && (newstate[TA_REV] != state[TA_REV])) || - (newstate[TA_BLINK] && (newstate[TA_BLINK] != state[TA_BLINK])) || - (newstate[TA_ULINE] && (newstate[TA_ULINE] != state[TA_ULINE])) || - (color && newstate[TA_FGC] && (newstate[TA_FGC] != state[TA_FGC])) || - (color && newstate[TA_BGC] && (newstate[TA_BGC] != state[TA_BGC]))) { - safe_chr(ESC_CHAR, t, o); - safe_chr('[', t, o); - i = 0; - add_ansi_if(TA_BOLD, "1"); - add_ansi_if(TA_REV, "7"); - add_ansi_if(TA_BLINK, "5"); - add_ansi_if(TA_ULINE, "4"); - if (color) { - add_ansi_if(TA_FGC, unparse_integer(newstate[TA_FGC] + 29)); - add_ansi_if(TA_BGC, unparse_integer(newstate[TA_BGC] + 39)); - } - safe_chr('m', t, o); - } - for (n = 0; n < 6; n++) - state[n] = newstate[n]; - } - - #undef add_ansi_if - - int html_cols[] = { - 0xC0C0C0, /* Default */ - 0x000000, - 0xC00000, - 0x00C000, - 0xC0C000, - 0x0000C0, - 0xC000C0, - 0x00C0C0, - 0xC0C0C0 - }; - - static void - zero_strings(struct notify_strings messages[]) - { - int n; - for (n = 0; n < MESSAGE_TYPES; n++) { - messages[n].message = NULL; - messages[n].len = 0; - messages[n].made = 0; - } - } - - static void - free_strings(struct notify_strings messages[]) - { - int n; - for (n = 0; n < MESSAGE_TYPES; n++) - if (messages[n].message) - mush_free(messages[n].message, "string"); - } - - static unsigned char * - notify_makestring(const char *message, struct notify_strings messages[], - enum na_type type) - { - char *o; - const unsigned char *p; - char *t; - int state[6] = { 0, 0, 0, 0, 0, 0 }; - int newstate[6] = { 0, 0, 0, 0, 0, 0 }; - int n; - int b, f; - int changed = 0; - int color = 0; - int strip = 0; - int fc, bc; - char colbuff[128]; - static char tbuf[BUFFER_LEN]; - - if (messages[type].made) - return messages[type].message; - messages[type].made = 1; - - p = (unsigned char *) message; - o = tbuf; - t = o; - - /* Since well over 50% is this type, we do it quick */ - switch (type) { - case NA_ASCII: - while (*p) { - switch (*p) { - case TAG_START: - while (*p && *p != TAG_END) - p++; - break; - case '\r': - case BEEP_CHAR: - break; - case ESC_CHAR: - while (*p && *p != 'm') - p++; - break; - default: - safe_chr(*p, t, &o); - } - p++; - } - *o = '\0'; - messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); - messages[type].len = o - tbuf; - return messages[type].message; - case NA_NPASCII: - strip = 1; - case NA_PASCII: - case NA_TPASCII: - /* PLAYER Ascii. Different output. \n is \r\n */ - if (type == NA_NPASCII) - strip = 1; - while (*p) { - switch (*p) { - case IAC: - if (type == NA_TPASCII) - safe_str("\xFF\xFF", t, &o); - else if (strip) - safe_str(accent_table[IAC].base, t, &o); - else - safe_chr((char) IAC, t, &o); - break; - case TAG_START: - while (*p && *p != TAG_END) - p++; - break; - case ESC_CHAR: - while (*p && *p != 'm') - p++; - break; - case '\r': - break; - case '\n': - safe_str("\r\n", t, &o); - break; - default: - if (strip && accent_table[(unsigned char) *p].base) - safe_str(accent_table[(unsigned char) *p].base, t, &o); - else - safe_chr(*p, t, &o); - } - p++; - } - *o = '\0'; - messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); - messages[type].len = o - tbuf; - return messages[type].message; - - case NA_NPUEBLO: - strip = 1; - case NA_PUEBLO: - while (*p) { - if (*p == ESC_CHAR) { - fillstate(newstate, &p); - changed = 1; - } else { - if (changed) { - changed = 0; - /* Do we need to close any attribute tags? */ - if (state[TA_BOLD] && !newstate[TA_BOLD]) - safe_str("", t, &o); - if (state[TA_ULINE] && !newstate[TA_ULINE]) - safe_str("", t, &o); - /* Are we going to start a new font? If so, temporarily - * close attribute tags */ - if (!state[TA_BGC] && !state[TA_FGC] && - (newstate[TA_FGC] || newstate[TA_FGC])) { - if (state[TA_BOLD] && newstate[TA_BOLD]) - safe_str("", t, &o); - if (state[TA_ULINE] && newstate[TA_ULINE]) - safe_str("", t, &o); - } - /* Are we changing fonts? If so, close the FONT tag and - any attribute tags */ - if (((state[TA_BGC] || state[TA_FGC]) && - ((state[TA_BGC] != newstate[TA_BGC]) || - (state[TA_FGC] != newstate[TA_FGC]))) || - (state[TA_REV] != newstate[TA_REV])) { - /* If we're in bold, and staying bold, temporarily close the tag */ - if (state[TA_BOLD] && newstate[TA_BOLD]) - safe_str("", t, &o); - if (state[TA_ULINE] && newstate[TA_ULINE]) - safe_str("", t, &o); - safe_str("", t, &o); - } - /* Should we start a new FONT tag? */ - if ((newstate[TA_BGC] && (state[TA_BGC] != newstate[TA_BGC])) - || (newstate[TA_FGC] && (state[TA_FGC] != newstate[TA_FGC])) - || (newstate[TA_REV] && (state[TA_REV] != newstate[TA_REV])) - ) { - fc = newstate[TA_FGC]; - bc = newstate[TA_BGC]; - if (newstate[TA_REV]) { - if (!fc) - fc = 8; - if (!bc) - bc = 1; - f = html_cols[bc]; - b = html_cols[fc]; - } else { - f = html_cols[fc]; - b = html_cols[bc]; - } - if (bc && fc) { - sprintf(colbuff, "", f, b); - } else if (fc) { - sprintf(colbuff, "", f); - } else { - sprintf(colbuff, "", b); - } - safe_str(colbuff, t, &o); - /* Should we reopen attribute tags, too? */ - if (state[TA_BOLD] && newstate[TA_BOLD]) - safe_str("", t, &o); - if (state[TA_ULINE] && newstate[TA_ULINE]) - safe_str("", t, &o); - } - /* If we weren't bold before, or if we were bold+font and now - * are just bold, we reopen bold tag if we're going to be bold - */ - if ((!state[TA_BOLD] || (state[TA_BOLD] && (state[TA_FGC] || - state[TA_BGC]) - && !newstate[TA_FGC] && !newstate[TA_BGC])) - && newstate[TA_BOLD]) - safe_str("", t, &o); - if ((!state[TA_ULINE] || (state[TA_ULINE] && (state[TA_FGC] || - state[TA_BGC]) - && !newstate[TA_FGC] && !newstate[TA_BGC])) - && newstate[TA_ULINE]) - safe_str("", t, &o); - for (n = 0; n < 6; n++) - state[n] = newstate[n]; - } - switch (*p) { - case TAG_START: - safe_chr('<', t, &o); - p++; - while ((*p) && (*p != TAG_END)) { - safe_chr(*p, t, &o); - p++; - } - safe_chr('>', t, &o); - break; - case TAG_END: - /* Should never be seen alone */ - break; - case '\r': - break; - default: - if (strip) { - /* Even if we're NOACCENTS, we must still translate a few things */ - switch ((unsigned char) *p) { - case '\n': - case '&': - case '<': - case '>': - safe_str(accent_table[(unsigned char) *p].entity, t, &o); - break; - default: - if (accent_table[(unsigned char) *p].base) - safe_str(accent_table[(unsigned char) *p].base, t, &o); - else - safe_chr(*p, t, &o); - break; - } - } else if (accent_table[(unsigned char) *p].entity) - safe_str(accent_table[(unsigned char) *p].entity, t, &o); - else - safe_chr(*p, t, &o); - } - } - p++; - } - if (state[TA_BGC] || state[TA_FGC] || state[TA_REV]) - safe_str("", t, &o); - if (state[TA_BOLD]) - safe_str("", t, &o); - if (state[TA_ULINE]) - safe_str("", t, &o); - break; - case NA_COLOR: - case NA_TCOLOR: - case NA_NCOLOR: - color = 1; - /* FALLTHROUGH */ - case NA_ANSI: - case NA_TANSI: - case NA_NANSI: - if (type == NA_NCOLOR || type == NA_NANSI) - strip = 1; - while (*p) { - switch ((unsigned char) *p) { - case IAC: - if (changed) { - changed = 0; - ansi_change_state(t, &o, color, state, newstate); - } - if (type == NA_TANSI || type == NA_TCOLOR) - safe_str("\xFF\xFF", t, &o); - else if (strip && accent_table[IAC].base) - safe_str(accent_table[IAC].base, t, &o); - else - safe_chr((char) IAC, t, &o); - break; - case TAG_START: - while (*p && *p != TAG_END) - p++; - break; - case '\r': - break; - case '\n': - if (changed) { - changed = 0; - ansi_change_state(t, &o, color, state, newstate); - } - safe_str("\r\n", t, &o); - - break; - case ESC_CHAR: - fillstate(newstate, &p); - changed = 1; - break; - default: - if (changed) { - changed = 0; - ansi_change_state(t, &o, color, state, newstate); - } - if (strip && accent_table[(unsigned char) *p].base) - safe_str(accent_table[(unsigned char) *p].base, t, &o); - else - safe_chr(*p, t, &o); - } - p++; - } - if (state[TA_BOLD] || state[TA_REV] || - state[TA_BLINK] || state[TA_ULINE] || - (color && (state[TA_FGC] || state[TA_BGC]))) - safe_str(ANSI_NORMAL, t, &o); - - break; - } - - *o = '\0'; - messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); - messages[type].len = o - tbuf; - return messages[type].message; - } - - dbref - na_one(dbref current, void *data) - { - if (current == NOTHING) - return *((dbref *) data); - else - return NOTHING; - } - - dbref - na_next(dbref current, void *data) - { - if (current == NOTHING) - return *((dbref *) data); - else - return Next(current); - } - - dbref - na_loc(dbref current, void *data) - { - dbref loc = *((dbref *) data); - if (current == NOTHING) - return loc; - else if (current == loc) - return Contents(current); - else - return Next(current); - } - - dbref - na_nextbut(dbref current, void *data) - { - dbref *dbrefs = data; - - do { - if (current == NOTHING) - current = dbrefs[0]; - else - current = Next(current); - } while (current == dbrefs[1]); - return current; - } - - dbref - na_except(dbref current, void *data) - { - dbref *dbrefs = data; - - do { - if (current == NOTHING) - current = dbrefs[0]; - else if (current == dbrefs[0]) - current = Contents(current); - else - current = Next(current); - } while (current == dbrefs[1]); - return current; - } - - dbref - na_except2(dbref current, void *data) - { - dbref *dbrefs = data; - - do { - if (current == NOTHING) - current = dbrefs[0]; - else if (current == dbrefs[0]) - current = Contents(current); - else - current = Next(current); - } while ((current == dbrefs[1]) || (current == dbrefs[2])); - return current; - } - - /* Works like na_except2, but with multiple exceptions. - * dbrefs[0] should indicate the number of exceptions. - * dbrefs[1] is the dbref of the room the message was emitted in. - * dbrefs[2] and up are the exceptions. - */ - dbref - na_exceptN(dbref current, void *data) - { - dbref *dbrefs = data; - int i, check; - - do { - if (current == NOTHING) - current = dbrefs[1]; - else if (current == dbrefs[1]) - current = Contents(current); - else - current = Next(current); - check = 0; - for (i = 2; i < dbrefs[0] + 2; i++) - if (current == dbrefs[i]) - check = 1; - } while (check); - return current; - } - - - static int nohtml_strlen(const char *s, dbref puppet); - static int - nohtml_strlen(const char *s, dbref puppet) - { - const char *p = s; - int n = 0; - - if (GoodObject(puppet)) { - char *name = strstr(s, tprintf("%s> ", Name(puppet))); - if (name == s) { - p += strlen(Name(puppet)) + 2; - } - } - - for (; *p != '\0'; p++) { - switch (*p) { - case TAG_START: - do { - p++; - } while (*p != '\0' && *p != TAG_END); - break; - case TAG_END: /* Just in case */ - break; - default: - n++; - } - } - return n; - } - - static enum na_type - notify_type(DESC *d) - { - enum na_type poutput; - int strip = 0; - - if (!d->connected || IS(d->player, TYPE_PLAYER, "NOACCENTS")) - strip = 1; - - if (d->conn_flags & CONN_HTML) { - poutput = strip ? NA_NPUEBLO : NA_PUEBLO; - } else if (ShowAnsi(d->player)) { - if (ShowAnsiColor(d->player)) { - if (strip) - poutput = NA_NCOLOR; - else - poutput = (d->conn_flags & CONN_TELNET) ? NA_TCOLOR : NA_COLOR; - } else { - if (strip) - poutput = NA_NANSI; - else - poutput = (d->conn_flags & CONN_TELNET) ? NA_TANSI : NA_ANSI; - } - } else { - if (strip) - poutput = NA_NPASCII; - else - poutput = (d->conn_flags & CONN_TELNET) ? NA_TPASCII : NA_PASCII; - } - return poutput; - } - - void - notify_anything(dbref speaker, na_lookup func, - void *fdata, char *(*nsfunc) (dbref, na_lookup func, void *, - int), int flags, - const char *message) - { - dbref target; - dbref passalong[3]; - struct notify_strings messages[MESSAGE_TYPES]; - struct notify_strings nospoofs[MESSAGE_TYPES]; - struct notify_strings paranoids[MESSAGE_TYPES]; - int i, j; - DESC *d; - enum na_type poutput; - unsigned char *pstring; - size_t plen; - char *bp; - ATTR *a; - char *asave; - char const *ap; - char *preserve[NUMQ]; - int havespoof = 0; - int havepara = 0; - char *wsave[10]; - char *tbuf1 = NULL, *nospoof = NULL, *paranoid = NULL, *msgbuf; - static dbref puppet = NOTHING; - - if (!message || *message == '\0' || !func) - return; - - /* Depth check */ - if (na_depth > 7) - return; - na_depth++; - - /* Only allocate these buffers when needed */ - for (i = 0; i < MESSAGE_TYPES; i++) { - messages[i].message = NULL; - messages[i].made = 0; - nospoofs[i].message = NULL; - nospoofs[i].made = 0; - paranoids[i].message = NULL; - paranoids[i].made = 0; - } - - msgbuf = mush_strdup(message, "string"); - - target = NOTHING; - - while ((target = func(target, fdata)) != NOTHING) { - if ((flags & NA_PONLY) && !IsPlayer(target)) - continue; - - if (IsPlayer(target)) { - if (!Connected(target) && options.login_allow && under_limit) - continue; - for (d = descriptor_list; d; d = d->next) { - if (d->connected && d->player == target) { - poutput = notify_type(d); - - if ((flags & NA_PONLY) && (poutput != NA_PUEBLO)) - continue; - - if (nsfunc && Nospoof(target) && (target != speaker)) { - if (Paranoid(target)) { - if (!havepara) { - paranoid = nsfunc(speaker, func, fdata, 1); - havepara = 1; - } - pstring = notify_makestring(paranoid, paranoids, poutput); - plen = paranoids[poutput].len; - } else { - if (!havespoof) { - nospoof = nsfunc(speaker, func, fdata, 0); - havespoof = 1; - } - pstring = notify_makestring(nospoof, nospoofs, poutput); - plen = nospoofs[poutput].len; - } - queue_newwrite(d, pstring, plen); - } - pstring = notify_makestring(msgbuf, messages, poutput); - plen = messages[poutput].len; - - if (pstring && *pstring - && ((d->conn_flags & CONN_HTML) || !(flags & NA_NOENTER) - || ((flags & NA_PUPPET2) - && nohtml_strlen(msgbuf, puppet) > 0))) { - queue_newwrite(d, pstring, plen); - } - if (!(flags & NA_NOENTER)) { - if ((poutput == NA_PUEBLO) || (poutput == NA_NPUEBLO)) { - if (flags & NA_NOPENTER) - queue_newwrite(d, (unsigned char *) "\n", 1); - else - queue_newwrite(d, (unsigned char *) "
\n", 5); - } else { - queue_newwrite(d, (unsigned char *) "\r\n", 2); - } - } - } - } - } else if (Puppet(target) && - ((Location(target) != Location(Owner(target))) || - has_flag_by_name(target, "VERBOSE", NOTYPE) || - (flags & NA_MUST_PUPPET)) && - ((flags & NA_PUPPET) || !(flags & NA_NORELAY))) { - dbref last = puppet; - puppet = target; - if (!tbuf1) - tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string"); - bp = tbuf1; - safe_str(Name(target), tbuf1, &bp); - safe_str("> ", tbuf1, &bp); - safe_str(msgbuf, tbuf1, &bp); - *bp = '\0'; - notify_anything(speaker, na_one, &Owner(target), NULL, - flags | NA_NORELAY | NA_PUPPET2, tbuf1); - puppet = last; - } - if ((flags & NA_NOLISTEN) - || (!PLAYER_LISTEN && IsPlayer(target)) - || IsExit(target)) - continue; - - /* do @listen stuff */ - a = atr_get_noparent(target, "LISTEN"); - if (a) { - if (!tbuf1) - tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string"); - strcpy(tbuf1, uncompress(a->value)); - if ((AL_FLAGS(a) & AF_REGEXP) - ? regexp_match_case(tbuf1, - (char *) notify_makestring(msgbuf, messages, - NA_ASCII), - AL_FLAGS(a) & AF_CASE) - : wild_match_case(tbuf1, - (char *) notify_makestring(msgbuf, messages, - NA_ASCII), - AL_FLAGS(a) & AF_CASE)) { - if (eval_lock(speaker, target, Listen_Lock)) - if (PLAYER_AHEAR || (!IsPlayer(target))) { - if (speaker != target) - charge_action(speaker, target, "AHEAR"); - else - charge_action(speaker, target, "AMHEAR"); - charge_action(speaker, target, "AAHEAR"); - } - if (!(flags & NA_NORELAY) && !member(speaker, Contents(target)) && - !filter_found(target, - (char *) notify_makestring(msgbuf, messages, - NA_ASCII), 1)) { - passalong[0] = target; - passalong[1] = target; - passalong[2] = Owner(target); - a = atr_get(target, "INPREFIX"); - if (a) { - for (j = 0; j < 10; j++) - wsave[j] = wenv[j]; - wenv[0] = (char *) msgbuf; - for (j = 1; j < 10; j++) - wenv[j] = NULL; - save_global_regs("inprefix_save", preserve); - asave = safe_uncompress(a->value); - ap = asave; - bp = tbuf1; - process_expression(tbuf1, &bp, &ap, target, speaker, speaker, - PE_DEFAULT, PT_DEFAULT, NULL); - if (bp != tbuf1) - safe_chr(' ', tbuf1, &bp); - safe_str(msgbuf, tbuf1, &bp); - *bp = 0; - free(asave); - restore_global_regs("inprefix_save", preserve); - for (j = 0; j < 10; j++) - wenv[j] = wsave[j]; - } - notify_anything(speaker, Puppet(target) ? na_except2 : na_except, - passalong, NULL, flags | NA_NORELAY, - (a) ? tbuf1 : msgbuf); - } - } - } - /* if object is flagged LISTENER, check for ^ listen patterns - * * these are like AHEAR - object cannot trigger itself. - * * unlike normal @listen, don't pass the message on. - * */ - - if ((speaker != target) && (ThingListen(target) || RoomListen(target)) - && eval_lock(speaker, target, Listen_Lock) - ) - atr_comm_match(target, speaker, '^', ':', - (char *) notify_makestring(msgbuf, messages, NA_ASCII), 0, - NULL, NULL); - - /* If object is flagged AUDIBLE and has a @FORWARDLIST, send - * stuff on */ - if (!(flags & NA_NORELAY) && Audible(target) - && ((a = atr_get_noparent(target, "FORWARDLIST")) != NULL) - && !filter_found(target, msgbuf, 0)) { - char *fwdstr, *orig, *curr; - dbref fwd; - - orig = safe_uncompress(AL_STR(a)); - fwdstr = trim_space_sep(orig, ' '); - - if (!tbuf1) - tbuf1 = mush_malloc(BUFFER_LEN, "string"); - bp = tbuf1; - make_prefixstr(target, msgbuf, tbuf1); - - while ((curr = split_token(&fwdstr, ' ')) != NULL) { - if (is_dbref(curr)) { - fwd = parse_dbref(curr); - if (GoodObject(fwd) && !IsGarbage(fwd) && Can_Forward(target, fwd)) { - if (IsRoom(fwd)) { - notify_anything(speaker, na_loc, &fwd, NULL, - flags | NA_NORELAY, tbuf1); - } else { - notify_anything(speaker, na_one, &fwd, NULL, - flags | NA_NORELAY, tbuf1); - } - } - } - } - free((Malloc_t) orig); - } - } - - for (i = 0; i < MESSAGE_TYPES; i++) { - if (messages[i].message) - mush_free((Malloc_t) messages[i].message, "string"); - if (nospoofs[i].message) - mush_free((Malloc_t) nospoofs[i].message, "string"); - if (paranoids[i].message) - mush_free((Malloc_t) paranoids[i].message, "string"); - } - if (nospoof) - mush_free((Malloc_t) nospoof, "string"); - if (paranoid) - mush_free((Malloc_t) paranoid, "string"); - if (tbuf1) - mush_free((Malloc_t) tbuf1, "string"); - mush_free((Malloc_t) msgbuf, "string"); - na_depth--; - } - - int - safe_tag(char const *a_tag, char *buf, char **bp) - { - int result = 0; - - if (SUPPORT_PUEBLO) { - result += safe_chr(TAG_START, buf, bp); - result += safe_str(a_tag, buf, bp); - result += safe_chr(TAG_END, buf, bp); - } - return result; - } - - int - safe_tag_cancel(char const *a_tag, char *buf, char **bp) - { - int result = 0; - if (SUPPORT_PUEBLO) { - result += safe_chr(TAG_START, buf, bp); - result += safe_chr('/', buf, bp); - result += safe_str(a_tag, buf, bp); - result += safe_chr(TAG_END, buf, bp); - } - return result; - } - - int - safe_tag_wrap(char const *a_tag, char const *params, char const *data, - char *buf, char **bp) - { - int result = 0; - if (SUPPORT_PUEBLO) { - result += safe_chr(TAG_START, buf, bp); - result += safe_str(a_tag, buf, bp); - if (params && *params) { - result += safe_chr(' ', buf, bp); - result += safe_str(params, buf, bp); - } - result += safe_chr(TAG_END, buf, bp); - } - result += safe_str(data, buf, bp); - if (SUPPORT_PUEBLO) { - result += safe_tag_cancel(a_tag, buf, bp); - } - return result; - } - - void - raw_notify(dbref player, const char *msg) - { - notify_anything(GOD, na_one, &player, NULL, NA_NOLISTEN, msg); - } - - /* Rewrite this to compute a flag mask from a list of flags names */ - /* You must have flag1 and flag2 to get the broadcast */ - void - WIN32_CDECL - flag_broadcast(const char *flag1, const char *flag2, const char *fmt, ...) - { - /* takes flag/toggle masks, format string, and format args, and notifies - * all connected players with that flag mask of something. - * If inflags=intoggles=0, broadcast to all. - * If one of them is 0, and the other isn't, then players - * with _at least_ one of the bits in the flag mask are notified, - * rather than players with that _entire_ flag mask. The former - * behavior is more useful. - * If both are nonzero, the player must have at least one bit in each. - */ - - va_list args; - char tbuf1[BUFFER_LEN]; - DESC *d; - int ok; - - va_start(args, fmt); - - #ifdef HAS_VSNPRINTF - (void) vsnprintf(tbuf1, sizeof tbuf1, fmt, args); - #else - (void) vsprintf(tbuf1, fmt, args); - #endif - va_end(args); - tbuf1[BUFFER_LEN - 1] = '\0'; - - DESC_ITER_CONN(d) { - ok = 1; - if (flag1) - ok = ok && flaglist_check_long(GOD, d->player, flag1, 0); - if (flag2) - ok = ok && flaglist_check_long(GOD, d->player, flag2, 0); - if (ok) { - queue_string_eol(d, tbuf1); - process_output(d); - } - } - } - #ifdef WIN32 /* Get the time using Windows function call * Looks weird, but it works. :-P --- 820,825 ---- *************** *** 3010,3253 **** #endif - struct text_block * - make_text_block(const unsigned char *s, int n) - { - struct text_block *p; - p = - (struct text_block *) mush_malloc(sizeof(struct text_block), "text_block"); - if (!p) - panic("Out of memory"); - p->buf = - (unsigned char *) mush_malloc(sizeof(unsigned char) * n, "text_block_buff"); - if (!p->buf) - panic("Out of memory"); - - memcpy(p->buf, s, n); - p->nchars = n; - p->start = p->buf; - p->nxt = 0; - return p; - } - - void - free_text_block(struct text_block *t) - { - if (t) { - if (t->buf) - mush_free((Malloc_t) t->buf, "text_block_buff"); - mush_free((Malloc_t) t, "text_block"); - } - } - - void - add_to_queue(struct text_queue *q, const unsigned char *b, int n) - { - struct text_block *p; - - if (n == 0) - return; - - p = make_text_block(b, n); - p->nxt = 0; - *q->tail = p; - q->tail = &p->nxt; - } - - int - flush_queue(struct text_queue *q, int n) - { - struct text_block *p; - int really_flushed = 0; - n += strlen(flushed_message); - - while (n > 0 && (p = q->head)) { - n -= p->nchars; - really_flushed += p->nchars; - q->head = p->nxt; - #ifdef DEBUG - do_rawlog(LT_ERR, "free_text_block(0x%x) at 1.", p); - #endif /* DEBUG */ - free_text_block(p); - } - p = - make_text_block((unsigned char *) flushed_message, strlen(flushed_message)); - p->nxt = q->head; - q->head = p; - if (!p->nxt) - q->tail = &p->nxt; - really_flushed -= p->nchars; - return really_flushed; - } - - static int - queue_write(DESC *d, const unsigned char *b, int n) - { - char buff[BUFFER_LEN]; - struct notify_strings messages[MESSAGE_TYPES]; - unsigned char *s; - PUEBLOBUFF; - size_t len; - - if ((n == 2) && (b[0] == '\r') && (b[1] == '\n')) { - if ((d->conn_flags & CONN_HTML)) - queue_newwrite(d, (unsigned char *) "
\n", 5); - else - queue_newwrite(d, b, 2); - return n; - } - if (n > BUFFER_LEN) - n = BUFFER_LEN; - - memcpy(buff, b, n); - buff[n] = '\0'; - - zero_strings(messages); - - if (d->conn_flags & CONN_HTML) { - PUSE; - tag_wrap("SAMP", NULL, buff); - PEND; - s = notify_makestring(pbuff, messages, NA_PUEBLO); - len = messages[NA_PUEBLO].len; - } else { - s = notify_makestring(buff, messages, notify_type(d)); - len = messages[notify_type(d)].len; - } - queue_newwrite(d, s, len); - free_strings(messages); - return n; - } - - static int - queue_newwrite(DESC *d, const unsigned char *b, int n) - { - int space; - - #ifdef NT_TCP - - /* queue up an asynchronous write if using Windows NT */ - if (platform == VER_PLATFORM_WIN32_NT) { - - struct text_block **qp, *cur; - DWORD nBytes; - BOOL bResult; - - /* don't write if connection dropped */ - if (d->bConnectionDropped) - return n; - - /* add to queue - this makes sure output arrives in the right order */ - add_to_queue(&d->output, b, n); - d->output_size += n; - - /* if we are already writing, exit and wait for IO completion */ - if (d->bWritePending) - return n; - - /* pull head item out of queue - not necessarily the one we just put in */ - qp = &d->output.head; - - if ((cur = *qp) == NULL) - return n; /* nothing in queue - rather strange, but oh well. */ - - - /* if buffer too long, write what we can and queue up the rest */ - - if (cur->nchars <= sizeof(d->output_buffer)) { - nBytes = cur->nchars; - memcpy(d->output_buffer, cur->start, nBytes); - if (!cur->nxt) - d->output.tail = qp; - *qp = cur->nxt; - free_text_block(cur); - } - /* end of able to write the lot */ - else { - nBytes = sizeof(d->output_buffer); - memcpy(d->output_buffer, cur->start, nBytes); - cur->nchars -= nBytes; - cur->start += nBytes; - } /* end of buffer too long */ - - d->OutboundOverlapped.Offset = 0; - d->OutboundOverlapped.OffsetHigh = 0; - - bResult = WriteFile((HANDLE) d->descriptor, - d->output_buffer, nBytes, NULL, &d->OutboundOverlapped); - - d->bWritePending = FALSE; - - if (!bResult) - if (GetLastError() == ERROR_IO_PENDING) - d->bWritePending = TRUE; - else { - d->bConnectionDropped = TRUE; /* do no more writes */ - /* post a notification that the descriptor should be shutdown */ - if (!PostQueuedCompletionStatus - (CompletionPort, 0, (DWORD) d, &lpo_shutdown)) { - char sMessage[200]; - DWORD nError = GetLastError(); - GetErrorMessage(nError, sMessage, sizeof sMessage); - printf - ("Error %ld (%s) on PostQueuedCompletionStatus in queue_newwrite\n", - nError, sMessage); - shutdownsock(d); - } - } /* end of had write */ - return n; - - } /* end of NT TCP/IP way of doing it */ - #endif - - space = MAX_OUTPUT - d->output_size - n; - if (space < SPILLOVER_THRESHOLD) { - process_output(d); - space = MAX_OUTPUT - d->output_size - n; - if (space < 0) - d->output_size -= flush_queue(&d->output, -space); - } - add_to_queue(&d->output, b, n); - d->output_size += n; - return n; - } - - static int - queue_eol(DESC *d) - { - if (SUPPORT_PUEBLO && (d->conn_flags & CONN_HTML)) - return queue_newwrite(d, (unsigned char *) "
\n", 5); - else - return queue_newwrite(d, (unsigned char *) "\r\n", 2); - } - - static int - queue_string_eol(DESC *d, const char *s) - { - queue_string(d, s); - return queue_eol(d); - } - - static int - queue_string(DESC *d, const char *s) - { - unsigned char *n; - enum na_type poutput; - struct notify_strings messages[MESSAGE_TYPES]; - dbref target; - int ret; - - zero_strings(messages); - - target = d->player; - - poutput = notify_type(d); - - n = notify_makestring(s, messages, poutput); - ret = queue_newwrite(d, n, messages[poutput].len); - free_strings(messages); - return ret; - } int process_output(DESC *d) --- 2025,2030 ---- *************** *** 3291,3331 **** void - freeqs(DESC *d) - { - struct text_block *cur, *next; - cur = d->output.head; - while (cur) { - next = cur->nxt; - #ifdef DEBUG - do_rawlog(LT_ERR, "free_text_block(0x%x) at 3.", cur); - #endif /* DEBUG */ - free_text_block(cur); - cur = next; - } - d->output.head = 0; - d->output.tail = &d->output.head; - - cur = d->input.head; - while (cur) { - next = cur->nxt; - #ifdef DEBUG - do_rawlog(LT_ERR, "free_text_block(0x%x) at 4.", cur); - #endif /* DEBUG */ - free_text_block(cur); - cur = next; - } - d->input.head = 0; - d->input.tail = &d->input.head; - - if (d->raw_input) { - mush_free((Malloc_t) d->raw_input, "descriptor_raw_input"); - } - d->raw_input = 0; - d->raw_input_at = 0; - } - - void welcome_user(DESC *d) { if (SUPPORT_PUEBLO && !(d->conn_flags & CONN_HTML)) --- 2068,2073 ---- *************** *** 4270,4275 **** --- 3012,3020 ---- T("GAME: ERROR! Forking database save failed!")); } else if (WIFEXITED(my_stat) && WEXITSTATUS(my_stat) == 0) { time(&last_dump_time); + if (DUMP_NOFORK_COMPLETE && *DUMP_NOFORK_COMPLETE) + flag_broadcast(0, 0, "%s", DUMP_NOFORK_COMPLETE); + } forked_dump_pid = -1; } *************** *** 4553,4563 **** dbref obj; int j; - #ifdef CHAT_SYSTEM - CHAN *c; - CHANUSER *u; - #endif - set_flag_internal(player, "CONNECTED"); if (isnew) { --- 3298,3303 ---- *************** *** 4590,4605 **** } else flag_broadcast(0, "MONITOR", "%s %s", T("GAME:"), tbuf1); - /* tell players on a channel when someone connects */ #ifdef CHAT_SYSTEM ! for (c = channels; c; c = c->next) { ! u = onchannel(player, c); ! if (u &&!Channel_Quiet(c) && (Channel_Admin(c) || Channel_Wizard(c) ! || (!Chanuser_Hide(u) ! && !Dark(player)))) ! channel_broadcast(c, player, 1, "<%s> %s", ChanName(c), tbuf1); ! } ! #endif /* CHAT_SYSTEM */ loc = Location(player); if (!GoodObject(loc)) { --- 3330,3338 ---- } else flag_broadcast(0, "MONITOR", "%s %s", T("GAME:"), tbuf1); #ifdef CHAT_SYSTEM ! chat_player_announce(player, tbuf1); ! #endif loc = Location(player); if (!GoodObject(loc)) { *************** *** 4675,4685 **** char *p; int j; - #ifdef CHAT_SYSTEM - CHAN *c; - CHANUSER *u; - #endif - p = ctime(&mudtime); p[strlen(p) - 1] = '\0'; if (p[8] == ' ') --- 3408,3413 ---- *************** *** 4747,4765 **** notify_except(Contents(player), player, tbuf1); } - /* tell players on channel that someone's left */ #ifdef CHAT_SYSTEM ! for (c = channels; c; c = c->next) { ! u = onchannel(player, c); ! if (u) { ! if (((!Dark(player) && !Chanuser_Hide(u)) ! || Channel_Admin(c) || Channel_Wizard(c)) && !Channel_Quiet(c)) ! channel_broadcast(c, player, 1, "<%s> %s", ChanName(c), tbuf1); ! /* Ungag them from the channel */ ! do_chan_user_flags(player, ChanName(c), "no", 2, 1); ! } ! } ! #endif /* CHAT_SYSTEM */ /* Monitor broadcasts */ /* Redundant, but better for translators */ --- 3475,3483 ---- notify_except(Contents(player), player, tbuf1); } #ifdef CHAT_SYSTEM ! chat_player_announce(player, tbuf1); ! #endif /* Monitor broadcasts */ /* Redundant, but better for translators */ *************** *** 5162,5224 **** } - #ifdef CHAT_SYSTEM - - - dbref - na_channel(dbref current, void *data) - { - struct na_cpass *nac = data; - CHANUSER *u, *nu; - int cont; - nu = nac->u; - do { - u = nu; - if (!u) - return NOTHING; - current = CUdbref(u); - nu = u->next; - cont = (!GoodObject(current) || - (nac->checkquiet && Chanuser_Quiet(u)) || - Chanuser_Gag(u) || (IsPlayer(current) - && !Connected(current))); - } - while (cont); - nac->u = nu; - return current; - } - - void - WIN32_CDECL - channel_broadcast(CHAN *channel, dbref player, int flags, const char *fmt, ...) - /* flags: 0x1 = checkquiet, 0x2 = nospoof */ - { - va_list args; - #ifdef HAS_VSNPRINTF - char tbuf1[BUFFER_LEN]; - #else - char tbuf1[BUFFER_LEN * 2]; /* Safety margin as per tprintf */ - #endif - struct na_cpass nac; - /* Make sure we can write to the channel before doing so */ - if (Channel_Disabled(channel)) - return; - va_start(args, fmt); - #ifdef HAS_VSNPRINTF - (void) vsnprintf(tbuf1, sizeof tbuf1, fmt, args); - #else - (void) vsprintf(tbuf1, fmt, args); - #endif - va_end(args); - tbuf1[BUFFER_LEN - 1] = '\0'; - nac.u = ChanUsers(channel); - nac.checkquiet = (flags & CU_QUIET) ? 1 : 0; - notify_anything(player, na_channel, &nac, - (flags & CU_HIDE) ? ns_esnotify : NULL, 0, tbuf1); - } - - #endif /* CHAT_SYSTEM */ - int hidden(dbref player) { --- 3880,3885 ---- *** 1_7_7.231/src/Makefile Sat, 01 Feb 2003 17:23:16 -0600 dunemush (pennmush/c/44_Makefile 1.21.1.13.1.1 700) --- 1_7_7.308(w)/src/Makefile Tue, 18 Mar 2003 16:14:21 -0600 dunemush (pennmush/c/44_Makefile 1.21.1.13.1.3 700) *************** *** 31,37 **** function.c funcrypt.c fundb.c funlist.c \ funlocal.c funmath.c funmisc.c funstr.c funtime.c funufun.c game.c \ help.c htab.c ident.c local.c lock.c log.c look.c mycrypt.c mymalloc.c \ ! malias.c match.c memcheck.c move.c mysocket.c parse.c pcre.c \ player.c plyrlist.c predicat.c privtab.c ptab.c rob.c services.c \ set.c shs.c sig.c speech.c strdup.c strtree.c strutil.c \ tables.c timer.c unparse.c utils.c version.c warnings.c wild.c wiz.c --- 31,37 ---- function.c funcrypt.c fundb.c funlist.c \ funlocal.c funmath.c funmisc.c funstr.c funtime.c funufun.c game.c \ help.c htab.c ident.c local.c lock.c log.c look.c mycrypt.c mymalloc.c \ ! malias.c match.c memcheck.c move.c mysocket.c notify.c parse.c pcre.c \ player.c plyrlist.c predicat.c privtab.c ptab.c rob.c services.c \ set.c shs.c sig.c speech.c strdup.c strtree.c strutil.c \ tables.c timer.c unparse.c utils.c version.c warnings.c wild.c wiz.c *************** *** 95,100 **** --- 95,101 ---- memcheck.o \ move.o \ mysocket.o \ + notify.o \ parse.o \ pcre.o \ player.o \ *************** *** 359,365 **** bsd.o: ../hdrs/log.h bsd.o: ../hdrs/memcheck.h bsd.o: ../hdrs/mymalloc.h - bsd.o: ../hdrs/extchat.h bsd.o: ../hdrs/extmail.h bsd.o: ../hdrs/attrib.h bsd.o: ../hdrs/game.h --- 360,365 ---- *************** *** 390,396 **** cmds.o: ../hdrs/attrib.h cmds.o: ../hdrs/extmail.h cmds.o: ../hdrs/malias.h - cmds.o: ../hdrs/extchat.h cmds.o: ../hdrs/getpgsiz.h cmds.o: ../hdrs/parse.h cmds.o: ../hdrs/access.h --- 390,395 ---- *************** *** 416,422 **** command.o: ../hdrs/match.h command.o: ../hdrs/attrib.h command.o: ../hdrs/extmail.h - command.o: ../hdrs/extchat.h command.o: ../hdrs/getpgsiz.h command.o: ../hdrs/parse.h command.o: ../hdrs/access.h --- 415,420 ---- *************** *** 565,570 **** --- 563,571 ---- extchat.o: ../hdrs/flags.h extchat.o: ../hdrs/dbdefs.h extchat.o: ../hdrs/htab.h + extchat.o: ../hdrs/function.h + extchat.o: ../hdrs/command.h + extchat.o: ../hdrs/switches.h extmail.o: ../config.h extmail.o: ../hdrs/copyrite.h extmail.o: ../hdrs/conf.h *************** *** 683,689 **** fundb.o: ../hdrs/log.h fundb.o: ../hdrs/attrib.h fundb.o: ../hdrs/function.h - fundb.o: ../hdrs/extchat.h funlist.o: ../hdrs/copyrite.h funlist.o: ../config.h funlist.o: ../hdrs/conf.h --- 684,689 ---- *************** *** 732,740 **** funmisc.o: ../hdrs/externs.h funmisc.o: ../confmagic.h funmisc.o: ../hdrs/version.h - funmisc.o: ../hdrs/extchat.h funmisc.o: ../hdrs/htab.h funmisc.o: ../hdrs/flags.h funmisc.o: ../hdrs/dbdefs.h funmisc.o: ../hdrs/parse.h funmisc.o: ../hdrs/function.h --- 732,741 ---- funmisc.o: ../hdrs/externs.h funmisc.o: ../confmagic.h funmisc.o: ../hdrs/version.h funmisc.o: ../hdrs/htab.h funmisc.o: ../hdrs/flags.h + funmisc.o: ../hdrs/match.h + funmisc.o: ../hdrs/mushdb.h funmisc.o: ../hdrs/dbdefs.h funmisc.o: ../hdrs/parse.h funmisc.o: ../hdrs/function.h *** 1_7_7.231/hdrs/version.h Sat, 22 Feb 2003 15:29:30 -0600 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.15 660) --- 1_7_7.308(w)/hdrs/version.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/c/47_version.h 1.32.1.2.1.7.1.9.1.1.1.17.1.16 660) *************** *** 1,3 **** ! #define VERSION "PennMUSH version 1.7.7 patchlevel 11 [02/22/2003]" ! #define SHORTVN "PennMUSH 1.7.7p11" ! #define NUMVERSION 001007007011 --- 1,3 ---- ! #define VERSION "PennMUSH version 1.7.7 patchlevel 12 [03/21/2003]" ! #define SHORTVN "PennMUSH 1.7.7p12" ! #define NUMVERSION 001007007012 *** 1_7_7.231/hdrs/lock.h Thu, 30 Jan 2003 13:16:01 -0600 dunemush (pennmush/d/6_lock.h 1.16 660) --- 1_7_7.308(w)/hdrs/lock.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/6_lock.h 1.17 660) *************** *** 53,60 **** /* lock.c */ struct boolexp *getlock(dbref thing, lock_type type); struct boolexp *getlock_noparent(dbref thing, lock_type type); - lock_list *getlockstruct(dbref thing, lock_type type); - lock_list *getlockstruct_noparent(dbref thing, lock_type type); lock_type match_lock(lock_type type); const lock_list *get_lockproto(lock_type type); int add_lock(dbref player, dbref thing, lock_type type, struct boolexp *key, --- 53,58 ---- *** 1_7_7.231/hdrs/flags.h Sun, 16 Feb 2003 21:57:00 -0600 dunemush (pennmush/d/14_flags.h 1.1.1.1.1.1.1.1.1.2.1.3.2.1.1.4.1.1.1.1.2.1.1.22 660) --- 1_7_7.308(w)/hdrs/flags.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/14_flags.h 1.1.1.1.1.1.1.1.1.2.1.3.2.1.1.4.1.1.1.1.2.1.1.24 660) *************** *** 54,60 **** /* From flags.c */ extern FLAG *flag_hash_lookup(const char *name, int type); - extern int has_flag(dbref thing, FLAG *f); extern int has_flag_by_name(dbref thing, const char *flag, int type); extern const char *unparse_flags(dbref thing, dbref player); extern const char *flag_description(dbref player, dbref thing); --- 54,59 ---- *************** *** 78,83 **** --- 77,83 ---- extern void clear_flag_bitmask(object_flag_type bitmask, int bit); extern int has_bit(object_flag_type bitmask, int bitpos); extern int has_all_bits(object_flag_type source, object_flag_type bitmask); + extern int null_flagmask(object_flag_type source); extern int has_any_bits(object_flag_type source, object_flag_type bitmask); extern object_flag_type string_to_bits(const char *str); extern const char *bits_to_string(object_flag_type bitmask, dbref privs, *** 1_7_7.231/hdrs/extchat.h Thu, 30 Jan 2003 13:16:01 -0600 dunemush (pennmush/d/17_extchat.h 1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.3.1.1.1.1.2.2.1.1 660) --- 1_7_7.308(w)/hdrs/extchat.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/17_extchat.h 1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.3.1.1.1.1.2.2.1.6 660) *************** *** 33,38 **** --- 33,40 ---- * @channel/delete channel * @channel/quiet channel = yes/no * @channel/wipe channel + * @channel/buffer channel = + * @channel/recall channel [= ] * *------------------------------------------------------------------*/ *************** *** 91,96 **** --- 93,102 ---- struct boolexp *seelock; /**< Who can see this in a list */ struct boolexp *hidelock; /**< Who may hide from view */ struct channel *next; /**< Next channel in linked list */ + char *buffer; /**< Pointer to channel recall buffer start */ + char *buffer_end; /**< Pointer to channel recall buffer end */ + int buffersize; /**< Size of channel recall buffer */ + int num_buffered; /**< Number of lines in the buffer */ }; /** A list of channels on an object. *************** *** 139,144 **** --- 145,154 ---- #define ChanModLock(c) ((c)->modifylock) #define ChanSeeLock(c) ((c)->seelock) #define ChanHideLock(c) ((c)->hidelock) + #define ChanBuffer(c) ((c)->buffer) + #define ChanBufferSize(c) ((c)->buffersize) + #define ChanBufferEnd(c) ((c)->buffer_end) + #define ChanNumBuffered(c) ((c)->num_buffered) #define Channel_Quiet(c) (ChanType(c) & CHANNEL_QUIET) #define Channel_Open(c) (ChanType(c) & CHANNEL_OPEN) #define Channel_Object(c) (ChanType(c) & CHANNEL_OBJECT) *************** *** 203,210 **** extern void do_chan_what(dbref player, const char *partname); extern void do_chan_desc(dbref player, const char *name, const char *title); extern void do_chan_title(dbref player, const char *name, const char *title); ! ! /* From chat.c */ extern void init_chat(void); extern void do_channel (dbref player, const char *name, const char *target, const char *com); --- 213,220 ---- extern void do_chan_what(dbref player, const char *partname); extern void do_chan_desc(dbref player, const char *name, const char *title); extern void do_chan_title(dbref player, const char *name, const char *title); ! extern void do_chan_recall(dbref player, const char *name, const char *lines); ! extern void do_chan_buffer(dbref player, const char *name, const char *lines); extern void init_chat(void); extern void do_channel (dbref player, const char *name, const char *target, const char *com); *************** *** 218,223 **** --- 228,234 ---- (dbref player, const char *name, const char *msg, int source); extern void do_chan_decompile(dbref player, const char *name, int brief); extern void do_chan_chown(dbref player, const char *name, const char *newowner); + extern const char *channel_description(dbref player); #endif /* CHAT_SYSTEM */ *** 1_7_7.231/hdrs/dbdefs.h Tue, 04 Feb 2003 22:13:06 -0600 dunemush (pennmush/d/18_dbdefs.h 1.1.1.1.1.1.1.1.1.1.1.2.2.2.1.1.1.1.1.1.2.1.1.9 660) --- 1_7_7.308(w)/hdrs/dbdefs.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/18_dbdefs.h 1.1.1.1.1.1.1.1.1.1.1.2.2.2.1.1.1.1.1.1.2.1.1.10 660) *************** *** 72,78 **** #define Powers(x) (db[(x)].powers) /* Generic type check */ ! #define Typeof(x) (db[(x)].type & ~TYPE_MARKED) /* Check for a specific one */ #define IsPlayer(x) (Typeof(x) & TYPE_PLAYER) --- 72,79 ---- #define Powers(x) (db[(x)].powers) /* Generic type check */ ! #define Type(x) (db[(x)].type) ! #define Typeof(x) (Type(x) & ~TYPE_MARKED) /* Check for a specific one */ #define IsPlayer(x) (Typeof(x) & TYPE_PLAYER) *** 1_7_7.231/hdrs/switches.h Wed, 08 Jan 2003 16:41:25 -0600 dunemush (pennmush/d/21_switches.h 1.2.1.6.2.7 660) --- 1_7_7.308(w)/hdrs/switches.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/21_switches.h 1.2.1.6.2.7.1.2 660) *************** *** 10,87 **** #define SWITCH_BEFORE 9 #define SWITCH_BLIND 10 #define SWITCH_BRIEF 11 ! #define SWITCH_CHECK 12 ! #define SWITCH_CHOWN 13 ! #define SWITCH_CLEAR 14 ! #define SWITCH_CMD 15 ! #define SWITCH_COMMANDS 16 ! #define SWITCH_CONN 17 ! #define SWITCH_CONNECT 18 ! #define SWITCH_CONNECTED 19 ! #define SWITCH_CONTENTS 20 ! #define SWITCH_COSTS 21 ! #define SWITCH_COUNT 22 ! #define SWITCH_CREATE 23 ! #define SWITCH_DATABASE 24 ! #define SWITCH_DB 25 ! #define SWITCH_DEBUG 26 ! #define SWITCH_DECOMPILE 27 ! #define SWITCH_DEFAULTS 28 ! #define SWITCH_DELETE 29 ! #define SWITCH_DELIMIT 30 ! #define SWITCH_DESCRIBE 31 ! #define SWITCH_DESTROY 32 ! #define SWITCH_DISABLE 33 ! #define SWITCH_DOWN 34 ! #define SWITCH_DSTATS 35 ! #define SWITCH_EMIT 36 ! #define SWITCH_ENABLE 37 ! #define SWITCH_ERR 38 ! #define SWITCH_EXITS 39 ! #define SWITCH_FILE 40 ! #define SWITCH_FIRST 41 ! #define SWITCH_FLAGS 42 ! #define SWITCH_FOLDERS 43 ! #define SWITCH_FORWARD 44 ! #define SWITCH_FSTATS 45 ! #define SWITCH_FULL 46 ! #define SWITCH_FUNCTIONS 47 ! #define SWITCH_FWD 48 ! #define SWITCH_GAG 49 ! #define SWITCH_GLOBALS 50 ! #define SWITCH_HEADER 51 ! #define SWITCH_HERE 52 ! #define SWITCH_HIDE 53 ! #define SWITCH_ILIST 54 ! #define SWITCH_INVENTORY 55 ! #define SWITCH_IPRINT 56 ! #define SWITCH_JOIN 57 ! #define SWITCH_LIST 58 ! #define SWITCH_LOWERCASE 59 ! #define SWITCH_ME 60 ! #define SWITCH_MEMBERS 61 ! #define SWITCH_MOD 62 ! #define SWITCH_MORTAL 63 ! #define SWITCH_MOTD 64 ! #define SWITCH_MUTE 65 ! #define SWITCH_NAME 66 ! #define SWITCH_NO 67 ! #define SWITCH_NOEVAL 68 ! #define SWITCH_NOFLAGCOPY 69 ! #define SWITCH_NOISY 70 ! #define SWITCH_NOSIG 71 ! #define SWITCH_NOSPACE 72 ! #define SWITCH_NOTIFY 73 ! #define SWITCH_NUKE 74 ! #define SWITCH_OFF 75 ! #define SWITCH_ON 76 ! #define SWITCH_OUTSIDE 77 ! #define SWITCH_OVERRIDE 78 ! #define SWITCH_PANIC 79 ! #define SWITCH_PARANOID 80 ! #define SWITCH_PLAYERS 81 ! #define SWITCH_PORT 82 ! #define SWITCH_POSE 83 #define SWITCH_PRESERVE 84 #define SWITCH_PRINT 85 #define SWITCH_PRIVS 86 --- 10,87 ---- #define SWITCH_BEFORE 9 #define SWITCH_BLIND 10 #define SWITCH_BRIEF 11 ! #define SWITCH_BUFFER 12 ! #define SWITCH_CHECK 13 ! #define SWITCH_CHOWN 14 ! #define SWITCH_CLEAR 15 ! #define SWITCH_CMD 16 ! #define SWITCH_COMMANDS 17 ! #define SWITCH_CONN 18 ! #define SWITCH_CONNECT 19 ! #define SWITCH_CONNECTED 20 ! #define SWITCH_CONTENTS 21 ! #define SWITCH_COSTS 22 ! #define SWITCH_COUNT 23 ! #define SWITCH_CREATE 24 ! #define SWITCH_DATABASE 25 ! #define SWITCH_DB 26 ! #define SWITCH_DEBUG 27 ! #define SWITCH_DECOMPILE 28 ! #define SWITCH_DEFAULTS 29 ! #define SWITCH_DELETE 30 ! #define SWITCH_DELIMIT 31 ! #define SWITCH_DESCRIBE 32 ! #define SWITCH_DESTROY 33 ! #define SWITCH_DISABLE 34 ! #define SWITCH_DOWN 35 ! #define SWITCH_DSTATS 36 ! #define SWITCH_EMIT 37 ! #define SWITCH_ENABLE 38 ! #define SWITCH_ERR 39 ! #define SWITCH_EXITS 40 ! #define SWITCH_FILE 41 ! #define SWITCH_FIRST 42 ! #define SWITCH_FLAGS 43 ! #define SWITCH_FOLDERS 44 ! #define SWITCH_FORWARD 45 ! #define SWITCH_FSTATS 46 ! #define SWITCH_FULL 47 ! #define SWITCH_FUNCTIONS 48 ! #define SWITCH_FWD 49 ! #define SWITCH_GAG 50 ! #define SWITCH_GLOBALS 51 ! #define SWITCH_HEADER 52 ! #define SWITCH_HERE 53 ! #define SWITCH_HIDE 54 ! #define SWITCH_ILIST 55 ! #define SWITCH_INVENTORY 56 ! #define SWITCH_IPRINT 57 ! #define SWITCH_JOIN 58 ! #define SWITCH_LIST 59 ! #define SWITCH_LOWERCASE 60 ! #define SWITCH_ME 61 ! #define SWITCH_MEMBERS 62 ! #define SWITCH_MOD 63 ! #define SWITCH_MORTAL 64 ! #define SWITCH_MOTD 65 ! #define SWITCH_MUTE 66 ! #define SWITCH_NAME 67 ! #define SWITCH_NO 68 ! #define SWITCH_NOEVAL 69 ! #define SWITCH_NOFLAGCOPY 70 ! #define SWITCH_NOISY 71 ! #define SWITCH_NOSIG 72 ! #define SWITCH_NOSPACE 73 ! #define SWITCH_NOTIFY 74 ! #define SWITCH_NUKE 75 ! #define SWITCH_OFF 76 ! #define SWITCH_ON 77 ! #define SWITCH_OUTSIDE 78 ! #define SWITCH_OVERRIDE 79 ! #define SWITCH_PANIC 80 ! #define SWITCH_PARANOID 81 ! #define SWITCH_PLAYERS 82 ! #define SWITCH_PORT 83 #define SWITCH_PRESERVE 84 #define SWITCH_PRINT 85 #define SWITCH_PRIVS 86 *************** *** 90,104 **** #define SWITCH_QUIET 89 #define SWITCH_READ 90 #define SWITCH_REBOOT 91 ! #define SWITCH_REGISTER 92 ! #define SWITCH_REMOVE 93 ! #define SWITCH_RENAME 94 ! #define SWITCH_RESTORE 95 ! #define SWITCH_RESTRICT 96 ! #define SWITCH_RETROACTIVE 97 ! #define SWITCH_ROOM 98 ! #define SWITCH_ROOMS 99 ! #define SWITCH_ROYALTY 100 #define SWITCH_SEE 101 #define SWITCH_SEEFLAG 102 #define SWITCH_SELF 103 --- 90,104 ---- #define SWITCH_QUIET 89 #define SWITCH_READ 90 #define SWITCH_REBOOT 91 ! #define SWITCH_RECALL 92 ! #define SWITCH_REGISTER 93 ! #define SWITCH_REMOVE 94 ! #define SWITCH_RENAME 95 ! #define SWITCH_RESTORE 96 ! #define SWITCH_RESTRICT 97 ! #define SWITCH_RETROACTIVE 98 ! #define SWITCH_ROOM 99 ! #define SWITCH_ROOMS 100 #define SWITCH_SEE 101 #define SWITCH_SEEFLAG 102 #define SWITCH_SELF 103 *** 1_7_7.231/hdrs/htab.h Thu, 30 Jan 2003 13:16:01 -0600 dunemush (pennmush/d/23_htab.h 1.6 660) --- 1_7_7.308(w)/hdrs/htab.h Tue, 25 Mar 2003 16:22:42 -0600 dunemush (pennmush/d/23_htab.h 1.7 660) *************** *** 49,55 **** extern void *hash_value(HASHENT *entry); extern char *hash_key(HASHENT *entry); extern void hash_resize(HASHTAB *htab, int size); - extern HASHENT *hash_new(HASHTAB *htab, const char *key); extern int hash_add (HASHTAB *htab, const char *key, void *hashdata, int extra_size); extern void hash_delete(HASHTAB *htab, HASHENT *entry); --- 49,54 ---- *** 1_7_7.231/hdrs/command.h Thu, 30 Jan 2003 13:16:01 -0600 dunemush (pennmush/d/24_command.h 1.22 660) --- 1_7_7.308(w)/hdrs/command.h Tue, 25 Mar 2003 16:22:41 -0600 dunemush (pennmush/d/24_command.h 1.23 660) *************** *** 151,157 **** const char *name; /**< Command name */ const char *switches; /**< Space-separated list of switch names */ command_func func; /**< Function to call when command is run */ ! unsigned int type; /** Types of objects that can use the command */ const char *flagstr; /**< Space-separated list of flags that can use */ unsigned int powers; /**< Powers to which the command is restricted */ }; --- 151,157 ---- const char *name; /**< Command name */ const char *switches; /**< Space-separated list of switch names */ command_func func; /**< Function to call when command is run */ ! unsigned int type; /**< Types of objects that can use the command */ const char *flagstr; /**< Space-separated list of flags that can use */ unsigned int powers; /**< Powers to which the command is restricted */ }; *** 1_7_7.231/Makefile.SH Sat, 22 Feb 2003 12:25:53 -0600 dunemush (pennmush/d/30_Makefile.S 1.14.1.1.1.9 700) --- 1_7_7.308(w)/Makefile.SH Sun, 23 Feb 2003 11:01:57 -0600 dunemush (pennmush/d/30_Makefile.S 1.14.1.1.1.7.1.2 700) *************** *** 121,127 **** versions: CHANGES* -rm -rf CHANGES*~ CHANGES*bak ! utils/mkvershlp.pl game/txt/hlp/pennvers.hlp CHANGES* safety: $(CP) src/*.c /var/pennmush-bak/src --- 121,127 ---- versions: CHANGES* -rm -rf CHANGES*~ CHANGES*bak ! utils/mkvershlp.pl game/txt/hlp CHANGES* safety: $(CP) src/*.c /var/pennmush-bak/src *** 1_7_7.231/MANIFEST Wed, 08 Jan 2003 12:55:54 -0600 dunemush (pennmush/d/34_MANIFEST 1.21.1.2.1.7.1.4 600) --- 1_7_7.308(w)/MANIFEST Tue, 18 Mar 2003 16:13:37 -0600 dunemush (pennmush/d/34_MANIFEST 1.21.1.2.1.7.1.3.1.3 600) *************** *** 1,5 **** Patchlevel ! CHANGES MANIFEST options.h.dist Configure --- 1,6 ---- Patchlevel ! CHANGES.177 ! CHANGES.176 MANIFEST options.h.dist Configure *************** *** 92,97 **** --- 93,99 ---- src/mycrypt.c src/mymalloc.c src/mysocket.c + src/notify.c src/parse.c src/pcre.c src/player.c *************** *** 192,198 **** game/txt/hlp/pennmail.hlp game/txt/hlp/pennpueb.hlp game/txt/hlp/penntop.hlp ! game/txt/hlp/pennvers.hlp game/txt/nws/index.nws game/txt/nws/pennmush.nws BUGS --- 194,204 ---- game/txt/hlp/pennmail.hlp game/txt/hlp/pennpueb.hlp game/txt/hlp/penntop.hlp ! game/txt/hlp/pennvOLD.hlp ! game/txt/hlp/pennv174.hlp ! game/txt/hlp/pennv175.hlp ! game/txt/hlp/pennv176.hlp ! game/txt/hlp/pennv177.hlp game/txt/nws/index.nws game/txt/nws/pennmush.nws BUGS *** 1_7_7.231/game/txt/hlp/penncode.hlp Wed, 19 Feb 2003 13:21:06 -0600 dunemush (pennmush/d/40_penncode.h 1.5.1.4 600) --- 1_7_7.308(w)/game/txt/hlp/penncode.hlp Wed, 12 Mar 2003 12:14:58 -0600 dunemush (pennmush/d/40_penncode.h 1.5.1.5 600) *************** *** 1,4 **** ! & Code The latest version of this MUSH code is available via anonymous FTP, at ftp.pennmush.org, directory /pub/PennMUSH/Source. It will be called something like pennmush-1.7.6p0.tar.Z, or similar, --- 1,5 ---- ! & code ! & contact The latest version of this MUSH code is available via anonymous FTP, at ftp.pennmush.org, directory /pub/PennMUSH/Source. It will be called something like pennmush-1.7.6p0.tar.Z, or similar, *** 1_7_7.231/utils/mkvershlp.pl Thu, 26 Apr 2001 10:27:46 -0500 dunemush (pennmush/d/41_mkvershlp. 1.4 700) --- 1_7_7.308(w)/utils/mkvershlp.pl Sun, 23 Feb 2003 11:02:00 -0600 dunemush (pennmush/d/41_mkvershlp. 1.5 700) *************** *** 1,26 **** #!/usr/local/bin/perl # ! # Generate game/txt/hlp/pennvers.hlp from the CHANGES file(s). # Should be run by Makefile from top-level directory # ! # Usage: mkvershlp game/txt/hlp/pennvers.hlp CHANGES CHANGES.OLD ... ! # Most recent file should be first, and files should have changes ! # in reverse chronological order. # use strict; use Sort::Versions; use Text::Wrap; ! my $target = shift; my @sources = @ARGV; my $verspat = '^Version (\S+) patchlevel (\S+)'; my %patchlevels; ! open(OUT,">$target") or die "Unable to open $target\n"; ! print OUT "& changes\n"; my $really_started = 0; foreach my $file (@sources) { warn "Can't open $file!\n", next unless open(IN,"<$file"); my $started = 0; while () { if (/$verspat/o) { --- 1,30 ---- #!/usr/local/bin/perl # ! # Generate game/txt/hlp/ files from the CHANGES file(s). # Should be run by Makefile from top-level directory # ! # Usage: mkvershlp game/txt/hlp CHANGES.176 CHANGES.OLD ... ! # ! # Each file CHANGES. generates file pennv.hlp in the ! # specified directory. # use strict; use Sort::Versions; use Text::Wrap; ! my $targetdir = shift; my @sources = @ARGV; my $verspat = '^Version (\S+) patchlevel (\S+)'; my %patchlevels; ! @sources = sort byrevision @sources; ! my $really_started = 0; foreach my $file (@sources) { warn "Can't open $file!\n", next unless open(IN,"<$file"); + my $target = $file; + $target =~ s/.*\.(.*)/pennv$1.hlp/; + open(OUT,">$targetdir/$target") or die "Unable to open $targetdir/$target\n"; my $started = 0; while () { if (/$verspat/o) { *************** *** 30,35 **** --- 34,40 ---- # This is the first one unless ($really_started) { print OUT <<'EOP'; + & changes This is a list of changes in this patchlevel which are probably of interest to players. More information about new commands and functions can probably be gotten via 'help '. 'help credits' *************** *** 78,80 **** --- 83,92 ---- close OUT; + # A sort subroutine to order CHANGES. in reverse chronological + # order + sub byrevision { + return $b cmp $a if ($a =~ /\d/ and $b =~ /\d/); + return $a cmp $b; + } + *** 1_7_7.231/win32/funs.h Wed, 22 Jan 2003 21:45:40 -0600 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.8.1.3.1.7.1.1.1.1.1.1.1.1.1.1.1.2.2.2 660) --- 1_7_7.308(w)/win32/funs.h Tue, 25 Mar 2003 16:17:47 -0600 dunemush (pennmush/f/12_funs.h 1.11.1.9.2.8.2.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.8.1.3.1.7.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1 660) *************** *** 1,6 **** --- 1,7 ---- /* AUTOGENERATED FILE. DO NOT EDIT */ FUNCTION_PROTO(fun_abs); FUNCTION_PROTO(fun_accent); + FUNCTION_PROTO(fun_accname); FUNCTION_PROTO(fun_acos); FUNCTION_PROTO(fun_add); FUNCTION_PROTO(fun_after); *************** *** 239,244 **** --- 240,246 ---- FUNCTION_PROTO(fun_room); FUNCTION_PROTO(fun_round); FUNCTION_PROTO(fun_s); + FUNCTION_PROTO(fun_scan); FUNCTION_PROTO(fun_scramble); FUNCTION_PROTO(fun_secs); FUNCTION_PROTO(fun_secure); *** 1_7_7.231/src/notify.c Tue, 25 Mar 2003 16:22:47 -0600 dunemush () --- 1_7_7.308(w)/src/notify.c Tue, 25 Mar 2003 16:22:37 -0600 dunemush (pennmush/g/35_notify.c 1.2 660) *************** *** 0 **** --- 1,1577 ---- + /* bsd.c */ + + #include "copyrite.h" + #include "config.h" + + #include + #include + #ifdef I_SYS_TYPES + #include + #endif + #ifdef WIN32 + #define FD_SETSIZE 256 + #include + #include + #include + #define EINTR WSAEINTR + #define EWOULDBLOCK WSAEWOULDBLOCK + #define MAXHOSTNAMELEN 32 + #define LC_MESSAGES 6 + void shutdown_checkpoint(void); + #else /* !WIN32 */ + #ifdef I_SYS_FILE + #include + #endif + #ifdef I_SYS_TIME + #include + #endif + #include + #include + #ifdef I_SYS_SOCKET + #include + #endif + #ifdef I_NETINET_IN + #include + #endif + #ifdef I_NETDB + #include + #endif + #ifdef I_SYS_PARAM + #include + #endif + #ifdef I_SYS_STAT + #include + #endif + #endif /* !WIN32 */ + #include + #ifdef I_SYS_WAIT + #include + #endif + #include + #include + #include + #include + #include + #ifdef I_SYS_SELECT + #include + #endif + #ifdef I_UNISTD + #include + #endif + #ifdef HAS_GETRLIMIT + #include + #endif + #include + #ifdef I_FLOATINGPOINT + #include + #endif + #include + #ifdef __APPLE__ + #define LC_MESSAGES 6 + #define AUTORESTART + #endif + #include + + #include "conf.h" + + #if defined(WIN32) && defined(INFO_SLAVE) + #undef INFO_SLAVE + #endif + + #ifdef INFO_SLAVE + #include + #endif + + #include "mushdb.h" + #include "externs.h" + #include "dbdefs.h" + #include "flags.h" + #include "lock.h" + #include "help.h" + #include "match.h" + #include "ansi.h" + #include "pueblo.h" + #include "parse.h" + #include "access.h" + #include "version.h" + #include "patches.h" + #include "mysocket.h" + #include "ident.h" + #include "strtree.h" + #include "log.h" + + #ifdef MEM_CHECK + #include "memcheck.h" + #endif + + #include "mymalloc.h" + + #ifdef CHAT_SYSTEM + #include "extchat.h" + extern CHAN *channels; + struct na_cpass { + CHANUSER *u; + int checkquiet; + }; + + #endif + #include "extmail.h" + #include "attrib.h" + #include "game.h" + #include "confmagic.h" + #ifdef HAS_WAITPID + #define WAIT_TYPE int + #else + #ifdef UNION_WAIT + #define WAIT_TYPE union wait + #else + #define WAIT_TYPE int + #endif + #endif + + /* BSD 4.2 and maybe some others need these defined */ + #ifndef FD_ZERO + #define fd_set int + #define FD_ZERO(p) (*p = 0) + #define FD_SET(n,p) (*p |= (1<<(n))) + #define FD_CLR(n,p) (*p &= ~(1<<(n))) + #define FD_ISSET(n,p) (*p & (1<<(n))) + #endif /* defines for BSD 4.2 */ + + #ifdef HAS_GETRUSAGE + extern void rusage_stats(void); + #endif + extern int que_next(void); /* from cque.c */ + extern int on_second; + extern void dispatch(void); /* from timer.c */ + extern dbref email_register_player(const char *name, const char *email, const char *host, const char *ip); /* from player.c */ + + extern time_t start_time, first_start_time; + extern int reboot_count; + #ifndef WIN32 + #ifndef errno + extern int errno; + #endif + #endif + extern int reserved; + extern int paranoid_dump; /* from game.c */ + + static int under_limit = 1; + + char cf_motd_msg[BUFFER_LEN], cf_wizmotd_msg[BUFFER_LEN], + cf_downmotd_msg[BUFFER_LEN], cf_fullmotd_msg[BUFFER_LEN]; + char confname[BUFFER_LEN]; + char errlog[BUFFER_LEN]; + + #define CONN_DEFAULT 0 + /* Using Pueblo, Smial, Mushclient, Simplemu, or some other + * pueblo-style HTML aware client */ + #define CONN_HTML 0x1 + /* Using a client that understands telnet options */ + #define CONN_TELNET 0x2 + /* Send a telnet option to test client */ + #define CONN_TELNET_QUERY 0x4 + + #define TELNET_ABLE(d) ((d)->conn_flags & (CONN_TELNET | CONN_TELNET_QUERY)) + + + /* When the mush gets a new connection, it tries sending a telnet + * option negotiation code for setting client-side line-editing mode + * to it. If it gets a reply, a flag in the descriptor struct is + * turned on indicated telnet-awareness. + * + * If the reply indicates that the client supports linemode, further + * instructions as to what linemode options are to be used is sent. + * Those options: Client-side line editing, and expanding literal + * client-side-entered tabs into spaces. + * + * Option negotation requests sent by the client are processed, + * with the only one we confirm rather than refuse outright being + * suppress-go-ahead, since a number of telnet clients try it. + * + * The character 255 is the telnet option escape character, so when it + * is sent to a telnet-aware client by itself (Since it's also often y-umlaut) + * it must be doubled to escape it for the client. This is done automatically, + * and is the original purpose of adding telnet option support. + */ + + /* Telnet codes */ + #define IAC 255 /* interpret as command: */ + #define DONT 254 /* you are not to use option */ + #define DO 253 /* please, you use option */ + #define WONT 252 /* I won't use option */ + #define WILL 251 /* I will use option */ + #define SB 250 /* interpret as subnegotiation */ + #define SE 240 /* end sub negotiation */ + #define TN_SGA 3 /* Suppress go-ahead */ + #define TN_LINEMODE 34 + #define TN_NAWS 31 /* Negotiate About Window Size */ + void test_telnet(DESC *d); + void setup_telnet(DESC *d); + int handle_telnet(DESC *d, unsigned char **q, unsigned char *qend); + + #define DESC_ITER_CONN(d) \ + for(d = descriptor_list;(d);d=(d)->next) \ + if((d)->connected) + + #define Hidden(d) ((d->hide == 1) && Can_Hide(d->player)) + + #ifdef NT_TCP + /* for Windows NT IO-completion-port method of TCP/IP - NJG */ + + /* Windows NT TCP/IP routines written by Nick Gammon */ + + #include + HANDLE CompletionPort; /* IOs are queued up on this port */ + SOCKET MUDListenSocket; /* for our listening thread */ + DWORD dwMUDListenThread; /* thread handle for listening thread */ + SOCKADDR_IN saServer; /* for listening thread */ + void __cdecl MUDListenThread(void *pVoid); /* the listening thread */ + DWORD platform; /* which version of Windows are we using? */ + OVERLAPPED lpo_aborted; /* special to indicate a player has finished TCP IOs */ + OVERLAPPED lpo_shutdown; /* special to indicate a player should do a shutdown */ + void ProcessWindowsTCP(void); /* handle NT-style IOs */ + CRITICAL_SECTION cs; /* for thread synchronisation */ + #endif + + + static const char *flushed_message = "\r\n\x1B[0m\r\n"; + #define REBOOTFILE "reboot.db" + + #if 0 + /* For translation */ + static void dummy_msgs(void); + static void + dummy_msgs() + { + char *temp; + temp = T("Either that player does not exist, or has a different password."); + temp = + T + ("Either there is already a player with that name, or that name is illegal."); + temp = T("Unable to register that player with that email address."); + temp = T("Registration successful! You will receive your password by email."); + temp = T("Going down - Bye"); + } + + #endif + + extern DESC *descriptor_list; + #ifdef WIN32 + static WSADATA wsadata; + #endif + char ccom[BUFFER_LEN]; + dbref cplr; + + + #ifndef BOOLEXP_DEBUGGING + #ifdef WIN32 + void mainthread(int argc, char **argv); + #else + int main(int argc, char **argv); + #endif + #endif + void set_signals(void); + struct timeval *timeval_sub(struct timeval *now, struct timeval *then); + /* Windows doesn't have gettimeofday(). Implement it if on windows, + * otherwise just call gettimeofday(). Cuts down on conditional code + * elsewhere */ + #ifdef WIN32 + void win_gettimeofday(struct timeval *now); + #define our_gettimeofday(now) win_gettimeofday((now)) + #else + #define our_gettimeofday(now) gettimeofday((now), (struct timezone *)NULL) + #endif + long int msec_diff(struct timeval *now, struct timeval *then); + struct timeval *msec_add(struct timeval *t, int x); + struct timeval *update_quotas(struct timeval *last, struct timeval *current); + + void clearstrings(DESC *d); + typedef struct fblock { + unsigned char *buff; + size_t len; + } FBLOCK; + + struct fcache_entries { + FBLOCK connect_fcache[2]; + FBLOCK motd_fcache[2]; + FBLOCK wizmotd_fcache[2]; + FBLOCK newuser_fcache[2]; + FBLOCK register_fcache[2]; + FBLOCK quit_fcache[2]; + FBLOCK down_fcache[2]; + FBLOCK full_fcache[2]; + FBLOCK guest_fcache[2]; + }; + DESC *initializesock(int s, char *addr, char *ip); + struct text_block *make_text_block(const unsigned char *s, int n); + void free_text_block(struct text_block *t); + void add_to_queue(struct text_queue *q, const unsigned char *b, int n); + int flush_queue(struct text_queue *q, int n); + int queue_write(DESC *d, const unsigned char *b, int n); + int queue_newwrite(DESC *d, const unsigned char *b, int n); + int queue_string(DESC *d, const char *s); + int queue_string_eol(DESC *d, const char *s); + int queue_eol(DESC *d); + void freeqs(DESC *d); + void welcome_user(DESC *d); + void save_command(DESC *d, const unsigned char *command); + int process_input(DESC *d); + void process_input_helper(DESC *d, char *tbuf1, int got); + void set_userstring(unsigned char **userstring, const char *command); + int process_output(DESC *d); + + enum na_type { + NA_ASCII = 0, + NA_ANSI, /* ANSI flag */ + NA_COLOR, /* ANSI and COLOR flags */ + NA_PUEBLO, /* html */ + NA_PASCII, /* Player without any of the above */ + NA_TANSI, /* Like above with telnet-aware client */ + NA_TCOLOR, /* Like above with telnet-aware client */ + NA_TPASCII, /* Like above with telnet-aware client */ + NA_NANSI, /* ANSI and NOACCENTS */ + NA_NCOLOR, /* ANSI, COLOR, NOACCENTS */ + NA_NPUEBLO, /* html & NOACCENTS */ + NA_NPASCII /* 11. NOACCENTS */ + }; + #define TA_BGC 0 + #define TA_FGC 1 + #define TA_BOLD 2 + #define TA_REV 3 + #define TA_BLINK 4 + #define TA_ULINE 5 + + static int na_depth = 0; + + #define MESSAGE_TYPES 12 + + struct notify_strings { + unsigned char *message; + size_t len; + int made; + }; + + static void fillstate(int state[], const unsigned char **f); + static void ansi_change_state(char *t, char **o, int color, int *state, + int *newstate); + static enum na_type notify_type(DESC *d); + static void free_strings(struct notify_strings messages[]); + static void zero_strings(struct notify_strings messages[]); + static unsigned char *notify_makestring(const char *message, + struct notify_strings messages[], + enum na_type type); + + + static void + fillstate(int state[6], const unsigned char **f) + { + const unsigned char *p; + int i; + int n; + p = *f; + p++; + if (*p != '[') { + while (*p && *p != 'm') + p++; + } else { + p++; + while (*p && *p != 'm') { + if ((*p > '9') || (*p < '0')) { + /* Nada */ + } else if (!(*(p + 1)) || (*(p + 1) == 'm') || (*(p + 1) == ';')) { + /* ShortCode */ ; + switch (*p) { + case '0': + for (i = 0; i < 6; i++) + state[i] = 0; + break; + case '1': + state[TA_BOLD] = 1; + break; + case '7': + state[TA_REV] = 1; + break; + case '5': + state[TA_BLINK] = 1; + break; + case '4': + state[TA_ULINE] = 1; + break; + } + } else { + n = (*p - '0') * 10; + p++; + n += (*p - '0'); + if ((n >= 30) && (n <= 37)) + state[TA_FGC] = n - 29; + else if ((n >= 40) && (n <= 47)) + state[TA_BGC] = n - 39; + } + p++; + } + } + if ((p != *f) && (*p != 'm')) + p--; + *f = p; + } + + #define add_ansi_if(x,c) \ + do { \ + if (newstate[(x)] && (newstate[(x)]!=state[(x)])) { \ + if (i) safe_chr(';',t,o); \ + safe_str((c),t,o); \ + i=1; \ + } \ + } while (0) + + static void + ansi_change_state(char *t, char **o, int color, int *state, int *newstate) + { + int i, n; + if ((state[TA_BOLD] && !newstate[TA_BOLD]) || + (state[TA_REV] && !newstate[TA_REV]) || + (state[TA_BLINK] && !newstate[TA_BLINK]) || + (state[TA_ULINE] && !newstate[TA_ULINE]) || + (color && state[TA_FGC] && !newstate[TA_FGC]) || + (color && state[TA_BGC] && !newstate[TA_BGC])) { + for (n = 0; n < 6; n++) + state[n] = 0; + safe_str(ANSI_NORMAL, t, o); + } + if ((newstate[TA_BOLD] && (newstate[TA_BOLD] != state[TA_BOLD])) || + (newstate[TA_REV] && (newstate[TA_REV] != state[TA_REV])) || + (newstate[TA_BLINK] && (newstate[TA_BLINK] != state[TA_BLINK])) || + (newstate[TA_ULINE] && (newstate[TA_ULINE] != state[TA_ULINE])) || + (color && newstate[TA_FGC] && (newstate[TA_FGC] != state[TA_FGC])) || + (color && newstate[TA_BGC] && (newstate[TA_BGC] != state[TA_BGC]))) { + safe_chr(ESC_CHAR, t, o); + safe_chr('[', t, o); + i = 0; + add_ansi_if(TA_BOLD, "1"); + add_ansi_if(TA_REV, "7"); + add_ansi_if(TA_BLINK, "5"); + add_ansi_if(TA_ULINE, "4"); + if (color) { + add_ansi_if(TA_FGC, unparse_integer(newstate[TA_FGC] + 29)); + add_ansi_if(TA_BGC, unparse_integer(newstate[TA_BGC] + 39)); + } + safe_chr('m', t, o); + } + for (n = 0; n < 6; n++) + state[n] = newstate[n]; + } + + #undef add_ansi_if + + int html_cols[] = { + 0xC0C0C0, /* Default */ + 0x000000, + 0xC00000, + 0x00C000, + 0xC0C000, + 0x0000C0, + 0xC000C0, + 0x00C0C0, + 0xC0C0C0 + }; + + static void + zero_strings(struct notify_strings messages[]) + { + int n; + for (n = 0; n < MESSAGE_TYPES; n++) { + messages[n].message = NULL; + messages[n].len = 0; + messages[n].made = 0; + } + } + + static void + free_strings(struct notify_strings messages[]) + { + int n; + for (n = 0; n < MESSAGE_TYPES; n++) + if (messages[n].message) + mush_free(messages[n].message, "string"); + } + + static unsigned char * + notify_makestring(const char *message, struct notify_strings messages[], + enum na_type type) + { + char *o; + const unsigned char *p; + char *t; + int state[6] = { 0, 0, 0, 0, 0, 0 }; + int newstate[6] = { 0, 0, 0, 0, 0, 0 }; + int n; + int b, f; + int changed = 0; + int color = 0; + int strip = 0; + int fc, bc; + char colbuff[128]; + static char tbuf[BUFFER_LEN]; + + if (messages[type].made) + return messages[type].message; + messages[type].made = 1; + + p = (unsigned char *) message; + o = tbuf; + t = o; + + /* Since well over 50% is this type, we do it quick */ + switch (type) { + case NA_ASCII: + while (*p) { + switch (*p) { + case TAG_START: + while (*p && *p != TAG_END) + p++; + break; + case '\r': + case BEEP_CHAR: + break; + case ESC_CHAR: + while (*p && *p != 'm') + p++; + break; + default: + safe_chr(*p, t, &o); + } + p++; + } + *o = '\0'; + messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); + messages[type].len = o - tbuf; + return messages[type].message; + case NA_NPASCII: + strip = 1; + case NA_PASCII: + case NA_TPASCII: + /* PLAYER Ascii. Different output. \n is \r\n */ + if (type == NA_NPASCII) + strip = 1; + while (*p) { + switch (*p) { + case IAC: + if (type == NA_TPASCII) + safe_str("\xFF\xFF", t, &o); + else if (strip) + safe_str(accent_table[IAC].base, t, &o); + else + safe_chr((char) IAC, t, &o); + break; + case TAG_START: + while (*p && *p != TAG_END) + p++; + break; + case ESC_CHAR: + while (*p && *p != 'm') + p++; + break; + case '\r': + break; + case '\n': + safe_str("\r\n", t, &o); + break; + default: + if (strip && accent_table[(unsigned char) *p].base) + safe_str(accent_table[(unsigned char) *p].base, t, &o); + else + safe_chr(*p, t, &o); + } + p++; + } + *o = '\0'; + messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); + messages[type].len = o - tbuf; + return messages[type].message; + + case NA_NPUEBLO: + strip = 1; + case NA_PUEBLO: + while (*p) { + if (*p == ESC_CHAR) { + fillstate(newstate, &p); + changed = 1; + } else { + if (changed) { + changed = 0; + /* Do we need to close any attribute tags? */ + if (state[TA_BOLD] && !newstate[TA_BOLD]) + safe_str("
", t, &o); + if (state[TA_ULINE] && !newstate[TA_ULINE]) + safe_str("", t, &o); + /* Are we going to start a new font? If so, temporarily + * close attribute tags */ + if (!state[TA_BGC] && !state[TA_FGC] && + (newstate[TA_FGC] || newstate[TA_FGC])) { + if (state[TA_BOLD] && newstate[TA_BOLD]) + safe_str("", t, &o); + if (state[TA_ULINE] && newstate[TA_ULINE]) + safe_str("", t, &o); + } + /* Are we changing fonts? If so, close the FONT tag and + any attribute tags */ + if (((state[TA_BGC] || state[TA_FGC]) && + ((state[TA_BGC] != newstate[TA_BGC]) || + (state[TA_FGC] != newstate[TA_FGC]))) || + (state[TA_REV] != newstate[TA_REV])) { + /* If we're in bold, and staying bold, temporarily close the tag */ + if (state[TA_BOLD] && newstate[TA_BOLD]) + safe_str("", t, &o); + if (state[TA_ULINE] && newstate[TA_ULINE]) + safe_str("", t, &o); + safe_str("
", t, &o); + } + /* Should we start a new FONT tag? */ + if ((newstate[TA_BGC] && (state[TA_BGC] != newstate[TA_BGC])) + || (newstate[TA_FGC] && (state[TA_FGC] != newstate[TA_FGC])) + || (newstate[TA_REV] && (state[TA_REV] != newstate[TA_REV])) + ) { + fc = newstate[TA_FGC]; + bc = newstate[TA_BGC]; + if (newstate[TA_REV]) { + if (!fc) + fc = 8; + if (!bc) + bc = 1; + f = html_cols[bc]; + b = html_cols[fc]; + } else { + f = html_cols[fc]; + b = html_cols[bc]; + } + if (bc && fc) { + sprintf(colbuff, "", f, b); + } else if (fc) { + sprintf(colbuff, "", f); + } else { + sprintf(colbuff, "", b); + } + safe_str(colbuff, t, &o); + /* Should we reopen attribute tags, too? */ + if (state[TA_BOLD] && newstate[TA_BOLD]) + safe_str("", t, &o); + if (state[TA_ULINE] && newstate[TA_ULINE]) + safe_str("", t, &o); + } + /* If we weren't bold before, or if we were bold+font and now + * are just bold, we reopen bold tag if we're going to be bold + */ + if ((!state[TA_BOLD] || (state[TA_BOLD] && (state[TA_FGC] || + state[TA_BGC]) + && !newstate[TA_FGC] && !newstate[TA_BGC])) + && newstate[TA_BOLD]) + safe_str("", t, &o); + if ((!state[TA_ULINE] || (state[TA_ULINE] && (state[TA_FGC] || + state[TA_BGC]) + && !newstate[TA_FGC] && !newstate[TA_BGC])) + && newstate[TA_ULINE]) + safe_str("", t, &o); + for (n = 0; n < 6; n++) + state[n] = newstate[n]; + } + switch (*p) { + case TAG_START: + safe_chr('<', t, &o); + p++; + while ((*p) && (*p != TAG_END)) { + safe_chr(*p, t, &o); + p++; + } + safe_chr('>', t, &o); + break; + case TAG_END: + /* Should never be seen alone */ + break; + case '\r': + break; + default: + if (strip) { + /* Even if we're NOACCENTS, we must still translate a few things */ + switch ((unsigned char) *p) { + case '\n': + case '&': + case '<': + case '>': + safe_str(accent_table[(unsigned char) *p].entity, t, &o); + break; + default: + if (accent_table[(unsigned char) *p].base) + safe_str(accent_table[(unsigned char) *p].base, t, &o); + else + safe_chr(*p, t, &o); + break; + } + } else if (accent_table[(unsigned char) *p].entity) + safe_str(accent_table[(unsigned char) *p].entity, t, &o); + else + safe_chr(*p, t, &o); + } + } + p++; + } + if (state[TA_BGC] || state[TA_FGC] || state[TA_REV]) + safe_str("", t, &o); + if (state[TA_BOLD]) + safe_str("", t, &o); + if (state[TA_ULINE]) + safe_str("", t, &o); + break; + case NA_COLOR: + case NA_TCOLOR: + case NA_NCOLOR: + color = 1; + /* FALLTHROUGH */ + case NA_ANSI: + case NA_TANSI: + case NA_NANSI: + if (type == NA_NCOLOR || type == NA_NANSI) + strip = 1; + while (*p) { + switch ((unsigned char) *p) { + case IAC: + if (changed) { + changed = 0; + ansi_change_state(t, &o, color, state, newstate); + } + if (type == NA_TANSI || type == NA_TCOLOR) + safe_str("\xFF\xFF", t, &o); + else if (strip && accent_table[IAC].base) + safe_str(accent_table[IAC].base, t, &o); + else + safe_chr((char) IAC, t, &o); + break; + case TAG_START: + while (*p && *p != TAG_END) + p++; + break; + case '\r': + break; + case '\n': + if (changed) { + changed = 0; + ansi_change_state(t, &o, color, state, newstate); + } + safe_str("\r\n", t, &o); + + break; + case ESC_CHAR: + fillstate(newstate, &p); + changed = 1; + break; + default: + if (changed) { + changed = 0; + ansi_change_state(t, &o, color, state, newstate); + } + if (strip && accent_table[(unsigned char) *p].base) + safe_str(accent_table[(unsigned char) *p].base, t, &o); + else + safe_chr(*p, t, &o); + } + p++; + } + if (state[TA_BOLD] || state[TA_REV] || + state[TA_BLINK] || state[TA_ULINE] || + (color && (state[TA_FGC] || state[TA_BGC]))) + safe_str(ANSI_NORMAL, t, &o); + + break; + } + + *o = '\0'; + messages[type].message = (unsigned char *) mush_strdup(tbuf, "string"); + messages[type].len = o - tbuf; + return messages[type].message; + } + + dbref + na_one(dbref current, void *data) + { + if (current == NOTHING) + return *((dbref *) data); + else + return NOTHING; + } + + dbref + na_next(dbref current, void *data) + { + if (current == NOTHING) + return *((dbref *) data); + else + return Next(current); + } + + dbref + na_loc(dbref current, void *data) + { + dbref loc = *((dbref *) data); + if (current == NOTHING) + return loc; + else if (current == loc) + return Contents(current); + else + return Next(current); + } + + dbref + na_nextbut(dbref current, void *data) + { + dbref *dbrefs = data; + + do { + if (current == NOTHING) + current = dbrefs[0]; + else + current = Next(current); + } while (current == dbrefs[1]); + return current; + } + + dbref + na_except(dbref current, void *data) + { + dbref *dbrefs = data; + + do { + if (current == NOTHING) + current = dbrefs[0]; + else if (current == dbrefs[0]) + current = Contents(current); + else + current = Next(current); + } while (current == dbrefs[1]); + return current; + } + + dbref + na_except2(dbref current, void *data) + { + dbref *dbrefs = data; + + do { + if (current == NOTHING) + current = dbrefs[0]; + else if (current == dbrefs[0]) + current = Contents(current); + else + current = Next(current); + } while ((current == dbrefs[1]) || (current == dbrefs[2])); + return current; + } + + /* Works like na_except2, but with multiple exceptions. + * dbrefs[0] should indicate the number of exceptions. + * dbrefs[1] is the dbref of the room the message was emitted in. + * dbrefs[2] and up are the exceptions. + */ + dbref + na_exceptN(dbref current, void *data) + { + dbref *dbrefs = data; + int i, check; + + do { + if (current == NOTHING) + current = dbrefs[1]; + else if (current == dbrefs[1]) + current = Contents(current); + else + current = Next(current); + check = 0; + for (i = 2; i < dbrefs[0] + 2; i++) + if (current == dbrefs[i]) + check = 1; + } while (check); + return current; + } + + + static int nohtml_strlen(const char *s, dbref puppet); + static int + nohtml_strlen(const char *s, dbref puppet) + { + const char *p = s; + int n = 0; + + if (GoodObject(puppet)) { + char *name = strstr(s, tprintf("%s> ", Name(puppet))); + if (name == s) { + p += strlen(Name(puppet)) + 2; + } + } + + for (; *p != '\0'; p++) { + switch (*p) { + case TAG_START: + do { + p++; + } while (*p != '\0' && *p != TAG_END); + break; + case TAG_END: /* Just in case */ + break; + default: + n++; + } + } + return n; + } + + static enum na_type + notify_type(DESC *d) + { + enum na_type poutput; + int strip = 0; + + if (!d->connected || IS(d->player, TYPE_PLAYER, "NOACCENTS")) + strip = 1; + + if (d->conn_flags & CONN_HTML) { + poutput = strip ? NA_NPUEBLO : NA_PUEBLO; + } else if (ShowAnsi(d->player)) { + if (ShowAnsiColor(d->player)) { + if (strip) + poutput = NA_NCOLOR; + else + poutput = (d->conn_flags & CONN_TELNET) ? NA_TCOLOR : NA_COLOR; + } else { + if (strip) + poutput = NA_NANSI; + else + poutput = (d->conn_flags & CONN_TELNET) ? NA_TANSI : NA_ANSI; + } + } else { + if (strip) + poutput = NA_NPASCII; + else + poutput = (d->conn_flags & CONN_TELNET) ? NA_TPASCII : NA_PASCII; + } + return poutput; + } + + void + notify_anything(dbref speaker, na_lookup func, + void *fdata, char *(*nsfunc) (dbref, na_lookup func, void *, + int), int flags, + const char *message) + { + dbref target; + dbref passalong[3]; + struct notify_strings messages[MESSAGE_TYPES]; + struct notify_strings nospoofs[MESSAGE_TYPES]; + struct notify_strings paranoids[MESSAGE_TYPES]; + int i, j; + DESC *d; + enum na_type poutput; + unsigned char *pstring; + size_t plen; + char *bp; + ATTR *a; + char *asave; + char const *ap; + char *preserve[NUMQ]; + int havespoof = 0; + int havepara = 0; + char *wsave[10]; + char *tbuf1 = NULL, *nospoof = NULL, *paranoid = NULL, *msgbuf; + static dbref puppet = NOTHING; + + if (!message || *message == '\0' || !func) + return; + + /* Depth check */ + if (na_depth > 7) + return; + na_depth++; + + /* Only allocate these buffers when needed */ + for (i = 0; i < MESSAGE_TYPES; i++) { + messages[i].message = NULL; + messages[i].made = 0; + nospoofs[i].message = NULL; + nospoofs[i].made = 0; + paranoids[i].message = NULL; + paranoids[i].made = 0; + } + + msgbuf = mush_strdup(message, "string"); + + target = NOTHING; + + while ((target = func(target, fdata)) != NOTHING) { + if ((flags & NA_PONLY) && !IsPlayer(target)) + continue; + + if (IsPlayer(target)) { + if (!Connected(target) && options.login_allow && under_limit) + continue; + for (d = descriptor_list; d; d = d->next) { + if (d->connected && d->player == target) { + poutput = notify_type(d); + + if ((flags & NA_PONLY) && (poutput != NA_PUEBLO)) + continue; + + if (nsfunc && Nospoof(target) && (target != speaker)) { + if (Paranoid(target)) { + if (!havepara) { + paranoid = nsfunc(speaker, func, fdata, 1); + havepara = 1; + } + pstring = notify_makestring(paranoid, paranoids, poutput); + plen = paranoids[poutput].len; + } else { + if (!havespoof) { + nospoof = nsfunc(speaker, func, fdata, 0); + havespoof = 1; + } + pstring = notify_makestring(nospoof, nospoofs, poutput); + plen = nospoofs[poutput].len; + } + queue_newwrite(d, pstring, plen); + } + pstring = notify_makestring(msgbuf, messages, poutput); + plen = messages[poutput].len; + + if (pstring && *pstring + && ((d->conn_flags & CONN_HTML) || !(flags & NA_NOENTER) + || ((flags & NA_PUPPET2) + && nohtml_strlen(msgbuf, puppet) > 0))) { + queue_newwrite(d, pstring, plen); + } + if (!(flags & NA_NOENTER)) { + if ((poutput == NA_PUEBLO) || (poutput == NA_NPUEBLO)) { + if (flags & NA_NOPENTER) + queue_newwrite(d, (unsigned char *) "\n", 1); + else + queue_newwrite(d, (unsigned char *) "
\n", 5); + } else { + queue_newwrite(d, (unsigned char *) "\r\n", 2); + } + } + } + } + } else if (Puppet(target) && + ((Location(target) != Location(Owner(target))) || + has_flag_by_name(target, "VERBOSE", NOTYPE) || + (flags & NA_MUST_PUPPET)) && + ((flags & NA_PUPPET) || !(flags & NA_NORELAY))) { + dbref last = puppet; + puppet = target; + if (!tbuf1) + tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string"); + bp = tbuf1; + safe_str(Name(target), tbuf1, &bp); + safe_str("> ", tbuf1, &bp); + safe_str(msgbuf, tbuf1, &bp); + *bp = '\0'; + notify_anything(speaker, na_one, &Owner(target), NULL, + flags | NA_NORELAY | NA_PUPPET2, tbuf1); + puppet = last; + } + if ((flags & NA_NOLISTEN) + || (!PLAYER_LISTEN && IsPlayer(target)) + || IsExit(target)) + continue; + + /* do @listen stuff */ + a = atr_get_noparent(target, "LISTEN"); + if (a) { + if (!tbuf1) + tbuf1 = (char *) mush_malloc(BUFFER_LEN, "string"); + strcpy(tbuf1, uncompress(a->value)); + if ((AL_FLAGS(a) & AF_REGEXP) + ? regexp_match_case(tbuf1, + (char *) notify_makestring(msgbuf, messages, + NA_ASCII), + AL_FLAGS(a) & AF_CASE) + : wild_match_case(tbuf1, + (char *) notify_makestring(msgbuf, messages, + NA_ASCII), + AL_FLAGS(a) & AF_CASE)) { + if (eval_lock(speaker, target, Listen_Lock)) + if (PLAYER_AHEAR || (!IsPlayer(target))) { + if (speaker != target) + charge_action(speaker, target, "AHEAR"); + else + charge_action(speaker, target, "AMHEAR"); + charge_action(speaker, target, "AAHEAR"); + } + if (!(flags & NA_NORELAY) && !member(speaker, Contents(target)) && + !filter_found(target, + (char *) notify_makestring(msgbuf, messages, + NA_ASCII), 1)) { + passalong[0] = target; + passalong[1] = target; + passalong[2] = Owner(target); + a = atr_get(target, "INPREFIX"); + if (a) { + for (j = 0; j < 10; j++) + wsave[j] = wenv[j]; + wenv[0] = (char *) msgbuf; + for (j = 1; j < 10; j++) + wenv[j] = NULL; + save_global_regs("inprefix_save", preserve); + asave = safe_uncompress(a->value); + ap = asave; + bp = tbuf1; + process_expression(tbuf1, &bp, &ap, target, speaker, speaker, + PE_DEFAULT, PT_DEFAULT, NULL); + if (bp != tbuf1) + safe_chr(' ', tbuf1, &bp); + safe_str(msgbuf, tbuf1, &bp); + *bp = 0; + free(asave); + restore_global_regs("inprefix_save", preserve); + for (j = 0; j < 10; j++) + wenv[j] = wsave[j]; + } + notify_anything(speaker, Puppet(target) ? na_except2 : na_except, + passalong, NULL, flags | NA_NORELAY, + (a) ? tbuf1 : msgbuf); + } + } + } + /* if object is flagged LISTENER, check for ^ listen patterns + * * these are like AHEAR - object cannot trigger itself. + * * unlike normal @listen, don't pass the message on. + * */ + + if ((speaker != target) && (ThingListen(target) || RoomListen(target)) + && eval_lock(speaker, target, Listen_Lock) + ) + atr_comm_match(target, speaker, '^', ':', + (char *) notify_makestring(msgbuf, messages, NA_ASCII), 0, + NULL, NULL); + + /* If object is flagged AUDIBLE and has a @FORWARDLIST, send + * stuff on */ + if (!(flags & NA_NORELAY) && Audible(target) + && ((a = atr_get_noparent(target, "FORWARDLIST")) != NULL) + && !filter_found(target, msgbuf, 0)) { + char *fwdstr, *orig, *curr; + dbref fwd; + + orig = safe_uncompress(AL_STR(a)); + fwdstr = trim_space_sep(orig, ' '); + + if (!tbuf1) + tbuf1 = mush_malloc(BUFFER_LEN, "string"); + bp = tbuf1; + make_prefixstr(target, msgbuf, tbuf1); + + while ((curr = split_token(&fwdstr, ' ')) != NULL) { + if (is_dbref(curr)) { + fwd = parse_dbref(curr); + if (GoodObject(fwd) && !IsGarbage(fwd) && Can_Forward(target, fwd)) { + if (IsRoom(fwd)) { + notify_anything(speaker, na_loc, &fwd, NULL, + flags | NA_NORELAY, tbuf1); + } else { + notify_anything(speaker, na_one, &fwd, NULL, + flags | NA_NORELAY, tbuf1); + } + } + } + } + free((Malloc_t) orig); + } + } + + for (i = 0; i < MESSAGE_TYPES; i++) { + if (messages[i].message) + mush_free((Malloc_t) messages[i].message, "string"); + if (nospoofs[i].message) + mush_free((Malloc_t) nospoofs[i].message, "string"); + if (paranoids[i].message) + mush_free((Malloc_t) paranoids[i].message, "string"); + } + if (nospoof) + mush_free((Malloc_t) nospoof, "string"); + if (paranoid) + mush_free((Malloc_t) paranoid, "string"); + if (tbuf1) + mush_free((Malloc_t) tbuf1, "string"); + mush_free((Malloc_t) msgbuf, "string"); + na_depth--; + } + + int + safe_tag(char const *a_tag, char *buf, char **bp) + { + int result = 0; + + if (SUPPORT_PUEBLO) { + result += safe_chr(TAG_START, buf, bp); + result += safe_str(a_tag, buf, bp); + result += safe_chr(TAG_END, buf, bp); + } + return result; + } + + int + safe_tag_cancel(char const *a_tag, char *buf, char **bp) + { + int result = 0; + if (SUPPORT_PUEBLO) { + result += safe_chr(TAG_START, buf, bp); + result += safe_chr('/', buf, bp); + result += safe_str(a_tag, buf, bp); + result += safe_chr(TAG_END, buf, bp); + } + return result; + } + + int + safe_tag_wrap(char const *a_tag, char const *params, char const *data, + char *buf, char **bp) + { + int result = 0; + if (SUPPORT_PUEBLO) { + result += safe_chr(TAG_START, buf, bp); + result += safe_str(a_tag, buf, bp); + if (params && *params) { + result += safe_chr(' ', buf, bp); + result += safe_str(params, buf, bp); + } + result += safe_chr(TAG_END, buf, bp); + } + result += safe_str(data, buf, bp); + if (SUPPORT_PUEBLO) { + result += safe_tag_cancel(a_tag, buf, bp); + } + return result; + } + + void + raw_notify(dbref player, const char *msg) + { + notify_anything(GOD, na_one, &player, NULL, NA_NOLISTEN, msg); + } + + /* Rewrite this to compute a flag mask from a list of flags names */ + /* You must have flag1 and flag2 to get the broadcast */ + void + WIN32_CDECL + flag_broadcast(const char *flag1, const char *flag2, const char *fmt, ...) + { + /* takes flag/toggle masks, format string, and format args, and notifies + * all connected players with that flag mask of something. + * If inflags=intoggles=0, broadcast to all. + * If one of them is 0, and the other isn't, then players + * with _at least_ one of the bits in the flag mask are notified, + * rather than players with that _entire_ flag mask. The former + * behavior is more useful. + * If both are nonzero, the player must have at least one bit in each. + */ + + va_list args; + char tbuf1[BUFFER_LEN]; + DESC *d; + int ok; + + va_start(args, fmt); + + #ifdef HAS_VSNPRINTF + (void) vsnprintf(tbuf1, sizeof tbuf1, fmt, args); + #else + (void) vsprintf(tbuf1, fmt, args); + #endif + va_end(args); + tbuf1[BUFFER_LEN - 1] = '\0'; + + DESC_ITER_CONN(d) { + ok = 1; + if (flag1) + ok = ok && flaglist_check_long(GOD, d->player, flag1, 0); + if (flag2) + ok = ok && flaglist_check_long(GOD, d->player, flag2, 0); + if (ok) { + queue_string_eol(d, tbuf1); + process_output(d); + } + } + } + + + + struct text_block * + make_text_block(const unsigned char *s, int n) + { + struct text_block *p; + p = + (struct text_block *) mush_malloc(sizeof(struct text_block), "text_block"); + if (!p) + panic("Out of memory"); + p->buf = + (unsigned char *) mush_malloc(sizeof(unsigned char) * n, "text_block_buff"); + if (!p->buf) + panic("Out of memory"); + + memcpy(p->buf, s, n); + p->nchars = n; + p->start = p->buf; + p->nxt = 0; + return p; + } + + void + free_text_block(struct text_block *t) + { + if (t) { + if (t->buf) + mush_free((Malloc_t) t->buf, "text_block_buff"); + mush_free((Malloc_t) t, "text_block"); + } + } + + void + add_to_queue(struct text_queue *q, const unsigned char *b, int n) + { + struct text_block *p; + + if (n == 0) + return; + + p = make_text_block(b, n); + p->nxt = 0; + *q->tail = p; + q->tail = &p->nxt; + } + + int + flush_queue(struct text_queue *q, int n) + { + struct text_block *p; + int really_flushed = 0; + n += strlen(flushed_message); + + while (n > 0 && (p = q->head)) { + n -= p->nchars; + really_flushed += p->nchars; + q->head = p->nxt; + #ifdef DEBUG + do_rawlog(LT_ERR, "free_text_block(0x%x) at 1.", p); + #endif /* DEBUG */ + free_text_block(p); + } + p = + make_text_block((unsigned char *) flushed_message, strlen(flushed_message)); + p->nxt = q->head; + q->head = p; + if (!p->nxt) + q->tail = &p->nxt; + really_flushed -= p->nchars; + return really_flushed; + } + + int + queue_write(DESC *d, const unsigned char *b, int n) + { + char buff[BUFFER_LEN]; + struct notify_strings messages[MESSAGE_TYPES]; + unsigned char *s; + PUEBLOBUFF; + size_t len; + + if ((n == 2) && (b[0] == '\r') && (b[1] == '\n')) { + if ((d->conn_flags & CONN_HTML)) + queue_newwrite(d, (unsigned char *) "
\n", 5); + else + queue_newwrite(d, b, 2); + return n; + } + if (n > BUFFER_LEN) + n = BUFFER_LEN; + + memcpy(buff, b, n); + buff[n] = '\0'; + + zero_strings(messages); + + if (d->conn_flags & CONN_HTML) { + PUSE; + tag_wrap("SAMP", NULL, buff); + PEND; + s = notify_makestring(pbuff, messages, NA_PUEBLO); + len = messages[NA_PUEBLO].len; + } else { + s = notify_makestring(buff, messages, notify_type(d)); + len = messages[notify_type(d)].len; + } + queue_newwrite(d, s, len); + free_strings(messages); + return n; + } + + int + queue_newwrite(DESC *d, const unsigned char *b, int n) + { + int space; + + #ifdef NT_TCP + + /* queue up an asynchronous write if using Windows NT */ + if (platform == VER_PLATFORM_WIN32_NT) { + + struct text_block **qp, *cur; + DWORD nBytes; + BOOL bResult; + + /* don't write if connection dropped */ + if (d->bConnectionDropped) + return n; + + /* add to queue - this makes sure output arrives in the right order */ + add_to_queue(&d->output, b, n); + d->output_size += n; + + /* if we are already writing, exit and wait for IO completion */ + if (d->bWritePending) + return n; + + /* pull head item out of queue - not necessarily the one we just put in */ + qp = &d->output.head; + + if ((cur = *qp) == NULL) + return n; /* nothing in queue - rather strange, but oh well. */ + + + /* if buffer too long, write what we can and queue up the rest */ + + if (cur->nchars <= sizeof(d->output_buffer)) { + nBytes = cur->nchars; + memcpy(d->output_buffer, cur->start, nBytes); + if (!cur->nxt) + d->output.tail = qp; + *qp = cur->nxt; + free_text_block(cur); + } + /* end of able to write the lot */ + else { + nBytes = sizeof(d->output_buffer); + memcpy(d->output_buffer, cur->start, nBytes); + cur->nchars -= nBytes; + cur->start += nBytes; + } /* end of buffer too long */ + + d->OutboundOverlapped.Offset = 0; + d->OutboundOverlapped.OffsetHigh = 0; + + bResult = WriteFile((HANDLE) d->descriptor, + d->output_buffer, nBytes, NULL, &d->OutboundOverlapped); + + d->bWritePending = FALSE; + + if (!bResult) + if (GetLastError() == ERROR_IO_PENDING) + d->bWritePending = TRUE; + else { + d->bConnectionDropped = TRUE; /* do no more writes */ + /* post a notification that the descriptor should be shutdown */ + if (!PostQueuedCompletionStatus + (CompletionPort, 0, (DWORD) d, &lpo_shutdown)) { + char sMessage[200]; + DWORD nError = GetLastError(); + GetErrorMessage(nError, sMessage, sizeof sMessage); + printf + ("Error %ld (%s) on PostQueuedCompletionStatus in queue_newwrite\n", + nError, sMessage); + shutdownsock(d); + } + } /* end of had write */ + return n; + + } /* end of NT TCP/IP way of doing it */ + #endif + + space = MAX_OUTPUT - d->output_size - n; + if (space < SPILLOVER_THRESHOLD) { + process_output(d); + space = MAX_OUTPUT - d->output_size - n; + if (space < 0) + d->output_size -= flush_queue(&d->output, -space); + } + add_to_queue(&d->output, b, n); + d->output_size += n; + return n; + } + + int + queue_eol(DESC *d) + { + if (SUPPORT_PUEBLO && (d->conn_flags & CONN_HTML)) + return queue_newwrite(d, (unsigned char *) "
\n", 5); + else + return queue_newwrite(d, (unsigned char *) "\r\n", 2); + } + + int + queue_string_eol(DESC *d, const char *s) + { + queue_string(d, s); + return queue_eol(d); + } + + int + queue_string(DESC *d, const char *s) + { + unsigned char *n; + enum na_type poutput; + struct notify_strings messages[MESSAGE_TYPES]; + dbref target; + int ret; + + zero_strings(messages); + + target = d->player; + + poutput = notify_type(d); + + n = notify_makestring(s, messages, poutput); + ret = queue_newwrite(d, n, messages[poutput].len); + free_strings(messages); + return ret; + } + + + void + freeqs(DESC *d) + { + struct text_block *cur, *next; + cur = d->output.head; + while (cur) { + next = cur->nxt; + #ifdef DEBUG + do_rawlog(LT_ERR, "free_text_block(0x%x) at 3.", cur); + #endif /* DEBUG */ + free_text_block(cur); + cur = next; + } + d->output.head = 0; + d->output.tail = &d->output.head; + + cur = d->input.head; + while (cur) { + next = cur->nxt; + #ifdef DEBUG + do_rawlog(LT_ERR, "free_text_block(0x%x) at 4.", cur); + #endif /* DEBUG */ + free_text_block(cur); + cur = next; + } + d->input.head = 0; + d->input.tail = &d->input.head; + + if (d->raw_input) { + mush_free((Malloc_t) d->raw_input, "descriptor_raw_input"); + } + d->raw_input = 0; + d->raw_input_at = 0; + } *** 1.7.7/CHANGES.176 Thu Apr 11 09:25:15 2002 --- 1.7.7/CHANGES.176 Sat Mar 22 10:43:59 2003 *************** *** 0 **** --- 1,258 ---- + + [TN] is Thorvald Natvig, a PennMUSH developer (aka Trivian) + [TAP] is T. Alexander Popiel, a PennMUSH developer (aka Talek) + [SW] is Shawn Wagner, a PennMUSH developer (aka Raevnos) + [LdW] is Luuk de Waard, a PennMUSH developer (aka Halatir) + [RLM] is Ralph Melton, a former PennMUSH developer + [NJG] is Nick Gammon, the Win32 porter + [EEH] is Ervin Hearn III, a Win32 porter (aka Noltar) + [DW] is Dan Williams, the MacOS porter + [2.2] refers to code which originated with the TinyMUSH 2.2 developers + [3] refers to code by (or inspired by) TinyMUSH 3.0 + [Rhost] refers to code by (or inspired by) RhostMUSH + + ========================================================================== + + Version 1.7.6 patchlevel 8 March 21, 2003 + + Minor changes: + * The CHANGES file has been renamed so that it always refers to + a version number, and utils/mkvershelp.pl now generates seperate + .hlp files for each CHANGES file. This will prevent patch hunk + failures when two patchlevels of different versions are released + and both used to try to modify the same .hlp file. + * Channel names are restricted to printable characters, with no + leading or trailing spaces. Suggested by Letters@M*U*S*H. + * Calling time() with any argument other than 'utc' now generates + an error. Report by Time@M*U*S*H. + Fixes: + * Some redundant code cleanup in look_exits suggested by Vadiv@M*U*S*H. + * Help file fixes by Ves@M*U*S*H, Jules@M*U*S*H, Cerekk@bDv. + * When page_aliases is on, there's a space between the player's + name and alias. Suggested by Saturn@M3. + * Command-checking for ZMR contents didn't function when a ZMR + was used as a player's personal zone. Reported by BlaZe@M*U*S*H. + * Default idle_timeout was different in code and mushcnf.dst. + Reported by James Bond@M*U*S*H. [SW] + + + Version 1.7.6 patchlevel 7 February 20, 2003 + + Fixes: + * Some sloppy coding in src/access.c could generate runtime + debugging exceptions. Reported by BladedThoth@M*U*S*H. + * wrap() could behave incorrectly when a line was exactly the length + of the wrap width and the total input size was larger than + any previously wrapped input. Reported by Liam@Firdeloth. + * Extra NUL characters were sent after telnet codes, which + confused Mudnet and maybe some clients. Patch by Alierak. + + + Version 1.7.6 patchlevel 6 January 23, 2003 + + Minor changes: + * nearby() always works for see_all players. Reported by Sparta. + * findable() now requires that executor control either the object + or the victim or be see_all. Reported by Sparta. + Fixes: + * POWER^ and CHANNEL^ locks tested the wrong object. [SW] + * @grep, @wipe, and @edit now report when no attributes are + matched. Suggested by Procyon@M3 + * Changes to telnet negotiation strings to match those in + PennMUSH 1.7.7, which seems to fix some problems with display + of connect.txt in some clients. Report by Howie@NewFrontier. + Patch by Time@M*U*S*H. + * @mail/silent wasn't unless you used /send too. Report by + Moe@Chicago. + * Wizards could set attributes on garbage objects (which were useless, + but may have leaked memory needlessly). Reported by Taz@M*U*S*H. + * @chan/hide didn't check for hide permissions properly in some + cases. Reported by Tanaku@M*U*S*H. + * Better explanation of when regexp matching is case sensitive vs. + insensitive. Suggested by Jake@BrazilMUX, Brazil@BrazilMUX, and + Vadiv@M*U*S*H. + + + Version 1.7.6 patchlevel 5 January 7, 2003 + + Fixes: + * 1.7.6p4 broke 'go #dbref', which broke the ability of followers + to follow. Reported by Ellis@M*U*S*H. + + + Version 1.7.6 patchlevel 4 January 2, 2003 + + Minor Changes: + * English-style matching now applies to exits in the room + (so '1st down' can match the first 'down' exit if you're not carrying + anything that matches 'down'). New english-style matching adjective + 'toward' restricts the match to exits (so: 'look toward 1st down'). + Fixes: + * Code cleanup to fix several potential buffer overflows. + * The wildcard matcher had problems with backslash escapes in + some cases, making matching a : in a $command very hard. + Reported by Wayne@PDX. + * @chzone could cause crashes on some systems. Reported by Wayne@PDX. + * When two exits match, one is no longer chosen at random. + Instead, the ambiguity should be reported as an error. + Reported by Intrevis@M*U*S*H. + * The dbref returned by locate when given the X parameter is + no longer random, but the last one found (as per the help). + * Serious bug in reading locks from the db on startup corrected. + * The profiling timer is turned off duing dumps, as some systems + (FreeBSD?) appear to continue to use it and interrupt dumps + due to cpu limiting. Reported by Nathan Schuette. + + + Version 1.7.6 patchlevel 3 December 22, 2002 + + Minor changes: + * call_limit now controls the maximum recursion in process_expression, + instead of maximum calls to p_e per command cycle. This still + limits stack size, but doesn't get in the way of massive code + nearly as much. People using a very high call_limit value should + probably lower it significantly. Patch by Philip Mak. + * Improved error messages for many database information functions. + Notably, several functions that require at least one argument, + now complain if they don't get it rather than returning silently. + Suggested by Intrevis@M*U*S*H. [SW] + Fixes: + * @warnings are no longer shown on GOING objects. Suggested by + Philip Mak. + * Help fixes by Intrevis, Time, and Ambrosia@M*U*S*H + * Bug in @decomp/skipdefaults reported by Philip Mak. [SW] + * Tweaks to utils/mkcmds.sh [SW] + * home() on a room acts as described in the help. Reported by + Intrevis@M*U*S*H. [SW] + * whisper/noisy double-notified the whisperer. Reported by Philip Mak. + * Crash bug in @mail fixed. Reported by Titan@OtherSpace. + + + Version 1.7.6 patchlevel 2 December 17, 2002 + + Minor changes: + * An invalid range argument to @search/lsearch is now coerced + to be the lowest or highest dbref, as appropriate. The search + range is also now inclusive. And lsearch() works. + Suggested by Philip Mak. + * mushcnf.dst now includes a default value for call_limit. + Suggested by Philip Mak. + * Testing for whether the mush is already running in the + restart script has been improved by Philip Mak. + Internationalization: + * Polish translation files (partial) are now being distributed. + Fixes: + * Fix to win32 warnings. [EEH] + * Under Win32, a failed accept() call in bsd.c would not be + correctly handled. Report by BladedThoth@M*U*S*H. + * Help fixes by Luigi@8bitMUSH, Kyieren@M*U*S*H, Intrevis@M*U*S*H. + * @map crash bug repoted by Philip Mak, fixed by Walker@M*U*S*H. + * Modifiying locks now updates the object's modification time. + Reported by Philip Mak. + + + Version 1.7.6 patchlevel 1 November 26, 2002 + + Minor changes: + * When using @nuke to destroy a SAFE object when really_safe is "no", + provide a warning (but schedule destruction anyway). Suggested by + Cerekk@bDV. + Fixes: + * VS.NET project file was defaulting to signed instead of unsigned + chars, causing crashes. Fixed by BladedThoth@M*U*S*H. + Several places where we should have cast things to unsigned to + avoid this kind of thing have been fixed. [SW] + * The *emit() functions now set the orator correctly. + Reported by Philip Mak. + * ccom and cplr are cleared after each command execution so they + can't be leaked as easily. Suggested by Philip Mak. + * Linting. + * If God gives the wrong password to @logwipe, provide some feedback. + Suggested by Cerekk@bDv. + * mkcmds.sh was needlessly rebuilding several autogenerated files. + * The rules for flag characters shown in object headers now allows + F_INTERNAL flags to be shown (like GOING), just the same as + when you get a full flag list on examine. Report by Philip Mak. + * Help fixes by Bird@M*U*S*H, Intrevis@M*U*S*H, Philip Mak. + * @search type=something would report an error AND match the entire + database when something wasn't object, player, exit or room. [SW] + * Cosmetic bug in @malias/list fixed. Report by Tanaku@M*U*S*H. + * The info_slave now properly obeys the use_dns setting in mush.cnf. + This requires a full shutdown to put into effect. Report by + BlaZe@M*U*S*H. [SW] + + + Version 1.7.6 patchlevel 0 November 11, 2002 + + License: + * PennMUSH 1.7.6 and later is now released under the Artistic + License. This is an OSI-compliant open source license. See the file + COPYRITE for the complete license text. + + Notable changes from the old license: + * No restrictions on commercial use + * No requirement to inform developers of improvements or submit + modifications, though it's still a nice thing to do. Note, however + that if you redistribute a modified version of PennMUSH, you MUST + include source code. + + The PennMUSH devteam thanks the copyright holders of TinyMUD, + TinyMUSH 2.0, TinyMUSH 2.2, and TinyMUSH 3.0 for their assistance + in making this possible. + Documentation: + * The README file has been split into README, INSTALL, UPGRADING, + and I18N files. + Minor Changes: + * Rooms now hear remits and lemits in them, and can be pemitted + to. This behavior now matches that of other MUSH servers. + * AUDIBLE objects now propagate sound @remit'd into them. + Report by [SW]. + * Added @lock/destroy to limit who can destroy a DESTROY_OK + object. Suggested by Luigi@8bit. + * PARANOID nospoof notification now includes the name of the object's + owner as well. Suggested by Philip Mak. + * room() no longer notifies the executor of permission errors out of + band. It now just returns the error instead, like loc(). Suggested by + Philip Mak. + * Creation times are now public information via ctime(); permission to + examine is no longer required. This allows objects to use, e.g., + %#@[ctime(%#)] as a historically unique identifier of an enactor. + Suggested by Philip Mak. + * The reboot.db is now versioned. This will make it possible to + @shutdown/reboot across patchlevels that change the reboot.db + format (in 1.7.7 and later versions). + * Rooms on an @forwardlist now receive the message as a remit, + rather than a pemit. Suggested by BladedThoth@M*U*S*H. + Fixes: + * More work on the great table() bug. Looks like a fix. [SW] + * Improved VS.NET project files by BladedThoth. + * Plugged a memory leak in deleting @locks. [SW] + * Fixed @lock-related crash bug reported by Philip Mak. [SW] + * General linting. + * process_expression ignores the [ in ansi escapes. Reported in the + context of #$ by Philip Mak. [SW] + * Internal changes to compress(), which now returns an allocated + string. Under Huffman compression, it should no longer be possible + to overflow a buffer with a pathological compression tree. Initial + concern voiced by Eyal Sagi. + * Table and ansi didn't play well together. Reported by Ellis@M*U*S*H. + * Config file reading should be better on Macs. Patch by Philip Mak. + * Obsolete checks for OLD_ANSI are removed. [SW] + * Crash bug in @function fixed. Report by Dallimar@Hemlock. + * Change to message on failed attribute flag set, to make it more + generic to cover all the possible failures. Report by Cerekk@bDv. + * Translations to some languages were broken. Fixed now. Report by + Sbot@M*U*S*H. + * QUEUE is now visible if you control an object, as promised in the + help. Reported by Luigi@8bit. + * Help fixes by Mortimer@M*U*S*H, Bellemore@M*U*S*H, Hyacinth@8bit, + [EEH], BladedThoth@M*U*S*H, Moe@M*U*S*H, Viila@M*U*S*H, Walker@M*U*S*H. + * Comment in src/Makefile fixed by Vadiv@M*U*S*H. + * A weird crash on @shutdown/reboot, probably attributable to a + broken library or system call, is now worked-around. Report by + Solarius@SWWF. + * Audible objects with @forwardlist set are no longer concealed by + the DARK flag. + * Win32 project files no longer use the win32/ directory as an include + directory, which causes problems. Reported by Gepht. +