This is 1.8.0p6-1.8.1p0 patch. After applyig this patch to PennMUSH 1.8.0p6, you will have version 1.8.1p0. But if you don't have any good reason not to, it's better to start with a fresh 1.8.1p0 tarball. To apply this patch, save it to a file in your top-level MUSH directory, and do the following: patch -p1 < 1.8.0p6-1.8.1p0.patch 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. - Alan/Javelin *** 1_8_0.61/Patchlevel Sat, 25 Jun 2005 12:43:00 -0500 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.43.1.6 600) --- 1_8_1.108(w)/Patchlevel Sat, 01 Jan 2005 10:41:47 -0600 dunemush (pennmush/5_Patchlevel 1.17.1.11.1.44 600) *************** *** 1,2 **** Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.0p6 --- 1,2 ---- Do not edit this file. It is maintained by the official PennMUSH patches. ! This is PennMUSH 1.8.1p0 *** 1_8_0.61/README Tue, 21 Dec 2004 10:14:22 -0600 dunemush (pennmush/4_README 1.14 600) --- 1_8_1.108(w)/README Wed, 02 Feb 2005 09:20:26 -0600 dunemush (pennmush/4_README 1.15 600) *************** *** 76,84 **** In August of 1997, Ralph Melton left the PennMUSH development team, and Thorvald Natvig joined as a new member. Many thanks go to Ralph who contributed much time, code, and good cheer to PennMUSH. ! ! Javelin, in conjunction with Talek (T. Alexander Popiel) and Thorvald ! Natvig, are the current PennMUSH development team. A MUSH manual should be available at ftp.digex.net, ftp.math.okstate.edu, primerd.prime.com, or from wherever you got this code from. The manual --- 76,90 ---- In August of 1997, Ralph Melton left the PennMUSH development team, and Thorvald Natvig joined as a new member. Many thanks go to Ralph who contributed much time, code, and good cheer to PennMUSH. ! Since that time, the development team has gained and lost members. ! The current membership is usually listed at the top of the ! latest CHANGES. file. ! ! In November 2002, with the release of PennMUSH 1.7.6, PennMUSH ! began using the Artistic License (see the COPYRITE file), ! an open source/free software license. This license was ! simultaneously adopted by TinyMUSH (2.2.5, 3.x) and TinyMUX to ! facilitate code sharing and widen use. A MUSH manual should be available at ftp.digex.net, ftp.math.okstate.edu, primerd.prime.com, or from wherever you got this code from. The manual *************** *** 87,93 **** If you are planning on modifying the source code to PennMUSH, you'll probably want Javelin's Guide for PennMUSH Gods, which should be available where you got this code, or, in hypertext, as ! http://pennmush.org/~alansz/guide.html Enjoy! --- 93,100 ---- If you are planning on modifying the source code to PennMUSH, you'll probably want Javelin's Guide for PennMUSH Gods, which should be available where you got this code, or, in hypertext, as ! http://pennmush.org/~alansz/guide.html. More recent versions ! may be available at http://community.pennmush.org. Enjoy! *** 1_8_0.61/game/txt/hlp/penntop.hlp Mon, 30 May 2005 15:53:13 -0500 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.1.1.1.1.8.1.11.1.1.1.3.2.1 600) --- 1_8_1.108(w)/game/txt/hlp/penntop.hlp Mon, 30 May 2005 16:51:59 -0500 dunemush (pennmush/13_penntop.hl 1.2.1.27.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.1.1.1.1.8.1.11.1.1.1.3.2.2 600) *************** *** 547,553 **** order of possible commands: Special game commands: WHO, QUIT, etc. - "home" command Single-token commands: ", :, ;, + Exits in the room @-commands --- 547,552 ---- *************** *** 1049,1056 **** no_quota Has an unlimited quota open_anywhere Can @open a link from any room. pemit_all Can @pemit to HAVEN/ulocked players. - poll Can use @poll command. player_create Can use @pcreate command. queue Has queue limit equal to the size of the database. quota Can use @quota commands on other players. search Can do @search, @stats, and @entrances on anything. --- 1048,1056 ---- no_quota Has an unlimited quota open_anywhere Can @open a link from any room. pemit_all Can @pemit to HAVEN/ulocked players. player_create Can use @pcreate command. + poll Can use @poll command. + pueblo_send Can use xch_cmd and send pueblo tags queue Has queue limit equal to the size of the database. quota Can use @quota commands on other players. search Can do @search, @stats, and @entrances on anything. *************** *** 1600,1605 **** --- 1600,1606 ---- %L = the dbref of the ENACTOR's location. %c = text of the last command, _before_ evaluation. %? = The current function invocation and depth counts. + %+ = The number of arguments passed to the current function. %qN = the equivalent of r(N), a register set by a setq() function. (continued in help substitutions4) *************** *** 1943,1948 **** --- 1944,1951 ---- to @command or @function. noparse Function arguments are not evaluated. Only applies to @functions. + localize %q-registers are saved/restored when evaluating, as if + the @function were wrapped in localize(). Commands can also use the 'noplayer' restriction, which stops player objects from using the command, as well as any generic *** 1_8_0.61/game/txt/hlp/pennmail.hlp Mon, 05 Apr 2004 00:46:42 -0500 dunemush (pennmush/15_pennmail.h 1.11 600) --- 1_8_1.108(w)/game/txt/hlp/pennmail.hlp Fri, 25 Feb 2005 16:26:31 -0600 dunemush (pennmush/15_pennmail.h 1.14 600) *************** *** 23,30 **** Message #'s, in which case you send to the sender of that message. An alias name (see help @malias) ! See also the following topics: mail-sending mail-reading ! mail-folders mail-other mail-admin @malias & mail-reading @mail --- 23,31 ---- Message #'s, in which case you send to the sender of that message. An alias name (see help @malias) ! See also the following topics: mail-sending mail-reading ! mail-folders mail-forward mail-other mail-admin ! @malias & mail-reading @mail *************** *** 208,210 **** --- 209,317 ---- number of aliases and members of aliases in use. @malias/chown is a wizard-only command that changes the owner of an alias. @malias/nuke is a God-only command that destroys all aliases. + & Mail functions + Mail functions work with @mail. + + folderstats() mail() maildstats() mailfrom() mailfstats() + mailsend() mailstats() mailstatus() mailsubject() mailtime() + malias() + + & FOLDERSTATS() + folderstats() + folderstats(folder#) + folderstats(player) + folderstats(player,folder#) + + FOLDERSTATS() returns the number of read, unread, and cleared messages + in a specific folder, or, if none is given, the player's current + folder. Only Wizards may use forms which get other players' mail + information. + & MAIL() + mail() + mail() + mail([:]) + mail(, [:]) + + Without arguments, mail() returns the number of messages in + all the player's mail folders. With a player name argument, + mail() returns the number of read, unread, and cleared messages + has in all folders. Only Wizards can use this on other players. + + When given numeric arguments, mail() returns the text of the + corresponding message in the current folder. The message number + may also be prefaced by the folder number and a colon, to indicate + a message in a different folder. + + Example: + > think mail(3:2) + (text of the second message in the player's third folder) + + & MAILFROM() + & MAILTIME() + & MAILSTATUS() + & MAILSUBJECT() + mailfrom([,] [:]) + mailtime([,] [:]) + mailstatus([,] [:]) + mailsubject([,] [:]) + + mailfrom() returns the dbref number of the sender of a mail message. + mailtime() is similar, but returns the time the mail was sent. + mailsubject() is similar, but returns the subject of the message. + mailstatus() returns the mail's status characters (as per + @mail/list) + + & MAILSTATS() + & MAILDSTATS() + & MAILFSTATS() + mailstats([]) + maildstats([]) + mailfstats([]) + + mail*stats() functions return data like @mail/*stats does. You + either must use this on yourself, or you must be a wizard. The + information will be joined together as a space separated list of + numbers. + + Example: + > think mailstats(One) + <# sent> <# received> + > think mailfstats(One) + <# sent> <# sent unread> <# sent cleared> <# sent bytes> <# received> + <# received unread> <# received cleared> <# received bytes> + & MAILSEND() + mailsend(,[/]) + + This function sends a message to a player, just like @mail/send. + It returns nothing if successful, or an error message. + & MALIAS() + malias([]) + malias() + malias([,]) + + With no arguments, malias() returns the list of all malias names + which are visible to the player. With two arguments, returns the list + of dbrefs that are members of the given malias, delimited by + . + + With one argument, the behavior is ambiguous. If the argument + matches a malias, returns the list of dbrefs that are memebrs of + the malias, space-delimited. If not, it's treated as a no-argument + case with a delimiter. + & mail-forward + & @mailforwardlist + @mailforwardlist me = + @lock/mailforward me = + + By setting a @mailforwardlist attribute, a player can direct that + @mail they receive should be delivered to the specified list + of dbrefs of other players. The list may include the player's own + dbref, in which case the player will receive a copy of the message, + or omit it, in which case the message will be delivered to those listed + but the player will not receive a copy. + + To deliver messages to other players this way, you must control them + (i.e. you're delivering to yourself or you're a wizard) or + pass their @lock/mailforward. An empty @lock/mailforward disallows + forwarding to you, and is the default. + *** 1_8_0.61/game/txt/hlp/pennfunc.hlp Thu, 02 Jun 2005 17:07:27 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.26.1.1.1.1 600) --- 1_8_1.108(w)/game/txt/hlp/pennfunc.hlp Thu, 02 Jun 2005 17:07:33 -0500 dunemush (pennmush/16_pennfunc.h 1.2.1.50.1.1.1.1.1.2.1.7.1.8.1.1.1.1.1.1.1.1.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.9.1.1.1.1.1.3.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.26.1.1.1.2 600) *************** *** 95,105 **** nor() not() or() t() xor() See also: BOOLEAN VALUES, @config - & Channel functions - Channel functions work with the channel system. - - cemit() cflags() channels() clock() cowner() - ctitle() cwho() & Communication functions Communication functions are side-effect functions that send a message to an object or objects. --- 95,100 ---- *************** *** 131,152 **** & Information functions Information functions return values related to objects or the game. ! andflags() andlflags() config() controls() ctime() ! elock() findable() flags() fullname() hasattr() ! hasattrp() hasflag() haspower() hastype() iname() ! lflags() lock() lstats() money() mtime() ! mudname() name() nattr() nearby() objid() ! objmem() orflags() orlflags() playermem() poll() ! powers() quota() restarts() type() version() ! visible() ! ! & Mail functions ! Mail functions work with @mail. ! ! folderstats() mail() maildstats() mailfrom() mailfstats() ! mailsend() mailstats() mailstatus() mailsubject() mailtime() ! malias() ! & List functions List functions take at least one list of elements and return transformed lists or one or more members of those lists. Most of these functions --- 126,140 ---- & Information functions Information functions return values related to objects or the game. ! alias() andflags() andlflags() config() controls() ! ctime() elock() findable() flags() fullalias() ! fullname() hasattr() hasattrp() hasflag() haspower() ! hastype() iname() lflags() lock() lstats() ! money() mtime() mudname() name() nattr() ! nearby() objid() objmem() orflags() orlflags() ! playermem() poll() powers() quota() restarts() ! type() version() visible() ! & List functions List functions take at least one list of elements and return transformed lists or one or more members of those lists. Most of these functions *************** *** 227,240 **** & Utility functions These functions don't quite fit into any other category. ! allof() ansi() atrlock() beep() checkpass() ! clone() create() die() dig() firstof() ! functions() isdbref() isint() isnum() isword() ! localize() link() list() lnum() null() ! objeval() open() pcreate() r-function rand() ! s-function scan() set() setq() setr() ! soundex() soundslike() tel() textfile() valid() ! wipe() @@() & @@() & NULL() --- 215,228 ---- & Utility functions These functions don't quite fit into any other category. ! allof() ansi() atrlock() attrib_set() beep() ! checkpass() clone() create() die() dig() ! firstof() functions() isdbref() isint() isnum() ! isword() localize() link() list() lnum() ! null() objeval() open() pcreate() r-function ! rand() s-function scan() set() setq() ! setr() soundex() soundslike() tel() textfile() ! valid() wipe() @@() & @@() & NULL() *************** *** 525,530 **** --- 513,535 ---- When given a second argument of "on" (or "off"), attempts to lock (unlock) the specified attribute, as per @atrlock. + & ATTRIB_SET() + attrib_set(/[, ]) + + Sets or clears an attribute. With a value, it sets the attribute, + without one, it clears the attribute. This is an easier-to-read + replacement for the old set(, :) notation, + and a less destructive replacement for wipe() that won't destroy + entire attribute trees in one shot. + + If there is a second argument, then attrib_set() will create an + attribute, even if the second argument is empty (in which case + attrib_set() will create an empty attribute). This means that + attrib_set(me/foo,%0) will _always_ create an attribute. + + Of course, if the empty_attrs configuration option is turned off, + then the above paragraph doesn't apply. See @config attribs. + & BAND() band(,,...) *************** *** 614,674 **** Returns the least integral value greater than or equal to . See also: floor(), bound(), round(), trunc() - & CEMIT() - cemit(, [, ]) - - Sends a message to all players listening to the given chat channel. - See help @cemit for details. - - If the third argument is a true value, the channel name will be - prepended to the message, behaving like @cemit/noisy. & CENTER() ! center(,[,]) This function will center within a field characters wide, ! using characters for padding on either end of the string for ! centering. If is not specified, a space will be used. Example: > say center(X,5,-) You say, "--X--" ! > say center(.NEAT.,15) ! You say, " .NEAT. " ! ! & CFLAGS() ! cflags() ! cflags(,) ! ! With one argument, cflags() returns a list of flags set on the ! given channel, represented as a string of characters. See ! 'help channel-list' for the list of flags (they appear in the ! "Access" column). You must be able to see the channel to use this ! function. - With two arguments, cflags() returns a list of flags for that - object on that channel, currently a string consisting of zero - or more of "G" (gagging), "Q" (muted), and "H" (hidden). - You must be able to see that channel and to examine the object - to use this function. If the object is not on the channel, an - error is returned. - & CHANNELS() - channels([]) - channels() - channels([,]) - - With no arguments, channels() returns the list of all channel names - which are visible to the player. With two arguments, returns the list - of channel names to which the object is listening, delimited by - . - - With one argument, the behavior is ambiguous. If the argument - matches an object, returns the list of names to which the object - is listening, space-delimited. If not, it's treated as a no-argument - case with a delimiter. - - If you don't have permission to examine the object, you only see - those channels to which the object belong for which you have - permission to join (or are joined to). & CHECKPASS() checkpass(,) --- 619,646 ---- Returns the least integral value greater than or equal to . See also: floor(), bound(), round(), trunc() & CENTER() ! center(,[,[,]]) This function will center within a field characters wide, ! using the string for padding on the left side of the string, ! and for padding on the right side. defaults ! to the mirror-image of if not specified. defaults to ! a space if neither nor are specified. ! ! If divides into uneven portions, the left side ! will be one character shorter than the right side. Example: > say center(X,5,-) You say, "--X--" ! > say center(X,5,-=) ! You say, "-=X=-" ! > say center(.NEAT.,15,-,=) ! You say, "----.NEAT.=====" ! > say center(hello,16,12345) ! You say, "12345hello543215" & CHECKPASS() checkpass(,) *************** *** 691,706 **** 65 > think chr(65) A - & CLOCK() - clock([/][, ]) - - With one argument, returns the value of a lock on a channel, if you - own the channel or are See_All. If no locktype is given, "JOIN" - is assumed. - With two arguments, sets the lock if you would be able to do so via - @clock. - - See also: @clock & CLONE() clone() --- 663,668 ---- *************** *** 854,863 **** You say, "0" See HELP CTU() for more on the angle type. - & COWNER() - cowner() - - Returns the dbref of the owner of a channel. & PCREATE() pcreate(,) --- 816,821 ---- *************** *** 877,888 **** If creation times are enabled, this function will return the date and time that the object was created, if the player is able to examine the object. - & CTITLE() - ctitle(,) - - Returns @chan/title on . You must either - be able to examine the object, or it must visible be on a channel - which you are allowed to join. & CTU() ctu(, , ) --- 835,840 ---- *************** *** 897,907 **** Example: > say 90 degrees is [ctu(90, d, r)] radians You say, "90 degrees is 1.570796 radians" - & CWHO() - cwho() - - This returns a list of connected dbrefs who are on . - When used by mortals, hidden/DARK players do not appear on the list. & DEC() dec() dec() --- 849,854 ---- *************** *** 921,926 **** --- 868,883 ---- Note especially the last example, which will trip you up if you use floating point numbers with dec() and expect it to work like sub(). See also: inc() + & DECOMPOSE() + decompose() + + decompose() works like escape() with the additional caveat that it inserts + parse-able characters to recreate exactly after one parsing. It + takes care of multiple spaces, '%r's, and '%t's. + + Someday, perhaps, it will also escape ansi() in a nice way. + + See also: @decompile2 & DECRYPT() decrypt(, ) *************** *** 1222,1231 **** Returns e to the power of . & EXTRACT() ! extract(,,[,]) This function returns elements of a list, counting ! from the element. For example: think extract(This is a test string,3,2) --- 1179,1191 ---- Returns e to the power of . & EXTRACT() ! extract([,[,[,]]]) This function returns elements of a list, counting ! from the element. If is not specified, the ! default is 1, so extract(list,3) acts like elements(list,3). ! If is not specified, the default is the 1, so ! extract(list) acts like first(list). For example: think extract(This is a test string,3,2) *************** *** 1383,1398 **** You say, "15" See also: anonymous attributes - & FOLDERSTATS() - folderstats() - folderstats(folder#) - folderstats(player) - folderstats(player,folder#) - - FOLDERSTATS() returns the number of read, unread, and cleared messages - in a specific folder, or, if none is given, the player's current - folder. Only Wizards may use forms which get other players' mail - information. & FOLLOWERS() followers() --- 1343,1348 ---- *************** *** 2239,2246 **** & SEARCH() & LSEARCHR() & CHILDREN() ! lsearch([, [, [, [, ]]]]) ! lsearchr([, [, [, [, ]]]]) children() This function is similar to the @search command, except it returns --- 2189,2196 ---- & SEARCH() & LSEARCHR() & CHILDREN() ! lsearch([, ,...]) ! lsearchr([, ,...]) children() This function is similar to the @search command, except it returns *************** *** 2248,2259 **** costs 100 pennies to perform. The function must have at least three arguments. Wizards can specify "all" or for the field; mortals must use "me". If you do not want to restrict ! something, use "none" for and/or . and ! restrict the search to that range of db#'s and are specified as ! dbrefs ("#2") with the #. The possible es and s are the same as those accepted ! by @search. See 'help @search' for information about them. children() is exactly the same as lsearch(,parent,), using "all" for See_All/Search_All players and "me" for others. --- 2198,2209 ---- costs 100 pennies to perform. The function must have at least three arguments. Wizards can specify "all" or for the field; mortals must use "me". If you do not want to restrict ! something, use "none" for and/or . The possible es and s are the same as those accepted ! by @search. lsearch() can accept multiple class/restriction pairs, and ! applies them in a boolean "AND" fashion, returning only dbrefs that ! fulfill all restrictions. See 'help @search' for information about them. children() is exactly the same as lsearch(,parent,), using "all" for See_All/Search_All players and "me" for others. *************** *** 2276,2283 **** Examples: ! lsearch(all, flags, Wc) <-- lists all connected wizards. lsearch(me, type, room) <-- lists all rooms owned by me. lsearch(me, type, room, 100, 200) <-- same, but only w/db# 100-200 lsearch(all, eplayer, \[eq(money(##),100)\]) <-- lists all players with 100 coins. --- 2226,2234 ---- Examples: ! lsearch(all, flags, Wc) <-- lists all connected wizards. lsearch(me, type, room) <-- lists all rooms owned by me. + lsearch(me, type, room, flag, W) <-- lists Wizard rooms owned by me. lsearch(me, type, room, 100, 200) <-- same, but only w/db# 100-200 lsearch(all, eplayer, \[eq(money(##),100)\]) <-- lists all players with 100 coins. *************** *** 2344,2422 **** 's point of view. See also: mwho(), nwho(), xwho() - & MAIL() - mail() - mail() - mail([:]) - mail(, [:]) - - Without arguments, mail() returns the number of messages in - all the player's mail folders. With a player name argument, - mail() returns the number of read, unread, and cleared messages - has in all folders. Only Wizards can use this on other players. - - When given numeric arguments, mail() returns the text of the - corresponding message in the current folder. The message number - may also be prefaced by the folder number and a colon, to indicate - a message in a different folder. - - Example: - > think mail(3:2) - (text of the second message in the player's third folder) - - & MAILFROM() - & MAILTIME() - & MAILSTATUS() - & MAILSUBJECT() - mailfrom([,] [:]) - mailtime([,] [:]) - mailstatus([,] [:]) - mailsubject([,] [:]) - - mailfrom() returns the dbref number of the sender of a mail message. - mailtime() is similar, but returns the time the mail was sent. - mailsubject() is similar, but returns the subject of the message. - mailstatus() returns the mail's status characters (as per - @mail/list) - - & MAILSTATS() - & MAILDSTATS() - & MAILFSTATS() - mailstats([]) - maildstats([]) - mailfstats([]) - - mail*stats() functions return data like @mail/*stats does. You - either must use this on yourself, or you must be a wizard. The - information will be joined together as a space separated list of - numbers. - - Example: - > think mailstats(One) - <# sent> <# received> - > think mailfstats(One) - <# sent> <# sent unread> <# sent cleared> <# sent bytes> <# received> - <# received unread> <# received cleared> <# received bytes> - & MAILSEND() - mailsend(,[/]) - - This function sends a message to a player, just like @mail/send. - It returns nothing if successful, or an error message. - & MALIAS() - malias([]) - malias() - malias([,]) - - With no arguments, malias() returns the list of all malias names - which are visible to the player. With two arguments, returns the list - of dbrefs that are members of the given malias, delimited by - . - - With one argument, the behavior is ambiguous. If the argument - matches a malias, returns the list of dbrefs that are memebrs of - the malias, space-delimited. If not, it's treated as a no-argument - case with a delimiter. - & MAP() map([/],[,][, ]) --- 2295,2300 ---- *************** *** 2671,2676 **** --- 2549,2577 ---- non-hidden players. It's exactly the same as lwho() used by a mortal, and is suitable for use on privileged global objects who need an unprivileged who-list. + & ALIAS() + alias([,]) + + Alias returns the alias of . If multiple aliases are set, + alias returns the first component of the alias. + + If function side effects are allowed, this function, given two arguments, + acts just like @alias =. + + Related functions: FULLALIAS() + + & FULLALIAS() + fullalias() + + fullalias() returns the alias of . It is identical to + alias() except when multiple aliases are set, fullalias() returns the + complete alias list. + + >"[fullalias(Noltar)] + You say, "$;No;Nol;Noli;Nolt" + + Related functions: ALIAS() + & NAME() name([,]) name([, ]) *************** *** 3296,3304 **** flags, set attributes, and many other things. The two arguments to the function are the same as the arguments that would appear on either side of the '=' in @set. This function returns nothing. ! ! Note that you can't clear an attribute with set(), though ! you can make it an empty attribute. Use wipe() to clear attributes. & SETDIFF() setdiff(, [, ][, ][, ]) --- 3197,3206 ---- flags, set attributes, and many other things. The two arguments to the function are the same as the arguments that would appear on either side of the '=' in @set. This function returns nothing. ! ! The attribute setting ability of set() is deprecated. You should ! use attrib_set() instead; it's easier to read, and allows you to ! clear attributes, too. & SETDIFF() setdiff(, [, ][, ][, ]) *************** *** 3330,3388 **** & SETQ() & SETR() ! setq(,) ! setr(,) The setq() and setr() functions are used to copy strings into local registers. setq() returns a null string; it is a purely "side effect" ! function. setr() returns the value stored. ! ! There are thirty-six local registers, numbered 0 through 9 and A through Z. ! They are cleared at the start of each new queue cycle (i.e. whenever ! a new command is evaluated). They are most useful for storing ! complex function evaluations which are used repeatedly within a ! single command. ! ! Registers set via setq() or setr() can be accessed via the r() function, or via the %qN percent-substitution. ! See "help SETQ2" for examples of its use. ! & SETQ2 ! The setq() function is probably best used at the start of the string being manipulated, such as in the following example: ! ! &TEST object=[strlen(%0)] ! &CMD object=$test *:"[setq(0,u(TEST,%0))]Test. %0 has length [r(0)]. ! test Foo ! > Object says, "Test. Foo has length 3." ! ! In this case, it is a waste to use setq(), since we only use the function ! result once, but if TEST was a complex function being used multiple times ! within the same command, it would be much more efficient to use the local ! register, since TEST would then only be evaluated once. ! ! setq() can thus be used to improve the readability of MUSH code, as well ! as to cut down the amount of time needed to do complex evaluations. ! See "help SETQ3" for scoping rules of setq(). ! & SETQ3 The registers set by setq() can be used in later commands in the same thread. That is, the registers are set to null on all $-commands, ! ^-commands, A-attribute triggers, etc., but are then retained from ! that point forward through the execution of all your code. Code ! branches like @wait and @switch retain the register values from the ! time of the branch, so the code: ! say setr(a,foo); @wait 0=say %qa; say setr(a,bar) ! produces the following when executed by an object: ! ! Object says "foo" ! Object says "bar" ! Object says "foo" & SETUNION() setunion(, [, ][, ][, ]) --- 3232,3290 ---- & SETQ() & SETR() ! setq(,[,,,...]) ! setr(,[,,,...]) The setq() and setr() functions are used to copy strings into local registers. setq() returns a null string; it is a purely "side effect" ! function. setr() returns the value stored. Multiple registers can be ! assigned with a single setq() or setr(), with additional pairs of ! registers and values in the function's arguments. In this case, ! setr() returns the value stored in the first register listed. ! ! There are thirty-six local registers, numbered 0 through 9 and A ! through Z. They are cleared at the start of each new queue cycle ! (i.e. whenever a new command is evaluated). They are most useful for ! storing complex function evaluations which are used repeatedly within ! a single command. ! ! Registers set via setq() or setr() can be accessed via the r() function, or via the %qN percent-substitution. ! See "help SETQ2" for examples of its use. ! & SETQ2 ! The setq() function is probably best used at the start of the string being manipulated, such as in the following example: ! ! &TEST object=[strlen(%0)] &CMD object=$test ! *:"[setq(0,u(TEST,%0))]Test. %0 has length [r(0)]. test Foo > ! Object says, "Test. Foo has length 3." ! ! In this case, it is a waste to use setq(), since we only use the ! function result once, but if TEST was a complex function being used ! multiple times within the same command, it would be much more efficient ! to use the local register, since TEST would then only be evaluated once. ! ! setq() can thus be used to improve the readability of MUSH code, as ! well as to cut down the amount of time needed to do complex evaluations. ! See "help SETQ3" for scoping rules of setq(). ! & SETQ3 The registers set by setq() can be used in later commands in the same thread. That is, the registers are set to null on all $-commands, ! ^-commands, A-attribute triggers, etc., but are then retained from that ! point forward through the execution of all your code. Code branches ! like @wait and @switch retain the register values from the time of ! the branch, so the code: ! say setr(a,foo); @wait 0=say %qa; say setr(a,bar) ! produces the following when executed by an object: ! ! Object says "foo" Object says "bar" Object says "foo" & SETUNION() setunion(, [, ][, ][, ]) *************** *** 4399,4405 **** & WIPE() wipe(/) ! This function is equivalent to @wipe. It returns nothing. & WORDPOS() wordpos(, [, ]) --- 4301,4309 ---- & WIPE() wipe(/) ! This function is equivalent to @wipe. It returns nothing. Like ! @wipe, this function will destroy entire attribute trees; for ! more judicious deletion, use attrib_set(). & WORDPOS() wordpos(, [, ]) *** 1_8_0.61/game/txt/hlp/pennflag.hlp Mon, 31 May 2004 08:41:25 -0500 dunemush (pennmush/17_pennflag.h 1.1.1.1.1.2.1.1.1.2.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.4.1.2.2.17 600) --- 1_8_1.108(w)/game/txt/hlp/pennflag.hlp Wed, 02 Feb 2005 13:45:00 -0600 dunemush (pennmush/17_pennflag.h 1.1.1.1.1.2.1.1.1.2.1.1.1.2.1.1.2.1.2.1.1.1.1.2.1.4.1.2.2.18 600) *************** *** 123,128 **** --- 123,149 ---- messages and broadcast them to other rooms) to be eliminated. The message is propagated only to the next room and no farther, so there is no danger of looping. + & TRACK_MONEY + Flag: TRACK_MONEY (players) + + By setting the TRACK_MONEY flag, a player can determine which + objects may be using their money. TRACK_MONEY reports all charges + to a player and their objects except the queue deposit. + + > @set me=TRACK_MONEY + > give Javelin=50 + You give 50 pennies to Javelin. + GAME: Walker spent 50 pennies! + > @create foo + GAME: Walker spent 10 pennies! + Created: Object #345. + > @for foo=@search + GAME: foo(#345) spent 100 pennies! + (search results) + > + GAME: Object Walker(#123) lost a Penny to queue loss. + + See also: no_pay & BUILDER BUILDER *** 1_8_0.61/game/txt/hlp/penncmd.hlp Wed, 02 Feb 2005 14:07:54 -0600 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.1.1.1.1.1.1.47.1.1 600) --- 1_8_1.108(w)/game/txt/hlp/penncmd.hlp Sun, 20 Mar 2005 14:07:46 -0600 dunemush (pennmush/18_penncmd.hl 1.2.1.1.1.47.1.1.1.1.1.3.1.4.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.10.1.1.1.1.1.1.1.1.1.1.1.47.1.4 600) *************** *** 278,296 **** See also: leave, @lfail, @olfail, ACTION LISTS & @alias ! @alias = ! @alias is a special attribute. When a player sets an @alias, he is ! effectively giving himself a secondary name; he can be paged by his ! @alias, and matched with *, and all other game functions which ! look up player names will also accept the alias. The attribute is ! visible to all players. ! Aliases cannot be longer than the limit allowed for player names, cannot contain spaces, and must be unique -- no other player may have the same alias or name as any other player's alias or name. @alias has no effect on non-players. & @allhalt @allhalt --- 278,306 ---- See also: leave, @lfail, @olfail, ACTION LISTS & @alias ! @alias =;[;[;[...]]] ! @alias is a special attribute that lists a player's names; players ! can be paged by their aliases, matched with *, and all other game ! functions which look up player names will also accept an alias. ! The attribute is visible to all players. ! ! A list of aliases, separated by semicolons, may be provided. ! Players should include their usual @name in the alias list, because ! the @name command allows setting name to any alias in the list. ! The number of aliases allowed in the list may be limited by ! the game's administrators through the 'max_aliases' @config parameter. ! ! If the page_aliases config directive is on, the first alias in the ! list is returned along with the player's name. ! Each alias cannot be longer than the limit allowed for player names, cannot contain spaces, and must be unique -- no other player may have the same alias or name as any other player's alias or name. @alias has no effect on non-players. + + See also: @name, alias(), fullalias() & @allhalt @allhalt *************** *** 369,375 **** See also: @success, @osuccess, get, @lock, EXITS, ACTION LISTS & @attribute @attribute ! @attribute/access[/retroactive] = @attribute/delete @attribute/rename = --- 379,385 ---- See also: @success, @osuccess, get, @lock, EXITS, ACTION LISTS & @attribute @attribute ! @attribute/access[/retroactive] = @attribute/delete @attribute/rename = *************** *** 387,394 **** @attribute/access adds a new standard attribute into the table, associating it with the given space-separated list of flags. ! See 'help @set' for possible flags. ! If the /retroactive switch is added, the flags are set on every copy of the attribute that already exists in the database. @attribute/delete removes a standard attribute from the table. --- 397,405 ---- @attribute/access adds a new standard attribute into the table, associating it with the given space-separated list of flags. ! See 'help @set' for possible flags. A flag list of "none" removes ! all flag associations. ! If the /retroactive switch is added, the flags are assigned to every copy of the attribute that already exists in the database. @attribute/delete removes a standard attribute from the table. *************** *** 672,677 **** --- 683,701 ---- for example. More complex things are, obviously, possible. See also: @exitformat, @nameformat, @descformat + & @invformat + @invformat [=] + + Replaces the usual "You are carrying:" format when an object uses the + "inventory" command, by a player-specified format. This is evaluated + as if it were a description or other similar message on the object. + The objects carried are passed as a dbref list in %0. + + One could change the format to 'You've got: Object1 Object2 Object3' + through '@invformat me = You've got: [iter(%0,name(##))]', + for example. More complex things are, obviously, possible. + + See also: inventory & @descformat @descformat [=] *************** *** 852,857 **** --- 876,886 ---- @decompile/skipdefault Don't output commands to set attribute flags if those flags are the defaults for that attribute on that MUSH. + + If an attribute contains special characters, such as %r or %t, or + begins or ends with spaces, then the command sent will be an @set command + that has its special characters escaped, and with such %rs, %ts, and %bs + as to exactly duplicate the attribute as it is currently set. (continued in help @decompile3) & @decompile3 *************** *** 1387,1393 **** All other switches to this command are restricted to God: /disable disables a flag, making it invisible and unusable /enable re-enables a disabled flag ! /alias adds a new alias for an existing flag /letter changes or removes a single-letter alias for an existing flag. /restrict changes flag permissions (see help @flag2) /type changes flag type(s) (see help @flag2) --- 1416,1422 ---- All other switches to this command are restricted to God: /disable disables a flag, making it invisible and unusable /enable re-enables a disabled flag ! /alias adds a new alias for an existing flag; use ! to delete one. /letter changes or removes a single-letter alias for an existing flag. /restrict changes flag permissions (see help @flag2) /type changes flag type(s) (see help @flag2) *************** *** 1616,1621 **** --- 1645,1651 ---- See also: enter, @enter, ENTER_OK, @describe, look, @idescformat & @hook @hook/ [=, ] + @hook/list @hook tells the command parser to evaluate given attributes at certain points in command evaluation. The possible points, indicated by the proper switch: *************** *** 1641,1647 **** the hooks. Leaving out the object and attribute clears an existing hook. Wizards can ! see existing hooks with @command. See HELP @HOOK2 for an example. & @hook2 --- 1671,1677 ---- the hooks. Leaving out the object and attribute clears an existing hook. Wizards can ! see existing hooks with @command or @hook/list. See HELP @HOOK2 for an example. & @hook2 *************** *** 2185,2196 **** names, the name should be enclosed in quotes: @name me = "James Bond" ! When changing a player's name to their alias, their current name and ! their alias are swapped. Changing the name of will cause object to execute its ONAME and ANAME. The old name will be passed at %0 to these; the new name will be passed as %1. & @newpassword @newpassword = --- 2215,2229 ---- names, the name should be enclosed in quotes: @name me = "James Bond" ! Players can change their name to any name not in use by another ! player; players may "reserve" a set of names for their use by ! setting them in their @alias. Changing the name of will cause object to execute its ONAME and ANAME. The old name will be passed at %0 to these; the new name will be passed as %1. + + See also: @alias & @newpassword @newpassword = *************** *** 2862,2867 **** --- 2895,2904 ---- See "help @search3" for more. & @search3 + If =MINDB, only objects with dbrefs of or + higher will be listed. If =MAXDB, only objects with dbrefs + of or lower will be listed. + For the class TYPE=PLAYER, and for PLAYER=, anyone may obtain information on any player. In all other cases, only wizards may obtain information about other players. This is computationally *************** *** 2874,2887 **** @search Joe eval=1,100,200 <-- list objects from #100-#200 owned by Joe. @search eval=gt(money(##),10) <-- list all objects owned by me worth more than 10 coins. ! ! If =POWERS, only objects with the given power are listed. Only ! one power may be specified. ! ! If =EVAL, only objects for which evaluates to a ! true boolean value will be listed. The token '##' in , which ! is a function, is replaced by each dbref sequentially. Classes EPLAYER, ! EROOM, EEXIT, and EOBJECT work like EVAL but are restricted to a single type. & @select @select =,[,,]...[,] This is similar to @switch, except it only executes the action --- 2911,2918 ---- @search Joe eval=1,100,200 <-- list objects from #100-#200 owned by Joe. @search eval=gt(money(##),10) <-- list all objects owned by me worth more than 10 coins. ! ! See also: lsearch, lsearchr & @select @select =,[,,]...[,] This is similar to @switch, except it only executes the action *************** *** 3877,3883 **** someone else's inventory. To be safe, @lock any objects that you do not want to lose. ! See also: score, take, drop, OPAQUE, @lock & kill kill [=] --- 3908,3914 ---- someone else's inventory. To be safe, @lock any objects that you do not want to lose. ! See also: score, take, drop, OPAQUE, @lock, @invformat & kill kill [=] *** 1_8_0.61/game/txt/hlp/pennchat.hlp Thu, 19 Aug 2004 14:13:49 -0500 dunemush (pennmush/19_pennchat.h 1.2.1.4.1.9 600) --- 1_8_1.108(w)/game/txt/hlp/pennchat.hlp Fri, 25 Feb 2005 13:28:46 -0600 dunemush (pennmush/19_pennchat.h 1.2.1.4.1.12 600) *************** *** 137,143 **** * "notitles" - chantitles are not displayed in channel messages. * "nonames" - player names are not displayed in channel messages. * "nocemit" - @cemit is prohibited on the channel. ! Specifications may be combined, space-separated. Default is "player" @channel/delete removes a channel. You must own it or be Wizard. @channel/desc sets the channel's description, shown on @channel/what. --- 137,146 ---- * "notitles" - chantitles are not displayed in channel messages. * "nonames" - player names are not displayed in channel messages. * "nocemit" - @cemit is prohibited on the channel. ! * "interact" - Interaction rules (defined in local.c) are applied to ! the channel ! Specifications may be combined, space-separated. Default is determined ! by the 'channel_flags' @config option, or 'player' if not set. @channel/delete removes a channel. You must own it or be Wizard. @channel/desc sets the channel's description, shown on @channel/what. *************** *** 235,237 **** --- 238,312 ---- >@clock/join anotherchannel=@#10/anotherchanneljoin >@lock/user:onechanneljoin #10 = 1 >@lock/user:anotherchanneljoin #10 = isunfind/1 + & COWNER() + cowner() + + Returns the dbref of the owner of a channel. + & CTITLE() + ctitle(,) + + Returns @chan/title on . You must either + be able to examine the object, or it must visible be on a channel + which you are allowed to join. + & CWHO() + cwho() + + This returns a list of connected dbrefs who are on . + When used by mortals, hidden/DARK players do not appear on the list. + & CEMIT() + cemit(, [, ]) + + Sends a message to all players listening to the given chat channel. + See help @cemit for details. + + If the third argument is a true value, the channel name will be + prepended to the message, behaving like @cemit/noisy. + & CFLAGS() + cflags() + cflags(,) + + With one argument, cflags() returns a list of flags set on the + given channel, represented as a string of characters. See + 'help channel-list' for the list of flags (they appear in the + "Access" column). You must be able to see the channel to use this + function. + + With two arguments, cflags() returns a list of flags for that + object on that channel, currently a string consisting of zero + or more of "G" (gagging), "Q" (muted), and "H" (hidden). + You must be able to see that channel and to examine the object + to use this function. If the object is not on the channel, an + error is returned. + & CHANNELS() + channels([]) + channels() + channels([,]) + + With no arguments, channels() returns the list of all channel names + which are visible to the player. With two arguments, returns the list + of channel names to which the object is listening, delimited by + . + + With one argument, the behavior is ambiguous. If the argument + matches an object, returns the list of names to which the object + is listening, space-delimited. If not, it's treated as a no-argument + case with a delimiter. + + If you don't have permission to examine the object, you only see + those channels to which the object belong for which you have + permission to join (or are joined to). + & CLOCK() + clock([/][, ]) + + With one argument, returns the value of a lock on a channel, if you + own the channel or are See_All. If no locktype is given, "JOIN" + is assumed. + With two arguments, sets the lock if you would be able to do so via + @clock. + + See also: @clock + & Channel functions + Channel functions work with the channel system. + + cemit() cflags() channels() clock() cowner() + ctitle() cwho() *** 1_8_0.61/game/restart Thu, 13 May 2004 11:43:05 -0500 dunemush (pennmush/39_restart 1.1.1.1.1.1.1.2.1.1.1.1.1.2.1.2.2.1.2.2.1.1.1.1.1.4 700) --- 1_8_1.108(w)/game/restart Tue, 18 Jan 2005 13:24:32 -0600 dunemush (pennmush/39_restart 1.1.1.1.1.1.1.2.1.1.1.1.1.2.1.2.2.1.2.2.1.1.1.1.1.4.2.1 700) *************** *** 65,74 **** # # Read the cnf file and set some variables. # ! INDB=`egrep "^input_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/"` ! OUTDB=`egrep "^output_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/"` ! PANICDB=`egrep "^crash_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/"` ! PANICDIR=`egrep "^crash_database" $CONF_FILE | sed "s/.*[ ][ ]*\(.*\)\/.*/\1/"` COMPRESSOR="cat" SUFFIX="" --- 65,74 ---- # # Read the cnf file and set some variables. # ! INDB=`egrep "^input_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/" | sed 's/\r$//'` ! OUTDB=`egrep "^output_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/" | sed 's/\r$//'` ! PANICDB=`egrep "^crash_database" $CONF_FILE | sed "s/.*[ ][ ]*.*\/\(.*\)/\1/" | sed 's/\r$//'` ! PANICDIR=`egrep "^crash_database" $CONF_FILE | sed "s/.*[ ][ ]*\(.*\)\/.*/\1/" | sed 's/\r$//'` COMPRESSOR="cat" SUFFIX="" *************** *** 76,83 **** egrep -s "^compress_program[ ]*[A-Za-z0-9]" $CONF_FILE nocompress=$? if [ $nocompress -eq 0 ]; then ! COMPRESSOR=`egrep "^compress_program" $CONF_FILE | sed "s/[^ ]*[ ]*\(.*\)/\1/"` ! SUFFIX=`egrep "^compress_suffix" $CONF_FILE | sed "s/[^ ]*[ ]*\(.*\)/\1/"` fi --- 76,83 ---- egrep -s "^compress_program[ ]*[A-Za-z0-9]" $CONF_FILE nocompress=$? if [ $nocompress -eq 0 ]; then ! COMPRESSOR=`egrep "^compress_program" $CONF_FILE | sed "s/[^ ]*[ ]*\(.*\)/\1/" | sed 's/\r$//'` ! SUFFIX=`egrep "^compress_suffix" $CONF_FILE | sed "s/[^ ]*[ ]*\(.*\)/\1/" | sed 's/\r$//'` fi *** 1_8_0.61/game/mushcnf.dst Tue, 23 Nov 2004 14:13:24 -0600 dunemush (pennmush/41_mushcnf.ds 1.1.1.19.1.1.1.2.1.1.1.8.1.1.1.1.1.34.1.1 600) --- 1_8_1.108(w)/game/mushcnf.dst Wed, 08 Jun 2005 18:17:00 -0500 dunemush (pennmush/41_mushcnf.ds 1.1.1.19.1.1.1.2.1.1.1.8.1.1.1.1.1.34.1.3 600) *************** *** 377,382 **** --- 377,387 ---- # actual maximum length you want. player_name_len 16 + # The maximum number of aliases a player may have simultaneously. + # Setting this to 0 disables aliases. To allow an unlimited number + # of aliases, set this to 4000 or so. + max_aliases 3 + # Limit the number of objects players can own. use_quota yes *************** *** 808,813 **** --- 813,824 ---- # See the explanation for rooms and no_command. thing_flags no_command + # -- Default flags for newly created channels + # + # For example, you might want: + # channel_flags player quiet open hide_ok + channel_flags player + ### ### Reserved command names, and command and function aliases are in ### alias.cnf *** 1_8_0.61/src/wiz.c Sat, 04 Jun 2005 22:07:33 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.17.1.9.1.30.1.3.1.2.1.1.1.4.1.1 660) --- 1_8_1.108(w)/src/wiz.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/23_wiz.c 1.44.1.1.1.1.1.2.1.7.1.1.1.1.1.1.1.1.1.1.1.8.1.2.2.2.1.2.1.1.1.1.1.1.1.2.1.1.1.2.2.17.1.9.1.30.1.3.1.2.1.1.1.4.1.2 660) *************** *** 59,70 **** #endif #endif static int tport_dest_ok(dbref player, dbref victim, dbref dest); static int tport_control_ok(dbref player, dbref victim, dbref loc); static int mem_usage(dbref thing); ! static int raw_search(dbref player, const char *owner, const char *class, ! const char *restriction, const char *start, ! const char *stop, dbref **result, PE_Info * pe_info); #ifdef INFO_SLAVE void kill_info_slave(void); --- 59,85 ---- #endif #endif + struct search_spec { + dbref owner; /**< Limit to this owner, if specified */ + int type; /**< Limit to this type */ + dbref parent; /**< Limit to children of this parent */ + dbref zone; /**< Limit to those in this zone */ + char flags[BUFFER_LEN]; /**< Limit to those with these flags */ + char lflags[BUFFER_LEN]; /**< Limit to those with these flags */ + char powers[BUFFER_LEN]; /**< Limit to those with these powers */ + char eval[BUFFER_LEN]; /**< Limit to those where this evals true */ + char name[BUFFER_LEN]; /**< Limit to those prefix-matching this name */ + dbref low; /**< Limit to dbrefs here or higher */ + dbref high; /**< Limit to dbrefs here or lower */ + }; + static int tport_dest_ok(dbref player, dbref victim, dbref dest); static int tport_control_ok(dbref player, dbref victim, dbref loc); static int mem_usage(dbref thing); ! static int raw_search(dbref player, const char *owner, int nargs, ! const char **args, dbref **result, PE_Info * pe_info); ! static int fill_search_spec(dbref player, const char *owner, int nargs, ! const char **args, struct search_spec *spec); #ifdef INFO_SLAVE void kill_info_slave(void); *************** *** 1165,1173 **** tbuf[0] = '\0'; } } ! ! nresults = raw_search(player, tbuf, arg2, arg3[1], arg3[2], arg3[3], ! &results, NULL); if (nresults == 0) { notify(player, T("Nothing found.")); --- 1180,1193 ---- tbuf[0] = '\0'; } } ! { ! const char *myargs[4]; ! myargs[0] = arg2; ! myargs[1] = arg3[1]; ! myargs[2] = arg3[2]; ! myargs[3] = arg3[3]; ! nresults = raw_search(player, tbuf, 4, myargs, &results, NULL); ! } if (nresults == 0) { notify(player, T("Nothing found.")); *************** *** 1238,1244 **** } if (nthings) { ! notify(player, "\nOBJECTS:"); for (n = 0; n < nthings; n++) { tbp = tbuf; safe_format(tbuf, &tbp, "%s [owner: ", --- 1258,1264 ---- } if (nthings) { ! notify(player, "\nTHINGS:"); for (n = 0; n < nthings; n++) { tbp = tbuf; safe_format(tbuf, &tbp, "%s [owner: ", *************** *** 1268,1274 **** notify(player, T("---------- Search Done ----------")); notify_format(player, T ! ("Totals: Rooms...%d Exits...%d Objects...%d Players...%d"), nrooms, nexits, nthings, nplayers); mush_free((Malloc_t) rooms, "dbref_list"); mush_free((Malloc_t) exits, "dbref_list"); --- 1288,1294 ---- notify(player, T("---------- Search Done ----------")); notify_format(player, T ! ("Totals: Rooms...%d Exits...%d Things...%d Players...%d"), nrooms, nexits, nthings, nplayers); mush_free((Malloc_t) rooms, "dbref_list"); mush_free((Malloc_t) exits, "dbref_list"); *************** *** 1290,1301 **** return; } ! if (!strcmp(called_as, "CHILDREN")) ! nresults = raw_search(executor, NULL, "PARENT", args[0], NULL, ! NULL, &results, pe_info); ! else ! nresults = raw_search(executor, args[0], args[1], args[2], args[3], args[4], ! &results, pe_info); if (nresults < 0) { safe_str("#-1", buff, bp); --- 1310,1324 ---- return; } ! if (!strcmp(called_as, "CHILDREN")) { ! const char *myargs[2]; ! myargs[0] = "PARENT"; ! myargs[1] = args[0]; ! nresults = raw_search(executor, NULL, 2, myargs, &results, pe_info); ! } else ! nresults = ! raw_search(executor, args[0], nargs - 1, (const char **) (args + 1), ! &results, pe_info); if (nresults < 0) { safe_str("#-1", buff, bp); *************** *** 1329,1654 **** } - /** Type of limitation to apply to a search of the db */ - enum search_class { - S_OWNER, /**< Limit to a single owner */ - S_TYPE, /**< Limit to a single type */ - S_PARENT, /**< Limit to objects with a given parent */ - S_ZONE, /**< Limit to objects in a given zone */ - S_FLAG, /**< Limit to objects with given flag characters */ - S_POWER, /**< Limit to objects with given power */ - S_EVAL, /**< Limit to objects for which an expression evals true */ - S_NAME, /**< Limit to objects prefix-matching a given name */ - S_LFLAG /**< Limit to objects with given flag names */ - }; - - /* Does the actual searching */ - static int - raw_search(dbref player, const char *owner, const char *class, - const char *restriction, const char *start, const char *stop, - dbref **result, PE_Info * pe_info) - { - size_t result_size; - size_t nresults = 0; - enum search_class sclass = S_OWNER; - int n; - int restrict_type = NOTYPE; - dbref restrict_obj = NOTHING, restrict_owner = ANY_OWNER; - int is_wiz; - dbref low = 0, high = db_top - 1; - - is_wiz = Search_All(player) || See_All(player); - - /* Range limits */ - if (start && *start) { - size_t offset = 0; - if (start[0] == '#') - offset = 1; - low = parse_integer(start + offset); - if (!GoodObject(low)) - low = 0; - } - if (stop && *stop) { - size_t offset = 0; - if (stop[0] == '#') - offset = 1; - high = parse_integer(stop + offset); - if (!GoodObject(high)) - high = db_top - 1; - } - - /* set limits on who we search */ - if (!owner || !*owner || strcasecmp(owner, "all") == 0) - restrict_owner = is_wiz ? ANY_OWNER : player; - else if (strcasecmp(owner, "me") == 0) - restrict_owner = player; - else - restrict_owner = lookup_player(owner); - if (restrict_owner == NOTHING) { - notify(player, T("Unknown owner.")); - return -1; - } - - /* Figure out the class */ - if (!class || !*class || strcasecmp(class, "none") == 0) { - sclass = S_OWNER; - } else if (string_prefix("type", class)) { - sclass = S_TYPE; - if (string_prefix("things", restriction) - || string_prefix("objects", restriction)) { - restrict_type = TYPE_THING; - } else if (string_prefix("rooms", restriction)) { - restrict_type = TYPE_ROOM; - } else if (string_prefix("exits", restriction)) { - restrict_type = TYPE_EXIT; - } else if (string_prefix("rooms", restriction)) { - restrict_type = TYPE_ROOM; - } else if (string_prefix("players", restriction)) { - restrict_type = TYPE_PLAYER; - } else { - notify(player, T("Unknown type.")); - return -1; - } - } else if (string_prefix("things", class) || string_prefix("objects", class)) { - sclass = S_NAME; - restrict_type = TYPE_THING; - } else if (string_prefix("exits", class)) { - sclass = S_NAME; - restrict_type = TYPE_EXIT; - } else if (string_prefix("rooms", class)) { - sclass = S_NAME; - restrict_type = TYPE_ROOM; - } else if (string_prefix("players", class)) { - sclass = S_NAME; - restrict_type = TYPE_PLAYER; - } else if (string_prefix("name", class)) { - sclass = S_NAME; - } else if (string_prefix("parent", class)) { - sclass = S_PARENT; - if (!is_objid(restriction)) { - notify(player, T("Unknown parent.")); - return -1; - } - restrict_obj = parse_objid(restriction); - if (!GoodObject(restrict_obj)) { - notify(player, T("Unknown parent.")); - return -1; - } - } else if (string_prefix("zone", class)) { - sclass = S_ZONE; - if (!is_objid(restriction)) { - notify(player, T("Unknown zone.")); - return -1; - } - restrict_obj = parse_objid(restriction); - if (!GoodObject(restrict_obj)) { - notify(player, T("Unknown zone.")); - return -1; - } - } else if (string_prefix("eval", class)) { - sclass = S_EVAL; - } else if (string_prefix("ethings", class) || - string_prefix("eobjects", class)) { - sclass = S_EVAL; - restrict_type = TYPE_THING; - } else if (string_prefix("eexits", class)) { - sclass = S_EVAL; - restrict_type = TYPE_EXIT; - } else if (string_prefix("erooms", class)) { - sclass = S_EVAL; - restrict_type = TYPE_ROOM; - } else if (string_prefix("eplayers", class)) { - sclass = S_EVAL; - restrict_type = TYPE_PLAYER; - } else if (string_prefix("powers", class)) { - /* Handle the checking later. */ - sclass = S_POWER; - if (!restriction || !*restriction) { - notify(player, T("You must give a list of power names.")); - return -1; - } - } else if (string_prefix("flags", class)) { - /* Handle the checking later. */ - sclass = S_FLAG; - if (!restriction || !*restriction) { - notify(player, T("You must give a string of flag characters.")); - return -1; - } - } else if (string_prefix("lflags", class)) { - /* Handle the checking later. */ - sclass = S_LFLAG; - if (!restriction || !*restriction) { - notify(player, T("You must give a list of flag names.")); - return -1; - } - } else { - notify(player, T("Unknown search class.")); - return -1; - } - - if ((restrict_owner != ANY_OWNER && restrict_owner != player) && - !(is_wiz || (sclass == S_TYPE && restrict_type == TYPE_PLAYER))) { - notify(player, T("You need a search warrant to do that.")); - return -1; - } - - /* make sure player has money to do the search */ - if (!payfor(player, FIND_COST)) { - notify_format(player, T("Searches cost %d %s."), FIND_COST, - ((FIND_COST == 1) ? MONEY : MONIES)); - return -1; - } - - result_size = (db_top / 4) + 1; - *result = - (dbref *) mush_malloc(sizeof(dbref) * result_size, "search_results"); - if (!*result) - mush_panic(T("Couldn't allocate memory in search!")); - - switch (sclass) { - case S_OWNER: /* @search someone */ - case S_TYPE: /* @search type=whatever */ - for (n = low; n <= high; n++) { - if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && (restrict_type == NOTYPE || Typeof(n) == restrict_type)) { - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = (dbref *) realloc((Malloc_t) *result, - sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - (*result)[nresults++] = (dbref) n; - } - } - break; - case S_ZONE: /* @search ZONE=#1234 */ - for (n = low; n <= high; n++) { - if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && Zone(n) == restrict_obj) { - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = - (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - - (*result)[nresults++] = (dbref) n; - } - } - break; - case S_PARENT: /* @search parent=#1234 */ - for (n = low; n <= high; n++) { - if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && Parent(n) == restrict_obj) { - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = - (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - - (*result)[nresults++] = (dbref) n; - } - } - break; - case S_NAME: /* @search (?:name|exits|objects|rooms|players|things)=name */ - for (n = low; n <= high; n++) { - if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && (restrict_type == NOTYPE || Typeof(n) == restrict_type) - && string_match(Name(n), restriction)) { - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = - (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - - (*result)[nresults++] = (dbref) n; - } - } - break; - case S_EVAL: /* @search (?:eval|ething|eroom|eplayer|eexit)=code */ - { - char *ebuf1; - const char *ebuf2; - char tbuf1[BUFFER_LEN]; - char *bp; - - if (!restriction || !*restriction) - break; - - for (n = low; n <= high; n++) { - if (!((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && (restrict_type == NOTYPE || Typeof(n) == restrict_type))) - continue; - - ebuf1 = replace_string("##", unparse_dbref(n), restriction); - ebuf2 = ebuf1; - bp = tbuf1; - process_expression(tbuf1, &bp, &ebuf2, player, player, player, - PE_DEFAULT, PT_DEFAULT, pe_info); - mush_free((Malloc_t) ebuf1, "replace_string.buff"); - *bp = '\0'; - if (!parse_boolean(tbuf1)) - continue; - - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = - (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - (*result)[nresults++] = (dbref) n; - if (pe_info && pe_info->fun_invocations >= FUNCTION_LIMIT) - break; - } - } - break; - case S_FLAG: - case S_LFLAG: - case S_POWER: - for (n = low; n <= high; n++) { - if ((restrict_owner == ANY_OWNER || Owner(n) == restrict_owner) - && (restrict_type == NOTYPE || Typeof(n) == restrict_type) - && ((sclass == S_POWER) ? - flaglist_check_long("POWER", player, n, restriction, 1) : - ((sclass == S_FLAG) ? - flaglist_check("FLAG", player, n, restriction, 1) - : flaglist_check_long("FLAG", player, n, restriction, 1)))) { - if (nresults >= result_size) { - dbref *newresults; - result_size *= 2; - newresults = - (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); - if (!newresults) - mush_panic(T("Couldn't reallocate memory in search!")); - *result = newresults; - } - - (*result)[nresults++] = (dbref) n; - } - } - break; - } - - return (int) nresults; - } - #ifdef WIN32 #pragma warning( disable : 4761) /* Disable bogus conversion warning */ #endif --- 1352,1357 ---- *************** *** 2068,2070 **** --- 1771,2054 ---- #endif /* WIN32 */ exit(1); /* Shouldn't ever get here, but just in case... */ } + + + static int + fill_search_spec(dbref player, const char *owner, int nargs, const char **args, + struct search_spec *spec) + { + int n; + int is_wiz; + const char *class, *restriction; + + spec->zone = spec->parent = spec->owner = ANY_OWNER; + spec->type = NOTYPE; + strcpy(spec->flags, ""); + strcpy(spec->lflags, ""); + strcpy(spec->powers, ""); + strcpy(spec->eval, ""); + strcpy(spec->name, ""); + spec->low = 0; + spec->high = db_top - 1; + + is_wiz = Search_All(player) || See_All(player); + /* set limits on who we search */ + if (!owner || !*owner || strcasecmp(owner, "all") == 0) + spec->owner = is_wiz ? ANY_OWNER : player; + else if (strcasecmp(owner, "me") == 0) + spec->owner = player; + else + spec->owner = lookup_player(owner); + if (spec->owner == NOTHING) { + notify(player, T("Unknown owner.")); + return -1; + } + + for (n = 0; n < nargs - 1; n += 2) { + class = args[n]; + 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; + spec->high = parse_integer(restriction + offset); + if (!GoodObject(spec->high)) + spec->high = db_top - 1; + continue; + } + } + 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; + spec->high = parse_integer(restriction + offset); + if (!GoodObject(spec->high)) + spec->high = db_top - 1; + + } + continue; + } + /* Figure out the class */ + /* Old-fashioned way to select everything */ + if (string_prefix("none", class)) + continue; + if (string_prefix("mindb", class)) { + size_t offset = 0; + if (*restriction == '#') + offset = 1; + spec->low = parse_integer(restriction + offset); + if (!GoodObject(spec->low)) + spec->low = 0; + continue; + } else if (string_prefix("maxdb", class)) { + size_t offset = 0; + if (*restriction == '#') + offset = 1; + spec->high = parse_integer(restriction + offset); + if (!GoodObject(spec->high)) + spec->low = db_top - 1; + continue; + } + + if (string_prefix("type", class)) { + if (string_prefix("things", restriction) + || string_prefix("objects", restriction)) { + spec->type = TYPE_THING; + } else if (string_prefix("rooms", restriction)) { + spec->type = TYPE_ROOM; + } else if (string_prefix("exits", restriction)) { + spec->type = TYPE_EXIT; + } else if (string_prefix("rooms", restriction)) { + spec->type = TYPE_ROOM; + } else if (string_prefix("players", restriction)) { + spec->type = TYPE_PLAYER; + } else { + notify(player, T("Unknown type.")); + return -1; + } + } else if (string_prefix("things", class) + || string_prefix("objects", class)) { + strcpy(spec->name, restriction); + spec->type = TYPE_THING; + } else if (string_prefix("exits", class)) { + strcpy(spec->name, restriction); + spec->type = TYPE_EXIT; + } else if (string_prefix("rooms", class)) { + strcpy(spec->name, restriction); + spec->type = TYPE_ROOM; + } else if (string_prefix("players", class)) { + strcpy(spec->name, restriction); + spec->type = TYPE_PLAYER; + } else if (string_prefix("name", class)) { + strcpy(spec->name, restriction); + } else if (string_prefix("parent", class)) { + if (!*restriction) { + spec->parent = NOTHING; + continue; + } + if (!is_objid(restriction)) { + notify(player, T("Unknown parent.")); + return -1; + } + spec->parent = parse_objid(restriction); + if (!GoodObject(spec->parent)) { + notify(player, T("Unknown parent.")); + return -1; + } + } else if (string_prefix("zone", class)) { + if (!*restriction) { + spec->zone = NOTHING; + continue; + } + if (!is_objid(restriction)) { + notify(player, T("Unknown zone.")); + return -1; + } + spec->zone = parse_objid(restriction); + if (!GoodObject(spec->zone)) { + notify(player, T("Unknown zone.")); + return -1; + } + } else if (string_prefix("eval", class)) { + strcpy(spec->eval, restriction); + } else if (string_prefix("ethings", class) || + string_prefix("eobjects", class)) { + strcpy(spec->eval, restriction); + spec->type = TYPE_THING; + } else if (string_prefix("eexits", class)) { + strcpy(spec->eval, restriction); + spec->type = TYPE_EXIT; + } else if (string_prefix("erooms", class)) { + strcpy(spec->eval, restriction); + spec->type = TYPE_ROOM; + } else if (string_prefix("eplayers", class)) { + strcpy(spec->eval, restriction); + spec->type = TYPE_PLAYER; + } else if (string_prefix("powers", class)) { + /* Handle the checking later. */ + if (!restriction || !*restriction) { + notify(player, T("You must give a list of power names.")); + return -1; + } + strcpy(spec->powers, restriction); + } else if (string_prefix("flags", class)) { + /* Handle the checking later. */ + if (!restriction || !*restriction) { + notify(player, T("You must give a string of flag characters.")); + return -1; + } + strcpy(spec->flags, restriction); + } else if (string_prefix("lflags", class)) { + /* Handle the checking later. */ + if (!restriction || !*restriction) { + notify(player, T("You must give a list of flag names.")); + return -1; + } + strcpy(spec->lflags, restriction); + } else { + notify(player, T("Unknown search class.")); + return -1; + } + } + return 0; + } + + + /* Does the actual searching */ + static int + raw_search(dbref player, const char *owner, int nargs, const char **args, + dbref **result, PE_Info * pe_info) + { + size_t result_size; + size_t nresults = 0; + int n; + int is_wiz; + struct search_spec spec; + + /* make sure player has money to do the search */ + if (!payfor(player, FIND_COST)) { + notify_format(player, T("Searches cost %d %s."), FIND_COST, + ((FIND_COST == 1) ? MONEY : MONIES)); + return -1; + } + + if (fill_search_spec(player, owner, nargs, args, &spec) < 0) + return -1; + + is_wiz = Search_All(player) || See_All(player); + + if ((spec.owner != ANY_OWNER && spec.owner != player) && + !(is_wiz || (spec.type == TYPE_PLAYER))) { + notify(player, T("You need a search warrant to do that.")); + return -1; + } + + result_size = (db_top / 4) + 1; + *result = + (dbref *) mush_malloc(sizeof(dbref) * result_size, "search_results"); + if (!*result) + mush_panic(T("Couldn't allocate memory in search!")); + + for (n = spec.low; n <= spec.high; n++) { + if (spec.owner != ANY_OWNER && Owner(n) != spec.owner) + continue; + if (spec.type != NOTYPE && Typeof(n) != spec.type) + continue; + if (spec.zone != ANY_OWNER && Zone(n) != spec.zone) + continue; + if (spec.parent != ANY_OWNER && Parent(n) != spec.parent) + continue; + if (*spec.name && !string_match(Name(n), spec.name)) + continue; + if (*spec.flags && !flaglist_check("FLAG", player, n, spec.flags, 1)) + continue; + if (*spec.lflags && !flaglist_check_long("FLAG", player, n, spec.lflags, 1)) + continue; + if (*spec.powers + && !flaglist_check_long("POWER", player, n, spec.powers, 1)) + continue; + if (*spec.eval) { + char *ebuf1; + const char *ebuf2; + char tbuf1[BUFFER_LEN]; + char *bp; + + ebuf1 = replace_string("##", unparse_dbref(n), spec.eval); + ebuf2 = ebuf1; + bp = tbuf1; + process_expression(tbuf1, &bp, &ebuf2, player, player, player, + PE_DEFAULT, PT_DEFAULT, pe_info); + mush_free((Malloc_t) ebuf1, "replace_string.buff"); + *bp = '\0'; + if (!parse_boolean(tbuf1)) + continue; + } + if (nresults >= result_size) { + dbref *newresults; + result_size *= 2; + newresults = + (dbref *) realloc((Malloc_t) *result, sizeof(dbref) * result_size); + if (!newresults) + mush_panic(T("Couldn't reallocate memory in search!")); + *result = newresults; + } + + (*result)[nresults++] = (dbref) n; + } + + return (int) nresults; + } *** 1_8_0.61/src/utils.c Thu, 02 Sep 2004 11:03:05 -0500 dunemush (pennmush/b/27_utils.c 1.30.1.1.1.23 660) --- 1_8_1.108(w)/src/utils.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/27_utils.c 1.30.1.1.1.27 660) *************** *** 530,535 **** --- 530,577 ---- return low + (n % x); } + /** Return an object's alias. We expect a valid object. + * \param it dbref of object. + * \return object's complete alias. + */ + char * + fullalias(dbref it) + { + static char n[BUFFER_LEN]; /* STATIC */ + ATTR *a = atr_get_noparent(it, "ALIAS"); + + if (!a) + return '\0'; + + strncpy(n, atr_value(a), BUFFER_LEN - 1); + n[BUFFER_LEN - 1] = '\0'; + + return n; + } + + /** Return only the first component of an object's alias. We expect + * a valid object. + * \param it dbref of object. + * \return object's short alias. + */ + char * + shortalias(dbref it) + { + static char n[BUFFER_LEN]; /* STATIC */ + char *s; + + s = fullalias(it); + if (!(s && *s)) + return '\0'; + + strncpy(n, s, BUFFER_LEN - 1); + n[BUFFER_LEN - 1] = '\0'; + if ((s = strchr(n, ';'))) + *s = '\0'; + + return n; + } + /** Return an object's name, but for exits, return just the first * component. We expect a valid object. * \param it dbref of object. *************** *** 614,621 **** /* If it's an audible message, it must pass your Interact_Lock * (or be from a privileged speaker) */ ! if ((type == INTERACT_HEAR) && !Pemit_All(from) ! && !eval_lock(from, to, Interact_Lock)) return 0; /* You can interact with the object you are in or any objects --- 656,662 ---- /* If it's an audible message, it must pass your Interact_Lock * (or be from a privileged speaker) */ ! if ((type == INTERACT_HEAR) && !Pass_Interact_Lock(from, to)) return 0; /* You can interact with the object you are in or any objects *** 1_8_0.61/src/htab.c Wed, 05 May 2004 23:48:09 -0500 dunemush (pennmush/b/30_htab.c 1.8.1.13 660) --- 1_8_1.108(w)/src/htab.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/b/30_htab.c 1.8.1.16 660) *************** *** 282,288 **** hash_new(HASHTAB *htab, const char *key) { int hval; - size_t keylen; HASHENT *hptr, *curr, *old; hptr = hash_find(htab, key); --- 282,287 ---- *************** *** 294,302 **** hval = hash_val(key, htab->mask); htab->entries++; ! keylen = strlen(key) + 1; ! hptr = (HASHENT *) mush_malloc(HASHENT_SIZE + keylen, "hash_entry"); ! memcpy(hptr->key, key, keylen); hptr->data = NULL; if (!htab->buckets[hval] || strcmp(key, htab->buckets[hval]->key) < 0) { --- 293,300 ---- hval = hash_val(key, htab->mask); htab->entries++; ! hptr = (HASHENT *) mush_malloc(HASHENT_SIZE, "hash_entry"); ! hptr->key = mush_strdup(key, "hash_key"); hptr->data = NULL; if (!htab->buckets[hval] || strcmp(key, htab->buckets[hval]->key) < 0) { *************** *** 349,355 **** return -1; hptr->data = hashdata; - /* hptr->extra_size = extra_size; */ return 0; } --- 347,352 ---- *************** *** 374,379 **** --- 371,377 ---- htab->buckets[hval] = hptr->next; else last->next = hptr->next; + mush_free(hptr->key, "hash_key"); mush_free(hptr, "hash_entry"); htab->entries--; return; *************** *** 400,405 **** --- 398,404 ---- while (hent != NULL) { thent = hent; hent = hent->next; + mush_free(thent->key, "hash_key"); mush_free(thent, "hash_entry"); } htab->buckets[i] = NULL; *************** *** 558,564 **** if (htab->buckets[n]) { for (b = htab->buckets[n]; b; b = b->next) { chain++; ! bytes += strlen(b->key) + 1 /* + b->extra_size */ ; } if (chain > longest) longest = chain; --- 557,563 ---- if (htab->buckets[n]) { for (b = htab->buckets[n]; b; b = b->next) { chain++; ! bytes += strlen(b->key) + 1; } if (chain > longest) longest = chain; *** 1_8_0.61/src/privtab.c Sat, 29 Mar 2003 13:08:58 -0600 dunemush (pennmush/b/31_privtab.c 1.7 660) --- 1_8_1.108(w)/src/privtab.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/31_privtab.c 1.8 660) *************** *** 68,73 **** --- 68,125 ---- return ((origprivs | yes) & ~no); } + /** Convert a string to 2 sets of privilege bits, privs to set and + * privs to clear. + * \param table pointer to a privtab. + * \param str a space-separated string of privilege names to apply. + * \param setprivs pointer to address to store privileges to set. + * \param clrprivs pointer to address to store privileges to clear. + * \retval 1 string successfully parsed for bits with no errors. + * \retval 0 string contained no privs + * \retval -1 string at least one name matched no privs. + */ + int + string_to_privsets(PRIV *table, const char *str, int *setprivs, int *clrprivs) + { + PRIV *c; + char *p, *r; + char tbuf1[BUFFER_LEN]; + int not; + int words = 0; + int err = 0; + int found = 0; + + *setprivs = *clrprivs = 0; + if (!str || !*str) + return 0; + strcpy(tbuf1, str); + r = trim_space_sep(tbuf1, ' '); + while ((p = split_token(&r, ' '))) { + words++; + not = 0; + if (*p == '!') { + not = 1; + if (!*++p) { + err = 1; + continue; + } + } + for (c = table; c->name; c++) { + if (string_prefix(c->name, p)) { + found++; + if (not) + *clrprivs |= c->bits_to_set; + else + *setprivs |= c->bits_to_set; + break; + } + } + } + if (err || (words != found)) + return -1; + return 1; + } + /** Convert a letter string to a set of privilege bits, masked by an original set. * Given a privs table, a letter string, and an original set of privileges, * return a modified set of privileges by applying the privs in the *** 1_8_0.61/src/strutil.c Sun, 08 Aug 2004 16:28:50 -0500 dunemush (pennmush/b/33_strutil.c 1.28.1.3.1.3.1.7.2.1.1.2.1.1.1.1.1.1.1.21.1.2.1.2.1.23 660) --- 1_8_1.108(w)/src/strutil.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/33_strutil.c 1.28.1.3.1.3.1.7.2.1.1.2.1.1.1.1.1.1.1.21.1.2.1.2.1.24 660) *************** *** 1605,1610 **** --- 1605,1635 ---- } } + /** Reverse an ansi string, preserving its ansification. + * This function destructively modifies the ansi_string passed. + * \param as pointer to an ansi string. + */ + void + flip_ansi_string(ansi_string *as) + { + int p, n; + + populate_codes(as); + + for (p = 0, n = as->len - 1; p < n; p++, n--) { + char *tcode; + char t; + + tcode = as->codes[p]; + t = as->text[p]; + as->codes[p] = as->codes[n]; + as->text[p] = as->text[n]; + as->codes[n] = tcode; + as->text[n] = t; + } + } + + static int is_ansi_code(const char *s); static int is_start_html_code(const char *s) __attribute__ ((__unused__)); static int is_end_html_code(const char *s); *** 1_8_0.61/src/speech.c Sat, 04 Jun 2005 14:30:47 -0500 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.3.1.1.5.1.1.1.6.1.1.1.7.1.1.3.1.1.1 660) --- 1_8_1.108(w)/src/speech.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/35_speech.c 1.21.1.2.1.3.1.5.1.1.1.7.1.3.1.1.1.8.1.1.1.1.1.1.1.10.1.2.1.13.2.4.1.1.3.1.1.5.1.1.1.6.1.1.1.7.1.1.3.1.1.2 660) *************** *** 652,657 **** --- 652,658 ---- int fails_lock; int is_haven; ATTR *a; + char *alias; tp2 = tbuf2 = (char *) mush_malloc(BUFFER_LEN, "string"); if (!tbuf2) *************** *** 861,868 **** message); /* Figure out the 'name' of the player */ ! if (PAGE_ALIASES && (a = atr_get_noparent(player, "ALIAS"))) ! current = tprintf("%s (%s)", Name(player), atr_value(a)); else current = (char *) Name(player); --- 862,869 ---- message); /* Figure out the 'name' of the player */ ! if (PAGE_ALIASES && (alias = shortalias(player)) && *alias) ! current = tprintf("%s (%s)", Name(player), alias); else current = (char *) Name(player); *** 1_8_0.61/src/set.c Sun, 16 Jan 2005 14:49:02 -0600 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.1.1.1.1.1.1.1.1.1.1.42 660) --- 1_8_1.108(w)/src/set.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/38_set.c 1.26.1.5.1.1.2.1.1.1.1.1.1.11.1.1.1.1.1.1.1.1.1.1.1.1.1.49 660) *************** *** 60,67 **** do_name(dbref player, const char *name, char *newname) { dbref thing; - ATTR *a = NULL; - char alias[BUFFER_LEN]; char *password; char *myenv[10]; int i; --- 60,65 ---- *************** *** 116,134 **** password++; } } ! a = atr_get_noparent(thing, "ALIAS"); ! if (a) ! strcpy(alias, atr_value(a)); ! if (strcasecmp(newname, Name(thing)) ! && !(a && !strcasecmp(newname, alias)) /* Swap alias, name */ ! &&!ok_player_name(newname, thing)) { ! /* strcasecmp allows changing foo to Foo, etc. */ notify(player, T("You can't give a player that name.")); return; } - if (a && strcasecmp(alias, newname)) { - a = NULL; - } /* everything ok, notify */ do_log(LT_CONN, 0, 0, T("Name change by %s(#%d) to %s"), Name(thing), thing, newname); --- 114,123 ---- password++; } } ! if (!ok_player_name(newname, player, thing)) { notify(player, T("You can't give a player that name.")); return; } /* everything ok, notify */ do_log(LT_CONN, 0, 0, T("Name change by %s(#%d) to %s"), Name(thing), thing, newname); *************** *** 153,168 **** for (i = 2; i < 10; i++) myenv[i] = NULL; ! if (IsPlayer(thing) && !a) ! delete_player(thing, NULL); ! else if (a) ! atr_add(thing, "ALIAS", Name(thing), player, 0); ! set_name(thing, newname); - if (IsPlayer(thing) && !a) - add_player(thing, NULL); - if (!AreQuiet(player, thing)) notify(player, T("Name set.")); real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING, --- 142,151 ---- for (i = 2; i < 10; i++) myenv[i] = NULL; ! if (IsPlayer(thing)) ! reset_player_list(thing, Name(thing), NULL, newname, NULL); set_name(thing, newname); if (!AreQuiet(player, thing)) notify(player, T("Name set.")); real_did_it(player, thing, NULL, NULL, "ONAME", NULL, "ANAME", NOTHING, *************** *** 488,496 **** /** Structure for af_helper() data. */ struct af_args { ! int f; /**< flag bits */ ! int clear; /**< True to remove the flag */ ! char *flag; /**< flag name */ }; static int --- 471,480 ---- /** Structure for af_helper() data. */ struct af_args { ! int setf; /**< flag bits to set */ ! int clrf; /**< flag bits to clear */ ! char *setflags; /**< list of names of flags to set */ ! char *clrflags; /**< list of names of flags to clear */ }; static int *************** *** 506,528 **** * There is one special case - the resetting of the SAFE flag. */ if (!(Can_Write_Attr(player, thing, AL_ATTR(atr)) || ! (af->clear && (af->f & AF_SAFE) && Can_Write_Attr_Ignore_Safe(player, thing, AL_ATTR(atr))))) { notify_format(player, T("You cannot change that flag on %s/%s"), Name(thing), AL_NAME(atr)); return 0; } ! if (af->clear) { ! AL_FLAGS(atr) &= ~af->f; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s reset."), Name(thing), AL_NAME(atr), ! af->flag); ! } else { ! AL_FLAGS(atr) |= af->f; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s set."), Name(thing), AL_NAME(atr), ! af->flag); } return 1; --- 490,514 ---- * There is one special case - the resetting of the SAFE flag. */ if (!(Can_Write_Attr(player, thing, AL_ATTR(atr)) || ! ((af->clrf & AF_SAFE) && Can_Write_Attr_Ignore_Safe(player, thing, AL_ATTR(atr))))) { notify_format(player, T("You cannot change that flag on %s/%s"), Name(thing), AL_NAME(atr)); return 0; } ! /* Clear flags first, then set flags */ ! if (af->clrf) { ! AL_FLAGS(atr) &= ~af->clrf; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s reset."), Name(thing), AL_NAME(atr), ! af->clrflags); ! } ! if (af->setf) { ! AL_FLAGS(atr) |= af->setf; if (!AreQuiet(player, thing)) notify_format(player, T("%s/%s - %s set."), Name(thing), AL_NAME(atr), ! af->setflags); } return 1; *************** *** 564,584 **** return; } ! af.clear = 0; ! ! /* move past NOT token if there is one */ ! for (p = flag; *p && ((*p == NOT_TOKEN) || isspace((unsigned char) *p)); p++) ! if (*p == NOT_TOKEN) ! af.clear = !af.clear; ! if ((af.f = string_to_atrflag(player, p)) < 0) { notify(player, T("Unrecognized attribute flag.")); return; } ! af.flag = mush_strdup(atrflag_to_string(af.f), "af_flag list"); if (!atr_iter_get(player, thing, atrname, 0, af_helper, &af)) notify(player, T("No attribute found to change.")); ! mush_free((Malloc_t) af.flag, "af_flag list"); } --- 550,571 ---- return; } ! p = flag; ! /* Skip leading spaces */ ! while (*p && isspace((unsigned char) *p)) ! p++; ! af.setf = af.clrf = 0; ! if (string_to_atrflagsets(player, p, &af.setf, &af.clrf) < 0) { notify(player, T("Unrecognized attribute flag.")); return; } ! af.clrflags = mush_strdup(atrflag_to_string(af.clrf), "af_flag list"); ! af.setflags = mush_strdup(atrflag_to_string(af.setf), "af_flag list"); if (!atr_iter_get(player, thing, atrname, 0, af_helper, &af)) notify(player, T("No attribute found to change.")); ! mush_free((Malloc_t) af.clrflags, "af_flag list"); ! mush_free((Malloc_t) af.setflags, "af_flag list"); } *** 1_8_0.61/src/predicat.c Sat, 17 Jul 2004 20:49:33 -0500 dunemush (pennmush/b/44_predicat.c 1.1.1.34.1.1.1.3.1.4.2.38.1.13.1.2 660) --- 1_8_1.108(w)/src/predicat.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/44_predicat.c 1.1.1.34.1.1.1.3.1.4.2.38.1.13.1.2.1.11 660) *************** *** 535,541 **** --- 535,573 ---- payfor(dbref who, int cost) { /* subtract cost from who's pennies */ + int tmp; + dbref owner; + if ((cost == 0) || NoPay(who)) + return 1; + owner = Owner(who); + if ((tmp = Pennies(owner)) >= cost) { + if (Track_Money(owner)) { + notify_format(owner, T("GAME: %s(%s) spent %d %s."), + Name(who), unparse_dbref(who), cost, + (cost == 1) ? MONEY : MONIES); + } + s_Pennies(owner, tmp - cost); + return 1; + } else { + if (Track_Money(owner)) { + notify_format(owner, T("GAME: %s(%s) tried to spend %d %s."), + Name(who), unparse_dbref(who), cost, + (cost == 1) ? MONEY : MONIES); + } + return 0; + } + } + /** Debit a player's pennies, if they can afford it. + * \param who player to debit. + * \param cost number of pennies to debit. + * \retval 1 player successfully debited. + * \retval 0 player can't afford the cost. + */ + int + quiet_payfor(dbref who, int cost) + { + /* subtract cost from who's pennies */ int tmp; if (NoPay(who)) return 1; *************** *** 706,726 **** && strcasecmp((char *) name, "here")); } ! /** Is a name a valid player name? * Player names must be valid object names, but also not forbidden (unless * the player is a wizard). They are * subject to a different length limit, and subject to more stringent * restrictions on valid characters. Finally, it can't be the same as ! * an existing player name or alias. * \param name name to check. * \param player player for permission checks. * \retval 1 name is valid for players. * \retval 0 name is not valid for players. */ int ! ok_player_name(const char *name, dbref player) { const unsigned char *scan, *good; if (!ok_name(name) || (forbidden_name(name) && !(GoodObject(player) && Wizard(player))) --- 738,760 ---- && strcasecmp((char *) name, "here")); } ! /** Is a name a valid player name when applied by player to thing? * Player names must be valid object names, but also not forbidden (unless * the player is a wizard). They are * subject to a different length limit, and subject to more stringent * restrictions on valid characters. Finally, it can't be the same as ! * an existing player name or alias unless it's one of theirs. * \param name name to check. * \param player player for permission checks. + * \param thing player who will get the name. * \retval 1 name is valid for players. * \retval 0 name is not valid for players. */ int ! ok_player_name(const char *name, dbref player, dbref thing) { const unsigned char *scan, *good; + dbref lookup; if (!ok_name(name) || (forbidden_name(name) && !(GoodObject(player) && Wizard(player))) *************** *** 737,745 **** return 0; } ! return (lookup_player(name) == NOTHING); } /** Is a password acceptable? * Acceptable passwords must be non-null and must contain only * printable characters and no whitespace. --- 771,817 ---- return 0; } ! lookup = lookup_player(name); ! return ((lookup == NOTHING) || (lookup == thing)); } + + /** Is a alias a valid player alias-list for thing? + * It must be a semicolon-separated list of valid player names + * with no more than than MAX_ALIASES names, if the player isn't + * a wizard. + * \param alias list to check. + * \param player player for permission checks. + * \param thing player who is being aliased. + * \retval 1 alias is valid for players. + * \retval 0 alias is not valid for players. + */ + int + ok_player_alias(const char *alias, dbref player, dbref thing) + { + char tbuf1[BUFFER_LEN], *s, *sp; + int cnt = 0; + + if (!alias || !*alias) + return 0; + + strncpy(tbuf1, alias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + s = trim_space_sep(tbuf1, ALIAS_DELIMITER); + while (s) { + sp = split_token(&s, ALIAS_DELIMITER); + while (sp && *sp && *sp == ' ') + sp++; + if (!sp || !*sp) + return 0; /* No null aliases */ + if (!ok_player_name(sp, player, thing)) + return 0; + cnt++; + } + return ((cnt <= MAX_ALIASES) || Wizard(player)); + } + + /** Is a password acceptable? * Acceptable passwords must be non-null and must contain only * printable characters and no whitespace. *************** *** 763,771 **** return 1; } ! /** Is a name ok for a command or function? ! * It must begin with an uppercase alpha, and contain only ! * uppercase alpha, numbers, or underscore thereafter. * \param name name to check. * \retval 1 name is acceptable. * \retval 0 name is not acceptable. --- 835,844 ---- return 1; } ! /** Is a name ok for a command? ! * It must contain only uppercase alpha, numbers, or punctuation. ! * It must contain at least one uppercase alpha. ! * It may not begin with " : ; & ] \ and # (the special tokens). * \param name name to check. * \retval 1 name is acceptable. * \retval 0 name is not acceptable. *************** *** 774,796 **** ok_command_name(const char *name) { const unsigned char *p; ! if (!isupper((unsigned char) *name)) return 0; for (p = (unsigned char *) name; p && *p; p++) { ! if (!(isupper(*p) || isdigit(*p) || (*p == '_'))) return 0; } ! /* Not too long */ if (strlen(name) >= COMMAND_NAME_LIMIT) return 0; return 1; } /** Does params contain only acceptable HTML tag attributes? * Right now, this means: filter out SEND and XCH_CMD if ! * the player isn't a Wizard. Params may contain a space-separated * list of tag=value pairs. It's probably possible to fool this * checking. Needs more work, or removing HTML support. * \param player player using the attribute, or NOTHING for internal. --- 847,932 ---- ok_command_name(const char *name) { const unsigned char *p; ! int cnt = 0; ! /* First char: uppercase alphanum or legal punctuation */ ! switch ((unsigned char) *name) { ! case SAY_TOKEN: ! case POSE_TOKEN: ! case SEMI_POSE_TOKEN: ! case EMIT_TOKEN: ! case NOEVAL_TOKEN: ! case NUMBER_TOKEN: ! case '&': return 0; + default: + if (!isupper((unsigned char) *name) && !isdigit((unsigned char) *name)) + return 0; + } + /* Everything else must be printable and non-space, and we need + * to find at least one uppercase alpha + */ for (p = (unsigned char *) name; p && *p; p++) { ! if (isspace(*p)) return 0; + if (isupper(*p)) + cnt++; } ! if (!cnt) ! return 0; /* Not too long */ if (strlen(name) >= COMMAND_NAME_LIMIT) return 0; + return 1; + } + /** Is a name ok for a function? + * It must start with uppercase alpha or punctuation and may contain only + * uppercase alpha, numbers, or punctuation thereafter. + * It must contain at least one uppercase alpha. + * It may not begin with " : ; & ] \ and # (the special tokens). + * \param name name to check. + * \retval 1 name is acceptable. + * \retval 0 name is not acceptable. + */ + int + ok_function_name(const char *name) + { + const unsigned char *p; + int cnt = 0; + /* First char: uppercase alpha or legal punctuation */ + switch ((unsigned char) *name) { + case SAY_TOKEN: + case POSE_TOKEN: + case SEMI_POSE_TOKEN: + case EMIT_TOKEN: + case NOEVAL_TOKEN: + case NUMBER_TOKEN: + case '&': + return 0; + default: + if (!isupper((unsigned char) *name)) + return 0; + } + /* Everything else must be printable and non-space, and we need + * to find at least one uppercase alpha + */ + for (p = (unsigned char *) name; p && *p; p++) { + if (isspace(*p)) + return 0; + if (isupper(*p)) + cnt++; + } + if (!cnt) + return 0; + /* Not too long */ + if (strlen(name) >= COMMAND_NAME_LIMIT) + return 0; return 1; } /** Does params contain only acceptable HTML tag attributes? * Right now, this means: filter out SEND and XCH_CMD if ! * the player isn't privileged. Params may contain a space-separated * list of tag=value pairs. It's probably possible to fool this * checking. Needs more work, or removing HTML support. * \param player player using the attribute, or NOTHING for internal. *************** *** 803,809 **** { const unsigned char *p, *q; ! if (!GoodObject(player) || Wizard(player)) return 1; p = (const unsigned char *) params; while (*p) { --- 939,945 ---- { const unsigned char *p, *q; ! if (!GoodObject(player) || Can_Pueblo_Send(player)) return 1; p = (const unsigned char *) params; while (*p) { *************** *** 814,820 **** q++; if (*q) { size_t n = q - p; ! /* Invalid params for non-wizards. Turn to a hashtable if we ever get more? */ if (strncasecmp(p, "SEND", n) == 0 || strncasecmp(p, "XCH_CMD", n) == 0) return 0; --- 950,956 ---- q++; if (*q) { size_t n = q - p; ! /* Invalid params for non-priv'd. Turn to a hashtable if we ever get more? */ if (strncasecmp(p, "SEND", n) == 0 || strncasecmp(p, "XCH_CMD", n) == 0) return 0; *** 1_8_0.61/src/plyrlist.c Thu, 27 May 2004 14:05:53 -0500 dunemush (pennmush/b/46_plyrlist.c 1.5.1.1.1.3.1.2.1.1 660) --- 1_8_1.108(w)/src/plyrlist.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/46_plyrlist.c 1.5.1.1.1.3.1.2.1.1.1.11 660) *************** *** 49,65 **** /** Add a player to the player list htab. * \param player dbref of player to add. - * \param alias name to use as hash table key for player, if given. */ void ! add_player(dbref player, const char *alias) { if (!hft_initialized) init_hft(); ! if (alias) ! hashadd(strupper(alias), (void *) player, &htab_player_list); ! else ! hashadd(strupper(Name(player)), (void *) player, &htab_player_list); } /** Look up a player in the player list htab (or by dbref). --- 49,88 ---- /** Add a player to the player list htab. * \param player dbref of player to add. */ void ! add_player(dbref player) { if (!hft_initialized) init_hft(); ! hashadd(strupper(Name(player)), (void *) player, &htab_player_list); ! } ! ! /** Add a player's alias list to the player list htab. ! * \param player dbref of player to add. ! * \param alias list of names ot use as hash table keys for player, ! * semicolon-separated. ! */ ! void ! add_player_alias(dbref player, const char *alias) ! { ! char tbuf1[BUFFER_LEN], *s, *sp; ! if (!hft_initialized) ! init_hft(); ! if (!alias) { ! add_player(player); ! return; ! } ! strncpy(tbuf1, alias, BUFFER_LEN - 1); ! tbuf1[BUFFER_LEN - 1] = '\0'; ! s = trim_space_sep(tbuf1, ALIAS_DELIMITER); ! while (s) { ! sp = split_token(&s, ALIAS_DELIMITER); ! while (sp && *sp && *sp == ' ') ! sp++; ! if (sp && *sp) ! hashadd(strupper(sp), (void *) player, &htab_player_list); ! } } /** Look up a player in the player list htab (or by dbref). *************** *** 70,76 **** lookup_player(const char *name) { int p; - void *hval; if (!name || !*name) return NOTHING; --- 93,98 ---- *************** *** 83,88 **** --- 105,121 ---- } if (*name == LOOKUP_TOKEN) name++; + return lookup_player_name(name); + } + + /** Look up a player in the player list htab only. + * \param name name of player to find. + * \return dbref of player, or NOTHING. + */ + dbref + lookup_player_name(const char *name) + { + void *hval; hval = hashfind(strupper(name), &htab_player_list); if (!hval) return NOTHING; *************** *** 96,101 **** --- 129,135 ---- */ } + /** Remove a player from the player list htab. * \param player dbref of player to remove. * \param alias key to remove if given. *************** *** 103,110 **** void delete_player(dbref player, const char *alias) { ! if (alias) ! hashdelete(strupper(alias), &htab_player_list); ! else hashdelete(strupper(Name(player)), &htab_player_list); } --- 137,211 ---- void delete_player(dbref player, const char *alias) { ! if (!hft_initialized) { ! init_hft(); ! return; ! } ! if (alias) { ! /* This could be a compound alias, in which case we need to delete ! * them all, but we shouldn't delete the player's own name! ! */ ! char tbuf1[BUFFER_LEN], *s, *sp; ! strncpy(tbuf1, alias, BUFFER_LEN - 1); ! tbuf1[BUFFER_LEN - 1] = '\0'; ! s = trim_space_sep(tbuf1, ALIAS_DELIMITER); ! while (s) { ! sp = split_token(&s, ALIAS_DELIMITER); ! while (sp && *sp && *sp == ' ') ! sp++; ! if (sp && *sp && strcasecmp(sp, Name(player))) ! hashdelete(strupper(sp), &htab_player_list); ! } ! } else hashdelete(strupper(Name(player)), &htab_player_list); } + + /** Reset all of a player's player list entries (names/aliases). + * This is called when a player changes name or alias. + * We remove all their old entries, and add back their new ones. + * \param player dbref of player + * \param oldname player's former name (NULL if not changing) + * \param oldalias player's former aliases (NULL if not changing) + * \param name player's new name + * \param alias player's new aliases + */ + void + reset_player_list(dbref player, const char *oldname, const char *oldalias, + const char *name, const char *alias) + { + char tbuf1[BUFFER_LEN]; + char tbuf2[BUFFER_LEN]; + if (!oldname) { + oldname = Name(player); + name = Name(player); + } + if (oldalias) { + strncpy(tbuf1, oldalias, BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + if (alias) { + strncpy(tbuf2, alias, BUFFER_LEN - 1); + tbuf2[BUFFER_LEN - 1] = '\0'; + } else { + tbuf2[0] = '\0'; + } + } else { + /* We are not changing aliases, just name, but we need to get the + * aliases anyway, since we may change name to something that's + * in the alias, and thus must not be deleted. + */ + ATTR *a = atr_get_noparent(player, "ALIAS"); + if (a) { + strncpy(tbuf1, atr_value(a), BUFFER_LEN - 1); + tbuf1[BUFFER_LEN - 1] = '\0'; + } else { + tbuf1[0] = '\0'; + } + strcpy(tbuf2, tbuf1); + } + /* Delete all the old stuff */ + delete_player(player, tbuf1); + delete_player(player, NULL); + /* Add in the new stuff */ + add_player_alias(player, name); + add_player_alias(player, tbuf2); + } *** 1_8_0.61/src/player.c Sat, 04 Jun 2005 22:07:33 -0500 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.1.1.15.1.1 660) --- 1_8_1.108(w)/src/player.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/47_player.c 1.15.1.1.1.1.1.4.1.6.1.1.1.15.1.2 660) *************** *** 197,203 **** create_player(const char *name, const char *password, const char *host, const char *ip) { ! if (!ok_player_name(name, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed creation (bad name) from %s"), host); return NOTHING; } --- 197,203 ---- create_player(const char *name, const char *password, const char *host, const char *ip) { ! if (!ok_player_name(name, NOTHING, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed creation (bad name) from %s"), host); return NOTHING; } *************** *** 248,254 **** dbref player; FILE *fp; ! if (!ok_player_name(name, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed registration (bad name) from %s"), host); return NOTHING; } --- 248,254 ---- dbref player; FILE *fp; ! if (!ok_player_name(name, NOTHING, NOTHING)) { do_log(LT_CONN, 0, 0, T("Failed registration (bad name) from %s"), host); return NOTHING; } *************** *** 393,399 **** /* link him to PLAYER_START */ PUSH(player, Contents(PLAYER_START)); ! add_player(player, NULL); add_lock(GOD, player, Basic_Lock, parse_boolexp(player, "=me", Basic_Lock), -1); add_lock(GOD, player, Enter_Lock, parse_boolexp(player, "=me", Basic_Lock), --- 393,399 ---- /* link him to PLAYER_START */ PUSH(player, Contents(PLAYER_START)); ! add_player(player); add_lock(GOD, player, Basic_Lock, parse_boolexp(player, "=me", Basic_Lock), -1); add_lock(GOD, player, Enter_Lock, parse_boolexp(player, "=me", Basic_Lock), *** 1_8_0.61/src/parse.c Wed, 08 Jun 2005 18:16:15 -0500 dunemush (pennmush/b/48_parse.c 1.23.1.10.1.2.1.1.1.1.1.2.1.2.1.41.1.1 660) --- 1_8_1.108(w)/src/parse.c Sat, 25 Jun 2005 13:07:14 -0500 dunemush (pennmush/b/48_parse.c 1.23.1.10.1.2.1.1.1.1.1.2.1.2.1.41.1.2 660) *************** *** 500,505 **** --- 500,506 ---- pe_info->nest_depth = 0; pe_info->call_depth = 0; pe_info->debug_strings = NULL; + pe_info->arg_count = 0; } else { old_iter_limit = -1; } *************** *** 740,745 **** --- 741,752 ---- case '~': /* enactor accented name */ safe_str(accented_name(enactor), buff, bp); break; + case '+': /* argument count */ + if (pe_info) + safe_integer(pe_info->arg_count, buff, bp); + else + safe_integer(0, buff, bp); + break; case '0': case '1': case '2': *************** *** 1119,1128 **** --- 1126,1139 ---- global_fun_recursions++; pe_info->fun_depth++; if (fp->flags & FN_BUILTIN) { + int old_nfargs; global_fun_invocations++; pe_info->fun_invocations++; + old_nfargs = pe_info->arg_count; + pe_info->arg_count = nfargs; fp->where.fun(fp, buff, bp, nfargs, fargs, arglens, executor, caller, enactor, fp->name, pe_info); + pe_info->arg_count = old_nfargs; if (fp->flags & FN_LOGARGS) { char logstr[BUFFER_LEN]; char *logp; *************** *** 1158,1166 **** safe_chr('/', buff, bp); safe_str(userfn_tab[fp->where.offset].name, buff, bp); safe_chr(')', buff, bp); ! } else do_userfn(buff, bp, thing, attrib, nfargs, fargs, executor, caller, enactor, pe_info); } pe_info->fun_depth--; global_fun_recursions--; --- 1169,1183 ---- safe_chr('/', buff, bp); safe_str(userfn_tab[fp->where.offset].name, buff, bp); safe_chr(')', buff, bp); ! } else { ! char *preserve[NUMQ]; ! if (fp->flags & FN_LOCALIZE) ! save_global_regs("@function.save", preserve); do_userfn(buff, bp, thing, attrib, nfargs, fargs, executor, caller, enactor, pe_info); + if (fp->flags & FN_LOCALIZE) + restore_global_regs("@function.save", preserve); + } } pe_info->fun_depth--; global_fun_recursions--; *** 1_8_0.61/src/move.c Tue, 21 Dec 2004 10:20:52 -0600 dunemush (pennmush/b/51_move.c 1.1.1.18.1.5.1.13.1.3.1.9.1.1.1.1.1.2.1.1.1.1.1.33.1.1 660) --- 1_8_1.108(w)/src/move.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/b/51_move.c 1.1.1.18.1.5.1.13.1.3.1.9.1.1.1.1.1.2.1.1.1.1.1.33.1.2 660) *************** *** 301,312 **** int can_move(dbref player, const char *direction) { ! if (!strcasecmp(direction, "home") && !Fixed(player)) ! return 1; ! ! /* otherwise match on exits - don't use GoodObject here! */ ! return (match_result(player, direction, TYPE_EXIT, MAT_ENGLISH | MAT_EXIT) != NOTHING); } static dbref --- 301,316 ---- int can_move(dbref player, const char *direction) { ! int ok; ! if (!strcasecmp(direction, "home")) { ! ok = !Fixed(player); ! ok = ok && command_check_byname(player, "HOME"); ! } else { ! /* otherwise match on exits - don't use GoodObject here! */ ! ok = (match_result(player, direction, TYPE_EXIT, MAT_ENGLISH | MAT_EXIT) != NOTHING); + } + return ok; /* Written like this due to overeager compiler */ } static dbref *************** *** 355,361 **** do_move(dbref player, const char *direction, enum move_type type) { dbref exit_m, loc, var_dest; ! if (!strcasecmp(direction, "home")) { /* send him home */ /* but steal all his possessions */ if (!Mobile(player) || !GoodObject(Home(player)) || --- 359,365 ---- do_move(dbref player, const char *direction, enum move_type type) { dbref exit_m, loc, var_dest; ! if (!strcasecmp(direction, "home") && can_move(player, "home")) { /* send him home */ /* but steal all his possessions */ if (!Mobile(player) || !GoodObject(Home(player)) || *** 1_8_0.61/src/look.c Tue, 21 Dec 2004 10:16:27 -0600 dunemush (pennmush/c/4_look.c 1.21.1.2.1.9.1.1.1.1.1.46 660) --- 1_8_1.108(w)/src/look.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/4_look.c 1.21.1.2.1.9.1.1.1.1.1.49 660) *************** *** 10,15 **** --- 10,16 ---- #include "copyrite.h" #include + #include #include "conf.h" #include "externs.h" *************** *** 966,971 **** --- 967,1017 ---- do_inventory(dbref player) { dbref thing; + ATTR *a; + + a = atr_get(player, "INVFORMAT"); + if (a) { + char *wsave[10], *rsave[NUMQ]; + char *arg, *buff, *bp, *save; + char const *sp; + int j; + + arg = (char *) mush_malloc(BUFFER_LEN, "string"); + buff = (char *) mush_malloc(BUFFER_LEN, "string"); + if (!arg || !buff) + mush_panic("Unable to allocate memory in do_inventory"); + save_global_regs("do_inventory", rsave); + for (j = 0; j < 10; j++) { + wsave[j] = global_eval_context.wenv[j]; + global_eval_context.wenv[j] = NULL; + } + for (j = 0; j < NUMQ; j++) + global_eval_context.renv[j][0] = '\0'; + bp = arg; + DOLIST(thing, Contents(player)) { + if (bp != arg) + safe_chr(' ', arg, &bp); + safe_dbref(thing, arg, &bp); + } + *bp = '\0'; + global_eval_context.wenv[0] = arg; + sp = save = safe_atr_value(a); + bp = buff; + process_expression(buff, &bp, &sp, player, player, player, + PE_DEFAULT, PT_DEFAULT, NULL); + *bp = '\0'; + free((Malloc_t) save); + notify(player, buff); + for (j = 0; j < 10; j++) { + global_eval_context.wenv[j] = wsave[j]; + } + restore_global_regs("do_inventory", rsave); + mush_free((Malloc_t) arg, "string"); + mush_free((Malloc_t) buff, "string"); + return; + } + + /* Default if no INVFORMAT */ if ((thing = Contents(player)) == NOTHING) { notify(player, T("You aren't carrying anything.")); } else { *************** *** 974,980 **** notify(player, unparse_object_myopic(player, thing)); } } - do_score(player); } --- 1020,1025 ---- *************** *** 1320,1325 **** --- 1365,1427 ---- int skipdef; /**< Skip default flags on attributes if true */ }; + extern char escaped_chars[UCHAR_MAX + 1]; + + char * + decompose_str(char *what) + { + static char value[BUFFER_LEN]; + char *ptr, *s; + int len; + int dospace; + + len = strlen(what); + /* Go through the string, escaping characters and + * turning every other space into %b. */ + + s = value; + ptr = what; + /* Put a \ at the beginning if it won't already be put there, + * unless it's a space, which would require %b, %r, or %t anyway */ + if (!escaped_chars[(unsigned int) *what] && !isspace(*what)) { + safe_chr('\\', value, &s); + } + dospace = 1; + for (; *ptr; ptr++) { + switch (*ptr) { + case ' ': + if (dospace) { + safe_str("%b", value, &s); + } else { + safe_chr(' ', value, &s); + } + dospace = !dospace; + break; + case '\n': + dospace = 0; + safe_str("%r", value, &s); + break; + case '\t': + dospace = 0; + safe_str("%t", value, &s); + break; + default: + if (escaped_chars[(unsigned int) *ptr]) { + safe_chr('\\', value, &s); + } + safe_chr(*ptr, value, &s); + dospace = 0; + } + } + /* Now check the last space. */ + if (*(s - 1) == ' ') { + s -= 1; + safe_str("%b", value, &s); + } + *s = '\0'; + return value; + } + static int decompile_helper(dbref player, dbref thing __attribute__ ((__unused__)), dbref parent __attribute__ ((__unused__)), *************** *** 1328,1333 **** --- 1430,1437 ---- { struct dh_args *dh = args; ATTR *ptr; + char *avalue; + int avlen; char msg[BUFFER_LEN]; char *bp; *************** *** 1337,1353 **** ptr = atr_match(AL_NAME(atr)); bp = msg; safe_str(dh->prefix, msg, &bp); ! if (ptr && !strcmp(AL_NAME(atr), AL_NAME(ptr))) ! safe_chr('@', msg, &bp); ! else { ! ptr = NULL; /* To speed later checks */ ! safe_chr('&', msg, &bp); } - safe_str(AL_NAME(atr), msg, &bp); - safe_chr(' ', msg, &bp); - safe_str(dh->name, msg, &bp); - safe_chr('=', msg, &bp); - safe_str(atr_value(atr), msg, &bp); *bp = '\0'; notify(player, msg); /* Now deal with attribute flags, if not FugueEditing */ --- 1441,1472 ---- ptr = atr_match(AL_NAME(atr)); bp = msg; safe_str(dh->prefix, msg, &bp); ! ! avalue = atr_value(atr); ! avlen = strlen(avalue); ! /* If avalue includes a %r, a %t, or begins or ends with a %b, ! * then use @set on the decompose_str'd value instead of &atrname */ ! if (strchr(avalue, '\n') || ! strchr(avalue, '\t') || *avalue == ' ' || avalue[avlen - 1] == ' ') { ! safe_str("@set ", msg, &bp); ! safe_str(dh->name, msg, &bp); ! safe_chr('=', msg, &bp); ! safe_str(AL_NAME(atr), msg, &bp); ! safe_chr(':', msg, &bp); ! safe_str(decompose_str(avalue), msg, &bp); ! } else { ! if (ptr && !strcmp(AL_NAME(atr), AL_NAME(ptr))) { ! safe_chr('@', msg, &bp); ! } else { ! ptr = NULL; /* To speed later checks */ ! safe_chr('&', msg, &bp); ! } ! safe_str(AL_NAME(atr), msg, &bp); ! safe_chr(' ', msg, &bp); ! safe_str(dh->name, msg, &bp); ! safe_chr('=', msg, &bp); ! safe_str(avalue, msg, &bp); } *bp = '\0'; notify(player, msg); /* Now deal with attribute flags, if not FugueEditing */ *** 1_8_0.61/src/lock.c Mon, 08 Nov 2004 10:47:50 -0600 dunemush (pennmush/c/6_lock.c 1.17.1.13.1.1.1.1.1.23 660) --- 1_8_1.108(w)/src/lock.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/6_lock.c 1.17.1.13.1.1.1.1.1.24 660) *************** *** 77,82 **** --- 77,83 ---- const lock_type Dropto_Lock = "Dropto"; /**< Name of dropto lock */ const lock_type Destroy_Lock = "Destroy"; /**< Name of destroy lock */ const lock_type Interact_Lock = "Interact"; /**< Name of interaction lock */ + const lock_type MailForward_Lock = "MailForward"; /**< Name of mailforward lock */ /* Define new lock types here. */ /** Table of lock names and permissions */ *************** *** 104,109 **** --- 105,111 ---- {"Dropto", TRUE_BOOLEXP, GOD, LF_PRIVATE, NULL}, {"Destroy", TRUE_BOOLEXP, GOD, LF_PRIVATE | LF_OWNER, NULL}, {"Interact", TRUE_BOOLEXP, GOD, LF_PRIVATE, NULL}, + {"MailForward", TRUE_BOOLEXP, GOD, LF_PRIVATE, NULL}, /* Add new lock types just before this line. */ {NULL, TRUE_BOOLEXP, GOD, 0, NULL} }; *** 1_8_0.61/src/game.c Sun, 20 Mar 2005 08:27:08 -0600 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.3.1.7.1.2.2.1.1.32.1.2.2.1.1.1.1.1 660) --- 1_8_1.108(w)/src/game.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/10_game.c 1.50.1.8.1.1.1.1.2.1.1.1.2.1.1.4.1.1.1.1.1.1.1.1.1.1.2.1.1.2.1.1.1.1.1.1.1.2.1.1.1.2.1.1.1.1.1.1.1.1.1.5.1.3.1.2.1.2.1.1.1.1.1.1.1.1.1.12.1.3.1.7.1.2.2.1.1.32.1.2.2.1.1.1.1.4 660) *************** *** 646,652 **** bp = buf; safe_str(atr_value(s), buf, &bp); *bp = '\0'; ! add_player(thing, buf); } } } --- 646,652 ---- bp = buf; safe_str(atr_value(s), buf, &bp); *bp = '\0'; ! add_player_alias(thing, buf); } } } *************** *** 968,974 **** /** Attempt to match and execute a command. * This function performs some sanity checks and then attempts to ! * run a command. It checks, in order: home, built-in commands, * enter aliases, leave aliases, $commands on neighboring objects or * the player, $commands on the container, $commands on inventory, * exits in the zone master room, $commands on objects in the ZMR, --- 968,974 ---- /** Attempt to match and execute a command. * This function performs some sanity checks and then attempts to ! * run a command. It checks, in order: built-in commands, * enter aliases, leave aliases, $commands on neighboring objects or * the player, $commands on the container, $commands on inventory, * exits in the zone master room, $commands on objects in the ZMR, *************** *** 1062,1077 **** if ((!command || !*command) && !from_port) return; - /* important home checking comes first! */ - if (strcmp(command, "home") == 0) { - if (!Mobile(player)) - return; - if (Fixed(player)) - notify(player, T("You can't do that IC!")); - else - do_move(player, command, MOVE_NORMAL); - return; - } strcpy(unp, command); cptr = command_parse(player, cause, command, from_port); --- 1062,1067 ---- *** 1_8_0.61/src/funufun.c Wed, 30 Jun 2004 15:00:16 -0500 dunemush (pennmush/c/11_funufun.c 1.22 660) --- 1_8_1.108(w)/src/funufun.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/11_funufun.c 1.23 660) *************** *** 110,115 **** --- 110,116 ---- char *tbuf; char const *tp; int pe_flags = PE_DEFAULT; + int old_args; /* save our stack */ for (j = 0; j < 10; j++) *************** *** 122,127 **** --- 123,132 ---- global_eval_context.wenv[j] = args[j]; for (; j < 10; j++) global_eval_context.wenv[j] = NULL; + if (pe_info) { + old_args = pe_info->arg_count; + pe_info->arg_count = nargs; + } tp = tbuf = safe_atr_value(attrib); if (attrib->flags & AF_DEBUG) *************** *** 133,138 **** --- 138,145 ---- /* restore the stack */ for (j = 0; j < 10; j++) global_eval_context.wenv[j] = tptr[j]; + if (pe_info) + pe_info->arg_count = old_args; } /* ARGSUSED */ *** 1_8_0.61/src/funstr.c Sun, 05 Dec 2004 22:51:03 -0600 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.1.1.1.1.1.1.1.1.14.1.25 660) --- 1_8_1.108(w)/src/funstr.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/13_funstr.c 1.28.1.1.1.2.1.4.1.6.1.1.1.1.1.2.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.1.2.1.3.1.5.1.3.1.2.1.1.1.1.1.1.1.1.1.14.1.27 660) *************** *** 606,633 **** FUNCTION(fun_flip) { ansi_string *as; - int p, n; - as = parse_ansi_string(args[0]); ! populate_codes(as); ! ! for (p = 0, n = as->len - 1; p < n; p++, n--) { ! char *tcode; ! char t; ! ! tcode = as->codes[p]; ! t = as->text[p]; ! as->codes[p] = as->codes[n]; ! as->text[p] = as->text[n]; ! as->codes[n] = tcode; ! as->text[n] = t; ! } ! safe_ansi_string(as, 0, as->len, buff, bp); - free_ansi_string(as); } /* ARGSUSED */ FUNCTION(fun_merge) { --- 606,618 ---- FUNCTION(fun_flip) { ansi_string *as; as = parse_ansi_string(args[0]); ! flip_ansi_string(as); safe_ansi_string(as, 0, as->len, buff, bp); free_ansi_string(as); } + /* ARGSUSED */ FUNCTION(fun_merge) { *************** *** 931,940 **** /* ARGSUSED */ FUNCTION(fun_center) { ! /* pads a string with leading blanks (or other fill character) */ ! ! size_t width, len, lsp, rsp; ! char sep; if (!is_uinteger(args[1])) { safe_str(T(e_uint), buff, bp); --- 916,926 ---- /* ARGSUSED */ FUNCTION(fun_center) { ! /* pads a string with leading blanks (or other fill string) */ ! size_t width, len, lsp, rsp, filllen; ! int fillq, fillr, i; ! char fillstr[BUFFER_LEN], *fp; ! ansi_string *as; if (!is_uinteger(args[1])) { safe_str(T(e_uint), buff, bp); *************** *** 946,965 **** safe_strl(args[0], arglens[0], buff, bp); return; } ! rsp = width - len; ! lsp = rsp / 2; ! rsp -= lsp; if (lsp >= BUFFER_LEN) ! lsp = BUFFER_LEN - 1; ! if (rsp >= BUFFER_LEN) ! rsp = BUFFER_LEN - 1; ! if (!delim_check(buff, bp, nargs, args, 3, &sep)) return; ! safe_fill(sep, lsp, buff, bp); safe_strl(args[0], arglens[0], buff, bp); ! safe_fill(sep, rsp, buff, bp); } /* ARGSUSED */ --- 932,991 ---- safe_strl(args[0], arglens[0], buff, bp); return; } ! lsp = rsp = (width - len) / 2; ! rsp += (width - len) % 2; if (lsp >= BUFFER_LEN) ! lsp = rsp = BUFFER_LEN - 1; ! if (!args[2] || !*args[2]) { ! /* Fast case for default fill with spaces */ ! safe_fill(' ', lsp, buff, bp); ! safe_strl(args[0], arglens[0], buff, bp); ! safe_fill(' ', rsp, buff, bp); return; + } ! /* args[2] contains the possibly ansi, multi-char fill string */ ! filllen = ansi_strlen(args[2]); ! as = parse_ansi_string(args[2]); ! fillq = lsp / filllen; ! fillr = lsp % filllen; ! fp = fillstr; ! for (i = 0; i < fillq; i++) ! safe_ansi_string(as, 0, as->len, fillstr, &fp); ! safe_ansi_string(as, 0, fillr, fillstr, &fp); ! *fp = '\0'; ! free_ansi_string(as); ! safe_str(fillstr, buff, bp); safe_strl(args[0], arglens[0], buff, bp); ! /* If we have args[3], that's the right-side fill string */ ! if (nargs > 3) { ! if (args[3] && *args[3]) { ! filllen = ansi_strlen(args[3]); ! as = parse_ansi_string(args[3]); ! fillq = rsp / filllen; ! fillr = rsp % filllen; ! fp = fillstr; ! for (i = 0; i < fillq; i++) ! safe_ansi_string(as, 0, as->len, fillstr, &fp); ! safe_ansi_string(as, 0, fillr, fillstr, &fp); ! *fp = '\0'; ! free_ansi_string(as); ! safe_str(fillstr, buff, bp); ! } else { ! /* Null args[3], fill right side with spaces */ ! safe_fill(' ', rsp, buff, bp); ! } ! return; ! } ! /* No args[3], so we flip args[2] */ ! as = parse_ansi_string(fillstr); ! flip_ansi_string(as); ! safe_ansi_string(as, 0, as->len, buff, bp); ! /* Is there an extra char left over we need to pad with? */ ! if (rsp > lsp) ! safe_ansi_string(as, 0, 1, buff, bp); ! free_ansi_string(as); } /* ARGSUSED */ *************** *** 1062,1067 **** --- 1088,1103 ---- extern char escaped_chars[UCHAR_MAX + 1]; /* ARGSUSED */ + FUNCTION(fun_decompose) + { + /* This function simply returns a decompose'd version of + * the included string, such that + * s(decompose(str)) == str, down to the last space, tab, + * and newline. Except for ansi. */ + safe_str(decompose_str(args[0]), buff, bp); + } + + /* ARGSUSED */ FUNCTION(fun_secure) { /* this function smashes all occurences of "unsafe" characters in a string. *** 1_8_0.61/src/funmisc.c Tue, 15 Feb 2005 09:52:21 -0600 dunemush (pennmush/c/14_funmisc.c 1.30.1.1.1.41.1.2 660) --- 1_8_1.108(w)/src/funmisc.c Sat, 25 Jun 2005 13:07:13 -0500 dunemush (pennmush/c/14_funmisc.c 1.30.1.1.1.41.1.5 660) *************** *** 51,63 **** else if (!strcasecmp(args[0], "attrname")) safe_boolean(good_atr_name(upcasestr(args[1])), buff, bp); else if (!strcasecmp(args[0], "playername")) ! safe_boolean(ok_player_name(args[1], executor), buff, bp); else if (!strcasecmp(args[0], "password")) safe_boolean(ok_password(args[1]), buff, bp); else if (!strcasecmp(args[0], "command")) safe_boolean(ok_command_name(upcasestr(args[1])), buff, bp); else if (!strcasecmp(args[0], "function")) ! safe_boolean(ok_command_name(upcasestr(args[1])), buff, bp); else safe_str("#-1", buff, bp); } --- 51,63 ---- else if (!strcasecmp(args[0], "attrname")) safe_boolean(good_atr_name(upcasestr(args[1])), buff, bp); else if (!strcasecmp(args[0], "playername")) ! safe_boolean(ok_player_name(args[1], executor, executor), buff, bp); else if (!strcasecmp(args[0], "password")) safe_boolean(ok_password(args[1]), buff, bp); else if (!strcasecmp(args[0], "command")) safe_boolean(ok_command_name(upcasestr(args[1])), buff, bp); else if (!strcasecmp(args[0], "function")) ! safe_boolean(ok_function_name(upcasestr(args[1])), buff, bp); else safe_str("#-1", buff, bp); } *************** *** 156,170 **** { /* sets a variable into a local register */ int qindex; ! if (*args[0] && (*(args[0] + 1) == '\0') && ! ((qindex = qreg_indexes[(unsigned char) args[0][0]]) != -1) ! && global_eval_context.renv[qindex]) { ! strcpy(global_eval_context.renv[qindex], args[1]); ! if (!strcmp(called_as, "SETR")) ! safe_strl(args[1], arglens[1], buff, bp); ! } else ! safe_str(T("#-1 REGISTER OUT OF RANGE"), buff, bp); } /* ARGSUSED */ --- 156,178 ---- { /* sets a variable into a local register */ int qindex; + int n; ! if ((nargs % 2) != 0) { ! safe_str(T("#-1 FUNCTION EXPECTS AN EVEN NUMBER OF ARGUMENTS"), buff, bp); ! return; ! } ! ! for (n = 0; n < nargs; n += 2) { ! if (*args[n] && (*(args[n] + 1) == '\0') && ! ((qindex = qreg_indexes[(unsigned char) args[n][0]]) != -1) ! && global_eval_cont