This is patch04 to PennMUSH 1.8.2. After applying this patch, you will have version 1.8.2p4 To apply this patch, save it to a file in your top-level MUSH directory, and do the following: patch -p1 < 1.8.2-patch04 make clean make install 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. On the off chance they appear not to be, simply rm them and re-run make. Then @shutdown and restart your MUSH. - Ervin/Noltar In this patch: Minor changes: * speak() uses accented names. Sketch. * config() no longer lists options that can't be set with @config/set. Suggested by Trispis. [SW] * 'page foo\=bar' pages the last person you paged. Fix by Nathan Baum. * Receipt of a SIGUSR1 (Causing a shutdown/reboot) is explictly logged. Suggested by Interloper. [SW] * @wipe reports the number of attributes deleted. [183] Fixes: * You can no longer save objects slated to be destroyed by using @set foo=!GOING (The help file for GOING now tells the truth) Reported by Cooee. [SW] * Useless variable in real_unparse() removed. Reported by Taladan. [SW] * 'make portmsg' works, and portmsg.c rewritten to current Penn standards. [SW] * case() would replace #$ in the default argument, contrary to the help file. Reported by Talvo. [SW] * Memory leak in grep(). [SW] * Quotes can be around the player name on the login screen always, instead of just when player_name_spaces was on. Suggested by Dan Widdis. [SW] * '{think foo} bar' exhibited odd behavior. [GM] * 'make test' wouldn't work right unless '.' was in you path. Fix by Nathan Baum. * stdin and stdout weren't getting closed, potentially causing problems when trying to log out of a shell after starting a mush. Reported by K Moon. [SW] * NetBSD compile and general warning fixes. [SW] * Favor difftime(3) over subtraction of time_t variables. [SW] * Clarification of attribute trees in HELP @WIPE. Suggested by Talvo. * Loading a db with empty attributes used as the roots of attribute trees didn't work if empty_attrs is set to no. Reported by Kevin. [SW] * Bugs in wiping attribute trees with attributes the wiper doesn't have permission to delete fixed. [SW] Prereq: 1.8.2p3 *** 1_8_2p3/Patchlevel Sun Mar 11 20:21:16 2007 --- 1_8_2p4/Patchlevel Wed May 16 22:19:21 2007 *************** *** 1,2 **** Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.2p3 --- 1,2 ---- Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.2p4 *** 1_8_2p3/CHANGES.182 Sun Mar 11 20:21:16 2007 --- 1_8_2p4/CHANGES.182 Wed May 16 22:19:21 2007 *************** *** 14,19 **** --- 14,61 ---- ========================================================================== + Version 1.8.2 patchlevel 4 May 16, 2007 + + Minor changes: + * speak() uses accented names. Sketch. + * config() no longer lists options that can't be set + with @config/set. Suggested by Trispis. [SW] + * 'page foo\=bar' pages the last person you paged. Fix by Nathan + Baum. + * Receipt of a SIGUSR1 (Causing a shutdown/reboot) is explictly + logged. Suggested by Interloper. [SW] + * @wipe reports the number of attributes deleted. [183] + + Fixes: + * You can no longer save objects slated to be destroyed + by using @set foo=!GOING (The help file for GOING now tells + the truth) Reported by Cooee. [SW] + * Useless variable in real_unparse() removed. Reported by + Taladan. [SW] + * 'make portmsg' works, and portmsg.c rewritten to current + Penn standards. [SW] + * case() would replace #$ in the default argument, contrary + to the help file. Reported by Talvo. [SW] + * Memory leak in grep(). [SW] + * Quotes can be around the player name on the login screen + always, instead of just when player_name_spaces was + on. Suggested by Dan Widdis. [SW] + * '{think foo} bar' exhibited odd behavior. [GM] + * 'make test' wouldn't work right unless '.' was in you path. + Fix by Nathan Baum. + * stdin and stdout weren't getting closed, potentially causing + problems when trying to log out of a shell after starting + a mush. Reported by K Moon. [SW] + * NetBSD compile and general warning fixes. [SW] + * Favor difftime(3) over subtraction of time_t variables. [SW] + * Clarification of attribute trees in HELP @WIPE. Suggested by + Talvo. + * Loading a db with empty attributes used as the roots of + attribute trees didn't work if empty_attrs is set to no. + Reported by Kevin. [SW] + * Bugs in wiping attribute trees with attributes the wiper + doesn't have permission to delete fixed. [SW] + Version 1.8.2 patchlevel 3 March 11, 2007 Fixes: *** 1_8_2p3/README Sun Mar 11 20:21:16 2007 --- 1_8_2p4/README Wed May 16 22:19:21 2007 *************** *** 13,19 **** I. Introduction and history II. Getting Help, Reporting Bugs III. Getting a .pennmush.org hostname and mailing lists ! IV. Comments You may also want to take a look at Javelin's Guide for PennMUSH Gods, at http://pennmush.org/~alansz/guide.html --- 13,20 ---- I. Introduction and history II. Getting Help, Reporting Bugs III. Getting a .pennmush.org hostname and mailing lists ! IV. Miscellaneous ! V. Comments You may also want to take a look at Javelin's Guide for PennMUSH Gods, at http://pennmush.org/~alansz/guide.html *************** *** 131,159 **** informed of new patches, subscribe to pennmush-announce instead, at http://www.pennmush.org/mailman/listinfo/pennmush-announce) ! 2. pennmush-bugs@pennmush.org is the bug reporting address ! for the PennMUSH developers (suggestions go to pennmush-developers, ! bugs to pennmush-bugs). This will generally give you the fastest ! response and is ideal for unusual bugs. A web-based submission ! form is at http://www.pennmush.org/jitterbug/pennmush ! ! When reporting a problem, please always include the following ! information: ! ! 1. PennMUSH version number ! 2. The type of machine you are using (Sun SparcStation, IBM RS/6000, etc.) ! 3. The operating system and version (SunOS 4.1.2, AIX 3.2.4, etc.), ! 4. The compiler and compiler version (gcc 2.4.5, SGI cc 2.10, etc. -- the ! 'file' command usually tells you the compiler version, if there's no ! built-in option like '-v' or '-V' to give it), ! 5. Whether or not you have made any changes to the code. ! ! If the problem resulted in a crash and a core dump, a stack trace of ! the core dump (see the section above) should also be included. ! ! If I need additional stuff (like a log of the Configure or make), I'll ! ask for it, but if you know that it's relevant, you can send it along, ! too. ============================================================================ --- 132,159 ---- informed of new patches, subscribe to pennmush-announce instead, at http://www.pennmush.org/mailman/listinfo/pennmush-announce) ! 2. The PennMUSH bug-tracking site is http://dev.pennmush.org/ ! To file a new report, click on the 'New Ticket' link. If ! you want to get emails about updates to the bug report, put your ! email address in the appropriate field. For 'type', please select ! the most appropriate category: Bug, suggested feature, documetation ! issue, build/compliation problems, etc. Be sure to include what version ! of PennMUSH you found the problem on. ! ! If the problem resulted in a crash and a core dump, a stack trace of ! the core dump (see the section above) should also be included. ! ! If we need additional stuff (like a log of the Configure or make), we'll ! ask for it, but if you know that it's relevant, you can send it along, ! too. ! ! You can also search to see if anyone else has already reported the issue,' ! see what issues have been fixed for upcoming releases, and much more at ! the site. ! ! The old way of emailing pennmush-bugs@pennmush.org still works, but using ! the web interface allows you to specifically give an issue type when ! reporting something. ============================================================================ *************** *** 178,186 **** ============================================================================ ! IV. Comments ! IV.a. Amberyl's Comments These are in the first person. :) --- 178,205 ---- ============================================================================ ! IV. Miscellaneous ! V.a Announcing when a mush is down ! ! If your mush is no longer running on a given port or server and ! you want to and are able to leave a programming running listening ! on that port, you can tell people about a new location or other news. ! ! Run: ! ! % make portmsg ! ! Then start the port announcer with: ! ! % ./src/portmsg message.txt port# ! ! Any connections to the given port will see the contents of the message ! file and then be disconnected after a few seconds. ! ! V. Comments ! ! V.a. Amberyl's Comments These are in the first person. :) *************** *** 213,219 **** -- Lydia Leong (lwl@digex.net) "Amberyl" just about everywhere ! IV.b. Paul/Javelin's Comments And let me recognize T. Alexander Popiel, Shawn Wagner, Nick Gammon, Dan Williams, Ervin Hearn III, Ralph Melton, David Cheatham, and Thorvald --- 232,238 ---- -- Lydia Leong (lwl@digex.net) "Amberyl" just about everywhere ! V.b. Paul/Javelin's Comments And let me recognize T. Alexander Popiel, Shawn Wagner, Nick Gammon, Dan Williams, Ervin Hearn III, Ralph Melton, David Cheatham, and Thorvald *************** *** 230,236 **** Javelin at most places ! IV.c. Alex/Talek's Comments I would like to thank Ralph, Amberyl, Moonchilde, and all the others who went either with us or before us. --- 249,255 ---- Javelin at most places ! V.c. Alex/Talek's Comments I would like to thank Ralph, Amberyl, Moonchilde, and all the others who went either with us or before us. *** 1_8_2p3/game/txt/hlp/penncmd.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/penncmd.hlp Wed May 16 22:19:20 2007 *************** *** 146,152 **** room of the location, as well as objects in the master room, are also checked for an @aconnect. If one is found, it will be executed when a player connects in that location or zone (or, in the case of ! the master room, anywhere). See also: @adisconnect, ACTION LISTS & @adeath --- 146,153 ---- room of the location, as well as objects in the master room, are also checked for an @aconnect. If one is found, it will be executed when a player connects in that location or zone (or, in the case of ! the master room, anywhere). This is only done if the room_connects ! config option is enabled. See also: @adisconnect, ACTION LISTS & @adeath *************** *** 188,194 **** room of the location, as well as objects in the master room, are checked for an @adisconnect. If one is found, it will be executed when a player disconnects in that location or zone (or, in the case of ! the master room, anywhere). Several descriptor variables are passed to @adisconnect: %1 = number of remaining connections (0 if a full disconnect) --- 189,196 ---- room of the location, as well as objects in the master room, are checked for an @adisconnect. If one is found, it will be executed when a player disconnects in that location or zone (or, in the case of ! the master room, anywhere). This is only done if the room_connects ! config option is enabled. Several descriptor variables are passed to @adisconnect: %1 = number of remaining connections (0 if a full disconnect) *************** *** 3568,3573 **** --- 3570,3578 ---- exceptions as given above. If is given, it gets rid of all attributes which match that pattern. Note that the restrictions above still apply. + + When wiping an attribute that is the root of an attribute tree, all + attributes in that tree will also be removed. & @wizwall @wizwall[/emit] *************** *** 4206,4209 **** In addition, the following commands can only be used at the login screen: ! cd ch connect create \ No newline at end of file --- 4211,4214 ---- In addition, the following commands can only be used at the login screen: ! cd ch connect create *** 1_8_2p3/game/txt/hlp/pennflag.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/pennflag.hlp Wed May 16 22:19:20 2007 *************** *** 429,434 **** --- 429,440 ---- When set on a thing or room, this flag activates the ^ listen patterns on the object. Objects which have ^ listen patterns but are not set MONITOR do not check those patterns. + + When using the LISTEN Attribute Tree, you must set the Root Attribute + !NO_COMMAND. By default this Attribute/Attribute Root has been set + NO_COMMAND by the system. Attributes which are set HALT or NO_COMMAND + will not be evaluated for purposes of the ^ listen patterns + & MORTAL The MORTAL flag is no longer available in PennMUSH. Please see help changes for more information. *** 1_8_2p3/game/txt/hlp/pennfunc.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/pennfunc.hlp Wed May 16 22:19:20 2007 *************** *** 372,379 **** & ALIGN2 Examples: ! > &line me=align(<5 10 20,\([left(xget(%0,sex),1)]\),name(%0),name(%L)) ! > th iter(lwho(),u(line,##)) (M) Walker Tree (F) Jane Doe Nowhere --- 372,379 ---- & ALIGN2 Examples: ! > &line me=align(<5 10 20,\([left(xget(%0,sex),1)]\),name(%0),name(loc(%0))) ! > th iter(lwho(),u(line,##),%b,%r) (M) Walker Tree (F) Jane Doe Nowhere *** 1_8_2p3/game/txt/hlp/pennv181.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/pennv181.hlp Wed May 16 22:19:20 2007 *************** *** 1,6 **** & 1.8.1p10 Version 1.8.1 patchlevel 10 September 13, 2006 - Fixes: * Cleaned up some compiler warnings. [SW] * The AAHEAR and AMHEAR attribute flags work on listening parents. --- 1,5 ---- *************** *** 10,16 **** * Win32 lacks the LC_MESSAGES setlocale() category. Reported by Intrevis. * Trying to ignore signals could crash on Win32. Reported by Intrevis. * Fixed parse errors in non-C99 compilers. Reported by Intrevis. ! * Help fixes by Talvo, Sketch. * Fixes for 64-bit platforms [SW] * @dump/paranoid produced corrupt databases. Reported by Marvin@M*U*S*H. [SW] --- 9,15 ---- * Win32 lacks the LC_MESSAGES setlocale() category. Reported by Intrevis. * Trying to ignore signals could crash on Win32. Reported by Intrevis. * Fixed parse errors in non-C99 compilers. Reported by Intrevis. ! * Help fixes by Talvo, Sketch * Fixes for 64-bit platforms [SW] * @dump/paranoid produced corrupt databases. Reported by Marvin@M*U*S*H. [SW] *************** *** 28,34 **** an entry. [SW] * The above is used in db.c, function.c and plyrlist.c [SW] * @config compile reports if MySQL support is present. (This does not ! mean the game is configured to use it.) * restart copies log files from the last time the mush was running to game/save/ instead of deleting them. [SW] --- 27,33 ---- an entry. [SW] * The above is used in db.c, function.c and plyrlist.c [SW] * @config compile reports if MySQL support is present. (This does not ! mean the game is configured to use it.) [SW] * restart copies log files from the last time the mush was running to game/save/ instead of deleting them. [SW] *************** *** 171,177 **** named captures. [SW] * NT_TCP code has been removed from the server. It was deemed less useful than keeping the networking code unitary and ! < the ability to @shutdown/reboot. Patch by Nathan Baum. Flags: * New LOUD flag (admin-settable) causes an object to bypass speech (including chat) and interaction locks. Admin and others --- 170,176 ---- named captures. [SW] * NT_TCP code has been removed from the server. It was deemed less useful than keeping the networking code unitary and ! the ability to @shutdown/reboot. Patch by Nathan Baum. Flags: * New LOUD flag (admin-settable) causes an object to bypass speech (including chat) and interaction locks. Admin and others *** 1_8_2p3/game/txt/hlp/pennv182.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/pennv182.hlp Wed May 16 22:19:20 2007 *************** *** 1,4 **** ! & 1.8.2p3 & changes This is a list of changes in this patchlevel which are probably of interest to players. More information about new commands and functions --- 1,4 ---- ! & 1.8.2p4 & changes This is a list of changes in this patchlevel which are probably of interest to players. More information about new commands and functions *************** *** 11,16 **** --- 11,59 ---- A list of the patchlevels associated with each release can be read in 'help patchlevels'. + Version 1.8.2 patchlevel 4 May 16, 2007 + + Minor changes: + * speak() uses accented names. Sketch. + * config() no longer lists options that can't be set + with @config/set. Suggested by Trispis. [SW] + * 'page foo\=bar' pages the last person you paged. Fix by Nathan + Baum. + * Receipt of a SIGUSR1 (Causing a shutdown/reboot) is explictly + logged. Suggested by Interloper. [SW] + * @wipe reports the number of attributes deleted. [183] + + Fixes: + * You can no longer save objects slated to be destroyed + by using @set foo=!GOING (The help file for GOING now tells + the truth) Reported by Cooee. [SW] + * Useless variable in real_unparse() removed. Reported by + Taladan. [SW] + * 'make portmsg' works, and portmsg.c rewritten to current + Penn standards. [SW] + * case() would replace #$ in the default argument, contrary + to the help file. Reported by Talvo. [SW] + * Memory leak in grep(). [SW] + * Quotes can be around the player name on the login screen + always, instead of just when player_name_spaces was + on. Suggested by Dan Widdis. [SW] + * '{think foo} bar' exhibited odd behavior. [GM] + * 'make test' wouldn't work right unless '.' was in you path. + Fix by Nathan Baum. + * stdin and stdout weren't getting closed, potentially causing + problems when trying to log out of a shell after starting + a mush. Reported by K Moon. [SW] + * NetBSD compile and general warning fixes. [SW] + * Favor difftime(3) over subtraction of time_t variables. [SW] + * Clarification of attribute trees in HELP @WIPE. Suggested by + Talvo. + * Loading a db with empty attributes used as the roots of + attribute trees didn't work if empty_attrs is set to no. + Reported by Kevin. [SW] + * Bugs in wiping attribute trees with attributes the wiper + doesn't have permission to delete fixed. [SW] + + & 1.8.2p3 Version 1.8.2 patchlevel 3 March 11, 2007 Fixes: *************** *** 53,59 **** * Looking at an object used the looker, not the lookee, as the origin of the name for @ahear/@aahear/@amhear. [SW] * Fixed the distribution of random numbers with a huge range. Reported ! by Luke. & 1.8.2p1 Version 1.8.2 patchlevel 1 November 26, 2006 --- 96,102 ---- * Looking at an object used the looker, not the lookee, as the origin of the name for @ahear/@aahear/@amhear. [SW] * Fixed the distribution of random numbers with a huge range. Reported ! by Luke. & 1.8.2p1 Version 1.8.2 patchlevel 1 November 26, 2006 *** 1_8_2p3/game/txt/hlp/pennvOLD.hlp Sun Mar 11 20:21:15 2007 --- 1_8_2p4/game/txt/hlp/pennvOLD.hlp Wed May 16 22:19:20 2007 *************** *** 4417,4423 **** For information on a specific patchlevel of one of the versions listed, type 'help p'. For example, 'help 1.7.2p3' ! 1.8.2: 0, 1 1.8.1: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 1.8.0: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, --- 4417,4423 ---- For information on a specific patchlevel of one of the versions listed, type 'help p'. For example, 'help 1.7.2p3' ! 1.8.2: 0, 1, 2, 3, 4 1.8.1: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 1.8.0: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 1.7.7: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, *** 1_8_2p3/hdrs/attrib.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/attrib.h Wed May 16 22:19:21 2007 *************** *** 1,3 **** --- 1,9 ---- + /** + * \file attrib.h + * + * \brief Attribute-related prototypes and constants. + */ + #ifndef _ATTRIB_H #define _ATTRIB_H *************** *** 10,16 **** */ struct attr { char const *name; /**< Name of attribute */ ! int flags; /**< Attribute flags */ chunk_reference_t data; /**< The attribute's value, compressed */ dbref creator; /**< The attribute's creator's dbref */ ATTR *next; /**< Pointer to next attribute in list */ --- 16,22 ---- */ struct attr { char const *name; /**< Name of attribute */ ! unsigned int flags; /**< Attribute flags */ chunk_reference_t data; /**< The attribute's value, compressed */ dbref creator; /**< The attribute's creator's dbref */ ATTR *next; /**< Pointer to next attribute in list */ *************** *** 30,44 **** extern void attr_init_postconfig(void); /* From attrib.c */ extern int good_atr_name(char const *s); extern ATTR *atr_match(char const *string); extern ATTR *atr_sub_branch(ATTR *branch); extern void atr_new_add(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, int flags, ! unsigned char derefs); ! extern int atr_add(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, int flags); ! extern int atr_clr(dbref thing, char const *atr, dbref player); extern ATTR *atr_get(dbref thing, char const *atr); extern ATTR *atr_get_noparent(dbref thing, char const *atr); typedef int (*aig_func) (dbref, dbref, dbref, const char *, ATTR *, void *); --- 36,65 ---- extern void attr_init_postconfig(void); /* From attrib.c */ + + /** atr_add(), atr_clr() error codes */ + typedef enum { + AE_OKAY = 0, /**< Success */ + AE_ERROR = -1, /**< general failure */ + AE_SAFE = -2, /**< attempt to overwrite a safe attribute */ + AE_BADNAME = -3, /**< invalid name */ + AE_TOOMANY = -4, /**< too many attribs */ + AE_TREE = -5, /**< unable to delete/create entire tree */ + AE_NOTFOUND = -6 /** No such attribute */ + } atr_err; + + extern int good_atr_name(char const *s); extern ATTR *atr_match(char const *string); extern ATTR *atr_sub_branch(ATTR *branch); extern void atr_new_add(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, ! unsigned int flags, unsigned char derefs); ! extern atr_err atr_add(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, ! unsigned int flags); ! extern atr_err atr_clr(dbref thing, char const *atr, dbref player); ! extern atr_err wipe_atr(dbref thing, char const *atr, dbref player); extern ATTR *atr_get(dbref thing, char const *atr); extern ATTR *atr_get_noparent(dbref thing, char const *atr); typedef int (*aig_func) (dbref, dbref, dbref, const char *, ATTR *, void *); *************** *** 49,55 **** extern int atr_pattern_count(dbref player, dbref thing, const char *name, int doparent, int mortal); extern ATTR *atr_complete_match(dbref player, char const *atr, dbref privs); ! extern void atr_free(dbref thing); extern void atr_cpy(dbref dest, dbref source); extern char const *convert_atr(int oldatr); extern int atr_comm_match(dbref thing, dbref player, int type, int end, --- 70,76 ---- extern int atr_pattern_count(dbref player, dbref thing, const char *name, int doparent, int mortal); extern ATTR *atr_complete_match(dbref player, char const *atr, dbref privs); ! extern void atr_free_all(dbref thing); extern void atr_cpy(dbref dest, dbref source); extern char const *convert_atr(int oldatr); extern int atr_comm_match(dbref thing, dbref player, int type, int end, *************** *** 58,64 **** extern int one_comm_match(dbref thing, dbref player, const char *atr, const char *str); extern int do_set_atr(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, int flags); extern void do_atrlock(dbref player, char const *arg1, char const *arg2); extern void do_atrchown(dbref player, char const *arg1, char const *arg2); extern int string_to_atrflag(dbref player, const char *p); --- 79,85 ---- extern int one_comm_match(dbref thing, dbref player, const char *atr, const char *str); extern int do_set_atr(dbref thing, char const *RESTRICT atr, ! char const *RESTRICT s, dbref player, unsigned int flags); extern void do_atrlock(dbref player, char const *arg1, char const *arg2); extern void do_atrchown(dbref player, char const *arg1, char const *arg2); extern int string_to_atrflag(dbref player, const char *p); *************** *** 77,117 **** __attribute_malloc__; /* possible attribute flags */ ! #define AF_ODARK 0x1 /* OBSOLETE! Leave here but don't use */ ! #define AF_INTERNAL 0x2 /* no one can see it or set it */ ! #define AF_WIZARD 0x4 /* Wizard only can change it */ ! #define AF_NUKED 0x8 /* OBSOLETE! Leave here but don't use */ ! #define AF_LOCKED 0x10 /* Only creator of attrib can change it. */ ! #define AF_NOPROG 0x20 /* won't be searched for $ commands. */ ! #define AF_MDARK 0x40 /* Only wizards can see it */ ! #define AF_PRIVATE 0x80 /* Children don't inherit it */ ! #define AF_NOCOPY 0x100 /* atr_cpy (for @clone) doesn't copy it */ ! #define AF_VISUAL 0x200 /* Everyone can see this attribute */ ! #define AF_REGEXP 0x400 /* Match $/^ patterns using regexps */ ! #define AF_CASE 0x800 /* Match $/^ patterns case-sensitive */ ! #define AF_SAFE 0x1000 /* This attribute may not be modified */ ! #define AF_STATIC 0x10000 /* OBSOLETE! Leave here but don't use */ ! #define AF_COMMAND 0x20000 /* INTERNAL: value starts with $ */ ! #define AF_LISTEN 0x40000 /* INTERNAL: value starts with ^ */ ! #define AF_NODUMP 0x80000 /* INTERNAL: attribute is not saved */ ! #define AF_LISTED 0x100000 /* INTERNAL: Used in @list attribs */ ! #define AF_PREFIXMATCH 0x200000 /* Subject to prefix-matching */ ! #define AF_VEILED 0x400000 /* On ex, show presence, not value */ ! #define AF_DEBUG 0x800000 /* Show debug when evaluated */ ! #define AF_NEARBY 0x1000000 /* Override AF_VISUAL if remote */ ! #define AF_PUBLIC 0x2000000 /* Override SAFER_UFUN */ ! #define AF_ANON 0x4000000 /* INTERNAL: Attribute doesn't really exist in the database */ ! #define AF_NONAME 0x8000000 /* No name in did_it */ ! #define AF_NOSPACE 0x10000000 /* No space in did_it */ ! #define AF_MHEAR 0x20000000 /* ^-listens can be triggered by %! */ ! #define AF_AHEAR 0x40000000 /* ^-listens can be triggered by anyone */ ! /* external predefined attributes. */ ! extern ATTR attr[]; ! /* external @wipe indicator (changes atr_clr() behaviour) */ ! extern int we_are_wiping; #define AL_ATTR(alist) (alist) #define AL_NAME(alist) ((alist)->name) --- 98,142 ---- __attribute_malloc__; /* possible attribute flags */ ! #define AF_EMPTY_FLAGS 0x0 /**< No flag at all */ ! #define AF_ODARK 0x1 /**< OBSOLETE! Leave here but don't use */ ! #define AF_INTERNAL 0x2 /**< no one can see it or set it */ ! #define AF_WIZARD 0x4 /**< Wizard only can change it */ ! #define AF_NUKED 0x8 /**< OBSOLETE! Leave here but don't use */ ! #define AF_LOCKED 0x10 /**< Only creator of attrib can change it. */ ! #define AF_NOPROG 0x20 /**< won't be searched for $ commands. */ ! #define AF_MDARK 0x40 /**< Only wizards can see it */ ! #define AF_PRIVATE 0x80 /**< Children don't inherit it */ ! #define AF_NOCOPY 0x100 /**< atr_cpy (for @clone) doesn't copy it */ ! #define AF_VISUAL 0x200 /**< Everyone can see this attribute */ ! #define AF_REGEXP 0x400 /**< Match $/^ patterns using regexps */ ! #define AF_CASE 0x800 /**< Match $/^ patterns case-sensitive */ ! #define AF_SAFE 0x1000 /**< This attribute may not be modified */ ! #define AF_ROOT 0x2000 /**< Root of an attribute tree */ ! #define AF_UNDEF1 0x4000 /**< Undefined; reserved for a future flag */ ! #define AF_UNDEF2 0x8000 /**< Undefined; reserved for a future flag */ ! #define AF_STATIC 0x10000 /**< OBSOLETE! Leave here but don't use */ ! #define AF_COMMAND 0x20000 /**< INTERNAL: value starts with $ */ ! #define AF_LISTEN 0x40000 /**< INTERNAL: value starts with ^ */ ! #define AF_NODUMP 0x80000 /**< INTERNAL: attribute is not saved */ ! #define AF_LISTED 0x100000 /**< INTERNAL: Used in @list attribs */ ! #define AF_PREFIXMATCH 0x200000 /**< Subject to prefix-matching */ ! #define AF_VEILED 0x400000 /**< On ex, show presence, not value */ ! #define AF_DEBUG 0x800000 /**< Show debug when evaluated */ ! #define AF_NEARBY 0x1000000 /**< Override AF_VISUAL if remote */ ! #define AF_PUBLIC 0x2000000 /**< Override SAFER_UFUN */ ! #define AF_ANON 0x4000000 /**< INTERNAL: Attribute doesn't really exist in the database */ ! #define AF_NONAME 0x8000000 /**< No name in did_it */ ! #define AF_NOSPACE 0x10000000 /**< No space in did_it */ ! #define AF_MHEAR 0x20000000 /**< ^-listens can be triggered by %! */ ! #define AF_AHEAR 0x40000000 /**< ^-listens can be triggered by anyone */ ! #define AF_UNDEF3 0x80000000 /**< Undefined; reserved for a future flag */ ! #define AF_MAXVAL 0x100000000 /**< Largest attribute flag value. */ ! /*** external predefined attributes. */ ! extern ATTR attr[]; #define AL_ATTR(alist) (alist) #define AL_NAME(alist) ((alist)->name) *************** *** 121,130 **** #define AL_FLAGS(alist) ((alist)->flags) #define AL_DEREFS(alist) ((alist)->data?chunk_derefs((alist)->data):0) ! /* Errors from ok_player_alias */ #define OPAE_SUCCESS 1 #define OPAE_INVALID -1 #define OPAE_TOOMANY -2 #define OPAE_NULL -3 #endif /* __ATTRIB_H */ --- 146,159 ---- #define AL_FLAGS(alist) ((alist)->flags) #define AL_DEREFS(alist) ((alist)->data?chunk_derefs((alist)->data):0) ! /** Errors from ok_player_alias */ ! /** Success */ #define OPAE_SUCCESS 1 + /** Invalid alias */ #define OPAE_INVALID -1 + /** Too many aliases already set */ #define OPAE_TOOMANY -2 + /** Null alias */ #define OPAE_NULL -3 #endif /* __ATTRIB_H */ *** 1_8_2p3/hdrs/chunk.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/chunk.h Wed May 16 22:19:21 2007 *************** *** 1,5 **** ! /* This must be first, otherwise dbref will be undefined */ ! #include "attrib.h" #ifndef _CHUNK_H_ #define _CHUNK_H_ --- 1,4 ---- ! /* Must be included after mushtype.h to get dbref typedef */ #ifndef _CHUNK_H_ #define _CHUNK_H_ *** 1_8_2p3/hdrs/log.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/log.h Wed May 16 22:19:21 2007 *************** *** 14,20 **** /* From log.c */ extern void start_all_logs(void); extern void end_all_logs(void); ! extern void redirect_stderr(void); extern void WIN32_CDECL do_log (int logtype, dbref player, dbref object, const char *fmt, ...) __attribute__ ((__format__(__printf__, 4, 5))); --- 14,20 ---- /* From log.c */ extern void start_all_logs(void); extern void end_all_logs(void); ! extern void redirect_streams(void); extern void WIN32_CDECL do_log (int logtype, dbref player, dbref object, const char *fmt, ...) __attribute__ ((__format__(__printf__, 4, 5))); *** 1_8_2p3/hdrs/mushtype.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/mushtype.h Wed May 16 22:19:21 2007 *************** *** 1,11 **** #ifndef MUSH_TYPES_H #define MUSH_TYPES_H #include "copyrite.h" - #include "options.h" - #include - #ifdef WIN32 - #include - #endif #ifdef HAS_OPENSSL #include #endif --- 1,6 ---- *** 1_8_2p3/hdrs/parse.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/parse.h Wed May 16 22:19:21 2007 *************** *** 52,58 **** ! /* The following routines all take varoius arguments, and return * string representations of same. The string representations * are stored in static buffers, so the next call to each function * will destroy any old string that was there. --- 52,58 ---- ! /* The following routines all take various arguments, and return * string representations of same. The string representations * are stored in static buffers, so the next call to each function * will destroy any old string that was there. *************** *** 67,73 **** char *unparse_types(int type); /* The following routines all take strings as arguments, and return ! * true iff the string is a valid representation of the appropriate type. */ int is_dbref(char const *str); int is_objid(char const *str); --- 67,73 ---- char *unparse_types(int type); /* The following routines all take strings as arguments, and return ! * true if the string is a valid representation of the appropriate type. */ int is_dbref(char const *str); int is_objid(char const *str); *************** *** 205,211 **** * and PE_FUNCTION_CHECK must be active for function evaluation to occur. * * PE_FUNCTION_MANDATORY causes an error to be reported if a function call ! * is attempted for a non-existant function. Otherwise, the function call * is not evaluated, but rather treated as normal text. * * PE_LITERAL prevents { and [ from being recognized and causing recursion. --- 205,211 ---- * and PE_FUNCTION_CHECK must be active for function evaluation to occur. * * PE_FUNCTION_MANDATORY causes an error to be reported if a function call ! * is attempted for a non-existent function. Otherwise, the function call * is not evaluated, but rather treated as normal text. * * PE_LITERAL prevents { and [ from being recognized and causing recursion. *************** *** 232,238 **** /* These represent '\0', '}', ']', ')', ',', ';', '=', and ' ', respectively. * If the character corresponding to a set flag is encountered, then * process_expression() will exit, with *str pointing at the terminating ! * charater. '\0' is always a terminating character. * * PT_DEFAULT, below, is provided as syntactic sugar. */ --- 232,238 ---- /* These represent '\0', '}', ']', ')', ',', ';', '=', and ' ', respectively. * If the character corresponding to a set flag is encountered, then * process_expression() will exit, with *str pointing at the terminating ! * character. '\0' is always a terminating character. * * PT_DEFAULT, below, is provided as syntactic sugar. */ *** 1_8_2p3/hdrs/version.h Sun Mar 11 20:21:16 2007 --- 1_8_2p4/hdrs/version.h Wed May 16 22:19:21 2007 *************** *** 1,4 **** #define VERSION "1.8.2" ! #define PATCHLEVEL "3" ! #define PATCHDATE "[03/11/2007]" ! #define NUMVERSION 1008002003 --- 1,4 ---- #define VERSION "1.8.2" ! #define PATCHLEVEL "4" ! #define PATCHDATE "[04/16/2007]" ! #define NUMVERSION 1008002004 *** 1_8_2p3/src/Makefile.SH Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/Makefile.SH Wed May 16 22:19:20 2007 *************** *** 211,217 **** (set +e; for file in *.dst *.c ../hdrs/*.h ; do echo $$file; \ /usr/bin/expand $$file > tmpfile; mv -f tmpfile $$file; \ /usr/bin/indent -npro -kr -ci2 -ss -psl -ip4 -i2 -cs -l80 -lc75 \ ! -T ATRALIAS -T DESC -T CNode -T CONF -T BQUE -T FUN \ -T NVAL -T i_rec -T f_rec -T USERFN_ENTRY -T PRIV -T FLAG \ -T FLAGENT -T FLAG_ALIAS -T tlist -T u -T stat -T tcheck -T ATTR \ -T ALIST -T CHTAB -T FBLKHDR -T FBLOCK -T OPTTAB -T dbref \ --- 211,217 ---- (set +e; for file in *.dst *.c ../hdrs/*.h ; do echo $$file; \ /usr/bin/expand $$file > tmpfile; mv -f tmpfile $$file; \ /usr/bin/indent -npro -kr -ci2 -ss -psl -ip4 -i2 -cs -l80 -lc75 \ ! -T atr_err -T ATRALIAS -T DESC -T CNode -T CONF -T BQUE -T FUN \ -T NVAL -T i_rec -T f_rec -T USERFN_ENTRY -T PRIV -T FLAG \ -T FLAGENT -T FLAG_ALIAS -T tlist -T u -T stat -T tcheck -T ATTR \ -T ALIST -T CHTAB -T FBLKHDR -T FBLOCK -T OPTTAB -T dbref \ *************** *** 235,242 **** test_compress: comp_h.c $(CC) $(CFLAGS) -o test_compress -DSTANDALONE comp_h.c ! portmsg: portmsg.c ! $(CC) $(CFLAGS) -o portmsg portmsg.c $(LIBS) # Some dependencies that make depend doesn't handle well compress.o: comp_h.c comp_w.c comp_w8.c --- 235,243 ---- test_compress: comp_h.c $(CC) $(CFLAGS) -o test_compress -DSTANDALONE comp_h.c ! portmsg: portmsg.c mysocket.c sig.o ! $(CC) $(CCFLAGS) -DINFOSLAVE -o portmsg portmsg.c mysocket.c sig.o \ ! $(LDFLAGS) $(LIBS) # Some dependencies that make depend doesn't handle well compress.o: comp_h.c comp_w.c comp_w8.c *** 1_8_2p3/src/atr_tab.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/atr_tab.c Wed May 16 22:19:20 2007 *************** *** 84,89 **** --- 84,90 ---- {"nospace", 's', AF_NOSPACE, AF_NOSPACE}, {"amhear", 'M', AF_MHEAR, AF_MHEAR}, {"aahear", 'A', AF_AHEAR, AF_AHEAR}, + {"root", '`', AF_ROOT, AF_ROOT}, {NULL, '\0', 0, 0} }; *** 1_8_2p3/src/attrib.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/attrib.c Wed May 16 22:19:20 2007 *************** *** 31,45 **** #pragma warning( disable : 4761) /* disable warning re conversion */ #endif - /** Attribute error - too many attribs */ - #define AE_TOOMANY -4 - /** Attribute error - invalid name */ - #define AE_BADNAME -3 - /** Attribute error - attempt to overwrite a safe attribute */ - #define AE_SAFE -2 - /** Attribute error - general failure */ - #define AE_ERROR -1 - /** A string tree of attribute names in use, to save us memory since * many are duplicated. */ --- 31,36 ---- *************** *** 48,60 **** extern PRIV attr_privs_set[]; extern PRIV attr_privs_view[]; ! /** A flag to show if we're in the middle of a @wipe (this changes ! * behaviour for atr_clr()). Yes, this is gross and ugly, but it ! * seemed like a better idea than propogating signature changes ! * for atr_clr() and do_set_atr() through the entire codebase. If ! * you come up with a better way, PLEASE fix this... ! */ ! int we_are_wiping; /** A string to hold the name of a missing prefix branch, set by * can_write_attr_internal. Again, gross and ugly. Please fix. --- 39,47 ---- extern PRIV attr_privs_set[]; extern PRIV attr_privs_view[]; ! static int real_atr_clr(dbref thinking, char const *atr, dbref player, ! int we_are_wiping); ! /** A string to hold the name of a missing prefix branch, set by * can_write_attr_internal. Again, gross and ugly. Please fix. *************** *** 75,85 **** ATTR atrs[ATTRS_PER_PAGE]; /**< Array of attribute structures */ } ATTRPAGE; ! static ATTR *atr_free_list; ! static ATTR *get_atr_free_list(void); static ATTR *find_atr_pos_in_list(ATTR ***pos, char const *name); ! static int can_create_attr(dbref player, dbref obj, char const *atr_name, ! int flags); static ATTR *find_atr_in_list(ATTR *atr, char const *name); static ATTR *atr_get_with_parent(dbref obj, char const *atrname, dbref *parent); --- 62,75 ---- ATTR atrs[ATTRS_PER_PAGE]; /**< Array of attribute structures */ } ATTRPAGE; ! static ATTR *atr_free_list = NULL; ! static ATTR *alloc_atr(void); ! static ATTR *pop_free_list(void); ! static void push_free_list(ATTR *); ! static void atr_free_one(ATTR *); static ATTR *find_atr_pos_in_list(ATTR ***pos, char const *name); ! static atr_err can_create_attr(dbref player, dbref obj, char const *atr_name, ! unsigned int flags); static ATTR *find_atr_in_list(ATTR *atr, char const *name); static ATTR *atr_get_with_parent(dbref obj, char const *atrname, dbref *parent); *************** *** 180,186 **** return NULL; } ! /** Find the place to insert/delete an attribute with the specified name. * \param pos a pointer to the ATTR ** holding the list position * \param name the attribute name to look for * \return the matching attribute, or NULL if no matching attribute --- 170,176 ---- return NULL; } ! /** Find the place to insert an attribute with the specified name. * \param pos a pointer to the ATTR ** holding the list position * \param name the attribute name to look for * \return the matching attribute, or NULL if no matching attribute *************** *** 411,422 **** #define set_default_flags(atr,flags) \ do { \ ATTR *std = atr_match(AL_NAME((atr))); \ ! if (std && !strcmp(AL_NAME(std), AL_NAME((atr)))) { \ AL_FLAGS(atr) = AL_FLAGS(std); \ } else { \ ! AL_FLAGS(atr) = 0; \ ! if (flags != NOTHING) \ ! AL_FLAGS(atr) |= flags; \ } \ } while (0) --- 401,410 ---- #define set_default_flags(atr,flags) \ do { \ ATTR *std = atr_match(AL_NAME((atr))); \ ! if (std && !(flags) && !strcmp(AL_NAME(std), AL_NAME((atr)))) { \ AL_FLAGS(atr) = AL_FLAGS(std); \ } else { \ ! AL_FLAGS(atr) = flags; \ } \ } while (0) *************** *** 427,438 **** * \param player the player trying to do the write. * \param obj the object targetted for the write. * \param atr the attribute being interrogated. ! * \param flags the default flags to add to the attribute. * \retval 0 if the player cannot write the attribute. * \retval 1 if the player can write the attribute. */ static int ! can_create_attr(dbref player, dbref obj, char const *atr_name, int flags) { char *p; ATTR tmpatr, *atr; --- 415,428 ---- * \param player the player trying to do the write. * \param obj the object targetted for the write. * \param atr the attribute being interrogated. ! * \param flags the default flags to add to the attribute. ! * 0 for default flags if it's a builtin attribute. * \retval 0 if the player cannot write the attribute. * \retval 1 if the player can write the attribute. */ static int ! can_create_attr(dbref player, dbref obj, char const *atr_name, ! unsigned int flags) { char *p; ATTR tmpatr, *atr; *************** *** 483,489 **** return AE_TOOMANY; } ! return 1; } /*======================================================================*/ --- 473,479 ---- return AE_TOOMANY; } ! return AE_OKAY; } /*======================================================================*/ *************** *** 505,516 **** return NULL; /* allocate a new page, if needed */ ! ptr = get_atr_free_list(); ! atr_free_list = AL_NEXT(ptr); /* initialize atr */ AL_NAME(ptr) = name; ptr->data = NULL_CHUNK_REFERENCE; /* link it in */ ins = &List(thing); --- 495,510 ---- return NULL; /* allocate a new page, if needed */ ! ptr = pop_free_list(); ! if (ptr == NULL) { ! st_delete(name, &atr_names); ! return NULL; ! } /* initialize atr */ AL_NAME(ptr) = name; ptr->data = NULL_CHUNK_REFERENCE; + AL_FLAGS(ptr) = 0; /* link it in */ ins = &List(thing); *************** *** 536,546 **** */ void atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, int flags, unsigned char derefs) { ATTR *ptr; ! if (!EMPTY_ATTRS && !*s) return; /* Don't fail on a bad name, but do log it */ --- 530,541 ---- */ void atr_new_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, unsigned int flags, unsigned char derefs) { ATTR *ptr; + char *p, root_name[ATTRIBUTE_NAME_LIMIT + 1]; ! if (!EMPTY_ATTRS && !*s && !(flags & AF_ROOT)) return; /* Don't fail on a bad name, but do log it */ *************** *** 552,558 **** if (!ptr) return; ! AL_FLAGS(ptr) = (flags != NOTHING) ? flags : 0; AL_FLAGS(ptr) &= ~AF_COMMAND & ~AF_LISTEN; AL_CREATOR(ptr) = player; --- 547,579 ---- if (!ptr) return; ! strcpy(root_name, atr); ! if ((p = strrchr(root_name, '`'))) { ! ATTR *root = NULL; ! *p = '\0'; ! root = find_atr_in_list(List(thing), root_name); ! if (!root) { ! do_rawlog(LT_ERR, T("Missing root attribute '%s' on object #%d!\n"), ! root_name, thing); ! root = create_atr(thing, root_name); ! set_default_flags(root, 0); ! AL_FLAGS(root) |= AF_ROOT; ! AL_CREATOR(root) = player; ! if (!EMPTY_ATTRS) { ! unsigned char *t = compress(" "); ! if (!t) { ! mush_panic(T("Unable to allocate memory in atr_new_add()!")); ! } ! root->data = chunk_create(t, u_strlen(t), 0); ! free(t); ! } ! } else { ! if (!AL_FLAGS(root) & AF_ROOT) /* Upgrading old database */ ! AL_FLAGS(root) |= AF_ROOT; ! } ! } ! ! AL_FLAGS(ptr) = flags; AL_FLAGS(ptr) &= ~AF_COMMAND & ~AF_LISTEN; AL_CREATOR(ptr) = player; *************** *** 563,568 **** --- 584,590 ---- unsigned char *t = compress(s); if (!t) return; + ptr->data = chunk_create(t, u_strlen(t), derefs); free(t); *************** *** 583,599 **** * \param atr name of the attribute to set. * \param s value of the attribute to set. * \param player the attribute creator. ! * \param flags bitmask of attribute flags for this attribute. ! * \retval AE_BADNAME invalid attribute name. ! * \retval AE_SAFE attempt to overwrite a SAFE attribute. ! * \retval AE_ERROR general failure. ! * \retval 1 success. */ ! int atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, int flags) { ! ATTR *ptr; char *p; if (!s || (!EMPTY_ATTRS && !*s)) --- 605,619 ---- * \param atr name of the attribute to set. * \param s value of the attribute to set. * \param player the attribute creator. ! * \param flags bitmask of attribute flags for this attribute. 0 will use ! * default. ! * \return AE_OKAY or an AE_* error code. */ ! atr_err atr_add(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, unsigned int flags) { ! ATTR *ptr, *root = NULL; char *p; if (!s || (!EMPTY_ATTRS && !*s)) *************** *** 613,620 **** /* make a new atr, if needed */ if (!ptr) { ! int res = can_create_attr(player, thing, atr, flags); ! if (res < 0) return res; strcpy(missing_name, atr); --- 633,640 ---- /* make a new atr, if needed */ if (!ptr) { ! atr_err res = can_create_attr(player, thing, atr, flags); ! if (res != AE_OKAY) return res; strcpy(missing_name, atr); *************** *** 622,650 **** for (p = strchr(missing_name, '`'); p; p = strchr(p + 1, '`')) { *p = '\0'; ! ptr = find_atr_in_list(ptr, missing_name); ! if (!ptr) { ! ptr = create_atr(thing, missing_name); ! if (!ptr) ! return AE_ERROR; /* update modification time here, because from now on, * we modify even if we fail */ ! if (!IsPlayer(thing) && !AF_Nodump(ptr)) ModTime(thing) = mudtime; ! set_default_flags(ptr, flags); ! AL_FLAGS(ptr) &= ~AF_COMMAND & ~AF_LISTEN; ! AL_CREATOR(ptr) = Owner(player); if (!EMPTY_ATTRS) { unsigned char *t = compress(" "); ! if (!t) ! return AE_ERROR; ! ptr->data = chunk_create(t, u_strlen(t), 0); free(t); } ! } *p = '`'; } --- 642,672 ---- for (p = strchr(missing_name, '`'); p; p = strchr(p + 1, '`')) { *p = '\0'; ! root = find_atr_in_list(ptr, missing_name); ! if (!root) { ! root = create_atr(thing, missing_name); ! if (!root) ! return AE_TREE; /* update modification time here, because from now on, * we modify even if we fail */ ! if (!IsPlayer(thing) && !AF_Nodump(root)) ModTime(thing) = mudtime; ! set_default_flags(root, flags); ! AL_FLAGS(root) &= ~AF_COMMAND & ~AF_LISTEN; ! AL_FLAGS(root) |= AF_ROOT; ! AL_CREATOR(root) = Owner(player); if (!EMPTY_ATTRS) { unsigned char *t = compress(" "); ! if (!t) ! mush_panic(T("Unable to allocate memory in atr_add()!")); ! root->data = chunk_create(t, u_strlen(t), 0); free(t); } ! } else ! AL_FLAGS(root) |= AF_ROOT; *p = '`'; } *************** *** 685,691 **** AL_FLAGS(ptr) |= AF_LISTEN; } ! return 1; } /** Remove an attribute from an object. --- 707,758 ---- AL_FLAGS(ptr) |= AF_LISTEN; } ! return AE_OKAY; ! } ! ! ! /** Remove all child attributes from root attribute that can be. ! * \param player object doing a @wipe. ! * \param thing object being @wiped. ! * \param root root of attribute tree. ! * \return 1 if all children were deleted, 0 if some were left. ! */ ! static int ! atr_clear_children(dbref player, dbref thing, ATTR *root) ! { ! ATTR *sub, *next = NULL, *prev; ! int skipped = 0; ! ! prev = root; ! ! for (sub = atr_sub_branch(root); ! sub && string_prefix(AL_NAME(sub), AL_NAME(root)); sub = next) { ! if (AL_FLAGS(sub) & AF_ROOT) { ! if (!atr_clear_children(player, thing, sub)) { ! skipped++; ! next = AL_NEXT(sub); ! prev = sub; ! continue; ! } ! } ! ! next = AL_NEXT(sub); ! ! if (!Can_Write_Attr(player, thing, sub)) { ! skipped++; ! prev = sub; ! continue; ! } ! ! /* Can safely delete attribute. */ ! AL_NEXT(prev) = next; ! atr_free_one(sub); ! AttrCount(thing)--; ! ! } ! ! return !skipped; ! } /** Remove an attribute from an object. *************** *** 694,760 **** * \param thing object to clear attribute from. * \param atr name of attribute to remove. * \param player enactor attempting to remove attribute. ! * \retval 0 no attribute found to reset ! * \retval AE_SAFE attribute is safe ! * \retval AE_ERROR other failure */ ! int ! atr_clr(dbref thing, char const *atr, dbref player) { ! ATTR *ptr, **prev, *sub; ! size_t len; prev = &List(thing); ptr = find_atr_pos_in_list(&prev, atr); if (!ptr) ! return 0; if (ptr && AF_Safe(ptr)) return AE_SAFE; if (!Can_Write_Attr(player, thing, ptr)) return AE_ERROR; ! sub = atr_sub_branch(ptr); ! if (!we_are_wiping && sub) ! return AE_ERROR; ! if (!IsPlayer(thing) && !AF_Nodump(ptr)) ! ModTime(thing) = mudtime; ! *prev = AL_NEXT(ptr); ! if (ptr->data) ! chunk_delete(ptr->data); ! len = strlen(AL_NAME(ptr)); ! st_delete(AL_NAME(ptr), &atr_names); ! AL_NEXT(ptr) = atr_free_list; ! AL_FLAGS(ptr) = 0; ! atr_free_list = ptr; ! AttrCount(thing)--; - if (we_are_wiping && sub) { - while (*prev != sub) - prev = &AL_NEXT(*prev); - ptr = *prev; - while (ptr && strlen(AL_NAME(ptr)) > len && AL_NAME(ptr)[len] == '`') { - *prev = AL_NEXT(ptr); - - if (ptr->data) - chunk_delete(ptr->data); - st_delete(AL_NAME(ptr), &atr_names); - - AL_NEXT(ptr) = atr_free_list; - AL_FLAGS(ptr) = 0; - atr_free_list = ptr; - AttrCount(thing)--; ! ptr = *prev; ! } ! } ! return 1; } /** Retrieve an attribute from an object or its ancestors. --- 761,854 ---- * \param thing object to clear attribute from. * \param atr name of attribute to remove. * \param player enactor attempting to remove attribute. ! * \param we_are_wiping true if called by \@wipe. ! * \return AE_OKAY or AE_* error code. */ ! static atr_err ! real_atr_clr(dbref thing, char const *atr, dbref player, int we_are_wiping) { ! ATTR *ptr, **prev; ! int can_clear = 1; prev = &List(thing); ptr = find_atr_pos_in_list(&prev, atr); if (!ptr) ! return AE_NOTFOUND; if (ptr && AF_Safe(ptr)) return AE_SAFE; if (!Can_Write_Attr(player, thing, ptr)) return AE_ERROR; ! if ((AL_FLAGS(ptr) & AF_ROOT) && !we_are_wiping) ! return AE_TREE; ! /* We only hit this if wiping. */ ! if (AL_FLAGS(ptr) & AF_ROOT) ! can_clear = atr_clear_children(player, thing, ptr); ! ! if (can_clear) { ! char *p; ! char root_name[ATTRIBUTE_NAME_LIMIT + 1]; ! ! strcpy(root_name, AL_NAME(ptr)); ! ! if (!IsPlayer(thing) && !AF_Nodump(ptr)) ! ModTime(thing) = mudtime; ! *prev = AL_NEXT(ptr); ! atr_free_one(ptr); ! AttrCount(thing)--; ! ! /* If this was the only leaf of a tree, clear the AF_ROOT flag from ! * the parent. */ ! if ((p = strrchr(root_name, '`'))) { ! ATTR *root; ! *p = '\0'; ! root = find_atr_in_list(List(thing), root_name); ! *p = '`'; ! if (!root) { ! do_rawlog(LT_ERR, T("Attribute %s on object #%d lacks a parent!"), ! root_name, thing); ! } else { ! if (!atr_sub_branch(root)) ! AL_FLAGS(root) &= ~AF_ROOT; ! } ! } ! return AE_OKAY; ! } else ! return AE_TREE; ! } ! /** Remove an attribute from an object. ! * This function clears an attribute from an object. ! * Permission is denied if the attribute is a branch, not a leaf. ! * \param thing object to clear attribute from. ! * \param atr name of attribute to remove. ! * \param player enactor attempting to remove attribute. ! * \return AE_OKAY or an AE_* error code ! */ ! atr_err ! atr_clr(dbref thing, char const *atr, dbref player) ! { ! return real_atr_clr(thing, atr, player, 0); ! } ! /** \@wipe an attribute (And any leaves) from an object. ! * This function clears an attribute from an object. ! * \param thing object to clear attribute from. ! * \param atr name of attribute to remove. ! * \param player enactor attempting to remove attribute. ! * \return AE_OKAY or an AE_* error code. ! */ ! atr_err ! wipe_atr(dbref thing, char const *atr, dbref player) ! { ! return real_atr_clr(thing, atr, player, 1); } /** Retrieve an attribute from an object or its ancestors. *************** *** 1056,1062 **** * \param thing dbref of object */ void ! atr_free(dbref thing) { ATTR *ptr; --- 1150,1156 ---- * \param thing dbref of object */ void ! atr_free_all(dbref thing) { ATTR *ptr; *************** *** 1068,1080 **** while ((ptr = List(thing))) { List(thing) = AL_NEXT(ptr); ! ! if (ptr->data) ! chunk_delete(ptr->data); ! st_delete(AL_NAME(ptr), &atr_names); ! ! AL_NEXT(ptr) = atr_free_list; ! atr_free_list = ptr; } } --- 1162,1168 ---- while ((ptr = List(thing))) { List(thing) = AL_NEXT(ptr); ! atr_free_one(ptr); } } *************** *** 1534,1545 **** */ int do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, int flags) { ATTR *old; char name[BUFFER_LEN]; char tbuf1[BUFFER_LEN]; ! int res; int was_hearer; int was_listener; dbref contents; --- 1622,1633 ---- */ int do_set_atr(dbref thing, const char *RESTRICT atr, const char *RESTRICT s, ! dbref player, unsigned int flags) { ATTR *old; char name[BUFFER_LEN]; char tbuf1[BUFFER_LEN]; ! atr_err res; int was_hearer; int was_listener; dbref contents; *************** *** 1636,1651 **** was_hearer = Hearer(thing); was_listener = Listener(thing); res = ! s ? atr_add(thing, name, s, player, (flags & 0x02) ? AF_NOPROG : NOTHING) : atr_clr(thing, name, player); ! if (res == AE_SAFE) { notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."), name); return 0; ! } else if (res == AE_BADNAME) { ! notify(player, T("That's not a very good name for an attribute.")); return 0; ! } else if (res == AE_ERROR) { if (*missing_name) { if (s && (EMPTY_ATTRS || *s)) notify_format(player, T("You must set %s first."), missing_name); --- 1724,1755 ---- was_hearer = Hearer(thing); was_listener = Listener(thing); res = ! s ? atr_add(thing, name, s, player, ! (flags & 0x02) ? AF_NOPROG : AF_EMPTY_FLAGS) : atr_clr(thing, name, player); ! switch (res) { ! case AE_SAFE: notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."), name); return 0; ! case AE_TREE: ! if (!s) { ! notify_format(player, ! T ! ("Unable to remove '%s' because of a protected tree attribute."), ! name); ! return 0; ! } else { ! notify_format(player, ! T ! ("Unable to set '%s' because of a failure to create a needed parent attribute."), ! name); ! return 0; ! } ! case AE_BADNAME: ! notify_format(player, T("That's not a very good name for an attribute.")); return 0; ! case AE_ERROR: if (*missing_name) { if (s && (EMPTY_ATTRS || *s)) notify_format(player, T("You must set %s first."), missing_name); *************** *** 1656,1667 **** } else notify(player, T("That attribute cannot be changed by you.")); return 0; ! } else if (res == AE_TOOMANY) { notify(player, T("Too many attributes on that object to add another.")); return 0; ! } else if (!res) { notify(player, T("No such attribute to reset.")); return 0; } if (!strcmp(name, "ALIAS") && IsPlayer(thing)) { reset_player_list(thing, NULL, tbuf1, NULL, s); --- 1760,1774 ---- } else notify(player, T("That attribute cannot be changed by you.")); return 0; ! case AE_TOOMANY: notify(player, T("Too many attributes on that object to add another.")); return 0; ! case AE_NOTFOUND: notify(player, T("No such attribute to reset.")); return 0; + case AE_OKAY: + /* Success */ + break; } if (!strcmp(name, "ALIAS") && IsPlayer(thing)) { reset_player_list(thing, NULL, tbuf1, NULL, s); *************** *** 1834,1847 **** * \return the pointer to the head of the attribute free list. */ static ATTR * ! get_atr_free_list(void) { if (!atr_free_list) { ATTRPAGE *page; int j; page = (ATTRPAGE *) mush_malloc(sizeof(ATTRPAGE), "ATTRPAGE"); if (!page) ! mush_panic("Couldn't allocate memory in get_atr_free_list"); for (j = 0; j < ATTRS_PER_PAGE - 1; j++) AL_NEXT(page->atrs + j) = page->atrs + j + 1; AL_NEXT(page->atrs + ATTRS_PER_PAGE - 1) = NULL; --- 1941,1954 ---- * \return the pointer to the head of the attribute free list. */ static ATTR * ! alloc_atr(void) { if (!atr_free_list) { ATTRPAGE *page; int j; page = (ATTRPAGE *) mush_malloc(sizeof(ATTRPAGE), "ATTRPAGE"); if (!page) ! mush_panic("Couldn't allocate memory in alloc_attr"); for (j = 0; j < ATTRS_PER_PAGE - 1; j++) AL_NEXT(page->atrs + j) = page->atrs + j + 1; AL_NEXT(page->atrs + ATTRS_PER_PAGE - 1) = NULL; *************** *** 1850,1855 **** --- 1957,2007 ---- return atr_free_list; } + /** Pop an empty attribute off of the free list for use on + * an object. + * \return the pointer to an attribute, or NULL on error. + */ + static ATTR * + pop_free_list(void) + { + ATTR *ptr; + ptr = alloc_atr(); + if (!ptr) + return NULL; + atr_free_list = AL_NEXT(ptr); + AL_NEXT(ptr) = NULL; + return ptr; + } + + /** Push a now-unused attribute onto the free list + * \param An attribute that's been deleted from an object and + * had its chunk reference deleted. + */ + static void + push_free_list(ATTR *a) + { + memset(a, 0, sizeof(*a)); + AL_NEXT(a) = atr_free_list; + atr_free_list = a; + } + + /** Delete one attribute, deallocating its name and data. + * Does not update the owning object's attribute list or + * attribute count. That is the caller's responsibility. + * + * \param a the attribute to free + */ + static void + atr_free_one(ATTR *a) + { + if (!a) + return; + st_delete(AL_NAME(a), &atr_names); + if (a->data) + chunk_delete(a->data); + push_free_list(a); + } + /** Return the compressed data for an attribute. * This is a chokepoint function for accessing the chunk data. * \param atr the attribute struct from which to get the data reference. *** 1_8_2p3/src/bsd.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/bsd.c Wed May 16 22:19:20 2007 *************** *** 373,380 **** void reaper(int sig); extern Pid_t forked_dump_pid; /**< Process id of forking dump process */ static void dump_users(DESC *call_by, char *match, int doing); ! static const char *time_format_1(long int dt); ! static const char *time_format_2(long int dt); static void announce_connect(dbref player, int isnew, int num); static void announce_disconnect(DESC *saved); void inactivity_check(void); --- 373,380 ---- void reaper(int sig); extern Pid_t forked_dump_pid; /**< Process id of forking dump process */ static void dump_users(DESC *call_by, char *match, int doing); ! static const char *time_format_1(time_t dt); ! static const char *time_format_2(time_t dt); static void announce_connect(dbref player, int isnew, int num); static void announce_disconnect(DESC *saved); void inactivity_check(void); *************** *** 2558,2564 **** if (ModTime(player)) notify_format(player, T("%ld failed connections since last login."), ! ModTime(player)); ModTime(player) = (time_t) 0; announce_connect(player, isnew, num); /* broadcast connect message */ check_last(player, d->addr, d->ip); /* set Last, Lastsite, give paycheck */ --- 2558,2564 ---- if (ModTime(player)) notify_format(player, T("%ld failed connections since last login."), ! (long) ModTime(player)); ModTime(player) = (time_t) 0; announce_connect(player, isnew, num); /* broadcast connect message */ check_last(player, d->addr, d->ip); /* set Last, Lastsite, give paycheck */ *************** *** 2768,2774 **** msg++; p = (unsigned char *) user; ! if (PLAYER_NAME_SPACES && *msg == '\"') { for (; *msg && ((*msg == '\"') || isspace(*msg)); msg++) ; while (*msg && (*msg != '\"')) { while (*msg && !isspace(*msg) && (*msg != '\"')) --- 2768,2774 ---- msg++; p = (unsigned char *) user; ! if (*msg == '\"') { for (; *msg && ((*msg == '\"') || isspace(*msg)); msg++) ; while (*msg && (*msg != '\"')) { while (*msg && !isspace(*msg) && (*msg != '\"')) *************** *** 3298,3312 **** } static const char * ! time_format_1(long dt) { register struct tm *delta; ! time_t holder; /* A hack for 64bit SGI */ static char buf[64]; if (dt < 0) dt = 0; ! holder = (time_t) dt; ! delta = gmtime(&holder); if (delta->tm_yday > 0) { sprintf(buf, "%dd %02d:%02d", delta->tm_yday, delta->tm_hour, delta->tm_min); --- 3298,3312 ---- } static const char * ! time_format_1(time_t dt) { register struct tm *delta; ! static char buf[64]; if (dt < 0) dt = 0; ! ! delta = gmtime(&dt); if (delta->tm_yday > 0) { sprintf(buf, "%dd %02d:%02d", delta->tm_yday, delta->tm_hour, delta->tm_min); *************** *** 3317,3330 **** } static const char * ! time_format_2(long dt) { register struct tm *delta; static char buf[64]; if (dt < 0) dt = 0; ! delta = gmtime((time_t *) & dt); if (delta->tm_yday > 0) { sprintf(buf, "%dd", delta->tm_yday); } else if (delta->tm_hour > 0) { --- 3317,3330 ---- } static const char * ! time_format_2(time_t dt) { register struct tm *delta; static char buf[64]; if (dt < 0) dt = 0; ! delta = gmtime(&dt); if (delta->tm_yday > 0) { sprintf(buf, "%dd", delta->tm_yday); } else if (delta->tm_hour > 0) { *************** *** 3584,3590 **** if (num < 2) { clear_flag_internal(player, "CONNECTED"); ! (void) atr_add(player, "LASTLOGOUT", show_time(mudtime, 0), GOD, NOTHING); } local_disconnect(player, num); } --- 3584,3590 ---- if (num < 2) { clear_flag_internal(player, "CONNECTED"); ! (void) atr_add(player, "LASTLOGOUT", show_time(mudtime, 0), GOD, 0); } local_disconnect(player, num); } *** 1_8_2p3/src/cmds.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/cmds.c Wed May 16 22:19:20 2007 *************** *** 1086,1101 **** } COMMAND (cmd_page) { - int has_eq = 0; - if (args_raw && *args_raw && strchr(args_raw, '=')) - has_eq = 1; if (SW_ISSET(sw, SWITCH_PORT)) do_page_port(player, arg_left, arg_right); else do_page(player, arg_left, arg_right, cause, SW_ISSET(sw, SWITCH_NOEVAL), !(SW_ISSET(sw, SWITCH_BLIND) || (!(SW_ISSET(sw, SWITCH_LIST)) && (BLIND_PAGE))), ! SW_ISSET(sw, SWITCH_OVERRIDE), has_eq); } COMMAND (cmd_pose) { --- 1086,1098 ---- } COMMAND (cmd_page) { if (SW_ISSET(sw, SWITCH_PORT)) do_page_port(player, arg_left, arg_right); else do_page(player, arg_left, arg_right, cause, SW_ISSET(sw, SWITCH_NOEVAL), !(SW_ISSET(sw, SWITCH_BLIND) || (!(SW_ISSET(sw, SWITCH_LIST)) && (BLIND_PAGE))), ! SW_ISSET(sw, SWITCH_OVERRIDE), rhs_present); } COMMAND (cmd_pose) { *** 1_8_2p3/src/command.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/command.c Wed May 16 22:19:20 2007 *************** *** 994,1000 **** cmd = command_find("ATTRIB_SET"); } else { c = command; ! while ((*c) && (*c != '/') && (*c != ' ')) c++; b = *c; *c = '\0'; --- 994,1000 ---- cmd = command_find("ATTRIB_SET"); } else { c = command; ! while ((*c) && (*c != '/')) c++; b = *c; *c = '\0'; *** 1_8_2p3/src/conf.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/conf.c Wed May 16 22:19:20 2007 *************** *** 1543,1556 **** safe_str(T("#-1 NO SUCH CONFIG OPTION"), buff, bp); return; } else { for (cp = conftable; cp->name; cp++) { ! safe_str(cp->name, buff, bp); ! safe_chr(' ', buff, bp); } for (cp = (PENNCONF *) hash_firstentry(&local_options); cp; cp = (PENNCONF *) hash_nextentry(&local_options)) { ! safe_str(cp->name, buff, bp); ! safe_chr(' ', buff, bp); } } } --- 1543,1567 ---- safe_str(T("#-1 NO SUCH CONFIG OPTION"), buff, bp); return; } else { + int first = 1; for (cp = conftable; cp->name; cp++) { ! if (cp->group) { ! if (first) ! first = 0; ! else ! safe_chr(' ', buff, bp); ! safe_str(cp->name, buff, bp); ! } } for (cp = (PENNCONF *) hash_firstentry(&local_options); cp; cp = (PENNCONF *) hash_nextentry(&local_options)) { ! if (cp->group) { ! if (first) ! first = 0; ! else ! safe_chr(' ', buff, bp); ! safe_str(cp->name, buff, bp); ! } } } } *** 1_8_2p3/src/cque.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/cque.c Wed May 16 22:19:20 2007 *************** *** 49,55 **** dbref cause; /**< player causing command (for %N) */ dbref sem; /**< semaphore object to block on */ char *semattr; /**< semaphore attribute to block on */ ! int left; /**< seconds left until execution */ char *env[10]; /**< environment, from wild match */ char *rval[NUMQ]; /**< environment, from setq() */ char *comm; /**< command to be executed */ --- 49,55 ---- dbref cause; /**< player causing command (for %N) */ dbref sem; /**< semaphore object to block on */ char *semattr; /**< semaphore attribute to block on */ ! time_t left; /**< seconds left until execution */ char *env[10]; /**< environment, from wild match */ char *rval[NUMQ]; /**< environment, from setq() */ char *comm; /**< command to be executed */ *************** *** 138,144 **** static int add_to(dbref player, int am) { ! return (add_to_generic(player, am, "QUEUE", NOTHING)); } static int --- 138,144 ---- static int add_to(dbref player, int am) { ! return (add_to_generic(player, am, "QUEUE", 0)); } static int *************** *** 613,619 **** /* Wait queue is in sorted order so we only have to look at the first item on it. Anything else is wasted time. */ if (qwait) { ! curr = qwait->left - mudtime; if (curr <= 2) return 1; if (curr < min) --- 613,619 ---- /* Wait queue is in sorted order so we only have to look at the first item on it. Anything else is wasted time. */ if (qwait) { ! curr = (int) difftime(qwait->left, mudtime); if (curr <= 2) return 1; if (curr < min) *************** *** 623,629 **** for (point = qsemfirst; point; point = point->next) { if (point->left == 0) /* no timeout */ continue; ! curr = point->left - mudtime; if (curr <= 2) return 1; if (curr < min) { --- 623,629 ---- for (point = qsemfirst; point; point = point->next) { if (point->left == 0) /* no timeout */ continue; ! curr = (int) difftime(point->left, mudtime); if (curr <= 2) return 1; if (curr < min) { *************** *** 879,885 **** } /* get timeout, default of -1 */ if (tcount && *tcount) ! waitfor = atol(tcount); else waitfor = -1; add_to_sem(thing, 1, aname); --- 879,885 ---- } /* get timeout, default of -1 */ if (tcount && *tcount) ! waitfor = parse_integer(tcount); else waitfor = -1; add_to_sem(thing, 1, aname); *************** *** 913,925 **** continue; switch (q_type) { case 1: /* wait queue */ ! notify_format(player, "[%ld]%s: %s", tmp->left - mudtime, unparse_object(player, tmp->player), tmp->comm); break; case 2: /* semaphore queue */ if (tmp->left != 0) { notify_format(player, "[#%d/%s/%ld]%s: %s", tmp->sem, ! tmp->semattr, tmp->left - mudtime, unparse_object(player, tmp->player), tmp->comm); } else { notify_format(player, "[#%d/%s]%s: %s", tmp->sem, --- 913,926 ---- continue; switch (q_type) { case 1: /* wait queue */ ! notify_format(player, "[%ld]%s: %s", ! (long) difftime(tmp->left, mudtime), unparse_object(player, tmp->player), tmp->comm); break; case 2: /* semaphore queue */ if (tmp->left != 0) { notify_format(player, "[#%d/%s/%ld]%s: %s", tmp->sem, ! tmp->semattr, (long) difftime(tmp->left, mudtime), unparse_object(player, tmp->player), tmp->comm); } else { notify_format(player, "[#%d/%s]%s: %s", tmp->sem, *** 1_8_2p3/src/db.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/db.c Wed May 16 22:19:20 2007 *************** *** 1101,1107 **** for (i = 0; i < db_top; i++) { set_name(i, NULL); ! atr_free(i); free_locks(Locks(i)); } --- 1101,1107 ---- for (i = 0; i < db_top; i++) { set_name(i, NULL); ! atr_free_all(i); free_locks(Locks(i)); } *** 1_8_2p3/src/destroy.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/destroy.c Wed May 16 22:19:20 2007 *************** *** 676,682 **** } /* chomp chomp */ ! atr_free(thing); List(thing) = NULL; /* don't eat name otherwise examine will crash */ --- 676,682 ---- } /* chomp chomp */ ! atr_free_all(thing); List(thing) = NULL; /* don't eat name otherwise examine will crash */ *** 1_8_2p3/src/flags.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/flags.c Wed May 16 22:19:20 2007 *************** *** 82,88 **** static FLAG flag_table[] = { {"CHOWN_OK", 'C', NOTYPE, CHOWN_OK, F_ANY, F_ANY}, {"DARK", 'D', NOTYPE, DARK, F_ANY, F_ANY}, ! {"GOING", 'G', NOTYPE, GOING, F_INTERNAL, F_ANY}, {"HAVEN", 'H', NOTYPE, HAVEN, F_ANY, F_ANY}, {"TRUST", 'I', NOTYPE, INHERIT, F_INHERIT, F_INHERIT}, {"LINK_OK", 'L', NOTYPE, LINK_OK, F_ANY, F_ANY}, --- 82,88 ---- static FLAG flag_table[] = { {"CHOWN_OK", 'C', NOTYPE, CHOWN_OK, F_ANY, F_ANY}, {"DARK", 'D', NOTYPE, DARK, F_ANY, F_ANY}, ! {"GOING", 'G', NOTYPE, GOING, F_INTERNAL, F_INTERNAL}, {"HAVEN", 'H', NOTYPE, HAVEN, F_ANY, F_ANY}, {"TRUST", 'I', NOTYPE, INHERIT, F_INHERIT, F_INHERIT}, {"LINK_OK", 'L', NOTYPE, LINK_OK, F_ANY, F_ANY}, *** 1_8_2p3/src/fundb.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/fundb.c Wed May 16 22:19:20 2007 *************** *** 2111,2119 **** sensitive = !strcmp(called_as, "GREP") || !strcmp(called_as, "WILDGREP"); wild = !strcmp(called_as, "WILDGREPI") || !strcmp(called_as, "WILDGREP"); tp = grep_util(executor, it, args[1], args[2], sensitive, wild); - add_check("fun_grep.attr_list"); safe_str(tp, buff, bp); ! mush_free((Malloc_t) tp, "fun_grep.attr_list"); } /* Get database size statistics */ --- 2111,2118 ---- sensitive = !strcmp(called_as, "GREP") || !strcmp(called_as, "WILDGREP"); wild = !strcmp(called_as, "WILDGREPI") || !strcmp(called_as, "WILDGREP"); tp = grep_util(executor, it, args[1], args[2], sensitive, wild); safe_str(tp, buff, bp); ! mush_free(tp, "grep_util.buff"); } /* Get database size statistics */ *** 1_8_2p3/src/funlist.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/funlist.c Wed May 16 22:19:20 2007 *************** *** 1238,1244 **** /* Now we make a list of keys */ for (i = 0; i < nptrs; i++) { /* Build our %0 args */ ! wenv[0] = (char *)ptrs[i]; call_ufun(&ufun, wenv, 2, result, executor, enactor, pe_info); keys[i] = mush_strdup(result, "sortkey"); } --- 1238,1244 ---- /* Now we make a list of keys */ for (i = 0; i < nptrs; i++) { /* Build our %0 args */ ! wenv[0] = (char *) ptrs[i]; call_ufun(&ufun, wenv, 2, result, executor, enactor, pe_info); keys[i] = mush_strdup(result, "sortkey"); } *** 1_8_2p3/src/funmisc.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/funmisc.c Wed May 16 22:19:20 2007 *************** *** 298,304 **** int j, per; char mstr[BUFFER_LEN], pstr[BUFFER_LEN], *dp; char const *sp; ! char *tbuf1; int first = 1, found = 0, exact = 0; if (strstr(called_as, "ALL")) --- 298,304 ---- int j, per; char mstr[BUFFER_LEN], pstr[BUFFER_LEN], *dp; char const *sp; ! char *tbuf1 = NULL; int first = 1, found = 0, exact = 0; if (strstr(called_as, "ALL")) *************** *** 348,358 **** if (!(nargs & 1) && !found) { /* Default case */ ! tbuf1 = replace_string("#$", mstr, args[nargs - 1]); ! sp = tbuf1; process_expression(buff, bp, &sp, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); ! mush_free((Malloc_t) tbuf1, "replace_string.buff"); } } --- 348,362 ---- if (!(nargs & 1) && !found) { /* Default case */ ! if (!exact) { ! tbuf1 = replace_string("#$", mstr, args[nargs - 1]); ! sp = tbuf1; ! } else ! sp = args[nargs - 1]; process_expression(buff, bp, &sp, executor, caller, enactor, PE_DEFAULT, PT_DEFAULT, pe_info); ! if (!exact) ! mush_free((Malloc_t) tbuf1, "replace_string.buff"); } } *** 1_8_2p3/src/funstr.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/funstr.c Wed May 16 22:19:20 2007 *************** *** 176,182 **** safe_chr('a', buff, bp); return; } ! c = tolower(*p); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') safe_str("an", buff, bp); else --- 176,182 ---- safe_chr('a', buff, bp); return; } ! c = DOWNCASE(*p); if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u') safe_str("an", buff, bp); else *************** *** 489,495 **** safe_str(T("#-1 INVALID THIRD ARGUMENT"), buff, bp); return; } else if (nargs == 3) { ! type = toupper(*args[2]); } switch (type) { --- 489,495 ---- safe_str(T("#-1 INVALID THIRD ARGUMENT"), buff, bp); return; } else if (nargs == 3) { ! type = UPCASE(*args[2]); } switch (type) { *************** *** 2194,2202 **** else close = args[6]; switch (*string) { case ':': ! safe_str(Name(speaker), buff, bp); string++; if (*string == ' ') { /* semipose it instead */ --- 2194,2203 ---- else close = args[6]; + switch (*string) { case ':': ! safe_str(accented_name(speaker), buff, bp); string++; if (*string == ' ') { /* semipose it instead */ *************** *** 2207,2213 **** break; case ';': string++; ! safe_str(Name(speaker), buff, bp); if (*string == ' ') { /* pose it instead */ safe_chr(' ', buff, bp); --- 2208,2214 ---- break; case ';': string++; ! safe_str(accented_name(speaker), buff, bp); if (*string == ' ') { /* pose it instead */ safe_chr(' ', buff, bp); *************** *** 2229,2235 **** if (!transform || (!say && !strstr(string, open))) { /* nice and easy */ if (say) ! safe_format(buff, bp, "%s %s \"%s\"", Name(speaker), say_string, string); else safe_str(string, buff, bp); return; --- 2230,2237 ---- if (!transform || (!say && !strstr(string, open))) { /* nice and easy */ if (say) ! safe_format(buff, bp, "%s %s \"%s\"", accented_name(speaker), ! say_string, string); else safe_str(string, buff, bp); return; *************** *** 2245,2251 **** return; } if (strlen(rbuff) > 0) { ! safe_format(buff, bp, "%s %s %s", Name(speaker), say_string, rbuff); return; } else if (null == 1) { wenv[0] = speaker_str; --- 2247,2254 ---- return; } if (strlen(rbuff) > 0) { ! safe_format(buff, bp, "%s %s %s", accented_name(speaker), ! say_string, rbuff); return; } else if (null == 1) { wenv[0] = speaker_str; *************** *** 2263,2269 **** int delete = 0; if (say) { ! safe_str(Name(speaker), buff, bp); safe_chr(' ', buff, bp); safe_str(say_string, buff, bp); safe_chr(' ', buff, bp); --- 2266,2272 ---- int delete = 0; if (say) { ! safe_str(accented_name(speaker), buff, bp); safe_chr(' ', buff, bp); safe_str(say_string, buff, bp); safe_chr(' ', buff, bp); *** 1_8_2p3/src/funtime.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/funtime.c Wed May 16 22:19:20 2007 *************** *** 20,25 **** --- 20,26 ---- #include "externs.h" #include "parse.h" #include "dbdefs.h" + #include "attrib.h" #include "log.h" #include "match.h" #include "confmagic.h" *** 1_8_2p3/src/game.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/game.c Wed May 16 22:19:20 2007 *************** *** 737,743 **** conf_default_set(); config_file_startup(conf, 0); start_all_logs(); ! redirect_stderr(); /* Initialize the attribute chunk storage */ chunk_init(); --- 737,743 ---- conf_default_set(); config_file_startup(conf, 0); start_all_logs(); ! redirect_streams(); /* Initialize the attribute chunk storage */ chunk_init(); *************** *** 1863,1869 **** *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); notify(player, T("Function mapped onto list.")); } if (flags & DOL_NOTIFY) { --- 1863,1869 ---- *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, 0); notify(player, T("Function mapped onto list.")); } if (flags & DOL_NOTIFY) { *************** *** 2125,2148 **** notify_format(player, T ("Time until next database save: %ld minutes %ld seconds, at %s"), ! (options.dump_counter - mudtime) / 60, ! (options.dump_counter - mudtime) % 60, tbuf1); when = localtime(&options.dbck_counter); strftime(tbuf1, sizeof tbuf1, "%X", when); notify_format(player, T (" Time until next dbck check: %ld minutes %ld seconds, at %s."), ! (options.dbck_counter - mudtime) / 60, ! (options.dbck_counter - mudtime) % 60, tbuf1); when = localtime(&options.purge_counter); strftime(tbuf1, sizeof tbuf1, "%X", when); notify_format(player, T (" Time until next purge: %ld minutes %ld seconds, at %s."), ! (options.purge_counter - mudtime) / 60, ! (options.purge_counter - mudtime) % 60, tbuf1); if (options.warn_interval) { when = localtime(&options.warn_counter); --- 2125,2148 ---- notify_format(player, T ("Time until next database save: %ld minutes %ld seconds, at %s"), ! ((long) difftime(options.dump_counter, mudtime)) / 60, ! ((long) difftime(options.dump_counter, mudtime)) % 60, tbuf1); when = localtime(&options.dbck_counter); strftime(tbuf1, sizeof tbuf1, "%X", when); notify_format(player, T (" Time until next dbck check: %ld minutes %ld seconds, at %s."), ! ((long) difftime(options.dbck_counter, mudtime)) / 60, ! ((long) difftime(options.dbck_counter, mudtime)) % 60, tbuf1); when = localtime(&options.purge_counter); strftime(tbuf1, sizeof tbuf1, "%X", when); notify_format(player, T (" Time until next purge: %ld minutes %ld seconds, at %s."), ! ((long) difftime(options.purge_counter, mudtime)) / 60, ! ((long) difftime(options.purge_counter, mudtime)) % 60, tbuf1); if (options.warn_interval) { when = localtime(&options.warn_counter); *************** *** 2150,2166 **** notify_format(player, T (" Time until next @warnings: %ld minutes %ld seconds, at %s."), ! (options.warn_counter - mudtime) / 60, ! (options.warn_counter - mudtime) % 60, tbuf1); } notify_format(player, T ("PennMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"), ! (mudtime - globals.first_start_time) / 86400, ! ((mudtime - globals.first_start_time) % 86400) / 3600, ! (((mudtime - globals.first_start_time) % 86400) % 3600) / 60, ! (((mudtime - globals.first_start_time) % 86400) % 3600) % 60); /* Mortals, go no further! */ if (!Wizard(player) || mortal) --- 2150,2169 ---- notify_format(player, T (" Time until next @warnings: %ld minutes %ld seconds, at %s."), ! ((long) difftime(options.warn_counter, mudtime)) / 60, ! ((long) difftime(options.warn_counter, mudtime)) % 60, tbuf1); } notify_format(player, T ("PennMUSH Uptime: %ld days %ld hours %ld minutes %ld seconds"), ! ((long) difftime(mudtime, globals.first_start_time)) / 86400, ! ((long) difftime(mudtime, globals.first_start_time) % 86400) / ! 3600, ! (((long) difftime(mudtime, globals.first_start_time) % 86400) % ! 3600) / 60, ! (((long) difftime(mudtime, globals.first_start_time) % 86400) % ! 3600) % 60); /* Mortals, go no further! */ if (!Wizard(player) || mortal) *** 1_8_2p3/src/log.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/log.c Wed May 16 22:19:20 2007 *************** *** 121,132 **** start_log(&cmdlog_fp, CMDLOG); } ! /** Redirect stderr to a error log file. * Should be called after start_all_logs(). * \param log name of logfile to redirect stderr to. */ void ! redirect_stderr(void) { FILE *errlog_fp; --- 121,132 ---- start_log(&cmdlog_fp, CMDLOG); } ! /** Redirect stderr to a error log file and close stdout and stdin. * Should be called after start_all_logs(). * \param log name of logfile to redirect stderr to. */ void ! redirect_streams(void) { FILE *errlog_fp; *************** *** 143,148 **** --- 143,152 ---- setvbuf(stderr, NULL, _IOLBF, BUFSIZ); fclose(errlog_fp); } + #ifndef DEBUG_BYTECODE + fclose(stdout); + #endif + fclose(stdin); } *** 1_8_2p3/src/look.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/look.c Wed May 16 22:19:20 2007 *************** *** 27,34 **** #include "command.h" #include "parse.h" #include "privtab.h" - #include "confmagic.h" #include "log.h" static void look_exits(dbref player, dbref loc, const char *exit_name); static void look_contents(dbref player, dbref loc, const char *contents_name); --- 27,36 ---- #include "command.h" #include "parse.h" #include "privtab.h" #include "log.h" + #include "case.h" + #include "confmagic.h" + static void look_exits(dbref player, dbref loc, const char *exit_name); static void look_contents(dbref player, dbref loc, const char *contents_name); *************** *** 334,341 **** if (parent == thing || !GoodObject(parent)) parent = NOTHING; strcpy(fbuf, privs_to_letters(attr_privs_view, AL_FLAGS(atr))); - if (atr_sub_branch(atr)) - strcat(fbuf, "`"); if (AF_Veiled(atr)) { if (ShowAnsi(player)) { if (GoodObject(parent)) --- 336,341 ---- *************** *** 396,403 **** if (parent == thing || !GoodObject(parent)) parent = NOTHING; strcpy(fbuf, privs_to_letters(attr_privs_view, AL_FLAGS(atr))); - if (atr_sub_branch(atr)) - strcat(fbuf, "`"); r = safe_atr_value(atr); if (ShowAnsi(player)) { if (GoodObject(parent)) --- 396,401 ---- *************** *** 1612,1618 **** } /* If background color, change the letter to a capital. */ if (*(ptr - 1) == '4') ! ansi_letter = toupper(ansi_letter); safe_chr(ansi_letter, value, &s); } /* No "else" here: If a two-digit code --- 1610,1616 ---- } /* If background color, change the letter to a capital. */ if (*(ptr - 1) == '4') ! ansi_letter = UPCASE(ansi_letter); safe_chr(ansi_letter, value, &s); } /* No "else" here: If a two-digit code *************** *** 1700,1706 **** if (dh->skipdef && ptr) { /* Standard attribute. Get the default perms, if any. */ /* Are we different? If so, do as usual */ ! int npmflags = AL_FLAGS(ptr) & (~AF_PREFIXMATCH); if (AL_FLAGS(atr) != AL_FLAGS(ptr) && AL_FLAGS(atr) != npmflags) privs = privs_to_string(attr_privs_view, AL_FLAGS(atr)); } else { --- 1698,1704 ---- if (dh->skipdef && ptr) { /* Standard attribute. Get the default perms, if any. */ /* Are we different? If so, do as usual */ ! unsigned int npmflags = AL_FLAGS(ptr) & (~AF_PREFIXMATCH); if (AL_FLAGS(atr) != AL_FLAGS(ptr) && AL_FLAGS(atr) != npmflags) privs = privs_to_string(attr_privs_view, AL_FLAGS(atr)); } else { *** 1_8_2p3/src/move.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/move.c Wed May 16 22:19:20 2007 *************** *** 1115,1128 **** char *bp; a = atr_get_noparent(leader, "FOLLOWERS"); if (!a) { ! (void) atr_add(leader, "FOLLOWERS", unparse_dbref(follower), GOD, NOTHING); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(follower, tbuf1, &bp); *bp = '\0'; ! (void) atr_add(leader, "FOLLOWERS", tbuf1, GOD, NOTHING); } } --- 1115,1128 ---- char *bp; a = atr_get_noparent(leader, "FOLLOWERS"); if (!a) { ! (void) atr_add(leader, "FOLLOWERS", unparse_dbref(follower), GOD, 0); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(follower, tbuf1, &bp); *bp = '\0'; ! (void) atr_add(leader, "FOLLOWERS", tbuf1, GOD, 0); } } *************** *** 1135,1148 **** char *bp; a = atr_get_noparent(follower, "FOLLOWING"); if (!a) { ! (void) atr_add(follower, "FOLLOWING", unparse_dbref(leader), GOD, NOTHING); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(leader, tbuf1, &bp); *bp = '\0'; ! (void) atr_add(follower, "FOLLOWING", tbuf1, GOD, NOTHING); } } --- 1135,1148 ---- char *bp; a = atr_get_noparent(follower, "FOLLOWING"); if (!a) { ! (void) atr_add(follower, "FOLLOWING", unparse_dbref(leader), GOD, 0); } else { bp = tbuf1; safe_str(atr_value(a), tbuf1, &bp); safe_chr(' ', tbuf1, &bp); safe_dbref(leader, tbuf1, &bp); *bp = '\0'; ! (void) atr_add(follower, "FOLLOWING", tbuf1, GOD, 0); } } *************** *** 1174,1181 **** /* Let's take it apart and put it back together w/o follower */ strcpy(flwr, unparse_dbref(follower)); strcpy(tbuf1, atr_value(a)); ! (void) atr_add(leader, "FOLLOWERS", ! remove_word(tbuf1, flwr, ' '), GOD, NOTHING); } /* Delete someone from a player's FOLLOWING attribute */ --- 1174,1180 ---- /* Let's take it apart and put it back together w/o follower */ strcpy(flwr, unparse_dbref(follower)); strcpy(tbuf1, atr_value(a)); ! (void) atr_add(leader, "FOLLOWERS", remove_word(tbuf1, flwr, ' '), GOD, 0); } /* Delete someone from a player's FOLLOWING attribute */ *************** *** 1191,1198 **** /* Let's take it apart and put it back together w/o leader */ strcpy(ldr, unparse_dbref(leader)); strcpy(tbuf1, atr_value(a)); ! (void) atr_add(follower, "FOLLOWING", ! remove_word(tbuf1, ldr, ' '), GOD, NOTHING); } static void --- 1190,1196 ---- /* Let's take it apart and put it back together w/o leader */ strcpy(ldr, unparse_dbref(leader)); strcpy(tbuf1, atr_value(a)); ! (void) atr_add(follower, "FOLLOWING", remove_word(tbuf1, ldr, ' '), GOD, 0); } static void *** 1_8_2p3/src/parse.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/parse.c Wed May 16 22:19:20 2007 *************** *** 248,255 **** * by a : and at least one digit, and nothing else. * In regex: ^#-?\d+(:\d+)?$ * \param str string to check. ! * \retval 1 string is a dbref. ! * \retval 0 string is not a dbref. */ int is_objid(char const *str) --- 248,255 ---- * by a : and at least one digit, and nothing else. * In regex: ^#-?\d+(:\d+)?$ * \param str string to check. ! * \retval 1 string is an objid ! * \retval 0 string is not an objid. */ int is_objid(char const *str) *************** *** 811,817 **** if (!nextc) goto exit_sequence; (*str)++; ! if (!isdigit(nextc)) { safe_str(T(e_int), buff, bp); break; } --- 811,817 ---- if (!nextc) goto exit_sequence; (*str)++; ! if (!isdigit((unsigned char) nextc)) { safe_str(T(e_int), buff, bp); break; } *** 1_8_2p3/src/player.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/player.c Wed May 16 22:19:20 2007 *************** *** 99,105 **** return 0; } /* Something worked. Change password to SHS-encrypted */ ! (void) atr_add(player, pword_attr, passwd, GOD, NOTHING); } free(saved); return 1; --- 99,105 ---- return 0; } /* Something worked. Change password to SHS-encrypted */ ! (void) atr_add(player, pword_attr, passwd, GOD, 0); } free(saved); return 1; *************** *** 339,345 **** reserve_fd(); /* Ok, all's well, make a player */ player = make_player(name, passwd, host, ip); ! (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, NOTHING); return player; } #else --- 339,345 ---- reserve_fd(); /* Ok, all's well, make a player */ player = make_player(name, passwd, host, ip); ! (void) atr_add(player, "REGISTERED_EMAIL", email, GOD, 0); return player; } #else *************** *** 378,391 **** set_initial_warnings(player); /* Modtime tracks login failures */ ModTime(player) = (time_t) 0; ! (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, NOTHING); giveto(player, START_BONUS); /* starting bonus */ ! (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, NOTHING); ! (void) atr_add(player, "LASTSITE", host, GOD, NOTHING); (void) atr_add(player, "LASTIP", ip, GOD, NOTHING); ! (void) atr_add(player, "LASTFAILED", " ", GOD, NOTHING); sprintf(temp, "%d", START_QUOTA); ! (void) atr_add(player, "RQUOTA", temp, GOD, NOTHING); (void) atr_add(player, "ICLOC", EMPTY_ATTRS ? "" : " ", GOD, AF_MDARK | AF_PRIVATE | AF_WIZARD | AF_NOCOPY); (void) atr_add(player, "MAILCURF", "0", GOD, --- 378,391 ---- set_initial_warnings(player); /* Modtime tracks login failures */ ModTime(player) = (time_t) 0; ! (void) atr_add(player, "XYXXY", mush_crypt(password), GOD, 0); giveto(player, START_BONUS); /* starting bonus */ ! (void) atr_add(player, "LAST", show_time(mudtime, 0), GOD, 0); ! (void) atr_add(player, "LASTSITE", host, GOD, 0); (void) atr_add(player, "LASTIP", ip, GOD, NOTHING); ! (void) atr_add(player, "LASTFAILED", " ", GOD, 0); sprintf(temp, "%d", START_QUOTA); ! (void) atr_add(player, "RQUOTA", temp, GOD, 0); (void) atr_add(player, "ICLOC", EMPTY_ATTRS ? "" : " ", GOD, AF_MDARK | AF_PRIVATE | AF_WIZARD | AF_NOCOPY); (void) atr_add(player, "MAILCURF", "0", GOD, *************** *** 447,453 **** } else if (!ok_password(newobj)) { notify(player, T("Bad new password.")); } else { ! (void) atr_add(player, "XYXXY", mush_crypt(newobj), GOD, NOTHING); notify(player, T("You have changed your password.")); } } --- 447,453 ---- } else if (!ok_password(newobj)) { notify(player, T("Bad new password.")); } else { ! (void) atr_add(player, "XYXXY", mush_crypt(newobj), GOD, 0); notify(player, T("You have changed your password.")); } } *************** *** 497,506 **** */ /* set the new attributes */ ! (void) atr_add(player, "LAST", s, GOD, NOTHING); ! (void) atr_add(player, "LASTSITE", host, GOD, NOTHING); ! (void) atr_add(player, "LASTIP", ip, GOD, NOTHING); ! (void) atr_add(player, "LASTFAILED", " ", GOD, NOTHING); } --- 497,506 ---- */ /* set the new attributes */ ! (void) atr_add(player, "LAST", s, GOD, 0); ! (void) atr_add(player, "LASTSITE", host, GOD, 0); ! (void) atr_add(player, "LASTIP", ip, GOD, 0); ! (void) atr_add(player, "LASTFAILED", " ", GOD, 0); } *************** *** 516,520 **** bp = last_place; safe_format(last_place, &bp, T("%s on %s"), host, show_time(mudtime, 0)); *bp = '\0'; ! (void) atr_add(player, "LASTFAILED", last_place, GOD, NOTHING); } --- 516,520 ---- bp = last_place; safe_format(last_place, &bp, T("%s on %s"), host, show_time(mudtime, 0)); *bp = '\0'; ! (void) atr_add(player, "LASTFAILED", last_place, GOD, 0); } *** 1_8_2p3/src/plyrlist.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/plyrlist.c Wed May 16 22:19:20 2007 *************** *** 13,23 **** #include #include "copyrite.h" - #include "conf.h" #include "externs.h" #include "mushdb.h" #include "dbdefs.h" #include "flags.h" #include "htab.h" #include "confmagic.h" --- 13,23 ---- #include #include "copyrite.h" #include "conf.h" #include "externs.h" #include "mushdb.h" #include "dbdefs.h" + #include "attrib.h" #include "flags.h" #include "htab.h" #include "confmagic.h" *** 1_8_2p3/src/portmsg.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/portmsg.c Wed May 16 22:19:20 2007 *************** *** 42,48 **** * SUCH DAMAGE. * * This version extensively modified by Javelin (Alan Schwartz) ! * to conform to PennMUSH autoconfiguration standards. */ /* If you have multiple IP addresses and want to bind to only one, --- 42,48 ---- * SUCH DAMAGE. * * This version extensively modified by Javelin (Alan Schwartz) ! * and Raevnos (Shawn Wagner) to conform to PennMUSH standards. */ /* If you have multiple IP addresses and want to bind to only one, *************** *** 74,88 **** #include #endif #include #include "conf.h" #include "externs.h" ! #include "mymalloc.h" #include "confmagic.h" - /* What htons expects */ - typedef unsigned short Port_t; - #ifdef HAS_WAITPID #define WAIT_TYPE int #else --- 74,86 ---- #include #endif #include + #include #include "conf.h" #include "externs.h" ! #include "mysocket.h" #include "confmagic.h" #ifdef HAS_WAITPID #define WAIT_TYPE int #else *************** *** 93,122 **** #endif #endif ! static Signal_t wait_on_child(int sig); ! static Signal_t lostconn(int sig); ! static int how_many_fds(void); ! static Signal_t ! wait_on_child(int sig __attribute__ ((__unused__))) { WAIT_TYPE status; #ifdef HAS_WAITPID ! while (waitpid(-1, &status, WNOHANG) > 0) ; #else ! while (wait3(&status, WNOHANG, 0) > 0) ; #endif ! #ifndef SIGNALS_KEPT ! signal(SIGCLD, (Sigfunc) wait_on_child); ! #endif ! #ifndef VOIDSIG ! return 0; ! #endif } ! Signal_t lostconn(int sig __attribute__ ((__unused__))) { exit(1); --- 91,129 ---- #endif #endif ! #ifndef SINGLE_IP_ADDR ! const char *host_ip = ""; ! #else ! const char *host_ip = SINGLE_IP_ADDR ! #endif ! static void wait_on_child(int sig); ! static void ! lostconn(int sig) ! NORETURN; ! ! enum { MAX_CONNECTIONS = 15 }; ! int connections = 0; ! static void ! wait_on_child(int sig __attribute__ ((__unused__))) { WAIT_TYPE status; #ifdef HAS_WAITPID ! while (waitpid(-1, &status, WNOHANG) > 0) ! connections--; #else ! while (wait3(&status, WNOHANG, NULL) > 0) ! connections--; #endif ! if (connections < 0) ! connections = 0; ! ! reload_sig_handler(SIGCHLD, wait_on_child); } ! void lostconn(int sig __attribute__ ((__unused__))) { exit(1); *************** *** 125,176 **** int main(int argc, char **argv) { ! int msgfd, fd, n; struct stat statBuf; Port_t port; char *msg; int sockfd, newsockfd; ! int addrlen; ! int opt; ! struct sockaddr_in tcp_srv_addr; ! struct sockaddr_in their_addr; ! int num_fds; if (argc != 3) { fprintf(stderr, "Usage: portmsg file port\n"); ! exit(1); } port = atoi(argv[2]); if (port == 0) { fprintf(stderr, "error: bad port number [%s]\n", argv[2]); ! exit(1); } if ((msgfd = open(argv[1], O_RDONLY)) < 0) { ! fprintf(stderr, "error: cannot open message file [%s]\n", argv[1]); ! exit(1); } /* read the message */ fstat(msgfd, &statBuf); if (statBuf.st_size <= 0) { fprintf(stderr, "error: message file [%s] is empty\n", argv[1]); ! exit(1); } msg = (char *) malloc(statBuf.st_size); if (read(msgfd, msg, statBuf.st_size) != statBuf.st_size) { fprintf(stderr, "error: cannot read message file [%s]\n", argv[1]); ! exit(1); } - num_fds = how_many_fds(); /* become a daemon */ switch (fork()) { case -1: ! fprintf(stderr, "error: can't fork\n"); ! exit(1); case 0: break; default: ! exit(0); } #ifdef HAS_SETPGRP #ifdef USE_BSD_SETPGRP --- 132,180 ---- int main(int argc, char **argv) { ! int msgfd, fd; struct stat statBuf; Port_t port; char *msg; int sockfd, newsockfd; ! socklen_t addrlen = 0; ! union sockaddr_u their_addr; if (argc != 3) { fprintf(stderr, "Usage: portmsg file port\n"); ! return 1; } port = atoi(argv[2]); if (port == 0) { fprintf(stderr, "error: bad port number [%s]\n", argv[2]); ! return 1; } if ((msgfd = open(argv[1], O_RDONLY)) < 0) { ! fprintf(stderr, "error: cannot open message file [%s]: %s\n", argv[1], ! strerror(errno)); ! return 1; } /* read the message */ fstat(msgfd, &statBuf); if (statBuf.st_size <= 0) { fprintf(stderr, "error: message file [%s] is empty\n", argv[1]); ! return 1; } msg = (char *) malloc(statBuf.st_size); if (read(msgfd, msg, statBuf.st_size) != statBuf.st_size) { fprintf(stderr, "error: cannot read message file [%s]\n", argv[1]); ! return 1; } /* become a daemon */ switch (fork()) { case -1: ! perror("can't fork"); ! return 1; case 0: break; default: ! return 0; } #ifdef HAS_SETPGRP #ifdef USE_BSD_SETPGRP *************** *** 178,185 **** #else if (setpgrp() == -1) { #endif ! fprintf(stderr, "error: can't change process group\n"); ! exit(1); } #endif --- 182,189 ---- #else if (setpgrp() == -1) { #endif ! perror("can't change process group"); ! return 1; } #endif *************** *** 190,287 **** } #endif ! signal(SIGCLD, (void *) wait_on_child); ! memset((char *) &tcp_srv_addr, 0, sizeof(tcp_srv_addr)); ! tcp_srv_addr.sin_family = AF_INET; ! #ifdef SINGLE_IP_ADDR ! tcp_srv_addr.sin_addr.s_addr = inet_addr(MUSH_IP_ADDR); ! #else ! tcp_srv_addr.sin_addr.s_addr = htonl(INADDR_ANY); ! #endif ! tcp_srv_addr.sin_port = htons(port); ! if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { ! fprintf(stderr, "can't create stream socket\n"); ! exit(-1); ! } ! opt = 1; ! if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, ! (char *) &opt, sizeof(opt)) < 0) { ! perror("setsockopt"); ! exit(1); } - if (bind(sockfd, (struct sockaddr *) &tcp_srv_addr, sizeof(tcp_srv_addr)) < 0) { - fprintf(stderr, "can't bind local address\n"); - exit(-1); - } - listen(sockfd, 5); main_again: addrlen = sizeof(their_addr); ! newsockfd = accept(sockfd, (struct sockaddr *) &their_addr, &addrlen); if (newsockfd < 0) { if (errno == EINTR) goto main_again; ! fprintf(stderr, "accept error\n"); ! exit(-1); } switch (fork()) { case -1: ! fprintf(stderr, "server can't fork\n"); ! exit(-1); case 0: ! dup2(newsockfd, 0); ! dup2(newsockfd, 1); ! for (n = 3; n < num_fds; n++) ! close(n); break; default: ! close(newsockfd); goto main_again; } ! /* daemon child arrives here */ ! signal(SIGPIPE, lostconn); ! signal(SIGCLD, SIG_IGN); ! ! fprintf(stdout, msg); ! fflush(stdout); ! sleep(5); ! exit(0); ! } ! ! static int ! how_many_fds(void) ! { ! /* Determine how many open file descriptors we're allowed ! * In order, we'll try: ! * 0. OPEN_MAX constant - POSIX.1 limits.h ! * 1. sysconf(_SC_OPEN_MAX) - POSIX.1 ! * 2. getdtablesize - BSD ! * 3. NOFILE - in some sys/param.h ! * 4. _NFILE - in some stdio.h ! */ ! #ifdef OPEN_MAX ! static int open_max = OPEN_MAX; ! #else ! static int open_max = 0; ! #endif ! ! if (open_max) ! return open_max; ! ! #ifdef HAS_SYSCONF ! errno = 0; ! if ((open_max = sysconf(_SC_OPEN_MAX)) < 0) { ! if (errno == 0) /* Value was indeterminate */ ! open_max = 0; ! } ! if (open_max) ! return open_max; ! #endif ! /* Caching getdtablesize is dangerous, since it's affected by ! * getrlimit, so we don't. ! */ ! open_max = 0; ! return getdtablesize(); } --- 194,236 ---- } #endif ! install_sig_handler(SIGCHLD, wait_on_child); ! if ((sockfd = make_socket(port, NULL, NULL, host_ip)) < 0) { ! perror("can't make socket"); ! return 1; } main_again: + if (connections > MAX_CONNECTIONS) { + sleep(1); + goto main_again; + } addrlen = sizeof(their_addr); ! newsockfd = accept(sockfd, &their_addr.addr, &addrlen); if (newsockfd < 0) { if (errno == EINTR) goto main_again; ! perror("Couldn't accept connection"); ! return 1; } + connections++; switch (fork()) { case -1: ! perror("server can't fork"); ! return 1; case 0: ! /* child process */ ! install_sig_handler(SIGPIPE, lostconn); ! ignore_signal(SIGCHLD); ! send(newsockfd, msg, statBuf.st_size, 0); ! sleep(5); ! closesocket(newsockfd); break; default: ! closesocket(newsockfd); goto main_again; } ! return 0; } *** 1_8_2p3/src/predicat.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/predicat.c Wed May 16 22:19:20 2007 *************** *** 124,134 **** int res; if ((res = queue_attribute(thing, awhat, player))) (void) atr_add(thing, "CHARGES", tprintf("%d", num - 1), ! Owner(b->creator), NOTHING); return res; } else { /* no charges left, try to execute runout */ ! return queue_attribute(thing, "RUNOUT", player); } } } --- 124,134 ---- int res; if ((res = queue_attribute(thing, awhat, player))) (void) atr_add(thing, "CHARGES", tprintf("%d", num - 1), ! Owner(b->creator), 0); return res; } else { /* no charges left, try to execute runout */ ! return queue_attribute(thing, "RUNOUT", 0); } } } *************** *** 619,625 **** else limit = owned; ! (void) atr_add(Owner(who), "RQUOTA", tprintf("%d", limit), GOD, NOTHING); return limit; } --- 619,625 ---- else limit = owned; ! (void) atr_add(Owner(who), "RQUOTA", tprintf("%d", limit), GOD, 0); return limit; } *** 1_8_2p3/src/rob.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/rob.c Wed May 16 22:19:20 2007 *************** *** 226,233 **** a = atr_get(vendor, "PRICELIST"); if (!a) continue; ! strncpy(prices,atr_value(a),BUFFER_LEN); ! prices[BUFFER_LEN-1] = '\0'; upcasestr(prices); count = list2arr(r, BUFFER_LEN / 2, prices, ' '); if (!count) --- 226,233 ---- a = atr_get(vendor, "PRICELIST"); if (!a) continue; ! strncpy(prices, atr_value(a), BUFFER_LEN); ! prices[BUFFER_LEN - 1] = '\0'; upcasestr(prices); count = list2arr(r, BUFFER_LEN / 2, prices, ' '); if (!count) *************** *** 548,554 **** notify(player, T("Did you want to give something *to* someone?")); return; } ! while ((s > arg) && isspace(*(s - 1))) { s--; } if (s == arg) { --- 548,554 ---- notify(player, T("Did you want to give something *to* someone?")); return; } ! while ((s > arg) && isspace((unsigned char) *(s - 1))) { s--; } if (s == arg) { *************** *** 558,564 **** *s++ = '\0'; s = (char *) string_match(s, "TO "); s += 3; ! while (*s && isspace(*s)) s++; if (!*s) { notify(player, T("Give to whom?")); --- 558,564 ---- *s++ = '\0'; s = (char *) string_match(s, "TO "); s += 3; ! while (*s && isspace((unsigned char) *s)) s++; if (!*s) { notify(player, T("Give to whom?")); *** 1_8_2p3/src/set.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/set.c Wed May 16 22:19:20 2007 *************** *** 1083,1093 **** * attributes using this command and wildcards. Wiping a specific * attr still works, though. */ if (wildcard(pattern) && AF_Wizard(atr) && !God(player)) return 0; ! return do_set_atr(thing, AL_NAME(atr), NULL, player, 0) == 1; } /** Clear an attribute. * \verbatim * This implements @wipe. --- 1083,1112 ---- * attributes using this command and wildcards. Wiping a specific * attr still works, though. */ + int saved_count = AttrCount(thing); + if (wildcard(pattern) && AF_Wizard(atr) && !God(player)) return 0; ! switch (wipe_atr(thing, AL_NAME(atr), player)) { ! case AE_SAFE: ! notify_format(player, T("Attribute %s is SAFE. Set it !SAFE to modify it."), ! AL_NAME(atr)); ! return 0; ! case AE_ERROR: ! notify_format(player, T("Unable to wipe attribute %s"), AL_NAME(atr)); ! return 0; ! case AE_TREE: ! notify_format(player, ! T ! ("Attribute %s cannot be wiped because a child attribute cannot be wiped."), ! AL_NAME(atr)); ! /* Fall through */ ! default: ! return saved_count - AttrCount(thing); ! } } + /** Clear an attribute. * \verbatim * This implements @wipe. *************** *** 1100,1105 **** --- 1119,1125 ---- { dbref thing; char *pattern; + int wiped; if ((pattern = strchr(name, '/')) != NULL) *pattern++ = '\0'; *************** *** 1120,1131 **** return; } ! we_are_wiping = 1; ! ! if (!atr_iter_get(player, thing, pattern, 0, wipe_helper, NULL)) notify(player, T("No attributes wiped.")); ! else ! notify(player, T("Attributes wiped.")); ! ! we_are_wiping = 0; } --- 1140,1153 ---- return; } ! switch ((wiped = atr_iter_get(player, thing, pattern, 0, wipe_helper, NULL))) { ! case 0: notify(player, T("No attributes wiped.")); ! break; ! case 1: ! notify(player, T("One attribute wiped.")); ! break; ! default: ! notify_format(player, T("%d attributes wiped."), wiped); ! } } *** 1_8_2p3/src/speech.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/speech.c Wed May 16 22:19:20 2007 *************** *** 856,862 **** } *tp = '\0'; *tp2 = '\0'; ! (void) atr_add(player, "LASTPAGED", tbuf, GOD, NOTHING); /* Reset tbuf to use later */ tp = tbuf; --- 856,862 ---- } *tp = '\0'; *tp2 = '\0'; ! (void) atr_add(player, "LASTPAGED", tbuf, GOD, 0); /* Reset tbuf to use later */ tp = tbuf; *** 1_8_2p3/src/timer.c Sun Mar 11 20:21:15 2007 --- 1_8_2p4/src/timer.c Wed May 16 22:19:20 2007 *************** *** 38,43 **** --- 38,44 ---- #include "game.h" #include "help.h" #include "parse.h" + #include "attrib.h" #include "confmagic.h" *************** *** 203,208 **** --- 204,210 ---- } /* A USR1 does a shutdown/reboot */ if (usr1_triggered) { + do_rawlog(LT_ERR, T("SIGUSR1 received. Rebooting.")); do_reboot(NOTHING, 0); /* We don't return from this */ usr1_triggered = 0; /* But just in case */ } *** 1_8_2p3/src/unparse.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/unparse.c Wed May 16 22:19:20 2007 *************** *** 119,125 **** static char buf[BUFFER_LEN], *bp; static char tbuf1[BUFFER_LEN]; char *p; - int got_nameformat = 0; couldunparse = 0; if (!(GoodObject(loc) || (loc == NOTHING) || (loc == AMBIGUOUS) || --- 119,124 ---- *************** *** 143,155 **** } if ((Can_Examine(player, loc) || can_link_to(player, loc) || JumpOk(loc) || ChownOk(loc) || DestOk(loc)) && ! (!Myopic(player) || !obey_myopic) && ! !(use_nameformat && got_nameformat)) { /* show everything */ if (SUPPORT_PUEBLO) couldunparse = 1; bp = buf; ! if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat) safe_format(buf, &bp, "%s%s%s(#%d%s)", ANSI_HILITE, tbuf1, ANSI_NORMAL, loc, unparse_flags(loc, player)); else --- 142,153 ---- } if ((Can_Examine(player, loc) || can_link_to(player, loc) || JumpOk(loc) || ChownOk(loc) || DestOk(loc)) && ! (!Myopic(player) || !obey_myopic)) { /* show everything */ if (SUPPORT_PUEBLO) couldunparse = 1; bp = buf; ! if (ANSI_NAMES && ShowAnsi(player)) safe_format(buf, &bp, "%s%s%s(#%d%s)", ANSI_HILITE, tbuf1, ANSI_NORMAL, loc, unparse_flags(loc, player)); else *************** *** 158,164 **** *bp = '\0'; } else { /* show only the name */ ! if (ANSI_NAMES && ShowAnsi(player) && !got_nameformat) { bp = buf; safe_format(buf, &bp, "%s%s%s", ANSI_HILITE, tbuf1, ANSI_NORMAL); *bp = '\0'; --- 156,162 ---- *bp = '\0'; } else { /* show only the name */ ! if (ANSI_NAMES && ShowAnsi(player)) { bp = buf; safe_format(buf, &bp, "%s%s%s", ANSI_HILITE, tbuf1, ANSI_NORMAL); *bp = '\0'; *** 1_8_2p3/src/wiz.c Sun Mar 11 20:21:14 2007 --- 1_8_2p4/src/wiz.c Wed May 16 22:19:20 2007 *************** *** 196,207 **** if (adjust) limit = owned + get_current_quota(who) + atoi(arg2); else ! limit = atoi(arg2); if (limit < owned) /* always have enough quota for your objects */ limit = owned; ! (void) atr_add(Owner(who), "RQUOTA", tprintf("%d", limit - owned), GOD, ! NOTHING); notify_format(player, T("Objects: %d Limit: %d"), owned, limit); } --- 196,206 ---- if (adjust) limit = owned + get_current_quota(who) + atoi(arg2); else ! limit = parse_integer(arg2); if (limit < owned) /* always have enough quota for your objects */ limit = owned; ! (void) atr_add(Owner(who), "RQUOTA", tprintf("%d", limit - owned), GOD, 0); notify_format(player, T("Objects: %d Limit: %d"), owned, limit); } *************** *** 264,273 **** } if (limit != -1) { if (limit <= owned) ! (void) atr_add(who, "RQUOTA", "0", GOD, NOTHING); else ! (void) atr_add(who, "RQUOTA", tprintf("%d", limit - owned), GOD, ! NOTHING); } } if (limit == -1) --- 263,271 ---- } if (limit != -1) { if (limit <= owned) ! (void) atr_add(who, "RQUOTA", "0", GOD, 0); else ! (void) atr_add(who, "RQUOTA", tprintf("%d", limit - owned), GOD, 0); } } if (limit == -1) *************** *** 774,780 **** notify(player, T("You cannot change that player's password.")); } else { /* it's ok, do it */ ! (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, NOTHING); notify_format(player, T("Password for %s changed."), Name(victim)); notify_format(victim, T("Your password has been changed by %s."), Name(player)); --- 772,778 ---- notify(player, T("You cannot change that player's password.")); } else { /* it's ok, do it */ ! (void) atr_add(victim, "XYXXY", mush_crypt(password), GOD, 0); notify_format(player, T("Password for %s changed."), Name(victim)); notify_format(victim, T("Your password has been changed by %s."), Name(player)); *************** *** 1824,1831 **** restriction = args[n + 1]; /* A special old-timey kludge */ if (class && !*class && restriction && *restriction) { ! if (isdigit(*restriction) || ((*restriction == '#') && *(restriction + 1) ! && isdigit(*(restriction + 1)))) { size_t offset = 0; if (*restriction == '#') offset = 1; --- 1822,1830 ---- restriction = args[n + 1]; /* A special old-timey kludge */ if (class && !*class && restriction && *restriction) { ! if (isdigit((unsigned char) *restriction) ! || ((*restriction == '#') && *(restriction + 1) ! && isdigit((unsigned char) *(restriction + 1)))) { size_t offset = 0; if (*restriction == '#') offset = 1; *************** *** 1837,1852 **** } if (!class || !*class || !restriction) continue; ! if (isdigit(*class) || ! ((*class == '#') && *(class + 1) && isdigit(*(class + 1)))) { size_t offset = 0; if (*class == '#') offset = 1; spec->low = parse_integer(class + offset); if (!GoodObject(spec->low)) spec->low = 0; ! if (isdigit(*restriction) || ((*restriction == '#') && *(restriction + 1) ! && isdigit(*(restriction + 1)))) { offset = 0; if (*restriction == '#') offset = 1; --- 1836,1853 ---- } if (!class || !*class || !restriction) continue; ! if (isdigit((unsigned char) *class) || ! ((*class == '#') && *(class + 1) ! && isdigit((unsigned char) *(class + 1)))) { size_t offset = 0; if (*class == '#') offset = 1; spec->low = parse_integer(class + offset); if (!GoodObject(spec->low)) spec->low = 0; ! if (isdigit((unsigned char) *restriction) ! || ((*restriction == '#') && *(restriction + 1) ! && isdigit((unsigned char) *(restriction + 1)))) { offset = 0; if (*restriction == '#') offset = 1; *** 1_8_2p3/test/PennMUSH.pm Sun Mar 11 20:21:16 2007 --- 1_8_2p4/test/PennMUSH.pm Wed May 16 22:19:20 2007 *************** *** 63,69 **** die "Could not start game process properly; pid $child!\n"; } elsif (defined($child)) { chdir("testgame"); ! exec("netmush", "test.cnf", "log/netmush.log"); } else { die "Could not spawn game process!\n"; } --- 63,69 ---- die "Could not start game process properly; pid $child!\n"; } elsif (defined($child)) { chdir("testgame"); ! exec("./netmush", "test.cnf", "log/netmush.log"); } else { die "Could not spawn game process!\n"; } *** 1_8_2p3/utils/mkvershlp.pl Sun Mar 11 20:21:16 2007 --- 1_8_2p4/utils/mkvershlp.pl Wed May 16 22:19:20 2007 *************** *** 1,4 **** ! #!/usr/local/bin/perl # # Generate game/txt/hlp/ files from the CHANGES file(s). # Should be run by Makefile from top-level directory --- 1,4 ---- ! #!/usr/bin/env perl # # Generate game/txt/hlp/ files from the CHANGES file(s). # Should be run by Makefile from top-level directory